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.
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.
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]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 /* $Id: common.c 162 2006-05-08 14:17:44Z njacobs $ */
33 #include <sys/types.h>
44 #ifndef HAVE_GETPASSPHRASE /* some systems don't have getpassphrase() */
45 #define getpassphrase getpass
48 /* give the most verbose error message to the caller */
50 verbose_papi_message(papi_service_t svc
, papi_status_t status
)
54 mesg
= papiServiceGetStatusMessage(svc
);
57 mesg
= papiStatusString(status
);
63 match_job(int id
, char *user
, int ac
, char *av
[])
67 for (i
= 0; i
< ac
; i
++)
68 if (strcmp("-", av
[i
]) == 0)
69 return (0); /* "current" user match */
70 else if ((isdigit(av
[i
][0]) != 0) && (id
== atoi(av
[i
])))
71 return (0); /* job-id match */
72 else if (strcmp(user
, av
[i
]) == 0)
73 return (0); /* user match */
79 * return 0 : argument passed is job-id && job-id matches
80 * or argument passed is user
83 match_job_rid(int id
, int ac
, char *av
[])
87 for (i
= 0; i
< ac
; i
++)
88 if (isdigit(av
[i
][0]) != 0) {
89 if (id
== atoi(av
[i
]))
93 /* argument passed is user */
102 { "text/plain", "simple" },
103 { "application/octet-stream", "raw" },
104 { "application/octet-stream", "any" },
105 { "application/postscript", "postscript" },
106 { "application/postscript", "ps" },
107 { "application/x-cif", "cif" },
108 { "application/x-dvi", "dvi" },
109 { "application/x-plot", "plot" },
110 { "application/x-ditroff", "troff" },
111 { "application/x-troff", "otroff" },
112 { "application/x-pr", "pr" },
113 { "application/x-fortran", "fortran" },
114 { "application/x-raster", "raster" },
119 lp_type_to_mime_type(char *lp_type
)
124 return ("application/octet-stream");
126 for (i
= 0; type_map
[i
].lp_type
!= NULL
; i
++)
127 if (strcasecmp(type_map
[i
].lp_type
, lp_type
) == 0)
128 return (type_map
[i
].mime_type
);
134 * to support job/printer status
137 state_string(int state
)
141 return (gettext("idle"));
143 return (gettext("processing"));
145 return (gettext("stopped"));
147 return (gettext("unknown"));
151 static char *_rank_suffixes
[] = {
152 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"
156 rank_string(const int rank
)
161 snprintf(buf
, sizeof (buf
), gettext("invalid"));
163 snprintf(buf
, sizeof (buf
), gettext("active"));
164 else if ((rank
> 10) && (rank
< 14))
165 sprintf(buf
, "%dth", rank
);
167 sprintf(buf
, "%d%s", rank
, _rank_suffixes
[rank
% 10]);
173 printer_state_line(FILE *fp
, papi_printer_t p
, int num_jobs
, char *name
)
175 papi_attribute_t
**list
= papiPrinterGetAttributeList(p
);
179 (void) papiAttributeListGetInteger(list
, NULL
,
180 "printer-state", &state
);
181 (void) papiAttributeListGetString(list
, NULL
,
182 "printer-state-reasons", &reason
);
183 (void) papiAttributeListGetString(list
, NULL
,
184 "printer-name", &name
);
186 if ((state
!= 0x03) || (num_jobs
!= 0)) {
187 fprintf(fp
, "%s: %s", name
, state_string(state
));
188 if ((state
== 0x05) ||
191 (state
== 0x08)) /* stopped */
192 fprintf(fp
, ": %s\n", reason
);
196 fprintf(fp
, "no entries\n");
200 print_header(FILE *fp
)
202 fprintf(fp
, gettext("Rank\tOwner\t Job\tFile(s)\t\t\t\tTotal Size\n"));
206 print_job_line(FILE *fp
, int count
, papi_job_t job
, int fmt
, int ac
, char *av
[])
208 papi_attribute_t
**list
= papiJobGetAttributeList(job
);
209 int copies
= 1, id
= 0, rank
= count
, size
= 0;
210 char *name
= "print job";
211 char *user
= "nobody";
212 char *host
= "localhost";
215 (void) papiAttributeListGetInteger(list
, NULL
,
217 (void) papiAttributeListGetInteger(list
, NULL
,
218 "job-id-requested", &id
);
219 (void) papiAttributeListGetString(list
, NULL
,
220 "job-originating-user-name", &user
);
221 (void) papiAttributeListGetString(list
, NULL
,
222 "job-originating-host-name", &host
);
224 /* if we are looking and it doesn't match, return early */
225 if ((ac
> 0) && (match_job(id
, user
, ac
, av
) < 0))
228 (void) papiAttributeListGetInteger(list
, NULL
,
230 (void) papiAttributeListGetInteger(list
, NULL
,
231 "number-of-intervening-jobs", &rank
);
233 if (papiAttributeListGetInteger(list
, NULL
, "job-octets", &size
)
237 (void) papiAttributeListGetInteger(list
, NULL
,
238 "job-k-octets", &size
);
239 (void) papiAttributeListGetString(list
, NULL
,
245 fprintf(fp
, gettext("%s\t%-8.8s %d\t%-32.32s%d %s\n"),
246 rank_string(++rank
), user
, id
, name
, size
, suffix
);
249 "\n%s: %s\t\t\t\t[job %d %s]\n\t%-32.32s\t%d %s\n"),
250 user
, rank_string(++rank
), id
, host
, name
, size
,
255 * to support job cancelation
258 cancel_job(papi_service_t svc
, FILE *fp
, char *printer
, papi_job_t job
,
261 papi_status_t status
;
262 papi_attribute_t
**list
= papiJobGetAttributeList(job
);
266 char *mesg
= gettext("cancelled");
269 papiAttributeListGetInteger(list
, NULL
,
271 papiAttributeListGetInteger(list
, NULL
,
272 "job-id-requested", &rid
);
273 papiAttributeListGetString(list
, NULL
,
274 "job-originating-user-name", &user
);
276 /* if we are looking and it doesn't match, return early */
277 if ((ac
> 0) && (match_job(id
, user
, ac
, av
) < 0) &&
278 (match_job(rid
, user
, ac
, av
) < 0))
282 * A remote lpd job should be cancelled only based on
286 if (match_job_rid(rid
, ac
, av
) == -1)
287 /* job-id mismatch */
291 status
= papiJobCancel(svc
, printer
, id
);
292 if (status
!= PAPI_OK
)
293 mesg
= papiStatusString(status
);
296 fprintf(fp
, "%s-%d: %s\n", printer
, rid
, mesg
);
298 fprintf(fp
, "%s-%d: %s\n", printer
, id
, mesg
);
302 berkeley_queue_report(papi_service_t svc
, FILE *fp
, char *dest
, int fmt
,
305 papi_status_t status
;
306 papi_printer_t p
= NULL
;
307 papi_job_t
*jobs
= NULL
;
308 char *pattrs
[] = { "printer-name", "printer-state",
309 "printer-state-reasons", NULL
};
310 char *jattrs
[] = { "job-name", "job-octets", "job-k-octets", "job-id",
311 "job-originating-user-name", "job-id-requested",
312 "job-originating-host-name",
313 "number-of-intervening-jobs", NULL
};
316 status
= papiPrinterQuery(svc
, dest
, pattrs
, NULL
, &p
);
317 if (status
!= PAPI_OK
) {
319 "Failed to query service for state of %s: %s\n"),
320 dest
, verbose_papi_message(svc
, status
));
324 status
= papiPrinterListJobs(svc
, dest
, jattrs
, PAPI_LIST_JOBS_ALL
,
326 if (status
!= PAPI_OK
) {
328 "Failed to query service for jobs on %s: %s\n"),
329 dest
, verbose_papi_message(svc
, status
));
333 while (jobs
[num_jobs
] != NULL
)
337 printer_state_line(fp
, p
, num_jobs
, dest
);
343 for (i
= 0; jobs
[i
] != NULL
; i
++)
344 print_job_line(fp
, i
, jobs
[i
], fmt
, ac
, av
);
348 papiJobListFree(jobs
);
354 berkeley_cancel_request(papi_service_t svc
, FILE *fp
, char *dest
,
357 papi_status_t status
;
358 papi_job_t
*jobs
= NULL
;
359 char *jattrs
[] = { "job-originating-user-name", "job-id",
360 "job-id-requested", NULL
};
362 status
= papiPrinterListJobs(svc
, dest
, jattrs
, PAPI_LIST_JOBS_ALL
,
365 if (status
!= PAPI_OK
) {
366 fprintf(fp
, gettext("Failed to query service for %s: %s\n"),
367 dest
, verbose_papi_message(svc
, status
));
371 /* cancel the job(s) */
375 for (i
= 0; jobs
[i
] != NULL
; i
++)
376 cancel_job(svc
, fp
, dest
, jobs
[i
], ac
, av
);
379 papiJobListFree(jobs
);
385 get_printer_id(char *name
, char **printer
, int *id
)
390 char *p
= strrchr(name
, '-');
396 *id
= strtol(p
+ 1, &s
, 10);
410 * strsplit() splits a string into a NULL terminated array of substrings
411 * determined by a seperator. The original string is modified, and newly
412 * allocated space is only returned for the array itself. If more than
413 * 1024 substrings exist, they will be ignored.
416 strsplit(char *string
, const char *seperators
)
422 if ((string
== NULL
) || (seperators
== NULL
))
425 (void) memset(list
, 0, sizeof (list
));
426 for (list
[length
] = strtok(string
, seperators
);
427 (list
[length
] != NULL
) && (length
< (BUFSIZ
- 2));
428 list
[length
] = strtok(NULL
, seperators
))
431 if ((result
= (char **)calloc(length
+1, sizeof (char *))) != NULL
)
432 (void) memcpy(result
, list
, length
* sizeof (char *));
438 jobSubmitSTDIN(papi_service_t svc
, char *printer
, char *prefetch
, int len
,
439 papi_attribute_t
**list
, papi_job_t
*job
)
441 papi_status_t status
;
442 papi_stream_t stream
= NULL
;
446 status
= papiJobStreamOpen(svc
, printer
, list
, NULL
, &stream
);
449 status
= papiJobStreamWrite(svc
, stream
, prefetch
, len
);
451 while ((status
== PAPI_OK
) && ((rc
= read(0, buf
, sizeof (buf
))) > 0))
452 status
= papiJobStreamWrite(svc
, stream
, buf
, rc
);
454 if (status
== PAPI_OK
)
455 status
= papiJobStreamClose(svc
, stream
, job
);
461 * is_postscript() will detect if the file passed in contains postscript
462 * data. A one is returned if the file contains postscript, zero is returned
463 * if the file is not postscript, and -1 is returned if an error occurs
465 #define PS_MAGIC "%!"
466 #define PC_PS_MAGIC "^D%!"
468 is_postscript_stream(int fd
, char *buf
, int *len
)
470 if ((*len
= read(fd
, buf
, *len
)) < 0) {
475 if ((strncmp(buf
, PS_MAGIC
, sizeof (PS_MAGIC
) - 1) == 0) ||
476 (strncmp(buf
, PC_PS_MAGIC
, sizeof (PC_PS_MAGIC
) - 1) == 0))
483 is_postscript(const char *file
)
488 if ((fd
= open(file
, O_RDONLY
)) >= 0) {
490 int len
= sizeof (buf
);
492 rc
= is_postscript_stream(fd
, buf
, &len
);
500 all_list(papi_service_t svc
)
502 papi_status_t status
;
503 papi_printer_t printer
= NULL
;
504 char *list
[] = { "member-names", NULL
};
505 char **result
= NULL
;
507 status
= papiPrinterQuery(svc
, "_all", list
, NULL
, &printer
);
508 if ((status
== PAPI_OK
) && (printer
!= NULL
)) {
509 papi_attribute_t
**attributes
=
510 papiPrinterGetAttributeList(printer
);
511 if (attributes
!= NULL
) {
515 for (status
= papiAttributeListGetString(attributes
,
516 &iter
, "member-names", &value
);
518 status
= papiAttributeListGetString(attributes
,
519 &iter
, NULL
, &value
))
520 list_append(&result
, strdup(value
));
522 papiPrinterFree(printer
);
529 printers_list(papi_service_t svc
)
531 papi_status_t status
;
532 papi_printer_t
*printers
= NULL
;
533 char *keys
[] = { "printer-name", NULL
};
534 char **result
= NULL
;
536 status
= papiPrintersList(svc
, keys
, NULL
, &printers
);
537 if ((status
== PAPI_OK
) && (printers
!= NULL
)) {
540 for (i
= 0; printers
[i
] != NULL
; i
++) {
541 papi_attribute_t
**attributes
=
542 papiPrinterGetAttributeList(printers
[i
]);
545 (void) papiAttributeListGetString(attributes
, NULL
,
546 "printer-name", &name
);
547 if ((name
!= NULL
) && (strcmp(name
, "_default") != 0))
548 list_append(&result
, strdup(name
));
550 papiPrinterListFree(printers
);
557 interest_list(papi_service_t svc
)
559 static char been_here
;
560 static char **result
;
562 if (been_here
== 0) { /* only do this once */
565 if ((result
= all_list(svc
)) == NULL
)
566 result
= printers_list(svc
);
577 if (result
== NULL
) {
578 static char buf
[256];
580 if (gethostname(buf
, sizeof (buf
)) == 0)
588 cli_auth_callback(papi_service_t svc
, void *app_data
)
591 char *user
, *svc_name
, *passphrase
;
593 /* get the name of the service we are contacting */
594 if ((svc_name
= papiServiceGetServiceName(svc
)) == NULL
)
597 /* find our who we are supposed to be */
598 if ((user
= papiServiceGetUserName(svc
)) == NULL
) {
601 if ((pw
= getpwuid(getuid())) != NULL
)
607 /* build the prompt string */
608 snprintf(prompt
, sizeof (prompt
),
609 gettext("passphrase for %s to access %s: "), user
, svc_name
);
611 /* ask for the passphrase */
612 if ((passphrase
= getpassphrase(prompt
)) != NULL
)
613 papiServiceSetPassword(svc
, passphrase
);
619 job_to_be_queried(papi_service_t svc
, char *printer
, int32_t id
)
621 papi_job_t
*jobs
= NULL
;
622 papi_status_t status
;
624 char *jattrs
[] = { "job-id",
625 "job-id-requested", NULL
};
627 status
= papiPrinterListJobs(svc
, printer
, jattrs
, PAPI_LIST_JOBS_ALL
,
630 if (status
!= PAPI_OK
) {
631 fprintf(stderr
, gettext("Failed to query service for %s: %s\n"),
632 printer
, verbose_papi_message(svc
, status
));
639 for (i
= 0; jobs
[i
] != NULL
; i
++) {
642 papi_attribute_t
**list
=
643 papiJobGetAttributeList(jobs
[i
]);
645 papiAttributeListGetInteger(list
, NULL
,
646 "job-id-requested", &rid
);
647 papiAttributeListGetInteger(list
, NULL
,
651 * check if id matches with either rid or jid
654 /* get the actual id and return it */
655 papiAttributeListGetInteger(list
, NULL
,
658 } else if (id
== jid
) {
661 * It is a remote lpd job
662 * can be cancelled only