]>
git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/util.c
2 * "$Id: util.c 7621 2008-06-06 18:55:35Z mike $"
4 * Mini-daemon utility functions for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 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 * cupsdCompareNames() - Compare two names.
18 * cupsdExec() - Run a program with the correct environment.
19 * cupsdPipeCommand() - Read output from a command.
20 * cupsdSendIPPGroup() - Send a group tag.
21 * cupsdSendIPPHeader() - Send the IPP response header.
22 * cupsdSendIPPInteger() - Send an integer attribute.
23 * cupsdSendIPPString() - Send a string attribute.
24 * cupsdSendIPPTrailer() - Send the end-of-message tag.
28 * Include necessary headers...
37 extern char **environ
;
38 #endif /* __APPLE__ */
42 * 'cupsdCompareNames()' - Compare two names.
44 * This function basically does a strcasecmp() of the two strings,
45 * but is also aware of numbers so that "a2" < "a100".
48 int /* O - Result of comparison */
49 cupsdCompareNames(const char *s
, /* I - First string */
50 const char *t
) /* I - Second string */
52 int diff
, /* Difference between digits */
53 digits
; /* Number of digits */
57 * Loop through both names, returning only when a difference is
58 * seen. Also, compare whole numbers rather than just characters, too!
63 if (isdigit(*s
& 255) && isdigit(*t
& 255))
66 * Got a number; start by skipping leading 0's...
75 * Skip equal digits...
78 while (isdigit(*s
& 255) && *s
== *t
)
85 * Bounce out if *s and *t aren't both digits...
88 if (isdigit(*s
& 255) && !isdigit(*t
& 255))
90 else if (!isdigit(*s
& 255) && isdigit(*t
& 255))
92 else if (!isdigit(*s
& 255) || !isdigit(*t
& 255))
101 * Figure out how many more digits there are...
108 while (isdigit(*s
& 255))
114 while (isdigit(*t
& 255))
121 * Return if the number or value of the digits is different...
131 else if (tolower(*s
) < tolower(*t
))
133 else if (tolower(*s
) > tolower(*t
))
143 * Return the results of the final comparison...
156 * 'cupsdExec()' - Run a program with the correct environment.
158 * On Mac OS X, we need to update the CFProcessPath environment variable that
159 * is passed in the environment so the child can access its bundled resources.
162 int /* O - exec() status */
163 cupsdExec(const char *command
, /* I - Full path to program */
164 char **argv
) /* I - Command-line arguments */
167 int i
, j
; /* Looping vars */
168 char *envp
[500], /* Array of environment variables */
169 cfprocesspath
[1024], /* CFProcessPath environment variable */
170 linkpath
[1024]; /* Link path for symlinks... */
171 int linkbytes
; /* Bytes for link path */
175 * Some Mac OS X programs are bundled and need the CFProcessPath environment
176 * variable defined. If the command is a symlink, resolve the link and point
177 * to the resolved location, otherwise, use the command path itself.
180 if ((linkbytes
= readlink(command
, linkpath
, sizeof(linkpath
) - 1)) > 0)
183 * Yes, this is a symlink to the actual program, nul-terminate and
187 linkpath
[linkbytes
] = '\0';
189 if (linkpath
[0] == '/')
190 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s",
193 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s/%s",
194 dirname((char *)command
), linkpath
);
197 snprintf(cfprocesspath
, sizeof(cfprocesspath
), "CFProcessPath=%s", command
);
199 envp
[0] = cfprocesspath
;
202 * Copy the rest of the environment except for any CFProcessPath that may
203 * already be there...
207 environ
[j
] && i
< (int)(sizeof(envp
) / sizeof(envp
[0]) - 1);
209 if (strncmp(environ
[j
], "CFProcessPath=", 14))
210 envp
[i
++] = environ
[j
];
215 * Use execve() to run the program...
218 return (execve(command
, argv
, envp
));
222 * On other operating systems, just call execv() to use the same environment
223 * variables as the parent...
226 return (execv(command
, argv
));
227 #endif /* __APPLE__ */
232 * 'cupsdPipeCommand()' - Read output from a command.
235 cups_file_t
* /* O - CUPS file or NULL on error */
236 cupsdPipeCommand(int *pid
, /* O - Process ID or 0 on error */
237 const char *command
, /* I - Command to run */
238 char **argv
, /* I - Arguments to pass to command */
239 int user
) /* I - User to run as or 0 for current */
241 int fds
[2]; /* Pipe file descriptors */
245 * First create the pipe...
255 * Set the "close on exec" flag on each end of the pipe...
258 if (fcntl(fds
[0], F_SETFD
, fcntl(fds
[0], F_GETFD
) | FD_CLOEXEC
))
268 if (fcntl(fds
[1], F_SETFD
, fcntl(fds
[1], F_GETFD
) | FD_CLOEXEC
))
279 * Then run the command...
282 if ((*pid
= fork()) < 0)
297 * Child comes here...
300 if (!getuid() && user
)
301 setuid(user
); /* Run as restricted user */
303 close(0); /* </dev/null */
304 open("/dev/null", O_RDONLY
);
306 close(1); /* >pipe */
309 cupsdExec(command
, argv
);
314 * Parent comes here, open the input side of the pipe...
319 return (cupsFileOpenFd(fds
[0], "r"));
324 * 'cupsdSendIPPGroup()' - Send a group tag.
328 cupsdSendIPPGroup(ipp_tag_t group_tag
) /* I - Group tag */
331 * Send IPP group tag (1 byte)...
339 * 'cupsdSendIPPHeader()' - Send the IPP response header.
344 ipp_status_t status_code
, /* I - Status code */
345 int request_id
) /* I - Request ID */
348 * Send IPP/1.1 response header: version number (2 bytes), status code
349 * (2 bytes), and request ID (4 bytes)...
355 putchar(status_code
>> 8);
356 putchar(status_code
);
358 putchar(request_id
>> 24);
359 putchar(request_id
>> 16);
360 putchar(request_id
>> 8);
366 * 'cupsdSendIPPInteger()' - Send an integer attribute.
371 ipp_tag_t value_tag
, /* I - Value tag */
372 const char *name
, /* I - Attribute name */
373 int value
) /* I - Attribute value */
375 size_t len
; /* Length of attribute name */
379 * Send IPP integer value: value tag (1 byte), name length (2 bytes),
380 * name string (without nul), value length (2 bytes), and value (4 bytes)...
394 putchar(value
>> 24);
395 putchar(value
>> 16);
402 * 'cupsdSendIPPString()' - Send a string attribute.
407 ipp_tag_t value_tag
, /* I - Value tag */
408 const char *name
, /* I - Attribute name */
409 const char *value
) /* I - Attribute value */
411 size_t len
; /* Length of attribute name */
415 * Send IPP string value: value tag (1 byte), name length (2 bytes),
416 * name string (without nul), value length (2 bytes), and value string
432 fputs(value
, stdout
);
437 * 'cupsdSendIPPTrailer()' - Send the end-of-message tag.
441 cupsdSendIPPTrailer(void)
443 putchar(IPP_TAG_END
);
449 * End of "$Id: util.c 7621 2008-06-06 18:55:35Z mike $".