1/* 2 * "$Id: lpc.c 11093 2013-07-03 20:48:42Z msweet $" 3 * 4 * "lpc" command for CUPS. 5 * 6 * Copyright 2007-2012 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 commands. 18 * compare_strings() - Compare two command-line strings. 19 * do_command() - Do an lpc command... 20 * show_help() - Show help messages. 21 * show_status() - Show printers. 22 */ 23 24/* 25 * Include necessary headers... 26 */ 27 28#include <cups/cups-private.h> 29 30 31/* 32 * Local functions... 33 */ 34 35static int compare_strings(const char *, const char *, int); 36static void do_command(http_t *, const char *, const char *); 37static void show_help(const char *); 38static void show_status(http_t *, const char *); 39 40 41/* 42 * 'main()' - Parse options and commands. 43 */ 44 45int 46main(int argc, /* I - Number of command-line arguments */ 47 char *argv[]) /* I - Command-line arguments */ 48{ 49 http_t *http; /* Connection to server */ 50 char line[1024], /* Input line from user */ 51 *params; /* Pointer to parameters */ 52 53 54 _cupsSetLocale(argv); 55 56 /* 57 * Connect to the scheduler... 58 */ 59 60 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); 61 62 if (argc > 1) 63 { 64 /* 65 * Process a single command on the command-line... 66 */ 67 68 do_command(http, argv[1], argv[2]); 69 } 70 else 71 { 72 /* 73 * Do the command prompt thing... 74 */ 75 76 _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no-newline version */ 77 while (fgets(line, sizeof(line), stdin) != NULL) 78 { 79 /* 80 * Strip trailing whitespace... 81 */ 82 83 for (params = line + strlen(line) - 1; params >= line;) 84 if (!isspace(*params & 255)) 85 break; 86 else 87 *params-- = '\0'; 88 89 /* 90 * Strip leading whitespace... 91 */ 92 93 for (params = line; isspace(*params & 255); params ++); 94 95 if (params > line) 96 _cups_strcpy(line, params); 97 98 if (!line[0]) 99 { 100 /* 101 * Nothing left, just show a prompt... 102 */ 103 104 _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */ 105 continue; 106 } 107 108 /* 109 * Find any options in the string... 110 */ 111 112 for (params = line; *params != '\0'; params ++) 113 if (isspace(*params & 255)) 114 break; 115 116 /* 117 * Remove whitespace between the command and parameters... 118 */ 119 120 while (isspace(*params & 255)) 121 *params++ = '\0'; 122 123 /* 124 * The "quit" and "exit" commands exit; otherwise, process as needed... 125 */ 126 127 if (!compare_strings(line, "quit", 1) || 128 !compare_strings(line, "exit", 2)) 129 break; 130 131 if (*params == '\0') 132 do_command(http, line, NULL); 133 else 134 do_command(http, line, params); 135 136 /* 137 * Put another prompt out to the user... 138 */ 139 140 _cupsLangPuts(stdout, _("lpc> ")); /* TODO: Need no newline version */ 141 } 142 } 143 144 /* 145 * Close the connection to the server and return... 146 */ 147 148 httpClose(http); 149 150 return (0); 151} 152 153 154/* 155 * 'compare_strings()' - Compare two command-line strings. 156 */ 157 158static int /* O - -1 or 1 = no match, 0 = match */ 159compare_strings(const char *s, /* I - Command-line string */ 160 const char *t, /* I - Option string */ 161 int tmin) /* I - Minimum number of unique chars in option */ 162{ 163 int slen; /* Length of command-line string */ 164 165 166 slen = strlen(s); 167 if (slen < tmin) 168 return (-1); 169 else 170 return (strncmp(s, t, slen)); 171} 172 173 174/* 175 * 'do_command()' - Do an lpc command... 176 */ 177 178static void 179do_command(http_t *http, /* I - HTTP connection to server */ 180 const char *command, /* I - Command string */ 181 const char *params) /* I - Parameters for command */ 182{ 183 if (!compare_strings(command, "status", 4)) 184 show_status(http, params); 185 else if (!compare_strings(command, "help", 1) || !strcmp(command, "?")) 186 show_help(params); 187 else 188 _cupsLangPrintf(stdout, 189 _("%s is not implemented by the CUPS version of lpc."), 190 command); 191} 192 193 194/* 195 * 'show_help()' - Show help messages. 196 */ 197 198static void 199show_help(const char *command) /* I - Command to describe or NULL */ 200{ 201 if (!command) 202 { 203 _cupsLangPrintf(stdout, 204 _("Commands may be abbreviated. Commands are:\n" 205 "\n" 206 "exit help quit status ?")); 207 } 208 else if (!compare_strings(command, "help", 1) || !strcmp(command, "?")) 209 _cupsLangPrintf(stdout, _("help\t\tGet help on commands.")); 210 else if (!compare_strings(command, "status", 4)) 211 _cupsLangPrintf(stdout, _("status\t\tShow status of daemon and queue.")); 212 else 213 _cupsLangPrintf(stdout, _("?Invalid help command unknown.")); 214} 215 216 217/* 218 * 'show_status()' - Show printers. 219 */ 220 221static void 222show_status(http_t *http, /* I - HTTP connection to server */ 223 const char *dests) /* I - Destinations */ 224{ 225 ipp_t *request, /* IPP Request */ 226 *response; /* IPP Response */ 227 ipp_attribute_t *attr; /* Current attribute */ 228 char *printer, /* Printer name */ 229 *device, /* Device URI */ 230 *delimiter; /* Char search result */ 231 ipp_pstate_t pstate; /* Printer state */ 232 int accepting; /* Is printer accepting jobs? */ 233 int jobcount; /* Count of current jobs */ 234 const char *dptr, /* Pointer into destination list */ 235 *ptr; /* Pointer into printer name */ 236 int match; /* Non-zero if this job matches */ 237 static const char *requested[] = /* Requested attributes */ 238 { 239 "device-uri", 240 "printer-is-accepting-jobs", 241 "printer-name", 242 "printer-state", 243 "queued-job-count" 244 }; 245 246 247 DEBUG_printf(("show_status(http=%p, dests=\"%s\")\n", http, dests)); 248 249 if (http == NULL) 250 return; 251 252 /* 253 * Build a CUPS_GET_PRINTERS request, which requires the following 254 * attributes: 255 * 256 * attributes-charset 257 * attributes-natural-language 258 */ 259 260 request = ippNewRequest(CUPS_GET_PRINTERS); 261 262 ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, 263 "requested-attributes", sizeof(requested) / sizeof(requested[0]), 264 NULL, requested); 265 266 /* 267 * Do the request and get back a response... 268 */ 269 270 if ((response = cupsDoRequest(http, request, "/")) != NULL) 271 { 272 DEBUG_puts("show_status: request succeeded..."); 273 274 /* 275 * Loop through the printers returned in the list and display 276 * their status... 277 */ 278 279 for (attr = response->attrs; attr != NULL; attr = attr->next) 280 { 281 /* 282 * Skip leading attributes until we hit a job... 283 */ 284 285 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) 286 attr = attr->next; 287 288 if (attr == NULL) 289 break; 290 291 /* 292 * Pull the needed attributes from this job... 293 */ 294 295 printer = NULL; 296 device = "file:/dev/null"; 297 pstate = IPP_PRINTER_IDLE; 298 jobcount = 0; 299 accepting = 1; 300 301 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) 302 { 303 if (!strcmp(attr->name, "device-uri") && 304 attr->value_tag == IPP_TAG_URI) 305 device = attr->values[0].string.text; 306 else if (!strcmp(attr->name, "printer-is-accepting-jobs") && 307 attr->value_tag == IPP_TAG_BOOLEAN) 308 accepting = attr->values[0].boolean; 309 else if (!strcmp(attr->name, "printer-name") && 310 attr->value_tag == IPP_TAG_NAME) 311 printer = attr->values[0].string.text; 312 else if (!strcmp(attr->name, "printer-state") && 313 attr->value_tag == IPP_TAG_ENUM) 314 pstate = (ipp_pstate_t)attr->values[0].integer; 315 else if (!strcmp(attr->name, "queued-job-count") && 316 attr->value_tag == IPP_TAG_INTEGER) 317 jobcount = attr->values[0].integer; 318 319 attr = attr->next; 320 } 321 322 /* 323 * See if we have everything needed... 324 */ 325 326 if (printer == NULL) 327 { 328 if (attr == NULL) 329 break; 330 else 331 continue; 332 } 333 334 /* 335 * A single 'all' printer name is special, meaning all printers. 336 */ 337 338 if (dests != NULL && !strcmp(dests, "all")) 339 dests = NULL; 340 341 /* 342 * See if this is a printer we're interested in... 343 */ 344 345 match = dests == NULL; 346 347 if (dests != NULL) 348 { 349 for (dptr = dests; *dptr != '\0';) 350 { 351 /* 352 * Skip leading whitespace and commas... 353 */ 354 355 while (isspace(*dptr & 255) || *dptr == ',') 356 dptr ++; 357 358 if (*dptr == '\0') 359 break; 360 361 /* 362 * Compare names... 363 */ 364 365 for (ptr = printer; 366 *ptr != '\0' && *dptr != '\0' && *ptr == *dptr; 367 ptr ++, dptr ++) 368 /* do nothing */; 369 370 if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' || 371 isspace(*dptr & 255))) 372 { 373 match = 1; 374 break; 375 } 376 377 /* 378 * Skip trailing junk... 379 */ 380 381 while (!isspace(*dptr & 255) && *dptr != '\0') 382 dptr ++; 383 while (isspace(*dptr & 255) || *dptr == ',') 384 dptr ++; 385 386 if (*dptr == '\0') 387 break; 388 } 389 } 390 391 /* 392 * Display the printer entry if needed... 393 */ 394 395 if (match) 396 { 397 /* 398 * Display it... 399 */ 400 401 printf("%s:\n", printer); 402 if (!strncmp(device, "file:", 5)) 403 _cupsLangPrintf(stdout, 404 _("\tprinter is on device \'%s\' speed -1"), 405 device + 5); 406 else 407 { 408 /* 409 * Just show the scheme... 410 */ 411 412 if ((delimiter = strchr(device, ':')) != NULL ) 413 { 414 *delimiter = '\0'; 415 _cupsLangPrintf(stdout, 416 _("\tprinter is on device \'%s\' speed -1"), 417 device); 418 } 419 } 420 421 if (accepting) 422 _cupsLangPuts(stdout, _("\tqueuing is enabled")); 423 else 424 _cupsLangPuts(stdout, _("\tqueuing is disabled")); 425 426 if (pstate != IPP_PRINTER_STOPPED) 427 _cupsLangPuts(stdout, _("\tprinting is enabled")); 428 else 429 _cupsLangPuts(stdout, _("\tprinting is disabled")); 430 431 if (jobcount == 0) 432 _cupsLangPuts(stdout, _("\tno entries")); 433 else 434 _cupsLangPrintf(stdout, _("\t%d entries"), jobcount); 435 436 _cupsLangPuts(stdout, _("\tdaemon present")); 437 } 438 439 if (attr == NULL) 440 break; 441 } 442 443 ippDelete(response); 444 } 445} 446 447 448/* 449 * End of "$Id: lpc.c 11093 2013-07-03 20:48:42Z msweet $". 450 */ 451