xref: /illumos-gate/usr/src/cmd/print/bsd-sysv-commands/lpstat.c (revision 828d47c166ce67972b1f1929669b9af5be769423)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  */
27 
28 /* $Id: lpstat.c 173 2006-05-25 04:52:06Z njacobs $ */
29 
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <locale.h>
36 #include <libintl.h>
37 #include <ctype.h>
38 #include <pwd.h>
39 #include <papi.h>
40 #include <uri.h>
41 #include "common.h"
42 #include "lp.h"
43 
44 static void
45 usage(char *program)
46 {
47 	char *name;
48 
49 	if ((name = strrchr(program, '/')) == NULL)
50 		name = program;
51 	else
52 		name++;
53 
54 	fprintf(stdout, gettext("Usage: %s [-d] [-r] [-s] [-t] [-a [list]] "
55 	    "[-c [list]] [-o [list] [-l]] [-R [list] [-l]] "
56 	    "[-p [list] [-D] [-l]] [-v [list]] [-S [list] [-l]] "
57 	    "[-f [list] [-l]] [-u list]\n"),
58 	    name);
59 	exit(1);
60 }
61 
62 static char *
63 nctime(time_t *t)
64 {
65 	static char buf[64];
66 	struct tm *tm = localtime(t);
67 
68 	(void) strftime(buf, sizeof (buf), "%c", tm);
69 
70 	return (buf);
71 }
72 
73 static char *
74 printer_name(papi_printer_t printer)
75 {
76 	papi_attribute_t **attributes = papiPrinterGetAttributeList(printer);
77 	char *result = NULL;
78 
79 	if (attributes != NULL)
80 		papiAttributeListGetString(attributes, NULL,
81 		    "printer-name", &result);
82 
83 	return (result);
84 }
85 
86 static int
87 lpstat_default_printer(papi_encryption_t encryption)
88 {
89 	papi_status_t status;
90 	papi_service_t svc = NULL;
91 	papi_printer_t p = NULL;
92 	char *name = NULL;
93 
94 	status = papiServiceCreate(&svc, NULL, NULL, NULL, cli_auth_callback,
95 	    encryption, NULL);
96 	if (status == PAPI_OK) {
97 		char *req[] = { "printer-name", NULL };
98 
99 		status = papiPrinterQuery(svc, DEFAULT_DEST, req, NULL, &p);
100 		if (p != NULL)
101 			name = printer_name(p);
102 	}
103 	if (name != NULL)
104 		printf(gettext("system default printer: %s\n"), name);
105 	else
106 		printf(gettext("no system default destination\n"));
107 	papiPrinterFree(p);
108 	papiServiceDestroy(svc);
109 
110 	return (0);
111 }
112 
113 static int
114 lpstat_service_status(papi_encryption_t encryption)
115 {
116 	int result = 0;
117 	papi_status_t status;
118 	papi_service_t svc = NULL;
119 	char *name = NULL;
120 
121 	if (((name = getenv("PAPI_SERVICE_URI")) == NULL) &&
122 	    ((name = getenv("IPP_SERVER")) == NULL) &&
123 	    ((name = getenv("CUPS_SERVER")) == NULL))
124 		name = DEFAULT_SERVICE_URI;
125 
126 	status = papiServiceCreate(&svc, name, NULL, NULL, cli_auth_callback,
127 	    encryption, NULL);
128 	if (status != PAPI_OK) {
129 		printf(gettext("scheduler is not running\n"));
130 		result = -1;
131 	} else
132 		printf(gettext("scheduler is running\n"));
133 	papiServiceDestroy(svc);
134 
135 	return (result);
136 }
137 
138 static char *
139 get_device_uri(papi_service_t svc, char *name)
140 {
141 	papi_status_t status;
142 	papi_printer_t p = NULL;
143 	char *keys[] = { "device-uri", NULL };
144 	char *result = NULL;
145 
146 	status = papiPrinterQuery(svc, name, keys, NULL, &p);
147 	if ((status == PAPI_OK) && (p != NULL)) {
148 		papi_attribute_t **attrs = papiPrinterGetAttributeList(p);
149 
150 		(void) papiAttributeListGetString(attrs, NULL,
151 		    "device-uri", &result);
152 		if (result != NULL)
153 			result = strdup(result);
154 
155 		papiPrinterFree(p);
156 	}
157 
158 	return (result);
159 }
160 
161 static void
162 print_description(papi_attribute_t **list, char *printer_name)
163 {
164 	char *str = "";
165 
166 	(void) papiAttributeListGetString(list, NULL,
167 	    "printer-info", &str);
168 
169 	/*
170 	 * If no printer-info is read then
171 	 * by default the printer-info is <printer-name>@<server>
172 	 */
173 	if (str[0] == '\0') {
174 		char *uri = NULL;
175 		uri_t *u = NULL;
176 
177 		(void) papiAttributeListGetString(list, NULL,
178 		    "printer-uri-supported", &uri);
179 
180 		if ((uri != NULL) && (uri_from_string(uri, &u) == 0)) {
181 			char *nodename = localhostname();
182 
183 			if ((u->host == NULL) ||
184 			    (strcasecmp(u->host, "localhost") == 0) ||
185 			    (strcasecmp(u->host, nodename) == 0))
186 				printf(gettext("\tDescription:\n"));
187 			else
188 				printf(gettext("\tDescription: %s@%s\n"),
189 				    printer_name, u->host);
190 
191 			uri_free(u);
192 		} else
193 			printf(gettext("\tDescription:\n"));
194 	} else
195 		printf(gettext("\tDescription: %s\n"), str);
196 }
197 
198 static char *report_device_keys[] = { "printer-name", "printer-uri-supported",
199 					NULL };
200 /* ARGSUSED2 */
201 static int
202 report_device(papi_service_t svc, char *name, papi_printer_t printer,
203 		int verbose, int description)
204 {
205 	papi_status_t status;
206 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
207 	char *uri = NULL;
208 	char *device = NULL;
209 	uri_t *u = NULL;
210 
211 	if (name == NULL) {
212 		status = papiAttributeListGetString(attrs, NULL,
213 		    "printer-name", &name);
214 		if (status != PAPI_OK)
215 			status = papiAttributeListGetString(attrs, NULL,
216 			    "printer-uri-supported", &name);
217 	}
218 
219 	if (name == NULL)
220 		return (-1);
221 
222 	(void) papiAttributeListGetString(attrs, NULL,
223 	    "printer-uri-supported", &uri);
224 
225 	if ((uri != NULL) && (uri_from_string(uri, &u) == 0)) {
226 		char *nodename = localhostname();
227 
228 		if ((u->host == NULL) ||
229 		    (strcasecmp(u->host, "localhost") == 0) ||
230 		    (strcasecmp(u->host, nodename) == 0))
231 			device = get_device_uri(svc, name);
232 
233 		if (device != NULL) {
234 			printf(gettext("device for %s: %s\n"), name, device);
235 			return (0);
236 		} else if (uri != NULL) {
237 			printf(gettext("system for %s: %s (as %s)\n"), name,
238 			    u->host?u->host:"localhost", uri);
239 			return (0);
240 		}
241 
242 		uri_free(u);
243 	}
244 
245 	return (0);
246 }
247 
248 static char *report_accepting_keys[] = { "printer-name",
249 			"printer-uri-supported", "printer-is-accepting-jobs",
250 			"printer-up-time", "printer-state-time",
251 			"lpsched-reject-date", "lpsched-reject-reason", NULL };
252 /* ARGSUSED2 */
253 static int
254 report_accepting(papi_service_t svc, char *name, papi_printer_t printer,
255 		int verbose, int description)
256 {
257 	papi_status_t status;
258 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
259 	time_t curr;
260 	char boolean = PAPI_FALSE;
261 
262 	if (name == NULL) {
263 		status = papiAttributeListGetString(attrs, NULL,
264 		    "printer-name", &name);
265 		if (status != PAPI_OK)
266 			status = papiAttributeListGetString(attrs, NULL,
267 			    "printer-uri-supported", &name);
268 	}
269 	if (name == NULL)
270 		return (-1);
271 
272 	(void) papiAttributeListGetBoolean(attrs, NULL,
273 	    "printer-is-accepting-jobs", &boolean);
274 	(void) time(&curr);
275 	(void) papiAttributeListGetDatetime(attrs, NULL,
276 	    "printer-up-time", &curr);
277 	(void) papiAttributeListGetDatetime(attrs, NULL,
278 	    "printer-state-time", &curr);
279 	(void) papiAttributeListGetDatetime(attrs, NULL,
280 	    "lpsched-reject-date", &curr);
281 
282 	if (boolean == PAPI_TRUE) {
283 		printf(gettext("%s accepting requests since %s\n"),
284 		    name, nctime(&curr));
285 	} else {
286 		char *reason = "unknown reason";
287 
288 		(void) papiAttributeListGetString(attrs, NULL,
289 		    "lpsched-reject-reason", &reason);
290 
291 		printf(gettext("%s not accepting requests since %s\n\t%s\n"),
292 		    name, nctime(&curr), reason);
293 	}
294 
295 	return (0);
296 }
297 
298 static char *report_class_keys[] = { "printer-name", "printer-uri-supported",
299 					"member-names", NULL };
300 /* ARGSUSED2 */
301 static int
302 report_class(papi_service_t svc, char *name, papi_printer_t printer,
303 		int verbose, int description)
304 {
305 	papi_status_t status;
306 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
307 	char *member = NULL;
308 	void *iter = NULL;
309 
310 	status = papiAttributeListGetString(attrs, &iter,
311 	    "member-names", &member);
312 	if (status == PAPI_NOT_FOUND)	/* it's not a class */
313 		return (0);
314 
315 	if (name == NULL) {
316 		status = papiAttributeListGetString(attrs, NULL,
317 		    "printer-name", &name);
318 		if (status != PAPI_OK)
319 			status = papiAttributeListGetString(attrs, NULL,
320 			    "printer-uri-supported", &name);
321 	}
322 	if (name == NULL)
323 		return (-1);
324 
325 	printf(gettext("members of class %s:\n\t%s\n"), name, member);
326 	while (papiAttributeListGetString(attrs, &iter, NULL, &member)
327 	    == PAPI_OK)
328 		printf("\t%s\n", member);
329 
330 	return (0);
331 }
332 
333 static char *report_printer_keys[] = { "printer-name",
334 			"printer-uri-supported", "printer-state",
335 			"printer-up-time", "printer-state-time",
336 			"lpsched-disable-date", "printer-state-reasons",
337 			"lpsched-disable-reason", NULL };
338 /* ARGSUSED2 */
339 static int
340 report_printer(papi_service_t svc, char *name, papi_printer_t printer,
341 		int verbose, int description)
342 {
343 	papi_status_t status;
344 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
345 	time_t curr;
346 	int32_t pstat = 0;
347 	char *member = NULL;
348 	papi_job_t *j = NULL;
349 
350 	status = papiAttributeListGetString(attrs, NULL,
351 	    "member-names", &member);
352 	if (status == PAPI_OK)	/* it's a class */
353 		return (0);
354 
355 	if (name == NULL) {
356 		status = papiAttributeListGetString(attrs, NULL,
357 		    "printer-name", &name);
358 		if (status != PAPI_OK)
359 			status = papiAttributeListGetString(attrs, NULL,
360 			    "printer-uri-supported", &name);
361 	}
362 	if (name == NULL)
363 		return (-1);
364 
365 	printf(gettext("printer %s "), name);
366 
367 	status = papiAttributeListGetInteger(attrs, NULL,
368 	    "printer-state", &pstat);
369 
370 	switch (pstat) {
371 	case 0x03:	/* idle */
372 		printf(gettext("idle. enabled"));
373 		break;
374 	case 0x04: /* processing */
375 		status = papiPrinterListJobs(svc, name, NULL,
376 		    0, 0, &j);
377 
378 		if (status == PAPI_OK) {
379 			if (j != NULL) {
380 				int i = 0;
381 				int32_t jobid = 0;
382 				int32_t jstate = 0;
383 				int flag = 0;
384 
385 				for (i = 0; j[i] != NULL; ++i) {
386 					papi_attribute_t **attr =
387 					    papiJobGetAttributeList(j[i]);
388 
389 					papiAttributeListGetInteger(attr,
390 					    NULL, "job-state", &jstate);
391 					papiAttributeListGetInteger(attr,
392 					    NULL, "job-id", &jobid);
393 
394 					/*
395 					 * If the job-state is in
396 					 * RS_PRINTING then only print.
397 					 */
398 					if (jstate == 0x0008) {
399 						if (flag == 0)
400 							printf(gettext
401 							    ("now printing"\
402 							    " %s-%d. enabled"),
403 							    name, jobid);
404 						flag = 1;
405 					}
406 				}
407 				papiJobListFree(j);
408 			}
409 		}
410 		break;
411 	case 0x05:	/* stopped */
412 		printf(gettext("disabled"));
413 		break;
414 	default:
415 		printf(gettext("unknown state(0x%x)."), pstat);
416 		break;
417 	}
418 
419 	(void) time(&curr);
420 	(void) papiAttributeListGetDatetime(attrs, NULL,
421 	    "printer-up-time", &curr);
422 	(void) papiAttributeListGetDatetime(attrs, NULL,
423 	    "printer-state-time", &curr);
424 	(void) papiAttributeListGetDatetime(attrs, NULL,
425 	    "lpsched-disable-date", &curr);
426 	printf(gettext(" since %s. available.\n"), nctime(&curr));
427 
428 	if (pstat == 0x05) {
429 		char *reason = "unknown reason";
430 
431 		(void) papiAttributeListGetString(attrs, NULL,
432 		    "printer-state-reasons", &reason);
433 		(void) papiAttributeListGetString(attrs, NULL,
434 		    "lpsched-disable-reason", &reason);
435 		printf(gettext("\t%s\n"), reason);
436 	}
437 
438 	if (verbose == 1) {
439 		void *iter;
440 		char *str;
441 
442 		str = "";
443 		(void) papiAttributeListGetString(attrs, NULL,
444 		    "form-ready", &str);
445 		printf(gettext("\tForm mounted: %s\n"), str);
446 
447 		str = "";
448 		iter = NULL;
449 		(void) papiAttributeListGetString(attrs, &iter,
450 		    "document-format-supported", &str);
451 		printf(gettext("\tContent types: %s"), str);
452 		while (papiAttributeListGetString(attrs, &iter, NULL, &str)
453 		    == PAPI_OK)
454 			printf(", %s", str);
455 		printf("\n");
456 
457 		/* Display the printer description */
458 		print_description(attrs, name);
459 
460 		str = "";
461 		iter = NULL;
462 		(void) papiAttributeListGetString(attrs, &iter,
463 		    "lpsched-printer-type", &str);
464 		printf(gettext("\tPrinter types: %s"), str);
465 		while (papiAttributeListGetString(attrs, &iter, NULL, &str)
466 		    == PAPI_OK)
467 			printf(", %s", str);
468 		printf("\n");
469 
470 		str = "";
471 		(void) papiAttributeListGetString(attrs, NULL,
472 		    "lpsched-dial-info", &str);
473 		printf(gettext("\tConnection: %s\n"),
474 		    ((str[0] == '\0') ? gettext("direct") : str));
475 
476 		str = "";
477 		(void) papiAttributeListGetString(attrs, NULL,
478 		    "lpsched-interface-script", &str);
479 		printf(gettext("\tInterface: %s\n"), str);
480 
481 		str = NULL;
482 		(void) papiAttributeListGetString(attrs, NULL,
483 		    "ppd-file-uri", &str);
484 		(void) papiAttributeListGetString(attrs, NULL,
485 		    "lpsched-ppd-source-path", &str);
486 		if (str != NULL)
487 			printf(gettext("\tPPD: %s\n"), str);
488 
489 		str = NULL;
490 		(void) papiAttributeListGetString(attrs, NULL,
491 		    "lpsched-fault-alert-command", &str);
492 		if (str != NULL)
493 			printf(gettext("\tOn fault: %s\n"), str);
494 
495 		str = "";
496 		(void) papiAttributeListGetString(attrs, NULL,
497 		    "lpsched-fault-recovery", &str);
498 		printf(gettext("\tAfter fault: %s\n"),
499 		    ((str[0] == '\0') ? gettext("continue") : str));
500 
501 		str = "(all)";
502 		iter = NULL;
503 		(void) papiAttributeListGetString(attrs, &iter,
504 		    "requesting-user-name-allowed", &str);
505 		printf(gettext("\tUsers allowed:\n\t\t%s\n"),
506 		    ((str[0] == '\0') ? gettext("(none)") : str));
507 		if ((str != NULL) && (str[0] != '\0'))
508 			while (papiAttributeListGetString(attrs, &iter, NULL,
509 			    &str) == PAPI_OK)
510 				printf("\t\t%s\n", str);
511 
512 		str = NULL;
513 		iter = NULL;
514 		(void) papiAttributeListGetString(attrs, &iter,
515 		    "requesting-user-name-denied", &str);
516 		if (str != NULL) {
517 			printf(gettext("\tUsers denied:\n\t\t%s\n"),
518 			    ((str[0] == '\0') ? gettext("(none)") : str));
519 			if ((str != NULL) && (str[0] != '\0'))
520 				while (papiAttributeListGetString(attrs, &iter,
521 				    NULL, &str) == PAPI_OK)
522 					printf("\t\t%s\n", str);
523 		}
524 
525 		str = "none";
526 		iter = NULL;
527 		(void) papiAttributeListGetString(attrs, &iter,
528 		    "form-supported", &str);
529 		printf(gettext("\tForms allowed:\n\t\t(%s)\n"),
530 		    ((str[0] == '\0') ? gettext("none") : str));
531 		if ((str != NULL) && (str[0] != '\0'))
532 			while (papiAttributeListGetString(attrs, &iter, NULL,
533 			    &str) == PAPI_OK)
534 				printf("\t\t(%s)\n", str);
535 
536 		str = "";
537 		iter = NULL;
538 		(void) papiAttributeListGetString(attrs, &iter,
539 		    "media-supported", &str);
540 		printf(gettext("\tMedia supported:\n\t\t%s\n"),
541 		    ((str[0] == '\0') ? gettext("(none)") : str));
542 		if ((str != NULL) && (str[0] != '\0'))
543 			while (papiAttributeListGetString(attrs, &iter, NULL,
544 			    &str) == PAPI_OK)
545 				printf("\t\t%s\n", str);
546 
547 		str = "";
548 		(void) papiAttributeListGetString(attrs, NULL,
549 		    "job-sheets-supported", &str);
550 		if ((strcasecmp(str, "none")) == 0)
551 			str = gettext("page never printed");
552 		else if (strcasecmp(str, "optional") == 0)
553 			str = gettext("not required");
554 		else
555 			str = gettext("required");
556 
557 		printf(gettext("\tBanner %s\n"), str);
558 
559 
560 		str = "";
561 		iter = NULL;
562 		(void) papiAttributeListGetString(attrs, &iter,
563 		    "lpsched-print-wheels", &str);
564 		printf(gettext("\tCharacter sets:\n\t\t%s\n"),
565 		    ((str[0] == '\0') ? gettext("(none)") : str));
566 		if ((str != NULL) && (str[0] != '\0'))
567 			while (papiAttributeListGetString(attrs, &iter, NULL,
568 			    &str) == PAPI_OK)
569 				printf("\t\t%s\n", str);
570 
571 		printf(gettext("\tDefault pitch:\n"));
572 		printf(gettext("\tDefault page size:\n"));
573 		printf(gettext("\tDefault port setting:\n"));
574 
575 		str = "";
576 		iter = NULL;
577 		(void) papiAttributeListGetString(attrs, &iter,
578 		    "lpsched-options", &str);
579 		if (str != NULL) {
580 			printf(gettext("\tOptions: %s"), str);
581 			while (papiAttributeListGetString(attrs, &iter, NULL,
582 			    &str) == PAPI_OK)
583 				printf(", %s", str);
584 			printf("\n");
585 		}
586 
587 	} else if (description == 1)
588 		/* Display printer description */
589 		print_description(attrs, name);
590 	else if (verbose > 1)
591 		papiAttributeListPrint(stdout, attrs, "\t");
592 
593 	if (verbose > 0)
594 		printf("\n");
595 
596 	return (0);
597 }
598 
599 static int
600 printer_query(char *name, int (*report)(papi_service_t, char *, papi_printer_t,
601 					int, int), papi_encryption_t encryption,
602 		int verbose, int description)
603 {
604 	int result = 0, i = 0;
605 	papi_status_t status;
606 	papi_service_t svc = NULL;
607 	char **list = getlist(name, LP_WS, LP_SEP);
608 
609 	if (list == NULL) {
610 		list = (char **)malloc(sizeof (char *));
611 		list[0] = name;
612 	}
613 
614 	/*
615 	 * The for loop executes once for every printer
616 	 * entry in list. If list is NULL that implies
617 	 * name is also NULL, the loop runs only one time.
618 	 */
619 
620 	for (i = 0; name == NULL || list[i] != NULL; i++) {
621 		name = list[i];
622 
623 		status = papiServiceCreate(&svc, name, NULL, NULL,
624 		    cli_auth_callback, encryption, NULL);
625 		if (status != PAPI_OK) {
626 			if (status == PAPI_NOT_FOUND)
627 				fprintf(stderr,
628 				    gettext("%s: unknown printer\n"),
629 				    name ? name : "(NULL)");
630 			else
631 				fprintf(stderr, gettext(
632 				    "Failed to contact service for %s: %s\n"),
633 				    name ? name : "(NULL)",
634 				    verbose_papi_message(svc, status));
635 			papiServiceDestroy(svc);
636 			result--;
637 			continue;
638 		}
639 
640 		if (name == NULL) { /* all */
641 			char **interest = interest_list(svc);
642 
643 			if (interest != NULL) {
644 				int i;
645 
646 				for (i = 0; interest[i] != NULL; i++)
647 					result += printer_query(interest[i],
648 					    report, encryption, verbose,
649 					    description);
650 			}
651 		} else {
652 			papi_printer_t printer = NULL;
653 			char **keys = NULL;
654 
655 			/*
656 			 * Limit the query to only required data
657 			 * to reduce the need to go remote for
658 			 * information.
659 			 */
660 			if (report == report_device)
661 				keys = report_device_keys;
662 			else if (report == report_class)
663 				keys = report_class_keys;
664 			else if (report == report_accepting)
665 				keys = report_accepting_keys;
666 			else if ((report == report_printer) && (verbose == 0))
667 				keys = report_printer_keys;
668 
669 			status = papiPrinterQuery(svc, name, keys,
670 			    NULL, &printer);
671 			if (status != PAPI_OK) {
672 				fprintf(stderr, gettext(
673 				    "Failed to get printer info for %s: %s\n"),
674 				    name, verbose_papi_message(svc, status));
675 				papiServiceDestroy(svc);
676 				result--;
677 				continue;
678 			}
679 
680 			if (printer != NULL)
681 				result += report(svc, name, printer, verbose,
682 				    description);
683 
684 			papiPrinterFree(printer);
685 		}
686 
687 		papiServiceDestroy(svc);
688 
689 		if (name == NULL)
690 			break;
691 	}
692 
693 	freelist(list);
694 
695 	return (result);
696 }
697 
698 static int
699 match_user(char *user, char **list)
700 {
701 	int i;
702 
703 	for (i = 0; list[i] != NULL; i++) {
704 		if (strcmp(user, list[i]) == 0)
705 			return (0);
706 	}
707 
708 	return (-1);
709 }
710 
711 static char **users = NULL;
712 
713 static int
714 report_job(char *printer, papi_job_t job, int show_rank, int verbose)
715 {
716 	papi_attribute_t **attrs = papiJobGetAttributeList(job);
717 	time_t clock = 0;
718 	char date[24];
719 	char request[26];
720 	char *user = "unknown";
721 	char *host = NULL;
722 	int32_t size = 0;
723 	int32_t jstate = 0;
724 	char User[50];
725 
726 	char *destination = "unknown";
727 	int32_t id = -1;
728 	static int check = 0;
729 	static char *uri = NULL;
730 
731 	(void) papiAttributeListGetString(attrs, NULL,
732 	    "job-originating-user-name", &user);
733 
734 	if ((users != NULL) && (match_user(user, users) < 0))
735 		return (0);
736 
737 	(void) papiAttributeListGetString(attrs, NULL,
738 	    "job-originating-host-name", &host);
739 
740 	if (check == 0) {
741 		/*
742 		 * Read the attribute "job-printer-uri"
743 		 * just once
744 		 */
745 		(void) papiAttributeListGetString(attrs, NULL,
746 		    "job-printer-uri", &uri);
747 		check = 1;
748 	}
749 
750 	if (host) {
751 		/* Check if it is local printer or remote printer */
752 		uri_t *u = NULL;
753 
754 		if ((uri != NULL) && (uri_from_string(uri, &u) == 0)) {
755 			char *nodename = localhostname();
756 
757 			if ((u->host == NULL) ||
758 			    (strcasecmp(u->host, "localhost") == 0) ||
759 			    (strcasecmp(u->host, nodename) == 0)) {
760 
761 				if (strcasecmp(host, nodename) == 0) {
762 					/*
763 					 * Request submitted locally
764 					 * for the local queue.
765 					 * Hostname will not be displayed
766 					 */
767 					snprintf(User, sizeof (User), "%s",
768 					    user);
769 				}
770 				else
771 					snprintf(User, sizeof (User), "%s@%s",
772 					    user, host);
773 			} else if (uri != NULL) {
774 				/*
775 				 * It's a remote printer.
776 				 * In case of remote printers hostname is
777 				 * always displayed.
778 				 */
779 				snprintf(User, sizeof (User), "%s@%s",
780 				    user, host);
781 			}
782 			uri_free(u);
783 		} else {
784 			/*
785 			 * If attribute "job-printer-uri"
786 			 * cannot be read
787 			 * by default append the hostname
788 			 */
789 			snprintf(User, sizeof (User), "%s@%s", user, host);
790 		}
791 	} else {
792 		/*
793 		 * When print server is s10u4 and ipp service is used
794 		 * "job-originating-hostname" attribute is not set
795 		 * So get the host information from the uri
796 		 */
797 		uri_t *u = NULL;
798 		if ((uri != NULL) && (uri_from_string(uri, &u) == 0)) {
799 			if ((u != NULL) && (u->host != NULL))
800 				snprintf(User, sizeof (User), "%s@%s",
801 				    user, u->host);
802 			else
803 				snprintf(User, sizeof (User), "%s", user);
804 
805 			uri_free(u);
806 		} else
807 			snprintf(User, sizeof (User), "%s", user);
808 	}
809 	(void) papiAttributeListGetInteger(attrs, NULL, "job-k-octets", &size);
810 	size *= 1024;	/* for the approximate byte size */
811 	(void) papiAttributeListGetInteger(attrs, NULL, "job-octets", &size);
812 
813 	(void) time(&clock);
814 	(void) papiAttributeListGetInteger(attrs, NULL,
815 	    "time-at-creation", (int32_t *)&clock);
816 	(void) strftime(date, sizeof (date), "%b %d %R", localtime(&clock));
817 
818 	(void) papiAttributeListGetString(attrs, NULL,
819 	    "job-printer-uri", &destination);
820 	(void) papiAttributeListGetString(attrs, NULL,
821 	    "printer-name", &destination);
822 	(void) papiAttributeListGetInteger(attrs, NULL,
823 	    "job-id", &id);
824 	(void) papiAttributeListGetInteger(attrs, NULL,
825 	    "job-id-requested", &id);
826 
827 
828 	snprintf(request, sizeof (request), "%s-%d", printer, id);
829 
830 	if (show_rank != 0) {
831 		int32_t rank = -1;
832 
833 		(void) papiAttributeListGetInteger(attrs, NULL,
834 		    "number-of-intervening-jobs", &rank);
835 		rank++;
836 
837 		printf("%3d %-21s %-14s %7ld %s",
838 		    rank, request, User, size, date);
839 	} else
840 		printf("%-23s %-14s %7ld   %s", request, User, size, date);
841 
842 	(void) papiAttributeListGetInteger(attrs, NULL,
843 	    "job-state", &jstate);
844 
845 	if (jstate == 0x0001)
846 		printf(gettext(" being held"));
847 	else if (jstate == 0x0800)
848 		printf(gettext(" notifying user"));
849 	else if (jstate == 0x0040)
850 		printf(gettext(" cancelled"));
851 	else if (jstate == 0x0010)
852 		printf(gettext(" finished printing"));
853 	else if (jstate == 0x0008)
854 		printf(gettext(" on %s"), destination);
855 	else if (jstate == 0x2000)
856 		printf(gettext(" held by admin"));
857 	else if (jstate == 0x0002)
858 		printf(gettext(" being filtered"));
859 	else if (jstate == 0x0004)
860 		printf(gettext(" filtered"));
861 	else if (jstate == 0x0020)
862 		printf(gettext(" held for change"));
863 
864 	if (verbose == 1) {
865 		char *form = NULL;
866 
867 		(void) papiAttributeListGetString(attrs, NULL,
868 		    "output-device-assigned", &destination);
869 		printf("\n\t assigned %s", destination);
870 
871 		(void) papiAttributeListGetString(attrs, NULL, "form", &form);
872 		if (form != NULL)
873 			printf(", form %s", form);
874 	} else if (verbose > 1) {
875 		printf("\n");
876 		papiAttributeListPrint(stdout, attrs, "\t");
877 	}
878 
879 	printf("\n");
880 
881 	return (0);
882 }
883 
884 static int
885 job_query(char *request, int (*report)(char *, papi_job_t, int, int),
886 		papi_encryption_t encryption, int show_rank, int verbose)
887 {
888 	int result = 0;
889 	papi_status_t status;
890 	papi_service_t svc = NULL;
891 	char *printer = request;
892 	int32_t id = -1;
893 	int flag1 = 0;
894 	int flag = 1;
895 	int print_flag = 0;
896 
897 	do {
898 		status = papiServiceCreate(&svc, printer, NULL, NULL,
899 		    cli_auth_callback, encryption, NULL);
900 
901 		if ((status == PAPI_OK) && (printer != NULL))
902 			print_flag = 1;
903 
904 		/* <name>-# printer name does not exist */
905 		if (status != PAPI_OK) {
906 			/*
907 			 * Check if <name>-# is a request-id
908 			 * Once this check is done flag1 is set
909 			 */
910 			if (flag1 == 1)
911 				break;
912 
913 			get_printer_id(printer, &printer, &id);
914 
915 			status = papiServiceCreate(&svc, printer, NULL, NULL,
916 			    cli_auth_callback, encryption, NULL);
917 
918 			if (status != PAPI_OK) {
919 				fprintf(stderr, gettext(
920 				    "Failed to contact service for %s: %s\n"),
921 				    (printer ? printer : "all"),
922 				    verbose_papi_message(svc, status));
923 				return (-1);
924 			}
925 		}
926 
927 		if (printer == NULL) { /* all */
928 			char **interest = interest_list(svc);
929 
930 			if (interest != NULL) {
931 				int i;
932 
933 				for (i = 0; interest[i] != NULL; i++)
934 					result += job_query(interest[i], report,
935 					    encryption, show_rank, verbose);
936 			}
937 		} else if (id == -1) { /* a printer */
938 			papi_job_t *jobs = NULL;
939 
940 			status = papiPrinterListJobs(svc, printer, NULL,
941 			    0, 0, &jobs);
942 			if (status != PAPI_OK) {
943 				fprintf(stderr, gettext(
944 				    "Failed to get job list: %s\n"),
945 				    verbose_papi_message(svc, status));
946 				papiServiceDestroy(svc);
947 				return (-1);
948 			}
949 
950 			if (jobs != NULL) {
951 				int i;
952 
953 				for (i = 0; jobs[i] != NULL; i++)
954 					result += report(printer,
955 					    jobs[i], show_rank,
956 					    verbose);
957 			}
958 
959 			papiJobListFree(jobs);
960 		} else {	/* a job */
961 			papi_job_t job = NULL;
962 			int rid = id;
963 
964 			/* Once a job has been found stop processing */
965 			flag = 0;
966 
967 			/*
968 			 * Job-id could be the job-id requested
969 			 * Check if it is job-id or job-id-requested
970 			 */
971 			id = job_to_be_queried(svc, printer, id);
972 
973 			if (id > 0)
974 				status = papiJobQuery(svc, printer, id,
975 				    NULL, &job);
976 			else
977 				status = papiJobQuery(svc, printer, rid,
978 				    NULL, &job);
979 
980 			if (status != PAPI_OK) {
981 				if (!print_flag)
982 					fprintf(stderr, gettext(
983 					    "Failed to get job"\
984 					    " info for %s: %s\n"),
985 					    request,
986 					    verbose_papi_message(svc, status));
987 				papiServiceDestroy(svc);
988 				return (-1);
989 			}
990 
991 			if (job != NULL)
992 				result = report(printer, job,
993 				    show_rank, verbose);
994 
995 			papiJobFree(job);
996 		}
997 
998 		if (flag) {
999 			id = -1;
1000 			get_printer_id(printer, &printer, &id);
1001 			if (id == -1)
1002 				flag = 0;
1003 			else
1004 				flag1 = 1;
1005 		}
1006 	} while (flag);
1007 
1008 	papiServiceDestroy(svc);
1009 
1010 	return (result);
1011 }
1012 
1013 static int
1014 report_form(char *name, papi_attribute_t **attrs, int verbose)
1015 {
1016 	papi_status_t status;
1017 	char *form = NULL;
1018 	void *iter = NULL;
1019 
1020 	for (status = papiAttributeListGetString(attrs, &iter,
1021 	    "form-supported", &form);
1022 	    status == PAPI_OK;
1023 	    status = papiAttributeListGetString(attrs, &iter,
1024 	    NULL, &form)) {
1025 		if ((name == NULL) || (strcmp(name, form) == 0)) {
1026 			printf(gettext("form %s is available to you\n"), form);
1027 			if (verbose != 0) {
1028 				char *detail = NULL;
1029 				status = papiAttributeListGetString(attrs, NULL,
1030 				    "form-supported-detail", &detail);
1031 				if (status == PAPI_OK)
1032 					printf("%s\n", detail);
1033 			}
1034 		}
1035 	}
1036 
1037 	return (0);
1038 }
1039 
1040 static int
1041 report_print_wheels(char *name, papi_attribute_t **attrs, int verbose)
1042 {
1043 	papi_status_t status;
1044 	char *pw = NULL;
1045 	void *iter = NULL;
1046 
1047 	for (status = papiAttributeListGetString(attrs, &iter,
1048 	    "pw-supported", &pw);
1049 	    status == PAPI_OK;
1050 	    status = papiAttributeListGetString(attrs, &iter, NULL, &pw)) {
1051 		if ((name == NULL) || (strcmp(name, pw) == 0)) {
1052 			printf(gettext("charset %s is available\n"), pw);
1053 			if (verbose != 0) {
1054 				char *info = NULL;
1055 				status = papiAttributeListGetString(attrs, NULL,
1056 				    "pw-supported-extra", &info);
1057 				if (status == PAPI_OK)
1058 					printf("%s\n", info);
1059 			}
1060 		}
1061 	}
1062 
1063 	return (0);
1064 }
1065 
1066 static int
1067 service_query(char *name, int (*report)(char *, papi_attribute_t **, int),
1068 		papi_encryption_t encryption, int verbose)
1069 {
1070 	int result = 0;
1071 	papi_status_t status;
1072 	papi_service_t svc = NULL;
1073 	papi_attribute_t **attrs = NULL;
1074 
1075 	status = papiServiceCreate(&svc, name, NULL, NULL, cli_auth_callback,
1076 	    encryption, NULL);
1077 	if (status != PAPI_OK) {
1078 		papiServiceDestroy(svc);
1079 		return (-1);
1080 	}
1081 
1082 	attrs = papiServiceGetAttributeList(svc);
1083 	if (attrs != NULL) {
1084 		result = report(name, attrs, verbose);
1085 
1086 		if (verbose > 1) {
1087 			printf("\n");
1088 			papiAttributeListPrint(stdout, attrs, "\t");
1089 			printf("\n");
1090 		}
1091 	}
1092 
1093 	papiServiceDestroy(svc);
1094 
1095 	return (result);
1096 }
1097 
1098 int
1099 main(int ac, char *av[])
1100 {
1101 	int exit_code = 0;
1102 	papi_encryption_t encryption = PAPI_ENCRYPT_NEVER;
1103 	int rank = 0;
1104 	int verbose = 0;
1105 	int description = 0;
1106 	int c;
1107 	char **argv;
1108 
1109 	(void) setlocale(LC_ALL, "");
1110 	(void) textdomain("SUNW_OST_OSCMD");
1111 
1112 	argv = (char **)calloc((ac + 1), sizeof (char *));
1113 	for (c = 0; c < ac; c++) {
1114 		if ((av[c][0] == '-') && (av[c][1] == 'l') &&
1115 		    (isalpha(av[c][2]) != 0)) {
1116 			/* preserve old "-l[po...]" behavior */
1117 			argv[c] = &av[c][1];
1118 			argv[c][0] = '-';
1119 			verbose = 1;
1120 
1121 		} else
1122 			argv[c] = av[c];
1123 	}
1124 
1125 	argv[c++] = "--";
1126 	ac = c;
1127 
1128 	/* preprocess argument list looking for '-l' or '-R' so it can trail */
1129 	while ((c = getopt(ac, argv, "LEDf:S:stc:p:a:drs:v:l:o:R:u:")) != EOF) {
1130 		switch (c) {    /* these may or may not have an option */
1131 		case 'a':
1132 		case 'c':
1133 		case 'p':
1134 		case 'o':
1135 		case 'R':
1136 		case 'u':
1137 		case 'v':
1138 		case 'l':
1139 		case 'f':
1140 		case 'S':
1141 			if (optarg[0] == '-') {
1142 				/* this check stop a possible infinite loop */
1143 				if ((optind > 1) && (argv[optind-1][1] != c))
1144 					optind--;
1145 				optarg = NULL;
1146 			} else if (strcmp(optarg, "all") == 0)
1147 				optarg = NULL;
1148 		}
1149 
1150 		switch (c) {
1151 		case 'l':
1152 			if ((optarg == NULL) || (optarg[0] == '-'))
1153 				optarg = "1";
1154 			verbose = atoi(optarg);
1155 			break;
1156 		case 'D':
1157 			description = 1;
1158 			break;
1159 		case 'R':
1160 			rank = 1;
1161 			break;
1162 		case 'E':
1163 			encryption = PAPI_ENCRYPT_REQUIRED;
1164 			break;
1165 		default:
1166 			break;
1167 		}
1168 	}
1169 	optind = 1;
1170 
1171 	/* process command line arguments */
1172 	while ((c = getopt(ac, argv, "LEDf:S:stc:p:a:drs:v:l:o:R:u:")) != EOF) {
1173 		switch (c) {	/* these may or may not have an option */
1174 		case 'a':
1175 		case 'c':
1176 		case 'p':
1177 		case 'o':
1178 		case 'R':
1179 		case 'u':
1180 		case 'v':
1181 		case 'l':
1182 		case 'f':
1183 		case 'S':
1184 			if (optarg[0] == '-') {
1185 				/* this check stop a possible infinite loop */
1186 				if ((optind > 1) && (argv[optind-1][1] != c))
1187 					optind--;
1188 				optarg = NULL;
1189 			} else if (strcmp(optarg, "all") == 0)
1190 				optarg = NULL;
1191 		}
1192 
1193 		switch (c) {
1194 		case 'a':
1195 			exit_code += printer_query(optarg, report_accepting,
1196 			    encryption, verbose, 0);
1197 			break;
1198 		case 'c':
1199 			exit_code += printer_query(optarg, report_class,
1200 			    encryption, verbose, 0);
1201 			break;
1202 		case 'p':
1203 			exit_code += printer_query(optarg, report_printer,
1204 			    encryption, verbose, description);
1205 			break;
1206 		case 'd':
1207 			exit_code += lpstat_default_printer(encryption);
1208 			break;
1209 		case 'r':
1210 			exit_code += lpstat_service_status(encryption);
1211 			break;
1212 		case 'u':
1213 			if (optarg != NULL)
1214 				users = strsplit(optarg, ", \n");
1215 			exit_code += job_query(NULL, report_job,
1216 			    encryption, rank, verbose);
1217 			if (users != NULL) {
1218 				free(users);
1219 				users = NULL;
1220 			}
1221 			break;
1222 		case 'v':
1223 			exit_code += printer_query(optarg, report_device,
1224 			    encryption, verbose, 0);
1225 			break;
1226 		case 'R':	/* set "rank" flag in first pass */
1227 		case 'o':
1228 			exit_code += job_query(optarg, report_job,
1229 			    encryption, rank, verbose);
1230 			break;
1231 		case 'f':
1232 			exit_code += service_query(optarg, report_form,
1233 			    encryption, verbose);
1234 			break;
1235 		case 'S':
1236 			exit_code += service_query(optarg, report_print_wheels,
1237 			    encryption, verbose);
1238 			break;
1239 		case 's':
1240 			exit_code += lpstat_service_status(encryption);
1241 			exit_code += lpstat_default_printer(encryption);
1242 			exit_code += printer_query(NULL, report_class,
1243 			    encryption, verbose, 0);
1244 			exit_code += printer_query(NULL, report_device,
1245 			    encryption, verbose, 0);
1246 			exit_code += service_query(optarg, report_form,
1247 			    encryption, verbose);
1248 			exit_code += service_query(optarg, report_print_wheels,
1249 			    encryption, verbose);
1250 			break;
1251 		case 't':
1252 			exit_code += lpstat_service_status(encryption);
1253 			exit_code += lpstat_default_printer(encryption);
1254 			exit_code += printer_query(NULL, report_class,
1255 			    encryption, verbose, 0);
1256 			exit_code += printer_query(NULL, report_device,
1257 			    encryption, verbose, 0);
1258 			exit_code += printer_query(NULL, report_accepting,
1259 			    encryption, verbose, 0);
1260 			exit_code += printer_query(NULL, report_printer,
1261 			    encryption, verbose, 0);
1262 			exit_code += service_query(optarg, report_form,
1263 			    encryption, verbose);
1264 			exit_code += service_query(optarg, report_print_wheels,
1265 			    encryption, verbose);
1266 			exit_code += job_query(NULL, report_job,
1267 			    encryption, rank, verbose);
1268 			break;
1269 		case 'L':	/* local-only, ignored */
1270 		case 'l':	/* increased verbose level in first pass */
1271 		case 'D':	/* set "description" flag in first pass */
1272 		case 'E':	/* set encryption in the first pass */
1273 			break;
1274 		default:
1275 			usage(av[0]);
1276 		}
1277 	}
1278 	ac--;
1279 
1280 	if (ac == 1) {	/* report on my jobs */
1281 		struct passwd *pw = getpwuid(getuid());
1282 
1283 		if (pw != NULL)
1284 			users = strsplit(pw->pw_name, "");
1285 		exit_code += job_query(NULL, report_job, encryption,
1286 		    rank, verbose);
1287 		if (users != NULL) {
1288 			free(users);
1289 			users = NULL;
1290 		}
1291 	} else {
1292 		for (c = optind; c < ac; c++)
1293 			exit_code += job_query(argv[c], report_job, encryption,
1294 			    rank, verbose);
1295 	}
1296 
1297 
1298 	if (exit_code != 0)
1299 		exit_code = 1;
1300 
1301 	return (exit_code);
1302 }
1303