1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "$Id: lpd-job.c,v 1.1 2005/02/26 06:58:42 njacobs Exp $"
7
8 #define __EXTENSIONS__ /* for strtok_r() */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <limits.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <string.h>
18 #include <pwd.h>
19 #include <libintl.h>
20 #include <papi_impl.h>
21
22 enum { LPD_RFC, LPD_SVR4 };
23
24 static char
mime_type_to_rfc1179_type(char * mime)25 mime_type_to_rfc1179_type(char *mime)
26 {
27 static struct { char *mime; char rfc; } cvt[] = {
28 { "plain/text", 'f' },
29 { "application/octet-stream", 'l' },
30 { "application/postscript", 'f' }, /* rfc incorrectly has 'o' */
31 { "application/x-pr", 'p' },
32 { "application/x-cif", 'c' },
33 { "application/x-dvi", 'd' },
34 { "application/x-fortran", 'r' },
35 { "application/x-plot", 'g' },
36 { "application/x-ditroff", 'n' },
37 { "application/x-troff", 't' },
38 { "application/x-raster", 'v' },
39 { NULL, 0}
40 };
41 char result = '\0';
42
43 if (mime != NULL) {
44 int i;
45
46 for (i = 0; cvt[i].mime != NULL; i++)
47 if (strcasecmp(cvt[i].mime, mime) == 0) {
48 result = cvt[i].rfc;
49 break;
50 }
51 }
52
53 return (result);
54 }
55
56 static papi_status_t
add_lpd_control_line(char ** metadata,char code,char * value)57 add_lpd_control_line(char **metadata, char code, char *value)
58 {
59 size_t size = 0;
60 char line[BUFSIZ];
61
62 if ((metadata == NULL) || (value == NULL))
63 return (PAPI_BAD_REQUEST);
64
65 if (*metadata != NULL)
66 size = strlen(*metadata);
67 size += strlen(value) + 3;
68
69 if (*metadata == NULL)
70 *metadata = (char *)calloc(1, size);
71 else
72 *metadata = (char *)realloc(*metadata, size);
73
74 snprintf(line, sizeof (line), "%c%s\n", code, value);
75 strlcat(*metadata, line, size);
76
77 return (PAPI_OK);
78 }
79
80 static papi_status_t
add_svr4_control_line(char ** metadata,char code,char * value)81 add_svr4_control_line(char **metadata, char code, char *value)
82 {
83
84 char line[BUFSIZ];
85
86 if ((metadata == NULL) || (value == NULL))
87 return (PAPI_BAD_REQUEST);
88
89 snprintf(line, sizeof (line), "%c%s", code, value);
90
91 return (add_lpd_control_line(metadata, '5', line));
92 }
93
94 static papi_status_t
add_hpux_control_line(char ** metadata,char * value)95 add_hpux_control_line(char **metadata, char *value)
96 {
97
98 char line[BUFSIZ];
99
100 if ((metadata == NULL) || (value == NULL))
101 return (PAPI_BAD_REQUEST);
102
103 snprintf(line, sizeof (line), " O%s", value);
104
105 return (add_lpd_control_line(metadata, 'N', line));
106 }
107
108 static papi_status_t
add_int_control_line(char ** metadata,char code,int value,int flag)109 add_int_control_line(char **metadata, char code, int value, int flag)
110 {
111 char buf[16];
112
113 snprintf(buf, sizeof (buf), "%d", value);
114
115 if (flag == LPD_SVR4)
116 return (add_svr4_control_line(metadata, code, buf));
117 else
118 return (add_lpd_control_line(metadata, code, buf));
119 }
120
121 static papi_status_t
lpd_add_rfc1179_attributes(service_t * svc,papi_attribute_t ** attributes,char ** metadata,papi_attribute_t *** used)122 lpd_add_rfc1179_attributes(service_t *svc, papi_attribute_t **attributes,
123 char **metadata, papi_attribute_t ***used)
124 {
125 papi_status_t status = PAPI_OK;
126 char *s;
127 int integer;
128 char bool;
129 char host[BUFSIZ];
130 char *user = "nobody";
131 uid_t uid = getuid();
132 struct passwd *pw;
133
134 if (svc == NULL)
135 return (PAPI_BAD_REQUEST);
136
137 /* There is nothing to do */
138 if (attributes == NULL)
139 return (PAPI_OK);
140
141 gethostname(host, sizeof (host));
142 add_lpd_control_line(metadata, 'H', host);
143 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
144 "job-originating-host-name", host);
145
146 if ((pw = getpwuid(uid)) != NULL)
147 user = pw->pw_name;
148 if (uid == 0)
149 papiAttributeListGetString(svc->attributes, NULL, "username",
150 &user);
151 add_lpd_control_line(metadata, 'P', user);
152 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
153 "job-originating-user-name", user);
154
155 /* Class for Banner Page */
156 s = NULL;
157 papiAttributeListGetString(attributes, NULL, "rfc-1179-class", &s);
158 if (s != NULL) {
159 add_lpd_control_line(metadata, 'C', s);
160 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
161 "rfc-1179-class", s);
162 }
163
164 /* Print Banner Page */
165 s = NULL;
166 papiAttributeListGetString(attributes, NULL, "job-sheets", &s);
167 if ((s != NULL) && (strcmp(s, "standard") == 0)) {
168 add_lpd_control_line(metadata, 'L', user);
169 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
170 "job-sheets", s);
171 }
172
173 /* Jobname */
174 s = NULL;
175 papiAttributeListGetString(attributes, NULL, "job-name", &s);
176 if (s != NULL) {
177 add_lpd_control_line(metadata, 'J', s);
178 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
179 "job-name", s);
180 }
181
182 /* User to mail when job is done - lpr -m */
183 bool = PAPI_FALSE;
184 papiAttributeListGetBoolean(attributes, NULL, "rfc-1179-mail", &bool);
185 if (bool == PAPI_TRUE) {
186 add_lpd_control_line(metadata, 'M', user);
187 papiAttributeListAddBoolean(used, PAPI_ATTR_EXCL,
188 "rfc-1179-mail", bool);
189 }
190
191 /* Title for pr */
192 s = NULL;
193 papiAttributeListGetString(attributes, NULL, "pr-title", &s);
194 if (s != NULL) {
195 add_lpd_control_line(metadata, 'T', s);
196 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
197 "pr-title", s);
198 }
199
200 /* Indent - used with pr filter */
201 integer = 0;
202 papiAttributeListGetInteger(attributes, NULL, "pr-indent", &integer);
203 if (integer >= 1) {
204 add_int_control_line(metadata, 'I', integer, LPD_RFC);
205 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL,
206 "pr-indent", integer);
207 }
208
209 /* Width - used with pr filter */
210 integer = 0;
211 papiAttributeListGetInteger(attributes, NULL, "pr-width", &integer);
212 if (integer >= 1) {
213 add_int_control_line(metadata, 'W', integer, LPD_RFC);
214 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL,
215 "pr-width", integer);
216 }
217
218 /* file with Times Roman font lpr -1 */
219 s = NULL;
220 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-r", &s);
221 if (s != NULL) {
222 add_lpd_control_line(metadata, '1', s);
223 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
224 "rfc-1179-font-r", s);
225 }
226
227 /* file with Times Roman font lpr -2 */
228 s = NULL;
229 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-i", &s);
230 if (s != NULL) {
231 add_lpd_control_line(metadata, '2', s);
232 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
233 "rfc-1179-font-i", s);
234 }
235
236 /* file with Times Roman font lpr -3 */
237 s = NULL;
238 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-b", &s);
239 if (s != NULL) {
240 add_lpd_control_line(metadata, '3', s);
241 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
242 "rfc-1179-font-b", s);
243 }
244
245 /* file with Times Roman font lpr -4 */
246 s = NULL;
247 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-s", &s);
248 if (s != NULL) {
249 add_lpd_control_line(metadata, '4', s);
250 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
251 "rfc-1179-font-s", s);
252 }
253
254 return (status);
255 }
256
257 /*
258 * lpd_add_svr4_attributes
259 * Solaris 2.x LP - BSD protocol extensions
260 */
261 static papi_status_t
lpd_add_svr4_attributes(service_t * svc,papi_attribute_t ** attributes,char ** metadata,papi_attribute_t *** used)262 lpd_add_svr4_attributes(service_t *svc, papi_attribute_t **attributes,
263 char **metadata, papi_attribute_t ***used)
264 {
265 char *s;
266 int integer;
267
268 if (svc == NULL)
269 return (PAPI_BAD_REQUEST);
270
271 /* media */
272 s = NULL;
273 papiAttributeListGetString(attributes, NULL, "media", &s);
274 if (s != NULL) {
275 add_svr4_control_line(metadata, 'f', s);
276 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
277 "media", s);
278 }
279
280 /* Handling */
281 s = NULL;
282 papiAttributeListGetString(attributes, NULL, "job_hold_until", &s);
283 if ((s != NULL) && (strcmp(s, "indefinite"))) {
284 add_svr4_control_line(metadata, 'H', "hold");
285 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
286 "media", "hold");
287 } else if ((s != NULL) && (strcmp(s, "no-hold"))) {
288 add_svr4_control_line(metadata, 'H', "release");
289 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
290 "media", "release");
291 } else if ((s != NULL) && (strcmp(s, "immediate"))) {
292 add_int_control_line(metadata, 'q', 0, LPD_SVR4);
293 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
294 "media", "immediate");
295 }
296
297 /* Pages */
298 s = NULL;
299 papiAttributeListGetString(attributes, NULL, "page-ranges", &s);
300 if (s != NULL) {
301 add_svr4_control_line(metadata, 'P', s);
302 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
303 "page-ranges", s);
304 }
305
306 /* Priority : lp -q */
307 integer = -1;
308 papiAttributeListGetInteger(attributes, NULL, "priority", &integer);
309 if (integer != -1) {
310 add_int_control_line(metadata, 'q', integer, LPD_SVR4);
311 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL,
312 "priority", integer);
313 }
314
315 /* Charset : lp -S */
316 s = NULL;
317 papiAttributeListGetString(attributes, NULL, "lp-charset", &s);
318 if (s != NULL) {
319 add_svr4_control_line(metadata, 'S', s);
320 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
321 "lp-charset", s);
322 }
323
324 /* Type : done when adding file */
325
326 /* Mode : lp -y */
327 s = NULL;
328 papiAttributeListGetString(attributes, NULL, "lp-modes", &s);
329 if (s != NULL) {
330 add_svr4_control_line(metadata, 'y', s);
331 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
332 "lp-modes", s);
333 }
334
335 /* Options lp -o */
336 s = NULL;
337 papiAttributeListGetString(attributes, NULL, "lp-options", &s);
338 if (s != NULL) {
339 add_svr4_control_line(metadata, 'o', s);
340 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
341 "lp-options", s);
342 }
343 }
344
345 papi_status_t
lpd_add_hpux_attributes(service_t * svc,papi_attribute_t ** attributes,char ** metadata,papi_attribute_t *** used)346 lpd_add_hpux_attributes(service_t *svc, papi_attribute_t **attributes,
347 char **metadata, papi_attribute_t ***used)
348 {
349 char *s = NULL;
350
351 /* Options lp -o */
352 s = NULL;
353 papiAttributeListGetString(attributes, NULL, "lp-options", &s);
354 if (s != NULL) {
355 add_hpux_control_line(metadata, s);
356 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
357 "lp-options", s);
358 }
359
360 return (PAPI_OK);
361 }
362
363 papi_status_t
lpd_job_add_attributes(service_t * svc,papi_attribute_t ** attributes,char ** metadata,papi_attribute_t *** used)364 lpd_job_add_attributes(service_t *svc, papi_attribute_t **attributes,
365 char **metadata, papi_attribute_t ***used)
366 {
367 if ((svc == NULL) || (metadata == NULL))
368 return (PAPI_BAD_REQUEST);
369
370 lpd_add_rfc1179_attributes(svc, attributes, metadata, used);
371
372 if (svc->uri->fragment != NULL) {
373 if ((strcasecmp(svc->uri->fragment, "solaris") == 0) ||
374 (strcasecmp(svc->uri->fragment, "svr4") == 0))
375 lpd_add_svr4_attributes(svc, attributes, metadata,
376 used);
377 else if (strcasecmp(svc->uri->fragment, "hpux") == 0)
378 lpd_add_hpux_attributes(svc, attributes, metadata,
379 used);
380 /*
381 * others could be added here:
382 * lprng, sco, aix, digital unix, xerox, ...
383 */
384 }
385
386 return (PAPI_OK);
387 }
388
389 papi_status_t
lpd_job_add_files(service_t * svc,papi_attribute_t ** attributes,char ** files,char ** metadata,papi_attribute_t *** used)390 lpd_job_add_files(service_t *svc, papi_attribute_t **attributes,
391 char **files, char **metadata, papi_attribute_t ***used)
392 {
393 char *format = "plain/text";
394 char rfc_fmt = 'l';
395 int copies = 1;
396 char host[BUFSIZ];
397 int i;
398
399 if ((svc == NULL) || (attributes == NULL) || (files == NULL) ||
400 (metadata == NULL))
401 return (PAPI_BAD_ARGUMENT);
402
403 papiAttributeListGetString(attributes, NULL, "document-format",
404 &format);
405 papiAttributeListAddString(used, PAPI_ATTR_EXCL,
406 "document-format", format);
407 if ((rfc_fmt = mime_type_to_rfc1179_type(format)) == '\0') {
408 if ((svc->uri->fragment != NULL) &&
409 ((strcasecmp(svc->uri->fragment, "solaris") == 0) ||
410 (strcasecmp(svc->uri->fragment, "svr4") == 0)))
411 add_svr4_control_line(metadata, 'T', format);
412 rfc_fmt = 'l';
413 }
414
415 papiAttributeListGetInteger(attributes, NULL, "copies", &copies);
416 if (copies < 1)
417 copies = 1;
418 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, "copies", copies);
419
420 gethostname(host, sizeof (host));
421
422 for (i = 0; files[i] != NULL; i++) {
423 char name[BUFSIZ];
424 char key;
425 int j;
426
427 if ((strcmp("standard input", files[i]) != 0) &&
428 (access(files[i], R_OK) < 0)) {
429 detailed_error(svc, gettext("aborting request, %s: %s"),
430 files[i], strerror(errno));
431 return (PAPI_NOT_AUTHORIZED);
432 }
433
434 if (i < 26)
435 key = 'A' + i;
436 else if (i < 52)
437 key = 'a' + (i - 26);
438 else if (i < 62)
439 key = '0' + (i - 52);
440 else {
441 detailed_error(svc,
442 gettext("too many files, truncated at 62"));
443 return (PAPI_OK_SUBST);
444 }
445
446 snprintf(name, sizeof (name), "df%cXXX%s", key, host);
447
448 for (j = 0; j < copies; j++)
449 add_lpd_control_line(metadata, rfc_fmt, name);
450 add_lpd_control_line(metadata, 'U', name);
451 add_lpd_control_line(metadata, 'N', (char *)files[i]);
452 }
453
454 return (PAPI_OK);
455 }
456
457 papi_status_t
lpd_submit_job(service_t * svc,char * metadata,papi_attribute_t *** attributes,int * ofd)458 lpd_submit_job(service_t *svc, char *metadata, papi_attribute_t ***attributes,
459 int *ofd)
460 {
461 papi_status_t status = PAPI_INTERNAL_ERROR;
462 int fd;
463 char path[32];
464 char *list[2];
465
466 if ((svc == NULL) || (metadata == NULL))
467 return (PAPI_BAD_ARGUMENT);
468
469 strcpy(path, "/tmp/lpd-job-XXXXXX");
470 fd = mkstemp(path);
471 write(fd, metadata, strlen(metadata));
472 close(fd);
473
474 list[0] = path;
475 list[1] = NULL;
476
477 if (((fd = lpd_open(svc, 's', list, 3)) < 0) && (errno != EBADMSG)) {
478 switch (errno) {
479 case ENOSPC:
480 status = PAPI_TEMPORARY_ERROR;
481 break;
482 case EIO:
483 status = PAPI_TEMPORARY_ERROR;
484 break;
485 case ECONNREFUSED:
486 status = PAPI_SERVICE_UNAVAILABLE;
487 break;
488 case ENOENT:
489 status = PAPI_NOT_ACCEPTING;
490 break;
491 case EBADMSG:
492 case EBADF:
493 status = PAPI_OK;
494 break;
495 default:
496 status = PAPI_TIMEOUT;
497 break;
498 }
499 } else
500 status = PAPI_OK;
501
502 if (ofd != NULL)
503 *ofd = fd;
504 else
505 close(fd);
506
507 /* read the ID and add it to to the job */
508 if ((fd = open(path, O_RDONLY)) >= 0) {
509 int job_id = 0;
510 read(fd, &job_id, sizeof (job_id));
511 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
512 "job-id", job_id);
513 close(fd);
514 }
515
516 unlink(path);
517
518 return (status);
519 }
520