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