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