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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 */ 27 28 /* $Id: common.c 162 2006-05-08 14:17:44Z njacobs $ */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <fcntl.h> 38 #include <alloca.h> 39 #include <string.h> 40 #include <libintl.h> 41 #include <ctype.h> 42 #include <pwd.h> 43 #include <papi.h> 44 #include "common.h" 45 46 #ifndef HAVE_GETPASSPHRASE /* some systems don't have getpassphrase() */ 47 #define getpassphrase getpass 48 #endif 49 50 /* give the most verbose error message to the caller */ 51 char * 52 verbose_papi_message(papi_service_t svc, papi_status_t status) 53 { 54 char *mesg; 55 56 mesg = papiServiceGetStatusMessage(svc); 57 58 if (mesg == NULL) 59 mesg = papiStatusString(status); 60 61 return (mesg); 62 } 63 64 static int 65 match_job(int id, char *user, int ac, char *av[]) 66 { 67 int i; 68 69 for (i = 0; i < ac; i++) 70 if (strcmp("-", av[i]) == 0) 71 return (0); /* "current" user match */ 72 else if ((isdigit(av[i][0]) != 0) && (id == atoi(av[i]))) 73 return (0); /* job-id match */ 74 else if (strcmp(user, av[i]) == 0) 75 return (0); /* user match */ 76 77 return (-1); 78 } 79 80 static struct { 81 char *mime_type; 82 char *lp_type; 83 } type_map[] = { 84 { "text/plain", "simple" }, 85 { "application/octet-stream", "raw" }, 86 { "application/octet-stream", "any" }, 87 { "application/postscript", "postscript" }, 88 { "application/postscript", "ps" }, 89 { "application/x-cif", "cif" }, 90 { "application/x-dvi", "dvi" }, 91 { "application/x-plot", "plot" }, 92 { "application/x-ditroff", "troff" }, 93 { "application/x-troff", "otroff" }, 94 { "application/x-pr", "pr" }, 95 { "application/x-fortran", "fortran" }, 96 { "application/x-raster", "raster" }, 97 { NULL, NULL} 98 }; 99 100 char * 101 lp_type_to_mime_type(char *lp_type) 102 { 103 int i; 104 105 if (lp_type == NULL) 106 return ("application/octet-stream"); 107 108 for (i = 0; type_map[i].lp_type != NULL; i++) 109 if (strcasecmp(type_map[i].lp_type, lp_type) == 0) 110 return (type_map[i].mime_type); 111 112 return (lp_type); 113 } 114 115 /* 116 * to support job/printer status 117 */ 118 static char * 119 state_string(int state) 120 { 121 switch (state) { 122 case 3: 123 return (gettext("idle")); 124 case 4: 125 return (gettext("processing")); 126 case 5: 127 return (gettext("stopped")); 128 default: 129 return (gettext("unknown")); 130 } 131 } 132 133 static char *_rank_suffixes[] = { 134 "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" 135 }; 136 137 static char * 138 rank_string(const int rank) 139 { 140 static char buf[12]; 141 142 if (rank < 0) 143 snprintf(buf, sizeof (buf), gettext("invalid")); 144 else if (rank == 0) 145 snprintf(buf, sizeof (buf), gettext("active")); 146 else if ((rank > 10) && (rank < 14)) 147 sprintf(buf, "%dth", rank); 148 else 149 sprintf(buf, "%d%s", rank, _rank_suffixes[rank % 10]); 150 151 return (buf); 152 } 153 154 static void 155 printer_state_line(FILE *fp, papi_printer_t p, int num_jobs, char *name) 156 { 157 papi_attribute_t **list = papiPrinterGetAttributeList(p); 158 int state = 0; 159 char *reason = ""; 160 161 (void) papiAttributeListGetInteger(list, NULL, 162 "printer-state", &state); 163 (void) papiAttributeListGetString(list, NULL, 164 "printer-state-reasons", &reason); 165 (void) papiAttributeListGetString(list, NULL, 166 "printer-name", &name); 167 168 if ((state != 0x03) || (num_jobs != 0)) { 169 fprintf(fp, "%s: %s", name, state_string(state)); 170 if (state == 0x05) /* stopped */ 171 fprintf(fp, ": %s\n", reason); 172 else 173 fprintf(fp, "\n"); 174 } else 175 fprintf(fp, "no entries\n"); 176 } 177 178 static void 179 print_header(FILE *fp) 180 { 181 fprintf(fp, gettext("Rank\tOwner\t Job\tFile(s)\t\t\t\tTotal Size\n")); 182 } 183 184 static void 185 print_job_line(FILE *fp, int count, papi_job_t job, int fmt, int ac, char *av[]) 186 { 187 papi_attribute_t **list = papiJobGetAttributeList(job); 188 int copies = 1, id = 0, rank = count, size = 0; 189 char *name = "print job"; 190 char *user = "nobody"; 191 char *host = "localhost"; 192 char *suffix = "k"; 193 194 (void) papiAttributeListGetInteger(list, NULL, 195 "job-id", &id); 196 (void) papiAttributeListGetInteger(list, NULL, 197 "job-id-requested", &id); 198 (void) papiAttributeListGetString(list, NULL, 199 "job-originating-user-name", &user); 200 (void) papiAttributeListGetString(list, NULL, 201 "job-originating-host-name", &host); 202 203 /* if we are looking and it doesn't match, return early */ 204 if ((ac > 0) && (match_job(id, user, ac, av) < 0)) 205 return; 206 207 (void) papiAttributeListGetInteger(list, NULL, 208 "copies", &copies); 209 (void) papiAttributeListGetInteger(list, NULL, 210 "number-of-intervening-jobs", &rank); 211 212 if (papiAttributeListGetInteger(list, NULL, "job-octets", &size) 213 == PAPI_OK) 214 suffix = "bytes"; 215 else 216 (void) papiAttributeListGetInteger(list, NULL, 217 "job-k-octets", &size); 218 (void) papiAttributeListGetString(list, NULL, 219 "job-name", &name); 220 221 size *= copies; 222 223 if (fmt == 3) { 224 fprintf(fp, gettext("%s\t%-8.8s %d\t%-32.32s%d %s\n"), 225 rank_string(++rank), user, id, name, size, suffix); 226 } else 227 fprintf(fp, gettext( 228 "\n%s: %s\t\t\t\t[job %d %s]\n\t%-32.32s\t%d %s\n"), 229 user, rank_string(++rank), id, host, name, size, 230 suffix); 231 } 232 233 /* 234 * to support job cancelation 235 */ 236 static void 237 cancel_job(papi_service_t svc, FILE *fp, char *printer, papi_job_t job, 238 int ac, char *av[]) 239 { 240 papi_status_t status; 241 papi_attribute_t **list = papiJobGetAttributeList(job); 242 int id = 0; 243 int rid = 0; 244 char *user = ""; 245 char *mesg = gettext("cancelled"); 246 247 papiAttributeListGetInteger(list, NULL, 248 "job-id", &id); 249 papiAttributeListGetInteger(list, NULL, 250 "job-id-requested", &rid); 251 papiAttributeListGetString(list, NULL, 252 "job-originating-user-name", &user); 253 254 /* if we are looking and it doesn't match, return early */ 255 if ((ac > 0) && (match_job(id, user, ac, av) < 0) && 256 (match_job(rid, user, ac, av) < 0)) 257 return; 258 259 status = papiJobCancel(svc, printer, id); 260 if (status != PAPI_OK) 261 mesg = papiStatusString(status); 262 263 fprintf(fp, "%s-%d: %s\n", printer, id, mesg); 264 } 265 266 int 267 berkeley_queue_report(papi_service_t svc, FILE *fp, char *dest, int fmt, 268 int ac, char *av[]) 269 { 270 papi_status_t status; 271 papi_printer_t p = NULL; 272 papi_job_t *jobs = NULL; 273 char *pattrs[] = { "printer-name", "printer-state", 274 "printer-state-reasons", NULL }; 275 char *jattrs[] = { "job-name", "job-octets", "job-k-octets", "job-id", 276 "job-originating-user-name", "job-id-requested", 277 "job-originating-host-name", 278 "number-of-intervening-jobs", NULL }; 279 int num_jobs = 0; 280 281 status = papiPrinterQuery(svc, dest, pattrs, NULL, &p); 282 if (status != PAPI_OK) { 283 fprintf(fp, gettext( 284 "Failed to query service for state of %s: %s\n"), 285 dest, verbose_papi_message(svc, status)); 286 return (-1); 287 } 288 289 status = papiPrinterListJobs(svc, dest, jattrs, PAPI_LIST_JOBS_ALL, 290 0, &jobs); 291 if (status != PAPI_OK) { 292 fprintf(fp, gettext( 293 "Failed to query service for jobs on %s: %s\n"), 294 dest, verbose_papi_message(svc, status)); 295 return (-1); 296 } 297 if (jobs != NULL) { 298 while (jobs[num_jobs] != NULL) 299 num_jobs++; 300 } 301 302 printer_state_line(fp, p, num_jobs, dest); 303 if (num_jobs > 0) { 304 int i; 305 306 if (fmt == 3) 307 print_header(fp); 308 for (i = 0; jobs[i] != NULL; i++) 309 print_job_line(fp, i, jobs[i], fmt, ac, av); 310 } 311 312 papiPrinterFree(p); 313 papiJobListFree(jobs); 314 315 return (num_jobs); 316 } 317 318 int 319 berkeley_cancel_request(papi_service_t svc, FILE *fp, char *dest, 320 int ac, char *av[]) 321 { 322 papi_status_t status; 323 papi_job_t *jobs = NULL; 324 char *jattrs[] = { "job-originating-user-name", "job-id", 325 "job-id-requested", NULL }; 326 327 status = papiPrinterListJobs(svc, dest, jattrs, PAPI_LIST_JOBS_ALL, 328 0, &jobs); 329 330 if (status != PAPI_OK) { 331 fprintf(fp, gettext("Failed to query service for %s: %s\n"), 332 dest, verbose_papi_message(svc, status)); 333 return (-1); 334 } 335 336 /* cancel the job(s) */ 337 if (jobs != NULL) { 338 int i; 339 340 for (i = 0; jobs[i] != NULL; i++) 341 cancel_job(svc, fp, dest, jobs[i], ac, av); 342 } 343 344 papiJobListFree(jobs); 345 346 return (0); 347 } 348 349 int 350 get_printer_id(char *name, char **printer, int *id) 351 { 352 int result = -1; 353 354 if (name != NULL) { 355 char *p = strrchr(name, '-'); 356 357 *printer = name; 358 if (p != NULL) { 359 char *s = NULL; 360 361 *id = strtol(p + 1, &s, 10); 362 if (s[0] != '\0') 363 *id = -1; 364 else 365 *p = '\0'; 366 result = 0; 367 } else 368 *id = -1; 369 } 370 371 return (result); 372 } 373 374 /* 375 * strsplit() splits a string into a NULL terminated array of substrings 376 * determined by a seperator. The original string is modified, and newly 377 * allocated space is only returned for the array itself. If more than 378 * 1024 substrings exist, they will be ignored. 379 */ 380 char ** 381 strsplit(char *string, const char *seperators) 382 { 383 char *list[BUFSIZ], 384 **result; 385 int length = 0; 386 387 if ((string == NULL) || (seperators == NULL)) 388 return (NULL); 389 390 (void) memset(list, 0, sizeof (list)); 391 for (list[length] = strtok(string, seperators); 392 (list[length] != NULL) && (length < (BUFSIZ - 2)); 393 list[length] = strtok(NULL, seperators)) 394 length++; 395 396 if ((result = (char **)calloc(length+1, sizeof (char *))) != NULL) 397 (void) memcpy(result, list, length * sizeof (char *)); 398 399 return (result); 400 } 401 402 papi_status_t 403 jobSubmitSTDIN(papi_service_t svc, char *printer, char *prefetch, int len, 404 papi_attribute_t **list, papi_job_t *job) 405 { 406 papi_status_t status; 407 papi_stream_t stream = NULL; 408 int rc; 409 char buf[BUFSIZ]; 410 411 status = papiJobStreamOpen(svc, printer, list, NULL, &stream); 412 413 if (len > 0) 414 status = papiJobStreamWrite(svc, stream, prefetch, len); 415 416 while ((status == PAPI_OK) && ((rc = read(0, buf, sizeof (buf))) > 0)) 417 status = papiJobStreamWrite(svc, stream, buf, rc); 418 419 if (status == PAPI_OK) 420 status = papiJobStreamClose(svc, stream, job); 421 422 return (status); 423 } 424 425 /* 426 * is_postscript() will detect if the file passed in contains postscript 427 * data. A one is returned if the file contains postscript, zero is returned 428 * if the file is not postscript, and -1 is returned if an error occurs 429 */ 430 #define PS_MAGIC "%!" 431 #define PC_PS_MAGIC "^D%!" 432 int 433 is_postscript_stream(int fd, char *buf, int *len) 434 { 435 if ((*len = read(fd, buf, *len)) < 0) { 436 close(fd); 437 return (-1); 438 } 439 440 if ((strncmp(buf, PS_MAGIC, sizeof (PS_MAGIC) - 1) == 0) || 441 (strncmp(buf, PC_PS_MAGIC, sizeof (PC_PS_MAGIC) - 1) == 0)) 442 return (1); 443 else 444 return (0); 445 } 446 447 int 448 is_postscript(const char *file) 449 { 450 int rc = -1; 451 int fd; 452 453 if ((fd = open(file, O_RDONLY)) >= 0) { 454 char buf[3]; 455 int len = sizeof (buf); 456 457 rc = is_postscript_stream(fd, buf, &len); 458 close(fd); 459 } 460 461 return (rc); 462 } 463 464 static char ** 465 all_list(papi_service_t svc) 466 { 467 papi_status_t status; 468 papi_printer_t printer = NULL; 469 char *list[] = { "member-names", NULL }; 470 char **result = NULL; 471 472 status = papiPrinterQuery(svc, "_all", list, NULL, &printer); 473 if ((status == PAPI_OK) && (printer != NULL)) { 474 papi_attribute_t **attributes = 475 papiPrinterGetAttributeList(printer); 476 if (attributes != NULL) { 477 void *iter = NULL; 478 char *value = NULL; 479 480 for (status = papiAttributeListGetString(attributes, 481 &iter, "member-names", &value); 482 status == PAPI_OK; 483 status = papiAttributeListGetString(attributes, 484 &iter, NULL, &value)) 485 list_append(&result, strdup(value)); 486 } 487 papiPrinterFree(printer); 488 } 489 490 return (result); 491 } 492 493 static char ** 494 printers_list(papi_service_t svc) 495 { 496 papi_status_t status; 497 papi_printer_t *printers = NULL; 498 char *keys[] = { "printer-name", NULL }; 499 char **result = NULL; 500 501 status = papiPrintersList(svc, keys, NULL, &printers); 502 if ((status == PAPI_OK) && (printers != NULL)) { 503 int i; 504 505 for (i = 0; printers[i] != NULL; i++) { 506 papi_attribute_t **attributes = 507 papiPrinterGetAttributeList(printers[i]); 508 char *name = NULL; 509 510 (void) papiAttributeListGetString(attributes, NULL, 511 "printer-name", &name); 512 if ((name != NULL) && (strcmp(name, "_default") != 0)) 513 list_append(&result, strdup(name)); 514 } 515 papiPrinterListFree(printers); 516 } 517 518 return (result); 519 } 520 521 char ** 522 interest_list(papi_service_t svc) 523 { 524 static char been_here; 525 static char **result; 526 527 if (been_here == 0) { /* only do this once */ 528 been_here = 1; 529 530 if ((result = all_list(svc)) == NULL) 531 result = printers_list(svc); 532 } 533 534 return (result); 535 } 536 537 char * 538 localhostname() 539 { 540 static char *result; 541 542 if (result == NULL) { 543 static char buf[256]; 544 545 if (gethostname(buf, sizeof (buf)) == 0) 546 result = buf; 547 } 548 549 return (result); 550 } 551 552 int 553 cli_auth_callback(papi_service_t svc, void *app_data) 554 { 555 char prompt[BUFSIZ]; 556 char *user, *svc_name, *passphrase; 557 558 /* get the name of the service we are contacting */ 559 if ((svc_name = papiServiceGetServiceName(svc)) == NULL) 560 return (-1); 561 562 /* find our who we are supposed to be */ 563 if ((user = papiServiceGetUserName(svc)) == NULL) { 564 struct passwd *pw; 565 566 if ((pw = getpwuid(getuid())) != NULL) 567 user = pw->pw_name; 568 else 569 user = "nobody"; 570 } 571 572 /* build the prompt string */ 573 snprintf(prompt, sizeof (prompt), 574 gettext("passphrase for %s to access %s: "), user, svc_name); 575 576 /* ask for the passphrase */ 577 if ((passphrase = getpassphrase(prompt)) != NULL) 578 papiServiceSetPassword(svc, passphrase); 579 580 return (0); 581 } 582