]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/util.c
4 * Mini-daemon utility functions for CUPS.
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2005 by Easy Software Products.
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 * Include necessary headers...
26 extern char **environ
;
27 #endif /* __APPLE__ */
31 * 'cupsdCompareNames()' - Compare two names.
33 * This function basically does a _cups_strcasecmp() of the two strings,
34 * but is also aware of numbers so that "a2" < "a100".
37 int /* O - Result of comparison */
38 cupsdCompareNames(const char *s
, /* I - First string */
39 const char *t
) /* I - Second string */
41 int diff
, /* Difference between digits */
42 digits
; /* Number of digits */
46 * Loop through both names, returning only when a difference is
47 * seen. Also, compare whole numbers rather than just characters, too!
52 if (isdigit(*s
& 255) && isdigit(*t
& 255))
55 * Got a number; start by skipping leading 0's...
64 * Skip equal digits...
67 while (isdigit(*s
& 255) && *s
== *t
)
74 * Bounce out if *s and *t aren't both digits...
77 if (isdigit(*s
& 255) && !isdigit(*t
& 255))
79 else if (!isdigit(*s
& 255) && isdigit(*t
& 255))
81 else if (!isdigit(*s
& 255) || !isdigit(*t
& 255))
90 * Figure out how many more digits there are...
97 while (isdigit(*s
& 255))
103 while (isdigit(*t
& 255))
110 * Return if the number or value of the digits is different...
120 else if (tolower(*s
) < tolower(*t
))
122 else if (tolower(*s
) > tolower(*t
))
132 * Return the results of the final comparison...
145 * 'cupsdCreateStringsArray()' - Create a CUPS array of strings.
148 cups_array_t
* /* O - CUPS array */
149 cupsdCreateStringsArray(const char *s
) /* I - Comma-delimited strings */
154 return (_cupsArrayNewStrings(s
, ','));
159 * 'cupsdExec()' - Run a program with the correct environment.
161 * On OS X, we need to update the CFProcessPath environment variable that
162 * is passed in the environment so the child can access its bundled resources.
165 int /* O - exec() status */
166 cupsdExec(const char *command
, /* I - Full path to program */
167 char **argv
) /* I - Command-line arguments */
170 int i
, j
; /* Looping vars */
171 char *envp
[500], /* Array of environment variables */
172 cfprocesspath
[1024], /* CFProcessPath environment variable */
173 linkpath
[1024]; /* Link path for symlinks... */
174 int linkbytes
; /* Bytes for link path */
178 * Some OS X programs are bundled and need the CFProcessPath environment
179 * variable defined. If the command is a symlink, resolve the link and point
180 * to the resolved location, otherwise, use the command path itself.
183 if ((linkbytes
= readlink(command
, linkpath
, sizeof(linkpath
) - 1)) > 0)
186 * Yes, this is a symlink to the actual program, nul-terminate and
190 linkpath
[linkbytes
] = '\0';
192 if (linkpath
[0] == '/')
193 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s",
196 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s/%s",
197 dirname((char *)command
), linkpath
);
200 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s", command
);
202 envp
[0] = cfprocesspath
;
205 * Copy the rest of the environment except for any CFProcessPath that may
206 * already be there...
210 environ
[j
] && i
< (int)(sizeof(envp
) / sizeof(envp
[0]) - 1);
212 if (strncmp(environ
[j
], "CFProcessPath=", 14))
213 envp
[i
++] = environ
[j
];
218 * Use execve() to run the program...
221 return (execve(command
, argv
, envp
));
225 * On other operating systems, just call execv() to use the same environment
226 * variables as the parent...
229 return (execv(command
, argv
));
230 #endif /* __APPLE__ */
235 * 'cupsdPipeCommand()' - Read output from a command.
238 cups_file_t
* /* O - CUPS file or NULL on error */
239 cupsdPipeCommand(int *pid
, /* O - Process ID or 0 on error */
240 const char *command
, /* I - Command to run */
241 char **argv
, /* I - Arguments to pass to command */
242 uid_t user
) /* I - User to run as or 0 for current */
244 int fd
, /* Temporary file descriptor */
245 fds
[2]; /* Pipe file descriptors */
249 * First create the pipe...
259 * Set the "close on exec" flag on each end of the pipe...
262 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
272 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
283 * Then run the command...
286 if ((*pid
= fork()) < 0)
301 * Child comes here...
304 if (!getuid() && user
)
305 setuid(user
); /* Run as restricted user */
307 if ((fd
= open("/dev/null", O_RDONLY
)) > 0)
309 dup2(fd
, 0); /* </dev/null */
313 dup2(fds
[1], 1); /* >pipe */
316 cupsdExec(command
, argv
);
321 * Parent comes here, open the input side of the pipe...
326 return (cupsFileOpenFd(fds
[0], "r"));
331 * 'cupsdSendIPPGroup()' - Send a group tag.
335 cupsdSendIPPGroup(ipp_tag_t group_tag
) /* I - Group tag */
338 * Send IPP group tag (1 byte)...
346 * 'cupsdSendIPPHeader()' - Send the IPP response header.
351 ipp_status_t status_code
, /* I - Status code */
352 int request_id
) /* I - Request ID */
355 * Send IPP/1.1 response header: version number (2 bytes), status code
356 * (2 bytes), and request ID (4 bytes)...
358 * TODO: Add version number (IPP/2.x and IPP/1.0) support.
364 putchar(status_code
>> 8);
365 putchar(status_code
);
367 putchar(request_id
>> 24);
368 putchar(request_id
>> 16);
369 putchar(request_id
>> 8);
375 * 'cupsdSendIPPInteger()' - Send an integer attribute.
380 ipp_tag_t value_tag
, /* I - Value tag */
381 const char *name
, /* I - Attribute name */
382 int value
) /* I - Attribute value */
384 size_t len
; /* Length of attribute name */
388 * Send IPP integer value: value tag (1 byte), name length (2 bytes),
389 * name string (without nul), value length (2 bytes), and value (4 bytes)...
395 putchar((int)(len
>> 8));
403 putchar(value
>> 24);
404 putchar(value
>> 16);
411 * 'cupsdSendIPPString()' - Send a string attribute.
416 ipp_tag_t value_tag
, /* I - Value tag */
417 const char *name
, /* I - Attribute name */
418 const char *value
) /* I - Attribute value */
420 size_t len
; /* Length of attribute name */
424 * Send IPP string value: value tag (1 byte), name length (2 bytes),
425 * name string (without nul), value length (2 bytes), and value string
432 putchar((int)(len
>> 8));
438 putchar((int)(len
>> 8));
441 fputs(value
, stdout
);
446 * 'cupsdSendIPPTrailer()' - Send the end-of-message tag.
450 cupsdSendIPPTrailer(void)
452 putchar(IPP_TAG_END
);