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