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