]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/testlpd.c
Import changes from CUPS 1.4svn-r8704.
[thirdparty/cups.git] / scheduler / testlpd.c
1 /*
2 * "$Id: testlpd.c 6789 2007-08-13 19:52:43Z mike $"
3 *
4 * cups-lpd test program for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007 by Apple Inc.
7 * Copyright 2006 by Easy Software Products, all rights reserved.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * Contents:
16 *
17 * main() - Simulate an LPD client.
18 * do_command() - Send the LPD command and wait for a response.
19 * print_job() - Submit a file for printing.
20 * print_waiting() - Print waiting jobs.
21 * remove_job() - Cancel a print job.
22 * status_long() - Show the long printer status.
23 * status_short() - Show the short printer status.
24 * usage() - Show program usage...
25 */
26
27 /*
28 * Include necessary headers...
29 */
30
31 #include <cups/cups.h>
32 #include <cups/string.h>
33 #include <stdlib.h>
34 #include <sys/stat.h>
35 #include <sys/wait.h>
36 #include <errno.h>
37 #include <signal.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40
41
42 /*
43 * Local functions...
44 */
45
46 static int do_command(int outfd, int infd, const char *command);
47 static int print_job(int outfd, int infd, char *dest, char **args);
48 static int print_waiting(int outfd, int infd, char *dest);
49 static int remove_job(int outfd, int infd, char *dest, char **args);
50 static int status_long(int outfd, int infd, char *dest, char **args);
51 static int status_short(int outfd, int infd, char *dest, char **args);
52 static void usage(void);
53
54
55 /*
56 * 'main()' - Simulate an LPD client.
57 */
58
59 int /* O - Exit status */
60 main(int argc, /* I - Number of command-line arguments */
61 char *argv[]) /* I - Command-line arguments */
62 {
63 int i; /* Looping var */
64 int status; /* Test status */
65 char *op, /* Operation to test */
66 **opargs, /* Remaining arguments */
67 *dest; /* Destination */
68 int cupslpd_argc; /* Argument count for cups-lpd */
69 char *cupslpd_argv[1000]; /* Arguments for cups-lpd */
70 int cupslpd_stdin[2], /* Standard input for cups-lpd */
71 cupslpd_stdout[2], /* Standard output for cups-lpd */
72 cupslpd_pid, /* Process ID for cups-lpd */
73 cupslpd_status; /* Status of cups-lpd process */
74
75
76 /*
77 * Collect command-line arguments...
78 */
79
80 op = NULL;
81 opargs = NULL;
82 dest = NULL;
83 cupslpd_argc = 1;
84 cupslpd_argv[0] = (char *)"cups-lpd";
85
86 for (i = 1; i < argc; i ++)
87 if (!strncmp(argv[i], "-o", 2))
88 {
89 cupslpd_argv[cupslpd_argc++] = argv[i];
90
91 if (!argv[i][2])
92 {
93 i ++;
94
95 if (i >= argc)
96 usage();
97
98 cupslpd_argv[cupslpd_argc++] = argv[i];
99 }
100 }
101 else if (argv[i][0] == '-')
102 usage();
103 else if (!op)
104 op = argv[i];
105 else if (!dest)
106 dest = argv[i];
107 else
108 {
109 opargs = argv + i;
110 break;
111 }
112
113 if (!op ||
114 (!strcmp(op, "print-job") && (!dest || !opargs)) ||
115 (!strcmp(op, "remove-job") && (!dest || !opargs)) ||
116 (strcmp(op, "print-job") && strcmp(op, "print-waiting") &&
117 strcmp(op, "remove-job") && strcmp(op, "status-long") &&
118 strcmp(op, "status-short")))
119 {
120 printf("op=\"%s\", dest=\"%s\", opargs=%p\n", op, dest, opargs);
121 usage();
122 }
123
124 /*
125 * Run the cups-lpd program using pipes...
126 */
127
128 cupslpd_argv[cupslpd_argc] = NULL;
129
130 pipe(cupslpd_stdin);
131 pipe(cupslpd_stdout);
132
133 if ((cupslpd_pid = fork()) < 0)
134 {
135 /*
136 * Error!
137 */
138
139 perror("testlpd: Unable to fork");
140 return (1);
141 }
142 else if (cupslpd_pid == 0)
143 {
144 /*
145 * Child goes here...
146 */
147
148 dup2(cupslpd_stdin[0], 0);
149 close(cupslpd_stdin[0]);
150 close(cupslpd_stdin[1]);
151
152 dup2(cupslpd_stdout[1], 1);
153 close(cupslpd_stdout[0]);
154 close(cupslpd_stdout[1]);
155
156 execv("./cups-lpd", cupslpd_argv);
157
158 perror("testlpd: Unable to exec ./cups-lpd");
159 exit(errno);
160 }
161 else
162 {
163 close(cupslpd_stdin[0]);
164 close(cupslpd_stdout[1]);
165 }
166
167 /*
168 * Do the operation test...
169 */
170
171 if (!strcmp(op, "print-job"))
172 status = print_job(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
173 else if (!strcmp(op, "print-waiting"))
174 status = print_waiting(cupslpd_stdin[1], cupslpd_stdout[0], dest);
175 else if (!strcmp(op, "remove-job"))
176 status = remove_job(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
177 else if (!strcmp(op, "status-long"))
178 status = status_long(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
179 else if (!strcmp(op, "status-short"))
180 status = status_short(cupslpd_stdin[1], cupslpd_stdout[0], dest, opargs);
181 else
182 {
183 printf("Unknown operation \"%s\"!\n", op);
184 status = 1;
185 }
186
187 /*
188 * Kill the test program...
189 */
190
191 close(cupslpd_stdin[1]);
192 close(cupslpd_stdout[0]);
193
194 while (wait(&cupslpd_status) != cupslpd_pid);
195
196 printf("cups-lpd exit status was %d...\n", cupslpd_status);
197
198 /*
199 * Return the test status...
200 */
201
202 return (status);
203 }
204
205
206 /*
207 * 'do_command()' - Send the LPD command and wait for a response.
208 */
209
210 static int /* O - Status from cups-lpd */
211 do_command(int outfd, /* I - Command file descriptor */
212 int infd, /* I - Response file descriptor */
213 const char *command) /* I - Command line to send */
214 {
215 int len; /* Length of command line */
216 char status; /* Status byte */
217
218
219 printf("COMMAND: %02X %s", command[0], command + 1);
220
221 len = strlen(command);
222
223 if (write(outfd, command, len) < len)
224 {
225 puts(" Write failed!");
226 return (-1);
227 }
228
229 if (read(infd, &status, 1) < 1)
230 puts("STATUS: ERROR");
231 else
232 printf("STATUS: %d\n", status);
233
234 return (status);
235 }
236
237
238 /*
239 * 'print_job()' - Submit a file for printing.
240 */
241
242 static int /* O - Status from cups-lpd */
243 print_job(int outfd, /* I - Command file descriptor */
244 int infd, /* I - Response file descriptor */
245 char *dest, /* I - Destination */
246 char **args) /* I - Arguments */
247 {
248 int fd; /* Print file descriptor */
249 char command[1024], /* Command buffer */
250 control[1024], /* Control file */
251 buffer[8192]; /* Print buffer */
252 int status; /* Status of command */
253 struct stat fileinfo; /* File information */
254 char *jobname; /* Job name */
255 int sequence; /* Sequence number */
256 int bytes; /* Bytes read/written */
257
258
259 /*
260 * Check the print file...
261 */
262
263 if (stat(args[0], &fileinfo))
264 {
265 perror(args[0]);
266 return (-1);
267 }
268
269 if ((fd = open(args[0], O_RDONLY)) < 0)
270 {
271 perror(args[0]);
272 return (-1);
273 }
274
275 /*
276 * Send the "receive print job" command...
277 */
278
279 snprintf(command, sizeof(command), "\002%s\n", dest);
280 if ((status = do_command(outfd, infd, command)) != 0)
281 {
282 close(fd);
283 return (status);
284 }
285
286 /*
287 * Format a control file string that will be used to submit the job...
288 */
289
290 if ((jobname = strrchr(args[0], '/')) != NULL)
291 jobname ++;
292 else
293 jobname = args[0];
294
295 sequence = (int)getpid() % 1000;
296
297 snprintf(control, sizeof(control),
298 "Hlocalhost\n"
299 "P%s\n"
300 "J%s\n"
301 "ldfA%03dlocalhost\n"
302 "UdfA%03dlocalhost\n"
303 "N%s\n",
304 cupsUser(), jobname, sequence, sequence, jobname);
305
306 /*
307 * Send the control file...
308 */
309
310 bytes = strlen(control);
311
312 snprintf(command, sizeof(command), "\002%d cfA%03dlocalhost\n",
313 bytes, sequence);
314
315 if ((status = do_command(outfd, infd, command)) != 0)
316 {
317 close(fd);
318 return (status);
319 }
320
321 bytes ++;
322
323 if (write(outfd, control, bytes) < bytes)
324 {
325 printf("CONTROL: Unable to write %d bytes!\n", bytes);
326 close(fd);
327 return (-1);
328 }
329
330 printf("CONTROL: Wrote %d bytes.\n", bytes);
331
332 if (read(infd, command, 1) < 1)
333 {
334 puts("STATUS: ERROR");
335 close(fd);
336 return (-1);
337 }
338 else
339 {
340 status = command[0];
341
342 printf("STATUS: %d\n", status);
343 }
344
345 /*
346 * Send the data file...
347 */
348
349 snprintf(command, sizeof(command), "\003%d dfA%03dlocalhost\n",
350 (int)fileinfo.st_size, sequence);
351
352 if ((status = do_command(outfd, infd, command)) != 0)
353 {
354 close(fd);
355 return (status);
356 }
357
358 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
359 {
360 if (write(outfd, buffer, bytes) < bytes)
361 {
362 printf("DATA: Unable to write %d bytes!\n", bytes);
363 close(fd);
364 return (-1);
365 }
366 }
367
368 write(outfd, "", 1);
369
370 close(fd);
371
372 printf("DATA: Wrote %d bytes.\n", (int)fileinfo.st_size);
373
374 if (read(infd, command, 1) < 1)
375 {
376 puts("STATUS: ERROR");
377 close(fd);
378 return (-1);
379 }
380 else
381 {
382 status = command[0];
383
384 printf("STATUS: %d\n", status);
385 }
386
387 return (status);
388 }
389
390
391 /*
392 * 'print_waiting()' - Print waiting jobs.
393 */
394
395 static int /* O - Status from cups-lpd */
396 print_waiting(int outfd, /* I - Command file descriptor */
397 int infd, /* I - Response file descriptor */
398 char *dest) /* I - Destination */
399 {
400 char command[1024]; /* Command buffer */
401
402
403 /*
404 * Send the "print waiting jobs" command...
405 */
406
407 snprintf(command, sizeof(command), "\001%s\n", dest);
408
409 return (do_command(outfd, infd, command));
410 }
411
412
413 /*
414 * 'remove_job()' - Cancel a print job.
415 */
416
417 static int /* O - Status from cups-lpd */
418 remove_job(int outfd, /* I - Command file descriptor */
419 int infd, /* I - Response file descriptor */
420 char *dest, /* I - Destination */
421 char **args) /* I - Arguments */
422 {
423 int i; /* Looping var */
424 char command[1024]; /* Command buffer */
425
426 /*
427 * Send the "remove jobs" command...
428 */
429
430 snprintf(command, sizeof(command), "\005%s", dest);
431
432 for (i = 0; args[i]; i ++)
433 {
434 strlcat(command, " ", sizeof(command));
435 strlcat(command, args[i], sizeof(command));
436 }
437
438 strlcat(command, "\n", sizeof(command));
439
440 return (do_command(outfd, infd, command));
441 }
442
443
444 /*
445 * 'status_long()' - Show the long printer status.
446 */
447
448 static int /* O - Status from cups-lpd */
449 status_long(int outfd, /* I - Command file descriptor */
450 int infd, /* I - Response file descriptor */
451 char *dest, /* I - Destination */
452 char **args) /* I - Arguments */
453 {
454 char command[1024], /* Command buffer */
455 buffer[8192]; /* Status buffer */
456 int bytes; /* Bytes read/written */
457
458
459 /*
460 * Send the "send short status" command...
461 */
462
463 if (args)
464 snprintf(command, sizeof(command), "\004%s %s\n", dest, args[0]);
465 else
466 snprintf(command, sizeof(command), "\004%s\n", dest);
467
468 bytes = strlen(command);
469
470 if (write(outfd, command, bytes) < bytes)
471 return (-1);
472
473 /*
474 * Read the status back...
475 */
476
477 while ((bytes = read(infd, buffer, sizeof(buffer))) > 0)
478 {
479 fwrite(buffer, 1, bytes, stdout);
480 fflush(stdout);
481 }
482
483 return (0);
484 }
485
486
487 /*
488 * 'status_short()' - Show the short printer status.
489 */
490
491 static int /* O - Status from cups-lpd */
492 status_short(int outfd, /* I - Command file descriptor */
493 int infd, /* I - Response file descriptor */
494 char *dest, /* I - Destination */
495 char **args) /* I - Arguments */
496 {
497 char command[1024], /* Command buffer */
498 buffer[8192]; /* Status buffer */
499 int bytes; /* Bytes read/written */
500
501
502 /*
503 * Send the "send short status" command...
504 */
505
506 if (args)
507 snprintf(command, sizeof(command), "\003%s %s\n", dest, args[0]);
508 else
509 snprintf(command, sizeof(command), "\003%s\n", dest);
510
511 bytes = strlen(command);
512
513 if (write(outfd, command, bytes) < bytes)
514 return (-1);
515
516 /*
517 * Read the status back...
518 */
519
520 while ((bytes = read(infd, buffer, sizeof(buffer))) > 0)
521 {
522 fwrite(buffer, 1, bytes, stdout);
523 fflush(stdout);
524 }
525
526 return (0);
527 }
528
529
530 /*
531 * 'usage()' - Show program usage...
532 */
533
534 static void
535 usage(void)
536 {
537 puts("Usage: testlpd [options] print-job printer filename [... filename]");
538 puts(" testlpd [options] print-waiting [printer or user]");
539 puts(" testlpd [options] remove-job printer [user [job-id]]");
540 puts(" testlpd [options] status-long [printer or user]");
541 puts(" testlpd [options] status-short [printer or user]");
542 puts("");
543 puts("Options:");
544 puts(" -o name=value");
545
546 exit(0);
547 }
548
549
550 /*
551 * End of "$Id: testlpd.c 6789 2007-08-13 19:52:43Z mike $".
552 */