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