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 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  */
27 
28 /* $Id: job.c 179 2006-07-17 18:24:07Z njacobs $ */
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <errno.h>
36 #include <unistd.h>
37 #include <limits.h>
38 #include <libintl.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <papi_impl.h>
43 #include <uri.h>
44 
45 /*
46  * must copy files before leaving routine
47  */
48 papi_status_t
49 papiJobSubmit(papi_service_t handle, char *name, papi_attribute_t **attributes,
50 		papi_job_ticket_t *job_ticket, char **files, papi_job_t *job)
51 {
52 	papi_status_t status = PAPI_OK;
53 	service_t *svc = handle;
54 	job_t *j = NULL;
55 	char *metadata = NULL;
56 
57 	if ((svc == NULL) || (name == NULL) || (files == NULL) ||
58 	    (job == NULL))
59 		return (PAPI_BAD_ARGUMENT);
60 
61 	if (job_ticket != NULL) {
62 		detailed_error(svc,
63 			gettext("papiJobSubmit: job ticket not supported"));
64 		return (PAPI_OPERATION_NOT_SUPPORTED);
65 	}
66 
67 	if ((status = service_fill_in(svc, name)) != PAPI_OK)
68 		return (status);
69 
70 	if ((*job = j = (job_t *)calloc(1, sizeof (*j))) == NULL) {
71 		detailed_error(svc,
72 			gettext("calloc() failed"));
73 		return (PAPI_TEMPORARY_ERROR);
74 	}
75 
76 	/* create a control file */
77 	status = lpd_job_add_attributes(svc, attributes, &metadata,
78 				&j->attributes);
79 	status = lpd_job_add_files(svc, attributes, files, &metadata,
80 				&j->attributes);
81 
82 	/* send the job to the server */
83 	status = lpd_submit_job(svc, metadata, &j->attributes, NULL);
84 	free(metadata);
85 
86 	return (status);
87 
88 }
89 
90 
91 papi_status_t
92 papiJobSubmitByReference(papi_service_t handle, char *name,
93 		papi_attribute_t **job_attributes,
94 		papi_job_ticket_t *job_ticket, char **files, papi_job_t *job)
95 {
96 	return (papiJobSubmit(handle, name, job_attributes,
97 		job_ticket, files, job));
98 }
99 
100 papi_status_t
101 papiJobStreamOpen(papi_service_t handle, char *name,
102 		papi_attribute_t **attributes,
103 		papi_job_ticket_t *job_ticket, papi_stream_t *stream)
104 {
105 	papi_status_t status = PAPI_OK;
106 	service_t *svc = handle;
107 	char *metadata = NULL;
108 	stream_t *s = NULL;
109 
110 	if ((svc == NULL) || (name == NULL) || (stream == NULL))
111 		return (PAPI_BAD_ARGUMENT);
112 
113 	if (job_ticket != NULL)
114 		return (PAPI_OPERATION_NOT_SUPPORTED);
115 
116 	if ((status = service_fill_in(svc, name)) != PAPI_OK)
117 		return (status);
118 
119 	/* create the stream container */
120 	if ((*stream = s = calloc(1, sizeof (*s))) == NULL)
121 		return (PAPI_TEMPORARY_ERROR);
122 
123 	/* create the job */
124 	if ((s->job = calloc(1, sizeof (*(s->job)))) == NULL)
125 		return (PAPI_TEMPORARY_ERROR);
126 
127 	/* process the attribute list */
128 	lpd_job_add_attributes(svc, attributes, &metadata, &s->job->attributes);
129 
130 	/* if we can stream, do it */
131 	if ((svc->uri->fragment != NULL) &&
132 	    (strcasecmp(svc->uri->fragment, "streaming") == 0)) {
133 		char *files[] = { "standard input", NULL };
134 
135 		lpd_job_add_files(svc, attributes, files, &metadata,
136 				&(s->job->attributes));
137 		status = lpd_submit_job(svc, metadata, &(s->job->attributes),
138 				&s->fd);
139 	} else {
140 		char dfname[18];
141 
142 		strcpy(dfname, "/tmp/stdin-XXXXX");
143 
144 		if ((s->fd = mkstemp(dfname)) >= 0)
145 			s->dfname = strdup(dfname);
146 	}
147 	s->metadata = metadata;
148 
149 	return (status);
150 }
151 
152 
153 papi_status_t
154 papiJobStreamWrite(papi_service_t handle, papi_stream_t stream,
155 		void *buffer, size_t buflen)
156 {
157 	service_t *svc = handle;
158 	stream_t *s = stream;
159 
160 	if ((svc == NULL) || (stream == NULL) || (buffer == NULL) ||
161 	    (buflen == 0))
162 		return (PAPI_BAD_ARGUMENT);
163 
164 	if (write(s->fd, buffer, buflen) != buflen)
165 		return (PAPI_DEVICE_ERROR);
166 
167 	return (PAPI_OK);
168 }
169 
170 papi_status_t
171 papiJobStreamClose(papi_service_t handle, papi_stream_t stream, papi_job_t *job)
172 {
173 	papi_status_t status = PAPI_INTERNAL_ERROR;
174 	service_t *svc = handle;
175 	job_t *j = NULL;
176 	stream_t *s = stream;
177 	int ret;
178 
179 	if ((svc == NULL) || (stream == NULL) || (job == NULL))
180 		return (PAPI_BAD_ARGUMENT);
181 
182 	close(s->fd);	/* close the stream */
183 
184 	if (s->dfname != NULL) {	/* if it is a tmpfile, print it */
185 		char *files[2];
186 
187 		files[0] = s->dfname;
188 		files[1] = NULL;
189 
190 		lpd_job_add_files(svc, s->job->attributes, files, &s->metadata,
191 				&(s->job->attributes));
192 		status = lpd_submit_job(svc, s->metadata,
193 					&(s->job->attributes), NULL);
194 		unlink(s->dfname);
195 		free(s->dfname);
196 	} else
197 		status = PAPI_OK;
198 
199 	if (s->metadata != NULL)
200 		free(s->metadata);
201 
202 	*job = s->job;
203 
204 	return (status);
205 }
206 
207 papi_status_t
208 papiJobQuery(papi_service_t handle, char *name, int32_t job_id,
209 		char **job_attributes, papi_job_t *job)
210 {
211 	papi_status_t status = PAPI_OK;
212 	service_t *svc = handle;
213 
214 	if ((svc == NULL) || (name == NULL) || job_id < 0)
215 		return (PAPI_BAD_ARGUMENT);
216 
217 	if ((status = service_fill_in(svc, name)) == PAPI_OK)
218 		status = lpd_find_job_info(svc, job_id, (job_t **)job);
219 
220 	return (status);
221 }
222 
223 papi_status_t
224 papiJobCancel(papi_service_t handle, char *name, int32_t job_id)
225 {
226 	papi_status_t status;
227 	service_t *svc = handle;
228 
229 	if ((svc == NULL) || (name == NULL) || (job_id < 0))
230 		return (PAPI_BAD_ARGUMENT);
231 
232 	if ((status = service_fill_in(svc, name)) == PAPI_OK)
233 		status = lpd_cancel_job(svc, job_id);
234 
235 	return (status);
236 }
237 
238 papi_attribute_t **
239 papiJobGetAttributeList(papi_job_t job)
240 {
241 	job_t *j = (job_t *)job;
242 
243 	if (j != NULL)
244 		return ((papi_attribute_t **)j->attributes);
245 
246 	return (NULL);
247 }
248 
249 char *
250 papiJobGetPrinterName(papi_job_t job)
251 {
252 	char *result = NULL;
253 	job_t *j = (job_t *)job;
254 
255 	if (j != NULL)
256 		papiAttributeListGetString(j->attributes, NULL,
257 					"printer-name", &result);
258 
259 	return (result);
260 }
261 
262 int
263 papiJobGetId(papi_job_t job)
264 {
265 	int result = -1;
266 	job_t *j = (job_t *)job;
267 
268 	if (j != NULL)
269 		papiAttributeListGetInteger(j->attributes, NULL,
270 					"job-id", &result);
271 
272 	return (result);
273 }
274 
275 void
276 papiJobFree(papi_job_t job)
277 {
278 	job_t *j = (job_t *)job;
279 
280 
281 	if (j != NULL) {
282 		papiAttributeListFree(j->attributes);
283 		free(j);
284 	}
285 }
286 
287 void
288 papiJobListFree(papi_job_t *jobs)
289 {
290 	if (jobs != NULL) {
291 		int i;
292 
293 		for (i = 0; jobs[i] != NULL; i++)
294 			papiJobFree(jobs[i]);
295 		free(jobs);
296 	}
297 }
298