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