1/* 2 * "$Id: lpinfo.c 11093 2013-07-03 20:48:42Z msweet $" 3 * 4 * "lpinfo" command for CUPS. 5 * 6 * Copyright 2007-2010 by Apple Inc. 7 * Copyright 1997-2006 by Easy Software Products. 8 * 9 * These coded instructions, statements, and computer programs are the 10 * property of Apple Inc. and are protected by Federal copyright 11 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 12 * which should have been included with this file. If this file is 13 * file is missing or damaged, see the license at "http://www.cups.org/". 14 * 15 * Contents: 16 * 17 * main() - Parse options and show information. 18 * device_cb - Device callback. 19 * show_devices() - Show available devices. 20 * show_models() - Show available PPDs. 21 */ 22 23/* 24 * Include necessary headers... 25 */ 26 27#include <cups/cups-private.h> 28 29 30/* 31 * Local functions... 32 */ 33 34static void device_cb(const char *device_clas, const char *device_id, 35 const char *device_info, 36 const char *device_make_and_model, 37 const char *device_uri, const char *device_location, 38 void *user_data); 39static int show_devices(int long_status, int timeout, 40 const char *include_schemes, 41 const char *exclude_schemes); 42static int show_models(int long_status, 43 const char *device_id, const char *language, 44 const char *make_model, const char *product, 45 const char *include_schemes, 46 const char *exclude_schemes); 47 48 49/* 50 * 'main()' - Parse options and show status information. 51 */ 52 53int 54main(int argc, /* I - Number of command-line arguments */ 55 char *argv[]) /* I - Command-line arguments */ 56{ 57 int i; /* Looping var */ 58 int long_status; /* Long listing? */ 59 const char *device_id, /* 1284 device ID */ 60 *language, /* Language */ 61 *make_model, /* Make and model */ 62 *product, /* Product */ 63 *include_schemes, /* Schemes to include */ 64 *exclude_schemes; /* Schemes to exclude */ 65 int timeout; /* Device timeout */ 66 67 68 _cupsSetLocale(argv); 69 70 long_status = 0; 71 device_id = NULL; 72 language = NULL; 73 make_model = NULL; 74 product = NULL; 75 include_schemes = CUPS_INCLUDE_ALL; 76 exclude_schemes = CUPS_EXCLUDE_NONE; 77 timeout = CUPS_TIMEOUT_DEFAULT; 78 79 for (i = 1; i < argc; i ++) 80 if (argv[i][0] == '-') 81 switch (argv[i][1]) 82 { 83 case 'E' : /* Encrypt */ 84#ifdef HAVE_SSL 85 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); 86#else 87 _cupsLangPrintf(stderr, 88 _("%s: Sorry, no encryption support."), 89 argv[0]); 90#endif /* HAVE_SSL */ 91 break; 92 93 case 'h' : /* Connect to host */ 94 if (argv[i][2] != '\0') 95 cupsSetServer(argv[i] + 2); 96 else 97 { 98 i ++; 99 100 if (i >= argc) 101 { 102 _cupsLangPuts(stderr, 103 _("Error: need hostname after \"-h\" option.")); 104 return (1); 105 } 106 107 cupsSetServer(argv[i]); 108 } 109 break; 110 111 case 'l' : /* Show long listing */ 112 long_status = 1; 113 break; 114 115 case 'm' : /* Show models */ 116 if (show_models(long_status, device_id, language, make_model, 117 product, include_schemes, exclude_schemes)) 118 return (1); 119 break; 120 121 case 'v' : /* Show available devices */ 122 if (show_devices(long_status, timeout, include_schemes, 123 exclude_schemes)) 124 return (1); 125 break; 126 127 case '-' : /* --something */ 128 if (!strcmp(argv[i], "--device-id")) 129 { 130 i ++; 131 132 if (i < argc) 133 device_id = argv[i]; 134 else 135 { 136 _cupsLangPuts(stderr, 137 _("lpinfo: Expected 1284 device ID string " 138 "after \"--device-id\".")); 139 return (1); 140 } 141 } 142 else if (!strncmp(argv[i], "--device-id=", 12) && argv[i][12]) 143 { 144 device_id = argv[i] + 12; 145 } 146 else if (!strcmp(argv[i], "--exclude-schemes")) 147 { 148 i ++; 149 150 if (i < argc) 151 exclude_schemes = argv[i]; 152 else 153 { 154 _cupsLangPuts(stderr, 155 _("lpinfo: Expected scheme list after " 156 "\"--exclude-schemes\".")); 157 return (1); 158 } 159 } 160 else if (!strncmp(argv[i], "--exclude-schemes=", 18) && argv[i][18]) 161 { 162 exclude_schemes = argv[i] + 18; 163 } 164 else if (!strcmp(argv[i], "--include-schemes")) 165 { 166 i ++; 167 168 if (i < argc) 169 include_schemes = argv[i]; 170 else 171 { 172 _cupsLangPuts(stderr, 173 _("lpinfo: Expected scheme list after " 174 "\"--include-schemes\".")); 175 return (1); 176 } 177 } 178 else if (!strncmp(argv[i], "--include-schemes=", 18) && argv[i][18]) 179 { 180 include_schemes = argv[i] + 18; 181 } 182 else if (!strcmp(argv[i], "--language")) 183 { 184 i ++; 185 if (i < argc) 186 language = argv[i]; 187 else 188 { 189 _cupsLangPuts(stderr, 190 _("lpinfo: Expected language after " 191 "\"--language\".")); 192 return (1); 193 } 194 } 195 else if (!strncmp(argv[i], "--language=", 11) && argv[i][11]) 196 { 197 language = argv[i] + 11; 198 } 199 else if (!strcmp(argv[i], "--make-and-model")) 200 { 201 i ++; 202 if (i < argc) 203 make_model= argv[i]; 204 else 205 { 206 _cupsLangPuts(stderr, 207 _("lpinfo: Expected make and model after " 208 "\"--make-and-model\".")); 209 return (1); 210 } 211 } 212 else if (!strncmp(argv[i], "--make-and-model=", 17) && argv[i][17]) 213 { 214 make_model = argv[i] + 17; 215 } 216 else if (!strcmp(argv[i], "--product")) 217 { 218 i ++; 219 if (i < argc) 220 product = argv[i]; 221 else 222 { 223 _cupsLangPuts(stderr, 224 _("lpinfo: Expected product string after " 225 "\"--product\".")); 226 return (1); 227 } 228 } 229 else if (!strncmp(argv[i], "--product=", 10) && argv[i][10]) 230 { 231 product = argv[i] + 10; 232 } 233 else if (!strcmp(argv[i], "--timeout")) 234 { 235 i ++; 236 if (i < argc) 237 timeout = atoi(argv[i]); 238 else 239 { 240 _cupsLangPuts(stderr, 241 _("lpinfo: Expected timeout after " 242 "\"--timeout\".")); 243 return (1); 244 } 245 } 246 else if (!strncmp(argv[i], "--timeout=", 10) && argv[i][10]) 247 { 248 timeout = atoi(argv[i] + 10); 249 } 250 else 251 { 252 _cupsLangPrintf(stderr, _("lpinfo: Unknown option \"%s\"."), 253 argv[i]); 254 return (1); 255 } 256 break; 257 258 default : 259 _cupsLangPrintf(stderr, _("lpinfo: Unknown option \"%c\"."), 260 argv[i][1]); 261 return (1); 262 } 263 else 264 { 265 _cupsLangPrintf(stderr, _("lpinfo: Unknown argument \"%s\"."), 266 argv[i]); 267 return (1); 268 } 269 270 return (0); 271} 272 273 274/* 275 * 'device_cb()' - Device callback. 276 */ 277 278static void 279device_cb( 280 const char *device_class, /* I - device-class string */ 281 const char *device_id, /* I - device-id string */ 282 const char *device_info, /* I - device-info string */ 283 const char *device_make_and_model, /* I - device-make-and-model string */ 284 const char *device_uri, /* I - device-uri string */ 285 const char *device_location, /* I - device-location string */ 286 void *user_data) /* I - User data */ 287{ 288 int *long_status; /* Show verbose info? */ 289 290 291 /* 292 * Display the device... 293 */ 294 295 long_status = (int *)user_data; 296 297 if (*long_status) 298 { 299 _cupsLangPrintf(stdout, 300 _("Device: uri = %s\n" 301 " class = %s\n" 302 " info = %s\n" 303 " make-and-model = %s\n" 304 " device-id = %s\n" 305 " location = %s"), 306 device_uri, device_class, device_info, 307 device_make_and_model, device_id, device_location); 308 } 309 else 310 _cupsLangPrintf(stdout, "%s %s", device_class, device_uri); 311} 312 313 314/* 315 * 'show_devices()' - Show available devices. 316 */ 317 318static int /* O - 0 on success, 1 on failure */ 319show_devices( 320 int long_status, /* I - Long status report? */ 321 int timeout, /* I - Timeout */ 322 const char *include_schemes, /* I - List of schemes to include */ 323 const char *exclude_schemes) /* I - List of schemes to exclude */ 324{ 325 if (cupsGetDevices(CUPS_HTTP_DEFAULT, timeout, include_schemes, 326 exclude_schemes, device_cb, &long_status) != IPP_OK) 327 { 328 _cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString()); 329 return (1); 330 } 331 332 return (0); 333} 334 335 336/* 337 * 'show_models()' - Show available PPDs. 338 */ 339 340static int /* O - 0 on success, 1 on failure */ 341show_models( 342 int long_status, /* I - Long status report? */ 343 const char *device_id, /* I - 1284 device ID */ 344 const char *language, /* I - Language */ 345 const char *make_model, /* I - Make and model */ 346 const char *product, /* I - Product */ 347 const char *include_schemes, /* I - List of schemes to include */ 348 const char *exclude_schemes) /* I - List of schemes to exclude */ 349{ 350 ipp_t *request, /* IPP Request */ 351 *response; /* IPP Response */ 352 ipp_attribute_t *attr; /* Current attribute */ 353 const char *ppd_device_id, /* Pointer to ppd-device-id */ 354 *ppd_language, /* Pointer to ppd-natural-language */ 355 *ppd_make_model, /* Pointer to ppd-make-and-model */ 356 *ppd_name; /* Pointer to ppd-name */ 357 cups_option_t option; /* in/exclude-schemes option */ 358 359 360 /* 361 * Build a CUPS_GET_PPDS request... 362 */ 363 364 request = ippNewRequest(CUPS_GET_PPDS); 365 366 if (device_id) 367 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-device-id", 368 NULL, device_id); 369 if (language) 370 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "ppd-language", 371 NULL, language); 372 if (make_model) 373 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make-and-model", 374 NULL, make_model); 375 if (product) 376 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-product", 377 NULL, product); 378 379 if (include_schemes) 380 { 381 option.name = "include-schemes"; 382 option.value = (char *)include_schemes; 383 384 cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); 385 } 386 387 if (exclude_schemes) 388 { 389 option.name = "exclude-schemes"; 390 option.value = (char *)exclude_schemes; 391 392 cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION); 393 } 394 395 /* 396 * Do the request and get back a response... 397 */ 398 399 if ((response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/")) != NULL) 400 { 401 /* 402 * Loop through the device list and display them... 403 */ 404 405 if (response->request.status.status_code > IPP_OK_CONFLICT) 406 { 407 _cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString()); 408 ippDelete(response); 409 return (1); 410 } 411 412 for (attr = response->attrs; attr != NULL; attr = attr->next) 413 { 414 /* 415 * Skip leading attributes until we hit a PPD... 416 */ 417 418 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) 419 attr = attr->next; 420 421 if (attr == NULL) 422 break; 423 424 /* 425 * Pull the needed attributes from this PPD... 426 */ 427 428 ppd_device_id = "NONE"; 429 ppd_language = NULL; 430 ppd_make_model = NULL; 431 ppd_name = NULL; 432 433 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) 434 { 435 if (!strcmp(attr->name, "ppd-device-id") && 436 attr->value_tag == IPP_TAG_TEXT) 437 ppd_device_id = attr->values[0].string.text; 438 else if (!strcmp(attr->name, "ppd-natural-language") && 439 attr->value_tag == IPP_TAG_LANGUAGE) 440 ppd_language = attr->values[0].string.text; 441 else if (!strcmp(attr->name, "ppd-make-and-model") && 442 attr->value_tag == IPP_TAG_TEXT) 443 ppd_make_model = attr->values[0].string.text; 444 else if (!strcmp(attr->name, "ppd-name") && 445 attr->value_tag == IPP_TAG_NAME) 446 ppd_name = attr->values[0].string.text; 447 448 attr = attr->next; 449 } 450 451 /* 452 * See if we have everything needed... 453 */ 454 455 if (ppd_language == NULL || ppd_make_model == NULL || ppd_name == NULL) 456 { 457 if (attr == NULL) 458 break; 459 else 460 continue; 461 } 462 463 /* 464 * Display the device... 465 */ 466 467 if (long_status) 468 { 469 _cupsLangPrintf(stdout, 470 _("Model: name = %s\n" 471 " natural_language = %s\n" 472 " make-and-model = %s\n" 473 " device-id = %s"), 474 ppd_name, ppd_language, ppd_make_model, ppd_device_id); 475 } 476 else 477 _cupsLangPrintf(stdout, "%s %s", ppd_name, ppd_make_model); 478 479 if (attr == NULL) 480 break; 481 } 482 483 ippDelete(response); 484 } 485 else 486 { 487 _cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString()); 488 489 return (1); 490 } 491 492 return (0); 493} 494 495 496/* 497 * End of "$Id: lpinfo.c 11093 2013-07-03 20:48:42Z msweet $". 498 */ 499