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