xref: /aosp_15_r20/external/libcups/scheduler/util.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Mini-daemon utility functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2014 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright 1997-2005 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
8*5e7646d2SAndroid Build Coastguard Worker  */
9*5e7646d2SAndroid Build Coastguard Worker 
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker  */
13*5e7646d2SAndroid Build Coastguard Worker 
14*5e7646d2SAndroid Build Coastguard Worker #include "util.h"
15*5e7646d2SAndroid Build Coastguard Worker #include <unistd.h>
16*5e7646d2SAndroid Build Coastguard Worker #include <sys/stat.h>
17*5e7646d2SAndroid Build Coastguard Worker #include <fcntl.h>
18*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
19*5e7646d2SAndroid Build Coastguard Worker #  include <libgen.h>
20*5e7646d2SAndroid Build Coastguard Worker extern char **environ;
21*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
22*5e7646d2SAndroid Build Coastguard Worker 
23*5e7646d2SAndroid Build Coastguard Worker 
24*5e7646d2SAndroid Build Coastguard Worker /*
25*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdCompareNames()' - Compare two names.
26*5e7646d2SAndroid Build Coastguard Worker  *
27*5e7646d2SAndroid Build Coastguard Worker  * This function basically does a _cups_strcasecmp() of the two strings,
28*5e7646d2SAndroid Build Coastguard Worker  * but is also aware of numbers so that "a2" < "a100".
29*5e7646d2SAndroid Build Coastguard Worker  */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker int					/* O - Result of comparison */
cupsdCompareNames(const char * s,const char * t)32*5e7646d2SAndroid Build Coastguard Worker cupsdCompareNames(const char *s,	/* I - First string */
33*5e7646d2SAndroid Build Coastguard Worker                   const char *t)	/* I - Second string */
34*5e7646d2SAndroid Build Coastguard Worker {
35*5e7646d2SAndroid Build Coastguard Worker   int		diff,			/* Difference between digits */
36*5e7646d2SAndroid Build Coastguard Worker 		digits;			/* Number of digits */
37*5e7646d2SAndroid Build Coastguard Worker 
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker  /*
40*5e7646d2SAndroid Build Coastguard Worker   * Loop through both names, returning only when a difference is
41*5e7646d2SAndroid Build Coastguard Worker   * seen.  Also, compare whole numbers rather than just characters, too!
42*5e7646d2SAndroid Build Coastguard Worker   */
43*5e7646d2SAndroid Build Coastguard Worker 
44*5e7646d2SAndroid Build Coastguard Worker   while (*s && *t)
45*5e7646d2SAndroid Build Coastguard Worker   {
46*5e7646d2SAndroid Build Coastguard Worker     if (isdigit(*s & 255) && isdigit(*t & 255))
47*5e7646d2SAndroid Build Coastguard Worker     {
48*5e7646d2SAndroid Build Coastguard Worker      /*
49*5e7646d2SAndroid Build Coastguard Worker       * Got a number; start by skipping leading 0's...
50*5e7646d2SAndroid Build Coastguard Worker       */
51*5e7646d2SAndroid Build Coastguard Worker 
52*5e7646d2SAndroid Build Coastguard Worker       while (*s == '0')
53*5e7646d2SAndroid Build Coastguard Worker         s ++;
54*5e7646d2SAndroid Build Coastguard Worker       while (*t == '0')
55*5e7646d2SAndroid Build Coastguard Worker         t ++;
56*5e7646d2SAndroid Build Coastguard Worker 
57*5e7646d2SAndroid Build Coastguard Worker      /*
58*5e7646d2SAndroid Build Coastguard Worker       * Skip equal digits...
59*5e7646d2SAndroid Build Coastguard Worker       */
60*5e7646d2SAndroid Build Coastguard Worker 
61*5e7646d2SAndroid Build Coastguard Worker       while (isdigit(*s & 255) && *s == *t)
62*5e7646d2SAndroid Build Coastguard Worker       {
63*5e7646d2SAndroid Build Coastguard Worker         s ++;
64*5e7646d2SAndroid Build Coastguard Worker 	t ++;
65*5e7646d2SAndroid Build Coastguard Worker       }
66*5e7646d2SAndroid Build Coastguard Worker 
67*5e7646d2SAndroid Build Coastguard Worker      /*
68*5e7646d2SAndroid Build Coastguard Worker       * Bounce out if *s and *t aren't both digits...
69*5e7646d2SAndroid Build Coastguard Worker       */
70*5e7646d2SAndroid Build Coastguard Worker 
71*5e7646d2SAndroid Build Coastguard Worker       if (isdigit(*s & 255) && !isdigit(*t & 255))
72*5e7646d2SAndroid Build Coastguard Worker         return (1);
73*5e7646d2SAndroid Build Coastguard Worker       else if (!isdigit(*s & 255) && isdigit(*t & 255))
74*5e7646d2SAndroid Build Coastguard Worker         return (-1);
75*5e7646d2SAndroid Build Coastguard Worker       else if (!isdigit(*s & 255) || !isdigit(*t & 255))
76*5e7646d2SAndroid Build Coastguard Worker         continue;
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker       if (*s < *t)
79*5e7646d2SAndroid Build Coastguard Worker         diff = -1;
80*5e7646d2SAndroid Build Coastguard Worker       else
81*5e7646d2SAndroid Build Coastguard Worker         diff = 1;
82*5e7646d2SAndroid Build Coastguard Worker 
83*5e7646d2SAndroid Build Coastguard Worker      /*
84*5e7646d2SAndroid Build Coastguard Worker       * Figure out how many more digits there are...
85*5e7646d2SAndroid Build Coastguard Worker       */
86*5e7646d2SAndroid Build Coastguard Worker 
87*5e7646d2SAndroid Build Coastguard Worker       digits = 0;
88*5e7646d2SAndroid Build Coastguard Worker       s ++;
89*5e7646d2SAndroid Build Coastguard Worker       t ++;
90*5e7646d2SAndroid Build Coastguard Worker 
91*5e7646d2SAndroid Build Coastguard Worker       while (isdigit(*s & 255))
92*5e7646d2SAndroid Build Coastguard Worker       {
93*5e7646d2SAndroid Build Coastguard Worker         digits ++;
94*5e7646d2SAndroid Build Coastguard Worker 	s ++;
95*5e7646d2SAndroid Build Coastguard Worker       }
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker       while (isdigit(*t & 255))
98*5e7646d2SAndroid Build Coastguard Worker       {
99*5e7646d2SAndroid Build Coastguard Worker         digits --;
100*5e7646d2SAndroid Build Coastguard Worker 	t ++;
101*5e7646d2SAndroid Build Coastguard Worker       }
102*5e7646d2SAndroid Build Coastguard Worker 
103*5e7646d2SAndroid Build Coastguard Worker      /*
104*5e7646d2SAndroid Build Coastguard Worker       * Return if the number or value of the digits is different...
105*5e7646d2SAndroid Build Coastguard Worker       */
106*5e7646d2SAndroid Build Coastguard Worker 
107*5e7646d2SAndroid Build Coastguard Worker       if (digits < 0)
108*5e7646d2SAndroid Build Coastguard Worker         return (-1);
109*5e7646d2SAndroid Build Coastguard Worker       else if (digits > 0)
110*5e7646d2SAndroid Build Coastguard Worker         return (1);
111*5e7646d2SAndroid Build Coastguard Worker       else
112*5e7646d2SAndroid Build Coastguard Worker         return (diff);
113*5e7646d2SAndroid Build Coastguard Worker     }
114*5e7646d2SAndroid Build Coastguard Worker     else if (tolower(*s) < tolower(*t))
115*5e7646d2SAndroid Build Coastguard Worker       return (-1);
116*5e7646d2SAndroid Build Coastguard Worker     else if (tolower(*s) > tolower(*t))
117*5e7646d2SAndroid Build Coastguard Worker       return (1);
118*5e7646d2SAndroid Build Coastguard Worker     else
119*5e7646d2SAndroid Build Coastguard Worker     {
120*5e7646d2SAndroid Build Coastguard Worker       s ++;
121*5e7646d2SAndroid Build Coastguard Worker       t ++;
122*5e7646d2SAndroid Build Coastguard Worker     }
123*5e7646d2SAndroid Build Coastguard Worker   }
124*5e7646d2SAndroid Build Coastguard Worker 
125*5e7646d2SAndroid Build Coastguard Worker  /*
126*5e7646d2SAndroid Build Coastguard Worker   * Return the results of the final comparison...
127*5e7646d2SAndroid Build Coastguard Worker   */
128*5e7646d2SAndroid Build Coastguard Worker 
129*5e7646d2SAndroid Build Coastguard Worker   if (*s)
130*5e7646d2SAndroid Build Coastguard Worker     return (1);
131*5e7646d2SAndroid Build Coastguard Worker   else if (*t)
132*5e7646d2SAndroid Build Coastguard Worker     return (-1);
133*5e7646d2SAndroid Build Coastguard Worker   else
134*5e7646d2SAndroid Build Coastguard Worker     return (0);
135*5e7646d2SAndroid Build Coastguard Worker }
136*5e7646d2SAndroid Build Coastguard Worker 
137*5e7646d2SAndroid Build Coastguard Worker 
138*5e7646d2SAndroid Build Coastguard Worker /*
139*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdCreateStringsArray()' - Create a CUPS array of strings.
140*5e7646d2SAndroid Build Coastguard Worker  */
141*5e7646d2SAndroid Build Coastguard Worker 
142*5e7646d2SAndroid Build Coastguard Worker cups_array_t *				/* O - CUPS array */
cupsdCreateStringsArray(const char * s)143*5e7646d2SAndroid Build Coastguard Worker cupsdCreateStringsArray(const char *s)	/* I - Comma-delimited strings */
144*5e7646d2SAndroid Build Coastguard Worker {
145*5e7646d2SAndroid Build Coastguard Worker   if (s && *s)
146*5e7646d2SAndroid Build Coastguard Worker     return (_cupsArrayNewStrings(s, ','));
147*5e7646d2SAndroid Build Coastguard Worker   else
148*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
149*5e7646d2SAndroid Build Coastguard Worker }
150*5e7646d2SAndroid Build Coastguard Worker 
151*5e7646d2SAndroid Build Coastguard Worker 
152*5e7646d2SAndroid Build Coastguard Worker /*
153*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdExec()' - Run a program with the correct environment.
154*5e7646d2SAndroid Build Coastguard Worker  *
155*5e7646d2SAndroid Build Coastguard Worker  * On macOS, we need to update the CFProcessPath environment variable that
156*5e7646d2SAndroid Build Coastguard Worker  * is passed in the environment so the child can access its bundled resources.
157*5e7646d2SAndroid Build Coastguard Worker  */
158*5e7646d2SAndroid Build Coastguard Worker 
159*5e7646d2SAndroid Build Coastguard Worker int					/* O - exec() status */
cupsdExec(const char * command,char ** argv)160*5e7646d2SAndroid Build Coastguard Worker cupsdExec(const char *command,		/* I - Full path to program */
161*5e7646d2SAndroid Build Coastguard Worker           char       **argv)		/* I - Command-line arguments */
162*5e7646d2SAndroid Build Coastguard Worker {
163*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
164*5e7646d2SAndroid Build Coastguard Worker   int	i, j;				/* Looping vars */
165*5e7646d2SAndroid Build Coastguard Worker   char	*envp[500],			/* Array of environment variables */
166*5e7646d2SAndroid Build Coastguard Worker 	cfprocesspath[1024],		/* CFProcessPath environment variable */
167*5e7646d2SAndroid Build Coastguard Worker 	linkpath[1024];			/* Link path for symlinks... */
168*5e7646d2SAndroid Build Coastguard Worker   int	linkbytes;			/* Bytes for link path */
169*5e7646d2SAndroid Build Coastguard Worker 
170*5e7646d2SAndroid Build Coastguard Worker 
171*5e7646d2SAndroid Build Coastguard Worker  /*
172*5e7646d2SAndroid Build Coastguard Worker   * Some macOS programs are bundled and need the CFProcessPath environment
173*5e7646d2SAndroid Build Coastguard Worker   * variable defined.  If the command is a symlink, resolve the link and point
174*5e7646d2SAndroid Build Coastguard Worker   * to the resolved location, otherwise, use the command path itself.
175*5e7646d2SAndroid Build Coastguard Worker   */
176*5e7646d2SAndroid Build Coastguard Worker 
177*5e7646d2SAndroid Build Coastguard Worker   if ((linkbytes = readlink(command, linkpath, sizeof(linkpath) - 1)) > 0)
178*5e7646d2SAndroid Build Coastguard Worker   {
179*5e7646d2SAndroid Build Coastguard Worker    /*
180*5e7646d2SAndroid Build Coastguard Worker     * Yes, this is a symlink to the actual program, nul-terminate and
181*5e7646d2SAndroid Build Coastguard Worker     * use it...
182*5e7646d2SAndroid Build Coastguard Worker     */
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker     linkpath[linkbytes] = '\0';
185*5e7646d2SAndroid Build Coastguard Worker 
186*5e7646d2SAndroid Build Coastguard Worker     if (linkpath[0] == '/')
187*5e7646d2SAndroid Build Coastguard Worker       snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s",
188*5e7646d2SAndroid Build Coastguard Worker 	       linkpath);
189*5e7646d2SAndroid Build Coastguard Worker     else
190*5e7646d2SAndroid Build Coastguard Worker       snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s/%s",
191*5e7646d2SAndroid Build Coastguard Worker 	       dirname((char *)command), linkpath);
192*5e7646d2SAndroid Build Coastguard Worker   }
193*5e7646d2SAndroid Build Coastguard Worker   else
194*5e7646d2SAndroid Build Coastguard Worker     snprintf(cfprocesspath, sizeof(cfprocesspath), "CFProcessPath=%s", command);
195*5e7646d2SAndroid Build Coastguard Worker 
196*5e7646d2SAndroid Build Coastguard Worker   envp[0] = cfprocesspath;
197*5e7646d2SAndroid Build Coastguard Worker 
198*5e7646d2SAndroid Build Coastguard Worker  /*
199*5e7646d2SAndroid Build Coastguard Worker   * Copy the rest of the environment except for any CFProcessPath that may
200*5e7646d2SAndroid Build Coastguard Worker   * already be there...
201*5e7646d2SAndroid Build Coastguard Worker   */
202*5e7646d2SAndroid Build Coastguard Worker 
203*5e7646d2SAndroid Build Coastguard Worker   for (i = 1, j = 0;
204*5e7646d2SAndroid Build Coastguard Worker        environ[j] && i < (int)(sizeof(envp) / sizeof(envp[0]) - 1);
205*5e7646d2SAndroid Build Coastguard Worker        j ++)
206*5e7646d2SAndroid Build Coastguard Worker     if (strncmp(environ[j], "CFProcessPath=", 14))
207*5e7646d2SAndroid Build Coastguard Worker       envp[i ++] = environ[j];
208*5e7646d2SAndroid Build Coastguard Worker 
209*5e7646d2SAndroid Build Coastguard Worker   envp[i] = NULL;
210*5e7646d2SAndroid Build Coastguard Worker 
211*5e7646d2SAndroid Build Coastguard Worker  /*
212*5e7646d2SAndroid Build Coastguard Worker   * Use execve() to run the program...
213*5e7646d2SAndroid Build Coastguard Worker   */
214*5e7646d2SAndroid Build Coastguard Worker 
215*5e7646d2SAndroid Build Coastguard Worker   return (execve(command, argv, envp));
216*5e7646d2SAndroid Build Coastguard Worker 
217*5e7646d2SAndroid Build Coastguard Worker #else
218*5e7646d2SAndroid Build Coastguard Worker  /*
219*5e7646d2SAndroid Build Coastguard Worker   * On other operating systems, just call execv() to use the same environment
220*5e7646d2SAndroid Build Coastguard Worker   * variables as the parent...
221*5e7646d2SAndroid Build Coastguard Worker   */
222*5e7646d2SAndroid Build Coastguard Worker 
223*5e7646d2SAndroid Build Coastguard Worker   return (execv(command, argv));
224*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
225*5e7646d2SAndroid Build Coastguard Worker }
226*5e7646d2SAndroid Build Coastguard Worker 
227*5e7646d2SAndroid Build Coastguard Worker 
228*5e7646d2SAndroid Build Coastguard Worker /*
229*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdPipeCommand()' - Read output from a command.
230*5e7646d2SAndroid Build Coastguard Worker  */
231*5e7646d2SAndroid Build Coastguard Worker 
232*5e7646d2SAndroid Build Coastguard Worker cups_file_t *				/* O - CUPS file or NULL on error */
cupsdPipeCommand(int * pid,const char * command,char ** argv,uid_t user)233*5e7646d2SAndroid Build Coastguard Worker cupsdPipeCommand(int        *pid,	/* O - Process ID or 0 on error */
234*5e7646d2SAndroid Build Coastguard Worker                  const char *command,	/* I - Command to run */
235*5e7646d2SAndroid Build Coastguard Worker                  char       **argv,	/* I - Arguments to pass to command */
236*5e7646d2SAndroid Build Coastguard Worker 		 uid_t      user)	/* I - User to run as or 0 for current */
237*5e7646d2SAndroid Build Coastguard Worker {
238*5e7646d2SAndroid Build Coastguard Worker   int	fd,				/* Temporary file descriptor */
239*5e7646d2SAndroid Build Coastguard Worker 	fds[2];				/* Pipe file descriptors */
240*5e7646d2SAndroid Build Coastguard Worker 
241*5e7646d2SAndroid Build Coastguard Worker 
242*5e7646d2SAndroid Build Coastguard Worker  /*
243*5e7646d2SAndroid Build Coastguard Worker   * First create the pipe...
244*5e7646d2SAndroid Build Coastguard Worker   */
245*5e7646d2SAndroid Build Coastguard Worker 
246*5e7646d2SAndroid Build Coastguard Worker   if (pipe(fds))
247*5e7646d2SAndroid Build Coastguard Worker   {
248*5e7646d2SAndroid Build Coastguard Worker     *pid = 0;
249*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
250*5e7646d2SAndroid Build Coastguard Worker   }
251*5e7646d2SAndroid Build Coastguard Worker 
252*5e7646d2SAndroid Build Coastguard Worker  /*
253*5e7646d2SAndroid Build Coastguard Worker   * Set the "close on exec" flag on each end of the pipe...
254*5e7646d2SAndroid Build Coastguard Worker   */
255*5e7646d2SAndroid Build Coastguard Worker 
256*5e7646d2SAndroid Build Coastguard Worker   if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
257*5e7646d2SAndroid Build Coastguard Worker   {
258*5e7646d2SAndroid Build Coastguard Worker     close(fds[0]);
259*5e7646d2SAndroid Build Coastguard Worker     close(fds[1]);
260*5e7646d2SAndroid Build Coastguard Worker 
261*5e7646d2SAndroid Build Coastguard Worker     *pid = 0;
262*5e7646d2SAndroid Build Coastguard Worker 
263*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
264*5e7646d2SAndroid Build Coastguard Worker   }
265*5e7646d2SAndroid Build Coastguard Worker 
266*5e7646d2SAndroid Build Coastguard Worker   if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
267*5e7646d2SAndroid Build Coastguard Worker   {
268*5e7646d2SAndroid Build Coastguard Worker     close(fds[0]);
269*5e7646d2SAndroid Build Coastguard Worker     close(fds[1]);
270*5e7646d2SAndroid Build Coastguard Worker 
271*5e7646d2SAndroid Build Coastguard Worker     *pid = 0;
272*5e7646d2SAndroid Build Coastguard Worker 
273*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
274*5e7646d2SAndroid Build Coastguard Worker   }
275*5e7646d2SAndroid Build Coastguard Worker 
276*5e7646d2SAndroid Build Coastguard Worker  /*
277*5e7646d2SAndroid Build Coastguard Worker   * Then run the command...
278*5e7646d2SAndroid Build Coastguard Worker   */
279*5e7646d2SAndroid Build Coastguard Worker 
280*5e7646d2SAndroid Build Coastguard Worker   if ((*pid = fork()) < 0)
281*5e7646d2SAndroid Build Coastguard Worker   {
282*5e7646d2SAndroid Build Coastguard Worker    /*
283*5e7646d2SAndroid Build Coastguard Worker     * Unable to fork!
284*5e7646d2SAndroid Build Coastguard Worker     */
285*5e7646d2SAndroid Build Coastguard Worker 
286*5e7646d2SAndroid Build Coastguard Worker     *pid = 0;
287*5e7646d2SAndroid Build Coastguard Worker     close(fds[0]);
288*5e7646d2SAndroid Build Coastguard Worker     close(fds[1]);
289*5e7646d2SAndroid Build Coastguard Worker 
290*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
291*5e7646d2SAndroid Build Coastguard Worker   }
292*5e7646d2SAndroid Build Coastguard Worker   else if (!*pid)
293*5e7646d2SAndroid Build Coastguard Worker   {
294*5e7646d2SAndroid Build Coastguard Worker    /*
295*5e7646d2SAndroid Build Coastguard Worker     * Child comes here...
296*5e7646d2SAndroid Build Coastguard Worker     */
297*5e7646d2SAndroid Build Coastguard Worker 
298*5e7646d2SAndroid Build Coastguard Worker     if (!getuid() && user)
299*5e7646d2SAndroid Build Coastguard Worker       setuid(user);			/* Run as restricted user */
300*5e7646d2SAndroid Build Coastguard Worker 
301*5e7646d2SAndroid Build Coastguard Worker     if ((fd = open("/dev/null", O_RDONLY)) > 0)
302*5e7646d2SAndroid Build Coastguard Worker     {
303*5e7646d2SAndroid Build Coastguard Worker       dup2(fd, 0);			/* </dev/null */
304*5e7646d2SAndroid Build Coastguard Worker       close(fd);
305*5e7646d2SAndroid Build Coastguard Worker     }
306*5e7646d2SAndroid Build Coastguard Worker 
307*5e7646d2SAndroid Build Coastguard Worker     dup2(fds[1], 1);			/* >pipe */
308*5e7646d2SAndroid Build Coastguard Worker     close(fds[1]);
309*5e7646d2SAndroid Build Coastguard Worker 
310*5e7646d2SAndroid Build Coastguard Worker     cupsdExec(command, argv);
311*5e7646d2SAndroid Build Coastguard Worker     exit(errno);
312*5e7646d2SAndroid Build Coastguard Worker   }
313*5e7646d2SAndroid Build Coastguard Worker 
314*5e7646d2SAndroid Build Coastguard Worker  /*
315*5e7646d2SAndroid Build Coastguard Worker   * Parent comes here, open the input side of the pipe...
316*5e7646d2SAndroid Build Coastguard Worker   */
317*5e7646d2SAndroid Build Coastguard Worker 
318*5e7646d2SAndroid Build Coastguard Worker   close(fds[1]);
319*5e7646d2SAndroid Build Coastguard Worker 
320*5e7646d2SAndroid Build Coastguard Worker   return (cupsFileOpenFd(fds[0], "r"));
321*5e7646d2SAndroid Build Coastguard Worker }
322*5e7646d2SAndroid Build Coastguard Worker 
323*5e7646d2SAndroid Build Coastguard Worker 
324*5e7646d2SAndroid Build Coastguard Worker /*
325*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdSendIPPGroup()' - Send a group tag.
326*5e7646d2SAndroid Build Coastguard Worker  */
327*5e7646d2SAndroid Build Coastguard Worker 
328*5e7646d2SAndroid Build Coastguard Worker void
cupsdSendIPPGroup(ipp_tag_t group_tag)329*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPGroup(ipp_tag_t group_tag)	/* I - Group tag */
330*5e7646d2SAndroid Build Coastguard Worker {
331*5e7646d2SAndroid Build Coastguard Worker  /*
332*5e7646d2SAndroid Build Coastguard Worker   * Send IPP group tag (1 byte)...
333*5e7646d2SAndroid Build Coastguard Worker   */
334*5e7646d2SAndroid Build Coastguard Worker 
335*5e7646d2SAndroid Build Coastguard Worker   putchar(group_tag);
336*5e7646d2SAndroid Build Coastguard Worker }
337*5e7646d2SAndroid Build Coastguard Worker 
338*5e7646d2SAndroid Build Coastguard Worker 
339*5e7646d2SAndroid Build Coastguard Worker /*
340*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdSendIPPHeader()' - Send the IPP response header.
341*5e7646d2SAndroid Build Coastguard Worker  */
342*5e7646d2SAndroid Build Coastguard Worker 
343*5e7646d2SAndroid Build Coastguard Worker void
cupsdSendIPPHeader(ipp_status_t status_code,int request_id)344*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPHeader(
345*5e7646d2SAndroid Build Coastguard Worker     ipp_status_t status_code,		/* I - Status code */
346*5e7646d2SAndroid Build Coastguard Worker     int          request_id)		/* I - Request ID */
347*5e7646d2SAndroid Build Coastguard Worker {
348*5e7646d2SAndroid Build Coastguard Worker  /*
349*5e7646d2SAndroid Build Coastguard Worker   * Send IPP/1.1 response header: version number (2 bytes), status code
350*5e7646d2SAndroid Build Coastguard Worker   * (2 bytes), and request ID (4 bytes)...
351*5e7646d2SAndroid Build Coastguard Worker   *
352*5e7646d2SAndroid Build Coastguard Worker   * TODO: Add version number (IPP/2.x and IPP/1.0) support.
353*5e7646d2SAndroid Build Coastguard Worker   */
354*5e7646d2SAndroid Build Coastguard Worker 
355*5e7646d2SAndroid Build Coastguard Worker   putchar(1);
356*5e7646d2SAndroid Build Coastguard Worker   putchar(1);
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker   putchar(status_code >> 8);
359*5e7646d2SAndroid Build Coastguard Worker   putchar(status_code);
360*5e7646d2SAndroid Build Coastguard Worker 
361*5e7646d2SAndroid Build Coastguard Worker   putchar(request_id >> 24);
362*5e7646d2SAndroid Build Coastguard Worker   putchar(request_id >> 16);
363*5e7646d2SAndroid Build Coastguard Worker   putchar(request_id >> 8);
364*5e7646d2SAndroid Build Coastguard Worker   putchar(request_id);
365*5e7646d2SAndroid Build Coastguard Worker }
366*5e7646d2SAndroid Build Coastguard Worker 
367*5e7646d2SAndroid Build Coastguard Worker 
368*5e7646d2SAndroid Build Coastguard Worker /*
369*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdSendIPPInteger()' - Send an integer attribute.
370*5e7646d2SAndroid Build Coastguard Worker  */
371*5e7646d2SAndroid Build Coastguard Worker 
372*5e7646d2SAndroid Build Coastguard Worker void
cupsdSendIPPInteger(ipp_tag_t value_tag,const char * name,int value)373*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPInteger(
374*5e7646d2SAndroid Build Coastguard Worker     ipp_tag_t  value_tag,		/* I - Value tag */
375*5e7646d2SAndroid Build Coastguard Worker     const char *name,			/* I - Attribute name */
376*5e7646d2SAndroid Build Coastguard Worker     int        value)			/* I - Attribute value */
377*5e7646d2SAndroid Build Coastguard Worker {
378*5e7646d2SAndroid Build Coastguard Worker   size_t	len;			/* Length of attribute name */
379*5e7646d2SAndroid Build Coastguard Worker 
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker  /*
382*5e7646d2SAndroid Build Coastguard Worker   * Send IPP integer value: value tag (1 byte), name length (2 bytes),
383*5e7646d2SAndroid Build Coastguard Worker   * name string (without nul), value length (2 bytes), and value (4 bytes)...
384*5e7646d2SAndroid Build Coastguard Worker   */
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker   putchar(value_tag);
387*5e7646d2SAndroid Build Coastguard Worker 
388*5e7646d2SAndroid Build Coastguard Worker   len = strlen(name);
389*5e7646d2SAndroid Build Coastguard Worker   putchar((int)(len >> 8));
390*5e7646d2SAndroid Build Coastguard Worker   putchar((int)len);
391*5e7646d2SAndroid Build Coastguard Worker 
392*5e7646d2SAndroid Build Coastguard Worker   fputs(name, stdout);
393*5e7646d2SAndroid Build Coastguard Worker 
394*5e7646d2SAndroid Build Coastguard Worker   putchar(0);
395*5e7646d2SAndroid Build Coastguard Worker   putchar(4);
396*5e7646d2SAndroid Build Coastguard Worker 
397*5e7646d2SAndroid Build Coastguard Worker   putchar(value >> 24);
398*5e7646d2SAndroid Build Coastguard Worker   putchar(value >> 16);
399*5e7646d2SAndroid Build Coastguard Worker   putchar(value >> 8);
400*5e7646d2SAndroid Build Coastguard Worker   putchar(value);
401*5e7646d2SAndroid Build Coastguard Worker }
402*5e7646d2SAndroid Build Coastguard Worker 
403*5e7646d2SAndroid Build Coastguard Worker 
404*5e7646d2SAndroid Build Coastguard Worker /*
405*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdSendIPPString()' - Send a string attribute.
406*5e7646d2SAndroid Build Coastguard Worker  */
407*5e7646d2SAndroid Build Coastguard Worker 
408*5e7646d2SAndroid Build Coastguard Worker void
cupsdSendIPPString(ipp_tag_t value_tag,const char * name,const char * value)409*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPString(
410*5e7646d2SAndroid Build Coastguard Worker     ipp_tag_t  value_tag,		/* I - Value tag */
411*5e7646d2SAndroid Build Coastguard Worker     const char *name,			/* I - Attribute name */
412*5e7646d2SAndroid Build Coastguard Worker     const char *value)			/* I - Attribute value */
413*5e7646d2SAndroid Build Coastguard Worker {
414*5e7646d2SAndroid Build Coastguard Worker   size_t	len;			/* Length of attribute name */
415*5e7646d2SAndroid Build Coastguard Worker 
416*5e7646d2SAndroid Build Coastguard Worker 
417*5e7646d2SAndroid Build Coastguard Worker  /*
418*5e7646d2SAndroid Build Coastguard Worker   * Send IPP string value: value tag (1 byte), name length (2 bytes),
419*5e7646d2SAndroid Build Coastguard Worker   * name string (without nul), value length (2 bytes), and value string
420*5e7646d2SAndroid Build Coastguard Worker   * (without nul)...
421*5e7646d2SAndroid Build Coastguard Worker   */
422*5e7646d2SAndroid Build Coastguard Worker 
423*5e7646d2SAndroid Build Coastguard Worker   putchar(value_tag);
424*5e7646d2SAndroid Build Coastguard Worker 
425*5e7646d2SAndroid Build Coastguard Worker   len = strlen(name);
426*5e7646d2SAndroid Build Coastguard Worker   putchar((int)(len >> 8));
427*5e7646d2SAndroid Build Coastguard Worker   putchar((int)len);
428*5e7646d2SAndroid Build Coastguard Worker 
429*5e7646d2SAndroid Build Coastguard Worker   fputs(name, stdout);
430*5e7646d2SAndroid Build Coastguard Worker 
431*5e7646d2SAndroid Build Coastguard Worker   len = strlen(value);
432*5e7646d2SAndroid Build Coastguard Worker   putchar((int)(len >> 8));
433*5e7646d2SAndroid Build Coastguard Worker   putchar((int)len);
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker   fputs(value, stdout);
436*5e7646d2SAndroid Build Coastguard Worker }
437*5e7646d2SAndroid Build Coastguard Worker 
438*5e7646d2SAndroid Build Coastguard Worker 
439*5e7646d2SAndroid Build Coastguard Worker /*
440*5e7646d2SAndroid Build Coastguard Worker  * 'cupsdSendIPPTrailer()' - Send the end-of-message tag.
441*5e7646d2SAndroid Build Coastguard Worker  */
442*5e7646d2SAndroid Build Coastguard Worker 
443*5e7646d2SAndroid Build Coastguard Worker void
cupsdSendIPPTrailer(void)444*5e7646d2SAndroid Build Coastguard Worker cupsdSendIPPTrailer(void)
445*5e7646d2SAndroid Build Coastguard Worker {
446*5e7646d2SAndroid Build Coastguard Worker   putchar(IPP_TAG_END);
447*5e7646d2SAndroid Build Coastguard Worker   fflush(stdout);
448*5e7646d2SAndroid Build Coastguard Worker }
449