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