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: 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) 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 char *user = ""; 242 char *mesg = gettext("cancelled"); 243 244 papiAttributeListGetInteger(list, NULL, 245 "job-id", &id); 246 papiAttributeListGetString(list, NULL, 247 "job-originating-user-name", &user); 248 249 /* if we are looking and it doesn't match, return early */ 250 if ((ac > 0) && (match_job(id, user, ac, av) < 0)) 251 return; 252 253 status = papiJobCancel(svc, printer, id); 254 if (status != PAPI_OK) 255 mesg = papiStatusString(status); 256 257 fprintf(fp, "%s-%d: %s\n", printer, id, mesg); 258 } 259 260 int 261 berkeley_queue_report(papi_service_t svc, FILE *fp, char *dest, int fmt, 262 int ac, char *av[]) 263 { 264 papi_status_t status; 265 papi_printer_t p = NULL; 266 papi_job_t *jobs = NULL; 267 char *pattrs[] = { "printer-name", "printer-state", 268 "printer-state-reasons", NULL }; 269 char *jattrs[] = { "job-name", "job-octets", "job-k-octets", "job-id", 270 "job-originating-user-name", 271 "job-originating-host-name", 272 "number-of-intervening-jobs", NULL }; 273 int num_jobs = 0; 274 275 status = papiPrinterQuery(svc, dest, pattrs, NULL, &p); 276 if (status != PAPI_OK) { 277 fprintf(fp, gettext( 278 "Failed to query service for state of %s: %s\n"), 279 dest, verbose_papi_message(svc, status)); 280 return (-1); 281 } 282 283 status = papiPrinterListJobs(svc, dest, jattrs, PAPI_LIST_JOBS_ALL, 284 0, &jobs); 285 if (status != PAPI_OK) { 286 fprintf(fp, gettext( 287 "Failed to query service for jobs on %s: %s\n"), 288 dest, verbose_papi_message(svc, status)); 289 return (-1); 290 } 291 if (jobs != NULL) { 292 while (jobs[num_jobs] != NULL) 293 num_jobs++; 294 } 295 296 printer_state_line(fp, p, num_jobs, dest); 297 if (num_jobs > 0) { 298 int i; 299 300 if (fmt == 3) 301 print_header(fp); 302 for (i = 0; jobs[i] != NULL; i++) 303 print_job_line(fp, i, jobs[i], fmt, ac, av); 304 } 305 306 papiPrinterFree(p); 307 papiJobListFree(jobs); 308 309 return (num_jobs); 310 } 311 312 int 313 berkeley_cancel_request(papi_service_t svc, FILE *fp, char *dest, 314 int ac, char *av[]) 315 { 316 papi_status_t status; 317 papi_job_t *jobs = NULL; 318 char *jattrs[] = { "job-originating-user-name", "job-id", NULL }; 319 320 status = papiPrinterListJobs(svc, dest, jattrs, PAPI_LIST_JOBS_ALL, 321 0, &jobs); 322 323 if (status != PAPI_OK) { 324 fprintf(fp, gettext("Failed to query service for %s: %s\n"), 325 dest, verbose_papi_message(svc, status)); 326 return (-1); 327 } 328 329 /* cancel the job(s) */ 330 if (jobs != NULL) { 331 int i; 332 333 for (i = 0; jobs[i] != NULL; i++) 334 cancel_job(svc, fp, dest, jobs[i], ac, av); 335 } 336 337 papiJobListFree(jobs); 338 339 return (0); 340 } 341 342 int 343 get_printer_id(char *name, char **printer, int *id) 344 { 345 int result = -1; 346 347 if (name != NULL) { 348 char *p = strrchr(name, '-'); 349 350 *printer = name; 351 if (p != NULL) { 352 char *s = NULL; 353 354 *id = strtol(p + 1, &s, 10); 355 if (s[0] != '\0') 356 *id = -1; 357 else 358 *p = '\0'; 359 result = 0; 360 } else 361 *id = -1; 362 } 363 364 return (result); 365 } 366 367 /* 368 * strsplit() splits a string into a NULL terminated array of substrings 369 * determined by a seperator. The original string is modified, and newly 370 * allocated space is only returned for the array itself. If more than 371 * 1024 substrings exist, they will be ignored. 372 */ 373 char ** 374 strsplit(char *string, const char *seperators) 375 { 376 char *list[BUFSIZ], 377 **result; 378 int length = 0; 379 380 if ((string == NULL) || (seperators == NULL)) 381 return (NULL); 382 383 (void) memset(list, 0, sizeof (list)); 384 for (list[length] = strtok(string, seperators); 385 (list[length] != NULL) && (length < (BUFSIZ - 2)); 386 list[length] = strtok(NULL, seperators)) 387 length++; 388 389 if ((result = (char **)calloc(length+1, sizeof (char *))) != NULL) 390 (void) memcpy(result, list, length * sizeof (char *)); 391 392 return (result); 393 } 394 395 papi_status_t 396 jobSubmitSTDIN(papi_service_t svc, char *printer, papi_attribute_t **list, 397 papi_job_t *job) 398 { 399 papi_status_t status; 400 papi_stream_t stream = NULL; 401 int rc; 402 char buf[BUFSIZ]; 403 404 status = papiJobStreamOpen(svc, printer, list, NULL, &stream); 405 while ((status == PAPI_OK) && ((rc = read(0, buf, sizeof (buf))) > 0)) 406 status = papiJobStreamWrite(svc, stream, buf, rc); 407 408 if (status == PAPI_OK) 409 status = papiJobStreamClose(svc, stream, job); 410 411 return (status); 412 } 413 414 /* 415 * is_postscript() will detect if the file passed in contains postscript 416 * data. A one is returned if the file contains postscript, zero is returned 417 * if the file is not postscript, and -1 is returned if an error occurs 418 */ 419 #define PS_MAGIC "%!" 420 #define PC_PS_MAGIC "^D%!" 421 int 422 is_postscript(const char *file) 423 { 424 char buf[3]; 425 int fd; 426 427 if ((fd = open(file, O_RDONLY)) < 0) 428 return (-1); 429 430 if (read(fd, buf, sizeof (buf)) < 0) { 431 close(fd); 432 return (-1); 433 } 434 close(fd); 435 436 if ((strncmp(buf, PS_MAGIC, sizeof (PS_MAGIC) - 1) == 0) || 437 (strncmp(buf, PC_PS_MAGIC, sizeof (PC_PS_MAGIC) - 1) == 0)) 438 return (1); 439 else 440 return (0); 441 } 442 443 static char ** 444 all_list(papi_service_t svc) 445 { 446 papi_status_t status; 447 papi_printer_t printer = NULL; 448 char *list[] = { "member-names", NULL }; 449 char **result = NULL; 450 451 status = papiPrinterQuery(svc, "_all", list, NULL, &printer); 452 if ((status == PAPI_OK) && (printer != NULL)) { 453 papi_attribute_t **attributes = 454 papiPrinterGetAttributeList(printer); 455 if (attributes != NULL) { 456 void *iter = NULL; 457 char *value = NULL; 458 459 for (status = papiAttributeListGetString(attributes, 460 &iter, "member-names", &value); 461 status == PAPI_OK; 462 status = papiAttributeListGetString(attributes, 463 &iter, NULL, &value)) 464 list_append(&result, strdup(value)); 465 } 466 papiPrinterFree(printer); 467 } 468 469 return (result); 470 } 471 472 static char ** 473 printers_list(papi_service_t svc) 474 { 475 papi_status_t status; 476 papi_printer_t *printers = NULL; 477 char *keys[] = { "printer-name", NULL }; 478 char **result = NULL; 479 480 status = papiPrintersList(svc, keys, NULL, &printers); 481 if ((status == PAPI_OK) && (printers != NULL)) { 482 int i; 483 484 for (i = 0; printers[i] != NULL; i++) { 485 papi_attribute_t **attributes = 486 papiPrinterGetAttributeList(printers[i]); 487 char *name = NULL; 488 489 (void) papiAttributeListGetString(attributes, NULL, 490 "printer-name", &name); 491 if ((name != NULL) && (strcmp(name, "_default") != 0)) 492 list_append(&result, strdup(name)); 493 } 494 papiPrinterListFree(printers); 495 } 496 497 return (result); 498 } 499 500 char ** 501 interest_list(papi_service_t svc) 502 { 503 static char been_here; 504 static char **result; 505 506 if (been_here == 0) { /* only do this once */ 507 been_here = 1; 508 509 if ((result = all_list(svc)) == NULL) 510 result = printers_list(svc); 511 } 512 513 return (result); 514 } 515 516 char * 517 localhostname() 518 { 519 static char *result; 520 521 if (result == NULL) { 522 static char buf[256]; 523 524 if (gethostname(buf, sizeof (buf)) == 0) 525 result = buf; 526 } 527 528 return (result); 529 } 530 531 int 532 cli_auth_callback(papi_service_t svc, void *app_data) 533 { 534 char prompt[BUFSIZ]; 535 char *user, *svc_name, *passphrase; 536 537 /* get the name of the service we are contacting */ 538 if ((svc_name = papiServiceGetServiceName(svc)) == NULL) 539 return (-1); 540 541 /* find our who we are supposed to be */ 542 if ((user = papiServiceGetUserName(svc)) == NULL) { 543 struct passwd *pw; 544 545 if ((pw = getpwuid(getuid())) != NULL) 546 user = pw->pw_name; 547 else 548 user = "nobody"; 549 } 550 551 /* build the prompt string */ 552 snprintf(prompt, sizeof (prompt), 553 gettext("passphrase for %s to access %s: "), user, svc_name); 554 555 /* ask for the passphrase */ 556 if ((passphrase = getpassphrase(prompt)) != NULL) 557 papiServiceSetPassword(svc, passphrase); 558 559 return (0); 560 } 561