]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/util.c
2 * Mini-daemon utility functions for CUPS.
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2005 by Easy Software Products.
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 * which should have been included with this file. If this file is
11 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * Include necessary headers...
24 extern char **environ
;
25 #endif /* __APPLE__ */
29 * 'cupsdCompareNames()' - Compare two names.
31 * This function basically does a _cups_strcasecmp() of the two strings,
32 * but is also aware of numbers so that "a2" < "a100".
35 int /* O - Result of comparison */
36 cupsdCompareNames(const char *s
, /* I - First string */
37 const char *t
) /* I - Second string */
39 int diff
, /* Difference between digits */
40 digits
; /* Number of digits */
44 * Loop through both names, returning only when a difference is
45 * seen. Also, compare whole numbers rather than just characters, too!
50 if (isdigit(*s
& 255) && isdigit(*t
& 255))
53 * Got a number; start by skipping leading 0's...
62 * Skip equal digits...
65 while (isdigit(*s
& 255) && *s
== *t
)
72 * Bounce out if *s and *t aren't both digits...
75 if (isdigit(*s
& 255) && !isdigit(*t
& 255))
77 else if (!isdigit(*s
& 255) && isdigit(*t
& 255))
79 else if (!isdigit(*s
& 255) || !isdigit(*t
& 255))
88 * Figure out how many more digits there are...
95 while (isdigit(*s
& 255))
101 while (isdigit(*t
& 255))
108 * Return if the number or value of the digits is different...
118 else if (tolower(*s
) < tolower(*t
))
120 else if (tolower(*s
) > tolower(*t
))
130 * Return the results of the final comparison...
143 * 'cupsdCreateStringsArray()' - Create a CUPS array of strings.
146 cups_array_t
* /* O - CUPS array */
147 cupsdCreateStringsArray(const char *s
) /* I - Comma-delimited strings */
152 return (_cupsArrayNewStrings(s
, ','));
157 * 'cupsdExec()' - Run a program with the correct environment.
159 * On macOS, we need to update the CFProcessPath environment variable that
160 * is passed in the environment so the child can access its bundled resources.
163 int /* O - exec() status */
164 cupsdExec(const char *command
, /* I - Full path to program */
165 char **argv
) /* I - Command-line arguments */
168 int i
, j
; /* Looping vars */
169 char *envp
[500], /* Array of environment variables */
170 cfprocesspath
[1024], /* CFProcessPath environment variable */
171 linkpath
[1024]; /* Link path for symlinks... */
172 int linkbytes
; /* Bytes for link path */
176 * Some macOS programs are bundled and need the CFProcessPath environment
177 * variable defined. If the command is a symlink, resolve the link and point
178 * to the resolved location, otherwise, use the command path itself.
181 if ((linkbytes
= readlink(command
, linkpath
, sizeof(linkpath
) - 1)) > 0)
184 * Yes, this is a symlink to the actual program, nul-terminate and
188 linkpath
[linkbytes
] = '\0';
190 if (linkpath
[0] == '/')
191 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s",
194 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s/%s",
195 dirname((char *)command
), linkpath
);
198 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s", command
);
200 envp
[0] = cfprocesspath
;
203 * Copy the rest of the environment except for any CFProcessPath that may
204 * already be there...
208 environ
[j
] && i
< (int)(sizeof(envp
) / sizeof(envp
[0]) - 1);
210 if (strncmp(environ
[j
], "CFProcessPath=", 14))
211 envp
[i
++] = environ
[j
];
216 * Use execve() to run the program...
219 return (execve(command
, argv
, envp
));
223 * On other operating systems, just call execv() to use the same environment
224 * variables as the parent...
227 return (execv(command
, argv
));
228 #endif /* __APPLE__ */
233 * 'cupsdPipeCommand()' - Read output from a command.
236 cups_file_t
* /* O - CUPS file or NULL on error */
237 cupsdPipeCommand(int *pid
, /* O - Process ID or 0 on error */
238 const char *command
, /* I - Command to run */
239 char **argv
, /* I - Arguments to pass to command */
240 uid_t user
) /* I - User to run as or 0 for current */
242 int fd
, /* Temporary file descriptor */
243 fds
[2]; /* Pipe file descriptors */
247 * First create the pipe...
257 * Set the "close on exec" flag on each end of the pipe...
260 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
270 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
281 * Then run the command...
284 if ((*pid
= fork()) < 0)
299 * Child comes here...
302 if (!getuid() && user
)
303 setuid(user
); /* Run as restricted user */
305 if ((fd
= open("/dev/null", O_RDONLY
)) > 0)
307 dup2(fd
, 0); /* </dev/null */
311 dup2(fds
[1], 1); /* >pipe */
314 cupsdExec(command
, argv
);
319 * Parent comes here, open the input side of the pipe...
324 return (cupsFileOpenFd(fds
[0], "r"));
329 * 'cupsdSendIPPGroup()' - Send a group tag.
333 cupsdSendIPPGroup(ipp_tag_t group_tag
) /* I - Group tag */
336 * Send IPP group tag (1 byte)...
344 * 'cupsdSendIPPHeader()' - Send the IPP response header.
349 ipp_status_t status_code
, /* I - Status code */
350 int request_id
) /* I - Request ID */
353 * Send IPP/1.1 response header: version number (2 bytes), status code
354 * (2 bytes), and request ID (4 bytes)...
356 * TODO: Add version number (IPP/2.x and IPP/1.0) support.
362 putchar(status_code
>> 8);
363 putchar(status_code
);
365 putchar(request_id
>> 24);
366 putchar(request_id
>> 16);
367 putchar(request_id
>> 8);
373 * 'cupsdSendIPPInteger()' - Send an integer attribute.
378 ipp_tag_t value_tag
, /* I - Value tag */
379 const char *name
, /* I - Attribute name */
380 int value
) /* I - Attribute value */
382 size_t len
; /* Length of attribute name */
386 * Send IPP integer value: value tag (1 byte), name length (2 bytes),
387 * name string (without nul), value length (2 bytes), and value (4 bytes)...
393 putchar((int)(len
>> 8));
401 putchar(value
>> 24);
402 putchar(value
>> 16);
409 * 'cupsdSendIPPString()' - Send a string attribute.
414 ipp_tag_t value_tag
, /* I - Value tag */
415 const char *name
, /* I - Attribute name */
416 const char *value
) /* I - Attribute value */
418 size_t len
; /* Length of attribute name */
422 * Send IPP string value: value tag (1 byte), name length (2 bytes),
423 * name string (without nul), value length (2 bytes), and value string
430 putchar((int)(len
>> 8));
436 putchar((int)(len
>> 8));
439 fputs(value
, stdout
);
444 * 'cupsdSendIPPTrailer()' - Send the end-of-message tag.
448 cupsdSendIPPTrailer(void)
450 putchar(IPP_TAG_END
);