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