You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

516 lines
13 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

/*
* "lpinfo" command for CUPS.
*
* Copyright © 2007-2018 by Apple Inc.
* Copyright © 1997-2006 by Easy Software Products.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more
* information.
*/
/*
* Include necessary headers...
*/
#include <cups/cups-private.h>
#include <cups/adminutil.h>
/*
* Local functions...
*/
static void device_cb(const char *device_class, const char *device_id,
const char *device_info,
const char *device_make_and_model,
const char *device_uri, const char *device_location,
void *user_data);
static int show_devices(int long_status, int timeout,
const char *include_schemes,
const char *exclude_schemes);
static int show_models(int long_status,
const char *device_id, const char *language,
const char *make_model, const char *product,
const char *include_schemes,
const char *exclude_schemes);
static void usage(void) _CUPS_NORETURN;
/*
* 'main()' - Parse options and show status information.
*/
int
main(int argc, /* I - Number of command-line arguments */
char *argv[]) /* I - Command-line arguments */
{
int i; /* Looping var */
int long_status; /* Long listing? */
const char *opt, /* Option pointer */
*device_id, /* 1284 device ID */
*language, /* Language */
*make_model, /* Make and model */
*product, /* Product */
*include_schemes, /* Schemes to include */
*exclude_schemes; /* Schemes to exclude */
int timeout; /* Device timeout */
_cupsSetLocale(argv);
long_status = 0;
device_id = NULL;
language = NULL;
make_model = NULL;
product = NULL;
include_schemes = CUPS_INCLUDE_ALL;
exclude_schemes = CUPS_EXCLUDE_NONE;
timeout = CUPS_TIMEOUT_DEFAULT;
for (i = 1; i < argc; i ++)
{
if (!strcmp(argv[i], "--device-id"))
{
i ++;
if (i < argc)
device_id = argv[i];
else
{
_cupsLangPuts(stderr, _("lpinfo: Expected 1284 device ID string after \"--device-id\"."));
usage();
}
}
else if (!strncmp(argv[i], "--device-id=", 12) && argv[i][12])
{
device_id = argv[i] + 12;
}
else if (!strcmp(argv[i], "--exclude-schemes"))
{
i ++;
if (i < argc)
exclude_schemes = argv[i];
else
{
_cupsLangPuts(stderr, _("lpinfo: Expected scheme list after \"--exclude-schemes\"."));
usage();
}
}
else if (!strncmp(argv[i], "--exclude-schemes=", 18) && argv[i][18])
{
exclude_schemes = argv[i] + 18;
}
else if (!strcmp(argv[i], "--help"))
usage();
else if (!strcmp(argv[i], "--include-schemes"))
{
i ++;
if (i < argc)
include_schemes = argv[i];
else
{
_cupsLangPuts(stderr, _("lpinfo: Expected scheme list after \"--include-schemes\"."));
usage();
}
}
else if (!strncmp(argv[i], "--include-schemes=", 18) && argv[i][18])
{
include_schemes = argv[i] + 18;
}
else if (!strcmp(argv[i], "--language"))
{
i ++;
if (i < argc)
language = argv[i];
else
{
_cupsLangPuts(stderr, _("lpinfo: Expected language after \"--language\"."));
usage();
}
}
else if (!strncmp(argv[i], "--language=", 11) && argv[i][11])
{
language = argv[i] + 11;
}
else if (!strcmp(argv[i], "--make-and-model"))
{
i ++;
if (i < argc)
make_model= argv[i];
else
{
_cupsLangPuts(stderr, _("lpinfo: Expected make and model after \"--make-and-model\"."));
usage();
}
}
else if (!strncmp(argv[i], "--make-and-model=", 17) && argv[i][17])
{
make_model = argv[i] + 17;
}
else if (!strcmp(argv[i], "--product"))
{
i ++;
if (i < argc)
product = argv[i];
else
{
_cupsLangPuts(stderr, _("lpinfo: Expected product string after \"--product\"."));
usage();
}
}
else if (!strncmp(argv[i], "--product=", 10) && argv[i][10])
{
product = argv[i] + 10;
}
else if (!strcmp(argv[i], "--timeout"))
{
i ++;
if (i < argc)
timeout = atoi(argv[i]);
else
{
_cupsLangPuts(stderr, _("lpinfo: Expected timeout after \"--timeout\"."));
usage();
}
}
else if (!strncmp(argv[i], "--timeout=", 10) && argv[i][10])
{
timeout = atoi(argv[i] + 10);
}
else if (argv[i][0] == '-')
{
for (opt = argv[i] + 1; *opt; opt ++)
{
switch (*opt)
{
case 'E' : /* Encrypt */
#ifdef HAVE_SSL
cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
#else
_cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]);
#endif /* HAVE_SSL */
break;
case 'h' : /* Connect to host */
if (opt[1] != '\0')
{
cupsSetServer(opt + 1);
opt += strlen(opt) - 1;
}
else
{
i ++;
if (i >= argc)
{
_cupsLangPuts(stderr, _("Error: need hostname after \"-h\" option."));
usage();
}
cupsSetServer(argv[i]);
}
break;
case 'l' : /* Show long listing */
long_status = 1;
break;
case 'm' : /* Show models */
if (show_models(long_status, device_id, language, make_model, product, include_schemes, exclude_schemes))
return (1);
break;
case 'v' : /* Show available devices */
if (show_devices(long_status, timeout, include_schemes, exclude_schemes))
return (1);
break;
default :
_cupsLangPrintf(stderr, _("%s: Unknown option \"%c\"."), argv[0], *opt);
usage();
}
}
}
else
{
_cupsLangPrintf(stderr, _("%s: Unknown argument \"%s\"."), argv[0], argv[i]);
usage();
}
}
return (0);
}
/*
* 'device_cb()' - Device callback.
*/
static void
device_cb(
const char *device_class, /* I - device-class string */
const char *device_id, /* I - device-id string */
const char *device_info, /* I - device-info string */
const char *device_make_and_model, /* I - device-make-and-model string */
const char *device_uri, /* I - device-uri string */
const char *device_location, /* I - device-location string */
void *user_data) /* I - User data */
{
int *long_status; /* Show verbose info? */
/*
* Display the device...
*/
long_status = (int *)user_data;
if (*long_status)
{
_cupsLangPrintf(stdout,
_("Device: uri = %s\n"
" class = %s\n"
" info = %s\n"
" make-and-model = %s\n"
" device-id = %s\n"
" location = %s"),
device_uri, device_class, device_info,
device_make_and_model, device_id, device_location);
}
else
_cupsLangPrintf(stdout, "%s %s", device_class, device_uri);
}
/*
* 'show_devices()' - Show available devices.
*/
static int /* O - 0 on success, 1 on failure */
show_devices(
int long_status, /* I - Long status report? */
int timeout, /* I - Timeout */
const char *include_schemes, /* I - List of schemes to include */
const char *exclude_schemes) /* I - List of schemes to exclude */
{
if (cupsGetDevices(CUPS_HTTP_DEFAULT, timeout, include_schemes,
exclude_schemes, device_cb, &long_status) != IPP_OK)
{
_cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString());
return (1);
}
return (0);
}
/*
* 'show_models()' - Show available PPDs.
*/
static int /* O - 0 on success, 1 on failure */
show_models(
int long_status, /* I - Long status report? */
const char *device_id, /* I - 1284 device ID */
const char *language, /* I - Language */
const char *make_model, /* I - Make and model */
const char *product, /* I - Product */
const char *include_schemes, /* I - List of schemes to include */
const char *exclude_schemes) /* I - List of schemes to exclude */
{
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
const char *ppd_device_id, /* Pointer to ppd-device-id */
*ppd_language, /* Pointer to ppd-natural-language */
*ppd_make_model, /* Pointer to ppd-make-and-model */
*ppd_name; /* Pointer to ppd-name */
cups_option_t option; /* in/exclude-schemes option */
/*
* Build a CUPS_GET_PPDS request...
*/
request = ippNewRequest(CUPS_GET_PPDS);
if (device_id)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-device-id",
NULL, device_id);
if (language)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "ppd-language",
NULL, language);
if (make_model)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-make-and-model",
NULL, make_model);
if (product)
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT, "ppd-product",
NULL, product);
if (include_schemes)
{
option.name = "include-schemes";
option.value = (char *)include_schemes;
cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION);
}
if (exclude_schemes)
{
option.name = "exclude-schemes";
option.value = (char *)exclude_schemes;
cupsEncodeOptions2(request, 1, &option, IPP_TAG_OPERATION);
}
/*
* Do the request and get back a response...
*/
if ((response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/")) != NULL)
{
/*
* Loop through the device list and display them...
*/
if (response->request.status.status_code > IPP_OK_CONFLICT)
{
_cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString());
ippDelete(response);
return (1);
}
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
/*
* Skip leading attributes until we hit a PPD...
*/
while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
attr = attr->next;
if (attr == NULL)
break;
/*
* Pull the needed attributes from this PPD...
*/
ppd_device_id = "NONE";
ppd_language = NULL;
ppd_make_model = NULL;
ppd_name = NULL;
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
{
if (!strcmp(attr->name, "ppd-device-id") &&
attr->value_tag == IPP_TAG_TEXT)
ppd_device_id = attr->values[0].string.text;
else if (!strcmp(attr->name, "ppd-natural-language") &&
attr->value_tag == IPP_TAG_LANGUAGE)
ppd_language = attr->values[0].string.text;
else if (!strcmp(attr->name, "ppd-make-and-model") &&
attr->value_tag == IPP_TAG_TEXT)
ppd_make_model = attr->values[0].string.text;
else if (!strcmp(attr->name, "ppd-name") &&
attr->value_tag == IPP_TAG_NAME)
ppd_name = attr->values[0].string.text;
attr = attr->next;
}
/*
* See if we have everything needed...
*/
if (ppd_language == NULL || ppd_make_model == NULL || ppd_name == NULL)
{
if (attr == NULL)
break;
else
continue;
}
/*
* Display the device...
*/
if (long_status)
{
_cupsLangPrintf(stdout,
_("Model: name = %s\n"
" natural_language = %s\n"
" make-and-model = %s\n"
" device-id = %s"),
ppd_name, ppd_language, ppd_make_model, ppd_device_id);
}
else
_cupsLangPrintf(stdout, "%s %s", ppd_name, ppd_make_model);
if (attr == NULL)
break;
}
ippDelete(response);
/*
* Show the "everywhere" model, which is handled by the lpadmin command...
*/
if ((!include_schemes || strstr(include_schemes, "everywhere")) && (!exclude_schemes || !strstr(exclude_schemes, "everywhere")))
{
if (long_status)
{
_cupsLangPrintf(stdout,
_("Model: name = %s\n"
" natural_language = %s\n"
" make-and-model = %s\n"
" device-id = %s"),
"everywhere", cupsLangDefault()->language, "IPP Everywhere™", "CMD:PwgRaster");
}
else
_cupsLangPuts(stdout, "everywhere IPP Everywhere");
}
}
else
{
_cupsLangPrintf(stderr, "lpinfo: %s", cupsLastErrorString());
return (1);
}
return (0);
}
/*
* 'usage()' - Show program usage and exit.
*/
static void
usage(void)
{
_cupsLangPuts(stdout, _("Usage: lpinfo [options] -m\n"
" lpinfo [options] -v"));
_cupsLangPuts(stdout, _("Options:"));
_cupsLangPuts(stdout, _("-E Encrypt the connection to the server"));
_cupsLangPuts(stdout, _("-h server[:port] Connect to the named server and port"));
_cupsLangPuts(stdout, _("-l Show verbose (long) output"));
_cupsLangPuts(stdout, _("-m Show models"));
_cupsLangPuts(stdout, _("-U username Specify the username to use for authentication"));
_cupsLangPuts(stdout, _("-v Show devices"));
_cupsLangPuts(stdout, _("--device-id device-id Show models matching the given IEEE 1284 device ID"));
_cupsLangPuts(stdout, _("--exclude-schemes scheme-list\n"
" Exclude the specified URI schemes"));
_cupsLangPuts(stdout, _("--include-schemes scheme-list\n"
" Include only the specified URI schemes"));
_cupsLangPuts(stdout, _("--language locale Show models matching the given locale"));
_cupsLangPuts(stdout, _("--make-and-model name Show models matching the given make and model name"));
_cupsLangPuts(stdout, _("--product name Show models matching the given PostScript product"));
_cupsLangPuts(stdout, _("--timeout seconds Specify the maximum number of seconds to discover devices"));
exit(1);
}