1*2264Sjacobs /*
2*2264Sjacobs  * CDDL HEADER START
3*2264Sjacobs  *
4*2264Sjacobs  * The contents of this file are subject to the terms of the
5*2264Sjacobs  * Common Development and Distribution License (the "License").
6*2264Sjacobs  * You may not use this file except in compliance with the License.
7*2264Sjacobs  *
8*2264Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*2264Sjacobs  * or http://www.opensolaris.org/os/licensing.
10*2264Sjacobs  * See the License for the specific language governing permissions
11*2264Sjacobs  * and limitations under the License.
12*2264Sjacobs  *
13*2264Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
14*2264Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*2264Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
16*2264Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
17*2264Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
18*2264Sjacobs  *
19*2264Sjacobs  * CDDL HEADER END
20*2264Sjacobs  */
21*2264Sjacobs 
22*2264Sjacobs /*
23*2264Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*2264Sjacobs  * Use is subject to license terms.
25*2264Sjacobs  *
26*2264Sjacobs  */
27*2264Sjacobs 
28*2264Sjacobs /* $Id: lpd-query.c 155 2006-04-26 02:34:54Z ktou $ */
29*2264Sjacobs 
30*2264Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*2264Sjacobs 
32*2264Sjacobs #define	__EXTENSIONS__	/* for strtok_r() */
33*2264Sjacobs #include <stdio.h>
34*2264Sjacobs #include <stdlib.h>
35*2264Sjacobs #include <unistd.h>
36*2264Sjacobs #include <sys/types.h>
37*2264Sjacobs #include <sys/stat.h>
38*2264Sjacobs #include <sys/fcntl.h>
39*2264Sjacobs #include <time.h>
40*2264Sjacobs #include <ctype.h>
41*2264Sjacobs #include <string.h>
42*2264Sjacobs #include <stdarg.h>
43*2264Sjacobs 
44*2264Sjacobs #include <papi_impl.h>
45*2264Sjacobs 
46*2264Sjacobs static void
47*2264Sjacobs parse_lpd_job_entry(service_t *svc, int fd, job_t **job)
48*2264Sjacobs {
49*2264Sjacobs 	char *iter = NULL;
50*2264Sjacobs 	char line[128];
51*2264Sjacobs 	papi_attribute_t **attributes = NULL;
52*2264Sjacobs 	char *p;
53*2264Sjacobs 	int octets = 0;
54*2264Sjacobs 
55*2264Sjacobs 	*job = NULL;
56*2264Sjacobs 
57*2264Sjacobs 	if (fdgets(line, sizeof (line), fd) == NULL)
58*2264Sjacobs 		return;
59*2264Sjacobs 	/*
60*2264Sjacobs 	 * 1st line...
61*2264Sjacobs 	 *	 user: rank			[job (ID)(host)]\n
62*2264Sjacobs 	 */
63*2264Sjacobs 	if ((p = strtok_r(line, ": ", &iter)) == NULL)	 /* user: ... */
64*2264Sjacobs 		return; /* invalid format */
65*2264Sjacobs 	papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE,
66*2264Sjacobs 				"job-originating-user-name", p);
67*2264Sjacobs 
68*2264Sjacobs 	p = strtok_r(NULL, "\t ", &iter);	/* ...rank... */
69*2264Sjacobs 	papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE,
70*2264Sjacobs 				"number-of-intervening-jobs", atoi(p) - 1);
71*2264Sjacobs 	p = strtok_r(NULL, " ", &iter);		/* ...[job ... */
72*2264Sjacobs 	if ((p = strtok_r(NULL, "]\n", &iter)) == NULL)	/* ...(id)(hostname)] */
73*2264Sjacobs 		return;
74*2264Sjacobs 	while (isspace(*p)) p++;
75*2264Sjacobs 	papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE,
76*2264Sjacobs 				"job-id", atoi(p));
77*2264Sjacobs 	while (isdigit(*(++p)));
78*2264Sjacobs 	while (isspace(*p)) p++;
79*2264Sjacobs 	papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE,
80*2264Sjacobs 				"job-originating-host-name", p);
81*2264Sjacobs 
82*2264Sjacobs 	/*
83*2264Sjacobs 	 * rest-o-lines
84*2264Sjacobs 	 *	[(num) copies of ]file			size bytes\n
85*2264Sjacobs 	 */
86*2264Sjacobs 	while ((fdgets(line, sizeof (line), fd) != NULL) && (line[0] != '\n')) {
87*2264Sjacobs 		int copies, size;
88*2264Sjacobs 		char *q;
89*2264Sjacobs 
90*2264Sjacobs 		/* find the number of copies */
91*2264Sjacobs 		if ((p = strstr(line, "copies of")) != NULL) {
92*2264Sjacobs 			copies = atoi(line);
93*2264Sjacobs 			p += 9;
94*2264Sjacobs 		} else {
95*2264Sjacobs 			copies = 1;
96*2264Sjacobs 			p = line;
97*2264Sjacobs 		}
98*2264Sjacobs 		papiAttributeListAddInteger(&attributes, PAPI_ATTR_EXCL,
99*2264Sjacobs 				"copies", copies);
100*2264Sjacobs 
101*2264Sjacobs 		/* eat the leading whitespace */
102*2264Sjacobs 		while (isspace(*p) != 0)
103*2264Sjacobs 			p++;
104*2264Sjacobs 		if ((q = strstr(p, " bytes\n")) != NULL) {
105*2264Sjacobs 			/* back up to the beginning of the size */
106*2264Sjacobs 			do { q--; } while (isdigit(*q) != 0);
107*2264Sjacobs 
108*2264Sjacobs 			/* seperate the name and size */
109*2264Sjacobs 			*q = '\0';
110*2264Sjacobs 			q++;
111*2264Sjacobs 
112*2264Sjacobs 			size = atoi(q);
113*2264Sjacobs 
114*2264Sjacobs 			papiAttributeListAddString(&attributes,
115*2264Sjacobs 				PAPI_ATTR_APPEND, "job-name", p);
116*2264Sjacobs 			papiAttributeListAddString(&attributes,
117*2264Sjacobs 				PAPI_ATTR_APPEND, "job-file-names", p);
118*2264Sjacobs 			papiAttributeListAddInteger(&attributes,
119*2264Sjacobs 				PAPI_ATTR_APPEND, "job-file-sizes", size);
120*2264Sjacobs 
121*2264Sjacobs 			octets += (size * copies);
122*2264Sjacobs 		}
123*2264Sjacobs 	}
124*2264Sjacobs 
125*2264Sjacobs 	papiAttributeListAddInteger(&attributes, PAPI_ATTR_APPEND,
126*2264Sjacobs 			"job-k-octets", octets/1024);
127*2264Sjacobs 	papiAttributeListAddInteger(&attributes, PAPI_ATTR_APPEND,
128*2264Sjacobs 			"job-octets", octets);
129*2264Sjacobs 	papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND,
130*2264Sjacobs 			"printer-name", queue_name_from_uri(svc->uri));
131*2264Sjacobs 
132*2264Sjacobs 	if ((*job = (job_t *)calloc(1, sizeof (**job))) != NULL)
133*2264Sjacobs 		(*job)->attributes = attributes;
134*2264Sjacobs }
135*2264Sjacobs 
136*2264Sjacobs static void
137*2264Sjacobs parse_lpd_job_entries(service_t *svc, int fd)
138*2264Sjacobs {
139*2264Sjacobs 	job_t *job = NULL;
140*2264Sjacobs 
141*2264Sjacobs 	do {
142*2264Sjacobs 		parse_lpd_job_entry(svc, fd, &job);
143*2264Sjacobs 		list_append(&svc->cache->jobs, job);
144*2264Sjacobs 	} while (job != NULL);
145*2264Sjacobs 
146*2264Sjacobs }
147*2264Sjacobs 
148*2264Sjacobs 
149*2264Sjacobs void
150*2264Sjacobs parse_lpd_query(service_t *svc, int fd)
151*2264Sjacobs {
152*2264Sjacobs 	papi_attribute_t **attributes = NULL;
153*2264Sjacobs 	cache_t *cache = NULL;
154*2264Sjacobs 	int state = 0x03; /* idle */
155*2264Sjacobs 	char line[128];
156*2264Sjacobs 	char buf[1024];
157*2264Sjacobs 
158*2264Sjacobs 	/* get the status line */
159*2264Sjacobs 	if (fdgets(line, sizeof (line), fd) == NULL)
160*2264Sjacobs 		return;	/* this should not happen. */
161*2264Sjacobs 
162*2264Sjacobs 	papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND,
163*2264Sjacobs 			"printer-name", queue_name_from_uri(svc->uri));
164*2264Sjacobs 
165*2264Sjacobs 	if (uri_to_string(svc->uri, buf, sizeof (buf)) == 0)
166*2264Sjacobs 		papiAttributeListAddString(&attributes, PAPI_ATTR_APPEND,
167*2264Sjacobs 				"printer-uri-supported", buf);
168*2264Sjacobs 
169*2264Sjacobs 	papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE,
170*2264Sjacobs 			"printer-state-reasons", line);
171*2264Sjacobs 
172*2264Sjacobs 	if (strstr(line, "ready and printing") != NULL)
173*2264Sjacobs 		state = 0x04; /* processing */
174*2264Sjacobs 	else if ((strstr(line, "no entries") != NULL) ||
175*2264Sjacobs 		 (strstr(line, "is ready") != NULL))
176*2264Sjacobs 		state = 0x03; /* idle */
177*2264Sjacobs 	else
178*2264Sjacobs 		state = 0x05; /* stopped */
179*2264Sjacobs 
180*2264Sjacobs 	papiAttributeListAddInteger(&attributes, PAPI_ATTR_REPLACE,
181*2264Sjacobs 			"printer-state", state);
182*2264Sjacobs 
183*2264Sjacobs 	if ((cache = (cache_t *)calloc(1, sizeof (*cache))) == NULL)
184*2264Sjacobs 		return;
185*2264Sjacobs 
186*2264Sjacobs 	if ((cache->printer = (printer_t *)calloc(1, sizeof (*cache->printer)))
187*2264Sjacobs 				== NULL)
188*2264Sjacobs 		return;
189*2264Sjacobs 
190*2264Sjacobs 	cache->printer->attributes = attributes;
191*2264Sjacobs 	svc->cache = cache;
192*2264Sjacobs 
193*2264Sjacobs 	if (fdgets(line, sizeof (line), fd) != NULL) {
194*2264Sjacobs 		/* get the jobs */
195*2264Sjacobs 		parse_lpd_job_entries(svc, fd);
196*2264Sjacobs 	}
197*2264Sjacobs 
198*2264Sjacobs 	time(&cache->timestamp);
199*2264Sjacobs }
200*2264Sjacobs 
201*2264Sjacobs void
202*2264Sjacobs cache_update(service_t *svc)
203*2264Sjacobs {
204*2264Sjacobs 	int fd;
205*2264Sjacobs 
206*2264Sjacobs 	if (svc->cache != NULL)	/* this should be time based */
207*2264Sjacobs 		return;
208*2264Sjacobs 
209*2264Sjacobs 	if (svc == NULL)
210*2264Sjacobs 		return;
211*2264Sjacobs 
212*2264Sjacobs 	if ((fd = lpd_open(svc, 'q', NULL, 3)) < 0)
213*2264Sjacobs 		return;
214*2264Sjacobs 
215*2264Sjacobs 	parse_lpd_query(svc, fd);
216*2264Sjacobs 
217*2264Sjacobs 	close(fd);
218*2264Sjacobs }
219*2264Sjacobs 
220*2264Sjacobs papi_status_t
221*2264Sjacobs lpd_find_printer_info(service_t *svc, printer_t **printer)
222*2264Sjacobs {
223*2264Sjacobs 	papi_status_t result = PAPI_BAD_ARGUMENT;
224*2264Sjacobs 
225*2264Sjacobs 	if ((svc == NULL) || (printer == NULL))
226*2264Sjacobs 		return (PAPI_BAD_ARGUMENT);
227*2264Sjacobs 
228*2264Sjacobs 	cache_update(svc);
229*2264Sjacobs 
230*2264Sjacobs 	if (svc->cache != NULL) {
231*2264Sjacobs 		*printer = svc->cache->printer;
232*2264Sjacobs 		result = PAPI_OK;
233*2264Sjacobs 	} else
234*2264Sjacobs 		result = PAPI_NOT_FOUND;
235*2264Sjacobs 
236*2264Sjacobs 	return (result);
237*2264Sjacobs }
238*2264Sjacobs 
239*2264Sjacobs papi_status_t
240*2264Sjacobs lpd_find_jobs_info(service_t *svc, job_t ***jobs)
241*2264Sjacobs {
242*2264Sjacobs 	papi_status_t result = PAPI_BAD_ARGUMENT;
243*2264Sjacobs 
244*2264Sjacobs 	if (svc != NULL) {
245*2264Sjacobs 		cache_update(svc);
246*2264Sjacobs 
247*2264Sjacobs 		if (svc->cache != NULL) {
248*2264Sjacobs 			*jobs = svc->cache->jobs;
249*2264Sjacobs 			result = PAPI_OK;
250*2264Sjacobs 		}
251*2264Sjacobs 	}
252*2264Sjacobs 
253*2264Sjacobs 	return (result);
254*2264Sjacobs }
255*2264Sjacobs 
256*2264Sjacobs papi_status_t
257*2264Sjacobs lpd_find_job_info(service_t *svc, int job_id, job_t **job)
258*2264Sjacobs {
259*2264Sjacobs 	papi_status_t result = PAPI_BAD_ARGUMENT;
260*2264Sjacobs 	job_t **jobs;
261*2264Sjacobs 
262*2264Sjacobs 	if (lpd_find_jobs_info(svc, &jobs) != PAPI_OK) {
263*2264Sjacobs 		int i;
264*2264Sjacobs 
265*2264Sjacobs 		*job = NULL;
266*2264Sjacobs 		for (i = 0; ((*job == NULL) && (jobs[i] != NULL)); i++) {
267*2264Sjacobs 			int id = -1;
268*2264Sjacobs 
269*2264Sjacobs 			papiAttributeListGetInteger(jobs[i]->attributes, NULL,
270*2264Sjacobs 					"job-id", &id);
271*2264Sjacobs 			if (id == job_id)
272*2264Sjacobs 				*job = jobs[i];
273*2264Sjacobs 		}
274*2264Sjacobs 
275*2264Sjacobs 		if (*job != NULL)
276*2264Sjacobs 			result = PAPI_OK;
277*2264Sjacobs 	}
278*2264Sjacobs 
279*2264Sjacobs 	return (result);
280*2264Sjacobs }
281*2264Sjacobs 
282*2264Sjacobs void
283*2264Sjacobs cache_free(cache_t *item)
284*2264Sjacobs {
285*2264Sjacobs 	if (item != NULL) {
286*2264Sjacobs 		if (item->printer != NULL)
287*2264Sjacobs 			papiPrinterFree((papi_printer_t *)item->printer);
288*2264Sjacobs 		if (item->jobs != NULL)
289*2264Sjacobs 			papiJobListFree((papi_job_t *)item->jobs);
290*2264Sjacobs 		free(item);
291*2264Sjacobs 	}
292*2264Sjacobs }
293