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