]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/testbackend.c
Fix lpadmin error reporting for IPP Everywhere printers (Issue #5370)
[thirdparty/cups.git] / backend / testbackend.c
CommitLineData
568fa3fa 1/*
7e86f2f6 2 * Backend test program for CUPS.
568fa3fa 3 *
53f8d64f
MS
4 * Copyright © 2007-2014 by Apple Inc.
5 * Copyright © 1997-2005 by Easy Software Products, all rights reserved.
568fa3fa 6 *
53f8d64f
MS
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more
8 * information.
568fa3fa
MS
9 */
10
11/*
12 * Include necessary headers.
13 */
14
71e16022 15#include <cups/string-private.h>
568fa3fa
MS
16#include <cups/cups.h>
17#include <cups/sidechannel.h>
18#include <unistd.h>
19#include <fcntl.h>
568fa3fa 20#include <sys/wait.h>
97c9a8d7
MS
21#include <signal.h>
22
23
24/*
25 * Local globals...
26 */
27
28static int job_canceled = 0;
568fa3fa
MS
29
30
31/*
32 * Local functions...
33 */
34
97c9a8d7 35static void sigterm_handler(int sig);
a32af27c 36static void usage(void) _CUPS_NORETURN;
b9faaae1
MS
37static void walk_cb(const char *oid, const char *data, int datalen,
38 void *context);
568fa3fa
MS
39
40
41/*
42 * 'main()' - Run the named backend.
43 *
44 * Usage:
45 *
dcb445bc 46 * testbackend [-s] [-t] device-uri job-id user title copies options [file]
568fa3fa
MS
47 */
48
49int /* O - Exit status */
50main(int argc, /* I - Number of command-line args */
51 char *argv[]) /* I - Command-line arguments */
52{
53 int first_arg, /* First argument for backend */
97c9a8d7 54 do_cancel = 0, /* Simulate a cancel-job via SIGTERM */
e07d4801
MS
55 do_ps = 0, /* Do PostScript query+test? */
56 do_pcl = 0, /* Do PCL query+test? */
568fa3fa 57 do_side_tests = 0, /* Test side-channel ops? */
b9faaae1
MS
58 do_trickle = 0, /* Trickle data to backend */
59 do_walk = 0, /* Do OID lookup (0) or walking (1) */
60 show_log = 0; /* Show log messages from backends? */
61 const char *oid = ".1.3.6.1.2.1.43.10.2.1.4.1.1";
62 /* OID to lookup or walk */
568fa3fa 63 char scheme[255], /* Scheme in URI == backend */
dcb445bc
MS
64 backend[1024], /* Backend path */
65 libpath[1024], /* Path for libcups */
66 *ptr; /* Pointer into path */
568fa3fa 67 const char *serverbin; /* CUPS_SERVERBIN environment variable */
97c9a8d7
MS
68 int fd, /* Temporary file descriptor */
69 back_fds[2], /* Back-channel pipe */
568fa3fa
MS
70 side_fds[2], /* Side-channel socket */
71 data_fds[2], /* Data pipe */
97c9a8d7
MS
72 back_pid = -1, /* Backend process ID */
73 data_pid = -1, /* Trickle process ID */
568fa3fa
MS
74 pid, /* Process ID */
75 status; /* Exit status */
76
77
dcb445bc
MS
78 /*
79 * Get the current directory and point the run-time linker at the "cups"
80 * subdirectory...
81 */
82
83 if (getcwd(libpath, sizeof(libpath)) &&
84 (ptr = strrchr(libpath, '/')) != NULL && !strcmp(ptr, "/backend"))
85 {
7e86f2f6 86 strlcpy(ptr, "/cups", sizeof(libpath) - (size_t)(ptr - libpath));
3e7fe0ca
MS
87 if (!access(libpath, 0))
88 {
dcb445bc 89#ifdef __APPLE__
3e7fe0ca 90 fprintf(stderr, "Setting DYLD_LIBRARY_PATH to \"%s\".\n", libpath);
dcb445bc
MS
91 setenv("DYLD_LIBRARY_PATH", libpath, 1);
92#else
3e7fe0ca 93 fprintf(stderr, "Setting LD_LIBRARY_PATH to \"%s\".\n", libpath);
dcb445bc
MS
94 setenv("LD_LIBRARY_PATH", libpath, 1);
95#endif /* __APPLE__ */
3e7fe0ca
MS
96 }
97 else
98 perror(libpath);
dcb445bc
MS
99 }
100
568fa3fa
MS
101 /*
102 * See if we have side-channel tests to do...
103 */
104
105 for (first_arg = 1;
106 argv[first_arg] && argv[first_arg][0] == '-';
107 first_arg ++)
b9faaae1
MS
108 if (!strcmp(argv[first_arg], "-d"))
109 show_log = 1;
97c9a8d7
MS
110 else if (!strcmp(argv[first_arg], "-cancel"))
111 do_cancel = 1;
e07d4801
MS
112 else if (!strcmp(argv[first_arg], "-pcl"))
113 do_pcl = 1;
b9faaae1 114 else if (!strcmp(argv[first_arg], "-ps"))
e07d4801 115 do_ps = 1;
634763e8 116 else if (!strcmp(argv[first_arg], "-s"))
568fa3fa
MS
117 do_side_tests = 1;
118 else if (!strcmp(argv[first_arg], "-t"))
119 do_trickle = 1;
b9faaae1
MS
120 else if (!strcmp(argv[first_arg], "-get") && (first_arg + 1) < argc)
121 {
122 first_arg ++;
123
124 do_side_tests = 1;
125 oid = argv[first_arg];
126 }
127 else if (!strcmp(argv[first_arg], "-walk") && (first_arg + 1) < argc)
128 {
129 first_arg ++;
130
131 do_side_tests = 1;
132 do_walk = 1;
133 oid = argv[first_arg];
134 }
568fa3fa
MS
135 else
136 usage();
137
138 argc -= first_arg;
139 if (argc < 6 || argc > 7 || (argc == 7 && do_trickle))
140 usage();
141
142 /*
143 * Extract the scheme from the device-uri - that's the program we want to
144 * execute.
145 */
146
147 if (sscanf(argv[first_arg], "%254[^:]", scheme) != 1)
148 {
149 fputs("testbackend: Bad device-uri - no colon!\n", stderr);
150 return (1);
151 }
152
153 if (!access(scheme, X_OK))
154 strlcpy(backend, scheme, sizeof(backend));
155 else
156 {
157 if ((serverbin = getenv("CUPS_SERVERBIN")) == NULL)
158 serverbin = CUPS_SERVERBIN;
159
160 snprintf(backend, sizeof(backend), "%s/backend/%s", serverbin, scheme);
161 if (access(backend, X_OK))
162 {
163 fprintf(stderr, "testbackend: Unknown device scheme \"%s\"!\n", scheme);
164 return (1);
165 }
166 }
167
168 /*
169 * Create the back-channel pipe and side-channel socket...
170 */
171
172 open("/dev/null", O_WRONLY); /* Make sure fd 3 and 4 are used */
173 open("/dev/null", O_WRONLY);
174
175 pipe(back_fds);
176 fcntl(back_fds[0], F_SETFL, fcntl(back_fds[0], F_GETFL) | O_NONBLOCK);
177 fcntl(back_fds[1], F_SETFL, fcntl(back_fds[1], F_GETFL) | O_NONBLOCK);
178
179 socketpair(AF_LOCAL, SOCK_STREAM, 0, side_fds);
180 fcntl(side_fds[0], F_SETFL, fcntl(side_fds[0], F_GETFL) | O_NONBLOCK);
181 fcntl(side_fds[1], F_SETFL, fcntl(side_fds[1], F_GETFL) | O_NONBLOCK);
182
183 /*
184 * Execute the trickle process as needed...
185 */
186
97c9a8d7 187 if (do_trickle || do_pcl || do_ps || do_cancel)
568fa3fa
MS
188 {
189 pipe(data_fds);
190
97c9a8d7
MS
191 signal(SIGTERM, sigterm_handler);
192
193 if ((data_pid = fork()) == 0)
568fa3fa
MS
194 {
195 /*
e07d4801
MS
196 * Trickle/query child comes here. Rearrange file descriptors so that
197 * FD 1, 3, and 4 point to the backend...
568fa3fa
MS
198 */
199
97c9a8d7
MS
200 if ((fd = open("/dev/null", O_RDONLY)) != 0)
201 {
202 dup2(fd, 0);
203 close(fd);
204 }
568fa3fa 205
97c9a8d7
MS
206 if (data_fds[1] != 1)
207 {
208 dup2(data_fds[1], 1);
209 close(data_fds[1]);
210 }
568fa3fa 211 close(data_fds[0]);
634763e8 212
97c9a8d7
MS
213 if (back_fds[0] != 3)
214 {
215 dup2(back_fds[0], 3);
216 close(back_fds[0]);
217 }
634763e8
MS
218 close(back_fds[1]);
219
97c9a8d7
MS
220 if (side_fds[0] != 4)
221 {
222 dup2(side_fds[0], 4);
223 close(side_fds[0]);
224 }
634763e8
MS
225 close(side_fds[1]);
226
227 if (do_trickle)
228 {
229 /*
230 * Write 10 spaces, 1 per second...
231 */
232
233 int i; /* Looping var */
234
235 for (i = 0; i < 10; i ++)
236 {
237 write(1, " ", 1);
238 sleep(1);
239 }
240 }
97c9a8d7
MS
241 else if (do_cancel)
242 {
243 /*
244 * Write PS or PCL lines until we see SIGTERM...
245 */
246
247 int line = 0, page = 0; /* Current line and page */
248 ssize_t bytes; /* Number of bytes of response data */
249 char buffer[1024]; /* Output buffer */
250
251
252 if (do_pcl)
253 write(1, "\033E", 2);
254 else
255 write(1, "%!\n/Courier findfont 12 scalefont setfont 0 setgray\n", 52);
256
257 while (!job_canceled)
258 {
259 if (line == 0)
260 {
261 page ++;
262
263 if (do_pcl)
264 snprintf(buffer, sizeof(buffer), "PCL Page %d\r\n\r\n", page);
265 else
266 snprintf(buffer, sizeof(buffer),
267 "18 732 moveto (PS Page %d) show\n", page);
268
269 write(1, buffer, strlen(buffer));
270 }
271
272 line ++;
273
274 if (do_pcl)
275 snprintf(buffer, sizeof(buffer), "Line %d\r\n", line);
276 else
277 snprintf(buffer, sizeof(buffer), "18 %d moveto (Line %d) show\n",
278 720 - line * 12, line);
279
280 write(1, buffer, strlen(buffer));
281
282 if (line >= 55)
283 {
284 /*
285 * Eject after 55 lines...
286 */
287
288 line = 0;
289 if (do_pcl)
290 write(1, "\014", 1);
291 else
292 write(1, "showpage\n", 9);
293 }
294
295 /*
296 * Check for back-channel data...
297 */
298
299 if ((bytes = cupsBackChannelRead(buffer, sizeof(buffer), 0)) > 0)
7e86f2f6 300 write(2, buffer, (size_t)bytes);
97c9a8d7
MS
301
302 /*
303 * Throttle output to ~100hz...
304 */
305
306 usleep(10000);
307 }
308
309 /*
310 * Eject current page with info...
311 */
312
313 if (do_pcl)
314 snprintf(buffer, sizeof(buffer),
315 "Canceled on line %d of page %d\r\n\014\033E", line, page);
316 else
317 snprintf(buffer, sizeof(buffer),
318 "\n18 %d moveto (Canceled on line %d of page %d)\nshowpage\n",
319 720 - line * 12, line, page);
320
321 write(1, buffer, strlen(buffer));
322
323 /*
324 * See if we get any back-channel data...
325 */
326
327 while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer), 5.0)) > 0)
7e86f2f6 328 write(2, buffer, (size_t)bytes);
97c9a8d7
MS
329
330 exit(0);
331 }
634763e8 332 else
568fa3fa
MS
333 {
334 /*
e07d4801 335 * Do PS or PCL query + test pages.
568fa3fa
MS
336 */
337
e07d4801
MS
338 char buffer[1024]; /* Buffer for response data */
339 ssize_t bytes; /* Number of bytes of response data */
340 double timeout; /* Timeout */
341 const char *data; /* Data to send */
342 static const char *pcl_data = /* PCL data */
343 "\033%-12345X@PJL\r\n"
344 "@PJL JOB NAME = \"Hello, World!\"\r\n"
345 "@PJL INFO USTATUS\r\n"
346 "@PJL ENTER LANGUAGE = PCL\r\n"
347 "\033E"
348 "Hello, World!\n"
349 "\014"
350 "\033%-12345X@PJL\r\n"
351 "@PJL EOJ NAME=\"Hello, World!\"\r\n"
352 "\033%-12345X";
353 static const char *ps_data = /* PostScript data */
634763e8
MS
354 "%!\n"
355 "save\n"
b9faaae1 356 "product = flush\n"
634763e8
MS
357 "currentpagedevice /PageSize get aload pop\n"
358 "2 copy gt {exch} if\n"
359 "(Unknown)\n"
360 "19 dict\n"
361 "dup [612 792] (Letter) put\n"
362 "dup [612 1008] (Legal) put\n"
363 "dup [612 935] (w612h935) put\n"
364 "dup [522 756] (Executive) put\n"
365 "dup [595 842] (A4) put\n"
366 "dup [420 595] (A5) put\n"
367 "dup [499 709] (ISOB5) put\n"
368 "dup [516 728] (B5) put\n"
369 "dup [612 936] (w612h936) put\n"
370 "dup [284 419] (Postcard) put\n"
371 "dup [419.5 567] (DoublePostcard) put\n"
372 "dup [558 774] (w558h774) put\n"
373 "dup [553 765] (w553h765) put\n"
374 "dup [522 737] (w522h737) put\n"
375 "dup [499 709] (EnvISOB5) put\n"
376 "dup [297 684] (Env10) put\n"
377 "dup [459 649] (EnvC5) put\n"
378 "dup [312 624] (EnvDL) put\n"
379 "dup [279 540] (EnvMonarch) put\n"
380 "{ exch aload pop 4 index sub abs 5 le exch\n"
381 " 5 index sub abs 5 le and\n"
382 " {exch pop exit} {pop} ifelse\n"
383 "} bind forall\n"
384 "= flush pop pop\n"
e07d4801
MS
385 "/Courier findfont 12 scalefont setfont\n"
386 "0 setgray 36 720 moveto (Hello, ) show product show (!) show\n"
387 "showpage\n"
634763e8
MS
388 "restore\n"
389 "\004";
390
391
e07d4801
MS
392 if (do_pcl)
393 data = pcl_data;
394 else
395 data = ps_data;
396
397 write(1, data, strlen(data));
634763e8 398 write(2, "DEBUG: START\n", 13);
e07d4801
MS
399 timeout = 60.0;
400 while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer),
401 timeout)) > 0)
402 {
7e86f2f6 403 write(2, buffer, (size_t)bytes);
e07d4801
MS
404 timeout = 5.0;
405 }
634763e8 406 write(2, "\nDEBUG: END\n", 12);
568fa3fa
MS
407 }
408
409 exit(0);
410 }
97c9a8d7 411 else if (data_pid < 0)
568fa3fa
MS
412 {
413 perror("testbackend: Unable to fork");
414 return (1);
415 }
416 }
417 else
418 data_fds[0] = data_fds[1] = -1;
419
420 /*
421 * Execute the backend...
422 */
423
97c9a8d7 424 if ((back_pid = fork()) == 0)
568fa3fa
MS
425 {
426 /*
427 * Child comes here...
428 */
429
97c9a8d7 430 if (do_trickle || do_ps || do_pcl || do_cancel)
568fa3fa 431 {
97c9a8d7
MS
432 if (data_fds[0] != 0)
433 {
434 dup2(data_fds[0], 0);
435 close(data_fds[0]);
436 }
568fa3fa
MS
437 close(data_fds[1]);
438 }
439
b9faaae1
MS
440 if (!show_log)
441 {
97c9a8d7
MS
442 if ((fd = open("/dev/null", O_WRONLY)) != 2)
443 {
444 dup2(fd, 2);
445 close(fd);
446 }
b9faaae1
MS
447 }
448
97c9a8d7
MS
449 if (back_fds[1] != 3)
450 {
451 dup2(back_fds[1], 3);
452 close(back_fds[0]);
453 }
568fa3fa
MS
454 close(back_fds[1]);
455
97c9a8d7
MS
456 if (side_fds[1] != 4)
457 {
458 dup2(side_fds[1], 4);
459 close(side_fds[0]);
460 }
568fa3fa
MS
461 close(side_fds[1]);
462
463 execv(backend, argv + first_arg);
1340db2d 464 fprintf(stderr, "testbackend: Unable to execute \"%s\": %s\n", backend,
568fa3fa
MS
465 strerror(errno));
466 return (errno);
467 }
97c9a8d7 468 else if (back_pid < 0)
568fa3fa
MS
469 {
470 perror("testbackend: Unable to fork");
471 return (1);
472 }
473
474 /*
475 * Parent comes here, setup back and side channel file descriptors...
476 */
477
97c9a8d7 478 if (do_trickle || do_ps || do_pcl || do_cancel)
568fa3fa
MS
479 {
480 close(data_fds[0]);
481 close(data_fds[1]);
482 }
483
97c9a8d7
MS
484 if (back_fds[0] != 3)
485 {
486 dup2(back_fds[0], 3);
487 close(back_fds[0]);
488 }
568fa3fa
MS
489 close(back_fds[1]);
490
97c9a8d7
MS
491 if (side_fds[0] != 4)
492 {
493 dup2(side_fds[0], 4);
494 close(side_fds[0]);
495 }
568fa3fa
MS
496 close(side_fds[1]);
497
498 /*
499 * Do side-channel tests as needed, then wait for the backend...
500 */
501
502 if (do_side_tests)
503 {
504 int length; /* Length of buffer */
505 char buffer[2049]; /* Buffer for reponse */
506 cups_sc_status_t scstatus; /* Status of side-channel command */
507 static const char * const statuses[] =
508 {
509 "CUPS_SC_STATUS_NONE", /* No status */
510 "CUPS_SC_STATUS_OK", /* Operation succeeded */
511 "CUPS_SC_STATUS_IO_ERROR", /* An I/O error occurred */
512 "CUPS_SC_STATUS_TIMEOUT", /* The backend did not respond */
513 "CUPS_SC_STATUS_NO_RESPONSE", /* The device did not respond */
514 "CUPS_SC_STATUS_BAD_MESSAGE", /* The command/response message was invalid */
515 "CUPS_SC_STATUS_TOO_BIG", /* Response too big */
516 "CUPS_SC_STATUS_NOT_IMPLEMENTED" /* Command not implemented */
517 };
518
519
20fbc903
MS
520 sleep(2);
521
568fa3fa
MS
522 length = 0;
523 scstatus = cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer,
1340db2d 524 &length, 60.0);
568fa3fa
MS
525 printf("CUPS_SC_CMD_DRAIN_OUTPUT returned %s\n", statuses[scstatus]);
526
527 length = 1;
528 scstatus = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_BIDI, buffer,
529 &length, 5.0);
530 printf("CUPS_SC_CMD_GET_BIDI returned %s, %d\n", statuses[scstatus], buffer[0]);
531
532 length = sizeof(buffer) - 1;
533 scstatus = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_DEVICE_ID, buffer,
534 &length, 5.0);
535 buffer[length] = '\0';
536 printf("CUPS_SC_CMD_GET_DEVICE_ID returned %s, \"%s\"\n",
537 statuses[scstatus], buffer);
538
539 length = 1;
540 scstatus = cupsSideChannelDoRequest(CUPS_SC_CMD_GET_STATE, buffer,
541 &length, 5.0);
542 printf("CUPS_SC_CMD_GET_STATE returned %s, %02X\n", statuses[scstatus],
543 buffer[0] & 255);
544
b9faaae1
MS
545 if (do_walk)
546 {
547 /*
548 * Walk the OID tree...
549 */
550
551 scstatus = cupsSideChannelSNMPWalk(oid, 5.0, walk_cb, NULL);
552 printf("CUPS_SC_CMD_SNMP_WALK returned %s\n", statuses[scstatus]);
553 }
554 else
555 {
556 /*
557 * Lookup the same OID twice...
558 */
559
560 length = sizeof(buffer);
561 scstatus = cupsSideChannelSNMPGet(oid, buffer, &length, 5.0);
82cc1f9a
MS
562 printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %d bytes (%s)\n", oid,
563 statuses[scstatus], (int)length, buffer);
b9faaae1
MS
564
565 length = sizeof(buffer);
566 scstatus = cupsSideChannelSNMPGet(oid, buffer, &length, 5.0);
82cc1f9a
MS
567 printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %d bytes (%s)\n", oid,
568 statuses[scstatus], (int)length, buffer);
b9faaae1 569 }
20fbc903 570
568fa3fa
MS
571 length = 0;
572 scstatus = cupsSideChannelDoRequest(CUPS_SC_CMD_SOFT_RESET, buffer,
573 &length, 5.0);
574 printf("CUPS_SC_CMD_SOFT_RESET returned %s\n", statuses[scstatus]);
575 }
576
97c9a8d7 577 if (do_cancel)
568fa3fa 578 {
97c9a8d7
MS
579 sleep(1);
580 kill(data_pid, SIGTERM);
581 kill(back_pid, SIGTERM);
582 }
85dda01c 583
97c9a8d7
MS
584 while ((pid = wait(&status)) > 0)
585 {
586 if (status)
587 {
588 if (WIFEXITED(status))
589 printf("%s exited with status %d!\n",
590 pid == back_pid ? backend : "test",
591 WEXITSTATUS(status));
592 else
593 printf("%s crashed with signal %d!\n",
594 pid == back_pid ? backend : "test",
595 WTERMSIG(status));
596 }
568fa3fa
MS
597 }
598
599 /*
600 * Exit accordingly...
601 */
602
603 return (status != 0);
604}
605
606
97c9a8d7
MS
607/*
608 * 'sigterm_handler()' - Flag when we get SIGTERM.
609 */
610
611static void
612sigterm_handler(int sig) /* I - Signal */
613{
614 (void)sig;
615
616 job_canceled = 1;
617}
618
619
568fa3fa
MS
620/*
621 * 'usage()' - Show usage information.
622 */
623
624static void
625usage(void)
626{
82cc1f9a 627 puts("Usage: testbackend [-cancel] [-d] [-ps | -pcl] [-s [-get OID] "
97c9a8d7 628 "[-walk OID]] [-t] device-uri job-id user title copies options [file]");
b9faaae1
MS
629 puts("");
630 puts("Options:");
97c9a8d7 631 puts(" -cancel Simulate a canceled print job after 2 seconds.");
b9faaae1 632 puts(" -d Show log messages from backend.");
82cc1f9a 633 puts(" -get OID Lookup the specified SNMP OID.");
1340db2d 634 puts(" (.1.3.6.1.2.1.43.10.2.1.4.1.1 is a good one for printers)");
e07d4801
MS
635 puts(" -pcl Send PCL+PJL query and test page to backend.");
636 puts(" -ps Send PostScript query and test page to backend.");
1340db2d 637 puts(" -s Do side-channel + SNMP tests.");
b9faaae1
MS
638 puts(" -t Send spaces slowly to backend ('trickle').");
639 puts(" -walk OID Walk the specified SNMP OID.");
1340db2d 640 puts(" (.1.3.6.1.2.1.43 is a good one for printers)");
b9faaae1 641
568fa3fa
MS
642 exit(1);
643}
644
645
b9faaae1
MS
646/*
647 * 'walk_cb()' - Show results of cupsSideChannelSNMPWalk...
648 */
649
650static void
651walk_cb(const char *oid, /* I - OID */
652 const char *data, /* I - Data */
653 int datalen, /* I - Length of data */
654 void *context) /* I - Context (unused) */
655{
94436c5a 656 char temp[80];
7e86f2f6
MS
657
658 (void)context;
659
660 if ((size_t)datalen > (sizeof(temp) - 1))
94436c5a
MS
661 {
662 memcpy(temp, data, sizeof(temp) - 1);
663 temp[sizeof(temp) - 1] = '\0';
664 }
665 else
666 {
07623986 667 memcpy(temp, data, (size_t)datalen);
94436c5a
MS
668 temp[datalen] = '\0';
669 }
670
671 printf("CUPS_SC_CMD_SNMP_WALK %s, %d bytes (%s)\n", oid, datalen, temp);
b9faaae1 672}