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-job.c 157 2006-04-26 15:07:55Z 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 <errno.h> 37 #include <limits.h> 38 #include <sys/types.h> 39 #include <sys/stat.h> 40 #include <fcntl.h> 41 #include <string.h> 42 #include <pwd.h> 43 #include <libintl.h> 44 #include <papi_impl.h> 45 46 enum { LPD_RFC, LPD_SVR4 }; 47 48 static char 49 mime_type_to_rfc1179_type(char *mime) 50 { 51 static struct { char *mime; char rfc; } cvt[] = { 52 { "plain/text", 'f' }, 53 { "application/octet-stream", 'l' }, 54 { "application/postscript", 'f' }, /* rfc incorrectly has 'o' */ 55 { "application/x-pr", 'p' }, 56 { "application/x-cif", 'c' }, 57 { "application/x-dvi", 'd' }, 58 { "application/x-fortran", 'r' }, 59 { "application/x-plot", 'g' }, 60 { "application/x-ditroff", 'n' }, 61 { "application/x-troff", 't' }, 62 { "application/x-raster", 'v' }, 63 { NULL, 0} 64 }; 65 char result = '\0'; 66 67 if (mime != NULL) { 68 int i; 69 70 for (i = 0; cvt[i].mime != NULL; i++) 71 if (strcasecmp(cvt[i].mime, mime) == 0) { 72 result = cvt[i].rfc; 73 break; 74 } 75 } 76 77 return (result); 78 } 79 80 static papi_status_t 81 add_lpd_control_line(char **metadata, char code, char *value) 82 { 83 size_t size = 0; 84 char line[BUFSIZ]; 85 86 if ((metadata == NULL) || (value == NULL)) 87 return (PAPI_BAD_REQUEST); 88 89 if (*metadata != NULL) 90 size = strlen(*metadata); 91 size += strlen(value) + 3; 92 93 if (*metadata == NULL) { 94 *metadata = (char *)calloc(1, size); 95 } else { 96 void *tmp; 97 tmp = realloc(*metadata, size); 98 if (tmp) 99 *metadata = (char *)tmp; 100 else 101 return (PAPI_TEMPORARY_ERROR); 102 } 103 104 snprintf(line, sizeof (line), "%c%s\n", code, value); 105 strlcat(*metadata, line, size); 106 107 return (PAPI_OK); 108 } 109 110 static papi_status_t 111 add_svr4_control_line(char **metadata, char code, char *value) 112 { 113 114 char line[BUFSIZ]; 115 116 if ((metadata == NULL) || (value == NULL)) 117 return (PAPI_BAD_REQUEST); 118 119 snprintf(line, sizeof (line), "%c%s", code, value); 120 121 return (add_lpd_control_line(metadata, '5', line)); 122 } 123 124 static papi_status_t 125 add_hpux_control_line(char **metadata, char *value) 126 { 127 128 char line[BUFSIZ]; 129 130 if ((metadata == NULL) || (value == NULL)) 131 return (PAPI_BAD_REQUEST); 132 133 snprintf(line, sizeof (line), " O%s", value); 134 135 return (add_lpd_control_line(metadata, 'N', line)); 136 } 137 138 static papi_status_t 139 add_int_control_line(char **metadata, char code, int value, int flag) 140 { 141 char buf[16]; 142 143 snprintf(buf, sizeof (buf), "%d", value); 144 145 if (flag == LPD_SVR4) 146 return (add_svr4_control_line(metadata, code, buf)); 147 else 148 return (add_lpd_control_line(metadata, code, buf)); 149 } 150 151 static papi_status_t 152 lpd_add_rfc1179_attributes(service_t *svc, papi_attribute_t **attributes, 153 char **metadata, papi_attribute_t ***used) 154 { 155 papi_status_t status = PAPI_OK; 156 char *s; 157 int integer; 158 char bool; 159 char host[BUFSIZ]; 160 char *user = "nobody"; 161 uid_t uid = getuid(); 162 struct passwd *pw; 163 164 if (svc == NULL) 165 return (PAPI_BAD_REQUEST); 166 167 /* There is nothing to do */ 168 if (attributes == NULL) 169 return (PAPI_OK); 170 171 gethostname(host, sizeof (host)); 172 add_lpd_control_line(metadata, 'H', host); 173 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 174 "job-originating-host-name", host); 175 176 if ((pw = getpwuid(uid)) != NULL) 177 user = pw->pw_name; 178 if (uid == 0) 179 papiAttributeListGetString(svc->attributes, NULL, "username", 180 &user); 181 add_lpd_control_line(metadata, 'P', user); 182 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 183 "job-originating-user-name", user); 184 185 /* Class for Banner Page */ 186 s = NULL; 187 papiAttributeListGetString(attributes, NULL, "rfc-1179-class", &s); 188 if (s != NULL) { 189 add_lpd_control_line(metadata, 'C', s); 190 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 191 "rfc-1179-class", s); 192 } 193 194 /* Print Banner Page */ 195 s = NULL; 196 papiAttributeListGetString(attributes, NULL, "job-sheets", &s); 197 if ((s != NULL) && (strcmp(s, "standard") == 0)) { 198 add_lpd_control_line(metadata, 'L', user); 199 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 200 "job-sheets", s); 201 } 202 203 /* Jobname */ 204 s = NULL; 205 papiAttributeListGetString(attributes, NULL, "job-name", &s); 206 if (s != NULL) { 207 add_lpd_control_line(metadata, 'J', s); 208 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 209 "job-name", s); 210 } 211 212 /* User to mail when job is done - lpr -m */ 213 bool = PAPI_FALSE; 214 papiAttributeListGetBoolean(attributes, NULL, "rfc-1179-mail", &bool); 215 if (bool == PAPI_TRUE) { 216 add_lpd_control_line(metadata, 'M', user); 217 papiAttributeListAddBoolean(used, PAPI_ATTR_EXCL, 218 "rfc-1179-mail", bool); 219 } 220 221 /* Title for pr */ 222 s = NULL; 223 papiAttributeListGetString(attributes, NULL, "pr-title", &s); 224 if (s != NULL) { 225 add_lpd_control_line(metadata, 'T', s); 226 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 227 "pr-title", s); 228 } 229 230 /* Indent - used with pr filter */ 231 integer = 0; 232 papiAttributeListGetInteger(attributes, NULL, "pr-indent", &integer); 233 if (integer >= 1) { 234 add_int_control_line(metadata, 'I', integer, LPD_RFC); 235 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, 236 "pr-indent", integer); 237 } 238 239 /* Width - used with pr filter */ 240 integer = 0; 241 papiAttributeListGetInteger(attributes, NULL, "pr-width", &integer); 242 if (integer >= 1) { 243 add_int_control_line(metadata, 'W', integer, LPD_RFC); 244 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, 245 "pr-width", integer); 246 } 247 248 /* file with Times Roman font lpr -1 */ 249 s = NULL; 250 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-r", &s); 251 if (s != NULL) { 252 add_lpd_control_line(metadata, '1', s); 253 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 254 "rfc-1179-font-r", s); 255 } 256 257 /* file with Times Roman font lpr -2 */ 258 s = NULL; 259 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-i", &s); 260 if (s != NULL) { 261 add_lpd_control_line(metadata, '2', s); 262 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 263 "rfc-1179-font-i", s); 264 } 265 266 /* file with Times Roman font lpr -3 */ 267 s = NULL; 268 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-b", &s); 269 if (s != NULL) { 270 add_lpd_control_line(metadata, '3', s); 271 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 272 "rfc-1179-font-b", s); 273 } 274 275 /* file with Times Roman font lpr -4 */ 276 s = NULL; 277 papiAttributeListGetString(attributes, NULL, "rfc-1179-font-s", &s); 278 if (s != NULL) { 279 add_lpd_control_line(metadata, '4', s); 280 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 281 "rfc-1179-font-s", s); 282 } 283 284 return (status); 285 } 286 287 /* 288 * lpd_add_svr4_attributes 289 * Solaris 2.x LP - BSD protocol extensions 290 */ 291 static papi_status_t 292 lpd_add_svr4_attributes(service_t *svc, papi_attribute_t **attributes, 293 char **metadata, papi_attribute_t ***used) 294 { 295 char *s; 296 int integer; 297 298 if (svc == NULL) 299 return (PAPI_BAD_REQUEST); 300 301 /* media */ 302 s = NULL; 303 papiAttributeListGetString(attributes, NULL, "media", &s); 304 if (s != NULL) { 305 add_svr4_control_line(metadata, 'f', s); 306 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 307 "media", s); 308 } 309 310 /* Handling */ 311 s = NULL; 312 papiAttributeListGetString(attributes, NULL, "job_hold_until", &s); 313 if ((s != NULL) && (strcmp(s, "indefinite"))) { 314 add_svr4_control_line(metadata, 'H', "hold"); 315 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 316 "media", "hold"); 317 } else if ((s != NULL) && (strcmp(s, "no-hold"))) { 318 add_svr4_control_line(metadata, 'H', "release"); 319 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 320 "media", "release"); 321 } else if ((s != NULL) && (strcmp(s, "immediate"))) { 322 add_int_control_line(metadata, 'q', 0, LPD_SVR4); 323 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 324 "media", "immediate"); 325 } 326 327 /* Pages */ 328 s = NULL; 329 papiAttributeListGetString(attributes, NULL, "page-ranges", &s); 330 if (s != NULL) { 331 add_svr4_control_line(metadata, 'P', s); 332 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 333 "page-ranges", s); 334 } 335 336 /* Priority : lp -q */ 337 integer = -1; 338 papiAttributeListGetInteger(attributes, NULL, "priority", &integer); 339 if (integer != -1) { 340 add_int_control_line(metadata, 'q', integer, LPD_SVR4); 341 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, 342 "priority", integer); 343 } 344 345 /* Charset : lp -S */ 346 s = NULL; 347 papiAttributeListGetString(attributes, NULL, "lp-charset", &s); 348 if (s != NULL) { 349 add_svr4_control_line(metadata, 'S', s); 350 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 351 "lp-charset", s); 352 } 353 354 /* Type : done when adding file */ 355 356 /* Mode : lp -y */ 357 s = NULL; 358 papiAttributeListGetString(attributes, NULL, "lp-modes", &s); 359 if (s != NULL) { 360 add_svr4_control_line(metadata, 'y', s); 361 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 362 "lp-modes", s); 363 } 364 365 /* Options lp -o */ 366 s = NULL; 367 papiAttributeListGetString(attributes, NULL, "lp-options", &s); 368 if (s != NULL) { 369 add_svr4_control_line(metadata, 'o', s); 370 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 371 "lp-options", s); 372 } 373 374 return (PAPI_OK); 375 } 376 377 papi_status_t 378 lpd_add_hpux_attributes(service_t *svc, papi_attribute_t **attributes, 379 char **metadata, papi_attribute_t ***used) 380 { 381 char *s = NULL; 382 383 /* Options lp -o */ 384 s = NULL; 385 papiAttributeListGetString(attributes, NULL, "lp-options", &s); 386 if (s != NULL) { 387 add_hpux_control_line(metadata, s); 388 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 389 "lp-options", s); 390 } 391 392 return (PAPI_OK); 393 } 394 395 papi_status_t 396 lpd_job_add_attributes(service_t *svc, papi_attribute_t **attributes, 397 char **metadata, papi_attribute_t ***used) 398 { 399 if ((svc == NULL) || (metadata == NULL)) 400 return (PAPI_BAD_REQUEST); 401 402 lpd_add_rfc1179_attributes(svc, attributes, metadata, used); 403 404 if (svc->uri->fragment != NULL) { 405 if ((strcasecmp(svc->uri->fragment, "solaris") == 0) || 406 (strcasecmp(svc->uri->fragment, "svr4") == 0)) 407 lpd_add_svr4_attributes(svc, attributes, metadata, 408 used); 409 else if (strcasecmp(svc->uri->fragment, "hpux") == 0) 410 lpd_add_hpux_attributes(svc, attributes, metadata, 411 used); 412 /* 413 * others could be added here: 414 * lprng, sco, aix, digital unix, xerox, ... 415 */ 416 } 417 418 return (PAPI_OK); 419 } 420 421 papi_status_t 422 lpd_job_add_files(service_t *svc, papi_attribute_t **attributes, 423 char **files, char **metadata, papi_attribute_t ***used) 424 { 425 char *format = "plain/text"; 426 char rfc_fmt = 'l'; 427 int copies = 1; 428 char host[BUFSIZ]; 429 int i; 430 431 if ((svc == NULL) || (attributes == NULL) || (files == NULL) || 432 (metadata == NULL)) 433 return (PAPI_BAD_ARGUMENT); 434 435 papiAttributeListGetString(attributes, NULL, "document-format", 436 &format); 437 papiAttributeListAddString(used, PAPI_ATTR_EXCL, 438 "document-format", format); 439 if ((rfc_fmt = mime_type_to_rfc1179_type(format)) == '\0') { 440 if ((svc->uri->fragment != NULL) && 441 ((strcasecmp(svc->uri->fragment, "solaris") == 0) || 442 (strcasecmp(svc->uri->fragment, "svr4") == 0))) 443 add_svr4_control_line(metadata, 'T', format); 444 rfc_fmt = 'l'; 445 } 446 447 papiAttributeListGetInteger(attributes, NULL, "copies", &copies); 448 if (copies < 1) 449 copies = 1; 450 papiAttributeListAddInteger(used, PAPI_ATTR_EXCL, "copies", copies); 451 452 gethostname(host, sizeof (host)); 453 454 for (i = 0; files[i] != NULL; i++) { 455 char name[BUFSIZ]; 456 char key; 457 int j; 458 459 if ((strcmp("standard input", files[i]) != 0) && 460 (access(files[i], R_OK) < 0)) { 461 detailed_error(svc, gettext("aborting request, %s: %s"), 462 files[i], strerror(errno)); 463 return (PAPI_NOT_AUTHORIZED); 464 } 465 466 if (i < 26) 467 key = 'A' + i; 468 else if (i < 52) 469 key = 'a' + (i - 26); 470 else if (i < 62) 471 key = '0' + (i - 52); 472 else { 473 detailed_error(svc, 474 gettext("too many files, truncated at 62")); 475 return (PAPI_OK_SUBST); 476 } 477 478 snprintf(name, sizeof (name), "df%cXXX%s", key, host); 479 480 for (j = 0; j < copies; j++) 481 add_lpd_control_line(metadata, rfc_fmt, name); 482 add_lpd_control_line(metadata, 'U', name); 483 add_lpd_control_line(metadata, 'N', (char *)files[i]); 484 } 485 486 return (PAPI_OK); 487 } 488 489 papi_status_t 490 lpd_submit_job(service_t *svc, char *metadata, papi_attribute_t ***attributes, 491 int *ofd) 492 { 493 papi_status_t status = PAPI_INTERNAL_ERROR; 494 int fd; 495 char path[32]; 496 char *list[2]; 497 498 if ((svc == NULL) || (metadata == NULL)) 499 return (PAPI_BAD_ARGUMENT); 500 501 strcpy(path, "/tmp/lpd-job-XXXXXX"); 502 fd = mkstemp(path); 503 write(fd, metadata, strlen(metadata)); 504 close(fd); 505 506 list[0] = path; 507 list[1] = NULL; 508 509 if (((fd = lpd_open(svc, 's', list, 3)) < 0) && (errno != EBADMSG)) { 510 switch (errno) { 511 case ENOSPC: 512 status = PAPI_TEMPORARY_ERROR; 513 break; 514 case EIO: 515 status = PAPI_TEMPORARY_ERROR; 516 break; 517 case ECONNREFUSED: 518 status = PAPI_SERVICE_UNAVAILABLE; 519 break; 520 case ENOENT: 521 status = PAPI_NOT_ACCEPTING; 522 break; 523 case EBADMSG: 524 case EBADF: 525 status = PAPI_OK; 526 break; 527 default: 528 status = PAPI_TIMEOUT; 529 break; 530 } 531 } else 532 status = PAPI_OK; 533 534 if (ofd != NULL) 535 *ofd = fd; 536 else 537 close(fd); 538 539 /* read the ID and add it to to the job */ 540 if ((fd = open(path, O_RDONLY)) >= 0) { 541 int job_id = 0; 542 read(fd, &job_id, sizeof (job_id)); 543 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 544 "job-id", job_id); 545 close(fd); 546 } 547 548 unlink(path); 549 550 return (status); 551 } 552