xref: /aosp_15_r20/external/libcups/scheduler/cups-lpd.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Line Printer Daemon interface for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2016 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright 1997-2006 by Easy Software Products, all rights reserved.
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 #define _CUPS_NO_DEPRECATED
15*5e7646d2SAndroid Build Coastguard Worker #include <cups/cups-private.h>
16*5e7646d2SAndroid Build Coastguard Worker #include <syslog.h>
17*5e7646d2SAndroid Build Coastguard Worker #include <unistd.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <fcntl.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <sys/types.h>
20*5e7646d2SAndroid Build Coastguard Worker #include <sys/socket.h>
21*5e7646d2SAndroid Build Coastguard Worker #include <netinet/in.h>
22*5e7646d2SAndroid Build Coastguard Worker #include <netdb.h>
23*5e7646d2SAndroid Build Coastguard Worker 
24*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_INTTYPES_H
25*5e7646d2SAndroid Build Coastguard Worker #  include <inttypes.h>
26*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_INTTYPES_H */
27*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
28*5e7646d2SAndroid Build Coastguard Worker #  include <xpc/xpc.h>
29*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker 
32*5e7646d2SAndroid Build Coastguard Worker /*
33*5e7646d2SAndroid Build Coastguard Worker  * LPD "mini-daemon" for CUPS.  This program must be used in conjunction
34*5e7646d2SAndroid Build Coastguard Worker  * with inetd or another similar program that monitors ports and starts
35*5e7646d2SAndroid Build Coastguard Worker  * daemons for each client connection.  A typical configuration is:
36*5e7646d2SAndroid Build Coastguard Worker  *
37*5e7646d2SAndroid Build Coastguard Worker  *    printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
38*5e7646d2SAndroid Build Coastguard Worker  *
39*5e7646d2SAndroid Build Coastguard Worker  * This daemon implements most of RFC 1179 (the unofficial LPD specification)
40*5e7646d2SAndroid Build Coastguard Worker  * except for:
41*5e7646d2SAndroid Build Coastguard Worker  *
42*5e7646d2SAndroid Build Coastguard Worker  *     - This daemon does not check to make sure that the source port is
43*5e7646d2SAndroid Build Coastguard Worker  *       between 721 and 731, since it isn't necessary for proper
44*5e7646d2SAndroid Build Coastguard Worker  *       functioning and port-based security is no security at all!
45*5e7646d2SAndroid Build Coastguard Worker  *
46*5e7646d2SAndroid Build Coastguard Worker  *     - The "Print any waiting jobs" command is a no-op.
47*5e7646d2SAndroid Build Coastguard Worker  *
48*5e7646d2SAndroid Build Coastguard Worker  * The LPD-to-IPP mapping is as defined in RFC 2569.  The report formats
49*5e7646d2SAndroid Build Coastguard Worker  * currently match the Solaris LPD mini-daemon.
50*5e7646d2SAndroid Build Coastguard Worker  */
51*5e7646d2SAndroid Build Coastguard Worker 
52*5e7646d2SAndroid Build Coastguard Worker /*
53*5e7646d2SAndroid Build Coastguard Worker  * Prototypes...
54*5e7646d2SAndroid Build Coastguard Worker  */
55*5e7646d2SAndroid Build Coastguard Worker 
56*5e7646d2SAndroid Build Coastguard Worker static int	create_job(http_t *http, const char *dest, const char *title, const char *user, int num_options, cups_option_t *options);
57*5e7646d2SAndroid Build Coastguard Worker static int	get_printer(http_t *http, const char *name, char *dest,
58*5e7646d2SAndroid Build Coastguard Worker 		            size_t destsize, cups_option_t **options,
59*5e7646d2SAndroid Build Coastguard Worker 			    int *accepting, int *shared, ipp_pstate_t *state);
60*5e7646d2SAndroid Build Coastguard Worker static int	print_file(http_t *http, int id, const char *filename,
61*5e7646d2SAndroid Build Coastguard Worker 		           const char *docname, const char *user,
62*5e7646d2SAndroid Build Coastguard Worker 			   const char *format, int last);
63*5e7646d2SAndroid Build Coastguard Worker static int	recv_print_job(const char *name, int num_defaults,
64*5e7646d2SAndroid Build Coastguard Worker 		               cups_option_t *defaults);
65*5e7646d2SAndroid Build Coastguard Worker static int	remove_jobs(const char *name, const char *agent,
66*5e7646d2SAndroid Build Coastguard Worker 		            const char *list);
67*5e7646d2SAndroid Build Coastguard Worker static int	send_state(const char *name, const char *list,
68*5e7646d2SAndroid Build Coastguard Worker 		           int longstatus);
69*5e7646d2SAndroid Build Coastguard Worker static char	*smart_gets(char *s, int len, FILE *fp);
70*5e7646d2SAndroid Build Coastguard Worker static void	smart_strlcpy(char *dst, const char *src, size_t dstsize);
71*5e7646d2SAndroid Build Coastguard Worker 
72*5e7646d2SAndroid Build Coastguard Worker 
73*5e7646d2SAndroid Build Coastguard Worker /*
74*5e7646d2SAndroid Build Coastguard Worker  * 'main()' - Process an incoming LPD request...
75*5e7646d2SAndroid Build Coastguard Worker  */
76*5e7646d2SAndroid Build Coastguard Worker 
77*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit status */
main(int argc,char * argv[])78*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line arguments */
79*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
80*5e7646d2SAndroid Build Coastguard Worker {
81*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
82*5e7646d2SAndroid Build Coastguard Worker   int		num_defaults;		/* Number of default options */
83*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*defaults;		/* Default options */
84*5e7646d2SAndroid Build Coastguard Worker   char		line[256],		/* Command string */
85*5e7646d2SAndroid Build Coastguard Worker 		command,		/* Command code */
86*5e7646d2SAndroid Build Coastguard Worker 		*dest,			/* Pointer to destination */
87*5e7646d2SAndroid Build Coastguard Worker 		*list,			/* Pointer to list */
88*5e7646d2SAndroid Build Coastguard Worker 		*agent,			/* Pointer to user */
89*5e7646d2SAndroid Build Coastguard Worker 		status;			/* Status for client */
90*5e7646d2SAndroid Build Coastguard Worker   socklen_t	hostlen;		/* Size of client address */
91*5e7646d2SAndroid Build Coastguard Worker   http_addr_t	hostaddr;		/* Address of client */
92*5e7646d2SAndroid Build Coastguard Worker   char		hostname[256],		/* Name of client */
93*5e7646d2SAndroid Build Coastguard Worker 		hostip[256],		/* IP address */
94*5e7646d2SAndroid Build Coastguard Worker 		*hostfamily;		/* Address family */
95*5e7646d2SAndroid Build Coastguard Worker   int		hostlookups;		/* Do hostname lookups? */
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker 
98*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
99*5e7646d2SAndroid Build Coastguard Worker   xpc_transaction_begin();
100*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
101*5e7646d2SAndroid Build Coastguard Worker 
102*5e7646d2SAndroid Build Coastguard Worker  /*
103*5e7646d2SAndroid Build Coastguard Worker   * Don't buffer the output...
104*5e7646d2SAndroid Build Coastguard Worker   */
105*5e7646d2SAndroid Build Coastguard Worker 
106*5e7646d2SAndroid Build Coastguard Worker   setbuf(stdout, NULL);
107*5e7646d2SAndroid Build Coastguard Worker 
108*5e7646d2SAndroid Build Coastguard Worker  /*
109*5e7646d2SAndroid Build Coastguard Worker   * Log things using the "cups-lpd" name...
110*5e7646d2SAndroid Build Coastguard Worker   */
111*5e7646d2SAndroid Build Coastguard Worker 
112*5e7646d2SAndroid Build Coastguard Worker   openlog("cups-lpd", LOG_PID, LOG_LPR);
113*5e7646d2SAndroid Build Coastguard Worker 
114*5e7646d2SAndroid Build Coastguard Worker  /*
115*5e7646d2SAndroid Build Coastguard Worker   * Scan the command-line for options...
116*5e7646d2SAndroid Build Coastguard Worker   */
117*5e7646d2SAndroid Build Coastguard Worker 
118*5e7646d2SAndroid Build Coastguard Worker   num_defaults = 0;
119*5e7646d2SAndroid Build Coastguard Worker   defaults     = NULL;
120*5e7646d2SAndroid Build Coastguard Worker   hostlookups  = 1;
121*5e7646d2SAndroid Build Coastguard Worker 
122*5e7646d2SAndroid Build Coastguard Worker   for (i = 1; i < argc; i ++)
123*5e7646d2SAndroid Build Coastguard Worker     if (argv[i][0] == '-')
124*5e7646d2SAndroid Build Coastguard Worker     {
125*5e7646d2SAndroid Build Coastguard Worker       switch (argv[i][1])
126*5e7646d2SAndroid Build Coastguard Worker       {
127*5e7646d2SAndroid Build Coastguard Worker         case 'h' : /* -h hostname[:port] */
128*5e7646d2SAndroid Build Coastguard Worker             if (argv[i][2])
129*5e7646d2SAndroid Build Coastguard Worker 	      cupsSetServer(argv[i] + 2);
130*5e7646d2SAndroid Build Coastguard Worker 	    else
131*5e7646d2SAndroid Build Coastguard Worker 	    {
132*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
133*5e7646d2SAndroid Build Coastguard Worker 	      if (i < argc)
134*5e7646d2SAndroid Build Coastguard Worker 	        cupsSetServer(argv[i]);
135*5e7646d2SAndroid Build Coastguard Worker 	      else
136*5e7646d2SAndroid Build Coastguard Worker 	        syslog(LOG_WARNING, "Expected hostname string after -h option!");
137*5e7646d2SAndroid Build Coastguard Worker 	    }
138*5e7646d2SAndroid Build Coastguard Worker 	    break;
139*5e7646d2SAndroid Build Coastguard Worker 
140*5e7646d2SAndroid Build Coastguard Worker 	case 'o' : /* Option */
141*5e7646d2SAndroid Build Coastguard Worker 	    if (argv[i][2])
142*5e7646d2SAndroid Build Coastguard Worker 	      num_defaults = cupsParseOptions(argv[i] + 2, num_defaults,
143*5e7646d2SAndroid Build Coastguard Worker 	                                      &defaults);
144*5e7646d2SAndroid Build Coastguard Worker 	    else
145*5e7646d2SAndroid Build Coastguard Worker 	    {
146*5e7646d2SAndroid Build Coastguard Worker 	      i ++;
147*5e7646d2SAndroid Build Coastguard Worker 	      if (i < argc)
148*5e7646d2SAndroid Build Coastguard Worker 		num_defaults = cupsParseOptions(argv[i], num_defaults,
149*5e7646d2SAndroid Build Coastguard Worker 		                                &defaults);
150*5e7646d2SAndroid Build Coastguard Worker               else
151*5e7646d2SAndroid Build Coastguard Worker         	syslog(LOG_WARNING, "Expected option string after -o option!");
152*5e7646d2SAndroid Build Coastguard Worker             }
153*5e7646d2SAndroid Build Coastguard Worker 	    break;
154*5e7646d2SAndroid Build Coastguard Worker 
155*5e7646d2SAndroid Build Coastguard Worker         case 'n' : /* Don't do hostname lookups */
156*5e7646d2SAndroid Build Coastguard Worker 	    hostlookups = 0;
157*5e7646d2SAndroid Build Coastguard Worker 	    break;
158*5e7646d2SAndroid Build Coastguard Worker 
159*5e7646d2SAndroid Build Coastguard Worker 	default :
160*5e7646d2SAndroid Build Coastguard Worker 	    syslog(LOG_WARNING, "Unknown option \"%c\" ignored!", argv[i][1]);
161*5e7646d2SAndroid Build Coastguard Worker 	    break;
162*5e7646d2SAndroid Build Coastguard Worker       }
163*5e7646d2SAndroid Build Coastguard Worker     }
164*5e7646d2SAndroid Build Coastguard Worker     else
165*5e7646d2SAndroid Build Coastguard Worker       syslog(LOG_WARNING, "Unknown command-line option \"%s\" ignored!",
166*5e7646d2SAndroid Build Coastguard Worker              argv[i]);
167*5e7646d2SAndroid Build Coastguard Worker 
168*5e7646d2SAndroid Build Coastguard Worker  /*
169*5e7646d2SAndroid Build Coastguard Worker   * Get the address of the client...
170*5e7646d2SAndroid Build Coastguard Worker   */
171*5e7646d2SAndroid Build Coastguard Worker 
172*5e7646d2SAndroid Build Coastguard Worker   hostlen = sizeof(hostaddr);
173*5e7646d2SAndroid Build Coastguard Worker 
174*5e7646d2SAndroid Build Coastguard Worker   if (getpeername(0, (struct sockaddr *)&hostaddr, &hostlen))
175*5e7646d2SAndroid Build Coastguard Worker   {
176*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_WARNING, "Unable to get client address - %s", strerror(errno));
177*5e7646d2SAndroid Build Coastguard Worker     strlcpy(hostname, "unknown", sizeof(hostname));
178*5e7646d2SAndroid Build Coastguard Worker   }
179*5e7646d2SAndroid Build Coastguard Worker   else
180*5e7646d2SAndroid Build Coastguard Worker   {
181*5e7646d2SAndroid Build Coastguard Worker     httpAddrString(&hostaddr, hostip, sizeof(hostip));
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker     if (hostlookups)
184*5e7646d2SAndroid Build Coastguard Worker       httpAddrLookup(&hostaddr, hostname, sizeof(hostname));
185*5e7646d2SAndroid Build Coastguard Worker     else
186*5e7646d2SAndroid Build Coastguard Worker       strlcpy(hostname, hostip, sizeof(hostname));
187*5e7646d2SAndroid Build Coastguard Worker 
188*5e7646d2SAndroid Build Coastguard Worker #ifdef AF_INET6
189*5e7646d2SAndroid Build Coastguard Worker     if (hostaddr.addr.sa_family == AF_INET6)
190*5e7646d2SAndroid Build Coastguard Worker       hostfamily = "IPv6";
191*5e7646d2SAndroid Build Coastguard Worker     else
192*5e7646d2SAndroid Build Coastguard Worker #endif /* AF_INET6 */
193*5e7646d2SAndroid Build Coastguard Worker     hostfamily = "IPv4";
194*5e7646d2SAndroid Build Coastguard Worker 
195*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_INFO, "Connection from %s (%s %s)", hostname, hostfamily,
196*5e7646d2SAndroid Build Coastguard Worker            hostip);
197*5e7646d2SAndroid Build Coastguard Worker   }
198*5e7646d2SAndroid Build Coastguard Worker 
199*5e7646d2SAndroid Build Coastguard Worker   num_defaults = cupsAddOption("job-originating-host-name", hostname,
200*5e7646d2SAndroid Build Coastguard Worker                                num_defaults, &defaults);
201*5e7646d2SAndroid Build Coastguard Worker 
202*5e7646d2SAndroid Build Coastguard Worker  /*
203*5e7646d2SAndroid Build Coastguard Worker   * RFC1179 specifies that only 1 daemon command can be received for
204*5e7646d2SAndroid Build Coastguard Worker   * every connection.
205*5e7646d2SAndroid Build Coastguard Worker   */
206*5e7646d2SAndroid Build Coastguard Worker 
207*5e7646d2SAndroid Build Coastguard Worker   if (smart_gets(line, sizeof(line), stdin) == NULL)
208*5e7646d2SAndroid Build Coastguard Worker   {
209*5e7646d2SAndroid Build Coastguard Worker    /*
210*5e7646d2SAndroid Build Coastguard Worker     * Unable to get command from client!  Send an error status and return.
211*5e7646d2SAndroid Build Coastguard Worker     */
212*5e7646d2SAndroid Build Coastguard Worker 
213*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "Unable to get command line from client!");
214*5e7646d2SAndroid Build Coastguard Worker     putchar(1);
215*5e7646d2SAndroid Build Coastguard Worker 
216*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
217*5e7646d2SAndroid Build Coastguard Worker     xpc_transaction_end();
218*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
219*5e7646d2SAndroid Build Coastguard Worker 
220*5e7646d2SAndroid Build Coastguard Worker     return (1);
221*5e7646d2SAndroid Build Coastguard Worker   }
222*5e7646d2SAndroid Build Coastguard Worker 
223*5e7646d2SAndroid Build Coastguard Worker  /*
224*5e7646d2SAndroid Build Coastguard Worker   * The first byte is the command byte.  After that will be the queue name,
225*5e7646d2SAndroid Build Coastguard Worker   * resource list, and/or user name.
226*5e7646d2SAndroid Build Coastguard Worker   */
227*5e7646d2SAndroid Build Coastguard Worker 
228*5e7646d2SAndroid Build Coastguard Worker   if ((command = line[0]) == '\0')
229*5e7646d2SAndroid Build Coastguard Worker     dest = line;
230*5e7646d2SAndroid Build Coastguard Worker   else
231*5e7646d2SAndroid Build Coastguard Worker     dest = line + 1;
232*5e7646d2SAndroid Build Coastguard Worker 
233*5e7646d2SAndroid Build Coastguard Worker   if (command == 0x02)
234*5e7646d2SAndroid Build Coastguard Worker     list = NULL;
235*5e7646d2SAndroid Build Coastguard Worker   else
236*5e7646d2SAndroid Build Coastguard Worker   {
237*5e7646d2SAndroid Build Coastguard Worker     for (list = dest; *list && !isspace(*list & 255); list ++);
238*5e7646d2SAndroid Build Coastguard Worker 
239*5e7646d2SAndroid Build Coastguard Worker     while (isspace(*list & 255))
240*5e7646d2SAndroid Build Coastguard Worker       *list++ = '\0';
241*5e7646d2SAndroid Build Coastguard Worker   }
242*5e7646d2SAndroid Build Coastguard Worker 
243*5e7646d2SAndroid Build Coastguard Worker  /*
244*5e7646d2SAndroid Build Coastguard Worker   * Do the command...
245*5e7646d2SAndroid Build Coastguard Worker   */
246*5e7646d2SAndroid Build Coastguard Worker 
247*5e7646d2SAndroid Build Coastguard Worker   switch (command)
248*5e7646d2SAndroid Build Coastguard Worker   {
249*5e7646d2SAndroid Build Coastguard Worker     default : /* Unknown command */
250*5e7646d2SAndroid Build Coastguard Worker         syslog(LOG_ERR, "Unknown LPD command 0x%02X!", command);
251*5e7646d2SAndroid Build Coastguard Worker         syslog(LOG_ERR, "Command line = %s", line + 1);
252*5e7646d2SAndroid Build Coastguard Worker 	putchar(1);
253*5e7646d2SAndroid Build Coastguard Worker 
254*5e7646d2SAndroid Build Coastguard Worker         status = 1;
255*5e7646d2SAndroid Build Coastguard Worker 	break;
256*5e7646d2SAndroid Build Coastguard Worker 
257*5e7646d2SAndroid Build Coastguard Worker     case 0x01 : /* Print any waiting jobs */
258*5e7646d2SAndroid Build Coastguard Worker         syslog(LOG_INFO, "Print waiting jobs (no-op)");
259*5e7646d2SAndroid Build Coastguard Worker 	putchar(0);
260*5e7646d2SAndroid Build Coastguard Worker 
261*5e7646d2SAndroid Build Coastguard Worker         status = 0;
262*5e7646d2SAndroid Build Coastguard Worker 	break;
263*5e7646d2SAndroid Build Coastguard Worker 
264*5e7646d2SAndroid Build Coastguard Worker     case 0x02 : /* Receive a printer job */
265*5e7646d2SAndroid Build Coastguard Worker         syslog(LOG_INFO, "Receive print job for %s", dest);
266*5e7646d2SAndroid Build Coastguard Worker         /* recv_print_job() sends initial status byte */
267*5e7646d2SAndroid Build Coastguard Worker 
268*5e7646d2SAndroid Build Coastguard Worker         status = (char)recv_print_job(dest, num_defaults, defaults);
269*5e7646d2SAndroid Build Coastguard Worker 	break;
270*5e7646d2SAndroid Build Coastguard Worker 
271*5e7646d2SAndroid Build Coastguard Worker     case 0x03 : /* Send queue state (short) */
272*5e7646d2SAndroid Build Coastguard Worker         syslog(LOG_INFO, "Send queue state (short) for %s %s", dest, list);
273*5e7646d2SAndroid Build Coastguard Worker 	/* no status byte for this command */
274*5e7646d2SAndroid Build Coastguard Worker 
275*5e7646d2SAndroid Build Coastguard Worker         status = (char)send_state(dest, list, 0);
276*5e7646d2SAndroid Build Coastguard Worker 	break;
277*5e7646d2SAndroid Build Coastguard Worker 
278*5e7646d2SAndroid Build Coastguard Worker     case 0x04 : /* Send queue state (long) */
279*5e7646d2SAndroid Build Coastguard Worker         syslog(LOG_INFO, "Send queue state (long) for %s %s", dest, list);
280*5e7646d2SAndroid Build Coastguard Worker 	/* no status byte for this command */
281*5e7646d2SAndroid Build Coastguard Worker 
282*5e7646d2SAndroid Build Coastguard Worker         status = (char)send_state(dest, list, 1);
283*5e7646d2SAndroid Build Coastguard Worker 	break;
284*5e7646d2SAndroid Build Coastguard Worker 
285*5e7646d2SAndroid Build Coastguard Worker     case 0x05 : /* Remove jobs */
286*5e7646d2SAndroid Build Coastguard Worker         if (list)
287*5e7646d2SAndroid Build Coastguard Worker 	{
288*5e7646d2SAndroid Build Coastguard Worker 	 /*
289*5e7646d2SAndroid Build Coastguard Worker 	  * Grab the agent and skip to the list of users and/or jobs.
290*5e7646d2SAndroid Build Coastguard Worker 	  */
291*5e7646d2SAndroid Build Coastguard Worker 
292*5e7646d2SAndroid Build Coastguard Worker 	  agent = list;
293*5e7646d2SAndroid Build Coastguard Worker 
294*5e7646d2SAndroid Build Coastguard Worker 	  for (; *list && !isspace(*list & 255); list ++);
295*5e7646d2SAndroid Build Coastguard Worker 	  while (isspace(*list & 255))
296*5e7646d2SAndroid Build Coastguard Worker 	    *list++ = '\0';
297*5e7646d2SAndroid Build Coastguard Worker 
298*5e7646d2SAndroid Build Coastguard Worker 	  syslog(LOG_INFO, "Remove jobs %s on %s by %s", list, dest, agent);
299*5e7646d2SAndroid Build Coastguard Worker 
300*5e7646d2SAndroid Build Coastguard Worker 	  status = (char)remove_jobs(dest, agent, list);
301*5e7646d2SAndroid Build Coastguard Worker         }
302*5e7646d2SAndroid Build Coastguard Worker 	else
303*5e7646d2SAndroid Build Coastguard Worker 	  status = 1;
304*5e7646d2SAndroid Build Coastguard Worker 
305*5e7646d2SAndroid Build Coastguard Worker 	putchar(status);
306*5e7646d2SAndroid Build Coastguard Worker 	break;
307*5e7646d2SAndroid Build Coastguard Worker   }
308*5e7646d2SAndroid Build Coastguard Worker 
309*5e7646d2SAndroid Build Coastguard Worker   syslog(LOG_INFO, "Closing connection");
310*5e7646d2SAndroid Build Coastguard Worker   closelog();
311*5e7646d2SAndroid Build Coastguard Worker 
312*5e7646d2SAndroid Build Coastguard Worker #ifdef __APPLE__
313*5e7646d2SAndroid Build Coastguard Worker   xpc_transaction_end();
314*5e7646d2SAndroid Build Coastguard Worker #endif /* __APPLE__ */
315*5e7646d2SAndroid Build Coastguard Worker 
316*5e7646d2SAndroid Build Coastguard Worker   return (status);
317*5e7646d2SAndroid Build Coastguard Worker }
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker 
320*5e7646d2SAndroid Build Coastguard Worker /*
321*5e7646d2SAndroid Build Coastguard Worker  * 'create_job()' - Create a new print job.
322*5e7646d2SAndroid Build Coastguard Worker  */
323*5e7646d2SAndroid Build Coastguard Worker 
324*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Job ID or -1 on error */
create_job(http_t * http,const char * dest,const char * title,const char * user,int num_options,cups_option_t * options)325*5e7646d2SAndroid Build Coastguard Worker create_job(http_t        *http,		/* I - HTTP connection */
326*5e7646d2SAndroid Build Coastguard Worker            const char    *dest,		/* I - Destination name */
327*5e7646d2SAndroid Build Coastguard Worker 	   const char    *title,	/* I - job-name */
328*5e7646d2SAndroid Build Coastguard Worker 	   const char    *user,		/* I - requesting-user-name */
329*5e7646d2SAndroid Build Coastguard Worker 	   int           num_options,	/* I - Number of options for job */
330*5e7646d2SAndroid Build Coastguard Worker 	   cups_option_t *options)	/* I - Options for job */
331*5e7646d2SAndroid Build Coastguard Worker {
332*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request;		/* IPP request */
333*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*response;		/* IPP response */
334*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attr;		/* IPP attribute */
335*5e7646d2SAndroid Build Coastguard Worker   char		uri[HTTP_MAX_URI];	/* Printer URI */
336*5e7646d2SAndroid Build Coastguard Worker   int		id;			/* Job ID */
337*5e7646d2SAndroid Build Coastguard Worker 
338*5e7646d2SAndroid Build Coastguard Worker 
339*5e7646d2SAndroid Build Coastguard Worker  /*
340*5e7646d2SAndroid Build Coastguard Worker   * Setup the Create-Job request...
341*5e7646d2SAndroid Build Coastguard Worker   */
342*5e7646d2SAndroid Build Coastguard Worker 
343*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(IPP_OP_CREATE_JOB);
344*5e7646d2SAndroid Build Coastguard Worker 
345*5e7646d2SAndroid Build Coastguard Worker   httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
346*5e7646d2SAndroid Build Coastguard Worker                    "localhost", 0, "/printers/%s", dest);
347*5e7646d2SAndroid Build Coastguard Worker 
348*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
349*5e7646d2SAndroid Build Coastguard Worker                NULL, uri);
350*5e7646d2SAndroid Build Coastguard Worker 
351*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
352*5e7646d2SAndroid Build Coastguard Worker                "requesting-user-name", NULL, user);
353*5e7646d2SAndroid Build Coastguard Worker 
354*5e7646d2SAndroid Build Coastguard Worker   if (title[0])
355*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
356*5e7646d2SAndroid Build Coastguard Worker                  NULL, title);
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker   cupsEncodeOptions(request, num_options, options);
359*5e7646d2SAndroid Build Coastguard Worker 
360*5e7646d2SAndroid Build Coastguard Worker  /*
361*5e7646d2SAndroid Build Coastguard Worker   * Do the request...
362*5e7646d2SAndroid Build Coastguard Worker   */
363*5e7646d2SAndroid Build Coastguard Worker 
364*5e7646d2SAndroid Build Coastguard Worker   snprintf(uri, sizeof(uri), "/printers/%s", dest);
365*5e7646d2SAndroid Build Coastguard Worker 
366*5e7646d2SAndroid Build Coastguard Worker   response = cupsDoRequest(http, request, uri);
367*5e7646d2SAndroid Build Coastguard Worker 
368*5e7646d2SAndroid Build Coastguard Worker   if (!response || cupsLastError() > IPP_STATUS_OK_CONFLICTING)
369*5e7646d2SAndroid Build Coastguard Worker   {
370*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "Unable to create job - %s", cupsLastErrorString());
371*5e7646d2SAndroid Build Coastguard Worker 
372*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
373*5e7646d2SAndroid Build Coastguard Worker 
374*5e7646d2SAndroid Build Coastguard Worker     return (-1);
375*5e7646d2SAndroid Build Coastguard Worker   }
376*5e7646d2SAndroid Build Coastguard Worker 
377*5e7646d2SAndroid Build Coastguard Worker  /*
378*5e7646d2SAndroid Build Coastguard Worker   * Get the job-id value from the response and return it...
379*5e7646d2SAndroid Build Coastguard Worker   */
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker   if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
382*5e7646d2SAndroid Build Coastguard Worker   {
383*5e7646d2SAndroid Build Coastguard Worker     id = -1;
384*5e7646d2SAndroid Build Coastguard Worker 
385*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "No job-id attribute found in response from server!");
386*5e7646d2SAndroid Build Coastguard Worker   }
387*5e7646d2SAndroid Build Coastguard Worker   else
388*5e7646d2SAndroid Build Coastguard Worker   {
389*5e7646d2SAndroid Build Coastguard Worker     id = attr->values[0].integer;
390*5e7646d2SAndroid Build Coastguard Worker 
391*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_INFO, "Print file - job ID = %d", id);
392*5e7646d2SAndroid Build Coastguard Worker   }
393*5e7646d2SAndroid Build Coastguard Worker 
394*5e7646d2SAndroid Build Coastguard Worker   ippDelete(response);
395*5e7646d2SAndroid Build Coastguard Worker 
396*5e7646d2SAndroid Build Coastguard Worker   return (id);
397*5e7646d2SAndroid Build Coastguard Worker }
398*5e7646d2SAndroid Build Coastguard Worker 
399*5e7646d2SAndroid Build Coastguard Worker 
400*5e7646d2SAndroid Build Coastguard Worker /*
401*5e7646d2SAndroid Build Coastguard Worker  * 'get_printer()' - Get the named printer and its options.
402*5e7646d2SAndroid Build Coastguard Worker  */
403*5e7646d2SAndroid Build Coastguard Worker 
404*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Number of options or -1 on error */
get_printer(http_t * http,const char * name,char * dest,size_t destsize,cups_option_t ** options,int * accepting,int * shared,ipp_pstate_t * state)405*5e7646d2SAndroid Build Coastguard Worker get_printer(http_t        *http,	/* I - HTTP connection */
406*5e7646d2SAndroid Build Coastguard Worker             const char    *name,	/* I - Printer name from request */
407*5e7646d2SAndroid Build Coastguard Worker 	    char          *dest,	/* I - Destination buffer */
408*5e7646d2SAndroid Build Coastguard Worker             size_t        destsize,	/* I - Size of destination buffer */
409*5e7646d2SAndroid Build Coastguard Worker 	    cups_option_t **options,	/* O - Printer options */
410*5e7646d2SAndroid Build Coastguard Worker 	    int           *accepting,	/* O - printer-is-accepting-jobs value */
411*5e7646d2SAndroid Build Coastguard Worker 	    int           *shared,	/* O - printer-is-shared value */
412*5e7646d2SAndroid Build Coastguard Worker 	    ipp_pstate_t  *state)	/* O - printer-state value */
413*5e7646d2SAndroid Build Coastguard Worker {
414*5e7646d2SAndroid Build Coastguard Worker   int		num_options;		/* Number of options */
415*5e7646d2SAndroid Build Coastguard Worker   cups_file_t	*fp;			/* lpoptions file */
416*5e7646d2SAndroid Build Coastguard Worker   char		line[1024],		/* Line from lpoptions file */
417*5e7646d2SAndroid Build Coastguard Worker 		*value,			/* Pointer to value on line */
418*5e7646d2SAndroid Build Coastguard Worker 		*optptr;		/* Pointer to options on line */
419*5e7646d2SAndroid Build Coastguard Worker   int		linenum;		/* Line number in file */
420*5e7646d2SAndroid Build Coastguard Worker   const char	*cups_serverroot;	/* CUPS_SERVERROOT env var */
421*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request;		/* IPP request */
422*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*response;		/* IPP response */
423*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attr;		/* IPP attribute */
424*5e7646d2SAndroid Build Coastguard Worker   char		uri[HTTP_MAX_URI];	/* Printer URI */
425*5e7646d2SAndroid Build Coastguard Worker   static const char * const requested[] =
426*5e7646d2SAndroid Build Coastguard Worker 		{			/* Requested attributes */
427*5e7646d2SAndroid Build Coastguard Worker 		  "printer-info",
428*5e7646d2SAndroid Build Coastguard Worker 		  "printer-is-accepting-jobs",
429*5e7646d2SAndroid Build Coastguard Worker 		  "printer-is-shared",
430*5e7646d2SAndroid Build Coastguard Worker 		  "printer-name",
431*5e7646d2SAndroid Build Coastguard Worker 		  "printer-state"
432*5e7646d2SAndroid Build Coastguard Worker 		};
433*5e7646d2SAndroid Build Coastguard Worker 
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker  /*
436*5e7646d2SAndroid Build Coastguard Worker   * Initialize everything...
437*5e7646d2SAndroid Build Coastguard Worker   */
438*5e7646d2SAndroid Build Coastguard Worker 
439*5e7646d2SAndroid Build Coastguard Worker   if (accepting)
440*5e7646d2SAndroid Build Coastguard Worker     *accepting = 0;
441*5e7646d2SAndroid Build Coastguard Worker   if (shared)
442*5e7646d2SAndroid Build Coastguard Worker     *shared = 0;
443*5e7646d2SAndroid Build Coastguard Worker   if (state)
444*5e7646d2SAndroid Build Coastguard Worker     *state = IPP_PSTATE_STOPPED;
445*5e7646d2SAndroid Build Coastguard Worker   if (options)
446*5e7646d2SAndroid Build Coastguard Worker     *options = NULL;
447*5e7646d2SAndroid Build Coastguard Worker 
448*5e7646d2SAndroid Build Coastguard Worker  /*
449*5e7646d2SAndroid Build Coastguard Worker   * See if the name is a queue name optionally with an instance name.
450*5e7646d2SAndroid Build Coastguard Worker   */
451*5e7646d2SAndroid Build Coastguard Worker 
452*5e7646d2SAndroid Build Coastguard Worker   strlcpy(dest, name, destsize);
453*5e7646d2SAndroid Build Coastguard Worker   if ((value = strchr(dest, '/')) != NULL)
454*5e7646d2SAndroid Build Coastguard Worker     *value = '\0';
455*5e7646d2SAndroid Build Coastguard Worker 
456*5e7646d2SAndroid Build Coastguard Worker  /*
457*5e7646d2SAndroid Build Coastguard Worker   * Setup the Get-Printer-Attributes request...
458*5e7646d2SAndroid Build Coastguard Worker   */
459*5e7646d2SAndroid Build Coastguard Worker 
460*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
461*5e7646d2SAndroid Build Coastguard Worker 
462*5e7646d2SAndroid Build Coastguard Worker   httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
463*5e7646d2SAndroid Build Coastguard Worker 		   "localhost", 0, "/printers/%s", dest);
464*5e7646d2SAndroid Build Coastguard Worker 
465*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
466*5e7646d2SAndroid Build Coastguard Worker 	       NULL, uri);
467*5e7646d2SAndroid Build Coastguard Worker 
468*5e7646d2SAndroid Build Coastguard Worker   ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
469*5e7646d2SAndroid Build Coastguard Worker 		"requested-attributes",
470*5e7646d2SAndroid Build Coastguard Worker 		(int)(sizeof(requested) / sizeof(requested[0])),
471*5e7646d2SAndroid Build Coastguard Worker 		NULL, requested);
472*5e7646d2SAndroid Build Coastguard Worker 
473*5e7646d2SAndroid Build Coastguard Worker  /*
474*5e7646d2SAndroid Build Coastguard Worker   * Do the request...
475*5e7646d2SAndroid Build Coastguard Worker   */
476*5e7646d2SAndroid Build Coastguard Worker 
477*5e7646d2SAndroid Build Coastguard Worker   response = cupsDoRequest(http, request, "/");
478*5e7646d2SAndroid Build Coastguard Worker 
479*5e7646d2SAndroid Build Coastguard Worker   if (!response || cupsLastError() > IPP_STATUS_OK_CONFLICTING)
480*5e7646d2SAndroid Build Coastguard Worker   {
481*5e7646d2SAndroid Build Coastguard Worker    /*
482*5e7646d2SAndroid Build Coastguard Worker     * If we can't find the printer by name, look up the printer-name
483*5e7646d2SAndroid Build Coastguard Worker     * using the printer-info values...
484*5e7646d2SAndroid Build Coastguard Worker     */
485*5e7646d2SAndroid Build Coastguard Worker 
486*5e7646d2SAndroid Build Coastguard Worker     ipp_attribute_t	*accepting_attr,/* printer-is-accepting-jobs */
487*5e7646d2SAndroid Build Coastguard Worker 			*info_attr,	/* printer-info */
488*5e7646d2SAndroid Build Coastguard Worker 			*name_attr,	/* printer-name */
489*5e7646d2SAndroid Build Coastguard Worker 			*shared_attr,	/* printer-is-shared */
490*5e7646d2SAndroid Build Coastguard Worker 			*state_attr;	/* printer-state */
491*5e7646d2SAndroid Build Coastguard Worker 
492*5e7646d2SAndroid Build Coastguard Worker 
493*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
494*5e7646d2SAndroid Build Coastguard Worker 
495*5e7646d2SAndroid Build Coastguard Worker    /*
496*5e7646d2SAndroid Build Coastguard Worker     * Setup the CUPS-Get-Printers request...
497*5e7646d2SAndroid Build Coastguard Worker     */
498*5e7646d2SAndroid Build Coastguard Worker 
499*5e7646d2SAndroid Build Coastguard Worker     request = ippNewRequest(IPP_OP_CUPS_GET_PRINTERS);
500*5e7646d2SAndroid Build Coastguard Worker 
501*5e7646d2SAndroid Build Coastguard Worker     ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
502*5e7646d2SAndroid Build Coastguard Worker                   "requested-attributes",
503*5e7646d2SAndroid Build Coastguard Worker 		  (int)(sizeof(requested) / sizeof(requested[0])),
504*5e7646d2SAndroid Build Coastguard Worker                   NULL, requested);
505*5e7646d2SAndroid Build Coastguard Worker 
506*5e7646d2SAndroid Build Coastguard Worker    /*
507*5e7646d2SAndroid Build Coastguard Worker     * Do the request...
508*5e7646d2SAndroid Build Coastguard Worker     */
509*5e7646d2SAndroid Build Coastguard Worker 
510*5e7646d2SAndroid Build Coastguard Worker     response = cupsDoRequest(http, request, "/");
511*5e7646d2SAndroid Build Coastguard Worker 
512*5e7646d2SAndroid Build Coastguard Worker     if (!response || cupsLastError() > IPP_STATUS_OK_CONFLICTING)
513*5e7646d2SAndroid Build Coastguard Worker     {
514*5e7646d2SAndroid Build Coastguard Worker       syslog(LOG_ERR, "Unable to get list of printers - %s",
515*5e7646d2SAndroid Build Coastguard Worker              cupsLastErrorString());
516*5e7646d2SAndroid Build Coastguard Worker 
517*5e7646d2SAndroid Build Coastguard Worker       ippDelete(response);
518*5e7646d2SAndroid Build Coastguard Worker 
519*5e7646d2SAndroid Build Coastguard Worker       return (-1);
520*5e7646d2SAndroid Build Coastguard Worker     }
521*5e7646d2SAndroid Build Coastguard Worker 
522*5e7646d2SAndroid Build Coastguard Worker    /*
523*5e7646d2SAndroid Build Coastguard Worker     * Scan the response for printers...
524*5e7646d2SAndroid Build Coastguard Worker     */
525*5e7646d2SAndroid Build Coastguard Worker 
526*5e7646d2SAndroid Build Coastguard Worker     *dest = '\0';
527*5e7646d2SAndroid Build Coastguard Worker     attr  = response->attrs;
528*5e7646d2SAndroid Build Coastguard Worker 
529*5e7646d2SAndroid Build Coastguard Worker     while (attr)
530*5e7646d2SAndroid Build Coastguard Worker     {
531*5e7646d2SAndroid Build Coastguard Worker      /*
532*5e7646d2SAndroid Build Coastguard Worker       * Skip to the next printer...
533*5e7646d2SAndroid Build Coastguard Worker       */
534*5e7646d2SAndroid Build Coastguard Worker 
535*5e7646d2SAndroid Build Coastguard Worker       while (attr && attr->group_tag != IPP_TAG_PRINTER)
536*5e7646d2SAndroid Build Coastguard Worker         attr = attr->next;
537*5e7646d2SAndroid Build Coastguard Worker 
538*5e7646d2SAndroid Build Coastguard Worker       if (!attr)
539*5e7646d2SAndroid Build Coastguard Worker         break;
540*5e7646d2SAndroid Build Coastguard Worker 
541*5e7646d2SAndroid Build Coastguard Worker      /*
542*5e7646d2SAndroid Build Coastguard Worker       * Get all of the attributes for the current printer...
543*5e7646d2SAndroid Build Coastguard Worker       */
544*5e7646d2SAndroid Build Coastguard Worker 
545*5e7646d2SAndroid Build Coastguard Worker       accepting_attr = NULL;
546*5e7646d2SAndroid Build Coastguard Worker       info_attr      = NULL;
547*5e7646d2SAndroid Build Coastguard Worker       name_attr      = NULL;
548*5e7646d2SAndroid Build Coastguard Worker       shared_attr    = NULL;
549*5e7646d2SAndroid Build Coastguard Worker       state_attr     = NULL;
550*5e7646d2SAndroid Build Coastguard Worker 
551*5e7646d2SAndroid Build Coastguard Worker       while (attr && attr->group_tag == IPP_TAG_PRINTER)
552*5e7646d2SAndroid Build Coastguard Worker       {
553*5e7646d2SAndroid Build Coastguard Worker         if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
554*5e7646d2SAndroid Build Coastguard Worker 	    attr->value_tag == IPP_TAG_BOOLEAN)
555*5e7646d2SAndroid Build Coastguard Worker 	  accepting_attr = attr;
556*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(attr->name, "printer-info") &&
557*5e7646d2SAndroid Build Coastguard Worker 	         attr->value_tag == IPP_TAG_TEXT)
558*5e7646d2SAndroid Build Coastguard Worker 	  info_attr = attr;
559*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(attr->name, "printer-name") &&
560*5e7646d2SAndroid Build Coastguard Worker 	         attr->value_tag == IPP_TAG_NAME)
561*5e7646d2SAndroid Build Coastguard Worker 	  name_attr = attr;
562*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(attr->name, "printer-is-shared") &&
563*5e7646d2SAndroid Build Coastguard Worker 	         attr->value_tag == IPP_TAG_BOOLEAN)
564*5e7646d2SAndroid Build Coastguard Worker 	  shared_attr = attr;
565*5e7646d2SAndroid Build Coastguard Worker 	else if (!strcmp(attr->name, "printer-state") &&
566*5e7646d2SAndroid Build Coastguard Worker 	         attr->value_tag == IPP_TAG_ENUM)
567*5e7646d2SAndroid Build Coastguard Worker 	  state_attr = attr;
568*5e7646d2SAndroid Build Coastguard Worker 
569*5e7646d2SAndroid Build Coastguard Worker         attr = attr->next;
570*5e7646d2SAndroid Build Coastguard Worker       }
571*5e7646d2SAndroid Build Coastguard Worker 
572*5e7646d2SAndroid Build Coastguard Worker       if (info_attr && name_attr &&
573*5e7646d2SAndroid Build Coastguard Worker           !_cups_strcasecmp(name, info_attr->values[0].string.text))
574*5e7646d2SAndroid Build Coastguard Worker       {
575*5e7646d2SAndroid Build Coastguard Worker        /*
576*5e7646d2SAndroid Build Coastguard Worker         * Found a match, use this one!
577*5e7646d2SAndroid Build Coastguard Worker 	*/
578*5e7646d2SAndroid Build Coastguard Worker 
579*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(dest, name_attr->values[0].string.text, destsize);
580*5e7646d2SAndroid Build Coastguard Worker 
581*5e7646d2SAndroid Build Coastguard Worker 	if (accepting && accepting_attr)
582*5e7646d2SAndroid Build Coastguard Worker 	  *accepting = accepting_attr->values[0].boolean;
583*5e7646d2SAndroid Build Coastguard Worker 
584*5e7646d2SAndroid Build Coastguard Worker 	if (shared && shared_attr)
585*5e7646d2SAndroid Build Coastguard Worker 	  *shared = shared_attr->values[0].boolean;
586*5e7646d2SAndroid Build Coastguard Worker 
587*5e7646d2SAndroid Build Coastguard Worker 	if (state && state_attr)
588*5e7646d2SAndroid Build Coastguard Worker 	  *state = (ipp_pstate_t)state_attr->values[0].integer;
589*5e7646d2SAndroid Build Coastguard Worker 
590*5e7646d2SAndroid Build Coastguard Worker         break;
591*5e7646d2SAndroid Build Coastguard Worker       }
592*5e7646d2SAndroid Build Coastguard Worker     }
593*5e7646d2SAndroid Build Coastguard Worker 
594*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker     if (!*dest)
597*5e7646d2SAndroid Build Coastguard Worker     {
598*5e7646d2SAndroid Build Coastguard Worker       syslog(LOG_ERR, "Unable to find \"%s\" in list of printers!", name);
599*5e7646d2SAndroid Build Coastguard Worker 
600*5e7646d2SAndroid Build Coastguard Worker       return (-1);
601*5e7646d2SAndroid Build Coastguard Worker     }
602*5e7646d2SAndroid Build Coastguard Worker 
603*5e7646d2SAndroid Build Coastguard Worker     name = dest;
604*5e7646d2SAndroid Build Coastguard Worker   }
605*5e7646d2SAndroid Build Coastguard Worker   else
606*5e7646d2SAndroid Build Coastguard Worker   {
607*5e7646d2SAndroid Build Coastguard Worker    /*
608*5e7646d2SAndroid Build Coastguard Worker     * Get values from the response...
609*5e7646d2SAndroid Build Coastguard Worker     */
610*5e7646d2SAndroid Build Coastguard Worker 
611*5e7646d2SAndroid Build Coastguard Worker     if (accepting)
612*5e7646d2SAndroid Build Coastguard Worker     {
613*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ippFindAttribute(response, "printer-is-accepting-jobs",
614*5e7646d2SAndroid Build Coastguard Worker 				   IPP_TAG_BOOLEAN)) == NULL)
615*5e7646d2SAndroid Build Coastguard Worker 	syslog(LOG_ERR, "No printer-is-accepting-jobs attribute found in "
616*5e7646d2SAndroid Build Coastguard Worker 			"response from server!");
617*5e7646d2SAndroid Build Coastguard Worker       else
618*5e7646d2SAndroid Build Coastguard Worker 	*accepting = attr->values[0].boolean;
619*5e7646d2SAndroid Build Coastguard Worker     }
620*5e7646d2SAndroid Build Coastguard Worker 
621*5e7646d2SAndroid Build Coastguard Worker     if (shared)
622*5e7646d2SAndroid Build Coastguard Worker     {
623*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ippFindAttribute(response, "printer-is-shared",
624*5e7646d2SAndroid Build Coastguard Worker 				   IPP_TAG_BOOLEAN)) == NULL)
625*5e7646d2SAndroid Build Coastguard Worker       {
626*5e7646d2SAndroid Build Coastguard Worker 	syslog(LOG_ERR, "No printer-is-shared attribute found in "
627*5e7646d2SAndroid Build Coastguard Worker 			"response from server!");
628*5e7646d2SAndroid Build Coastguard Worker 	*shared = 1;
629*5e7646d2SAndroid Build Coastguard Worker       }
630*5e7646d2SAndroid Build Coastguard Worker       else
631*5e7646d2SAndroid Build Coastguard Worker 	*shared = attr->values[0].boolean;
632*5e7646d2SAndroid Build Coastguard Worker     }
633*5e7646d2SAndroid Build Coastguard Worker 
634*5e7646d2SAndroid Build Coastguard Worker     if (state)
635*5e7646d2SAndroid Build Coastguard Worker     {
636*5e7646d2SAndroid Build Coastguard Worker       if ((attr = ippFindAttribute(response, "printer-state",
637*5e7646d2SAndroid Build Coastguard Worker 				   IPP_TAG_ENUM)) == NULL)
638*5e7646d2SAndroid Build Coastguard Worker 	syslog(LOG_ERR, "No printer-state attribute found in "
639*5e7646d2SAndroid Build Coastguard Worker 			"response from server!");
640*5e7646d2SAndroid Build Coastguard Worker       else
641*5e7646d2SAndroid Build Coastguard Worker 	*state = (ipp_pstate_t)attr->values[0].integer;
642*5e7646d2SAndroid Build Coastguard Worker     }
643*5e7646d2SAndroid Build Coastguard Worker 
644*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
645*5e7646d2SAndroid Build Coastguard Worker   }
646*5e7646d2SAndroid Build Coastguard Worker 
647*5e7646d2SAndroid Build Coastguard Worker  /*
648*5e7646d2SAndroid Build Coastguard Worker   * Next look for the printer in the lpoptions file...
649*5e7646d2SAndroid Build Coastguard Worker   */
650*5e7646d2SAndroid Build Coastguard Worker 
651*5e7646d2SAndroid Build Coastguard Worker   num_options = 0;
652*5e7646d2SAndroid Build Coastguard Worker 
653*5e7646d2SAndroid Build Coastguard Worker   if (options && shared && accepting)
654*5e7646d2SAndroid Build Coastguard Worker   {
655*5e7646d2SAndroid Build Coastguard Worker     if ((cups_serverroot = getenv("CUPS_SERVERROOT")) == NULL)
656*5e7646d2SAndroid Build Coastguard Worker       cups_serverroot = CUPS_SERVERROOT;
657*5e7646d2SAndroid Build Coastguard Worker 
658*5e7646d2SAndroid Build Coastguard Worker     snprintf(line, sizeof(line), "%s/lpoptions", cups_serverroot);
659*5e7646d2SAndroid Build Coastguard Worker     if ((fp = cupsFileOpen(line, "r")) != NULL)
660*5e7646d2SAndroid Build Coastguard Worker     {
661*5e7646d2SAndroid Build Coastguard Worker       linenum = 0;
662*5e7646d2SAndroid Build Coastguard Worker       while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
663*5e7646d2SAndroid Build Coastguard Worker       {
664*5e7646d2SAndroid Build Coastguard Worker        /*
665*5e7646d2SAndroid Build Coastguard Worker 	* Make sure we have "Dest name options" or "Default name options"...
666*5e7646d2SAndroid Build Coastguard Worker 	*/
667*5e7646d2SAndroid Build Coastguard Worker 
668*5e7646d2SAndroid Build Coastguard Worker 	if ((_cups_strcasecmp(line, "Dest") && _cups_strcasecmp(line, "Default")) || !value)
669*5e7646d2SAndroid Build Coastguard Worker           continue;
670*5e7646d2SAndroid Build Coastguard Worker 
671*5e7646d2SAndroid Build Coastguard Worker        /*
672*5e7646d2SAndroid Build Coastguard Worker 	* Separate destination name from options...
673*5e7646d2SAndroid Build Coastguard Worker 	*/
674*5e7646d2SAndroid Build Coastguard Worker 
675*5e7646d2SAndroid Build Coastguard Worker 	for (optptr = value; *optptr && !isspace(*optptr & 255); optptr ++);
676*5e7646d2SAndroid Build Coastguard Worker 
677*5e7646d2SAndroid Build Coastguard Worker 	while (*optptr == ' ')
678*5e7646d2SAndroid Build Coastguard Worker 	  *optptr++ = '\0';
679*5e7646d2SAndroid Build Coastguard Worker 
680*5e7646d2SAndroid Build Coastguard Worker        /*
681*5e7646d2SAndroid Build Coastguard Worker 	* If this is our destination, parse the options and break out of
682*5e7646d2SAndroid Build Coastguard Worker 	* the loop - we're done!
683*5e7646d2SAndroid Build Coastguard Worker 	*/
684*5e7646d2SAndroid Build Coastguard Worker 
685*5e7646d2SAndroid Build Coastguard Worker 	if (!_cups_strcasecmp(value, name))
686*5e7646d2SAndroid Build Coastguard Worker 	{
687*5e7646d2SAndroid Build Coastguard Worker           num_options = cupsParseOptions(optptr, num_options, options);
688*5e7646d2SAndroid Build Coastguard Worker 	  break;
689*5e7646d2SAndroid Build Coastguard Worker 	}
690*5e7646d2SAndroid Build Coastguard Worker       }
691*5e7646d2SAndroid Build Coastguard Worker 
692*5e7646d2SAndroid Build Coastguard Worker       cupsFileClose(fp);
693*5e7646d2SAndroid Build Coastguard Worker     }
694*5e7646d2SAndroid Build Coastguard Worker   }
695*5e7646d2SAndroid Build Coastguard Worker   else if (options)
696*5e7646d2SAndroid Build Coastguard Worker     *options = NULL;
697*5e7646d2SAndroid Build Coastguard Worker 
698*5e7646d2SAndroid Build Coastguard Worker  /*
699*5e7646d2SAndroid Build Coastguard Worker   * Return the number of options for this destination...
700*5e7646d2SAndroid Build Coastguard Worker   */
701*5e7646d2SAndroid Build Coastguard Worker 
702*5e7646d2SAndroid Build Coastguard Worker   return (num_options);
703*5e7646d2SAndroid Build Coastguard Worker }
704*5e7646d2SAndroid Build Coastguard Worker 
705*5e7646d2SAndroid Build Coastguard Worker 
706*5e7646d2SAndroid Build Coastguard Worker /*
707*5e7646d2SAndroid Build Coastguard Worker  * 'print_file()' - Add a file to the current job.
708*5e7646d2SAndroid Build Coastguard Worker  */
709*5e7646d2SAndroid Build Coastguard Worker 
710*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 0 on success, -1 on failure */
print_file(http_t * http,int id,const char * filename,const char * docname,const char * user,const char * format,int last)711*5e7646d2SAndroid Build Coastguard Worker print_file(http_t     *http,		/* I - HTTP connection */
712*5e7646d2SAndroid Build Coastguard Worker            int        id,		/* I - Job ID */
713*5e7646d2SAndroid Build Coastguard Worker 	   const char *filename,	/* I - File to print */
714*5e7646d2SAndroid Build Coastguard Worker            const char *docname,		/* I - document-name */
715*5e7646d2SAndroid Build Coastguard Worker 	   const char *user,		/* I - requesting-user-name */
716*5e7646d2SAndroid Build Coastguard Worker 	   const char *format,		/* I - document-format */
717*5e7646d2SAndroid Build Coastguard Worker 	   int        last)		/* I - 1 = last file in job */
718*5e7646d2SAndroid Build Coastguard Worker {
719*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request;		/* IPP request */
720*5e7646d2SAndroid Build Coastguard Worker   char		uri[HTTP_MAX_URI];	/* Printer URI */
721*5e7646d2SAndroid Build Coastguard Worker 
722*5e7646d2SAndroid Build Coastguard Worker 
723*5e7646d2SAndroid Build Coastguard Worker  /*
724*5e7646d2SAndroid Build Coastguard Worker   * Setup the Send-Document request...
725*5e7646d2SAndroid Build Coastguard Worker   */
726*5e7646d2SAndroid Build Coastguard Worker 
727*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(IPP_OP_SEND_DOCUMENT);
728*5e7646d2SAndroid Build Coastguard Worker 
729*5e7646d2SAndroid Build Coastguard Worker   snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", id);
730*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
731*5e7646d2SAndroid Build Coastguard Worker 
732*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
733*5e7646d2SAndroid Build Coastguard Worker                "requesting-user-name", NULL, user);
734*5e7646d2SAndroid Build Coastguard Worker 
735*5e7646d2SAndroid Build Coastguard Worker   if (docname)
736*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
737*5e7646d2SAndroid Build Coastguard Worker         	 "document-name", NULL, docname);
738*5e7646d2SAndroid Build Coastguard Worker 
739*5e7646d2SAndroid Build Coastguard Worker   if (format)
740*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
741*5e7646d2SAndroid Build Coastguard Worker                  "document-format", NULL, format);
742*5e7646d2SAndroid Build Coastguard Worker 
743*5e7646d2SAndroid Build Coastguard Worker   ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", (char)last);
744*5e7646d2SAndroid Build Coastguard Worker 
745*5e7646d2SAndroid Build Coastguard Worker  /*
746*5e7646d2SAndroid Build Coastguard Worker   * Do the request...
747*5e7646d2SAndroid Build Coastguard Worker   */
748*5e7646d2SAndroid Build Coastguard Worker 
749*5e7646d2SAndroid Build Coastguard Worker   snprintf(uri, sizeof(uri), "/jobs/%d", id);
750*5e7646d2SAndroid Build Coastguard Worker 
751*5e7646d2SAndroid Build Coastguard Worker   ippDelete(cupsDoFileRequest(http, request, uri, filename));
752*5e7646d2SAndroid Build Coastguard Worker 
753*5e7646d2SAndroid Build Coastguard Worker   if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
754*5e7646d2SAndroid Build Coastguard Worker   {
755*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "Unable to send document - %s", cupsLastErrorString());
756*5e7646d2SAndroid Build Coastguard Worker 
757*5e7646d2SAndroid Build Coastguard Worker     return (-1);
758*5e7646d2SAndroid Build Coastguard Worker   }
759*5e7646d2SAndroid Build Coastguard Worker 
760*5e7646d2SAndroid Build Coastguard Worker   return (0);
761*5e7646d2SAndroid Build Coastguard Worker }
762*5e7646d2SAndroid Build Coastguard Worker 
763*5e7646d2SAndroid Build Coastguard Worker 
764*5e7646d2SAndroid Build Coastguard Worker /*
765*5e7646d2SAndroid Build Coastguard Worker  * 'recv_print_job()' - Receive a print job from the client.
766*5e7646d2SAndroid Build Coastguard Worker  */
767*5e7646d2SAndroid Build Coastguard Worker 
768*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Command status */
recv_print_job(const char * queue,int num_defaults,cups_option_t * defaults)769*5e7646d2SAndroid Build Coastguard Worker recv_print_job(
770*5e7646d2SAndroid Build Coastguard Worker     const char    *queue,		/* I - Printer name */
771*5e7646d2SAndroid Build Coastguard Worker     int           num_defaults,		/* I - Number of default options */
772*5e7646d2SAndroid Build Coastguard Worker     cups_option_t *defaults)		/* I - Default options */
773*5e7646d2SAndroid Build Coastguard Worker {
774*5e7646d2SAndroid Build Coastguard Worker   http_t	*http;			/* HTTP connection */
775*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
776*5e7646d2SAndroid Build Coastguard Worker   int		status;			/* Command status */
777*5e7646d2SAndroid Build Coastguard Worker   int		fd;			/* Temporary file */
778*5e7646d2SAndroid Build Coastguard Worker   FILE		*fp;			/* File pointer */
779*5e7646d2SAndroid Build Coastguard Worker   char		filename[1024];		/* Temporary filename */
780*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes;			/* Bytes received */
781*5e7646d2SAndroid Build Coastguard Worker   size_t	total;			/* Total bytes */
782*5e7646d2SAndroid Build Coastguard Worker   char		line[256],		/* Line from file/stdin */
783*5e7646d2SAndroid Build Coastguard Worker 		command,		/* Command from line */
784*5e7646d2SAndroid Build Coastguard Worker 		*count,			/* Number of bytes */
785*5e7646d2SAndroid Build Coastguard Worker 		*name;			/* Name of file */
786*5e7646d2SAndroid Build Coastguard Worker   const char	*job_sheets;		/* Job sheets */
787*5e7646d2SAndroid Build Coastguard Worker   int		num_data;		/* Number of data files */
788*5e7646d2SAndroid Build Coastguard Worker   char		control[1024],		/* Control filename */
789*5e7646d2SAndroid Build Coastguard Worker 		data[100][256],		/* Data files */
790*5e7646d2SAndroid Build Coastguard Worker 		temp[100][1024];	/* Temporary files */
791*5e7646d2SAndroid Build Coastguard Worker   char		user[1024],		/* User name */
792*5e7646d2SAndroid Build Coastguard Worker 		title[1024],		/* Job title */
793*5e7646d2SAndroid Build Coastguard Worker 		docname[1024],		/* Document name */
794*5e7646d2SAndroid Build Coastguard Worker 		dest[256];		/* Printer/class queue */
795*5e7646d2SAndroid Build Coastguard Worker   int		accepting,		/* printer-is-accepting */
796*5e7646d2SAndroid Build Coastguard Worker 		shared,			/* printer-is-shared */
797*5e7646d2SAndroid Build Coastguard Worker 		num_options;		/* Number of options */
798*5e7646d2SAndroid Build Coastguard Worker   cups_option_t	*options;		/* Options */
799*5e7646d2SAndroid Build Coastguard Worker   int		id;			/* Job ID */
800*5e7646d2SAndroid Build Coastguard Worker   int		docnumber,		/* Current document number */
801*5e7646d2SAndroid Build Coastguard Worker 		doccount;		/* Count of documents */
802*5e7646d2SAndroid Build Coastguard Worker 
803*5e7646d2SAndroid Build Coastguard Worker 
804*5e7646d2SAndroid Build Coastguard Worker  /*
805*5e7646d2SAndroid Build Coastguard Worker   * Connect to the server...
806*5e7646d2SAndroid Build Coastguard Worker   */
807*5e7646d2SAndroid Build Coastguard Worker 
808*5e7646d2SAndroid Build Coastguard Worker   http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL);
809*5e7646d2SAndroid Build Coastguard Worker   if (!http)
810*5e7646d2SAndroid Build Coastguard Worker   {
811*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "Unable to connect to server: %s", strerror(errno));
812*5e7646d2SAndroid Build Coastguard Worker 
813*5e7646d2SAndroid Build Coastguard Worker     putchar(1);
814*5e7646d2SAndroid Build Coastguard Worker 
815*5e7646d2SAndroid Build Coastguard Worker     return (1);
816*5e7646d2SAndroid Build Coastguard Worker   }
817*5e7646d2SAndroid Build Coastguard Worker 
818*5e7646d2SAndroid Build Coastguard Worker  /*
819*5e7646d2SAndroid Build Coastguard Worker   * See if the printer is available...
820*5e7646d2SAndroid Build Coastguard Worker   */
821*5e7646d2SAndroid Build Coastguard Worker 
822*5e7646d2SAndroid Build Coastguard Worker   num_options = get_printer(http, queue, dest, sizeof(dest), &options,
823*5e7646d2SAndroid Build Coastguard Worker                             &accepting, &shared, NULL);
824*5e7646d2SAndroid Build Coastguard Worker 
825*5e7646d2SAndroid Build Coastguard Worker   if (num_options < 0 || !accepting || !shared)
826*5e7646d2SAndroid Build Coastguard Worker   {
827*5e7646d2SAndroid Build Coastguard Worker     if (dest[0])
828*5e7646d2SAndroid Build Coastguard Worker       syslog(LOG_INFO, "Rejecting job because \"%s\" is not %s", dest,
829*5e7646d2SAndroid Build Coastguard Worker              !accepting ? "accepting jobs" : "shared");
830*5e7646d2SAndroid Build Coastguard Worker     else
831*5e7646d2SAndroid Build Coastguard Worker       syslog(LOG_ERR, "Unable to get printer information for \"%s\"", queue);
832*5e7646d2SAndroid Build Coastguard Worker 
833*5e7646d2SAndroid Build Coastguard Worker     httpClose(http);
834*5e7646d2SAndroid Build Coastguard Worker 
835*5e7646d2SAndroid Build Coastguard Worker     putchar(1);
836*5e7646d2SAndroid Build Coastguard Worker 
837*5e7646d2SAndroid Build Coastguard Worker     return (1);
838*5e7646d2SAndroid Build Coastguard Worker   }
839*5e7646d2SAndroid Build Coastguard Worker 
840*5e7646d2SAndroid Build Coastguard Worker   putchar(0);				/* OK so far... */
841*5e7646d2SAndroid Build Coastguard Worker 
842*5e7646d2SAndroid Build Coastguard Worker  /*
843*5e7646d2SAndroid Build Coastguard Worker   * Read the request...
844*5e7646d2SAndroid Build Coastguard Worker   */
845*5e7646d2SAndroid Build Coastguard Worker 
846*5e7646d2SAndroid Build Coastguard Worker   status   = 0;
847*5e7646d2SAndroid Build Coastguard Worker   num_data = 0;
848*5e7646d2SAndroid Build Coastguard Worker   fd       = -1;
849*5e7646d2SAndroid Build Coastguard Worker 
850*5e7646d2SAndroid Build Coastguard Worker   control[0] = '\0';
851*5e7646d2SAndroid Build Coastguard Worker 
852*5e7646d2SAndroid Build Coastguard Worker   while (smart_gets(line, sizeof(line), stdin) != NULL)
853*5e7646d2SAndroid Build Coastguard Worker   {
854*5e7646d2SAndroid Build Coastguard Worker     if (strlen(line) < 2)
855*5e7646d2SAndroid Build Coastguard Worker     {
856*5e7646d2SAndroid Build Coastguard Worker       status = 1;
857*5e7646d2SAndroid Build Coastguard Worker       break;
858*5e7646d2SAndroid Build Coastguard Worker     }
859*5e7646d2SAndroid Build Coastguard Worker 
860*5e7646d2SAndroid Build Coastguard Worker     command = line[0];
861*5e7646d2SAndroid Build Coastguard Worker     count   = line + 1;
862*5e7646d2SAndroid Build Coastguard Worker 
863*5e7646d2SAndroid Build Coastguard Worker     for (name = count + 1; *name && !isspace(*name & 255); name ++);
864*5e7646d2SAndroid Build Coastguard Worker     while (isspace(*name & 255))
865*5e7646d2SAndroid Build Coastguard Worker       *name++ = '\0';
866*5e7646d2SAndroid Build Coastguard Worker 
867*5e7646d2SAndroid Build Coastguard Worker     switch (command)
868*5e7646d2SAndroid Build Coastguard Worker     {
869*5e7646d2SAndroid Build Coastguard Worker       default :
870*5e7646d2SAndroid Build Coastguard Worker       case 0x01 : /* Abort */
871*5e7646d2SAndroid Build Coastguard Worker           status = 1;
872*5e7646d2SAndroid Build Coastguard Worker 	  break;
873*5e7646d2SAndroid Build Coastguard Worker 
874*5e7646d2SAndroid Build Coastguard Worker       case 0x02 : /* Receive control file */
875*5e7646d2SAndroid Build Coastguard Worker           if (strlen(name) < 2)
876*5e7646d2SAndroid Build Coastguard Worker 	  {
877*5e7646d2SAndroid Build Coastguard Worker 	    syslog(LOG_ERR, "Bad control file name \"%s\"", name);
878*5e7646d2SAndroid Build Coastguard Worker 	    putchar(1);
879*5e7646d2SAndroid Build Coastguard Worker 	    status = 1;
880*5e7646d2SAndroid Build Coastguard Worker 	    break;
881*5e7646d2SAndroid Build Coastguard Worker 	  }
882*5e7646d2SAndroid Build Coastguard Worker 
883*5e7646d2SAndroid Build Coastguard Worker           if (control[0])
884*5e7646d2SAndroid Build Coastguard Worker 	  {
885*5e7646d2SAndroid Build Coastguard Worker 	   /*
886*5e7646d2SAndroid Build Coastguard Worker 	    * Append to the existing control file - the LPD spec is
887*5e7646d2SAndroid Build Coastguard Worker 	    * not entirely clear, but at least the OS/2 LPD code sends
888*5e7646d2SAndroid Build Coastguard Worker 	    * multiple control files per connection...
889*5e7646d2SAndroid Build Coastguard Worker 	    */
890*5e7646d2SAndroid Build Coastguard Worker 
891*5e7646d2SAndroid Build Coastguard Worker 	    if ((fd = open(control, O_WRONLY)) < 0)
892*5e7646d2SAndroid Build Coastguard Worker 	    {
893*5e7646d2SAndroid Build Coastguard Worker 	      syslog(LOG_ERR,
894*5e7646d2SAndroid Build Coastguard Worker 	             "Unable to append to temporary control file \"%s\" - %s",
895*5e7646d2SAndroid Build Coastguard Worker         	     control, strerror(errno));
896*5e7646d2SAndroid Build Coastguard Worker 	      putchar(1);
897*5e7646d2SAndroid Build Coastguard Worker 	      status = 1;
898*5e7646d2SAndroid Build Coastguard Worker 	      break;
899*5e7646d2SAndroid Build Coastguard Worker 	    }
900*5e7646d2SAndroid Build Coastguard Worker 
901*5e7646d2SAndroid Build Coastguard Worker 	    lseek(fd, 0, SEEK_END);
902*5e7646d2SAndroid Build Coastguard Worker           }
903*5e7646d2SAndroid Build Coastguard Worker 	  else
904*5e7646d2SAndroid Build Coastguard Worker 	  {
905*5e7646d2SAndroid Build Coastguard Worker 	    if ((fd = cupsTempFd(control, sizeof(control))) < 0)
906*5e7646d2SAndroid Build Coastguard Worker 	    {
907*5e7646d2SAndroid Build Coastguard Worker 	      syslog(LOG_ERR, "Unable to open temporary control file \"%s\" - %s",
908*5e7646d2SAndroid Build Coastguard Worker         	     control, strerror(errno));
909*5e7646d2SAndroid Build Coastguard Worker 	      putchar(1);
910*5e7646d2SAndroid Build Coastguard Worker 	      status = 1;
911*5e7646d2SAndroid Build Coastguard Worker 	      break;
912*5e7646d2SAndroid Build Coastguard Worker 	    }
913*5e7646d2SAndroid Build Coastguard Worker 
914*5e7646d2SAndroid Build Coastguard Worker 	    strlcpy(filename, control, sizeof(filename));
915*5e7646d2SAndroid Build Coastguard Worker 	  }
916*5e7646d2SAndroid Build Coastguard Worker 	  break;
917*5e7646d2SAndroid Build Coastguard Worker 
918*5e7646d2SAndroid Build Coastguard Worker       case 0x03 : /* Receive data file */
919*5e7646d2SAndroid Build Coastguard Worker           if (strlen(name) < 2)
920*5e7646d2SAndroid Build Coastguard Worker 	  {
921*5e7646d2SAndroid Build Coastguard Worker 	    syslog(LOG_ERR, "Bad data file name \"%s\"", name);
922*5e7646d2SAndroid Build Coastguard Worker 	    putchar(1);
923*5e7646d2SAndroid Build Coastguard Worker 	    status = 1;
924*5e7646d2SAndroid Build Coastguard Worker 	    break;
925*5e7646d2SAndroid Build Coastguard Worker 	  }
926*5e7646d2SAndroid Build Coastguard Worker 
927*5e7646d2SAndroid Build Coastguard Worker           if (num_data >= (int)(sizeof(data) / sizeof(data[0])))
928*5e7646d2SAndroid Build Coastguard Worker 	  {
929*5e7646d2SAndroid Build Coastguard Worker 	   /*
930*5e7646d2SAndroid Build Coastguard Worker 	    * Too many data files...
931*5e7646d2SAndroid Build Coastguard Worker 	    */
932*5e7646d2SAndroid Build Coastguard Worker 
933*5e7646d2SAndroid Build Coastguard Worker 	    syslog(LOG_ERR, "Too many data files (%d)", num_data);
934*5e7646d2SAndroid Build Coastguard Worker 	    putchar(1);
935*5e7646d2SAndroid Build Coastguard Worker 	    status = 1;
936*5e7646d2SAndroid Build Coastguard Worker 	    break;
937*5e7646d2SAndroid Build Coastguard Worker 	  }
938*5e7646d2SAndroid Build Coastguard Worker 
939*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(data[num_data], name, sizeof(data[0]));
940*5e7646d2SAndroid Build Coastguard Worker 
941*5e7646d2SAndroid Build Coastguard Worker           if ((fd = cupsTempFd(temp[num_data], sizeof(temp[0]))) < 0)
942*5e7646d2SAndroid Build Coastguard Worker 	  {
943*5e7646d2SAndroid Build Coastguard Worker 	    syslog(LOG_ERR, "Unable to open temporary data file \"%s\" - %s",
944*5e7646d2SAndroid Build Coastguard Worker         	   temp[num_data], strerror(errno));
945*5e7646d2SAndroid Build Coastguard Worker 	    putchar(1);
946*5e7646d2SAndroid Build Coastguard Worker 	    status = 1;
947*5e7646d2SAndroid Build Coastguard Worker 	    break;
948*5e7646d2SAndroid Build Coastguard Worker 	  }
949*5e7646d2SAndroid Build Coastguard Worker 
950*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(filename, temp[num_data], sizeof(filename));
951*5e7646d2SAndroid Build Coastguard Worker 
952*5e7646d2SAndroid Build Coastguard Worker           num_data ++;
953*5e7646d2SAndroid Build Coastguard Worker 	  break;
954*5e7646d2SAndroid Build Coastguard Worker     }
955*5e7646d2SAndroid Build Coastguard Worker 
956*5e7646d2SAndroid Build Coastguard Worker     putchar(status);
957*5e7646d2SAndroid Build Coastguard Worker 
958*5e7646d2SAndroid Build Coastguard Worker     if (status)
959*5e7646d2SAndroid Build Coastguard Worker       break;
960*5e7646d2SAndroid Build Coastguard Worker 
961*5e7646d2SAndroid Build Coastguard Worker    /*
962*5e7646d2SAndroid Build Coastguard Worker     * Copy the data or control file from the client...
963*5e7646d2SAndroid Build Coastguard Worker     */
964*5e7646d2SAndroid Build Coastguard Worker 
965*5e7646d2SAndroid Build Coastguard Worker     for (total = (size_t)strtoll(count, NULL, 10); total > 0; total -= (size_t)bytes)
966*5e7646d2SAndroid Build Coastguard Worker     {
967*5e7646d2SAndroid Build Coastguard Worker       if (total > sizeof(line))
968*5e7646d2SAndroid Build Coastguard Worker         bytes = (ssize_t)sizeof(line);
969*5e7646d2SAndroid Build Coastguard Worker       else
970*5e7646d2SAndroid Build Coastguard Worker         bytes = (ssize_t)total;
971*5e7646d2SAndroid Build Coastguard Worker 
972*5e7646d2SAndroid Build Coastguard Worker       if ((bytes = (ssize_t)fread(line, 1, (size_t)bytes, stdin)) > 0)
973*5e7646d2SAndroid Build Coastguard Worker         bytes = write(fd, line, (size_t)bytes);
974*5e7646d2SAndroid Build Coastguard Worker 
975*5e7646d2SAndroid Build Coastguard Worker       if (bytes < 1)
976*5e7646d2SAndroid Build Coastguard Worker       {
977*5e7646d2SAndroid Build Coastguard Worker 	syslog(LOG_ERR, "Error while reading file - %s",
978*5e7646d2SAndroid Build Coastguard Worker                strerror(errno));
979*5e7646d2SAndroid Build Coastguard Worker         status = 1;
980*5e7646d2SAndroid Build Coastguard Worker 	break;
981*5e7646d2SAndroid Build Coastguard Worker       }
982*5e7646d2SAndroid Build Coastguard Worker     }
983*5e7646d2SAndroid Build Coastguard Worker 
984*5e7646d2SAndroid Build Coastguard Worker    /*
985*5e7646d2SAndroid Build Coastguard Worker     * Read trailing nul...
986*5e7646d2SAndroid Build Coastguard Worker     */
987*5e7646d2SAndroid Build Coastguard Worker 
988*5e7646d2SAndroid Build Coastguard Worker     if (!status)
989*5e7646d2SAndroid Build Coastguard Worker     {
990*5e7646d2SAndroid Build Coastguard Worker       if (fread(line, 1, 1, stdin) < 1)
991*5e7646d2SAndroid Build Coastguard Worker       {
992*5e7646d2SAndroid Build Coastguard Worker         status = 1;
993*5e7646d2SAndroid Build Coastguard Worker 	syslog(LOG_ERR, "Error while reading trailing nul - %s",
994*5e7646d2SAndroid Build Coastguard Worker                strerror(errno));
995*5e7646d2SAndroid Build Coastguard Worker       }
996*5e7646d2SAndroid Build Coastguard Worker       else if (line[0])
997*5e7646d2SAndroid Build Coastguard Worker       {
998*5e7646d2SAndroid Build Coastguard Worker         status = 1;
999*5e7646d2SAndroid Build Coastguard Worker 	syslog(LOG_ERR, "Trailing character after file is not nul (%02X)!",
1000*5e7646d2SAndroid Build Coastguard Worker 	       line[0]);
1001*5e7646d2SAndroid Build Coastguard Worker       }
1002*5e7646d2SAndroid Build Coastguard Worker     }
1003*5e7646d2SAndroid Build Coastguard Worker 
1004*5e7646d2SAndroid Build Coastguard Worker    /*
1005*5e7646d2SAndroid Build Coastguard Worker     * Close the file and send an acknowledgement...
1006*5e7646d2SAndroid Build Coastguard Worker     */
1007*5e7646d2SAndroid Build Coastguard Worker 
1008*5e7646d2SAndroid Build Coastguard Worker     close(fd);
1009*5e7646d2SAndroid Build Coastguard Worker 
1010*5e7646d2SAndroid Build Coastguard Worker     putchar(status);
1011*5e7646d2SAndroid Build Coastguard Worker 
1012*5e7646d2SAndroid Build Coastguard Worker     if (status)
1013*5e7646d2SAndroid Build Coastguard Worker       break;
1014*5e7646d2SAndroid Build Coastguard Worker   }
1015*5e7646d2SAndroid Build Coastguard Worker 
1016*5e7646d2SAndroid Build Coastguard Worker   if (!status)
1017*5e7646d2SAndroid Build Coastguard Worker   {
1018*5e7646d2SAndroid Build Coastguard Worker    /*
1019*5e7646d2SAndroid Build Coastguard Worker     * Process the control file and print stuff...
1020*5e7646d2SAndroid Build Coastguard Worker     */
1021*5e7646d2SAndroid Build Coastguard Worker 
1022*5e7646d2SAndroid Build Coastguard Worker     if ((fp = fopen(control, "rb")) == NULL)
1023*5e7646d2SAndroid Build Coastguard Worker       status = 1;
1024*5e7646d2SAndroid Build Coastguard Worker     else
1025*5e7646d2SAndroid Build Coastguard Worker     {
1026*5e7646d2SAndroid Build Coastguard Worker      /*
1027*5e7646d2SAndroid Build Coastguard Worker       * Copy the default options...
1028*5e7646d2SAndroid Build Coastguard Worker       */
1029*5e7646d2SAndroid Build Coastguard Worker 
1030*5e7646d2SAndroid Build Coastguard Worker       for (i = 0; i < num_defaults; i ++)
1031*5e7646d2SAndroid Build Coastguard Worker 	num_options = cupsAddOption(defaults[i].name,
1032*5e7646d2SAndroid Build Coastguard Worker 		                    defaults[i].value,
1033*5e7646d2SAndroid Build Coastguard Worker 		                    num_options, &options);
1034*5e7646d2SAndroid Build Coastguard Worker 
1035*5e7646d2SAndroid Build Coastguard Worker      /*
1036*5e7646d2SAndroid Build Coastguard Worker       * Grab the job information...
1037*5e7646d2SAndroid Build Coastguard Worker       */
1038*5e7646d2SAndroid Build Coastguard Worker 
1039*5e7646d2SAndroid Build Coastguard Worker       title[0]   = '\0';
1040*5e7646d2SAndroid Build Coastguard Worker       user[0]    = '\0';
1041*5e7646d2SAndroid Build Coastguard Worker       docname[0] = '\0';
1042*5e7646d2SAndroid Build Coastguard Worker       doccount   = 0;
1043*5e7646d2SAndroid Build Coastguard Worker 
1044*5e7646d2SAndroid Build Coastguard Worker       while (smart_gets(line, sizeof(line), fp) != NULL)
1045*5e7646d2SAndroid Build Coastguard Worker       {
1046*5e7646d2SAndroid Build Coastguard Worker        /*
1047*5e7646d2SAndroid Build Coastguard Worker         * Process control lines...
1048*5e7646d2SAndroid Build Coastguard Worker 	*/
1049*5e7646d2SAndroid Build Coastguard Worker 
1050*5e7646d2SAndroid Build Coastguard Worker 	switch (line[0])
1051*5e7646d2SAndroid Build Coastguard Worker 	{
1052*5e7646d2SAndroid Build Coastguard Worker 	  case 'J' : /* Job name */
1053*5e7646d2SAndroid Build Coastguard Worker 	      smart_strlcpy(title, line + 1, sizeof(title));
1054*5e7646d2SAndroid Build Coastguard Worker 	      break;
1055*5e7646d2SAndroid Build Coastguard Worker 
1056*5e7646d2SAndroid Build Coastguard Worker           case 'N' : /* Document name */
1057*5e7646d2SAndroid Build Coastguard Worker               smart_strlcpy(docname, line + 1, sizeof(docname));
1058*5e7646d2SAndroid Build Coastguard Worker               break;
1059*5e7646d2SAndroid Build Coastguard Worker 
1060*5e7646d2SAndroid Build Coastguard Worker 	  case 'P' : /* User identification */
1061*5e7646d2SAndroid Build Coastguard Worker 	      smart_strlcpy(user, line + 1, sizeof(user));
1062*5e7646d2SAndroid Build Coastguard Worker 	      break;
1063*5e7646d2SAndroid Build Coastguard Worker 
1064*5e7646d2SAndroid Build Coastguard Worker 	  case 'L' : /* Print banner page */
1065*5e7646d2SAndroid Build Coastguard Worker 	     /*
1066*5e7646d2SAndroid Build Coastguard Worker 	      * If a banner was requested and it's not overridden by a
1067*5e7646d2SAndroid Build Coastguard Worker 	      * command line option and the destination's default is none
1068*5e7646d2SAndroid Build Coastguard Worker 	      * then add the standard banner...
1069*5e7646d2SAndroid Build Coastguard Worker 	      */
1070*5e7646d2SAndroid Build Coastguard Worker 
1071*5e7646d2SAndroid Build Coastguard Worker 	      if (cupsGetOption("job-sheets", num_defaults, defaults) == NULL &&
1072*5e7646d2SAndroid Build Coastguard Worker         	  ((job_sheets = cupsGetOption("job-sheets", num_options,
1073*5e7646d2SAndroid Build Coastguard Worker 					       options)) == NULL ||
1074*5e7646d2SAndroid Build Coastguard Worker         	   !strcmp(job_sheets, "none,none")))
1075*5e7646d2SAndroid Build Coastguard Worker 	      {
1076*5e7646d2SAndroid Build Coastguard Worker 		num_options = cupsAddOption("job-sheets", "standard",
1077*5e7646d2SAndroid Build Coastguard Worker 		                	    num_options, &options);
1078*5e7646d2SAndroid Build Coastguard Worker 	      }
1079*5e7646d2SAndroid Build Coastguard Worker 	      break;
1080*5e7646d2SAndroid Build Coastguard Worker 
1081*5e7646d2SAndroid Build Coastguard Worker 	  case 'c' : /* Plot CIF file */
1082*5e7646d2SAndroid Build Coastguard Worker 	  case 'd' : /* Print DVI file */
1083*5e7646d2SAndroid Build Coastguard Worker 	  case 'f' : /* Print formatted file */
1084*5e7646d2SAndroid Build Coastguard Worker 	  case 'g' : /* Plot file */
1085*5e7646d2SAndroid Build Coastguard Worker 	  case 'l' : /* Print file leaving control characters (raw) */
1086*5e7646d2SAndroid Build Coastguard Worker 	  case 'n' : /* Print ditroff output file */
1087*5e7646d2SAndroid Build Coastguard Worker 	  case 'o' : /* Print PostScript output file */
1088*5e7646d2SAndroid Build Coastguard Worker 	  case 'p' : /* Print file with 'pr' format (prettyprint) */
1089*5e7646d2SAndroid Build Coastguard Worker 	  case 'r' : /* File to print with FORTRAN carriage control */
1090*5e7646d2SAndroid Build Coastguard Worker 	  case 't' : /* Print troff output file */
1091*5e7646d2SAndroid Build Coastguard Worker 	  case 'v' : /* Print raster file */
1092*5e7646d2SAndroid Build Coastguard Worker 	      doccount ++;
1093*5e7646d2SAndroid Build Coastguard Worker 
1094*5e7646d2SAndroid Build Coastguard Worker 	      if (line[0] == 'l' &&
1095*5e7646d2SAndroid Build Coastguard Worker 	          !cupsGetOption("document-format", num_options, options))
1096*5e7646d2SAndroid Build Coastguard Worker 		num_options = cupsAddOption("raw", "", num_options, &options);
1097*5e7646d2SAndroid Build Coastguard Worker 
1098*5e7646d2SAndroid Build Coastguard Worker               if (line[0] == 'p')
1099*5e7646d2SAndroid Build Coastguard Worker 		num_options = cupsAddOption("prettyprint", "", num_options,
1100*5e7646d2SAndroid Build Coastguard Worker 		                	    &options);
1101*5e7646d2SAndroid Build Coastguard Worker               break;
1102*5e7646d2SAndroid Build Coastguard Worker 	}
1103*5e7646d2SAndroid Build Coastguard Worker 
1104*5e7646d2SAndroid Build Coastguard Worker 	if (status)
1105*5e7646d2SAndroid Build Coastguard Worker 	  break;
1106*5e7646d2SAndroid Build Coastguard Worker       }
1107*5e7646d2SAndroid Build Coastguard Worker 
1108*5e7646d2SAndroid Build Coastguard Worker      /*
1109*5e7646d2SAndroid Build Coastguard Worker       * Check that we have a username...
1110*5e7646d2SAndroid Build Coastguard Worker       */
1111*5e7646d2SAndroid Build Coastguard Worker 
1112*5e7646d2SAndroid Build Coastguard Worker       if (!user[0])
1113*5e7646d2SAndroid Build Coastguard Worker       {
1114*5e7646d2SAndroid Build Coastguard Worker 	syslog(LOG_WARNING, "No username specified by client! "
1115*5e7646d2SAndroid Build Coastguard Worker 		            "Using \"anonymous\"...");
1116*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(user, "anonymous", sizeof(user));
1117*5e7646d2SAndroid Build Coastguard Worker       }
1118*5e7646d2SAndroid Build Coastguard Worker 
1119*5e7646d2SAndroid Build Coastguard Worker      /*
1120*5e7646d2SAndroid Build Coastguard Worker       * Create the job...
1121*5e7646d2SAndroid Build Coastguard Worker       */
1122*5e7646d2SAndroid Build Coastguard Worker 
1123*5e7646d2SAndroid Build Coastguard Worker       if ((id = create_job(http, dest, title, user, num_options, options)) < 0)
1124*5e7646d2SAndroid Build Coastguard Worker         status = 1;
1125*5e7646d2SAndroid Build Coastguard Worker       else
1126*5e7646d2SAndroid Build Coastguard Worker       {
1127*5e7646d2SAndroid Build Coastguard Worker        /*
1128*5e7646d2SAndroid Build Coastguard Worker 	* Then print the job files...
1129*5e7646d2SAndroid Build Coastguard Worker 	*/
1130*5e7646d2SAndroid Build Coastguard Worker 
1131*5e7646d2SAndroid Build Coastguard Worker 	rewind(fp);
1132*5e7646d2SAndroid Build Coastguard Worker 
1133*5e7646d2SAndroid Build Coastguard Worker 	docname[0] = '\0';
1134*5e7646d2SAndroid Build Coastguard Worker 	docnumber  = 0;
1135*5e7646d2SAndroid Build Coastguard Worker 
1136*5e7646d2SAndroid Build Coastguard Worker 	while (smart_gets(line, sizeof(line), fp) != NULL)
1137*5e7646d2SAndroid Build Coastguard Worker 	{
1138*5e7646d2SAndroid Build Coastguard Worker 	 /*
1139*5e7646d2SAndroid Build Coastguard Worker           * Process control lines...
1140*5e7646d2SAndroid Build Coastguard Worker 	  */
1141*5e7646d2SAndroid Build Coastguard Worker 
1142*5e7646d2SAndroid Build Coastguard Worker 	  switch (line[0])
1143*5e7646d2SAndroid Build Coastguard Worker 	  {
1144*5e7646d2SAndroid Build Coastguard Worker 	    case 'N' : /* Document name */
1145*5e7646d2SAndroid Build Coastguard Worker 		smart_strlcpy(docname, line + 1, sizeof(docname));
1146*5e7646d2SAndroid Build Coastguard Worker 		break;
1147*5e7646d2SAndroid Build Coastguard Worker 
1148*5e7646d2SAndroid Build Coastguard Worker 	    case 'c' : /* Plot CIF file */
1149*5e7646d2SAndroid Build Coastguard Worker 	    case 'd' : /* Print DVI file */
1150*5e7646d2SAndroid Build Coastguard Worker 	    case 'f' : /* Print formatted file */
1151*5e7646d2SAndroid Build Coastguard Worker 	    case 'g' : /* Plot file */
1152*5e7646d2SAndroid Build Coastguard Worker 	    case 'l' : /* Print file leaving control characters (raw) */
1153*5e7646d2SAndroid Build Coastguard Worker 	    case 'n' : /* Print ditroff output file */
1154*5e7646d2SAndroid Build Coastguard Worker 	    case 'o' : /* Print PostScript output file */
1155*5e7646d2SAndroid Build Coastguard Worker 	    case 'p' : /* Print file with 'pr' format (prettyprint) */
1156*5e7646d2SAndroid Build Coastguard Worker 	    case 'r' : /* File to print with FORTRAN carriage control */
1157*5e7646d2SAndroid Build Coastguard Worker 	    case 't' : /* Print troff output file */
1158*5e7646d2SAndroid Build Coastguard Worker 	    case 'v' : /* Print raster file */
1159*5e7646d2SAndroid Build Coastguard Worker                /*
1160*5e7646d2SAndroid Build Coastguard Worker 		* Figure out which file we are printing...
1161*5e7646d2SAndroid Build Coastguard Worker 		*/
1162*5e7646d2SAndroid Build Coastguard Worker 
1163*5e7646d2SAndroid Build Coastguard Worker 		for (i = 0; i < num_data; i ++)
1164*5e7646d2SAndroid Build Coastguard Worker 	          if (!strcmp(data[i], line + 1))
1165*5e7646d2SAndroid Build Coastguard Worker 		    break;
1166*5e7646d2SAndroid Build Coastguard Worker 
1167*5e7646d2SAndroid Build Coastguard Worker         	if (i >= num_data)
1168*5e7646d2SAndroid Build Coastguard Worker 		{
1169*5e7646d2SAndroid Build Coastguard Worker 	          status = 1;
1170*5e7646d2SAndroid Build Coastguard Worker 		  break;
1171*5e7646d2SAndroid Build Coastguard Worker 		}
1172*5e7646d2SAndroid Build Coastguard Worker 
1173*5e7646d2SAndroid Build Coastguard Worker                /*
1174*5e7646d2SAndroid Build Coastguard Worker 		* Send the print file...
1175*5e7646d2SAndroid Build Coastguard Worker 		*/
1176*5e7646d2SAndroid Build Coastguard Worker 
1177*5e7646d2SAndroid Build Coastguard Worker         	docnumber ++;
1178*5e7646d2SAndroid Build Coastguard Worker 
1179*5e7646d2SAndroid Build Coastguard Worker         	if (print_file(http, id, temp[i], docname, user,
1180*5e7646d2SAndroid Build Coastguard Worker 		               cupsGetOption("document-format", num_options,
1181*5e7646d2SAndroid Build Coastguard Worker 			                     options),
1182*5e7646d2SAndroid Build Coastguard Worker 	                       docnumber == doccount))
1183*5e7646d2SAndroid Build Coastguard Worker                   status = 1;
1184*5e7646d2SAndroid Build Coastguard Worker 		else
1185*5e7646d2SAndroid Build Coastguard Worker 	          status = 0;
1186*5e7646d2SAndroid Build Coastguard Worker 
1187*5e7646d2SAndroid Build Coastguard Worker 		break;
1188*5e7646d2SAndroid Build Coastguard Worker 	  }
1189*5e7646d2SAndroid Build Coastguard Worker 
1190*5e7646d2SAndroid Build Coastguard Worker 	  if (status)
1191*5e7646d2SAndroid Build Coastguard Worker 	    break;
1192*5e7646d2SAndroid Build Coastguard Worker 	}
1193*5e7646d2SAndroid Build Coastguard Worker       }
1194*5e7646d2SAndroid Build Coastguard Worker 
1195*5e7646d2SAndroid Build Coastguard Worker       fclose(fp);
1196*5e7646d2SAndroid Build Coastguard Worker     }
1197*5e7646d2SAndroid Build Coastguard Worker   }
1198*5e7646d2SAndroid Build Coastguard Worker 
1199*5e7646d2SAndroid Build Coastguard Worker   cupsFreeOptions(num_options, options);
1200*5e7646d2SAndroid Build Coastguard Worker 
1201*5e7646d2SAndroid Build Coastguard Worker   httpClose(http);
1202*5e7646d2SAndroid Build Coastguard Worker 
1203*5e7646d2SAndroid Build Coastguard Worker  /*
1204*5e7646d2SAndroid Build Coastguard Worker   * Clean up all temporary files and return...
1205*5e7646d2SAndroid Build Coastguard Worker   */
1206*5e7646d2SAndroid Build Coastguard Worker 
1207*5e7646d2SAndroid Build Coastguard Worker   unlink(control);
1208*5e7646d2SAndroid Build Coastguard Worker 
1209*5e7646d2SAndroid Build Coastguard Worker   for (i = 0; i < num_data; i ++)
1210*5e7646d2SAndroid Build Coastguard Worker     unlink(temp[i]);
1211*5e7646d2SAndroid Build Coastguard Worker 
1212*5e7646d2SAndroid Build Coastguard Worker   return (status);
1213*5e7646d2SAndroid Build Coastguard Worker }
1214*5e7646d2SAndroid Build Coastguard Worker 
1215*5e7646d2SAndroid Build Coastguard Worker 
1216*5e7646d2SAndroid Build Coastguard Worker /*
1217*5e7646d2SAndroid Build Coastguard Worker  * 'remove_jobs()' - Cancel one or more jobs.
1218*5e7646d2SAndroid Build Coastguard Worker  */
1219*5e7646d2SAndroid Build Coastguard Worker 
1220*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Command status */
remove_jobs(const char * dest,const char * agent,const char * list)1221*5e7646d2SAndroid Build Coastguard Worker remove_jobs(const char *dest,		/* I - Destination */
1222*5e7646d2SAndroid Build Coastguard Worker             const char *agent,		/* I - User agent */
1223*5e7646d2SAndroid Build Coastguard Worker 	    const char *list)		/* I - List of jobs or users */
1224*5e7646d2SAndroid Build Coastguard Worker {
1225*5e7646d2SAndroid Build Coastguard Worker   int		id;			/* Job ID */
1226*5e7646d2SAndroid Build Coastguard Worker   http_t	*http;			/* HTTP server connection */
1227*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request;		/* IPP Request */
1228*5e7646d2SAndroid Build Coastguard Worker   char		uri[HTTP_MAX_URI];	/* Job URI */
1229*5e7646d2SAndroid Build Coastguard Worker 
1230*5e7646d2SAndroid Build Coastguard Worker 
1231*5e7646d2SAndroid Build Coastguard Worker   (void)dest;	/* Suppress compiler warnings... */
1232*5e7646d2SAndroid Build Coastguard Worker 
1233*5e7646d2SAndroid Build Coastguard Worker  /*
1234*5e7646d2SAndroid Build Coastguard Worker   * Try connecting to the local server...
1235*5e7646d2SAndroid Build Coastguard Worker   */
1236*5e7646d2SAndroid Build Coastguard Worker 
1237*5e7646d2SAndroid Build Coastguard Worker   if ((http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL)) == NULL)
1238*5e7646d2SAndroid Build Coastguard Worker   {
1239*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
1240*5e7646d2SAndroid Build Coastguard Worker            strerror(errno));
1241*5e7646d2SAndroid Build Coastguard Worker     return (1);
1242*5e7646d2SAndroid Build Coastguard Worker   }
1243*5e7646d2SAndroid Build Coastguard Worker 
1244*5e7646d2SAndroid Build Coastguard Worker  /*
1245*5e7646d2SAndroid Build Coastguard Worker   * Loop for each job...
1246*5e7646d2SAndroid Build Coastguard Worker   */
1247*5e7646d2SAndroid Build Coastguard Worker 
1248*5e7646d2SAndroid Build Coastguard Worker   while ((id = atoi(list)) > 0)
1249*5e7646d2SAndroid Build Coastguard Worker   {
1250*5e7646d2SAndroid Build Coastguard Worker    /*
1251*5e7646d2SAndroid Build Coastguard Worker     * Skip job ID in list...
1252*5e7646d2SAndroid Build Coastguard Worker     */
1253*5e7646d2SAndroid Build Coastguard Worker 
1254*5e7646d2SAndroid Build Coastguard Worker     while (isdigit(*list & 255))
1255*5e7646d2SAndroid Build Coastguard Worker       list ++;
1256*5e7646d2SAndroid Build Coastguard Worker     while (isspace(*list & 255))
1257*5e7646d2SAndroid Build Coastguard Worker       list ++;
1258*5e7646d2SAndroid Build Coastguard Worker 
1259*5e7646d2SAndroid Build Coastguard Worker    /*
1260*5e7646d2SAndroid Build Coastguard Worker     * Build an IPP_OP_CANCEL_JOB request, which requires the following
1261*5e7646d2SAndroid Build Coastguard Worker     * attributes:
1262*5e7646d2SAndroid Build Coastguard Worker     *
1263*5e7646d2SAndroid Build Coastguard Worker     *    attributes-charset
1264*5e7646d2SAndroid Build Coastguard Worker     *    attributes-natural-language
1265*5e7646d2SAndroid Build Coastguard Worker     *    job-uri
1266*5e7646d2SAndroid Build Coastguard Worker     *    requesting-user-name
1267*5e7646d2SAndroid Build Coastguard Worker     */
1268*5e7646d2SAndroid Build Coastguard Worker 
1269*5e7646d2SAndroid Build Coastguard Worker     request = ippNewRequest(IPP_OP_CANCEL_JOB);
1270*5e7646d2SAndroid Build Coastguard Worker 
1271*5e7646d2SAndroid Build Coastguard Worker     snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", id);
1272*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
1273*5e7646d2SAndroid Build Coastguard Worker 
1274*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1275*5e7646d2SAndroid Build Coastguard Worker                  "requesting-user-name", NULL, agent);
1276*5e7646d2SAndroid Build Coastguard Worker 
1277*5e7646d2SAndroid Build Coastguard Worker    /*
1278*5e7646d2SAndroid Build Coastguard Worker     * Do the request and get back a response...
1279*5e7646d2SAndroid Build Coastguard Worker     */
1280*5e7646d2SAndroid Build Coastguard Worker 
1281*5e7646d2SAndroid Build Coastguard Worker     ippDelete(cupsDoRequest(http, request, "/jobs"));
1282*5e7646d2SAndroid Build Coastguard Worker 
1283*5e7646d2SAndroid Build Coastguard Worker     if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1284*5e7646d2SAndroid Build Coastguard Worker     {
1285*5e7646d2SAndroid Build Coastguard Worker       syslog(LOG_WARNING, "Cancel of job ID %d failed: %s\n", id,
1286*5e7646d2SAndroid Build Coastguard Worker              cupsLastErrorString());
1287*5e7646d2SAndroid Build Coastguard Worker       httpClose(http);
1288*5e7646d2SAndroid Build Coastguard Worker       return (1);
1289*5e7646d2SAndroid Build Coastguard Worker     }
1290*5e7646d2SAndroid Build Coastguard Worker     else
1291*5e7646d2SAndroid Build Coastguard Worker       syslog(LOG_INFO, "Job ID %d canceled", id);
1292*5e7646d2SAndroid Build Coastguard Worker   }
1293*5e7646d2SAndroid Build Coastguard Worker 
1294*5e7646d2SAndroid Build Coastguard Worker   httpClose(http);
1295*5e7646d2SAndroid Build Coastguard Worker 
1296*5e7646d2SAndroid Build Coastguard Worker   return (0);
1297*5e7646d2SAndroid Build Coastguard Worker }
1298*5e7646d2SAndroid Build Coastguard Worker 
1299*5e7646d2SAndroid Build Coastguard Worker 
1300*5e7646d2SAndroid Build Coastguard Worker /*
1301*5e7646d2SAndroid Build Coastguard Worker  * 'send_state()' - Send the queue state.
1302*5e7646d2SAndroid Build Coastguard Worker  */
1303*5e7646d2SAndroid Build Coastguard Worker 
1304*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Command status */
send_state(const char * queue,const char * list,int longstatus)1305*5e7646d2SAndroid Build Coastguard Worker send_state(const char *queue,		/* I - Destination */
1306*5e7646d2SAndroid Build Coastguard Worker            const char *list,		/* I - Job or user */
1307*5e7646d2SAndroid Build Coastguard Worker 	   int        longstatus)	/* I - List of jobs or users */
1308*5e7646d2SAndroid Build Coastguard Worker {
1309*5e7646d2SAndroid Build Coastguard Worker   int		id;			/* Job ID from list */
1310*5e7646d2SAndroid Build Coastguard Worker   http_t	*http;			/* HTTP server connection */
1311*5e7646d2SAndroid Build Coastguard Worker   ipp_t		*request,		/* IPP Request */
1312*5e7646d2SAndroid Build Coastguard Worker 		*response;		/* IPP Response */
1313*5e7646d2SAndroid Build Coastguard Worker   ipp_attribute_t *attr;		/* Current attribute */
1314*5e7646d2SAndroid Build Coastguard Worker   ipp_pstate_t	state;			/* Printer state */
1315*5e7646d2SAndroid Build Coastguard Worker   const char	*jobdest,		/* Pointer into job-printer-uri */
1316*5e7646d2SAndroid Build Coastguard Worker 		*jobuser,		/* Pointer to job-originating-user-name */
1317*5e7646d2SAndroid Build Coastguard Worker 		*jobname;		/* Pointer to job-name */
1318*5e7646d2SAndroid Build Coastguard Worker   ipp_jstate_t	jobstate;		/* job-state */
1319*5e7646d2SAndroid Build Coastguard Worker   int		jobid,			/* job-id */
1320*5e7646d2SAndroid Build Coastguard Worker 		jobsize,		/* job-k-octets */
1321*5e7646d2SAndroid Build Coastguard Worker 		jobcount,		/* Number of jobs */
1322*5e7646d2SAndroid Build Coastguard Worker 		jobcopies,		/* Number of copies */
1323*5e7646d2SAndroid Build Coastguard Worker 		rank;			/* Rank of job */
1324*5e7646d2SAndroid Build Coastguard Worker   char		rankstr[255];		/* Rank string */
1325*5e7646d2SAndroid Build Coastguard Worker   char		namestr[1024];		/* Job name string */
1326*5e7646d2SAndroid Build Coastguard Worker   char		uri[HTTP_MAX_URI];	/* Printer URI */
1327*5e7646d2SAndroid Build Coastguard Worker   char		dest[256];		/* Printer/class queue */
1328*5e7646d2SAndroid Build Coastguard Worker   static const char * const ranks[10] =	/* Ranking strings */
1329*5e7646d2SAndroid Build Coastguard Worker 		{
1330*5e7646d2SAndroid Build Coastguard Worker 		  "th",
1331*5e7646d2SAndroid Build Coastguard Worker 		  "st",
1332*5e7646d2SAndroid Build Coastguard Worker 		  "nd",
1333*5e7646d2SAndroid Build Coastguard Worker 		  "rd",
1334*5e7646d2SAndroid Build Coastguard Worker 		  "th",
1335*5e7646d2SAndroid Build Coastguard Worker 		  "th",
1336*5e7646d2SAndroid Build Coastguard Worker 		  "th",
1337*5e7646d2SAndroid Build Coastguard Worker 		  "th",
1338*5e7646d2SAndroid Build Coastguard Worker 		  "th",
1339*5e7646d2SAndroid Build Coastguard Worker 		  "th"
1340*5e7646d2SAndroid Build Coastguard Worker 		};
1341*5e7646d2SAndroid Build Coastguard Worker   static const char * const requested[] =
1342*5e7646d2SAndroid Build Coastguard Worker 		{			/* Requested attributes */
1343*5e7646d2SAndroid Build Coastguard Worker 		  "job-id",
1344*5e7646d2SAndroid Build Coastguard Worker 		  "job-k-octets",
1345*5e7646d2SAndroid Build Coastguard Worker 		  "job-state",
1346*5e7646d2SAndroid Build Coastguard Worker 		  "job-printer-uri",
1347*5e7646d2SAndroid Build Coastguard Worker 		  "job-originating-user-name",
1348*5e7646d2SAndroid Build Coastguard Worker 		  "job-name",
1349*5e7646d2SAndroid Build Coastguard Worker 		  "copies"
1350*5e7646d2SAndroid Build Coastguard Worker 		};
1351*5e7646d2SAndroid Build Coastguard Worker 
1352*5e7646d2SAndroid Build Coastguard Worker 
1353*5e7646d2SAndroid Build Coastguard Worker  /*
1354*5e7646d2SAndroid Build Coastguard Worker   * Try connecting to the local server...
1355*5e7646d2SAndroid Build Coastguard Worker   */
1356*5e7646d2SAndroid Build Coastguard Worker 
1357*5e7646d2SAndroid Build Coastguard Worker   if ((http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL)) == NULL)
1358*5e7646d2SAndroid Build Coastguard Worker   {
1359*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "Unable to connect to server %s: %s", cupsServer(),
1360*5e7646d2SAndroid Build Coastguard Worker            strerror(errno));
1361*5e7646d2SAndroid Build Coastguard Worker     printf("Unable to connect to server %s: %s", cupsServer(), strerror(errno));
1362*5e7646d2SAndroid Build Coastguard Worker     return (1);
1363*5e7646d2SAndroid Build Coastguard Worker   }
1364*5e7646d2SAndroid Build Coastguard Worker 
1365*5e7646d2SAndroid Build Coastguard Worker  /*
1366*5e7646d2SAndroid Build Coastguard Worker   * Get the actual destination name and printer state...
1367*5e7646d2SAndroid Build Coastguard Worker   */
1368*5e7646d2SAndroid Build Coastguard Worker 
1369*5e7646d2SAndroid Build Coastguard Worker   if (get_printer(http, queue, dest, sizeof(dest), NULL, NULL, NULL, &state))
1370*5e7646d2SAndroid Build Coastguard Worker   {
1371*5e7646d2SAndroid Build Coastguard Worker     syslog(LOG_ERR, "Unable to get printer %s: %s", queue,
1372*5e7646d2SAndroid Build Coastguard Worker            cupsLastErrorString());
1373*5e7646d2SAndroid Build Coastguard Worker     printf("Unable to get printer %s: %s", queue, cupsLastErrorString());
1374*5e7646d2SAndroid Build Coastguard Worker     return (1);
1375*5e7646d2SAndroid Build Coastguard Worker   }
1376*5e7646d2SAndroid Build Coastguard Worker 
1377*5e7646d2SAndroid Build Coastguard Worker  /*
1378*5e7646d2SAndroid Build Coastguard Worker   * Show the queue state...
1379*5e7646d2SAndroid Build Coastguard Worker   */
1380*5e7646d2SAndroid Build Coastguard Worker 
1381*5e7646d2SAndroid Build Coastguard Worker   switch (state)
1382*5e7646d2SAndroid Build Coastguard Worker   {
1383*5e7646d2SAndroid Build Coastguard Worker     case IPP_PSTATE_IDLE :
1384*5e7646d2SAndroid Build Coastguard Worker         printf("%s is ready\n", dest);
1385*5e7646d2SAndroid Build Coastguard Worker 	break;
1386*5e7646d2SAndroid Build Coastguard Worker     case IPP_PSTATE_PROCESSING :
1387*5e7646d2SAndroid Build Coastguard Worker         printf("%s is ready and printing\n", dest);
1388*5e7646d2SAndroid Build Coastguard Worker 	break;
1389*5e7646d2SAndroid Build Coastguard Worker     case IPP_PSTATE_STOPPED :
1390*5e7646d2SAndroid Build Coastguard Worker         printf("%s is not ready\n", dest);
1391*5e7646d2SAndroid Build Coastguard Worker 	break;
1392*5e7646d2SAndroid Build Coastguard Worker   }
1393*5e7646d2SAndroid Build Coastguard Worker 
1394*5e7646d2SAndroid Build Coastguard Worker  /*
1395*5e7646d2SAndroid Build Coastguard Worker   * Build an IPP_OP_GET_JOBS or IPP_OP_GET_JOB_ATTRIBUTES request, which requires
1396*5e7646d2SAndroid Build Coastguard Worker   * the following attributes:
1397*5e7646d2SAndroid Build Coastguard Worker   *
1398*5e7646d2SAndroid Build Coastguard Worker   *    attributes-charset
1399*5e7646d2SAndroid Build Coastguard Worker   *    attributes-natural-language
1400*5e7646d2SAndroid Build Coastguard Worker   *    job-uri or printer-uri
1401*5e7646d2SAndroid Build Coastguard Worker   */
1402*5e7646d2SAndroid Build Coastguard Worker 
1403*5e7646d2SAndroid Build Coastguard Worker   id = atoi(list);
1404*5e7646d2SAndroid Build Coastguard Worker 
1405*5e7646d2SAndroid Build Coastguard Worker   request = ippNewRequest(id ? IPP_OP_GET_JOB_ATTRIBUTES : IPP_OP_GET_JOBS);
1406*5e7646d2SAndroid Build Coastguard Worker 
1407*5e7646d2SAndroid Build Coastguard Worker   httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
1408*5e7646d2SAndroid Build Coastguard Worker                    "localhost", 0, "/printers/%s", dest);
1409*5e7646d2SAndroid Build Coastguard Worker 
1410*5e7646d2SAndroid Build Coastguard Worker   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
1411*5e7646d2SAndroid Build Coastguard Worker                NULL, uri);
1412*5e7646d2SAndroid Build Coastguard Worker 
1413*5e7646d2SAndroid Build Coastguard Worker   if (id)
1414*5e7646d2SAndroid Build Coastguard Worker     ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", id);
1415*5e7646d2SAndroid Build Coastguard Worker   else
1416*5e7646d2SAndroid Build Coastguard Worker   {
1417*5e7646d2SAndroid Build Coastguard Worker     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
1418*5e7646d2SAndroid Build Coastguard Worker                  "requesting-user-name", NULL, list);
1419*5e7646d2SAndroid Build Coastguard Worker     ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
1420*5e7646d2SAndroid Build Coastguard Worker   }
1421*5e7646d2SAndroid Build Coastguard Worker 
1422*5e7646d2SAndroid Build Coastguard Worker   ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
1423*5e7646d2SAndroid Build Coastguard Worker                 "requested-attributes",
1424*5e7646d2SAndroid Build Coastguard Worker 	        sizeof(requested) / sizeof(requested[0]),
1425*5e7646d2SAndroid Build Coastguard Worker 		NULL, requested);
1426*5e7646d2SAndroid Build Coastguard Worker 
1427*5e7646d2SAndroid Build Coastguard Worker  /*
1428*5e7646d2SAndroid Build Coastguard Worker   * Do the request and get back a response...
1429*5e7646d2SAndroid Build Coastguard Worker   */
1430*5e7646d2SAndroid Build Coastguard Worker 
1431*5e7646d2SAndroid Build Coastguard Worker   jobcount = 0;
1432*5e7646d2SAndroid Build Coastguard Worker   response = cupsDoRequest(http, request, "/");
1433*5e7646d2SAndroid Build Coastguard Worker 
1434*5e7646d2SAndroid Build Coastguard Worker   if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
1435*5e7646d2SAndroid Build Coastguard Worker   {
1436*5e7646d2SAndroid Build Coastguard Worker     printf("get-jobs failed: %s\n", cupsLastErrorString());
1437*5e7646d2SAndroid Build Coastguard Worker     ippDelete(response);
1438*5e7646d2SAndroid Build Coastguard Worker     return (1);
1439*5e7646d2SAndroid Build Coastguard Worker   }
1440*5e7646d2SAndroid Build Coastguard Worker 
1441*5e7646d2SAndroid Build Coastguard Worker  /*
1442*5e7646d2SAndroid Build Coastguard Worker   * Loop through the job list and display them...
1443*5e7646d2SAndroid Build Coastguard Worker   */
1444*5e7646d2SAndroid Build Coastguard Worker 
1445*5e7646d2SAndroid Build Coastguard Worker   for (attr = response->attrs, rank = 1; attr; attr = attr->next)
1446*5e7646d2SAndroid Build Coastguard Worker   {
1447*5e7646d2SAndroid Build Coastguard Worker    /*
1448*5e7646d2SAndroid Build Coastguard Worker     * Skip leading attributes until we hit a job...
1449*5e7646d2SAndroid Build Coastguard Worker     */
1450*5e7646d2SAndroid Build Coastguard Worker 
1451*5e7646d2SAndroid Build Coastguard Worker     while (attr && (attr->group_tag != IPP_TAG_JOB || !attr->name))
1452*5e7646d2SAndroid Build Coastguard Worker       attr = attr->next;
1453*5e7646d2SAndroid Build Coastguard Worker 
1454*5e7646d2SAndroid Build Coastguard Worker     if (!attr)
1455*5e7646d2SAndroid Build Coastguard Worker       break;
1456*5e7646d2SAndroid Build Coastguard Worker 
1457*5e7646d2SAndroid Build Coastguard Worker    /*
1458*5e7646d2SAndroid Build Coastguard Worker     * Pull the needed attributes from this job...
1459*5e7646d2SAndroid Build Coastguard Worker     */
1460*5e7646d2SAndroid Build Coastguard Worker 
1461*5e7646d2SAndroid Build Coastguard Worker     jobid     = 0;
1462*5e7646d2SAndroid Build Coastguard Worker     jobsize   = 0;
1463*5e7646d2SAndroid Build Coastguard Worker     jobstate  = IPP_JSTATE_PENDING;
1464*5e7646d2SAndroid Build Coastguard Worker     jobname   = "untitled";
1465*5e7646d2SAndroid Build Coastguard Worker     jobuser   = NULL;
1466*5e7646d2SAndroid Build Coastguard Worker     jobdest   = NULL;
1467*5e7646d2SAndroid Build Coastguard Worker     jobcopies = 1;
1468*5e7646d2SAndroid Build Coastguard Worker 
1469*5e7646d2SAndroid Build Coastguard Worker     while (attr && attr->group_tag == IPP_TAG_JOB)
1470*5e7646d2SAndroid Build Coastguard Worker     {
1471*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(attr->name, "job-id") &&
1472*5e7646d2SAndroid Build Coastguard Worker 	  attr->value_tag == IPP_TAG_INTEGER)
1473*5e7646d2SAndroid Build Coastguard Worker 	jobid = attr->values[0].integer;
1474*5e7646d2SAndroid Build Coastguard Worker 
1475*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(attr->name, "job-k-octets") &&
1476*5e7646d2SAndroid Build Coastguard Worker 	  attr->value_tag == IPP_TAG_INTEGER)
1477*5e7646d2SAndroid Build Coastguard Worker 	jobsize = attr->values[0].integer;
1478*5e7646d2SAndroid Build Coastguard Worker 
1479*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(attr->name, "job-state") &&
1480*5e7646d2SAndroid Build Coastguard Worker 	  attr->value_tag == IPP_TAG_ENUM)
1481*5e7646d2SAndroid Build Coastguard Worker 	jobstate = (ipp_jstate_t)attr->values[0].integer;
1482*5e7646d2SAndroid Build Coastguard Worker 
1483*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(attr->name, "job-printer-uri") &&
1484*5e7646d2SAndroid Build Coastguard Worker 	  attr->value_tag == IPP_TAG_URI)
1485*5e7646d2SAndroid Build Coastguard Worker 	if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
1486*5e7646d2SAndroid Build Coastguard Worker 	  jobdest ++;
1487*5e7646d2SAndroid Build Coastguard Worker 
1488*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(attr->name, "job-originating-user-name") &&
1489*5e7646d2SAndroid Build Coastguard Worker 	  attr->value_tag == IPP_TAG_NAME)
1490*5e7646d2SAndroid Build Coastguard Worker 	jobuser = attr->values[0].string.text;
1491*5e7646d2SAndroid Build Coastguard Worker 
1492*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(attr->name, "job-name") &&
1493*5e7646d2SAndroid Build Coastguard Worker 	  attr->value_tag == IPP_TAG_NAME)
1494*5e7646d2SAndroid Build Coastguard Worker 	jobname = attr->values[0].string.text;
1495*5e7646d2SAndroid Build Coastguard Worker 
1496*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(attr->name, "copies") &&
1497*5e7646d2SAndroid Build Coastguard Worker 	  attr->value_tag == IPP_TAG_INTEGER)
1498*5e7646d2SAndroid Build Coastguard Worker 	jobcopies = attr->values[0].integer;
1499*5e7646d2SAndroid Build Coastguard Worker 
1500*5e7646d2SAndroid Build Coastguard Worker       attr = attr->next;
1501*5e7646d2SAndroid Build Coastguard Worker     }
1502*5e7646d2SAndroid Build Coastguard Worker 
1503*5e7646d2SAndroid Build Coastguard Worker    /*
1504*5e7646d2SAndroid Build Coastguard Worker     * See if we have everything needed...
1505*5e7646d2SAndroid Build Coastguard Worker     */
1506*5e7646d2SAndroid Build Coastguard Worker 
1507*5e7646d2SAndroid Build Coastguard Worker     if (!jobdest || !jobid)
1508*5e7646d2SAndroid Build Coastguard Worker     {
1509*5e7646d2SAndroid Build Coastguard Worker       if (!attr)
1510*5e7646d2SAndroid Build Coastguard Worker 	break;
1511*5e7646d2SAndroid Build Coastguard Worker       else
1512*5e7646d2SAndroid Build Coastguard Worker         continue;
1513*5e7646d2SAndroid Build Coastguard Worker     }
1514*5e7646d2SAndroid Build Coastguard Worker 
1515*5e7646d2SAndroid Build Coastguard Worker     if (!longstatus && jobcount == 0)
1516*5e7646d2SAndroid Build Coastguard Worker       puts("Rank    Owner   Job     File(s)                         Total Size");
1517*5e7646d2SAndroid Build Coastguard Worker 
1518*5e7646d2SAndroid Build Coastguard Worker     jobcount ++;
1519*5e7646d2SAndroid Build Coastguard Worker 
1520*5e7646d2SAndroid Build Coastguard Worker    /*
1521*5e7646d2SAndroid Build Coastguard Worker     * Display the job...
1522*5e7646d2SAndroid Build Coastguard Worker     */
1523*5e7646d2SAndroid Build Coastguard Worker 
1524*5e7646d2SAndroid Build Coastguard Worker     if (jobstate == IPP_JSTATE_PROCESSING)
1525*5e7646d2SAndroid Build Coastguard Worker       strlcpy(rankstr, "active", sizeof(rankstr));
1526*5e7646d2SAndroid Build Coastguard Worker     else
1527*5e7646d2SAndroid Build Coastguard Worker     {
1528*5e7646d2SAndroid Build Coastguard Worker       snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
1529*5e7646d2SAndroid Build Coastguard Worker       rank ++;
1530*5e7646d2SAndroid Build Coastguard Worker     }
1531*5e7646d2SAndroid Build Coastguard Worker 
1532*5e7646d2SAndroid Build Coastguard Worker     if (longstatus)
1533*5e7646d2SAndroid Build Coastguard Worker     {
1534*5e7646d2SAndroid Build Coastguard Worker       puts("");
1535*5e7646d2SAndroid Build Coastguard Worker 
1536*5e7646d2SAndroid Build Coastguard Worker       if (jobcopies > 1)
1537*5e7646d2SAndroid Build Coastguard Worker 	snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
1538*5e7646d2SAndroid Build Coastguard Worker 	         jobname);
1539*5e7646d2SAndroid Build Coastguard Worker       else
1540*5e7646d2SAndroid Build Coastguard Worker 	strlcpy(namestr, jobname, sizeof(namestr));
1541*5e7646d2SAndroid Build Coastguard Worker 
1542*5e7646d2SAndroid Build Coastguard Worker       printf("%s: %-33.33s [job %d localhost]\n", jobuser, rankstr, jobid);
1543*5e7646d2SAndroid Build Coastguard Worker       printf("        %-39.39s %.0f bytes\n", namestr, 1024.0 * jobsize);
1544*5e7646d2SAndroid Build Coastguard Worker     }
1545*5e7646d2SAndroid Build Coastguard Worker     else
1546*5e7646d2SAndroid Build Coastguard Worker       printf("%-7s %-7.7s %-7d %-31.31s %.0f bytes\n", rankstr, jobuser,
1547*5e7646d2SAndroid Build Coastguard Worker 	     jobid, jobname, 1024.0 * jobsize);
1548*5e7646d2SAndroid Build Coastguard Worker 
1549*5e7646d2SAndroid Build Coastguard Worker     if (!attr)
1550*5e7646d2SAndroid Build Coastguard Worker       break;
1551*5e7646d2SAndroid Build Coastguard Worker   }
1552*5e7646d2SAndroid Build Coastguard Worker 
1553*5e7646d2SAndroid Build Coastguard Worker   ippDelete(response);
1554*5e7646d2SAndroid Build Coastguard Worker 
1555*5e7646d2SAndroid Build Coastguard Worker   if (jobcount == 0)
1556*5e7646d2SAndroid Build Coastguard Worker     puts("no entries");
1557*5e7646d2SAndroid Build Coastguard Worker 
1558*5e7646d2SAndroid Build Coastguard Worker   httpClose(http);
1559*5e7646d2SAndroid Build Coastguard Worker 
1560*5e7646d2SAndroid Build Coastguard Worker   return (0);
1561*5e7646d2SAndroid Build Coastguard Worker }
1562*5e7646d2SAndroid Build Coastguard Worker 
1563*5e7646d2SAndroid Build Coastguard Worker 
1564*5e7646d2SAndroid Build Coastguard Worker /*
1565*5e7646d2SAndroid Build Coastguard Worker  * 'smart_gets()' - Get a line of text, removing the trailing CR and/or LF.
1566*5e7646d2SAndroid Build Coastguard Worker  */
1567*5e7646d2SAndroid Build Coastguard Worker 
1568*5e7646d2SAndroid Build Coastguard Worker static char *				/* O - Line read or NULL */
smart_gets(char * s,int len,FILE * fp)1569*5e7646d2SAndroid Build Coastguard Worker smart_gets(char *s,			/* I - Pointer to line buffer */
1570*5e7646d2SAndroid Build Coastguard Worker            int  len,			/* I - Size of line buffer */
1571*5e7646d2SAndroid Build Coastguard Worker 	   FILE *fp)			/* I - File to read from */
1572*5e7646d2SAndroid Build Coastguard Worker {
1573*5e7646d2SAndroid Build Coastguard Worker   char	*ptr,				/* Pointer into line */
1574*5e7646d2SAndroid Build Coastguard Worker 	*end;				/* End of line */
1575*5e7646d2SAndroid Build Coastguard Worker   int	ch;				/* Character from file */
1576*5e7646d2SAndroid Build Coastguard Worker 
1577*5e7646d2SAndroid Build Coastguard Worker 
1578*5e7646d2SAndroid Build Coastguard Worker  /*
1579*5e7646d2SAndroid Build Coastguard Worker   * Read the line; unlike fgets(), we read the entire line but dump
1580*5e7646d2SAndroid Build Coastguard Worker   * characters that go past the end of the buffer.  Also, we accept
1581*5e7646d2SAndroid Build Coastguard Worker   * CR, LF, or CR LF for the line endings to be "safe", although
1582*5e7646d2SAndroid Build Coastguard Worker   * RFC 1179 specifically says "just use LF".
1583*5e7646d2SAndroid Build Coastguard Worker   */
1584*5e7646d2SAndroid Build Coastguard Worker 
1585*5e7646d2SAndroid Build Coastguard Worker   ptr = s;
1586*5e7646d2SAndroid Build Coastguard Worker   end = s + len - 1;
1587*5e7646d2SAndroid Build Coastguard Worker 
1588*5e7646d2SAndroid Build Coastguard Worker   while ((ch = getc(fp)) != EOF)
1589*5e7646d2SAndroid Build Coastguard Worker   {
1590*5e7646d2SAndroid Build Coastguard Worker     if (ch == '\n')
1591*5e7646d2SAndroid Build Coastguard Worker       break;
1592*5e7646d2SAndroid Build Coastguard Worker     else if (ch == '\r')
1593*5e7646d2SAndroid Build Coastguard Worker     {
1594*5e7646d2SAndroid Build Coastguard Worker      /*
1595*5e7646d2SAndroid Build Coastguard Worker       * See if a LF follows...
1596*5e7646d2SAndroid Build Coastguard Worker       */
1597*5e7646d2SAndroid Build Coastguard Worker 
1598*5e7646d2SAndroid Build Coastguard Worker       ch = getc(fp);
1599*5e7646d2SAndroid Build Coastguard Worker 
1600*5e7646d2SAndroid Build Coastguard Worker       if (ch != '\n')
1601*5e7646d2SAndroid Build Coastguard Worker         ungetc(ch, fp);
1602*5e7646d2SAndroid Build Coastguard Worker 
1603*5e7646d2SAndroid Build Coastguard Worker       break;
1604*5e7646d2SAndroid Build Coastguard Worker     }
1605*5e7646d2SAndroid Build Coastguard Worker     else if (ptr < end)
1606*5e7646d2SAndroid Build Coastguard Worker       *ptr++ = (char)ch;
1607*5e7646d2SAndroid Build Coastguard Worker   }
1608*5e7646d2SAndroid Build Coastguard Worker 
1609*5e7646d2SAndroid Build Coastguard Worker   *ptr = '\0';
1610*5e7646d2SAndroid Build Coastguard Worker 
1611*5e7646d2SAndroid Build Coastguard Worker   if (ch == EOF && ptr == s)
1612*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
1613*5e7646d2SAndroid Build Coastguard Worker   else
1614*5e7646d2SAndroid Build Coastguard Worker     return (s);
1615*5e7646d2SAndroid Build Coastguard Worker }
1616*5e7646d2SAndroid Build Coastguard Worker 
1617*5e7646d2SAndroid Build Coastguard Worker 
1618*5e7646d2SAndroid Build Coastguard Worker /*
1619*5e7646d2SAndroid Build Coastguard Worker  * 'smart_strlcpy()' - Copy a string and convert from ISO-8859-1 to UTF-8 as needed.
1620*5e7646d2SAndroid Build Coastguard Worker  */
1621*5e7646d2SAndroid Build Coastguard Worker 
1622*5e7646d2SAndroid Build Coastguard Worker static void
smart_strlcpy(char * dst,const char * src,size_t dstsize)1623*5e7646d2SAndroid Build Coastguard Worker smart_strlcpy(char       *dst,		/* I - Output buffer */
1624*5e7646d2SAndroid Build Coastguard Worker               const char *src,		/* I - Input string */
1625*5e7646d2SAndroid Build Coastguard Worker               size_t     dstsize)	/* I - Size of output buffer */
1626*5e7646d2SAndroid Build Coastguard Worker {
1627*5e7646d2SAndroid Build Coastguard Worker   const unsigned char	*srcptr;	/* Pointer into input string */
1628*5e7646d2SAndroid Build Coastguard Worker   unsigned char		*dstptr,	/* Pointer into output buffer */
1629*5e7646d2SAndroid Build Coastguard Worker 			*dstend;	/* End of output buffer */
1630*5e7646d2SAndroid Build Coastguard Worker   int			saw_8859 = 0;	/* Saw an extended character that was not UTF-8? */
1631*5e7646d2SAndroid Build Coastguard Worker 
1632*5e7646d2SAndroid Build Coastguard Worker 
1633*5e7646d2SAndroid Build Coastguard Worker   for (srcptr = (unsigned char *)src, dstptr = (unsigned char *)dst, dstend = dstptr + dstsize - 1; *srcptr;)
1634*5e7646d2SAndroid Build Coastguard Worker   {
1635*5e7646d2SAndroid Build Coastguard Worker     if (*srcptr < 0x80)
1636*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;		/* ASCII */
1637*5e7646d2SAndroid Build Coastguard Worker     else if (saw_8859)
1638*5e7646d2SAndroid Build Coastguard Worker     {
1639*5e7646d2SAndroid Build Coastguard Worker      /*
1640*5e7646d2SAndroid Build Coastguard Worker       * Map ISO-8859-1 (most likely character set for legacy LPD clients) to
1641*5e7646d2SAndroid Build Coastguard Worker       * UTF-8...
1642*5e7646d2SAndroid Build Coastguard Worker       */
1643*5e7646d2SAndroid Build Coastguard Worker 
1644*5e7646d2SAndroid Build Coastguard Worker       if (dstptr > (dstend - 2))
1645*5e7646d2SAndroid Build Coastguard Worker         break;
1646*5e7646d2SAndroid Build Coastguard Worker 
1647*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = 0xc0 | (*srcptr >> 6);
1648*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = 0x80 | (*srcptr++ & 0x3f);
1649*5e7646d2SAndroid Build Coastguard Worker     }
1650*5e7646d2SAndroid Build Coastguard Worker     else if ((*srcptr & 0xe0) == 0xc0 && (srcptr[1] & 0xc0) == 0x80)
1651*5e7646d2SAndroid Build Coastguard Worker     {
1652*5e7646d2SAndroid Build Coastguard Worker      /*
1653*5e7646d2SAndroid Build Coastguard Worker       * 2-byte UTF-8 sequence...
1654*5e7646d2SAndroid Build Coastguard Worker       */
1655*5e7646d2SAndroid Build Coastguard Worker 
1656*5e7646d2SAndroid Build Coastguard Worker       if (dstptr > (dstend - 2))
1657*5e7646d2SAndroid Build Coastguard Worker         break;
1658*5e7646d2SAndroid Build Coastguard Worker 
1659*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1660*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1661*5e7646d2SAndroid Build Coastguard Worker     }
1662*5e7646d2SAndroid Build Coastguard Worker     else if ((*srcptr & 0xf0) == 0xe0 && (srcptr[1] & 0xc0) == 0x80 && (srcptr[2] & 0xc0) == 0x80)
1663*5e7646d2SAndroid Build Coastguard Worker     {
1664*5e7646d2SAndroid Build Coastguard Worker      /*
1665*5e7646d2SAndroid Build Coastguard Worker       * 3-byte UTF-8 sequence...
1666*5e7646d2SAndroid Build Coastguard Worker       */
1667*5e7646d2SAndroid Build Coastguard Worker 
1668*5e7646d2SAndroid Build Coastguard Worker       if (dstptr > (dstend - 3))
1669*5e7646d2SAndroid Build Coastguard Worker         break;
1670*5e7646d2SAndroid Build Coastguard Worker 
1671*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1672*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1673*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1674*5e7646d2SAndroid Build Coastguard Worker     }
1675*5e7646d2SAndroid Build Coastguard Worker     else if ((*srcptr & 0xf8) == 0xf0 && (srcptr[1] & 0xc0) == 0x80 && (srcptr[2] & 0xc0) == 0x80 && (srcptr[3] & 0xc0) == 0x80)
1676*5e7646d2SAndroid Build Coastguard Worker     {
1677*5e7646d2SAndroid Build Coastguard Worker      /*
1678*5e7646d2SAndroid Build Coastguard Worker       * 4-byte UTF-8 sequence...
1679*5e7646d2SAndroid Build Coastguard Worker       */
1680*5e7646d2SAndroid Build Coastguard Worker 
1681*5e7646d2SAndroid Build Coastguard Worker       if (dstptr > (dstend - 4))
1682*5e7646d2SAndroid Build Coastguard Worker         break;
1683*5e7646d2SAndroid Build Coastguard Worker 
1684*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1685*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1686*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1687*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = *srcptr++;
1688*5e7646d2SAndroid Build Coastguard Worker     }
1689*5e7646d2SAndroid Build Coastguard Worker     else
1690*5e7646d2SAndroid Build Coastguard Worker     {
1691*5e7646d2SAndroid Build Coastguard Worker      /*
1692*5e7646d2SAndroid Build Coastguard Worker       * Bad UTF-8 sequence, this must be an ISO-8859-1 string...
1693*5e7646d2SAndroid Build Coastguard Worker       */
1694*5e7646d2SAndroid Build Coastguard Worker 
1695*5e7646d2SAndroid Build Coastguard Worker       saw_8859 = 1;
1696*5e7646d2SAndroid Build Coastguard Worker 
1697*5e7646d2SAndroid Build Coastguard Worker       if (dstptr > (dstend - 2))
1698*5e7646d2SAndroid Build Coastguard Worker         break;
1699*5e7646d2SAndroid Build Coastguard Worker 
1700*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = 0xc0 | (*srcptr >> 6);
1701*5e7646d2SAndroid Build Coastguard Worker       *dstptr++ = 0x80 | (*srcptr++ & 0x3f);
1702*5e7646d2SAndroid Build Coastguard Worker     }
1703*5e7646d2SAndroid Build Coastguard Worker   }
1704*5e7646d2SAndroid Build Coastguard Worker 
1705*5e7646d2SAndroid Build Coastguard Worker   *dstptr = '\0';
1706*5e7646d2SAndroid Build Coastguard Worker }
1707