]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/process.c
38f6a41f985b9ebe6af12299fc3f724a42cb6163
[thirdparty/cups.git] / scheduler / process.c
1 /*
2 * "$Id$"
3 *
4 * Process management routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 * cupsdEndProcess() - End a process.
27 * cupsdStartProcess() - Start a process.
28 */
29
30 /*
31 * Include necessary headers...
32 */
33
34 #include "cupsd.h"
35 #include <grp.h>
36
37
38 /*
39 * 'cupsdEndProcess()' - End a process.
40 */
41
42 int /* O - 0 on success, -1 on failure */
43 cupsdEndProcess(int pid, /* I - Process ID */
44 int force) /* I - Force child to die */
45 {
46 if (force)
47 return (kill(pid, SIGKILL));
48 else
49 return (kill(pid, SIGTERM));
50 }
51
52
53 /*
54 * 'cupsdStartProcess()' - Start a process.
55 */
56
57 int /* O - Process ID or 0 */
58 cupsdStartProcess(
59 const char *command, /* I - Full path to command */
60 char *argv[], /* I - Command-line arguments */
61 char *envp[], /* I - Environment */
62 int infd, /* I - Standard input file descriptor */
63 int outfd, /* I - Standard output file descriptor */
64 int errfd, /* I - Standard error file descriptor */
65 int backfd, /* I - Backchannel file descriptor */
66 int root, /* I - Run as root? */
67 int *pid) /* O - Process ID */
68 {
69 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
70 struct sigaction action; /* POSIX signal handler */
71 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
72
73
74 cupsdLogMessage(L_DEBUG2, "cupsdStartProcess(\"%s\", %p, %p, %d, %d, %d)",
75 command, argv, envp, infd, outfd, errfd);
76
77 /*
78 * Block signals before forking...
79 */
80
81 cupsdHoldSignals();
82
83 if ((*pid = fork()) == 0)
84 {
85 /*
86 * Child process goes here...
87 *
88 * Update stdin/stdout/stderr as needed...
89 */
90
91 if (infd != 0)
92 {
93 close(0);
94 if (infd > 0)
95 dup(infd);
96 else
97 open("/dev/null", O_RDONLY);
98 }
99 if (outfd != 1)
100 {
101 close(1);
102 if (outfd > 0)
103 dup(outfd);
104 else
105 open("/dev/null", O_WRONLY);
106 }
107 if (errfd != 2)
108 {
109 close(2);
110 if (errfd > 0)
111 dup(errfd);
112 else
113 open("/dev/null", O_WRONLY);
114 }
115 if (backfd != 3)
116 {
117 close(3);
118 if (backfd > 0)
119 dup(backfd);
120 else
121 open("/dev/null", O_RDWR);
122 fcntl(3, F_SETFL, O_NDELAY);
123 }
124
125 /*
126 * Change the priority of the process based on the FilterNice setting.
127 * (this is not done for backends...)
128 */
129
130 if (!root)
131 nice(FilterNice);
132
133 /*
134 * Change user to something "safe"...
135 */
136
137 if (!root && !RunUser)
138 {
139 /*
140 * Running as root, so change to non-priviledged user...
141 */
142
143 if (setgid(Group))
144 exit(errno);
145
146 if (setgroups(1, &Group))
147 exit(errno);
148
149 if (setuid(User))
150 exit(errno);
151 }
152 else
153 {
154 /*
155 * Reset group membership to just the main one we belong to.
156 */
157
158 setgroups(1, &Group);
159 }
160
161 /*
162 * Change umask to restrict permissions on created files...
163 */
164
165 umask(077);
166
167 /*
168 * Unblock signals before doing the exec...
169 */
170
171 #ifdef HAVE_SIGSET
172 sigset(SIGTERM, SIG_DFL);
173 sigset(SIGCHLD, SIG_DFL);
174 #elif defined(HAVE_SIGACTION)
175 memset(&action, 0, sizeof(action));
176
177 sigemptyset(&action.sa_mask);
178 action.sa_handler = SIG_DFL;
179
180 sigaction(SIGTERM, &action, NULL);
181 sigaction(SIGCHLD, &action, NULL);
182 #else
183 signal(SIGTERM, SIG_DFL);
184 signal(SIGCHLD, SIG_DFL);
185 #endif /* HAVE_SIGSET */
186
187 cupsdReleaseSignals();
188
189 /*
190 * Execute the command; if for some reason this doesn't work,
191 * return the error code...
192 */
193
194 if (envp)
195 execve(command, argv, envp);
196 else
197 execv(command, argv);
198
199 perror(command);
200
201 exit(errno);
202 }
203 else if (*pid < 0)
204 {
205 /*
206 * Error - couldn't fork a new process!
207 */
208
209 cupsdLogMessage(L_ERROR, "Unable to fork %s - %s.", command, strerror(errno));
210
211 *pid = 0;
212 }
213
214 cupsdReleaseSignals();
215
216 return (*pid);
217 }
218
219
220 /*
221 * End of "$Id$".
222 */