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.

2068 lines
54 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.

/*
* "lpstat" 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>
/*
* Local functions...
*/
static void check_dest(const char *command, const char *name,
int *num_dests, cups_dest_t **dests);
static int match_list(const char *list, const char *name);
static int show_accepting(const char *printers, int num_dests,
cups_dest_t *dests);
static int show_classes(const char *dests);
static void show_default(cups_dest_t *dest);
static int show_devices(const char *printers, int num_dests,
cups_dest_t *dests);
static int show_jobs(const char *dests, const char *users, int long_status,
int ranking, const char *which);
static int show_printers(const char *printers, int num_dests,
cups_dest_t *dests, int long_status);
static void show_scheduler(void);
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 */
status; /* Exit status */
char *opt; /* Option pointer */
int num_dests; /* Number of user destinations */
cups_dest_t *dests; /* User destinations */
int long_status; /* Long status report? */
int ranking; /* Show job ranking? */
const char *which; /* Which jobs to show? */
char op; /* Last operation on command-line */
_cupsSetLocale(argv);
/*
* Parse command-line options...
*/
num_dests = 0;
dests = NULL;
long_status = 0;
ranking = 0;
status = 0;
which = "not-completed";
op = 0;
for (i = 1; i < argc; i ++)
{
if (!strcmp(argv[i], "--help"))
usage();
else if (argv[i][0] == '-')
{
for (opt = argv[i] + 1; *opt; opt ++)
{
switch (*opt)
{
case 'D' : /* Show description */
long_status = 1;
break;
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' : /* Show server and port */
if (cupsServer()[0] == '/')
_cupsLangPuts(stdout, cupsServer());
else
_cupsLangPrintf(stdout, "%s:%d", cupsServer(), ippPort());
op = 'H';
break;
case 'P' : /* Show paper types */
op = 'P';
break;
case 'R' : /* Show ranking */
ranking = 1;
break;
case 'S' : /* Show charsets */
op = 'S';
if (!argv[i][2])
i ++;
break;
case 'U' : /* Username */
if (opt[1] != '\0')
{
cupsSetUser(opt + 1);
opt += strlen(opt) - 1;
}
else
{
i ++;
if (i >= argc)
{
_cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), argv[0]);
usage();
}
cupsSetUser(argv[i]);
}
break;
case 'W' : /* Show which jobs? */
if (opt[1] != '\0')
{
which = opt + 1;
opt += strlen(opt) - 1;
}
else
{
i ++;
if (i >= argc)
{
_cupsLangPrintf(stderr, _("%s: Error - need \"completed\", \"not-completed\", or \"all\" after \"-W\" option."), argv[0]);
usage();
}
which = argv[i];
}
if (strcmp(which, "completed") && strcmp(which, "not-completed") && strcmp(which, "all"))
{
_cupsLangPrintf(stderr, _("%s: Error - need \"completed\", \"not-completed\", or \"all\" after \"-W\" option."), argv[0]);
usage();
}
break;
case 'a' : /* Show acceptance status */
op = 'a';
if (opt[1] != '\0')
{
check_dest(argv[0], opt + 1, &num_dests, &dests);
status |= show_accepting(opt + 1, num_dests, dests);
opt += strlen(opt) - 1;
}
else if ((i + 1) < argc && argv[i + 1][0] != '-')
{
i ++;
check_dest(argv[0], argv[i], &num_dests, &dests);
status |= show_accepting(argv[i], num_dests, dests);
}
else
{
if (num_dests <= 1)
{
cupsFreeDests(num_dests, dests);
num_dests = cupsGetDests(&dests);
if (num_dests == 0 && (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED))
{
_cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
return (1);
}
}
status |= show_accepting(NULL, num_dests, dests);
}
break;
case 'c' : /* Show classes and members */
op = 'c';
if (opt[1] != '\0')
{
check_dest(argv[0], opt + 1, &num_dests, &dests);
status |= show_classes(opt + 1);
opt += strlen(opt) - 1;
}
else if ((i + 1) < argc && argv[i + 1][0] != '-')
{
i ++;
check_dest(argv[0], argv[i], &num_dests, &dests);
status |= show_classes(argv[i]);
}
else
status |= show_classes(NULL);
break;
case 'd' : /* Show default destination */
op = 'd';
if (num_dests != 1 || !dests[0].is_default)
{
cupsFreeDests(num_dests, dests);
dests = cupsGetNamedDest(CUPS_HTTP_DEFAULT, NULL, NULL);
num_dests = dests ? 1 : 0;
if (num_dests == 0 &&
(cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED))
{
_cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
return (1);
}
}
show_default(dests);
break;
case 'e' : /* List destinations */
{
cups_dest_t *temp = NULL, *dest;
int j, num_temp = cupsGetDests(&temp);
op = 'e';
for (j = num_temp, dest = temp; j > 0; j --, dest ++)
{
if (dest->instance)
printf("%s/%s", dest->name, dest->instance);
else
fputs(dest->name, stdout);
if (long_status)
{
const char *printer_uri_supported = cupsGetOption("printer-uri-supported", dest->num_options, dest->options);
const char *printer_is_temporary = cupsGetOption("printer-is-temporary", dest->num_options, dest->options);
const char *type = "network";
if (printer_is_temporary && !strcmp(printer_is_temporary, "true"))
type = "temporary";
else if (printer_uri_supported)
type = "permanent";
printf(" %s %s %s\n", type, printer_uri_supported ? printer_uri_supported : "none", cupsGetOption("device-uri", dest->num_options, dest->options));
}
else
putchar('\n');
}
cupsFreeDests(num_temp, temp);
}
break;
case 'f' : /* Show forms */
op = 'f';
if (opt[1] != '\0')
{
opt += strlen(opt) - 1;
}
else
{
i ++;
if (i >= argc)
return (1);
}
break;
case 'h' : /* Connect to host */
if (opt[1] != '\0')
{
cupsSetServer(opt + 1);
opt += strlen(opt) - 1;
}
else
{
i ++;
if (i >= argc)
{
_cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-h\" option."), argv[0]);
return (1);
}
cupsSetServer(argv[i]);
}
break;
case 'l' : /* Long status or long job status */
long_status = 2;
break;
case 'o' : /* Show jobs by destination */
op = 'o';
if (opt[1])
{
check_dest(argv[0], opt + 1, &num_dests, &dests);
status |= show_jobs(opt + 1, NULL, long_status, ranking, which);
opt += strlen(opt) - 1;
}
else if ((i + 1) < argc && argv[i + 1][0] != '-')
{
i ++;
check_dest(argv[0], argv[i], &num_dests, &dests);
status |= show_jobs(argv[i], NULL, long_status, ranking, which);
}
else
status |= show_jobs(NULL, NULL, long_status, ranking, which);
break;
case 'p' : /* Show printers */
op = 'p';
if (opt[1] != '\0')
{
check_dest(argv[0], opt + 1, &num_dests, &dests);
status |= show_printers(opt + 1, num_dests, dests,
long_status);
opt += strlen(opt) - 1;
}
else if ((i + 1) < argc && argv[i + 1][0] != '-')
{
i ++;
check_dest(argv[0], argv[i], &num_dests, &dests);
status |= show_printers(argv[i], num_dests, dests, long_status);
}
else
{
if (num_dests <= 1)
{
cupsFreeDests(num_dests, dests);
num_dests = cupsGetDests(&dests);
if (num_dests == 0 &&
(cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED))
{
_cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
return (1);
}
}
status |= show_printers(NULL, num_dests, dests, long_status);
}
break;
case 'r' : /* Show scheduler status */
op = 'r';
show_scheduler();
break;
case 's' : /* Show summary */
op = 's';
if (num_dests <= 1)
{
cupsFreeDests(num_dests, dests);
num_dests = cupsGetDests(&dests);
if (num_dests == 0 &&
(cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED))
{
_cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
return (1);
}
}
show_default(cupsGetDest(NULL, NULL, num_dests, dests));
status |= show_classes(NULL);
status |= show_devices(NULL, num_dests, dests);
break;
case 't' : /* Show all info */
op = 't';
if (num_dests <= 1)
{
cupsFreeDests(num_dests, dests);
num_dests = cupsGetDests(&dests);
if (num_dests == 0 &&
(cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED))
{
_cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
return (1);
}
}
show_scheduler();
show_default(cupsGetDest(NULL, NULL, num_dests, dests));
status |= show_classes(NULL);
status |= show_devices(NULL, num_dests, dests);
status |= show_accepting(NULL, num_dests, dests);
status |= show_printers(NULL, num_dests, dests, long_status);
status |= show_jobs(NULL, NULL, long_status, ranking, which);
break;
case 'u' : /* Show jobs by user */
op = 'u';
if (opt[1] != '\0')
{
status |= show_jobs(NULL, opt + 1, long_status, ranking, which);
opt += strlen(opt) - 1;
}
else if ((i + 1) < argc && argv[i + 1][0] != '-')
{
i ++;
status |= show_jobs(NULL, argv[i], long_status, ranking, which);
}
else
status |= show_jobs(NULL, NULL, long_status, ranking, which);
break;
case 'v' : /* Show printer devices */
op = 'v';
if (opt[1] != '\0')
{
check_dest(argv[0], opt + 1, &num_dests, &dests);
status |= show_devices(opt + 1, num_dests, dests);
opt += strlen(opt) - 1;
}
else if ((i + 1) < argc && argv[i + 1][0] != '-')
{
i ++;
check_dest(argv[0], argv[i], &num_dests, &dests);
status |= show_devices(argv[i], num_dests, dests);
}
else
{
if (num_dests <= 1)
{
cupsFreeDests(num_dests, dests);
num_dests = cupsGetDests(&dests);
if (num_dests == 0 &&
(cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED))
{
_cupsLangPrintf(stderr, _("%s: Error - add '/version=1.1' to server name."), argv[0]);
return (1);
}
}
status |= show_devices(NULL, num_dests, dests);
}
break;
default :
_cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), argv[0], argv[i][1]);
usage();
}
}
}
else
{
status |= show_jobs(argv[i], NULL, long_status, ranking, which);
op = 'o';
}
}
if (!op)
status |= show_jobs(NULL, cupsUser(), long_status, ranking, which);
return (status);
}
/*
* 'check_dest()' - Verify that the named destination(s) exists.
*/
static void
check_dest(const char *command, /* I - Command name */
const char *name, /* I - List of printer/class names */
int *num_dests, /* IO - Number of destinations */
cups_dest_t **dests) /* IO - Destinations */
{
const char *dptr; /* Pointer into name */
char *pptr, /* Pointer into printer */
printer[1024]; /* Current printer/class name */
/*
* Load the destination list as necessary...
*/
if (*num_dests <= 1)
{
if (*num_dests)
cupsFreeDests(*num_dests, *dests);
if (strchr(name, ','))
*num_dests = cupsGetDests(dests);
else
{
strlcpy(printer, name, sizeof(printer));
if ((pptr = strchr(printer, '/')) != NULL)
*pptr++ = '\0';
if ((*dests = cupsGetNamedDest(CUPS_HTTP_DEFAULT, printer, pptr)) == NULL)
{
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
_cupsLangPrintf(stderr,
_("%s: Error - add '/version=1.1' to server name."),
command);
else
_cupsLangPrintf(stderr,
_("%s: Invalid destination name in list \"%s\"."),
command, name);
exit(1);
}
else
{
*num_dests = 1;
return;
}
}
}
/*
* Scan the name string for printer/class name(s)...
*/
for (dptr = name; *dptr;)
{
/*
* Skip leading whitespace and commas...
*/
while (isspace(*dptr & 255) || *dptr == ',')
dptr ++;
if (!*dptr)
break;
/*
* Extract a single destination name from the name string...
*/
for (pptr = printer; !isspace(*dptr & 255) && *dptr != ',' && *dptr;)
{
if ((size_t)(pptr - printer) < (sizeof(printer) - 1))
*pptr++ = *dptr++;
else
{
_cupsLangPrintf(stderr,
_("%s: Invalid destination name in list \"%s\"."),
command, name);
exit(1);
}
}
*pptr = '\0';
/*
* Check the destination...
*/
if (!cupsGetDest(printer, NULL, *num_dests, *dests))
{
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
_cupsLangPrintf(stderr,
_("%s: Error - add '/version=1.1' to server name."),
command);
else
_cupsLangPrintf(stderr,
_("%s: Unknown destination \"%s\"."), command, printer);
exit(1);
}
}
}
/*
* 'match_list()' - Match a name from a list of comma or space-separated names.
*/
static int /* O - 1 on match, 0 on no match */
match_list(const char *list, /* I - List of names */
const char *name) /* I - Name to find */
{
const char *nameptr; /* Pointer into name */
/*
* An empty list always matches...
*/
if (!list || !*list)
return (1);
if (!name)
return (0);
while (*list)
{
/*
* Skip leading whitespace and commas...
*/
while (isspace(*list & 255) || *list == ',')
list ++;
if (!*list)
break;
/*
* Compare names...
*/
for (nameptr = name;
*nameptr && *list && tolower(*nameptr & 255) == tolower(*list & 255);
nameptr ++, list ++);
if (!*nameptr && (!*list || *list == ',' || isspace(*list & 255)))
return (1);
while (*list && !isspace(*list & 255) && *list != ',')
list ++;
}
return (0);
}
/*
* 'show_accepting()' - Show acceptance status.
*/
static int /* O - 0 on success, 1 on fail */
show_accepting(const char *printers, /* I - Destinations */
int num_dests, /* I - Number of user-defined dests */
cups_dest_t *dests) /* I - User-defined destinations */
{
int i; /* Looping var */
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
const char *printer, /* Printer name */
*message; /* Printer device URI */
int accepting; /* Accepting requests? */
time_t ptime; /* Printer state time */
char printer_state_time[255];/* Printer state time */
static const char *pattrs[] = /* Attributes we need for printers... */
{
"printer-name",
"printer-state-change-time",
"printer-state-message",
"printer-is-accepting-jobs"
};
if (printers != NULL && !strcmp(printers, "all"))
printers = NULL;
/*
* Build a CUPS_GET_PRINTERS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* requested-attributes
* requesting-user-name
*/
request = ippNewRequest(CUPS_GET_PRINTERS);
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
NULL, pattrs);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
/*
* Do the request and get back a response...
*/
response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
{
_cupsLangPrintf(stderr,
_("%s: Error - add '/version=1.1' to server name."),
"lpstat");
ippDelete(response);
return (1);
}
else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
{
_cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString());
ippDelete(response);
return (1);
}
if (response)
{
/*
* Loop through the printers returned in the list and display
* their devices...
*/
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
/*
* Skip leading attributes until we hit a printer...
*/
while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
attr = attr->next;
if (attr == NULL)
break;
/*
* Pull the needed attributes from this printer...
*/
printer = NULL;
message = NULL;
accepting = 1;
ptime = 0;
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
{
if (!strcmp(attr->name, "printer-name") &&
attr->value_tag == IPP_TAG_NAME)
printer = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-state-change-time") &&
attr->value_tag == IPP_TAG_INTEGER)
ptime = (time_t)attr->values[0].integer;
else if (!strcmp(attr->name, "printer-state-message") &&
attr->value_tag == IPP_TAG_TEXT)
message = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-is-accepting-jobs") &&
attr->value_tag == IPP_TAG_BOOLEAN)
accepting = attr->values[0].boolean;
attr = attr->next;
}
/*
* See if we have everything needed...
*/
if (printer == NULL)
{
if (attr == NULL)
break;
else
continue;
}
/*
* Display the printer entry if needed...
*/
if (match_list(printers, printer))
{
_cupsStrDate(printer_state_time, sizeof(printer_state_time), ptime);
if (accepting)
_cupsLangPrintf(stdout, _("%s accepting requests since %s"),
printer, printer_state_time);
else
{
_cupsLangPrintf(stdout, _("%s not accepting requests since %s -"),
printer, printer_state_time);
_cupsLangPrintf(stdout, _("\t%s"),
(message == NULL || !*message) ?
"reason unknown" : message);
}
for (i = 0; i < num_dests; i ++)
if (!_cups_strcasecmp(dests[i].name, printer) && dests[i].instance)
{
if (accepting)
_cupsLangPrintf(stdout, _("%s/%s accepting requests since %s"),
printer, dests[i].instance, printer_state_time);
else
{
_cupsLangPrintf(stdout,
_("%s/%s not accepting requests since %s -"),
printer, dests[i].instance, printer_state_time);
_cupsLangPrintf(stdout, _("\t%s"),
(message == NULL || !*message) ?
"reason unknown" : message);
}
}
}
if (attr == NULL)
break;
}
ippDelete(response);
}
return (0);
}
/*
* 'show_classes()' - Show printer classes.
*/
static int /* O - 0 on success, 1 on fail */
show_classes(const char *dests) /* I - Destinations */
{
int i; /* Looping var */
ipp_t *request, /* IPP Request */
*response, /* IPP Response */
*response2; /* IPP response from remote server */
http_t *http2; /* Remote server */
ipp_attribute_t *attr; /* Current attribute */
const char *printer, /* Printer class name */
*printer_uri; /* Printer class URI */
ipp_attribute_t *members; /* Printer members */
char method[HTTP_MAX_URI], /* Request method */
username[HTTP_MAX_URI], /* Username:password */
server[HTTP_MAX_URI], /* Server name */
resource[HTTP_MAX_URI]; /* Resource name */
int port; /* Port number */
static const char *cattrs[] = /* Attributes we need for classes... */
{
"printer-name",
"printer-uri-supported",
"member-names"
};
if (dests != NULL && !strcmp(dests, "all"))
dests = NULL;
/*
* Build a CUPS_GET_CLASSES request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* requested-attributes
* requesting-user-name
*/
request = ippNewRequest(CUPS_GET_CLASSES);
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", sizeof(cattrs) / sizeof(cattrs[0]),
NULL, cattrs);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
/*
* Do the request and get back a response...
*/
response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
{
_cupsLangPrintf(stderr,
_("%s: Error - add '/version=1.1' to server name."),
"lpstat");
ippDelete(response);
return (1);
}
else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
{
_cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString());
ippDelete(response);
return (1);
}
if (response)
{
if (response->request.status.status_code > IPP_OK_CONFLICT)
{
_cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString());
ippDelete(response);
return (1);
}
/*
* Loop through the printers returned in the list and display
* their devices...
*/
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
/*
* Skip leading attributes until we hit a job...
*/
while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
attr = attr->next;
if (attr == NULL)
break;
/*
* Pull the needed attributes from this job...
*/
printer = NULL;
printer_uri = NULL;
members = NULL;
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
{
if (!strcmp(attr->name, "printer-name") &&
attr->value_tag == IPP_TAG_NAME)
printer = attr->values[0].string.text;
if (!strcmp(attr->name, "printer-uri-supported") &&
attr->value_tag == IPP_TAG_URI)
printer_uri = attr->values[0].string.text;
if (!strcmp(attr->name, "member-names") &&
attr->value_tag == IPP_TAG_NAME)
members = attr;
attr = attr->next;
}
/*
* If this is a remote class, grab the class info from the
* remote server...
*/
response2 = NULL;
if (members == NULL && printer_uri != NULL)
{
httpSeparateURI(HTTP_URI_CODING_ALL, printer_uri, method, sizeof(method),
username, sizeof(username), server, sizeof(server),
&port, resource, sizeof(resource));
if (!_cups_strcasecmp(server, cupsServer()))
http2 = CUPS_HTTP_DEFAULT;
else
http2 = httpConnectEncrypt(server, port, cupsEncryption());
/*
* Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
* following attributes:
*
* attributes-charset
* attributes-natural-language
* printer-uri
* requested-attributes
*/
request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, printer_uri);
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes",
sizeof(cattrs) / sizeof(cattrs[0]),
NULL, cattrs);
if ((response2 = cupsDoRequest(http2, request, "/")) != NULL)
members = ippFindAttribute(response2, "member-names", IPP_TAG_NAME);
if (http2)
httpClose(http2);
}
/*
* See if we have everything needed...
*/
if (printer == NULL)
{
if (response2)
ippDelete(response2);
if (attr == NULL)
break;
else
continue;
}
/*
* Display the printer entry if needed...
*/
if (match_list(dests, printer))
{
_cupsLangPrintf(stdout, _("members of class %s:"), printer);
if (members)
{
for (i = 0; i < members->num_values; i ++)
_cupsLangPrintf(stdout, "\t%s", members->values[i].string.text);
}
else
_cupsLangPuts(stdout, "\tunknown");
}
if (response2)
ippDelete(response2);
if (attr == NULL)
break;
}
ippDelete(response);
}
return (0);
}
/*
* 'show_default()' - Show default destination.
*/
static void
show_default(cups_dest_t *dest) /* I - Default destination */
{
const char *printer, /* Printer name */
*val; /* Environment variable name */
if (dest)
{
if (dest->instance)
_cupsLangPrintf(stdout, _("system default destination: %s/%s"),
dest->name, dest->instance);
else
_cupsLangPrintf(stdout, _("system default destination: %s"),
dest->name);
}
else
{
val = NULL;
if ((printer = getenv("LPDEST")) == NULL)
{
if ((printer = getenv("PRINTER")) != NULL)
{
if (!strcmp(printer, "lp"))
printer = NULL;
else
val = "PRINTER";
}
}
else
val = "LPDEST";
if (printer)
_cupsLangPrintf(stdout,
_("lpstat: error - %s environment variable names "
"non-existent destination \"%s\"."),
val, printer);
else
_cupsLangPuts(stdout, _("no system default destination"));
}
}
/*
* 'show_devices()' - Show printer devices.
*/
static int /* O - 0 on success, 1 on fail */
show_devices(const char *printers, /* I - Destinations */
int num_dests, /* I - Number of user-defined dests */
cups_dest_t *dests) /* I - User-defined destinations */
{
int i; /* Looping var */
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr; /* Current attribute */
const char *printer, /* Printer name */
*uri, /* Printer URI */
*device; /* Printer device URI */
static const char *pattrs[] = /* Attributes we need for printers... */
{
"printer-name",
"printer-uri-supported",
"device-uri"
};
if (printers != NULL && !strcmp(printers, "all"))
printers = NULL;
/*
* Build a CUPS_GET_PRINTERS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* requested-attributes
* requesting-user-name
*/
request = ippNewRequest(CUPS_GET_PRINTERS);
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
NULL, pattrs);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
/*
* Do the request and get back a response...
*/
response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
{
_cupsLangPrintf(stderr,
_("%s: Error - add '/version=1.1' to server name."),
"lpstat");
ippDelete(response);
return (1);
}
else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
{
_cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString());
ippDelete(response);
return (1);
}
if (response)
{
/*
* Loop through the printers returned in the list and display
* their devices...
*/
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
/*
* Skip leading attributes until we hit a job...
*/
while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
attr = attr->next;
if (attr == NULL)
break;
/*
* Pull the needed attributes from this job...
*/
printer = NULL;
device = NULL;
uri = NULL;
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
{
if (!strcmp(attr->name, "printer-name") &&
attr->value_tag == IPP_TAG_NAME)
printer = attr->values[0].string.text;
if (!strcmp(attr->name, "printer-uri-supported") &&
attr->value_tag == IPP_TAG_URI)
uri = attr->values[0].string.text;
if (!strcmp(attr->name, "device-uri") &&
attr->value_tag == IPP_TAG_URI)
device = attr->values[0].string.text;
attr = attr->next;
}
/*
* See if we have everything needed...
*/
if (printer == NULL)
{
if (attr == NULL)
break;
else
continue;
}
/*
* Display the printer entry if needed...
*/
if (match_list(printers, printer))
{
if (device == NULL)
_cupsLangPrintf(stdout, _("device for %s: %s"),
printer, uri);
else if (!strncmp(device, "file:", 5))
_cupsLangPrintf(stdout, _("device for %s: %s"),
printer, device + 5);
else
_cupsLangPrintf(stdout, _("device for %s: %s"),
printer, device);
for (i = 0; i < num_dests; i ++)
{
if (!_cups_strcasecmp(printer, dests[i].name) && dests[i].instance)
{
if (device == NULL)
_cupsLangPrintf(stdout, _("device for %s/%s: %s"),
printer, dests[i].instance, uri);
else if (!strncmp(device, "file:", 5))
_cupsLangPrintf(stdout, _("device for %s/%s: %s"),
printer, dests[i].instance, device + 5);
else
_cupsLangPrintf(stdout, _("device for %s/%s: %s"),
printer, dests[i].instance, device);
}
}
}
if (attr == NULL)
break;
}
ippDelete(response);
}
return (0);
}
/*
* 'show_jobs()' - Show active print jobs.
*/
static int /* O - 0 on success, 1 on fail */
show_jobs(const char *dests, /* I - Destinations */
const char *users, /* I - Users */
int long_status, /* I - Show long status? */
int ranking, /* I - Show job ranking? */
const char *which) /* I - Show which jobs? */
{
int i; /* Looping var */
ipp_t *request, /* IPP Request */
*response; /* IPP Response */
ipp_attribute_t *attr, /* Current attribute */
*reasons; /* Job state reasons attribute */
const char *dest, /* Pointer into job-printer-uri */
*username, /* Pointer to job-originating-user-name */
*message, /* Pointer to job-printer-state-message */
*time_at; /* time-at-xxx attribute name to use */
int rank, /* Rank in queue */
jobid, /* job-id */
size; /* job-k-octets */
time_t jobtime; /* time-at-creation */
char temp[255], /* Temporary buffer */
date[255]; /* Date buffer */
static const char *jattrs[] = /* Attributes we need for jobs... */
{
"job-id",
"job-k-octets",
"job-name",
"job-originating-user-name",
"job-printer-state-message",
"job-printer-uri",
"job-state-reasons",
"time-at-creation",
"time-at-completed"
};
if (dests != NULL && !strcmp(dests, "all"))
dests = NULL;
/*
* Build a IPP_GET_JOBS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* printer-uri
* requested-attributes
* requesting-user-name
* which-jobs
*/
request = ippNewRequest(IPP_GET_JOBS);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, "ipp://localhost/");
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", sizeof(jattrs) / sizeof(jattrs[0]),
NULL, jattrs);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs",
NULL, which);
/*
* Do the request and get back a response...
*/
response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
{
_cupsLangPrintf(stderr,
_("%s: Error - add '/version=1.1' to server name."),
"lpstat");
ippDelete(response);
return (1);
}
else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
{
_cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString());
ippDelete(response);
return (1);
}
if (response)
{
/*
* Loop through the job list and display them...
*/
if (!strcmp(which, "aborted") ||
!strcmp(which, "canceled") ||
!strcmp(which, "completed"))
time_at = "time-at-completed";
else
time_at = "time-at-creation";
rank = -1;
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
/*
* Skip leading attributes until we hit a job...
*/
while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
attr = attr->next;
if (attr == NULL)
break;
/*
* Pull the needed attributes from this job...
*/
jobid = 0;
size = 0;
username = NULL;
dest = NULL;
jobtime = 0;
message = NULL;
reasons = NULL;
while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
{
if (!strcmp(attr->name, "job-id") &&
attr->value_tag == IPP_TAG_INTEGER)
jobid = attr->values[0].integer;
else if (!strcmp(attr->name, "job-k-octets") &&
attr->value_tag == IPP_TAG_INTEGER)
size = attr->values[0].integer;
else if (!strcmp(attr->name, time_at) && attr->value_tag == IPP_TAG_INTEGER)
jobtime = attr->values[0].integer;
else if (!strcmp(attr->name, "job-printer-state-message") &&
attr->value_tag == IPP_TAG_TEXT)
message = attr->values[0].string.text;
else if (!strcmp(attr->name, "job-printer-uri") &&
attr->value_tag == IPP_TAG_URI)
{
if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
dest ++;
}
else if (!strcmp(attr->name, "job-originating-user-name") &&
attr->value_tag == IPP_TAG_NAME)
username = attr->values[0].string.text;
else if (!strcmp(attr->name, "job-state-reasons") &&
attr->value_tag == IPP_TAG_KEYWORD)
reasons = attr;
attr = attr->next;
}
/*
* See if we have everything needed...
*/
if (dest == NULL || jobid == 0)
{
if (attr == NULL)
break;
else
continue;
}
/*
* Display the job...
*/
rank ++;
if (match_list(dests, dest) && match_list(users, username))
{
snprintf(temp, sizeof(temp), "%s-%d", dest, jobid);
_cupsStrDate(date, sizeof(date), jobtime);
if (ranking)
_cupsLangPrintf(stdout, "%3d %-21s %-13s %8.0f %s",
rank, temp, username ? username : "unknown",
1024.0 * size, date);
else
_cupsLangPrintf(stdout, "%-23s %-13s %8.0f %s",
temp, username ? username : "unknown",
1024.0 * size, date);
if (long_status)
{
if (message)
_cupsLangPrintf(stdout, _("\tStatus: %s"), message);
if (reasons)
{
char alerts[1024], /* Alerts string */
*aptr; /* Pointer into alerts string */
for (i = 0, aptr = alerts; i < reasons->num_values; i ++)
{
if (i)
snprintf(aptr, sizeof(alerts) - (size_t)(aptr - alerts), " %s", reasons->values[i].string.text);
else
strlcpy(alerts, reasons->values[i].string.text, sizeof(alerts));
aptr += strlen(aptr);
}
_cupsLangPrintf(stdout, _("\tAlerts: %s"), alerts);
}
_cupsLangPrintf(stdout, _("\tqueued for %s"), dest);
}
}
if (attr == NULL)
break;
}
ippDelete(response);
}
return (0);
}
/*
* 'show_printers()' - Show printers.
*/
static int /* O - 0 on success, 1 on fail */
show_printers(const char *printers, /* I - Destinations */
int num_dests, /* I - Number of user-defined dests */
cups_dest_t *dests, /* I - User-defined destinations */
int long_status) /* I - Show long status? */
{
int i, j; /* Looping vars */
ipp_t *request, /* IPP Request */
*response, /* IPP Response */
*jobs; /* IPP Get Jobs response */
ipp_attribute_t *attr, /* Current attribute */
*jobattr, /* Job ID attribute */
*reasons; /* Job state reasons attribute */
const char *printer, /* Printer name */
*message, /* Printer state message */
*description, /* Description of printer */
*location, /* Location of printer */
*make_model, /* Make and model of printer */
*uri; /* URI of printer */
ipp_attribute_t *allowed, /* requesting-user-name-allowed */
*denied; /* requestint-user-name-denied */
ipp_pstate_t pstate; /* Printer state */
cups_ptype_t ptype; /* Printer type */
time_t ptime; /* Printer state time */
int jobid; /* Job ID of current job */
char printer_uri[HTTP_MAX_URI],
/* Printer URI */
printer_state_time[255];/* Printer state time */
_cups_globals_t *cg = _cupsGlobals(); /* Global data */
static const char *pattrs[] = /* Attributes we need for printers... */
{
"printer-name",
"printer-state",
"printer-state-message",
"printer-state-reasons",
"printer-state-change-time",
"printer-type",
"printer-info",
"printer-location",
"printer-make-and-model",
"printer-uri-supported",
"requesting-user-name-allowed",
"requesting-user-name-denied"
};
static const char *jattrs[] = /* Attributes we need for jobs... */
{
"job-id",
"job-state"
};
if (printers != NULL && !strcmp(printers, "all"))
printers = NULL;
/*
* Build a CUPS_GET_PRINTERS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* requested-attributes
* requesting-user-name
*/
request = ippNewRequest(CUPS_GET_PRINTERS);
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
NULL, pattrs);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
NULL, cupsUser());
/*
* Do the request and get back a response...
*/
response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST ||
cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED)
{
_cupsLangPrintf(stderr,
_("%s: Error - add '/version=1.1' to server name."),
"lpstat");
ippDelete(response);
return (1);
}
else if (cupsLastError() > IPP_STATUS_OK_CONFLICTING)
{
_cupsLangPrintf(stderr, "lpstat: %s", cupsLastErrorString());
ippDelete(response);
return (1);
}
if (response)
{
/*
* Loop through the printers returned in the list and display
* their status...
*/
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
/*
* Skip leading attributes until we hit a job...
*/
while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
attr = attr->next;
if (attr == NULL)
break;
/*
* Pull the needed attributes from this job...
*/
printer = NULL;
ptime = 0;
ptype = CUPS_PRINTER_LOCAL;
pstate = IPP_PRINTER_IDLE;
message = NULL;
description = NULL;
location = NULL;
make_model = NULL;
reasons = NULL;
uri = NULL;
jobid = 0;
allowed = NULL;
denied = NULL;
while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
{
if (!strcmp(attr->name, "printer-name") &&
attr->value_tag == IPP_TAG_NAME)
printer = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-state") &&
attr->value_tag == IPP_TAG_ENUM)
pstate = (ipp_pstate_t)attr->values[0].integer;
else if (!strcmp(attr->name, "printer-type") &&
attr->value_tag == IPP_TAG_ENUM)
ptype = (cups_ptype_t)attr->values[0].integer;
else if (!strcmp(attr->name, "printer-state-message") &&
attr->value_tag == IPP_TAG_TEXT)
message = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-state-change-time") &&
attr->value_tag == IPP_TAG_INTEGER)
ptime = (time_t)attr->values[0].integer;
else if (!strcmp(attr->name, "printer-info") &&
attr->value_tag == IPP_TAG_TEXT)
description = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-location") &&
attr->value_tag == IPP_TAG_TEXT)
location = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-make-and-model") &&
attr->value_tag == IPP_TAG_TEXT)
make_model = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-uri-supported") &&
attr->value_tag == IPP_TAG_URI)
uri = attr->values[0].string.text;
else if (!strcmp(attr->name, "printer-state-reasons") &&
attr->value_tag == IPP_TAG_KEYWORD)
reasons = attr;
else if (!strcmp(attr->name, "requesting-user-name-allowed") &&
attr->value_tag == IPP_TAG_NAME)
allowed = attr;
else if (!strcmp(attr->name, "requesting-user-name-denied") &&
attr->value_tag == IPP_TAG_NAME)
denied = attr;
attr = attr->next;
}
/*
* See if we have everything needed...
*/
if (printer == NULL)
{
if (attr == NULL)
break;
else
continue;
}
/*
* Display the printer entry if needed...
*/
if (match_list(printers, printer))
{
/*
* If the printer state is "IPP_PRINTER_PROCESSING", then grab the
* current job for the printer.
*/
if (pstate == IPP_PRINTER_PROCESSING)
{
/*
* Build an IPP_GET_JOBS request, which requires the following
* attributes:
*
* attributes-charset
* attributes-natural-language
* printer-uri
* limit
* requested-attributes
*/
request = ippNewRequest(IPP_GET_JOBS);
request->request.op.operation_id = IPP_GET_JOBS;
request->request.op.request_id = 1;
ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes",
sizeof(jattrs) / sizeof(jattrs[0]), NULL, jattrs);
httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
"ipp", NULL, "localhost", 0, "/printers/%s", printer);
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, printer_uri);
if ((jobs = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/")) != NULL)
{
/*
* Get the current active job on this queue...
*/
ipp_jstate_t jobstate = IPP_JOB_PENDING;
jobid = 0;
for (jobattr = jobs->attrs; jobattr; jobattr = jobattr->next)
{
if (!jobattr->name)
{
if (jobstate == IPP_JOB_PROCESSING)
break;
else
continue;
}
if (!strcmp(jobattr->name, "job-id") &&
jobattr->value_tag == IPP_TAG_INTEGER)
jobid = jobattr->values[0].integer;
else if (!strcmp(jobattr->name, "job-state") &&
jobattr->value_tag == IPP_TAG_ENUM)
jobstate = (ipp_jstate_t)jobattr->values[0].integer;
}
if (jobstate != IPP_JOB_PROCESSING)
jobid = 0;
ippDelete(jobs);
}
}
/*
* Display it...
*/
_cupsStrDate(printer_state_time, sizeof(printer_state_time), ptime);
switch (pstate)
{
case IPP_PRINTER_IDLE :
if (ippContainsString(reasons, "hold-new-jobs"))
_cupsLangPrintf(stdout, _("printer %s is holding new jobs. enabled since %s"), printer, printer_state_time);
else
_cupsLangPrintf(stdout, _("printer %s is idle. enabled since %s"), printer, printer_state_time);
break;
case IPP_PRINTER_PROCESSING :
_cupsLangPrintf(stdout, _("printer %s now printing %s-%d. enabled since %s"), printer, printer, jobid, printer_state_time);
break;
case IPP_PRINTER_STOPPED :
_cupsLangPrintf(stdout, _("printer %s disabled since %s -"), printer, printer_state_time);
break;
}
if ((message && *message) || pstate == IPP_PRINTER_STOPPED)
{
if (!message || !*message)
_cupsLangPuts(stdout, _("\treason unknown"));
else
_cupsLangPrintf(stdout, "\t%s", message);
}
if (long_status > 1)
{
_cupsLangPuts(stdout, _("\tForm mounted:"));
_cupsLangPuts(stdout, _("\tContent types: any"));
_cupsLangPuts(stdout, _("\tPrinter types: unknown"));
}
if (long_status)
{
_cupsLangPrintf(stdout, _("\tDescription: %s"),
description ? description : "");
if (reasons)
{
char alerts[1024], /* Alerts string */
*aptr; /* Pointer into alerts string */
for (i = 0, aptr = alerts; i < reasons->num_values; i ++)
{
if (i)
snprintf(aptr, sizeof(alerts) - (size_t)(aptr - alerts), " %s", reasons->values[i].string.text);
else
strlcpy(alerts, reasons->values[i].string.text, sizeof(alerts));
aptr += strlen(aptr);
}
_cupsLangPrintf(stdout, _("\tAlerts: %s"), alerts);
}
}
if (long_status > 1)
{
_cupsLangPrintf(stdout, _("\tLocation: %s"),
location ? location : "");
if (ptype & CUPS_PRINTER_REMOTE)
{
_cupsLangPuts(stdout, _("\tConnection: remote"));
if (make_model && !strstr(make_model, "System V Printer") &&
!strstr(make_model, "Raw Printer") && uri)
_cupsLangPrintf(stdout, _("\tInterface: %s.ppd"),
uri);
}
else
{
_cupsLangPuts(stdout, _("\tConnection: direct"));
if (make_model && !strstr(make_model, "Raw Printer"))
_cupsLangPrintf(stdout,
_("\tInterface: %s/ppd/%s.ppd"),
cg->cups_serverroot, printer);
}
_cupsLangPuts(stdout, _("\tOn fault: no alert"));
_cupsLangPuts(stdout, _("\tAfter fault: continue"));
/* TODO update to use printer-error-policy */
if (allowed)
{
_cupsLangPuts(stdout, _("\tUsers allowed:"));
for (j = 0; j < allowed->num_values; j ++)
_cupsLangPrintf(stdout, "\t\t%s",
allowed->values[j].string.text);
}
else if (denied)
{
_cupsLangPuts(stdout, _("\tUsers denied:"));
for (j = 0; j < denied->num_values; j ++)
_cupsLangPrintf(stdout, "\t\t%s",
denied->values[j].string.text);
}
else
{
_cupsLangPuts(stdout, _("\tUsers allowed:"));
_cupsLangPuts(stdout, _("\t\t(all)"));
}
_cupsLangPuts(stdout, _("\tForms allowed:"));
_cupsLangPuts(stdout, _("\t\t(none)"));
_cupsLangPuts(stdout, _("\tBanner required"));
_cupsLangPuts(stdout, _("\tCharset sets:"));
_cupsLangPuts(stdout, _("\t\t(none)"));
_cupsLangPuts(stdout, _("\tDefault pitch:"));
_cupsLangPuts(stdout, _("\tDefault page size:"));
_cupsLangPuts(stdout, _("\tDefault port settings:"));
}
for (i = 0; i < num_dests; i ++)
if (!_cups_strcasecmp(printer, dests[i].name) && dests[i].instance)
{
switch (pstate)
{
case IPP_PRINTER_IDLE :
_cupsLangPrintf(stdout,
_("printer %s/%s is idle. "
"enabled since %s"),
printer, dests[i].instance,
printer_state_time);
break;
case IPP_PRINTER_PROCESSING :
_cupsLangPrintf(stdout,
_("printer %s/%s now printing %s-%d. "
"enabled since %s"),
printer, dests[i].instance, printer, jobid,
printer_state_time);
break;
case IPP_PRINTER_STOPPED :
_cupsLangPrintf(stdout,
_("printer %s/%s disabled since %s -"),
printer, dests[i].instance,
printer_state_time);
break;
}
if ((message && *message) || pstate == IPP_PRINTER_STOPPED)
{
if (!message || !*message)
_cupsLangPuts(stdout, _("\treason unknown"));
else
_cupsLangPrintf(stdout, "\t%s", message);
}
if (long_status > 1)
{
_cupsLangPuts(stdout, _("\tForm mounted:"));
_cupsLangPuts(stdout, _("\tContent types: any"));
_cupsLangPuts(stdout, _("\tPrinter types: unknown"));
}
if (long_status)
{
_cupsLangPrintf(stdout, _("\tDescription: %s"),
description ? description : "");
if (reasons)
{
char alerts[1024], /* Alerts string */
*aptr; /* Pointer into alerts string */
for (i = 0, aptr = alerts; i < reasons->num_values; i ++)
{
if (i)
snprintf(aptr, sizeof(alerts) - (size_t)(aptr - alerts), " %s", reasons->values[i].string.text);
else
strlcpy(alerts, reasons->values[i].string.text, sizeof(alerts));
aptr += strlen(aptr);
}
_cupsLangPrintf(stdout, _("\tAlerts: %s"), alerts);
}
}
if (long_status > 1)
{
_cupsLangPrintf(stdout, _("\tLocation: %s"),
location ? location : "");
if (ptype & CUPS_PRINTER_REMOTE)
{
_cupsLangPuts(stdout, _("\tConnection: remote"));
if (make_model && !strstr(make_model, "System V Printer") &&
!strstr(make_model, "Raw Printer") && uri)
_cupsLangPrintf(stdout, _("\tInterface: %s.ppd"), uri);
}
else
{
_cupsLangPuts(stdout, _("\tConnection: direct"));
if (make_model && !strstr(make_model, "Raw Printer"))
_cupsLangPrintf(stdout,
_("\tInterface: %s/ppd/%s.ppd"),
cg->cups_serverroot, printer);
}
_cupsLangPuts(stdout, _("\tOn fault: no alert"));
_cupsLangPuts(stdout, _("\tAfter fault: continue"));
/* TODO update to use printer-error-policy */
if (allowed)
{
_cupsLangPuts(stdout, _("\tUsers allowed:"));
for (j = 0; j < allowed->num_values; j ++)
_cupsLangPrintf(stdout, "\t\t%s",
allowed->values[j].string.text);
}
else if (denied)
{
_cupsLangPuts(stdout, _("\tUsers denied:"));
for (j = 0; j < denied->num_values; j ++)
_cupsLangPrintf(stdout, "\t\t%s",
denied->values[j].string.text);
}
else
{
_cupsLangPuts(stdout, _("\tUsers allowed:"));
_cupsLangPuts(stdout, _("\t\t(all)"));
}
_cupsLangPuts(stdout, _("\tForms allowed:"));
_cupsLangPuts(stdout, _("\t\t(none)"));
_cupsLangPuts(stdout, _("\tBanner required"));
_cupsLangPuts(stdout, _("\tCharset sets:"));
_cupsLangPuts(stdout, _("\t\t(none)"));
_cupsLangPuts(stdout, _("\tDefault pitch:"));
_cupsLangPuts(stdout, _("\tDefault page size:"));
_cupsLangPuts(stdout, _("\tDefault port settings:"));
}
}
}
if (attr == NULL)
break;
}
ippDelete(response);
}
return (0);
}
/*
* 'show_scheduler()' - Show scheduler status.
*/
static void
show_scheduler(void)
{
http_t *http; /* Connection to server */
if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
cupsEncryption())) != NULL)
{
_cupsLangPuts(stdout, _("scheduler is running"));
httpClose(http);
}
else
_cupsLangPuts(stdout, _("scheduler is not running"));
}
/*
* 'usage()' - Show program usage and exit.
*/
static void
usage(void)
{
_cupsLangPuts(stdout, _("Usage: lpstat [options]"));
_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, _("-U username Specify the username to use for authentication"));
_cupsLangPuts(stdout, _("-H Show the default server and port"));
_cupsLangPuts(stdout, _("-W completed Show completed jobs"));
_cupsLangPuts(stdout, _("-W not-completed Show pending jobs"));
_cupsLangPuts(stdout, _("-a [destination(s)] Show the accepting state of destinations"));
_cupsLangPuts(stdout, _("-c [class(es)] Show classes and their member printers"));
_cupsLangPuts(stdout, _("-d Show the default destination"));
_cupsLangPuts(stdout, _("-e Show available destinations on the network"));
_cupsLangPuts(stdout, _("-o [destination(s)] Show jobs"));
_cupsLangPuts(stdout, _("-p [printer(s)] Show the processing state of destinations"));
_cupsLangPuts(stdout, _("-r Show whether the CUPS server is running"));
_cupsLangPuts(stdout, _("-R Show the ranking of jobs"));
_cupsLangPuts(stdout, _("-s Show a status summary"));
_cupsLangPuts(stdout, _("-t Show all status information"));
_cupsLangPuts(stdout, _("-u [user(s)] Show jobs queued by the current or specified users"));
_cupsLangPuts(stdout, _("-v [printer(s)] Show the devices for each destination"));
exit(1);
}