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.

611 lines
14 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.

/*
* CUPS API test program for CUPS.
*
* Copyright © 2007-2018 by Apple Inc.
* Copyright © 2007 by Easy Software Products.
*
* Licensed under Apache License v2.0. See the file "LICENSE" for more information.
*/
/*
* Include necessary headers...
*/
#undef _CUPS_NO_DEPRECATED
#include "cups-private.h"
#include "ppd.h"
#include <stdlib.h>
/*
* Local functions...
*/
static int dests_equal(cups_dest_t *a, cups_dest_t *b);
static int enum_cb(void *user_data, unsigned flags, cups_dest_t *dest);
static void show_diffs(cups_dest_t *a, cups_dest_t *b);
/*
* 'main()' - Main entry.
*/
int /* O - Exit status */
main(int argc, /* I - Number of command-line arguments */
char *argv[]) /* I - Command-line arguments */
{
http_t *http, /* First HTTP connection */
*http2; /* Second HTTP connection */
int status = 0, /* Exit status */
i, /* Looping var */
num_dests; /* Number of destinations */
cups_dest_t *dests, /* Destinations */
*dest, /* Current destination */
*named_dest; /* Current named destination */
const char *dest_name, /* Destination name */
*dval, /* Destination value */
*ppdfile; /* PPD file */
ppd_file_t *ppd; /* PPD file data */
int num_jobs; /* Number of jobs for queue */
cups_job_t *jobs; /* Jobs for queue */
if (argc > 1)
{
if (!strcmp(argv[1], "enum"))
{
cups_ptype_t mask = CUPS_PRINTER_LOCAL,
/* Printer type mask */
type = CUPS_PRINTER_LOCAL;
/* Printer type */
int msec = 0; /* Timeout in milliseconds */
for (i = 2; i < argc; i ++)
if (isdigit(argv[i][0] & 255) || argv[i][0] == '.')
msec = (int)(atof(argv[i]) * 1000);
else if (!_cups_strcasecmp(argv[i], "bw"))
{
mask |= CUPS_PRINTER_BW;
type |= CUPS_PRINTER_BW;
}
else if (!_cups_strcasecmp(argv[i], "color"))
{
mask |= CUPS_PRINTER_COLOR;
type |= CUPS_PRINTER_COLOR;
}
else if (!_cups_strcasecmp(argv[i], "mono"))
{
mask |= CUPS_PRINTER_COLOR;
}
else if (!_cups_strcasecmp(argv[i], "duplex"))
{
mask |= CUPS_PRINTER_DUPLEX;
type |= CUPS_PRINTER_DUPLEX;
}
else if (!_cups_strcasecmp(argv[i], "simplex"))
{
mask |= CUPS_PRINTER_DUPLEX;
}
else if (!_cups_strcasecmp(argv[i], "staple"))
{
mask |= CUPS_PRINTER_STAPLE;
type |= CUPS_PRINTER_STAPLE;
}
else if (!_cups_strcasecmp(argv[i], "copies"))
{
mask |= CUPS_PRINTER_COPIES;
type |= CUPS_PRINTER_COPIES;
}
else if (!_cups_strcasecmp(argv[i], "collate"))
{
mask |= CUPS_PRINTER_COLLATE;
type |= CUPS_PRINTER_COLLATE;
}
else if (!_cups_strcasecmp(argv[i], "punch"))
{
mask |= CUPS_PRINTER_PUNCH;
type |= CUPS_PRINTER_PUNCH;
}
else if (!_cups_strcasecmp(argv[i], "cover"))
{
mask |= CUPS_PRINTER_COVER;
type |= CUPS_PRINTER_COVER;
}
else if (!_cups_strcasecmp(argv[i], "bind"))
{
mask |= CUPS_PRINTER_BIND;
type |= CUPS_PRINTER_BIND;
}
else if (!_cups_strcasecmp(argv[i], "sort"))
{
mask |= CUPS_PRINTER_SORT;
type |= CUPS_PRINTER_SORT;
}
else if (!_cups_strcasecmp(argv[i], "mfp"))
{
mask |= CUPS_PRINTER_MFP;
type |= CUPS_PRINTER_MFP;
}
else if (!_cups_strcasecmp(argv[i], "printer"))
{
mask |= CUPS_PRINTER_MFP;
}
else if (!_cups_strcasecmp(argv[i], "large"))
{
mask |= CUPS_PRINTER_LARGE;
type |= CUPS_PRINTER_LARGE;
}
else if (!_cups_strcasecmp(argv[i], "medium"))
{
mask |= CUPS_PRINTER_MEDIUM;
type |= CUPS_PRINTER_MEDIUM;
}
else if (!_cups_strcasecmp(argv[i], "small"))
{
mask |= CUPS_PRINTER_SMALL;
type |= CUPS_PRINTER_SMALL;
}
else
fprintf(stderr, "Unknown argument \"%s\" ignored...\n", argv[i]);
cupsEnumDests(CUPS_DEST_FLAGS_NONE, msec, NULL, type, mask, enum_cb, NULL);
}
else if (!strcmp(argv[1], "password"))
{
const char *pass = cupsGetPassword("Password:");
/* Password string */
if (pass)
printf("Password entered: %s\n", pass);
else
puts("No password entered.");
}
else if (!strcmp(argv[1], "ppd") && argc == 3)
{
/*
* ./testcups ppd printer
*/
http_status_t http_status; /* Status */
char buffer[1024]; /* PPD filename */
time_t modtime = 0; /* Last modified */
if ((http_status = cupsGetPPD3(CUPS_HTTP_DEFAULT, argv[2], &modtime,
buffer, sizeof(buffer))) != HTTP_STATUS_OK)
printf("Unable to get PPD: %d (%s)\n", (int)http_status,
cupsLastErrorString());
else
puts(buffer);
}
else if (!strcmp(argv[1], "print") && argc == 5)
{
/*
* ./testcups print printer file interval
*/
int interval, /* Interval between writes */
job_id; /* Job ID */
cups_file_t *fp; /* Print file */
char buffer[16384]; /* Read/write buffer */
ssize_t bytes; /* Bytes read/written */
if ((fp = cupsFileOpen(argv[3], "r")) == NULL)
{
printf("Unable to open \"%s\": %s\n", argv[2], strerror(errno));
return (1);
}
if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, argv[2], "testcups", 0,
NULL)) <= 0)
{
printf("Unable to create print job on %s: %s\n", argv[1],
cupsLastErrorString());
return (1);
}
interval = atoi(argv[4]);
if (cupsStartDocument(CUPS_HTTP_DEFAULT, argv[1], job_id, argv[2],
CUPS_FORMAT_AUTO, 1) != HTTP_STATUS_CONTINUE)
{
puts("Unable to start document!");
return (1);
}
while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
{
printf("Writing %d bytes...\n", (int)bytes);
if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes) != HTTP_STATUS_CONTINUE)
{
puts("Unable to write bytes!");
return (1);
}
if (interval > 0)
sleep((unsigned)interval);
}
cupsFileClose(fp);
if (cupsFinishDocument(CUPS_HTTP_DEFAULT,
argv[1]) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
{
puts("Unable to finish document!");
return (1);
}
}
else
{
puts("Usage:");
puts("");
puts("Run basic unit tests:");
puts("");
puts(" ./testcups");
puts("");
puts("Enumerate printers (for N seconds, -1 for indefinitely):");
puts("");
puts(" ./testcups enum [seconds]");
puts("");
puts("Ask for a password:");
puts("");
puts(" ./testcups password");
puts("");
puts("Get the PPD file:");
puts("");
puts(" ./testcups ppd printer");
puts("");
puts("Print a file (interval controls delay between buffers in seconds):");
puts("");
puts(" ./testcups print printer file interval");
return (1);
}
return (0);
}
/*
* _cupsConnect() connection reuse...
*/
fputs("_cupsConnect: ", stdout);
http = _cupsConnect();
http2 = _cupsConnect();
if (http == http2)
{
puts("PASS");
}
else
{
puts("FAIL (different connections)");
return (1);
}
/*
* cupsGetDests()
*/
fputs("cupsGetDests: ", stdout);
fflush(stdout);
num_dests = cupsGetDests(&dests);
if (num_dests == 0)
{
puts("FAIL");
return (1);
}
else
{
printf("PASS (%d dests)\n", num_dests);
for (i = num_dests, dest = dests; i > 0; i --, dest ++)
{
printf(" %s", dest->name);
if (dest->instance)
printf(" /%s", dest->instance);
if (dest->is_default)
puts(" ***DEFAULT***");
else
putchar('\n');
}
}
/*
* cupsGetDest(NULL)
*/
fputs("cupsGetDest(NULL): ", stdout);
fflush(stdout);
if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
{
for (i = num_dests, dest = dests; i > 0; i --, dest ++)
if (dest->is_default)
break;
if (i)
{
status = 1;
puts("FAIL");
}
else
puts("PASS (no default)");
dest = NULL;
}
else
printf("PASS (%s)\n", dest->name);
/*
* cupsGetNamedDest(NULL, NULL, NULL)
*/
fputs("cupsGetNamedDest(NULL, NULL, NULL): ", stdout);
fflush(stdout);
if ((named_dest = cupsGetNamedDest(NULL, NULL, NULL)) == NULL ||
!dests_equal(dest, named_dest))
{
if (!dest)
puts("PASS (no default)");
else if (named_dest)
{
puts("FAIL (different values)");
show_diffs(dest, named_dest);
status = 1;
}
else
{
puts("FAIL (no default)");
status = 1;
}
}
else
printf("PASS (%s)\n", named_dest->name);
if (named_dest)
cupsFreeDests(1, named_dest);
/*
* cupsGetDest(printer)
*/
for (i = 0, dest_name = NULL; i < num_dests; i ++)
{
if ((dval = cupsGetOption("printer-is-temporary", dests[i].num_options, dest[i].options)) != NULL && !strcmp(dval, "false"))
{
dest_name = dests[i].name;
break;
}
}
printf("cupsGetDest(\"%s\"): ", dest_name ? dest_name : "(null)");
fflush(stdout);
if ((dest = cupsGetDest(dest_name, NULL, num_dests, dests)) == NULL)
{
puts("FAIL");
return (1);
}
else
puts("PASS");
/*
* cupsGetNamedDest(NULL, printer, instance)
*/
printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name,
dest->instance ? dest->instance : "(null)");
fflush(stdout);
if ((named_dest = cupsGetNamedDest(NULL, dest->name, dest->instance)) == NULL ||
!dests_equal(dest, named_dest))
{
if (named_dest)
{
puts("FAIL (different values)");
show_diffs(dest, named_dest);
}
else
puts("FAIL (no destination)");
status = 1;
}
else
puts("PASS");
if (named_dest)
cupsFreeDests(1, named_dest);
/*
* cupsPrintFile()
*/
fputs("cupsPrintFile: ", stdout);
fflush(stdout);
if (cupsPrintFile(dest->name, "../test/testfile.pdf", "Test Page",
dest->num_options, dest->options) <= 0)
{
printf("FAIL (%s)\n", cupsLastErrorString());
return (1);
}
else
puts("PASS");
/*
* cupsGetPPD(printer)
*/
fputs("cupsGetPPD: ", stdout);
fflush(stdout);
if ((ppdfile = cupsGetPPD(dest->name)) == NULL)
{
puts("FAIL");
}
else
{
puts("PASS");
/*
* ppdOpenFile()
*/
fputs("ppdOpenFile: ", stdout);
fflush(stdout);
if ((ppd = ppdOpenFile(ppdfile)) == NULL)
{
puts("FAIL");
return (1);
}
else
puts("PASS");
ppdClose(ppd);
unlink(ppdfile);
}
/*
* cupsGetJobs()
*/
fputs("cupsGetJobs: ", stdout);
fflush(stdout);
num_jobs = cupsGetJobs(&jobs, NULL, 0, -1);
if (num_jobs == 0)
{
puts("FAIL");
return (1);
}
else
puts("PASS");
cupsFreeJobs(num_jobs, jobs);
cupsFreeDests(num_dests, dests);
return (status);
}
/*
* 'dests_equal()' - Determine whether two destinations are equal.
*/
static int /* O - 1 if equal, 0 if not equal */
dests_equal(cups_dest_t *a, /* I - First destination */
cups_dest_t *b) /* I - Second destination */
{
int i; /* Looping var */
cups_option_t *aoption; /* Current option */
const char *bval; /* Option value */
if (a == b)
return (1);
if (!a || !b)
return (0);
if (_cups_strcasecmp(a->name, b->name) ||
(a->instance && !b->instance) ||
(!a->instance && b->instance) ||
(a->instance && _cups_strcasecmp(a->instance, b->instance)) ||
a->num_options != b->num_options)
return (0);
for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++)
if ((bval = cupsGetOption(aoption->name, b->num_options,
b->options)) == NULL ||
strcmp(aoption->value, bval))
return (0);
return (1);
}
/*
* 'enum_cb()' - Report additions and removals.
*/
static int /* O - 1 to continue, 0 to stop */
enum_cb(void *user_data, /* I - User data (unused) */
unsigned flags, /* I - Destination flags */
cups_dest_t *dest) /* I - Destination */
{
int i; /* Looping var */
cups_option_t *option; /* Current option */
(void)user_data;
if (flags & CUPS_DEST_FLAGS_REMOVED)
printf("Removed '%s':\n", dest->name);
else
printf("Added '%s':\n", dest->name);
for (i = dest->num_options, option = dest->options; i > 0; i --, option ++)
printf(" %s=\"%s\"\n", option->name, option->value);
putchar('\n');
return (1);
}
/*
* 'show_diffs()' - Show differences between two destinations.
*/
static void
show_diffs(cups_dest_t *a, /* I - First destination */
cups_dest_t *b) /* I - Second destination */
{
int i; /* Looping var */
cups_option_t *aoption; /* Current option */
cups_option_t *boption; /* Current option */
const char *bval; /* Option value */
if (!a || !b)
return;
puts(" Item cupsGetDest cupsGetNamedDest");
puts(" -------------------- ------------------------ ------------------------");
if (_cups_strcasecmp(a->name, b->name))
printf(" name %-24.24s %-24.24s\n", a->name, b->name);
if ((a->instance && !b->instance) ||
(!a->instance && b->instance) ||
(a->instance && _cups_strcasecmp(a->instance, b->instance)))
printf(" instance %-24.24s %-24.24s\n",
a->instance ? a->instance : "(null)",
b->instance ? b->instance : "(null)");
if (a->num_options != b->num_options)
printf(" num_options %-24d %-24d\n", a->num_options,
b->num_options);
for (i = a->num_options, aoption = a->options; i > 0; i --, aoption ++)
if ((bval = cupsGetOption(aoption->name, b->num_options,
b->options)) == NULL ||
strcmp(aoption->value, bval))
printf(" %-20.20s %-24.24s %-24.24s\n", aoption->name,
aoption->value, bval ? bval : "(null)");
for (i = b->num_options, boption = b->options; i > 0; i --, boption ++)
if (!cupsGetOption(boption->name, a->num_options, a->options))
printf(" %-20.20s %-24.24s %-24.24s\n", boption->name,
boption->value, "(null)");
}