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: lp.c 179 2006-07-17 18:24:07Z 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 <string.h> 36 #include <locale.h> 37 #include <libintl.h> 38 #include <papi.h> 39 #include "common.h" 40 41 #ifdef HAVE_LIBMAGIC /* for mimetype auto-detection */ 42 #include <magic.h> 43 #endif /* HAVE_LIBMAGIC */ 44 45 static void 46 usage(char *program) 47 { 48 char *name; 49 50 if ((name = strrchr(program, '/')) == NULL) 51 name = program; 52 else 53 name++; 54 55 fprintf(stdout, 56 gettext("Usage: %s [-c] [-m] [-p] [-s] [-w] [-d destination] " 57 "[-f form-name] [-H special-handling] [-n number] " 58 "[-o option] [-P page-list] [-q priority-level] " 59 "[-S character-set | print-wheel] [-t title] [-v] " 60 "[-T content-type [-r]] [-y mode-list] [file...]\n"), 61 name); 62 exit(1); 63 } 64 65 static struct { 66 char *mime_type; 67 char *lp_type; 68 } type_map[] = { 69 { "text/plain", "simple" }, 70 { "application/octet-stream", "raw" }, 71 { "application/octet-stream", "any" }, 72 { "application/postscript", "postscript" }, 73 { "application/postscript", "ps" }, 74 { "application/x-cif", "cif" }, 75 { "application/x-dvi", "dvi" }, 76 { "application/x-plot", "plot" }, 77 { "application/x-ditroff", "troff" }, 78 { "application/x-troff", "otroff" }, 79 { "application/x-pr", "pr" }, 80 { "application/x-fortran", "fortran" }, 81 { "application/x-raster", "raster" }, 82 { NULL, NULL} 83 }; 84 85 static char * 86 lp_type_to_mime_type(char *lp_type) 87 { 88 int i; 89 90 if (lp_type == NULL) 91 return ("application/octet-stream"); 92 93 for (i = 0; type_map[i].lp_type != NULL; i++) 94 if (strcasecmp(type_map[i].lp_type, lp_type) == 0) 95 return (type_map[i].mime_type); 96 97 return (lp_type); 98 } 99 100 int 101 main(int ac, char *av[]) 102 { 103 papi_status_t status; 104 papi_service_t svc = NULL; 105 papi_attribute_t **list = NULL; 106 papi_encryption_t encryption = PAPI_ENCRYPT_NEVER; 107 papi_job_t job = NULL; 108 char *printer = NULL; 109 char b = PAPI_TRUE; 110 int copy = 0; 111 int silent = 0; 112 int dump = 0; 113 int validate = 0; 114 int modify = -1; 115 int c; 116 117 (void) setlocale(LC_ALL, ""); 118 (void) textdomain("SUNW_OST_OSCMD"); 119 120 while ((c = getopt(ac, av, "DEH:P:S:T:cd:f:i:mn:o:pq:rst:Vwy:")) != EOF) 121 switch (c) { 122 case 'H': /* handling */ 123 if (strcasecmp(optarg, "hold") == 0) 124 papiAttributeListAddString(&list, 125 PAPI_ATTR_EXCL, 126 "job-hold-until", "indefinite"); 127 else if (strcasecmp(optarg, "release") == 0) 128 papiAttributeListAddString(&list, 129 PAPI_ATTR_EXCL, 130 "job-hold-until", "no-hold"); 131 else if (strcasecmp(optarg, "immediate") == 0) 132 papiAttributeListAddInteger(&list, 133 PAPI_ATTR_EXCL, 134 "job-priority", 100); 135 else 136 papiAttributeListAddString(&list, 137 PAPI_ATTR_EXCL, 138 "job-hold-until", optarg); 139 break; 140 case 'P': /* page list */ 141 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 142 "page-ranges", optarg); 143 break; 144 case 'S': /* charset */ 145 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 146 "lp-charset", optarg); 147 break; 148 case 'T': /* type */ 149 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 150 "document-format", 151 lp_type_to_mime_type(optarg)); 152 break; 153 case 'D': /* dump */ 154 dump = 1; 155 break; 156 case 'c': /* copy */ 157 copy = 1; 158 break; 159 case 'd': /* destination */ 160 printer = optarg; 161 break; 162 case 'f': /* form */ 163 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 164 "media", optarg); 165 break; 166 case 'i': /* modify job */ 167 if ((get_printer_id(optarg, &printer, &modify) < 0) || 168 (modify < 0)) { 169 fprintf(stderr, 170 gettext("invalid request id: %s\n"), 171 optarg); 172 exit(1); 173 } 174 break; 175 case 'm': /* mail when complete */ 176 papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL, 177 "rfc-1179-mail", 1); 178 break; 179 case 'n': /* copies */ 180 papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 181 "copies", atoi(optarg)); 182 break; 183 case 'o': /* lp "options" */ 184 papiAttributeListFromString(&list, 185 PAPI_ATTR_REPLACE, optarg); 186 break; 187 case 'p': /* Solaris - notification */ 188 papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL, 189 "rfc-1179-mail", 1); 190 break; 191 case 'q': { /* priority */ 192 int i = atoi(optarg); 193 194 i = 99 * (39 - i) / 39 + 1; 195 if ((i < 1) || (i > 100)) { 196 fprintf(stderr, gettext( 197 "priority must be between 0 and 39.\n")); 198 exit(1); 199 } 200 papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 201 "priority", i); 202 } 203 break; 204 case 'r': /* "raw" mode */ 205 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 206 "document-format", 207 "application/octet-stream"); 208 papiAttributeListAddString(&list, PAPI_ATTR_APPEND, 209 "stty", "raw"); 210 break; 211 case 's': /* suppress message */ 212 silent = 1; 213 break; 214 case 't': /* title */ 215 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 216 "job-name", optarg); 217 break; 218 case 'V': /* validate */ 219 validate = 1; 220 break; 221 case 'w': 222 papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL, 223 "rfc-1179-mail", 1); 224 break; 225 case 'y': /* lp "modes" */ 226 papiAttributeListAddString(&list, PAPI_ATTR_APPEND, 227 "lp-modes", optarg); 228 break; 229 case 'E': 230 encryption = PAPI_ENCRYPT_REQUIRED; 231 break; 232 default: 233 usage(av[0]); 234 } 235 236 /* convert "banner", "nobanner" to "job-sheet" */ 237 if (papiAttributeListGetBoolean(list, NULL, "banner", &b) == PAPI_OK) { 238 (void) papiAttributeListDelete(&list, "banner"); 239 if (b == PAPI_FALSE) 240 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 241 "job-sheets", "none"); 242 } 243 244 if ((printer == NULL) && 245 ((printer = getenv("PRINTER")) == NULL) && 246 ((printer = getenv("LPDEST")) == NULL)) 247 printer = DEFAULT_DEST; 248 249 if (((optind + 1) == ac) && (strcmp(av[optind], "-") == 0)) 250 optind = ac; 251 252 if (modify == -1) { 253 char *document_format = "application/octet-stream"; 254 255 #ifdef MAGIC_MIME 256 if (optind != ac) { 257 /* get the mime type of the file data */ 258 magic_t ms = NULL; 259 260 if ((ms = magic_open(MAGIC_MIME)) != NULL) { 261 document_format = magic_file(ms, av[optind]); 262 magic_close(ms); 263 } 264 } 265 #endif 266 267 papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, "copies", 1); 268 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 269 "document-format", document_format); 270 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 271 "job-sheets", "standard"); 272 } 273 274 status = papiServiceCreate(&svc, printer, NULL, NULL, cli_auth_callback, 275 encryption, NULL); 276 if (status != PAPI_OK) { 277 fprintf(stderr, gettext( 278 "Failed to contact service for %s: %s\n"), printer, 279 verbose_papi_message(svc, status)); 280 exit(1); 281 } 282 283 if (modify != -1) 284 status = papiJobModify(svc, printer, modify, list, &job); 285 else if (optind == ac) /* no file list, use stdin */ 286 status = jobSubmitSTDIN(svc, printer, list, &job); 287 else if (validate == 1) /* validate the request can be processed */ 288 status = papiJobValidate(svc, printer, list, 289 NULL, &av[optind], &job); 290 else if (copy == 0) /* reference the files in the job, default */ 291 status = papiJobSubmitByReference(svc, printer, list, 292 NULL, &av[optind], &job); 293 else /* copy the files before return, -c */ 294 status = papiJobSubmit(svc, printer, list, 295 NULL, &av[optind], &job); 296 297 papiAttributeListFree(list); 298 299 if (status != PAPI_OK) { 300 fprintf(stderr, gettext("%s: %s\n"), printer, 301 verbose_papi_message(svc, status)); 302 papiJobFree(job); 303 papiServiceDestroy(svc); 304 exit(1); 305 } 306 307 if (((silent == 0) || (dump != 0)) && 308 ((list = papiJobGetAttributeList(job)) != NULL)) { 309 int32_t id = 0; 310 311 papiAttributeListGetString(list, NULL, 312 "printer-name", &printer); 313 papiAttributeListGetInteger(list, NULL, "job-id", &id); 314 printf(gettext("request id is %s-%d "), printer, id); 315 if (ac != optind) 316 printf("(%d file(s))\n", ac - optind); 317 else 318 printf("(standard input)\n"); 319 320 if (dump != 0) { 321 printf("job attributes:\n"); 322 papiAttributeListPrint(stdout, list, "\t"); 323 printf("\n"); 324 } 325 } 326 327 papiJobFree(job); 328 papiServiceDestroy(svc); 329 330 return (0); 331 } 332