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