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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*LINTLIBRARY*/
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <libintl.h>
32 #include <pwd.h>
33
34 /* lpsched include files */
35 #include "lp.h"
36 #include "requests.h"
37 #include "printers.h"
38
39 #include <papi_impl.h>
40
41 papi_status_t
job_attributes_to_lpsched_request(papi_service_t svc,REQUEST * r,papi_attribute_t ** attributes)42 job_attributes_to_lpsched_request(papi_service_t svc, REQUEST *r,
43 papi_attribute_t **attributes)
44 {
45 papi_status_t status = PAPI_OK;
46 papi_attribute_t *attr;
47 papi_attribute_t **unmapped = NULL;
48 papi_attribute_t *tmp[2];
49 int i;
50 char *s;
51
52 char **options = NULL;
53 char **modes = NULL;
54
55 char pr_filter = 0;
56 char *pr_title = NULL;
57 int pr_width = -1;
58 int pr_indent = -1;
59 int numberUp = 0;
60 int orientation = 0;
61 int lower = 0;
62 int upper = 0;
63 char buf[256];
64 void *iterator = NULL;
65 char *mapped_keys[] = { "copies", "document-format", "form",
66 "job-class", "job-hold-until", "job-host", "job-name",
67 "job-originating-user-name", "job-printer",
68 "job-sheets", "lp-charset", "lp-modes", "number-up",
69 "orienttation-requested", "page-ranges", "pr-filter",
70 "pr-indent", "pr-title", "pr-width", "job-priority",
71 "requesting-user-name", "job-originating-host-name",
72 NULL };
73
74 if (attributes == NULL)
75 return (PAPI_BAD_ARGUMENT);
76
77 /* replace the current destination */
78 papiAttributeListGetLPString(attributes,
79 "job-printer", &r->destination);
80
81 /* set the copies. We need at least 1 */
82 i = r->copies;
83 papiAttributeListGetInteger(attributes, NULL, "copies", &i);
84 if (i <= 0)
85 i = 1;
86 r->copies = i;
87
88 /*
89 * set the priority. PAPI/IPP uses 1-100, lpsched use 0-39, so we
90 * have to convert it.
91 */
92 if (papiAttributeListGetInteger(attributes, NULL, "job-priority", &i)
93 == PAPI_OK) {
94 if ((i < 1) || (i > 100))
95 i = 50;
96 i = 40 - (i / 2.5);
97 r->priority = i;
98 }
99 if ((r->priority < 0) || (r->priority > 39))
100 r->priority = 20;
101
102 /* set the requested form to print on */
103 papiAttributeListGetLPString(attributes, "form", &r->form);
104
105 /* set the page range */
106 memset(tmp, NULL, sizeof (tmp));
107 tmp[0] = papiAttributeListFind(attributes, "page-ranges");
108 if (tmp[0] != NULL) {
109 char buf[BUFSIZ];
110
111 papiAttributeListToString(tmp, " ", buf, sizeof (buf));
112 if ((s = strchr(buf, '=')) != NULL)
113 r->pages = (char *)strdup(++s);
114 }
115
116 /*
117 * set the document format, converting to old format names as
118 * as needed.
119 */
120 s = NULL;
121 papiAttributeListGetString(attributes, NULL, "document-format", &s);
122 if (s != NULL)
123 r->input_type = strdup(mime_type_to_lp_type(s));
124
125
126 /*
127 * If we don't have an owner, set one.
128 */
129 if (r->user == NULL) {
130 uid_t uid = getuid();
131 struct passwd *pw;
132 char *user = "intruder";
133 char *host = NULL;
134 char buf[256];
135
136 if ((pw = getpwuid(uid)) != NULL)
137 user = pw->pw_name; /* default to the process owner */
138
139 papiAttributeListGetString(attributes, NULL,
140 "job-originating-host-name", &host);
141 papiAttributeListGetString(attributes, NULL,
142 "job-host", &host);
143 papiAttributeListGetString(attributes, NULL,
144 "job-originating-user-name", &user);
145 papiAttributeListGetString(attributes, NULL,
146 "requesting-user-name", &user);
147
148 snprintf(buf, sizeof (buf), "%s%s%s", user,
149 (host ? "@" : ""), (host ? host : ""));
150 user = buf;
151
152 r->user = strdup(user);
153 }
154
155 /* set any held state */
156 s = NULL;
157 papiAttributeListGetString(attributes, NULL, "job-hold-until", &s);
158 if (s != NULL) {
159 r->actions &= ~(ACT_SPECIAL); /* strip immediate/hold/resume */
160 if (strcmp(s, "resume") == 0)
161 r->actions |= ACT_RESUME;
162 else if ((strcmp(s, "immediate") == 0) ||
163 (strcmp(s, "no-hold") == 0))
164 r->actions |= ACT_IMMEDIATE;
165 else if ((strcmp(s, "indefinite") == 0) ||
166 (strcmp(s, "hold") == 0))
167 r->actions |= ACT_HOLD;
168 }
169
170 /* set lp charset/printwheel */
171 papiAttributeListGetLPString(attributes, "lp-charset", &r->charset);
172
173 /* legacy pr(1) filter related garbage "lpr -p" */
174 papiAttributeListGetBoolean(attributes, NULL, "pr-filter", &pr_filter);
175 papiAttributeListGetString(attributes, NULL, "pr-title", &pr_title);
176 papiAttributeListGetInteger(attributes, NULL, "pr-width", &pr_width);
177 papiAttributeListGetInteger(attributes, NULL, "pr-indent", &pr_indent);
178
179 if (pr_filter != 0) {
180 char buf[128];
181
182 if (pr_title != NULL) {
183 snprintf(buf, sizeof (buf), "prtitle='%s'", pr_title);
184 appendlist(&modes, buf);
185 }
186
187 if (pr_width > 0) {
188 snprintf(buf, sizeof (buf), "prwidth=%d", pr_width);
189 appendlist(&modes, buf);
190 }
191
192 if (pr_indent > 0) {
193 snprintf(buf, sizeof (buf), "indent=%d", pr_indent);
194 appendlist(&modes, buf);
195 }
196 } else if ((pr_title != NULL) || (pr_width >= 0) || (pr_indent >= 0))
197 detailed_error(svc, gettext(
198 "pr(1) filter options specified without enabling pr(1) filter"));
199
200 /* add burst page information */
201 s = NULL;
202 papiAttributeListGetString(attributes, NULL, "job-sheets", &s);
203 if ((s != NULL) && (strcasecmp(s, "none") != 0)) {
204 char buf[128];
205 char *class = NULL;
206 char *job_name = NULL;
207
208 papiAttributeListGetLPString(attributes, "job-class", &class);
209 papiAttributeListGetLPString(attributes, "job-name", &job_name);
210
211 /* burst page is enabled by default, add the title */
212 snprintf(buf, sizeof (buf), "%s%s%s",
213 (job_name ? job_name : ""),
214 (job_name && class ? "\\n#####\\n#####\\t\\t " : ""),
215 (class ? class : ""));
216 if (buf[0] != '\0') {
217 if (r->title != NULL)
218 free(r->title);
219 r->title = strdup(buf);
220 }
221 } else if ((s != NULL) && (strcasecmp(s, "none") == 0)) {
222 /* burst page is disabled via lp "option" */
223 appendlist(&options, "nobanner");
224 }
225
226 /* Convert attribute "number-up" to mode group=n */
227 papiAttributeListGetInteger(attributes, NULL, "number-up", &numberUp);
228 if ((numberUp >= 2) && ((numberUp % 2) == 0)) {
229 snprintf(buf, sizeof (buf), "group=%d", numberUp);
230 appendlist(&modes, buf);
231 }
232
233 /*
234 * Convert attribute "orientation-requested" to modes
235 * 'landscape', 'portrait', etc.
236 */
237 papiAttributeListGetInteger(attributes, NULL,
238 "orientation-requested", &orientation);
239 if ((orientation >= 3) && (orientation <= 6)) {
240 switch (orientation) {
241 case 4: /* landscape */
242 case 5: /* reverse-landscape, use landscape instead */
243 appendlist(&modes, "landscape");
244 break;
245 case 3: /* portrait */
246 case 6: /* reverse-portrait, use portrait instead */
247 default:
248 appendlist(&modes, "portrait");
249 break;
250 }
251 }
252
253 /* add "lp -y" modes */
254 attr = papiAttributeListFind(attributes, "lp-modes");
255 if ((attr != NULL) && (attr->type == PAPI_STRING) &&
256 (attr->values != NULL)) {
257 int i;
258
259 for (i = 0; attr->values[i] != NULL; i++)
260 appendlist(&modes, attr->values[i]->string);
261 }
262
263 if (modes != NULL) {
264 if (r->modes == NULL)
265 free(r->modes);
266 r->modes = sprintlist(modes);
267 freelist(modes);
268 }
269
270 /* add any unconsumed attributes to the "options" list */
271 split_and_copy_attributes(mapped_keys, attributes, NULL, &unmapped);
272 if (unmapped != NULL) { /* convert them to lp options */
273 char *buf = malloc(1024);
274 ssize_t size = 1024;
275
276 while (papiAttributeListToString(unmapped, " ", buf, size)
277 != PAPI_OK) {
278 size += 1024;
279 buf = realloc(buf, size);
280 }
281 appendlist(&options, buf);
282 free(buf);
283 papiAttributeListFree(unmapped);
284 }
285
286 if (options != NULL) {
287 if (r->options != NULL)
288 free(r->options);
289 r->options = sprintlist(options);
290 freelist(options);
291 }
292
293 return (PAPI_OK);
294 }
295
296 /*
297 * Convert REQUEST->outcome (or R_REQUEST_* state) to the equivalent
298 * PAPI attribute representation.
299 */
300 static void
lpsched_request_outcome_to_attributes(papi_attribute_t *** attributes,unsigned short state)301 lpsched_request_outcome_to_attributes(papi_attribute_t ***attributes,
302 unsigned short state)
303 {
304 if (attributes == NULL)
305 return;
306
307 if (state & RS_NOTIFYING) {
308 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
309 "job-state", 0x0800); /* notifying user */
310 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
311 "job-state-reasons", "job-notifying");
312 } else if (state & RS_HELD) {
313 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
314 "job-state", 0x0001); /* held */
315 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
316 "job-state-reasons", "job-hold-until-specified");
317 } else if (state & RS_CANCELLED) {
318 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
319 "job-state", 0x0040); /* job cancelled */
320 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
321 "job-state-reasons", "job-canceled-by-user");
322 } else if (state & RS_PRINTED) {
323 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
324 "job-state", 0x0010); /* finished printing job */
325 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
326 "job-state-reasons", "job-complete");
327 } else if (state & RS_PRINTING) {
328 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
329 "job-state", 0x0008); /* printing job */
330 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
331 "job-state-reasons", "job-printing");
332 } else if (state & RS_ADMINHELD) {
333 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
334 "job-state", 0x2000); /* held by admin */
335 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
336 "job-state-reasons", "job-hold-until-specified");
337 } else if (state & RS_FILTERED) {
338 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
339 "job-state", 0x0004); /* filtered */
340 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
341 "job-state-reasons", "job-filtered");
342 } else if (state & RS_CHANGING) {
343 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
344 "job-state", 0x0020); /* job held for changing */
345 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
346 "job-state-reasons", "job-held-for-change");
347 } else if (state & RS_FILTERING) {
348 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
349 "job-state", 0x0002); /* being filtered */
350 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
351 "job-state-reasons", "job-being-filtered");
352 } else {
353 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE,
354 "job-state", 0x4000); /* else */
355 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
356 "job-state-reasons", "job-queued");
357 }
358
359
360
361 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE,
362 "job-hold-until",
363 ((state & RS_HELD) ? "indefinite" : "no-hold"));
364 }
365
366 /*
367 * convert user[@host] to papi attributes
368 */
369 static void
lpsched_user_to_job_attributes(papi_attribute_t *** list,char * user)370 lpsched_user_to_job_attributes(papi_attribute_t ***list, char *user)
371 {
372 if ((list != NULL) && (user != NULL) && (user[0] != NULL)) {
373 char *host = strrchr(user, '@');
374
375 if (host != NULL) {
376 *host = NULL;
377 papiAttributeListAddString(list, PAPI_ATTR_REPLACE,
378 "job-originating-user-name", user);
379 papiAttributeListAddString(list, PAPI_ATTR_REPLACE,
380 "job-originating-host-name", host + 1);
381 *host = '@';
382 } else
383 papiAttributeListAddString(list, PAPI_ATTR_REPLACE,
384 "job-originating-user-name", user);
385 }
386 }
387
388 /*
389 * Convert REQUEST structure to the equivalent PAPI attribute representation.
390 */
391 void
lpsched_request_to_job_attributes(REQUEST * r,job_t * j)392 lpsched_request_to_job_attributes(REQUEST *r, job_t *j)
393 {
394 char *tmp;
395 int i;
396
397 /* copies */
398 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
399 "copies", r->copies);
400
401 /* destination */
402 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE,
403 "printer-name", r->destination);
404
405 /* form */
406 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE,
407 "form", r->form);
408
409 /* options */
410 papiAttributeListFromString(&j->attributes, PAPI_ATTR_APPEND,
411 r->options);
412
413 tmp = (((r->options != NULL) && (strstr(r->options, "nobanner")
414 != NULL)) ? "none" : "standard");
415 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
416 "job-sheets", tmp);
417
418 tmp = (((r->options != NULL) && (strstr(r->options, "duplex")
419 != NULL)) ? "two-sized" : "one-sided");
420 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
421 "sides", tmp);
422
423 i = (((r->options != NULL) && (strstr(r->options, "landscape")
424 != NULL)) ? 4 : 3);
425 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
426 "orientation-requested", i);
427
428 /* priority (map 0-39 to 1-100) */
429 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
430 "job-priority",
431 (int)(100 - (r->priority * 2.5)));
432
433 /* pages */
434 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE,
435 "page-ranges", r->pages);
436
437 /* charset */
438 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE,
439 "lp-charset", r->charset);
440
441 /* modes */
442 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE,
443 "lp-modes", r->modes);
444
445 /* title */
446 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE,
447 "job-name", r->title);
448
449 /* input_type */
450
451 /* user */
452 lpsched_user_to_job_attributes(&j->attributes, r->user);
453
454 /* outcome */
455 lpsched_request_outcome_to_attributes(&j->attributes, r->outcome);
456
457 /* constants, (should be derived from options) */
458 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
459 "number-up", 1);
460
461 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
462 "multiple-document-handling",
463 "seperate-documents-collated-copies");
464 }
465
466 /*
467 * Convert R_REQUEST_* results to the equivalent PAPI attribute representation.
468 */
469 void
job_status_to_attributes(job_t * job,char * req_id,char * user,char * slabel,size_t size,time_t date,short state,char * destination,char * form,char * charset,short rank,char * file)470 job_status_to_attributes(job_t *job, char *req_id, char *user, char *slabel,
471 size_t size, time_t date, short state, char *destination,
472 char *form, char *charset, short rank, char *file)
473 {
474 char buf[BUFSIZ];
475 char *p;
476
477 lpsched_user_to_job_attributes(&job->attributes, user);
478 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE,
479 "job-k-octets", size/1024);
480 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE,
481 "job-octets", size);
482 if ((p = strrchr(req_id, '-')) != NULL) {
483 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE,
484 "job-id", atoi(++p));
485 }
486 snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s/%d",
487 destination, atoi(p));
488 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE,
489 "job-uri", buf);
490 snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s",
491 destination);
492 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE,
493 "job-printer-uri", buf);
494 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE,
495 "job-printer-up-time", time(NULL));
496 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE,
497 "output-device-assigned", destination);
498 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE,
499 "printer-name", destination);
500 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE,
501 "form", form);
502
503 lpsched_request_outcome_to_attributes(&job->attributes, state);
504
505 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE,
506 "time-at-creation", date);
507 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE,
508 "lpsched-request-id", req_id);
509 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE,
510 "lp-charset", charset);
511 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE,
512 "lpsched-job-state", state);
513 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE,
514 "number-of-intervening-jobs", rank - 1);
515 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE,
516 "lpsched-file", file);
517 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL,
518 "job-name", file);
519 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL,
520 "tsol-sensitivity-label", slabel);
521 }
522
523 void
lpsched_read_job_configuration(service_t * svc,job_t * j,char * file)524 lpsched_read_job_configuration(service_t *svc, job_t *j, char *file)
525 {
526 REQUEST *r;
527
528 if ((r = getrequest(file)) == NULL) {
529 detailed_error(svc, gettext("unable to read job data: %s"),
530 file);
531 return;
532 }
533
534 lpsched_request_to_job_attributes(r, j);
535 }
536