xref: /titanic_50/usr/src/cmd/print/bsd-sysv-commands/lpstat.c (revision a60fc142342386d0b786e65fba901234400d7020)
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 2007 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <locale.h>
37 #include <libintl.h>
38 #include <ctype.h>
39 #include <pwd.h>
40 #include <papi.h>
41 #include <uri.h>
42 #include "common.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 char *report_device_keys[] = { "printer-name", "printer-uri-supported",
162 					NULL };
163 /* ARGSUSED2 */
164 static int
165 report_device(papi_service_t svc, char *name, papi_printer_t printer,
166 		int verbose, int description)
167 {
168 	papi_status_t status;
169 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
170 	char *uri = NULL;
171 	char *device = NULL;
172 	uri_t *u = NULL;
173 
174 	if (name == NULL) {
175 		status = papiAttributeListGetString(attrs, NULL,
176 					"printer-name", &name);
177 		if (status != PAPI_OK)
178 			status = papiAttributeListGetString(attrs, NULL,
179 					"printer-uri-supported", &name);
180 	}
181 
182 	if (name == NULL)
183 		return (-1);
184 
185 	(void) papiAttributeListGetString(attrs, NULL,
186 					"printer-uri-supported", &uri);
187 
188 	if ((uri != NULL) && (uri_from_string(uri, &u) == 0)) {
189 		char *nodename = localhostname();
190 
191 		if ((u->host == NULL) ||
192 		    (strcasecmp(u->host, "localhost") == 0) ||
193 		    (strcasecmp(u->host, nodename) == 0))
194 			device = get_device_uri(svc, name);
195 
196 		if (device != NULL) {
197 			printf(gettext("device for %s: %s\n"), name, device);
198 			return (0);
199 		} else if (uri != NULL) {
200 			printf(gettext("system for %s: %s (as %s)\n"), name,
201 				u->host, uri);
202 			return (0);
203 		}
204 
205 		uri_free(u);
206 	}
207 
208 	return (0);
209 }
210 
211 static char *report_accepting_keys[] = { "printer-name",
212 			"printer-uri-supported", "printer-is-accepting-jobs",
213 			"printer-up-time", "printer-state-time",
214 			"lpsched-reject-date", "lpsched-reject-reason", NULL };
215 /* ARGSUSED2 */
216 static int
217 report_accepting(papi_service_t svc, char *name, papi_printer_t printer,
218 		int verbose, int description)
219 {
220 	papi_status_t status;
221 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
222 	time_t curr;
223 	char boolean = PAPI_FALSE;
224 
225 	if (name == NULL) {
226 		status = papiAttributeListGetString(attrs, NULL,
227 					"printer-name", &name);
228 		if (status != PAPI_OK)
229 			status = papiAttributeListGetString(attrs, NULL,
230 					"printer-uri-supported", &name);
231 	}
232 	if (name == NULL)
233 		return (-1);
234 
235 	(void) papiAttributeListGetBoolean(attrs, NULL,
236 				"printer-is-accepting-jobs", &boolean);
237 	(void) time(&curr);
238 	(void) papiAttributeListGetDatetime(attrs, NULL,
239 					"printer-up-time", &curr);
240 	(void) papiAttributeListGetDatetime(attrs, NULL,
241 					"printer-state-time", &curr);
242 	(void) papiAttributeListGetDatetime(attrs, NULL,
243 					"lpsched-reject-date", &curr);
244 
245 	if (boolean == PAPI_TRUE) {
246 		printf(gettext("%s accepting requests since %s\n"),
247 			name, nctime(&curr));
248 	} else {
249 		char *reason = "unknown reason";
250 
251 		(void) papiAttributeListGetString(attrs, NULL,
252 					"lpsched-reject-reason", &reason);
253 
254 		printf(gettext("%s not accepting requests since %s\n\t%s\n"),
255 			name, nctime(&curr), reason);
256 	}
257 
258 	return (0);
259 }
260 
261 static char *report_class_keys[] = { "printer-name", "printer-uri-supported",
262 					"member-names", NULL };
263 /* ARGSUSED2 */
264 static int
265 report_class(papi_service_t svc, char *name, papi_printer_t printer,
266 		int verbose, int description)
267 {
268 	papi_status_t status;
269 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
270 	char *member = NULL;
271 	void *iter = NULL;
272 
273 	status = papiAttributeListGetString(attrs, &iter,
274 				"member-names", &member);
275 	if (status == PAPI_NOT_FOUND)	/* it's not a class */
276 		return (0);
277 
278 	if (name == NULL) {
279 		status = papiAttributeListGetString(attrs, NULL,
280 					"printer-name", &name);
281 		if (status != PAPI_OK)
282 			status = papiAttributeListGetString(attrs, NULL,
283 					"printer-uri-supported", &name);
284 	}
285 	if (name == NULL)
286 		return (-1);
287 
288 	printf(gettext("members of class %s:\n\t%s\n"), name, member);
289 	while (papiAttributeListGetString(attrs, &iter, NULL, &member)
290 			== PAPI_OK)
291 		printf("\t%s\n", member);
292 
293 	return (0);
294 }
295 
296 static char *report_printer_keys[] = { "printer-name",
297 			"printer-uri-supported", "printer-state",
298 			"printer-up-time", "printer-state-time",
299 			"lpsched-disable-date", "printer-state-reasons",
300 			"lpsched-disable-reason", NULL };
301 /* ARGSUSED2 */
302 static int
303 report_printer(papi_service_t svc, char *name, papi_printer_t printer,
304 		int verbose, int description)
305 {
306 	papi_status_t status;
307 	papi_attribute_t **attrs = papiPrinterGetAttributeList(printer);
308 	time_t curr;
309 	int32_t pstat = 0;
310 	char *member = NULL;
311 
312 	status = papiAttributeListGetString(attrs, NULL,
313 				"member-names", &member);
314 	if (status == PAPI_OK)	/* it's a class */
315 		return (0);
316 
317 	if (name == NULL) {
318 		status = papiAttributeListGetString(attrs, NULL,
319 					"printer-name", &name);
320 		if (status != PAPI_OK)
321 			status = papiAttributeListGetString(attrs, NULL,
322 					"printer-uri-supported", &name);
323 	}
324 	if (name == NULL)
325 		return (-1);
326 
327 	printf(gettext("printer %s "), name);
328 
329 	status = papiAttributeListGetInteger(attrs, NULL,
330 					"printer-state", &pstat);
331 
332 	switch (pstat) {
333 	case 0x03:	/* idle */
334 		printf(gettext("idle. enabled"));
335 		break;
336 	case 0x04: {	/* processing */
337 		char *requested[] = { "job-id", NULL };
338 		papi_job_t *j = NULL;
339 		int32_t jobid = 0;
340 
341 		(void) papiPrinterListJobs(svc, name, requested, 0, 1, &j);
342 		if ((j != NULL) && (j[0] != NULL))
343 			jobid = papiJobGetId(j[0]);
344 		papiJobListFree(j);
345 
346 		printf(gettext("now printing %s-%d. enabled"), name, jobid);
347 		}
348 		break;
349 	case 0x05:	/* stopped */
350 		printf(gettext("disabled"));
351 		break;
352 	default:
353 		printf(gettext("unknown state(0x%x)."), pstat);
354 		break;
355 	}
356 
357 	(void) time(&curr);
358 	(void) papiAttributeListGetDatetime(attrs, NULL,
359 					"printer-up-time", &curr);
360 	(void) papiAttributeListGetDatetime(attrs, NULL,
361 					"printer-state-time", &curr);
362 	(void) papiAttributeListGetDatetime(attrs, NULL,
363 					"lpsched-disable-date", &curr);
364 	printf(gettext(" since %s. available.\n"), nctime(&curr));
365 
366 	if (pstat == 0x05) {
367 		char *reason = "unknown reason";
368 
369 		(void) papiAttributeListGetString(attrs, NULL,
370 					"printer-state-reasons", &reason);
371 		(void) papiAttributeListGetString(attrs, NULL,
372 					"lpsched-disable-reason", &reason);
373 		printf(gettext("\t%s\n"), reason);
374 	}
375 
376 	if (verbose == 1) {
377 		void *iter;
378 		char *str;
379 
380 		str = "";
381 		(void) papiAttributeListGetString(attrs, NULL,
382 					"form-ready", &str);
383 		printf(gettext("\tForm mounted: %s\n"), str);
384 
385 		str = "";
386 		iter = NULL;
387 		(void) papiAttributeListGetString(attrs, &iter,
388 					"document-format-supported", &str);
389 		printf(gettext("\tContent types: %s"), str);
390 		while (papiAttributeListGetString(attrs, &iter, NULL, &str)
391 				== PAPI_OK)
392 			printf(", %s", str);
393 		printf("\n");
394 
395 		str = "";
396 		(void) papiAttributeListGetString(attrs, NULL,
397 					"printer-info", &str);
398 		printf(gettext("\tDescription: %s\n"), str);
399 
400 		str = "";
401 		(void) papiAttributeListGetString(attrs, NULL,
402 					"lpsched-dial-info", &str);
403 		printf(gettext("\tConnection: %s\n"),
404 			((str[0] != '\0') ? gettext("direct") : str));
405 
406 		str = "";
407 		(void) papiAttributeListGetString(attrs, NULL,
408 					"lpsched-interface-script", &str);
409 		printf(gettext("\tInterface: %s\n"), str);
410 
411 		str = NULL;
412 		(void) papiAttributeListGetString(attrs, NULL,
413 					"ppd-file-uri", &str);
414 		(void) papiAttributeListGetString(attrs, NULL,
415 					"lpsched-ppd-source-path", &str);
416 		if (str != NULL)
417 			printf(gettext("\tPPD: %s\n"), str);
418 
419 		str = NULL;
420 		(void) papiAttributeListGetString(attrs, NULL,
421 					"lpsched-fault-alert-command", &str);
422 		if (str != NULL)
423 			printf(gettext("\tOn fault: %s\n"), str);
424 
425 		str = "";
426 		(void) papiAttributeListGetString(attrs, NULL,
427 					"lpsched-fault-recovery", &str);
428 		printf(gettext("\tAfter fault: %s\n"),
429 			((str[0] == '\0') ? gettext("continue") : str));
430 
431 		str = "(all)";
432 		iter = NULL;
433 		(void) papiAttributeListGetString(attrs, &iter,
434 					"requesting-user-name-allowed", &str);
435 		printf(gettext("\tUsers allowed:\n\t\t%s\n"),
436 			((str[0] == '\0') ? gettext("(none)") : str));
437 		if ((str != NULL) && (str[0] != '\0'))
438 			while (papiAttributeListGetString(attrs, &iter, NULL,
439 					&str) == PAPI_OK)
440 				printf("\t\t%s\n", str);
441 
442 		str = NULL;
443 		iter = NULL;
444 		(void) papiAttributeListGetString(attrs, &iter,
445 					"requesting-user-name-denied", &str);
446 		if (str != NULL) {
447 			printf(gettext("\tUsers denied:\n\t\t%s\n"),
448 				((str[0] == '\0') ? gettext("(none)") : str));
449 			if ((str != NULL) && (str[0] != '\0'))
450 				while (papiAttributeListGetString(attrs, &iter,
451 						NULL, &str) == PAPI_OK)
452 					printf("\t\t%s\n", str);
453 		}
454 
455 		str = "(none)";
456 		iter = NULL;
457 		(void) papiAttributeListGetString(attrs, &iter,
458 					"form-supported", &str);
459 		printf(gettext("\tForms allowed:\n\t\t%s\n"),
460 			((str[0] == '\0') ? gettext("(none)") : str));
461 		if ((str != NULL) && (str[0] != '\0'))
462 			while (papiAttributeListGetString(attrs, &iter, NULL,
463 					&str) == PAPI_OK)
464 				printf("\t\t%s\n", str);
465 
466 		str = "";
467 		iter = NULL;
468 		(void) papiAttributeListGetString(attrs, &iter,
469 					"media-supported", &str);
470 		printf(gettext("\tMedia supported:\n\t\t%s\n"),
471 			((str[0] == '\0') ? gettext("(none)") : str));
472 		if ((str != NULL) && (str[0] != '\0'))
473 			while (papiAttributeListGetString(attrs, &iter, NULL,
474 					&str) == PAPI_OK)
475 				printf("\t\t%s\n", str);
476 
477 		str = "";
478 		(void) papiAttributeListGetString(attrs, NULL,
479 					"job-sheets-supported", &str);
480 		printf(gettext("\tBanner %s\n"),
481 			(strcasecmp(str, "none") == 0 ?
482 				gettext("not required") : gettext("required")));
483 
484 		str = "";
485 		iter = NULL;
486 		(void) papiAttributeListGetString(attrs, &iter,
487 					"lpsched-print-wheels", &str);
488 		printf(gettext("\tCharacter sets:\n\t\t%s\n"),
489 			((str[0] == '\0') ? gettext("(none)") : str));
490 		if ((str != NULL) && (str[0] != '\0'))
491 			while (papiAttributeListGetString(attrs, &iter, NULL,
492 					&str) == PAPI_OK)
493 				printf("\t\t%s\n", str);
494 
495 		printf(gettext("\tDefault pitch:\n"));
496 		printf(gettext("\tDefault page size:\n"));
497 		printf(gettext("\tDefault port setting:\n"));
498 
499 		str = "";
500 		iter = NULL;
501 		(void) papiAttributeListGetString(attrs, &iter,
502 					"lpsched-options", &str);
503 		if (str != NULL) {
504 			printf(gettext("\tOptions: %s"), str);
505 			while (papiAttributeListGetString(attrs, &iter, NULL,
506 						&str) == PAPI_OK)
507 				printf(", %s", str);
508 			printf("\n");
509 		}
510 
511 	} else if (description == 1) {
512 		char *str = "";
513 		(void) papiAttributeListGetString(attrs, NULL,
514 					"printer-description", &str);
515 		printf(gettext("\tDescription: %s\n"), str);
516 	} else if (verbose > 1)
517 		papiAttributeListPrint(stdout, attrs, "\t");
518 
519 	if (verbose > 0)
520 		printf("\n");
521 
522 	return (0);
523 }
524 
525 static int
526 printer_query(char *name, int (*report)(papi_service_t, char *, papi_printer_t,
527 					int, int), papi_encryption_t encryption,
528 		int verbose, int description)
529 {
530 	int result = 0;
531 	papi_status_t status;
532 	papi_service_t svc = NULL;
533 
534 	status = papiServiceCreate(&svc, name, NULL, NULL, cli_auth_callback,
535 					encryption, NULL);
536 	if (status != PAPI_OK) {
537 		if (status == PAPI_NOT_FOUND)
538 			fprintf(stderr, gettext("%s: unknown printer\n"),
539 				name ? name : "(NULL)");
540 		else
541 			fprintf(stderr, gettext(
542 				"Failed to contact service for %s: %s\n"),
543 				name ? name : "(NULL)",
544 				verbose_papi_message(svc, status));
545 		papiServiceDestroy(svc);
546 		return (-1);
547 	}
548 
549 	if (name == NULL) { /* all */
550 		char **interest = interest_list(svc);
551 
552 		if (interest != NULL) {
553 			int i;
554 
555 			for (i = 0; interest[i] != NULL; i++)
556 				result += printer_query(interest[i], report,
557 							encryption, verbose,
558 							description);
559 		}
560 	} else {
561 		papi_printer_t printer = NULL;
562 		char **keys = NULL;
563 
564 		/*
565 		 * Limit the query to only required data to reduce the need
566 		 * to go remote for information.
567 		 */
568 		if (report == report_device)
569 			keys = report_device_keys;
570 		else if (report == report_class)
571 			keys = report_class_keys;
572 		else if (report == report_accepting)
573 			keys = report_accepting_keys;
574 		else if ((report == report_printer) && (verbose == 0))
575 			keys = report_printer_keys;
576 
577 		status = papiPrinterQuery(svc, name, keys, NULL, &printer);
578 		if (status != PAPI_OK) {
579 			fprintf(stderr, gettext(
580 				"Failed to get printer info for %s: %s\n"),
581 				name, verbose_papi_message(svc, status));
582 			papiServiceDestroy(svc);
583 			return (-1);
584 		}
585 
586 		if (printer != NULL)
587 			result = report(svc, name, printer, verbose,
588 					description);
589 
590 		papiPrinterFree(printer);
591 	}
592 
593 	papiServiceDestroy(svc);
594 
595 	return (result);
596 }
597 
598 static int
599 match_user(char *user, char **list)
600 {
601 	int i;
602 
603 	for (i = 0; list[i] != NULL; i++) {
604 		if (strcmp(user, list[i]) == 0)
605 			return (0);
606 	}
607 
608 	return (-1);
609 }
610 
611 static char **users = NULL;
612 
613 static int
614 report_job(papi_job_t job, int show_rank, int verbose)
615 {
616 	papi_attribute_t **attrs = papiJobGetAttributeList(job);
617 	time_t clock = 0;
618 	char date[24];
619 	char request[26];
620 	char *user = "unknown";
621 	int32_t size = 0;
622 	int32_t jstate = 0;
623 
624 	char *destination = "unknown";
625 	int32_t id = -1;
626 
627 	(void) papiAttributeListGetString(attrs, NULL,
628 				"job-originating-user-name", &user);
629 
630 	if ((users != NULL) && (match_user(user, users) < 0))
631 		return (0);
632 
633 	(void) papiAttributeListGetInteger(attrs, NULL, "job-k-octets", &size);
634 	size *= 1024;	/* for the approximate byte size */
635 	(void) papiAttributeListGetInteger(attrs, NULL, "job-octets", &size);
636 
637 	(void) time(&clock);
638 	(void) papiAttributeListGetInteger(attrs, NULL,
639 				"time-at-creation", (int32_t *)&clock);
640 	(void) strftime(date, sizeof (date), "%b %d %R", localtime(&clock));
641 
642 	(void) papiAttributeListGetString(attrs, NULL,
643 				"job-printer-uri", &destination);
644 	(void) papiAttributeListGetString(attrs, NULL,
645 				"printer-name", &destination);
646 	(void) papiAttributeListGetInteger(attrs, NULL,
647 				"job-id", &id);
648 	snprintf(request, sizeof (request), "%s-%d", destination, id);
649 
650 	if (show_rank != 0) {
651 		int32_t rank = -1;
652 
653 		(void) papiAttributeListGetInteger(attrs, NULL,
654 				"number-of-intervening-jobs", &rank);
655 		rank++;
656 
657 		printf("%3d %-21s %-14s %7ld %s",
658 			rank, request, user, size, date);
659 	} else
660 		printf("%-23s %-14s %7ld   %s", request, user, size, date);
661 
662 	(void) papiAttributeListGetInteger(attrs, NULL,
663 				"job-state", &jstate);
664 	if (jstate == 0x04)
665 		printf(gettext(", being held"));
666 	else if (jstate == 0x07)
667 		printf(gettext(", cancelled"));
668 	else if (jstate == 0x09)
669 		printf(gettext(", complete"));
670 
671 	if (verbose == 1) {
672 		char *form = NULL;
673 
674 		(void) papiAttributeListGetString(attrs, NULL,
675 				"output-device-assigned", &destination);
676 		printf("\n\t assigned %s", destination);
677 
678 		(void) papiAttributeListGetString(attrs, NULL, "form", &form);
679 		if (form != NULL)
680 			printf(", form %s", form);
681 	} else if (verbose > 1) {
682 		printf("\n");
683 		papiAttributeListPrint(stdout, attrs, "\t");
684 	}
685 
686 	printf("\n");
687 
688 	return (0);
689 }
690 
691 static int
692 job_query(char *request, int (*report)(papi_job_t, int, int),
693 		papi_encryption_t encryption, int show_rank, int verbose)
694 {
695 	int result = 0;
696 	papi_status_t status;
697 	papi_service_t svc = NULL;
698 	char *printer = NULL;
699 	int32_t id = -1;
700 
701 	get_printer_id(request, &printer, &id);
702 
703 	status = papiServiceCreate(&svc, printer, NULL, NULL, cli_auth_callback,
704 					encryption, NULL);
705 	if (status != PAPI_OK) {
706 		fprintf(stderr, gettext(
707 			"Failed to contact service for %s: %s\n"),
708 			(printer ? printer : "all"),
709 			verbose_papi_message(svc, status));
710 		return (-1);
711 	}
712 
713 	if (printer == NULL) { /* all */
714 		char **interest = interest_list(svc);
715 
716 		if (interest != NULL) {
717 			int i;
718 
719 			for (i = 0; interest[i] != NULL; i++)
720 				result += job_query(interest[i], report,
721 						encryption, show_rank, verbose);
722 		}
723 	} else if (id == -1) { /* a printer */
724 		papi_job_t *jobs = NULL;
725 
726 		status = papiPrinterListJobs(svc, printer, NULL, 0, 0, &jobs);
727 		if (status != PAPI_OK) {
728 			fprintf(stderr, gettext(
729 				"Failed to get job list: %s\n"),
730 				verbose_papi_message(svc, status));
731 			papiServiceDestroy(svc);
732 			return (-1);
733 		}
734 
735 		if (jobs != NULL) {
736 			int i;
737 
738 			for (i = 0; jobs[i] != NULL; i++)
739 				result += report(jobs[i], show_rank, verbose);
740 		}
741 
742 		papiJobListFree(jobs);
743 	} else {	/* a job */
744 		papi_job_t job = NULL;
745 
746 		status = papiJobQuery(svc, printer, id, NULL, &job);
747 		if (status != PAPI_OK) {
748 			fprintf(stderr, gettext(
749 				"Failed to get job info for %s: %s\n"),
750 				request, verbose_papi_message(svc, status));
751 			papiServiceDestroy(svc);
752 			return (-1);
753 		}
754 
755 		if (job != NULL)
756 			result = report(job, show_rank, verbose);
757 
758 		papiJobFree(job);
759 	}
760 
761 	papiServiceDestroy(svc);
762 
763 	return (result);
764 }
765 
766 static int
767 report_form(char *name, papi_attribute_t **attrs, int verbose)
768 {
769 	papi_status_t status;
770 	char *form = NULL;
771 	void *iter = NULL;
772 
773 	for (status = papiAttributeListGetString(attrs, &iter,
774 					"form-supported", &form);
775 		status == PAPI_OK;
776 		status = papiAttributeListGetString(attrs, &iter,
777 							NULL, &form)) {
778 		if ((name == NULL) || (strcmp(name, form) == 0)) {
779 			printf(gettext("form %s is available to you\n"), form);
780 			if (verbose != 0) {
781 				char *detail = NULL;
782 				status = papiAttributeListGetString(attrs, NULL,
783 						"form-supported-detail",
784 						&detail);
785 				if (status == PAPI_OK)
786 					printf("%s\n", detail);
787 			}
788 		}
789 	}
790 
791 	return (0);
792 }
793 
794 static int
795 report_print_wheels(char *name, papi_attribute_t **attrs, int verbose)
796 {
797 	papi_status_t status;
798 	char *pw = NULL;
799 	void *iter = NULL;
800 
801 	for (status = papiAttributeListGetString(attrs, &iter,
802 					"pw-supported", &pw);
803 		status == PAPI_OK;
804 		status = papiAttributeListGetString(attrs, &iter, NULL, &pw)) {
805 		if ((name == NULL) || (strcmp(name, pw) == 0)) {
806 			printf(gettext("charset %s is available\n"), pw);
807 			if (verbose != 0) {
808 				char *info = NULL;
809 				status = papiAttributeListGetString(attrs, NULL,
810 						"pw-supported-extra", &info);
811 				if (status == PAPI_OK)
812 					printf("%s\n", info);
813 			}
814 		}
815 	}
816 
817 	return (0);
818 }
819 
820 static int
821 service_query(char *name, int (*report)(char *, papi_attribute_t **, int),
822 		papi_encryption_t encryption, int verbose)
823 {
824 	int result = 0;
825 	papi_status_t status;
826 	papi_service_t svc = NULL;
827 	papi_attribute_t **attrs = NULL;
828 
829 	status = papiServiceCreate(&svc, name, NULL, NULL, cli_auth_callback,
830 					encryption, NULL);
831 	if (status != PAPI_OK) {
832 		papiServiceDestroy(svc);
833 		return (-1);
834 	}
835 
836 	attrs = papiServiceGetAttributeList(svc);
837 	if (attrs != NULL) {
838 		result = report(name, attrs, verbose);
839 
840 		if (verbose > 1) {
841 			printf("\n");
842 			papiAttributeListPrint(stdout, attrs, "\t");
843 			printf("\n");
844 		}
845 	}
846 
847 	papiServiceDestroy(svc);
848 
849 	return (result);
850 }
851 
852 int
853 main(int ac, char *av[])
854 {
855 	int exit_code = 0;
856 	papi_encryption_t encryption = PAPI_ENCRYPT_NEVER;
857 	int rank = 0;
858 	int verbose = 0;
859 	int description = 0;
860 	int c;
861 	char **argv;
862 
863 	(void) setlocale(LC_ALL, "");
864 	(void) textdomain("SUNW_OST_OSCMD");
865 
866 	argv = (char **)calloc((ac + 1), sizeof (char *));
867 	for (c = 0; c < ac; c++) {
868 		if ((av[c][0] == '-') && (av[c][1] == 'l') &&
869 			(isalpha(av[c][2]) != 0)) {
870 			/* preserve old "-l[po...]" behavior */
871 			argv[c] = &av[c][1];
872 			argv[c][0] = '-';
873 			verbose = 1;
874 
875 		} else
876 			argv[c] = av[c];
877 	}
878 
879 	argv[c++] = "--";
880 	ac = c;
881 
882 	/* preprocess argument list looking for '-l' or '-R' so it can trail */
883 	while ((c = getopt(ac, argv, "LEDf:S:stc:p:a:drs:v:l:o:R:u:")) != EOF)
884 		switch (c) {
885 		case 'l':
886 			if ((optarg == NULL) || (optarg[0] == '-'))
887 				optarg = "1";
888 			verbose = atoi(optarg);
889 			break;
890 		case 'D':
891 			description = 1;
892 			break;
893 		case 'R':
894 			rank = 1;
895 			break;
896 		case 'E':
897 			encryption = PAPI_ENCRYPT_REQUIRED;
898 			break;
899 		default:
900 			break;
901 		}
902 	optind = 1;
903 
904 	/* process command line arguments */
905 	while ((c = getopt(ac, argv, "LEDf:S:stc:p:a:drs:v:l:o:R:u:")) != EOF) {
906 		switch (c) {	/* these may or may not have an option */
907 		case 'a':
908 		case 'c':
909 		case 'p':
910 		case 'o':
911 		case 'R':
912 		case 'u':
913 		case 'v':
914 		case 'l':
915 		case 'f':
916 		case 'S':
917 			if (optarg[0] == '-') {
918 				/* this check stop a possible infinite loop */
919 				if ((optind > 1) && (argv[optind-1][1] != c))
920 					optind--;
921 				optarg = NULL;
922 			} else if (strcmp(optarg, "all") == 0)
923 				optarg = NULL;
924 		}
925 
926 		switch (c) {
927 		case 'a':
928 			exit_code += printer_query(optarg, report_accepting,
929 						encryption, verbose, 0);
930 			break;
931 		case 'c':
932 			exit_code += printer_query(optarg, report_class,
933 						encryption, verbose, 0);
934 			break;
935 		case 'p':
936 			exit_code += printer_query(optarg, report_printer,
937 						encryption, verbose,
938 						description);
939 			break;
940 		case 'd':
941 			exit_code += lpstat_default_printer(encryption);
942 			break;
943 		case 'r':
944 			exit_code += lpstat_service_status(encryption);
945 			break;
946 		case 'u':
947 			if (optarg != NULL)
948 				users = strsplit(optarg, ", \n");
949 			exit_code += job_query(NULL, report_job,
950 						encryption, rank, verbose);
951 			if (users != NULL) {
952 				free(users);
953 				users = NULL;
954 			}
955 			break;
956 		case 'v':
957 			exit_code += printer_query(optarg, report_device,
958 						encryption, verbose, 0);
959 			break;
960 		case 'o':
961 			exit_code += job_query(optarg, report_job,
962 						encryption, rank, verbose);
963 			break;
964 		case 'f':
965 			exit_code += service_query(optarg, report_form,
966 						encryption, verbose);
967 			break;
968 		case 'S':
969 			exit_code += service_query(optarg, report_print_wheels,
970 						encryption, verbose);
971 			break;
972 		case 's':
973 			exit_code += lpstat_service_status(encryption);
974 			exit_code += lpstat_default_printer(encryption);
975 			exit_code += printer_query(NULL, report_class,
976 						encryption, verbose, 0);
977 			exit_code += printer_query(NULL, report_device,
978 						encryption, verbose, 0);
979 			exit_code += service_query(optarg, report_form,
980 						encryption, verbose);
981 			exit_code += service_query(optarg, report_print_wheels,
982 						encryption, verbose);
983 			break;
984 		case 't':
985 			exit_code += lpstat_service_status(encryption);
986 			exit_code += lpstat_default_printer(encryption);
987 			exit_code += printer_query(NULL, report_class,
988 						encryption, verbose, 0);
989 			exit_code += printer_query(NULL, report_device,
990 						encryption, verbose, 0);
991 			exit_code += printer_query(NULL, report_accepting,
992 						encryption, verbose, 0);
993 			exit_code += printer_query(NULL, report_printer,
994 						encryption, verbose, 0);
995 			exit_code += service_query(optarg, report_form,
996 						encryption, verbose);
997 			exit_code += service_query(optarg, report_print_wheels,
998 						encryption, verbose);
999 			exit_code += job_query(NULL, report_job,
1000 						encryption, rank, verbose);
1001 			break;
1002 		case 'L':	/* local-only, ignored */
1003 		case 'l':	/* increased verbose level in first pass */
1004 		case 'D':	/* set "description" flag in first pass */
1005 		case 'R':	/* set "rank" flag in first pass */
1006 		case 'E':	/* set encryption in the first pass */
1007 			break;
1008 		default:
1009 			usage(av[0]);
1010 		}
1011 	}
1012 	ac--;
1013 
1014 	if (ac == 1) {	/* report on my jobs */
1015 		struct passwd *pw = getpwuid(getuid());
1016 
1017 		if (pw != NULL)
1018 			users = strsplit(pw->pw_name, "");
1019 		exit_code += job_query(NULL, report_job, encryption,
1020 					rank, verbose);
1021 		if (users != NULL) {
1022 			free(users);
1023 			users = NULL;
1024 		}
1025 	} else {
1026 		for (c = optind; c < ac; c++)
1027 			exit_code += job_query(argv[c], report_job, encryption,
1028 					rank, verbose);
1029 	}
1030 
1031 
1032 	if (exit_code != 0)
1033 		exit_code = 1;
1034 
1035 	return (exit_code);
1036 }
1037