]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/process.c
06c9800c4334011d545c6c0d9fd12e0f0f0bfd15
2 * "$Id: process.c 6783 2007-08-10 19:48:57Z mike $"
4 * Process management routines for the Common UNIX Printing System (CUPS).
6 * Copyright 2007 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * cupsdEndProcess() - End a process.
18 * cupsdFinishProcess() - Finish a process and get its name.
19 * cupsdStartProcess() - Start a process.
20 * compare_procs() - Compare two processes.
24 * Include necessary headers...
29 #if defined(__APPLE__)
31 #endif /* __APPLE__ */
35 * Process structure...
40 int pid
; /* Process ID */
41 char name
[1]; /* Name of process */
49 static cups_array_t
*process_array
= NULL
;
56 static int compare_procs(cupsd_proc_t
*a
, cupsd_proc_t
*b
);
60 * 'cupsdEndProcess()' - End a process.
63 int /* O - 0 on success, -1 on failure */
64 cupsdEndProcess(int pid
, /* I - Process ID */
65 int force
) /* I - Force child to die */
68 return (kill(pid
, SIGKILL
));
70 return (kill(pid
, SIGTERM
));
75 * 'cupsdFinishProcess()' - Finish a process and get its name.
78 const char * /* O - Process name */
79 cupsdFinishProcess(int pid
, /* I - Process ID */
80 char *name
, /* I - Name buffer */
81 int namelen
) /* I - Size of name buffer */
83 cupsd_proc_t key
, /* Search key */
84 *proc
; /* Matching process */
89 if ((proc
= (cupsd_proc_t
*)cupsArrayFind(process_array
, &key
)) != NULL
)
91 strlcpy(name
, proc
->name
, namelen
);
92 cupsArrayRemove(process_array
, proc
);
103 * 'cupsdStartProcess()' - Start a process.
106 int /* O - Process ID or 0 */
108 const char *command
, /* I - Full path to command */
109 char *argv
[], /* I - Command-line arguments */
110 char *envp
[], /* I - Environment */
111 int infd
, /* I - Standard input file descriptor */
112 int outfd
, /* I - Standard output file descriptor */
113 int errfd
, /* I - Standard error file descriptor */
114 int backfd
, /* I - Backchannel file descriptor */
115 int sidefd
, /* I - Sidechannel file descriptor */
116 int root
, /* I - Run as root? */
117 int *pid
) /* O - Process ID */
119 cupsd_proc_t
*proc
; /* New process record */
120 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
121 struct sigaction action
; /* POSIX signal handler */
122 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
123 #if defined(__APPLE__)
124 char processPath
[1024], /* CFProcessPath environment variable */
125 linkpath
[1024]; /* Link path for symlinks... */
126 int linkbytes
; /* Bytes for link path */
127 #endif /* __APPLE__ */
130 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
131 "cupsdStartProcess(\"%s\", %p, %p, %d, %d, %d)",
132 command
, argv
, envp
, infd
, outfd
, errfd
);
134 if (access(command
, X_OK
))
136 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to execute %s: %s", command
,
141 #if defined(__APPLE__)
145 * Add special voodoo magic for MacOS X - this allows MacOS X
146 * programs to access their bundle resources properly...
149 if ((linkbytes
= readlink(command
, linkpath
, sizeof(linkpath
) - 1)) > 0)
152 * Yes, this is a symlink to the actual program, nul-terminate and
156 linkpath
[linkbytes
] = '\0';
158 if (linkpath
[0] == '/')
159 snprintf(processPath
, sizeof(processPath
), "CFProcessPath=%s",
162 snprintf(processPath
, sizeof(processPath
), "CFProcessPath=%s/%s",
163 dirname((char *)command
), linkpath
);
166 snprintf(processPath
, sizeof(processPath
), "CFProcessPath=%s", command
);
168 envp
[0] = processPath
; /* Replace <CFProcessPath> string */
170 #endif /* __APPLE__ */
173 * Block signals before forking...
178 if ((*pid
= fork()) == 0)
181 * Child process goes here...
183 * Update stdin/stdout/stderr as needed...
192 open("/dev/null", O_RDONLY
);
200 open("/dev/null", O_WRONLY
);
208 open("/dev/null", O_WRONLY
);
216 open("/dev/null", O_RDWR
);
217 fcntl(3, F_SETFL
, O_NDELAY
);
219 if (sidefd
!= 4 && sidefd
> 0)
223 fcntl(4, F_SETFL
, O_NDELAY
);
227 * Change the priority of the process based on the FilterNice setting.
228 * (this is not done for backends...)
235 * Change user to something "safe"...
238 if (!root
&& !RunUser
)
241 * Running as root, so change to non-priviledged user...
247 if (setgroups(1, &Group
))
256 * Reset group membership to just the main one we belong to.
260 setgroups(1, &Group
);
264 * Change umask to restrict permissions on created files...
270 * Unblock signals before doing the exec...
274 sigset(SIGTERM
, SIG_DFL
);
275 sigset(SIGCHLD
, SIG_DFL
);
276 #elif defined(HAVE_SIGACTION)
277 memset(&action
, 0, sizeof(action
));
279 sigemptyset(&action
.sa_mask
);
280 action
.sa_handler
= SIG_DFL
;
282 sigaction(SIGTERM
, &action
, NULL
);
283 sigaction(SIGCHLD
, &action
, NULL
);
285 signal(SIGTERM
, SIG_DFL
);
286 signal(SIGCHLD
, SIG_DFL
);
287 #endif /* HAVE_SIGSET */
289 cupsdReleaseSignals();
292 * Execute the command; if for some reason this doesn't work,
293 * return the error code...
297 execve(command
, argv
, envp
);
299 execv(command
, argv
);
308 * Error - couldn't fork a new process!
311 cupsdLogMessage(CUPSD_LOG_ERROR
, "Unable to fork %s - %s.", command
,
319 process_array
= cupsArrayNew((cups_array_func_t
)compare_procs
, NULL
);
323 if ((proc
= calloc(1, sizeof(cupsd_proc_t
) + strlen(command
))) != NULL
)
326 strcpy(proc
->name
, command
);
328 cupsArrayAdd(process_array
, proc
);
333 cupsdReleaseSignals();
340 * 'compare_procs()' - Compare two processes.
343 static int /* O - Result of comparison */
344 compare_procs(cupsd_proc_t
*a
, /* I - First process */
345 cupsd_proc_t
*b
) /* I - Second process */
347 return (a
->pid
- b
->pid
);
352 * End of "$Id: process.c 6783 2007-08-10 19:48:57Z mike $".