diff options
Diffstat (limited to 'systemv/lpoptions.c')
-rw-r--r-- | systemv/lpoptions.c | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/systemv/lpoptions.c b/systemv/lpoptions.c new file mode 100644 index 0000000..438fcf2 --- /dev/null +++ b/systemv/lpoptions.c @@ -0,0 +1,565 @@ +/* + * "$Id: lpoptions.c 9793 2011-05-20 03:49:49Z mike $" + * + * Printer option program for CUPS. + * + * Copyright 2007-2011 by Apple Inc. + * Copyright 1997-2006 by Easy Software Products. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * Contents: + * + * main() - Main entry. + * list_group() - List printer-specific options from the PPD group. + * list_options() - List printer-specific options from the PPD file. + * usage() - Show program usage and exit. + */ + +/* + * Include necessary headers... + */ + +#include <cups/cups-private.h> + + +/* + * Local functions... + */ + +static void list_group(ppd_file_t *ppd, ppd_group_t *group); +static void list_options(cups_dest_t *dest); +static void usage(void); + + +/* + * 'main()' - Main entry. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ +{ + int i, j; /* Looping vars */ + int changes; /* Did we make changes? */ + int num_options; /* Number of options */ + cups_option_t *options; /* Options */ + int num_dests; /* Number of destinations */ + cups_dest_t *dests; /* Destinations */ + cups_dest_t *dest; /* Current destination */ + char *printer, /* Printer name */ + *instance, /* Instance name */ + *option; /* Current option */ + + + _cupsSetLocale(argv); + + /* + * Loop through the command-line arguments... + */ + + dest = NULL; + num_dests = 0; + dests = NULL; + num_options = 0; + options = NULL; + changes = 0; + + for (i = 1; i < argc; i ++) + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'd' : /* -d printer */ + if (argv[i][2]) + printer = argv[i] + 2; + else + { + i ++; + if (i >= argc) + usage(); + + printer = argv[i]; + } + + if ((instance = strrchr(printer, '/')) != NULL) + *instance++ = '\0'; + + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if (num_dests == 0 || !dests || + (dest = cupsGetDest(printer, instance, num_dests, + dests)) == NULL) + { + _cupsLangPuts(stderr, _("lpoptions: Unknown printer or class.")); + return (1); + } + + /* + * Set the default destination... + */ + + for (j = 0; j < num_dests; j ++) + dests[j].is_default = 0; + + dest->is_default = 1; + + cupsSetDests(num_dests, dests); + + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, + options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + break; + + case 'h' : /* -h server */ + if (argv[i][2]) + cupsSetServer(argv[i] + 2); + else + { + i ++; + if (i >= argc) + usage(); + + cupsSetServer(argv[i]); + } + break; + + case 'E' : /* Encrypt connection */ + cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); + break; + + case 'l' : /* -l (list options) */ + if (dest == NULL) + { + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) + dest = dests; + } + + if (dest == NULL) + _cupsLangPuts(stderr, _("lpoptions: No printers.")); + else + list_options(dest); + + changes = -1; + break; + + case 'o' : /* -o option[=value] */ + if (dest == NULL) + { + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) + dest = dests; + + if (dest == NULL) + { + _cupsLangPuts(stderr, _("lpoptions: No printers.")); + return (1); + } + + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + } + + if (argv[i][2]) + num_options = cupsParseOptions(argv[i] + 2, num_options, &options); + else + { + i ++; + if (i >= argc) + usage(); + + num_options = cupsParseOptions(argv[i], num_options, &options); + } + + changes = 1; + break; + + case 'p' : /* -p printer */ + if (argv[i][2]) + printer = argv[i] + 2; + else + { + i ++; + if (i >= argc) + usage(); + + printer = argv[i]; + } + + if ((instance = strrchr(printer, '/')) != NULL) + *instance++ = '\0'; + + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if ((dest = cupsGetDest(printer, instance, num_dests, dests)) == NULL) + { + num_dests = cupsAddDest(printer, instance, num_dests, &dests); + dest = cupsGetDest(printer, instance, num_dests, dests); + + if (dest == NULL) + { + _cupsLangPrintf(stderr, + _("lpoptions: Unable to add printer or " + "instance: %s"), + strerror(errno)); + return (1); + } + } + + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + break; + + case 'r' : /* -r option (remove) */ + if (dest == NULL) + { + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL) + dest = dests; + + if (dest == NULL) + { + _cupsLangPuts(stderr, _("lpoptions: No printers.")); + return (1); + } + + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, + options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + } + + if (argv[i][2]) + option = argv[i] + 2; + else + { + i ++; + if (i >= argc) + usage(); + + option = argv[i]; + } + + for (j = 0; j < num_options; j ++) + if (!_cups_strcasecmp(options[j].name, option)) + { + /* + * Remove this option... + */ + + num_options --; + + if (j < num_options) + memcpy(options + j, options + j + 1, + sizeof(cups_option_t) * (num_options - j)); + break; + } + + changes = 1; + break; + + case 'x' : /* -x printer */ + if (argv[i][2]) + printer = argv[i] + 2; + else + { + i ++; + if (i >= argc) + usage(); + + printer = argv[i]; + } + + if ((instance = strrchr(printer, '/')) != NULL) + *instance++ = '\0'; + + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if ((dest = cupsGetDest(printer, instance, num_dests, + dests)) != NULL) + { + cupsFreeOptions(dest->num_options, dest->options); + + /* + * If we are "deleting" the default printer, then just set the + * number of options to 0; if it is also the system default + * then cupsSetDests() will remove it for us... + */ + + if (dest->is_default) + { + dest->num_options = 0; + dest->options = NULL; + } + else + { + num_dests --; + + j = dest - dests; + if (j < num_dests) + memcpy(dest, dest + 1, (num_dests - j) * sizeof(cups_dest_t)); + } + } + + cupsSetDests(num_dests, dests); + dest = NULL; + changes = -1; + break; + + default : + usage(); + } + } + else + usage(); + + if (num_dests == 0) + num_dests = cupsGetDests(&dests); + + if (dest == NULL) + { + if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL) + { + for (j = 0; j < dest->num_options; j ++) + if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) + num_options = cupsAddOption(dest->options[j].name, + dest->options[j].value, + num_options, &options); + } + } + + if (dest == NULL) + return (0); + + if (changes > 0) + { + /* + * Set printer options... + */ + + cupsFreeOptions(dest->num_options, dest->options); + + dest->num_options = num_options; + dest->options = options; + + cupsSetDests(num_dests, dests); + } + else if (changes == 0) + { + char buffer[10240], /* String for options */ + *ptr; /* Pointer into string */ + + num_options = dest->num_options; + options = dest->options; + + for (i = 0, ptr = buffer; + ptr < (buffer + sizeof(buffer) - 1) && i < num_options; + i ++) + { + if (i) + *ptr++ = ' '; + + if (!options[i].value[0]) + strlcpy(ptr, options[i].name, sizeof(buffer) - (ptr - buffer)); + else if (strchr(options[i].value, ' ') != NULL || + strchr(options[i].value, '\t') != NULL) + snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s=\'%s\'", + options[i].name, options[i].value); + else + snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s=%s", + options[i].name, options[i].value); + + ptr += strlen(ptr); + } + + _cupsLangPuts(stdout, buffer); + } + + return (0); +} + +/* + * 'list_group()' - List printer-specific options from the PPD group. + */ + +static void +list_group(ppd_file_t *ppd, /* I - PPD file */ + ppd_group_t *group) /* I - Group to show */ +{ + int i, j; /* Looping vars */ + ppd_option_t *option; /* Current option */ + ppd_choice_t *choice; /* Current choice */ + ppd_group_t *subgroup; /* Current subgroup */ + char buffer[10240], /* Option string buffer */ + *ptr; /* Pointer into option string */ + + + for (i = group->num_options, option = group->options; i > 0; i --, option ++) + { + if (!_cups_strcasecmp(option->keyword, "PageRegion")) + continue; + + snprintf(buffer, sizeof(buffer), "%s/%s:", option->keyword, option->text); + + for (j = option->num_choices, choice = option->choices, + ptr = buffer + strlen(buffer); + j > 0 && ptr < (buffer + sizeof(buffer) - 1); + j --, choice ++) + { + if (!_cups_strcasecmp(choice->choice, "Custom")) + { + ppd_coption_t *coption; /* Custom option */ + ppd_cparam_t *cparam; /* Custom parameter */ + static const char * const types[] = + { /* Parameter types */ + "CURVE", + "INTEGER", + "INVCURVE", + "PASSCODE", + "PASSWORD", + "POINTS", + "REAL", + "STRING" + }; + + + if ((coption = ppdFindCustomOption(ppd, option->keyword)) == NULL || + cupsArrayCount(coption->params) == 0) + snprintf(ptr, sizeof(buffer) - (ptr - buffer), " %sCustom", + choice->marked ? "*" : ""); + else if (!_cups_strcasecmp(option->keyword, "PageSize") || + !_cups_strcasecmp(option->keyword, "PageRegion")) + snprintf(ptr, sizeof(buffer) - (ptr - buffer), + " %sCustom.WIDTHxHEIGHT", choice->marked ? "*" : ""); + else + { + cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params); + + if (cupsArrayCount(coption->params) == 1) + snprintf(ptr, sizeof(buffer) - (ptr - buffer), " %sCustom.%s", + choice->marked ? "*" : "", types[cparam->type]); + else + { + const char *prefix; /* Prefix string */ + + + if (choice->marked) + prefix = " *{"; + else + prefix = " {"; + + while (cparam) + { + snprintf(ptr, sizeof(buffer) - (ptr - buffer), "%s%s=%s", prefix, + cparam->name, types[cparam->type]); + cparam = (ppd_cparam_t *)cupsArrayNext(coption->params); + prefix = " "; + ptr += strlen(ptr); + } + + if (ptr < (buffer + sizeof(buffer) - 1)) + strlcpy(ptr, "}", sizeof(buffer) - (ptr - buffer)); + } + } + } + else if (choice->marked) + snprintf(ptr, sizeof(buffer) - (ptr - buffer), " *%s", choice->choice); + else + snprintf(ptr, sizeof(buffer) - (ptr - buffer), " %s", choice->choice); + + ptr += strlen(ptr); + } + + _cupsLangPuts(stdout, buffer); + } + + for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++) + list_group(ppd, subgroup); +} + + +/* + * 'list_options()' - List printer-specific options from the PPD file. + */ + +static void +list_options(cups_dest_t *dest) /* I - Destination to list */ +{ + int i; /* Looping var */ + const char *filename; /* PPD filename */ + ppd_file_t *ppd; /* PPD data */ + ppd_group_t *group; /* Current group */ + + + if ((filename = cupsGetPPD(dest->name)) == NULL) + { + _cupsLangPrintf(stderr, _("lpoptions: Unable to get PPD file for %s: %s"), + dest->name, cupsLastErrorString()); + return; + } + + if ((ppd = ppdOpenFile(filename)) == NULL) + { + unlink(filename); + _cupsLangPrintf(stderr, _("lpoptions: Unable to open PPD file for %s."), + dest->name); + return; + } + + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, dest->num_options, dest->options); + + for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) + list_group(ppd, group); + + ppdClose(ppd); + unlink(filename); +} + + +/* + * 'usage()' - Show program usage and exit. + */ + +static void +usage(void) +{ + _cupsLangPuts(stdout, + _("Usage: lpoptions [-h server] [-E] -d printer\n" + " lpoptions [-h server] [-E] [-p printer] -l\n" + " lpoptions [-h server] [-E] -p printer -o " + "option[=value] ...\n" + " lpoptions [-h server] [-E] -x printer")); + + exit(1); +} + + +/* + * End of "$Id: lpoptions.c 9793 2011-05-20 03:49:49Z mike $". + */ |