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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*LINTLIBRARY*/
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <libintl.h>
31 #include <pwd.h>
32 #include <sys/stat.h>
33 #include <papi_impl.h>
34
35 /*
36 * for an older application that may have been linked with a pre-v1.0
37 * PAPI implementation.
38 */
39 papi_status_t
papiAttributeListAdd(papi_attribute_t *** attrs,int flags,char * name,papi_attribute_value_type_t type,papi_attribute_value_t * value)40 papiAttributeListAdd(papi_attribute_t ***attrs, int flags, char *name,
41 papi_attribute_value_type_t type, papi_attribute_value_t *value)
42 {
43 return (papiAttributeListAddValue(attrs, flags, name, type, value));
44 }
45
46 #ifdef LP_USE_PAPI_ATTR
47 static papi_status_t psm_modifyAttrsFile(papi_attribute_t **attrs, char *file);
48 static papi_status_t psm_modifyAttrsList(char *file, papi_attribute_t **attrs,
49 papi_attribute_t ***newAttrs);
50 #endif
51
52 int32_t
check_job_id(papi_service_t svc,char * printer,int32_t id)53 check_job_id(papi_service_t svc, char *printer, int32_t id)
54 {
55 papi_job_t *jobs = NULL;
56 papi_status_t status;
57 int ret = -1;
58 char *jattrs[] = { "job-id",
59 "job-id-requested", NULL };
60
61 status = papiPrinterListJobs(svc, printer, jattrs, PAPI_LIST_JOBS_ALL,
62 0, &jobs);
63
64 if (status != PAPI_OK) {
65 detailed_error(svc,
66 gettext("Failed to query service for %s: %s\n"),
67 printer, lpsched_status_string(status));
68 return (-1);
69 }
70
71 if (jobs != NULL) {
72 int i = 0;
73
74 for (i = 0; jobs[i] != NULL; i++) {
75 int32_t rid = -1;
76 int32_t jid = -1;
77 papi_attribute_t **list =
78 papiJobGetAttributeList(jobs[i]);
79
80 papiAttributeListGetInteger(list, NULL,
81 "job-id-requested", &rid);
82 papiAttributeListGetInteger(list, NULL,
83 "job-id", &jid);
84
85 /*
86 * check if id matches with either rid or jid
87 */
88 if (rid == id) {
89 /* get the actual id and return it */
90 papiAttributeListGetInteger(list, NULL,
91 "job-id", &id);
92 return (id);
93 } else if (jid == id) {
94 if (rid != -1) {
95 /*
96 * It is a remote lpd job.
97 * It cannot be modified based on job-id
98 * or spool number
99 */
100 return (-1);
101 } else {
102 /*
103 * It is either local job or
104 * remote ipp job
105 */
106 return (id);
107 }
108 }
109 }
110 }
111 return (id);
112 }
113
114 void
papiJobFree(papi_job_t job)115 papiJobFree(papi_job_t job)
116 {
117 job_t *tmp = (job_t *)job;
118
119 if (tmp != NULL) {
120 papiAttributeListFree(tmp->attributes);
121 free(tmp);
122 }
123 }
124
125 void
papiJobListFree(papi_job_t * jobs)126 papiJobListFree(papi_job_t *jobs)
127 {
128 if (jobs != NULL) {
129 int i;
130
131 for (i = 0; jobs[i] != NULL; i++) {
132 papiJobFree(jobs[i]);
133 }
134 free(jobs);
135 }
136 }
137
138 papi_attribute_t **
papiJobGetAttributeList(papi_job_t job)139 papiJobGetAttributeList(papi_job_t job)
140 {
141 job_t *tmp = (job_t *)job;
142
143 if (tmp != NULL)
144 return (tmp->attributes);
145
146 return (NULL);
147 }
148
149 char *
papiJobGetPrinterName(papi_job_t job)150 papiJobGetPrinterName(papi_job_t job)
151 {
152 job_t *tmp = (job_t *)job;
153 char *result = NULL;
154
155 if (tmp != NULL)
156 papiAttributeListGetString(tmp->attributes, NULL,
157 "printer-name", &result);
158
159 return (result);
160 }
161
162 int32_t
papiJobGetId(papi_job_t job)163 papiJobGetId(papi_job_t job)
164 {
165 job_t *tmp = (job_t *)job;
166 int result = -1;
167
168 if (tmp != NULL)
169 papiAttributeListGetInteger(tmp->attributes, NULL, "job-id",
170 &result);
171
172 return (result);
173 }
174
175 static REQUEST *
create_request(papi_service_t svc,char * printer,papi_attribute_t ** attributes)176 create_request(papi_service_t svc, char *printer, papi_attribute_t **attributes)
177 {
178 REQUEST *r;
179
180 if ((r = calloc(1, sizeof (*r))) != NULL) {
181 char *hostname = NULL;
182
183 r->priority = -1;
184 r->destination = printer_name_from_uri_id(printer, -1);
185
186 papiAttributeListGetString(attributes, NULL,
187 "job-originating-host-name", &hostname);
188
189 if (hostname == NULL) {
190 char host[BUFSIZ];
191
192 if (gethostname(host, sizeof (host)) == 0)
193 papiAttributeListAddString(&attributes,
194 PAPI_ATTR_REPLACE,
195 "job-originating-host-name",
196 host);
197 }
198
199 job_attributes_to_lpsched_request(svc, r, attributes);
200 }
201
202 return (r);
203 }
204
205 static papi_status_t
authorized(service_t * svc,int32_t id)206 authorized(service_t *svc, int32_t id)
207 {
208 papi_status_t result = PAPI_NOT_AUTHORIZED; /* assume the worst */
209 char file[32];
210 REQUEST *r;
211
212 snprintf(file, sizeof (file), "%d-0", id);
213 if ((r = getrequest(file)) != NULL) {
214 uid_t uid = getuid();
215 struct passwd *pw = NULL;
216 char *user = "intruder"; /* assume an intruder */
217
218 if ((pw = getpwuid(uid)) != NULL)
219 user = pw->pw_name; /* use the process owner */
220
221 if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */
222 papi_status_t s;
223 s = papiAttributeListGetString(svc->attributes, NULL,
224 "user-name", &user);
225 if (s != PAPI_OK) /* true root/lp are almighty */
226 result = PAPI_OK;
227 }
228
229 if (result != PAPI_OK) {
230 if (strcmp(user, r->user) == 0)
231 result = PAPI_OK;
232 else {
233 /*
234 * user and r->user might contain the
235 * host info also
236 */
237 char *token1 = strtok(r->user, "@");
238 char *token2 = strtok(NULL, "@");
239 char *token3 = strtok(user, "@");
240 char *token4 = strtok(NULL, "@");
241
242 /*
243 * token1 and token3 contain usernames
244 * token2 and token4 contain hostnames
245 */
246 if ((token1 == NULL) || (token3 == NULL))
247 result = PAPI_NOT_AUTHORIZED;
248 else if ((token4 != NULL) &&
249 (strcmp(token4, "localhost") == 0) &&
250 (strcmp(token3, "root") == 0) ||
251 (strcmp(token3, "lp") == 0)) {
252 /*
253 * root/lp user on server can
254 * cancel any requset
255 */
256 result = PAPI_OK;
257 } else if (strcmp(token1, token3) == 0) {
258 /*
259 * usernames are same
260 * compare the hostnames
261 */
262 if ((token4 != NULL) &&
263 (token2 != NULL) &&
264 (strcmp(token4, "localhost") ==
265 0)) {
266 /*
267 * Its server machine
268 */
269 static char host[256];
270 if (gethostname(host,
271 sizeof (host)) == 0) {
272 if ((host != NULL) &&
273 (strcmp(host,
274 token2) == 0))
275 result =
276 PAPI_OK;
277 }
278
279 } else if ((token4 != NULL) &&
280 (token2 != NULL) &&
281 (strcmp(token4, token2) == 0)) {
282 result = PAPI_OK;
283 } else if ((token4 == NULL) &&
284 (token2 != NULL)) {
285 /*
286 * When the request is sent from
287 * client to server using ipp
288 * token4 is NULL
289 */
290 result = PAPI_OK;
291 }
292 }
293 }
294 }
295
296 freerequest(r);
297 } else
298 result = PAPI_NOT_FOUND;
299
300 return (result);
301 }
302
303 static papi_status_t
copy_file(char * from,char * to)304 copy_file(char *from, char *to)
305 {
306 int ifd, ofd;
307 char buf[BUFSIZ];
308 int rc;
309
310 if ((ifd = open(from, O_RDONLY)) < 0)
311 return (PAPI_DOCUMENT_ACCESS_ERROR);
312
313 if ((ofd = open(to, O_WRONLY)) < 0) {
314 close(ifd);
315 return (PAPI_NOT_POSSIBLE);
316 }
317
318 while ((rc = read(ifd, buf, sizeof (buf))) > 0)
319 write(ofd, buf, rc);
320
321 close(ifd);
322 close(ofd);
323
324 return (PAPI_OK);
325 }
326
327
328 #ifdef LP_USE_PAPI_ATTR
329 /*
330 * *****************************************************************************
331 *
332 * Description: Create a file containing all the attributes in the attribute
333 * list passed to this function.
334 * This file is then passed through lpsched and given to either
335 * a slow-filter or to the printer's interface script to process
336 * the attributes.
337 *
338 * Parameters: attrs - list of attributes and their values
339 * file - file pathname to create and put the attributes into.
340 *
341 * *****************************************************************************
342 */
343
344 static papi_status_t
psm_copy_attrsToFile(papi_attribute_t ** attrs,char * file)345 psm_copy_attrsToFile(papi_attribute_t **attrs, char *file)
346
347 {
348 papi_status_t result = PAPI_OK;
349
350 if ((attrs != NULL) && (*attrs != NULL)) {
351 FILE *out = NULL;
352
353 if ((out = fopen(file, "w")) != NULL) {
354 papiAttributeListPrint(out, attrs, "");
355 fclose(out);
356 } else {
357 result = PAPI_NOT_POSSIBLE;
358 }
359 }
360
361 return (result);
362 } /* psm_copy_attrsToFile */
363
364
365 /*
366 * *****************************************************************************
367 *
368 * Description: Modify the given attribute 'file' with the attributes from the
369 * 'attrs' list. Attributes already in the file will be replaced
370 * with the new value. New attributes will be added into the file.
371 *
372 * Parameters: attrs - list of attributes and their values
373 * file - file pathname to create and put the attributes into.
374 *
375 * *****************************************************************************
376 */
377
378 static papi_status_t
psm_modifyAttrsFile(papi_attribute_t ** attrs,char * file)379 psm_modifyAttrsFile(papi_attribute_t **attrs, char *file)
380
381 {
382 papi_status_t result = PAPI_OK;
383 papi_attribute_t **newAttrs = NULL;
384 struct stat tmpBuf;
385 FILE *fd = NULL;
386
387 if ((attrs != NULL) && (*attrs != NULL) && (file != NULL)) {
388
389 /*
390 * check file exist before try to modify it, if it doesn't
391 * exist assume there is an error
392 */
393 if (stat(file, &tmpBuf) == 0) {
394 /*
395 * if file is currently empty just write the given
396 * attributes to the file otherwise exact the attributes
397 * from the file and modify them accordingly before
398 * writing them back to the file
399 */
400 if (tmpBuf.st_size == 0) {
401 newAttrs = (papi_attribute_t **)attrs;
402
403 fd = fopen(file, "w");
404 if (fd != NULL) {
405 papiAttributeListPrint(fd,
406 newAttrs, "");
407 fclose(fd);
408 } else {
409 result = PAPI_NOT_POSSIBLE;
410 }
411 } else {
412 result =
413 psm_modifyAttrsList(file, attrs, &newAttrs);
414
415 fd = fopen(file, "w");
416 if (fd != NULL) {
417 papiAttributeListPrint(fd,
418 newAttrs, "");
419 fclose(fd);
420 } else {
421 result = PAPI_NOT_POSSIBLE;
422 }
423
424 papiAttributeListFree(newAttrs);
425 }
426 } else {
427 result = PAPI_NOT_POSSIBLE;
428 }
429 }
430
431 return (result);
432 } /* psm_modifyAttrsFile */
433
434
435 /*
436 * *****************************************************************************
437 *
438 * Description: Extracts the attributes in the given attribute 'file' and
439 * creates a new list 'newAttrs' containing the modified list of
440 * attributes.
441 *
442 * Parameters: file - pathname of file containing attributes to be modified
443 * attrs - list of attributes and their values to modify
444 * newAttrs - returns the modified list of attributes
445 *
446 * *****************************************************************************
447 */
448
449 static papi_status_t
psm_modifyAttrsList(char * file,papi_attribute_t ** attrs,papi_attribute_t *** newAttrs)450 psm_modifyAttrsList(char *file, papi_attribute_t **attrs,
451 papi_attribute_t ***newAttrs)
452
453 {
454 papi_status_t result = PAPI_OK;
455 papi_attribute_t *nextAttr = NULL;
456 papi_attribute_value_t **values = NULL;
457 void *iter = NULL;
458 FILE *fd = NULL;
459 register int fD = 0;
460 char aBuff[200];
461 char *a = NULL;
462 char *p = NULL;
463 int count = 0;
464 int n = 0;
465
466 fd = fopen(file, "r");
467 if (fd != NULL) {
468 fD = fileno(fd);
469 a = &aBuff[0];
470 p = &aBuff[0];
471 count = read(fD, &aBuff[0], sizeof (aBuff) - 1);
472 while ((result == PAPI_OK) && (count > 0)) {
473 aBuff[count+n] = '\0';
474 if (count == sizeof (aBuff) - n - 1) {
475 p = strrchr(aBuff, '\n');
476 if (p != NULL) {
477 /* terminate at last complete line */
478 *p = '\0';
479 }
480 }
481 result = papiAttributeListFromString(
482 newAttrs, PAPI_ATTR_EXCL, aBuff);
483
484 if (result == PAPI_OK) {
485 /*
486 * handle any part lines and then read the next
487 * buffer from the file
488 */
489 n = 0;
490 if (p != a) {
491 p++; /* skip NL */
492 n = sizeof (aBuff) - 1 - (p - a);
493 strncpy(aBuff, p, n);
494 }
495 count = read(fD, &aBuff[n],
496 sizeof (aBuff) - n - 1);
497 p = &aBuff[0];
498 }
499 }
500 fclose(fd);
501 }
502
503 /* now modify the attribute list with the new attributes in 'attrs' */
504
505 nextAttr = papiAttributeListGetNext((papi_attribute_t **)attrs, &iter);
506 while ((result == PAPI_OK) && (nextAttr != NULL)) {
507 values = nextAttr->values;
508
509 if ((values != NULL) && (*values != NULL)) {
510 result = papiAttributeListAddValue(newAttrs,
511 PAPI_ATTR_REPLACE,
512 nextAttr->name,
513 nextAttr->type, *values);
514 values++;
515 }
516
517 while ((result == PAPI_OK) &&
518 (values != NULL) && (*values != NULL)) {
519 result = papiAttributeListAddValue(newAttrs,
520 PAPI_ATTR_APPEND,
521 nextAttr->name,
522 nextAttr->type, *values);
523 values++;
524 }
525 nextAttr =
526 papiAttributeListGetNext((papi_attribute_t **)attrs, &iter);
527 }
528
529 return (result);
530 } /* papi_modifyAttrsList() */
531 #endif
532
533
534 papi_status_t
papiJobSubmit(papi_service_t handle,char * printer,papi_attribute_t ** job_attributes,papi_job_ticket_t * job_ticket,char ** files,papi_job_t * job)535 papiJobSubmit(papi_service_t handle, char *printer,
536 papi_attribute_t **job_attributes,
537 papi_job_ticket_t *job_ticket,
538 char **files, papi_job_t *job)
539 {
540 papi_status_t status;
541 service_t *svc = handle;
542 struct stat statbuf;
543 job_t *j;
544 int file_no;
545 char *request_id = NULL;
546 REQUEST *request;
547 int i;
548 char *c;
549 char *tmp = NULL;
550 char lpfile[BUFSIZ];
551
552 if ((svc == NULL) || (printer == NULL) || (files == NULL) ||
553 (job == NULL))
554 return (PAPI_BAD_ARGUMENT);
555
556 if (job_ticket != NULL)
557 return (PAPI_OPERATION_NOT_SUPPORTED);
558
559 if (files != NULL)
560 for (file_no = 0; files[file_no] != NULL; file_no++) {
561 if (access(files[file_no], R_OK) < 0) {
562 detailed_error(svc,
563 gettext("Cannot access file: %s: %s"),
564 files[file_no], strerror(errno));
565 return (PAPI_BAD_ARGUMENT);
566 }
567 if (stat(files[file_no], &statbuf) < 0) {
568 detailed_error(svc,
569 gettext("Cannot access file: %s: %s"),
570 files[file_no], strerror(errno));
571 return (PAPI_DOCUMENT_ACCESS_ERROR);
572 }
573 if (statbuf.st_size == 0) {
574 detailed_error(svc,
575 gettext("Zero byte (empty) file: %s"),
576 files[file_no]);
577 return (PAPI_BAD_ARGUMENT);
578 }
579 }
580
581 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
582 return (PAPI_TEMPORARY_ERROR);
583
584 /* file_no + 1 for the control file (-0) */
585 status = lpsched_alloc_files(svc, file_no + 1, &request_id);
586 if (status != PAPI_OK)
587 return (status);
588
589 request = create_request(svc, (char *)printer,
590 (papi_attribute_t **)job_attributes);
591
592 for (i = 0; files[i] != NULL; i++) {
593 papi_status_t status;
594 snprintf(lpfile, sizeof (lpfile), "%s%s-%d",
595 "/var/spool/lp/temp/", request_id, i+1);
596 status = copy_file(files[i], lpfile);
597 if (status != PAPI_OK) {
598 detailed_error(svc,
599 gettext("unable to copy: %s -> %s: %s"),
600 files[i], lpfile, strerror(errno));
601 freerequest(request);
602 return (PAPI_DEVICE_ERROR);
603 }
604 addlist(&(request->file_list), lpfile);
605 }
606
607 #ifdef LP_USE_PAPI_ATTR
608 /*
609 * store the job attributes in the PAPI job attribute file that was
610 * created by lpsched_alloc_files(), the attributes will then pass
611 * through lpsched and be given to the slow-filters and the printer's
612 * interface script to process them
613 */
614 snprintf(lpfile, sizeof (lpfile), "%s%s-%s",
615 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
616 status = psm_copy_attrsToFile(job_attributes, lpfile);
617 if (status != PAPI_OK) {
618 detailed_error(svc, "unable to copy attributes to file: %s: %s",
619 lpfile, strerror(errno));
620 return (PAPI_DEVICE_ERROR);
621 }
622 #endif
623
624 /* store the meta-data file */
625 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id);
626 if (putrequest(lpfile, request) < 0) {
627 detailed_error(svc, gettext("unable to save request: %s: %s"),
628 lpfile, strerror(errno));
629 freerequest(request);
630 return (PAPI_DEVICE_ERROR);
631 }
632
633 status = lpsched_commit_job(svc, lpfile, &tmp);
634 if (status != PAPI_OK) {
635 unlink(lpfile);
636 freerequest(request);
637 return (status);
638 }
639
640 lpsched_request_to_job_attributes(request, j);
641 freerequest(request);
642
643 if ((c = strrchr(tmp, '-')) != NULL)
644 c++;
645 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
646 "job-id", atoi(c));
647 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
648 "job-uri", tmp);
649
650 return (PAPI_OK);
651 }
652
653 papi_status_t
papiJobSubmitByReference(papi_service_t handle,char * printer,papi_attribute_t ** job_attributes,papi_job_ticket_t * job_ticket,char ** files,papi_job_t * job)654 papiJobSubmitByReference(papi_service_t handle, char *printer,
655 papi_attribute_t **job_attributes,
656 papi_job_ticket_t *job_ticket,
657 char **files, papi_job_t *job)
658 {
659 service_t *svc = handle;
660 struct stat statbuf;
661 job_t *j;
662 int file_no;
663 short status;
664 char *request_id = NULL;
665 REQUEST *request;
666 char *c;
667 char *tmp = NULL;
668 char lpfile[BUFSIZ];
669 char **file_list = NULL;
670
671 if ((svc == NULL) || (printer == NULL) || (files == NULL) ||
672 (job == NULL))
673 return (PAPI_BAD_ARGUMENT);
674
675 if (job_ticket != NULL)
676 return (PAPI_OPERATION_NOT_SUPPORTED);
677
678 if (files != NULL)
679 for (file_no = 0; files[file_no] != NULL; file_no++) {
680 if (access(files[file_no], R_OK) < 0) {
681 detailed_error(svc,
682 gettext("Cannot access file: %s: %s"),
683 files[file_no], strerror(errno));
684 return (PAPI_DOCUMENT_ACCESS_ERROR);
685 }
686 if (stat(files[file_no], &statbuf) < 0) {
687 detailed_error(svc,
688 gettext("Cannot access file: %s: %s"),
689 files[file_no], strerror(errno));
690 return (PAPI_DOCUMENT_ACCESS_ERROR);
691 }
692 if (statbuf.st_size == 0) {
693 detailed_error(svc,
694 gettext("Zero byte (empty) file: %s"),
695 files[file_no]);
696 return (PAPI_BAD_ARGUMENT);
697 }
698
699 if (files[file_no][0] != '/') {
700 char path[MAXPATHLEN];
701
702 if (getcwd(path, sizeof (path)) == NULL) {
703 detailed_error(svc, gettext(
704 "getcwd for file: %s: %s"),
705 files[file_no],
706 strerror(errno));
707 return (PAPI_DOCUMENT_ACCESS_ERROR);
708 }
709 strlcat(path, "/", sizeof (path));
710 if (strlcat(path, files[file_no], sizeof (path))
711 >= sizeof (path)) {
712 detailed_error(svc, gettext(
713 "pathname too long: %s"),
714 files[file_no]);
715 return (PAPI_DOCUMENT_ACCESS_ERROR);
716 }
717 addlist(&file_list, path);
718 } else
719 addlist(&file_list, (char *)files[file_no]);
720 }
721
722 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
723 return (PAPI_TEMPORARY_ERROR);
724
725 /* 1 for the control file (-0) */
726 status = lpsched_alloc_files(svc, 1, &request_id);
727 if (status != PAPI_OK)
728 return (status);
729
730 request = create_request(svc, (char *)printer,
731 (papi_attribute_t **)job_attributes);
732 request->file_list = file_list;
733
734 #ifdef LP_USE_PAPI_ATTR
735 /*
736 * store the job attributes in the PAPI job attribute file that was
737 * created by lpsched_alloc_files(), the attributes will then pass
738 * through lpsched and be given to the slow-filters and the printer's
739 * interface script to process them
740 */
741 snprintf(lpfile, sizeof (lpfile), "%s%s-%s",
742 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
743 status = psm_copy_attrsToFile(job_attributes, lpfile);
744 if (status != PAPI_OK) {
745 detailed_error(svc, "unable to copy attributes to file: %s: %s",
746 lpfile, strerror(errno));
747 return (PAPI_DEVICE_ERROR);
748 }
749 #endif
750
751 /* store the meta-data file */
752 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id);
753 if (putrequest(lpfile, request) < 0) {
754 detailed_error(svc, gettext("unable to save request: %s: %s"),
755 lpfile, strerror(errno));
756 freerequest(request);
757 return (PAPI_DEVICE_ERROR);
758 }
759
760 status = lpsched_commit_job(svc, lpfile, &tmp);
761 if (status != PAPI_OK) {
762 unlink(lpfile);
763 freerequest(request);
764 return (status);
765 }
766
767 lpsched_request_to_job_attributes(request, j);
768
769 freerequest(request);
770
771 if ((c = strrchr(tmp, '-')) != NULL)
772 c++;
773 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
774 "job-id", atoi(c));
775 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
776 "job-uri", tmp);
777
778 return (PAPI_OK);
779 }
780
781 papi_status_t
papiJobValidate(papi_service_t handle,char * printer,papi_attribute_t ** job_attributes,papi_job_ticket_t * job_ticket,char ** files,papi_job_t * job)782 papiJobValidate(papi_service_t handle, char *printer,
783 papi_attribute_t **job_attributes,
784 papi_job_ticket_t *job_ticket,
785 char **files, papi_job_t *job)
786 {
787 papi_status_t status;
788 papi_attribute_t **attributes = NULL;
789 int i;
790
791 papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE,
792 "job-hold-until", "indefinite");
793 for (i = 0; job_attributes[i]; i++)
794 list_append(&attributes, job_attributes[i]);
795
796 status = papiJobSubmitByReference(handle, printer,
797 (papi_attribute_t **)attributes,
798 job_ticket, files, job);
799 if (status == PAPI_OK) {
800 int id = papiJobGetId(*job);
801
802 if (id != -1)
803 papiJobCancel(handle, printer, id);
804 }
805
806 attributes[1] = NULL; /* after attr[0], they are in another list */
807 papiAttributeListFree(attributes);
808
809 return (status);
810 }
811
812 papi_status_t
papiJobStreamOpen(papi_service_t handle,char * printer,papi_attribute_t ** job_attributes,papi_job_ticket_t * job_ticket,papi_stream_t * stream)813 papiJobStreamOpen(papi_service_t handle, char *printer,
814 papi_attribute_t **job_attributes,
815 papi_job_ticket_t *job_ticket, papi_stream_t *stream)
816 {
817 papi_status_t status;
818 service_t *svc = handle;
819 job_stream_t *s = NULL;
820 char *request_id = NULL;
821 char lpfile[BUFSIZ];
822
823 if ((svc == NULL) || (printer == NULL) || (stream == NULL))
824 return (PAPI_BAD_ARGUMENT);
825
826 if (job_ticket != NULL)
827 return (PAPI_OPERATION_NOT_SUPPORTED);
828
829 if ((*stream = s = calloc(1, sizeof (*s))) == NULL)
830 return (PAPI_TEMPORARY_ERROR);
831
832 /* 1 for data, 1 for the meta-data (-0) */
833 status = lpsched_alloc_files(svc, 2, &request_id);
834 if (status != PAPI_OK)
835 return (status);
836
837 papiAttributeListAddString(&job_attributes, PAPI_ATTR_EXCL,
838 "job-name", "standard input");
839
840 s->request = create_request(svc, (char *)printer,
841 (papi_attribute_t **)job_attributes);
842 snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1",
843 request_id);
844 s->fd = open(lpfile, O_WRONLY);
845 addlist(&(s->request->file_list), lpfile);
846
847 #ifdef LP_USE_PAPI_ATTR
848 /*
849 * store the job attributes in the PAPI job attribute file that was
850 * created by lpsched_alloc_files(), the attributes will then pass
851 * through lpsched and be given to the slow-filters and the printer's
852 * interface script to process them
853 */
854 snprintf(lpfile, sizeof (lpfile), "%s%s-%s",
855 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
856 status = psm_copy_attrsToFile(job_attributes, lpfile);
857 if (status != PAPI_OK) {
858 detailed_error(svc, "unable to copy attributes to file: %s: %s",
859 lpfile, strerror(errno));
860 close(s->fd);
861 free(s);
862 return (PAPI_DEVICE_ERROR);
863 }
864 #endif
865
866 /* store the meta-data file */
867 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id);
868 s->meta_data_file = strdup(lpfile);
869 if (putrequest(lpfile, s->request) < 0) {
870 detailed_error(svc, gettext("unable to save request: %s: %s"),
871 lpfile, strerror(errno));
872 s->request = NULL;
873 return (PAPI_DEVICE_ERROR);
874 }
875
876 return (PAPI_OK);
877 }
878
879 papi_status_t
papiJobStreamWrite(papi_service_t handle,papi_stream_t stream,void * buffer,size_t buflen)880 papiJobStreamWrite(papi_service_t handle,
881 papi_stream_t stream, void *buffer, size_t buflen)
882 {
883 service_t *svc = handle;
884 job_stream_t *s = stream;
885
886 if ((svc == NULL) || (stream == NULL) || (buffer == NULL))
887 return (PAPI_BAD_ARGUMENT);
888
889 if (write(s->fd, buffer, buflen) != buflen)
890 return (PAPI_DEVICE_ERROR);
891
892 return (PAPI_OK);
893 }
894 papi_status_t
papiJobStreamClose(papi_service_t handle,papi_stream_t stream,papi_job_t * job)895 papiJobStreamClose(papi_service_t handle,
896 papi_stream_t stream, papi_job_t *job)
897 {
898 papi_status_t status = PAPI_OK;
899 service_t *svc = handle;
900 job_stream_t *s = stream;
901 job_t *j = NULL;
902 char *tmp = NULL, *c;
903
904 if ((svc == NULL) || (stream == NULL) || (job == NULL))
905 return (PAPI_BAD_ARGUMENT);
906
907 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
908 return (PAPI_TEMPORARY_ERROR);
909
910 close(s->fd);
911
912 lpsched_request_to_job_attributes(s->request, j);
913
914 if (s->meta_data_file != NULL) {
915 status = lpsched_commit_job(svc, s->meta_data_file, &tmp);
916 if (status != PAPI_OK) {
917 unlink(s->meta_data_file);
918 return (status);
919 }
920 if ((c = strrchr(tmp, '-')) != NULL)
921 c++;
922 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
923 "job-id", atoi(c));
924 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
925 "job-uri", tmp);
926 free(s->meta_data_file);
927 }
928 freerequest(s->request);
929 free(s);
930
931 return (PAPI_OK);
932 }
933
934 papi_status_t
papiJobQuery(papi_service_t handle,char * printer,int32_t job_id,char ** requested_attrs,papi_job_t * job)935 papiJobQuery(papi_service_t handle, char *printer, int32_t job_id,
936 char **requested_attrs,
937 papi_job_t *job)
938 {
939 service_t *svc = handle;
940 job_t *j;
941 char *dest;
942 char req_id[32];
943 short rc;
944 char *form = NULL,
945 *request_id = NULL,
946 *charset = NULL,
947 *user = NULL,
948 *slabel = NULL,
949 *file = NULL;
950 time_t date = 0;
951 size_t size = 0;
952 short rank = 0,
953 state = 0;
954
955 if ((handle == NULL) || (printer == NULL) || (job_id < 0))
956 return (PAPI_BAD_ARGUMENT);
957
958 dest = printer_name_from_uri_id(printer, job_id);
959 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id);
960 free(dest);
961
962 rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", "");
963 if (rc < 0)
964 return (PAPI_SERVICE_UNAVAILABLE);
965
966 if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id,
967 &user, &slabel, &size, &date, &state, &dest, &form,
968 &charset, &rank, &file) < 0) {
969 detailed_error(svc,
970 gettext("failed to read response from scheduler"));
971 return (PAPI_DEVICE_ERROR);
972 }
973
974 if ((request_id == NULL) || (request_id[0] == NULL))
975 return (PAPI_NOT_FOUND);
976
977 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
978 return (PAPI_TEMPORARY_ERROR);
979
980 snprintf(req_id, sizeof (req_id), "%d-0", job_id);
981 lpsched_read_job_configuration(svc, j, req_id);
982
983 job_status_to_attributes(j, request_id, user, slabel, size, date, state,
984 dest, form, charset, rank, file);
985
986 return (PAPI_OK);
987 }
988
989 papi_status_t
papiJobMove(papi_service_t handle,char * printer,int32_t job_id,char * destination)990 papiJobMove(papi_service_t handle, char *printer, int32_t job_id,
991 char *destination)
992 {
993 papi_status_t result = PAPI_OK;
994 long bits;
995 service_t *svc = handle;
996 char req_id[64];
997 char *queue;
998 char *user = NULL;
999
1000 if ((svc == NULL) || (printer == NULL) || (job_id < 0) ||
1001 (destination == NULL))
1002 return (PAPI_BAD_ARGUMENT);
1003
1004 queue = printer_name_from_uri_id(printer, job_id);
1005 snprintf(req_id, sizeof (req_id), "%s-%d", queue, job_id);
1006 free(queue);
1007
1008 if (papiAttributeListGetString(svc->attributes, NULL, "user-name",
1009 &user) == PAPI_OK) {
1010 REQUEST *r = getrequest(req_id);
1011
1012 if ((r != NULL) && (r->user != NULL) &&
1013 (strcmp(r->user, user) != 0))
1014 result = PAPI_NOT_AUTHORIZED;
1015 freerequest(r);
1016 }
1017
1018 if (result == PAPI_OK) {
1019 short status = MOK;
1020 char *dest = printer_name_from_uri_id(destination, -1);
1021
1022 if ((snd_msg(svc, S_MOVE_REQUEST, req_id, dest) < 0) ||
1023 (rcv_msg(svc, R_MOVE_REQUEST, &status, &bits) < 0))
1024 status = MTRANSMITERR;
1025
1026 free(dest);
1027
1028 result = lpsched_status_to_papi_status(status);
1029 }
1030
1031 return (result);
1032 }
1033
1034 papi_status_t
papiJobCancel(papi_service_t handle,char * printer,int32_t job_id)1035 papiJobCancel(papi_service_t handle, char *printer, int32_t job_id)
1036 {
1037 papi_status_t result = PAPI_OK;
1038 service_t *svc = handle;
1039 char req_id[64];
1040 char *dest;
1041 char *user = NULL;
1042
1043 if ((svc == NULL) || (printer == NULL) || (job_id < 0))
1044 return (PAPI_BAD_ARGUMENT);
1045
1046 dest = printer_name_from_uri_id(printer, job_id);
1047 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id);
1048 free(dest);
1049
1050 if (papiAttributeListGetString(svc->attributes, NULL, "user-name",
1051 &user) == PAPI_OK) {
1052 REQUEST *r = getrequest(req_id);
1053
1054 if ((result = authorized(handle, job_id)) != PAPI_OK)
1055 result = PAPI_NOT_AUTHORIZED;
1056
1057 if ((r != NULL) && (r->user != NULL) &&
1058 (strcmp(r->user, user) != 0))
1059 result = PAPI_NOT_AUTHORIZED;
1060 freerequest(r);
1061 }
1062
1063 if (result == PAPI_OK) {
1064 short status = MOK;
1065
1066 if ((snd_msg(svc, S_CANCEL_REQUEST, req_id) < 0) ||
1067 (rcv_msg(svc, R_CANCEL_REQUEST, &status) < 0))
1068 status = MTRANSMITERR;
1069
1070 result = lpsched_status_to_papi_status(status);
1071 }
1072
1073 return (result);
1074 }
1075
1076 papi_status_t
hold_release_job(papi_service_t handle,char * printer,int32_t job_id,int flag)1077 hold_release_job(papi_service_t handle, char *printer,
1078 int32_t job_id, int flag)
1079 {
1080 papi_status_t status;
1081 service_t *svc = handle;
1082 REQUEST *r = NULL;
1083 char *file;
1084 char *dest;
1085
1086 if ((svc == NULL) || (printer == NULL) || (job_id < 0))
1087 return (PAPI_BAD_ARGUMENT);
1088
1089 if ((status = authorized(svc, job_id)) != PAPI_OK)
1090 return (status);
1091
1092 dest = printer_name_from_uri_id(printer, job_id);
1093 status = lpsched_start_change(svc, dest, job_id, &file);
1094 if (status != PAPI_OK)
1095 return (status);
1096
1097 if ((r = getrequest(file)) != NULL) {
1098 r->actions &= ~ACT_RESUME;
1099 switch (flag) {
1100 case 0:
1101 r->actions |= ACT_HOLD;
1102 break;
1103 case 1:
1104 r->actions |= ACT_RESUME;
1105 break;
1106 case 2:
1107 r->actions |= ACT_IMMEDIATE;
1108 break;
1109 }
1110 if (putrequest(file, r) < 0) {
1111 detailed_error(svc,
1112 gettext("failed to write job: %s: %s"),
1113 file, strerror(errno));
1114 freerequest(r);
1115 return (PAPI_DEVICE_ERROR);
1116 }
1117 freerequest(r);
1118 } else {
1119 detailed_error(svc, gettext("failed to read job: %s: %s"),
1120 file, strerror(errno));
1121 return (PAPI_DEVICE_ERROR);
1122 }
1123
1124 status = lpsched_end_change(svc, dest, job_id);
1125
1126 return (status);
1127 }
1128
1129 papi_status_t
papiJobHold(papi_service_t handle,char * printer,int32_t job_id)1130 papiJobHold(papi_service_t handle, char *printer, int32_t job_id)
1131 {
1132 return (hold_release_job(handle, printer, job_id, 0));
1133 }
1134
1135 papi_status_t
papiJobRelease(papi_service_t handle,char * printer,int32_t job_id)1136 papiJobRelease(papi_service_t handle, char *printer, int32_t job_id)
1137 {
1138 return (hold_release_job(handle, printer, job_id, 1));
1139 }
1140
1141 papi_status_t
papiJobPromote(papi_service_t handle,char * printer,int32_t job_id)1142 papiJobPromote(papi_service_t handle, char *printer, int32_t job_id)
1143 {
1144 return (hold_release_job(handle, printer, job_id, 2));
1145 }
1146
1147 papi_status_t
papiJobModify(papi_service_t handle,char * printer,int32_t job_id,papi_attribute_t ** attributes,papi_job_t * job)1148 papiJobModify(papi_service_t handle, char *printer, int32_t job_id,
1149 papi_attribute_t **attributes, papi_job_t *job)
1150 {
1151 papi_status_t status;
1152 job_t *j = NULL;
1153 service_t *svc = handle;
1154 char *file = NULL;
1155 char *dest;
1156 REQUEST *r = NULL;
1157 char lpfile[BUFSIZ];
1158 int32_t job_id_actual;
1159
1160 if ((svc == NULL) || (printer == NULL) || (job_id < 0) ||
1161 (attributes == NULL))
1162 return (PAPI_BAD_ARGUMENT);
1163
1164 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
1165 return (PAPI_TEMPORARY_ERROR);
1166
1167 dest = printer_name_from_uri_id(printer, job_id);
1168
1169 /*
1170 * job-id might be job-id-requested
1171 * If it is job-id-requested then we need to
1172 * look for corresponding job-id
1173 */
1174 job_id_actual = check_job_id(svc, printer, job_id);
1175
1176 if (job_id_actual < 0) {
1177 status = PAPI_NOT_FOUND;
1178 detailed_error(svc,
1179 "failed to initiate change for job (%s-%d): %s",
1180 dest, job_id, "no such resource");
1181 return (status);
1182 }
1183
1184 status = lpsched_start_change(svc, dest, job_id_actual, &file);
1185 if (status != PAPI_OK)
1186 return (status);
1187
1188 if ((r = getrequest(file)) != NULL) {
1189 job_attributes_to_lpsched_request(handle, r,
1190 (papi_attribute_t **)attributes);
1191 #ifdef LP_USE_PAPI_ATTR
1192 /*
1193 * store the job attributes in the PAPI job attribute file
1194 * that was created by the original job request. We need to
1195 * modify the attributes in the file as per the new attributes
1196 */
1197 snprintf(lpfile, sizeof (lpfile), "%s%d-%s",
1198 "/var/spool/lp/temp/", job_id_actual, LP_PAPIATTRNAME);
1199 status = psm_modifyAttrsFile(attributes, lpfile);
1200 if (status != PAPI_OK) {
1201 detailed_error(svc,
1202 "unable to modify the attributes file: %s: %s",
1203 lpfile, strerror(errno));
1204 return (PAPI_DEVICE_ERROR);
1205 }
1206 #endif
1207
1208 if (putrequest(file, r) < 0) {
1209 detailed_error(svc,
1210 gettext("failed to write job: %s: %s"),
1211 file, strerror(errno));
1212 freerequest(r);
1213 return (PAPI_DEVICE_ERROR);
1214 }
1215 } else {
1216 detailed_error(svc, gettext("failed to read job: %s: %s"),
1217 file, strerror(errno));
1218 return (PAPI_DEVICE_ERROR);
1219 }
1220
1221 status = lpsched_end_change(svc, dest, job_id_actual);
1222 lpsched_request_to_job_attributes(r, j);
1223
1224 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
1225 "job-id", job_id_actual);
1226
1227 freerequest(r);
1228
1229 return (status);
1230 }
1231
1232 /*
1233 * Extension to PAPI, a variation of this is slated for post-1.0
1234 */
1235 #define DUMMY_FILE "/var/spool/lp/fifos/FIFO"
1236
1237 papi_status_t
papiJobCreate(papi_service_t handle,char * printer,papi_attribute_t ** job_attributes,papi_job_ticket_t * job_ticket,papi_job_t * job)1238 papiJobCreate(papi_service_t handle, char *printer,
1239 papi_attribute_t **job_attributes,
1240 papi_job_ticket_t *job_ticket, papi_job_t *job)
1241 {
1242 papi_status_t status;
1243 service_t *svc = handle;
1244 job_t *j = NULL;
1245 REQUEST *request;
1246 char *request_id = NULL;
1247 char *c;
1248 char *tmp = NULL;
1249 char metadata_file[MAXPATHLEN];
1250
1251 if ((svc == NULL) || (printer == NULL) || (job == NULL))
1252 return (PAPI_BAD_ARGUMENT);
1253
1254 if (job_ticket != NULL)
1255 return (PAPI_JOB_TICKET_NOT_SUPPORTED);
1256
1257 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
1258 return (PAPI_TEMPORARY_ERROR);
1259
1260 /* 1 for the control file (-0) */
1261 status = lpsched_alloc_files(svc, 1, &request_id);
1262 if (status != PAPI_OK)
1263 return (status);
1264
1265 /* convert the attributes to an lpsched REQUEST structure */
1266 request = create_request(svc, (char *)printer,
1267 (papi_attribute_t **)job_attributes);
1268 if (request == NULL)
1269 return (PAPI_TEMPORARY_ERROR);
1270 addlist(&request->file_list, DUMMY_FILE); /* add a dummy file */
1271 request->actions |= ACT_HOLD; /* hold the job */
1272
1273 #ifdef LP_USE_PAPI_ATTR
1274 /*
1275 * store the job attributes in the PAPI job attribute file that was
1276 * created by lpsched_alloc_files(), the attributes will then pass
1277 * through lpsched and be given to the slow-filters and the printer's
1278 * interface script to process them
1279 */
1280 snprintf(metadata_file, sizeof (metadata_file), "%s%s-%s",
1281 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
1282 status = psm_copy_attrsToFile(job_attributes, metadata_file);
1283 if (status != PAPI_OK) {
1284 detailed_error(svc, "unable to copy attributes to file: %s: %s",
1285 metadata_file, strerror(errno));
1286 free(request_id);
1287 return (PAPI_DEVICE_ERROR);
1288 }
1289 #endif
1290
1291 /* store the REQUEST on disk */
1292 snprintf(metadata_file, sizeof (metadata_file), "%s-0", request_id);
1293 free(request_id);
1294 if (putrequest(metadata_file, request) < 0) {
1295 detailed_error(svc, gettext("unable to save request: %s: %s"),
1296 metadata_file, strerror(errno));
1297 return (PAPI_DEVICE_ERROR);
1298 }
1299
1300 status = lpsched_commit_job(svc, metadata_file, &tmp);
1301 if (status != PAPI_OK) {
1302 unlink(metadata_file);
1303 return (status);
1304 }
1305
1306 lpsched_request_to_job_attributes(request, j);
1307
1308 if ((c = strrchr(tmp, '-')) != NULL)
1309 c++;
1310 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
1311 "job-id", atoi(c));
1312 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
1313 "job-uri", tmp);
1314
1315 return (PAPI_OK);
1316 }
1317
1318 papi_status_t
papiJobCommit(papi_service_t handle,char * printer,int32_t id)1319 papiJobCommit(papi_service_t handle, char *printer, int32_t id)
1320 {
1321 papi_status_t status = PAPI_OK;
1322 service_t *svc = handle;
1323 REQUEST *r = NULL;
1324 char *metadata_file;
1325 char *dest;
1326
1327 if ((svc == NULL) || (printer == NULL))
1328 return (PAPI_BAD_ARGUMENT);
1329
1330 dest = printer_name_from_uri_id(printer, id);
1331 /* tell the scheduler that we want to change the job */
1332 status = lpsched_start_change(svc, dest, id, &metadata_file);
1333 if (status != PAPI_OK)
1334 return (status);
1335
1336 if ((r = getrequest(metadata_file)) != NULL) {
1337 r->actions &= ~ACT_RESUME;
1338 r->actions |= ACT_RESUME;
1339 dellist(&r->file_list, DUMMY_FILE);
1340
1341 if (putrequest(metadata_file, r) < 0) {
1342 detailed_error(svc,
1343 gettext("failed to write job: %s: %s"),
1344 metadata_file, strerror(errno));
1345 freerequest(r);
1346 return (PAPI_DEVICE_ERROR);
1347 }
1348 } else {
1349 detailed_error(svc, gettext("failed to read job: %s: %s"),
1350 metadata_file, strerror(errno));
1351 return (PAPI_DEVICE_ERROR);
1352 }
1353
1354 status = lpsched_end_change(svc, dest, id);
1355 freerequest(r);
1356
1357 return (status);
1358 }
1359
1360 papi_status_t
papiJobStreamAdd(papi_service_t handle,char * printer,int32_t id,papi_stream_t * stream)1361 papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id,
1362 papi_stream_t *stream)
1363 {
1364 papi_status_t status;
1365 service_t *svc = handle;
1366 job_stream_t *s = NULL;
1367 char *metadata_file = NULL;
1368 char *dest;
1369 char path[MAXPATHLEN];
1370
1371 /* allocate space for the stream */
1372 if ((*stream = s = calloc(1, sizeof (*s))) == NULL)
1373 return (PAPI_TEMPORARY_ERROR);
1374
1375 dest = printer_name_from_uri_id(printer, id);
1376 /* create/open data file (only root or lp can really do this */
1377 snprintf(path, sizeof (path), "/var/spool/lp/temp/%d-XXXXXX", id);
1378 if ((s->fd = mkstemp(path)) < 0) {
1379 detailed_error(svc, gettext("unable to create sink (%s): %s"),
1380 path, strerror(errno));
1381 free(s);
1382 return (PAPI_NOT_AUTHORIZED);
1383 }
1384
1385 /* add data file to job */
1386 status = lpsched_start_change(svc, dest, id, &metadata_file);
1387 if (status != PAPI_OK) {
1388 close(s->fd);
1389 free(s);
1390 unlink(path);
1391 return (status);
1392 }
1393
1394 if ((s->request = getrequest(metadata_file)) == NULL) {
1395 detailed_error(svc, gettext("unable to load request: %s: %s"),
1396 metadata_file, strerror(errno));
1397 close(s->fd);
1398 free(s);
1399 unlink(path);
1400 return (PAPI_NOT_POSSIBLE);
1401 }
1402
1403 addlist(&(s->request->file_list), path);
1404
1405 if (putrequest(metadata_file, s->request) < 0) {
1406 detailed_error(svc, gettext("unable to save request: %s: %s"),
1407 metadata_file, strerror(errno));
1408 close(s->fd);
1409 free(s);
1410 unlink(path);
1411 return (PAPI_NOT_POSSIBLE);
1412 }
1413
1414 status = lpsched_end_change(svc, dest, id);
1415
1416 if (status != PAPI_OK)
1417 return (status);
1418
1419 return (PAPI_OK);
1420 }
1421