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