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 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 /* $Id: lpd-job.c 157 2006-04-26 15:07:55Z ktou $ */
31 #define __EXTENSIONS__ /* for strtok_r() */
37 #include <sys/types.h>
43 #include <papi_impl.h>
45 enum { LPD_RFC
, LPD_SVR4
};
48 mime_type_to_rfc1179_type(char *mime
)
50 static struct { char *mime
; char rfc
; } cvt
[] = {
51 { "text/plain", 'f' },
52 { "application/octet-stream", 'l' },
53 { "application/postscript", 'f' }, /* rfc incorrectly has 'o' */
54 { "application/x-pr", 'p' },
55 { "application/x-cif", 'c' },
56 { "application/x-dvi", 'd' },
57 { "application/x-fortran", 'r' },
58 { "application/x-plot", 'g' },
59 { "application/x-ditroff", 'n' },
60 { "application/x-troff", 't' },
61 { "application/x-raster", 'v' },
69 for (i
= 0; cvt
[i
].mime
!= NULL
; i
++)
70 if (strcasecmp(cvt
[i
].mime
, mime
) == 0) {
80 add_lpd_control_line(char **metadata
, char code
, char *value
)
85 if ((metadata
== NULL
) || (value
== NULL
))
86 return (PAPI_BAD_REQUEST
);
88 if (*metadata
!= NULL
)
89 size
= strlen(*metadata
);
90 size
+= strlen(value
) + 3;
92 if (*metadata
== NULL
) {
93 *metadata
= (char *)calloc(1, size
);
96 tmp
= calloc(1, size
);
98 strlcpy(tmp
, *metadata
, size
);
100 *metadata
= (char *)tmp
;
102 return (PAPI_TEMPORARY_ERROR
);
105 snprintf(line
, sizeof (line
), "%c%s\n", code
, value
);
106 strlcat(*metadata
, line
, size
);
112 add_svr4_control_line(char **metadata
, char code
, char *value
)
117 if ((metadata
== NULL
) || (value
== NULL
))
118 return (PAPI_BAD_REQUEST
);
120 snprintf(line
, sizeof (line
), "%c%s", code
, value
);
122 return (add_lpd_control_line(metadata
, '5', line
));
126 add_hpux_control_line(char **metadata
, char *value
)
131 if ((metadata
== NULL
) || (value
== NULL
))
132 return (PAPI_BAD_REQUEST
);
134 snprintf(line
, sizeof (line
), " O%s", value
);
136 return (add_lpd_control_line(metadata
, 'N', line
));
140 add_int_control_line(char **metadata
, char code
, int value
, int flag
)
144 snprintf(buf
, sizeof (buf
), "%d", value
);
146 if (flag
== LPD_SVR4
)
147 return (add_svr4_control_line(metadata
, code
, buf
));
149 return (add_lpd_control_line(metadata
, code
, buf
));
153 lpd_add_rfc1179_attributes(service_t
*svc
, papi_attribute_t
**attributes
,
154 char **metadata
, papi_attribute_t
***used
)
156 papi_status_t status
= PAPI_OK
;
161 char *user
= "nobody";
162 uid_t uid
= getuid();
167 return (PAPI_BAD_REQUEST
);
169 /* There is nothing to do */
170 if (attributes
== NULL
)
173 gethostname(host
, sizeof (host
));
174 if (papiAttributeListGetString(attributes
, NULL
,
175 "job-originating-host-name", &h1
) == PAPI_OK
) {
176 papiAttributeListAddString(&attributes
, PAPI_ATTR_APPEND
,
179 add_lpd_control_line(metadata
, 'H', host
);
180 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
181 "job-originating-host-name", host
);
183 if ((pw
= getpwuid(uid
)) != NULL
)
186 papiAttributeListGetString(svc
->attributes
, NULL
, "username",
188 add_lpd_control_line(metadata
, 'P', user
);
189 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
190 "job-originating-user-name", user
);
192 /* Class for Banner Page */
194 papiAttributeListGetString(attributes
, NULL
, "rfc-1179-class", &s
);
196 add_lpd_control_line(metadata
, 'C', s
);
197 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
198 "rfc-1179-class", s
);
201 /* Print Banner Page */
203 papiAttributeListGetString(attributes
, NULL
, "job-sheets", &s
);
204 if ((s
!= NULL
) && (strcmp(s
, "standard") == 0)) {
205 add_lpd_control_line(metadata
, 'L', user
);
206 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
212 papiAttributeListGetString(attributes
, NULL
, "job-name", &s
);
214 add_lpd_control_line(metadata
, 'J', s
);
215 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
219 /* User to mail when job is done - lpr -m */
221 papiAttributeListGetBoolean(attributes
, NULL
, "rfc-1179-mail", &bool);
222 if (bool == PAPI_TRUE
) {
223 add_lpd_control_line(metadata
, 'M', user
);
224 papiAttributeListAddBoolean(used
, PAPI_ATTR_EXCL
,
225 "rfc-1179-mail", bool);
230 papiAttributeListGetString(attributes
, NULL
, "pr-title", &s
);
232 add_lpd_control_line(metadata
, 'T', s
);
233 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
237 /* Indent - used with pr filter */
239 papiAttributeListGetInteger(attributes
, NULL
, "pr-indent", &integer
);
241 add_int_control_line(metadata
, 'I', integer
, LPD_RFC
);
242 papiAttributeListAddInteger(used
, PAPI_ATTR_EXCL
,
243 "pr-indent", integer
);
246 /* Width - used with pr filter */
248 papiAttributeListGetInteger(attributes
, NULL
, "pr-width", &integer
);
250 add_int_control_line(metadata
, 'W', integer
, LPD_RFC
);
251 papiAttributeListAddInteger(used
, PAPI_ATTR_EXCL
,
252 "pr-width", integer
);
255 /* file with Times Roman font lpr -1 */
257 papiAttributeListGetString(attributes
, NULL
, "rfc-1179-font-r", &s
);
259 add_lpd_control_line(metadata
, '1', s
);
260 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
261 "rfc-1179-font-r", s
);
264 /* file with Times Roman font lpr -2 */
266 papiAttributeListGetString(attributes
, NULL
, "rfc-1179-font-i", &s
);
268 add_lpd_control_line(metadata
, '2', s
);
269 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
270 "rfc-1179-font-i", s
);
273 /* file with Times Roman font lpr -3 */
275 papiAttributeListGetString(attributes
, NULL
, "rfc-1179-font-b", &s
);
277 add_lpd_control_line(metadata
, '3', s
);
278 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
279 "rfc-1179-font-b", s
);
282 /* file with Times Roman font lpr -4 */
284 papiAttributeListGetString(attributes
, NULL
, "rfc-1179-font-s", &s
);
286 add_lpd_control_line(metadata
, '4', s
);
287 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
288 "rfc-1179-font-s", s
);
292 * The document format needs to be added, but the control line
293 * should be added when the filenames are figured out.
296 papiAttributeListGetString(attributes
, NULL
, "document-format", &s
);
298 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
299 "document-format", s
);
306 unused_attributes(papi_attribute_t
**list
, papi_attribute_t
**used
)
312 if ((list
== NULL
) || (used
== NULL
))
315 for (i
= 0; used
[i
] != NULL
; i
++)
316 list_append(&names
, used
[i
]->name
);
319 papi_attribute_t
**unused
= NULL
;
321 /* add these to the list of things to ignore */
322 list_append(&names
, "document-format");
323 list_append(&names
, "copies");
325 split_and_copy_attributes(names
, list
, NULL
, &unused
);
326 if (unused
!= NULL
) {
333 result
= calloc(1, size
);
334 } while (papiAttributeListToString(unused
, " ",
335 result
, size
) != PAPI_OK
);
336 papiAttributeListFree(unused
);
345 * lpd_add_svr4_attributes
346 * Solaris 2.x LP - BSD protocol extensions
349 lpd_add_svr4_attributes(service_t
*svc
, papi_attribute_t
**attributes
,
350 char **metadata
, papi_attribute_t
***used
)
352 papi_attribute_t
*tmp
[2];
357 return (PAPI_BAD_REQUEST
);
361 papiAttributeListGetString(attributes
, NULL
, "media", &s
);
363 add_svr4_control_line(metadata
, 'f', s
);
364 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
370 papiAttributeListGetString(attributes
, NULL
, "job-hold-until", &s
);
371 if ((s
!= NULL
) && (strcmp(s
, "indefinite") == 0)) {
372 add_svr4_control_line(metadata
, 'H', "hold");
373 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
374 "job-hold-until", "indefinite");
375 } else if ((s
!= NULL
) && (strcmp(s
, "no-hold") == 0)) {
376 add_svr4_control_line(metadata
, 'H', "immediate");
377 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
378 "job-hold-until", "no-hold");
379 } else if (s
!= NULL
) {
380 add_svr4_control_line(metadata
, 'H', s
);
381 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
382 "job-hold-until", s
);
387 memset(tmp
, NULL
, sizeof (tmp
));
388 tmp
[0] = papiAttributeListFind(attributes
, "page-ranges");
389 if (tmp
[0] != NULL
) {
392 papiAttributeListToString(tmp
, " ", buf
, sizeof (buf
));
393 if ((s
= strchr(buf
, '=')) != NULL
) {
394 add_svr4_control_line(metadata
, 'P', ++s
);
395 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
400 /* Priority : lp -q */
402 papiAttributeListGetInteger(attributes
, NULL
, "job-priority", &integer
);
404 integer
= 40 - (integer
/ 2.5);
405 add_int_control_line(metadata
, 'q', integer
, LPD_SVR4
);
406 papiAttributeListAddInteger(used
, PAPI_ATTR_EXCL
,
407 "job-priority", integer
);
410 /* Charset : lp -S */
412 papiAttributeListGetString(attributes
, NULL
, "lp-charset", &s
);
414 add_svr4_control_line(metadata
, 'S', s
);
415 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
419 /* Type : done when adding file */
423 papiAttributeListGetString(attributes
, NULL
, "lp-modes", &s
);
425 add_svr4_control_line(metadata
, 'y', s
);
426 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
430 /* Options lp -o are handled elsewhere */
431 if ((s
= unused_attributes(attributes
, *used
)) != NULL
) {
432 add_lpd_control_line(metadata
, 'O', s
);
440 lpd_add_hpux_attributes(service_t
*svc
, papi_attribute_t
**attributes
,
441 char **metadata
, papi_attribute_t
***used
)
446 if ((s
= unused_attributes(attributes
, *used
)) != NULL
) {
447 add_hpux_control_line(metadata
, s
);
455 lpd_job_add_attributes(service_t
*svc
, papi_attribute_t
**attributes
,
456 char **metadata
, papi_attribute_t
***used
)
458 if ((svc
== NULL
) || (metadata
== NULL
))
459 return (PAPI_BAD_REQUEST
);
461 lpd_add_rfc1179_attributes(svc
, attributes
, metadata
, used
);
463 /* add protocol extensions if applicable */
464 if (svc
->uri
->fragment
!= NULL
) {
465 if ((strcasecmp(svc
->uri
->fragment
, "solaris") == 0) ||
466 (strcasecmp(svc
->uri
->fragment
, "svr4") == 0))
467 lpd_add_svr4_attributes(svc
, attributes
, metadata
,
469 else if (strcasecmp(svc
->uri
->fragment
, "hpux") == 0)
470 lpd_add_hpux_attributes(svc
, attributes
, metadata
,
473 * others could be added here:
474 * lprng, sco, aix, digital unix, xerox, ...
482 lpd_job_add_files(service_t
*svc
, papi_attribute_t
**attributes
,
483 char **files
, char **metadata
, papi_attribute_t
***used
)
485 char *format
= "text/plain";
491 if ((svc
== NULL
) || (attributes
== NULL
) || (files
== NULL
) ||
493 return (PAPI_BAD_ARGUMENT
);
495 papiAttributeListGetString(attributes
, NULL
, "document-format",
497 papiAttributeListAddString(used
, PAPI_ATTR_EXCL
,
498 "document-format", format
);
499 if ((rfc_fmt
= mime_type_to_rfc1179_type(format
)) == '\0') {
500 if ((svc
->uri
->fragment
!= NULL
) &&
501 ((strcasecmp(svc
->uri
->fragment
, "solaris") == 0) ||
502 (strcasecmp(svc
->uri
->fragment
, "svr4") == 0)))
503 add_svr4_control_line(metadata
, 'T', format
);
507 papiAttributeListGetInteger(attributes
, NULL
, "copies", &copies
);
510 papiAttributeListAddInteger(used
, PAPI_ATTR_EXCL
, "copies", copies
);
512 gethostname(host
, sizeof (host
));
514 for (i
= 0; files
[i
] != NULL
; i
++) {
520 if ((strcmp("standard input", files
[i
]) != 0) &&
521 (access(files
[i
], R_OK
) < 0)) {
522 detailed_error(svc
, gettext("aborting request, %s: %s"),
523 files
[i
], strerror(errno
));
524 return (PAPI_NOT_AUTHORIZED
);
526 if (strcmp("standard input", files
[i
]) != 0) {
527 if (stat(files
[i
], &statbuf
) < 0) {
529 gettext("Cannot access file: %s: %s"),
530 files
[i
], strerror(errno
));
531 return (PAPI_DOCUMENT_ACCESS_ERROR
);
533 if (statbuf
.st_size
== 0) {
535 gettext("Zero byte (empty) file: %s"),
537 return (PAPI_BAD_ARGUMENT
);
544 key
= 'a' + (i
- 26);
546 key
= '0' + (i
- 52);
549 gettext("too many files, truncated at 62"));
550 return (PAPI_OK_SUBST
);
553 snprintf(name
, sizeof (name
), "df%cXXX%s", key
, host
);
555 for (j
= 0; j
< copies
; j
++)
556 add_lpd_control_line(metadata
, rfc_fmt
, name
);
557 add_lpd_control_line(metadata
, 'U', name
);
558 add_lpd_control_line(metadata
, 'N', (char *)files
[i
]);
565 lpd_submit_job(service_t
*svc
, char *metadata
, papi_attribute_t
***attributes
,
568 papi_status_t status
= PAPI_INTERNAL_ERROR
;
573 if ((svc
== NULL
) || (metadata
== NULL
))
574 return (PAPI_BAD_ARGUMENT
);
576 strcpy(path
, "/tmp/lpd-job-XXXXXX");
578 write(fd
, metadata
, strlen(metadata
));
584 if (((fd
= lpd_open(svc
, 's', list
, 15)) < 0) && (errno
!= EBADMSG
)) {
587 status
= PAPI_TEMPORARY_ERROR
;
590 status
= PAPI_TEMPORARY_ERROR
;
593 status
= PAPI_SERVICE_UNAVAILABLE
;
596 status
= PAPI_NOT_ACCEPTING
;
603 status
= PAPI_TIMEOUT
;
614 /* read the ID and add it to to the job */
615 if ((fd
= open(path
, O_RDONLY
)) >= 0) {
617 read(fd
, &job_id
, sizeof (job_id
));
618 papiAttributeListAddInteger(attributes
, PAPI_ATTR_REPLACE
,