303 lines
11 KiB
C
303 lines
11 KiB
C
/*
|
|
*
|
|
* poll_ppd_base
|
|
* -------------
|
|
#
|
|
# A simple tool for getting a list of all installed PPD files
|
|
# with printer manufacturer and printer model, polling the database
|
|
# of the CUPS daemon. This program is mainly intended to be called
|
|
# from installation/configuration scripts for CUPS.
|
|
#
|
|
# ONLY WORKS WITH CUPS DAEMON RUNNING!
|
|
# The CUPS library (libcups.so.*) must be installed!
|
|
#
|
|
# Compile with: gcc -opoll_ppd_base -lcups poll_ppd_base.c
|
|
#
|
|
* Copyright 2000 by Till Kamppeter
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
* 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Include necessary headers...
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <cups/cups.h>
|
|
#include <cups/ipp.h>
|
|
#include <cups/language.h>
|
|
|
|
// IPP Request routines for getting the printer type, stolen from QTCUPS from
|
|
// Michael Goffioul (file qtcups/cupshelper.cpp)
|
|
|
|
ipp_t* newIppRequest()
|
|
{
|
|
ipp_t *request;
|
|
cups_lang_t *lang;
|
|
request = ippNew();
|
|
request->request.op.request_id = 1;
|
|
lang = cupsLangDefault();
|
|
ippAddString(request,IPP_TAG_OPERATION,IPP_TAG_CHARSET,"attributes-charset",NULL,cupsLangEncoding(lang));
|
|
ippAddString(request,IPP_TAG_OPERATION,IPP_TAG_LANGUAGE,"attributes-natural-language",NULL,lang->language);
|
|
return request;
|
|
}
|
|
|
|
ipp_t* processRequest(ipp_t *req, const char *res)
|
|
{
|
|
http_t *HTTP;
|
|
ipp_t *answer;
|
|
HTTP = httpConnect(cupsServer(),ippPort());
|
|
if (!HTTP) {
|
|
ippDelete(req);
|
|
return 0;
|
|
}
|
|
answer = cupsDoRequest(HTTP,req,res);
|
|
httpClose(HTTP);
|
|
if (!answer) return 0;
|
|
if (answer->state == IPP_ERROR || answer->state == IPP_IDLE) {
|
|
ippDelete(answer);
|
|
return 0;
|
|
}
|
|
return answer;
|
|
}
|
|
|
|
ipp_t *getPPDList()
|
|
{
|
|
ipp_t *request = newIppRequest();
|
|
char str[1024];
|
|
const char* server = cupsServer();
|
|
int port = ippPort();
|
|
|
|
request->request.op.operation_id = CUPS_GET_PPDS;
|
|
if ((!server) || (port < 0)) return NULL;
|
|
sprintf(str,"ipp://%s:%d/printers/",cupsServer(),ippPort());
|
|
ippAddString(request,IPP_TAG_OPERATION,IPP_TAG_URI,"printer-uri",NULL,str);
|
|
//str.sprintf("/printers/%s",name);
|
|
request = processRequest(request,"/");
|
|
return request;
|
|
}
|
|
|
|
/*
|
|
* Main program
|
|
*/
|
|
|
|
int /* O - exit state */
|
|
main(int argc, /* I - Number of command-line arguments */
|
|
char *argv[]) /* I - Command-line arguments */
|
|
{
|
|
int i,j; /* Looping vars */
|
|
int makelen = 0; /* Length of current manufacturer name */
|
|
int makelist = 0; /* List of manufacturers */
|
|
int makegiven = 0; /* List of models for given manufacturer */
|
|
int all = 0; /* LIst of all models */
|
|
char *make; /* Chosen manufacturer */
|
|
ipp_t *ppdlist; /* List of PPD files resulting from IPP */
|
|
/* request */
|
|
ipp_attribute_t *attr, /* Current attribute */
|
|
*last; /* Last attribute */
|
|
char *currmake, /* current data red from PPD list */
|
|
*currmod,
|
|
*currlang,
|
|
*currfile,
|
|
*c;
|
|
char buffer[80],
|
|
buffer2[256];
|
|
int lineprinted = 1; /* Is the current line already printed to
|
|
stdout */
|
|
|
|
// read command line arguments
|
|
|
|
for (i = 1; i < argc; i ++)
|
|
if (argv[i][0] == '-') {
|
|
switch (argv[i][1]) {
|
|
case 'm' : /* Manufacturer options */
|
|
if (argv[i][2] != '\0') {
|
|
if (strcmp(argv[i],"-ml") == 0) {
|
|
makelist = 1;
|
|
} else {
|
|
make = argv[i] + 2;
|
|
makegiven = 1;
|
|
}
|
|
} else {
|
|
i ++;
|
|
if (!(make = argv[i])) return 1;
|
|
makegiven = 1;
|
|
}
|
|
break;
|
|
case 'a' : /* List all PPD files */
|
|
all = 1;
|
|
break;
|
|
default :
|
|
fprintf(stderr,"Unknown option \'%c\'!\n", argv[i][1]);
|
|
fprintf(stderr,"Start program without options for help!\n");
|
|
return(1);
|
|
}
|
|
} else {
|
|
fprintf(stderr,"Unknown option \'%s\'!", argv[i]);
|
|
fprintf(stderr,"Start program without options for help!\n");
|
|
return(1);
|
|
}
|
|
if ((all) || (makegiven)) { // list all PPDs or PPDs of given manufacturer
|
|
ppdlist = getPPDList();
|
|
if (!ppdlist) return 1;
|
|
for (attr = ppdlist->attrs; // go through all entries
|
|
attr != NULL;
|
|
attr = attr->next)
|
|
if (attr->name) {
|
|
// read data items
|
|
if (strcmp(attr->name, "ppd-name") == 0) {
|
|
currfile = attr->values[0].string.text;
|
|
lineprinted = 0;
|
|
} else if (strcmp(attr->name, "ppd-make") == 0) {
|
|
currmake = attr->values[0].string.text;
|
|
} else if (strcmp(attr->name, "ppd-make-and-model") == 0) {
|
|
currmod = attr->values[0].string.text;
|
|
} else if (strcmp(attr->name, "ppd-natural-language") == 0) {
|
|
currlang = attr->values[0].string.text;
|
|
}
|
|
} else { // attr->name = NULL ==> data set completed
|
|
lineprinted = 1;
|
|
// Fill empty entries with some default stuff
|
|
if (!currmod) currmod = "UNKNOWN";
|
|
if (!currmake) currmake = "UNKNOWN";
|
|
if (!currlang) currlang = "en";
|
|
// Remove the manufacturer's name from the model entries
|
|
makelen = strlen(currmake);
|
|
if (strcasecmp(currmake,"UNKNOWN") != 0) {
|
|
if (strncasecmp(currmake,currmod,makelen) == 0) {
|
|
currmod += makelen;
|
|
while ((*currmod == ' ') ||
|
|
(*currmod == '-') ||
|
|
(*currmod == '\t')) currmod ++;
|
|
}
|
|
}
|
|
// Make the manufacturer's name all-uppercase
|
|
currmake = strcpy(buffer,currmake);
|
|
for (i = 0; i < makelen; i ++) buffer[i] = toupper(buffer[i]);
|
|
// Clean up the driver info
|
|
currmod = strcpy(buffer2,currmod);
|
|
if (c = strstr(currmod, "Foomatic + Postscript")) {
|
|
memmove(c, "PostScript", 10);
|
|
memmove(c + 10, c + 21, strlen(c) - 20);
|
|
} else if (c = strstr(currmod, "Foomatic")) {
|
|
memmove(c + 11, c + 8, strlen(c) - 7);
|
|
memmove(c, "GhostScript", 11);
|
|
} else if (c = strstr(currmod, "CUPS+GIMP-print")) {
|
|
memmove(c + 17, c + 15, strlen(c) - 14);
|
|
memmove(c, "CUPS + GIMP-Print", 17);
|
|
} else if (c = strstr(currmod, "Series CUPS")) {
|
|
memmove(c + 12, c + 11, strlen(c) - 10);
|
|
memmove(c, "Series, CUPS", 12);
|
|
} else if (!((strstr(currmod, "PostScript")) ||
|
|
(strstr(currmod, "Postscript")) ||
|
|
(strstr(currmod, "POSTSCRIPT")))) {
|
|
memmove(currmod + strlen(currmod), ", PostScript", 13);
|
|
}
|
|
// Put data to stdout when "all" is chosen or when the manufacturer
|
|
// matches the given one.
|
|
if ((currfile) && ((all) || !strcasecmp(currmake,make)))
|
|
printf("%s|%s|%s|%s\n",currfile,currmake,currmod,currlang);
|
|
}
|
|
if (!lineprinted) {
|
|
// Fill empty entries with some default stuff
|
|
if (!currmod) currmod = "UNKNOWN";
|
|
if (!currmake) currmake = "UNKNOWN";
|
|
if (!currlang) currlang = "en";
|
|
// Remove the manufacturer's name from the model entries
|
|
makelen = strlen(currmake);
|
|
if (strcasecmp(currmake,"UNKNOWN") != 0) {
|
|
if (strncasecmp(currmake,currmod,makelen) == 0) {
|
|
currmod += makelen;
|
|
while ((*currmod == ' ') ||
|
|
(*currmod == '-') ||
|
|
(*currmod == '\t')) currmod ++;
|
|
}
|
|
}
|
|
// Make the manufacturer's name all-uppercase
|
|
currmake = strcpy(buffer,currmake);
|
|
for (i = 0; i < makelen; i ++) buffer[i] = toupper(buffer[i]);
|
|
// Clean up the driver info
|
|
currmod = strcpy(buffer2,currmod);
|
|
if (c = strstr(currmod, "Foomatic + Postscript")) {
|
|
memmove(c, "PostScript", 10);
|
|
memmove(c + 10, c + 21, strlen(c) - 20);
|
|
} else if (c = strstr(currmod, "Foomatic")) {
|
|
memmove(c + 11, c + 8, strlen(c) - 7);
|
|
memmove(c, "GhostScript", 11);
|
|
} else if (c = strstr(currmod, "CUPS+GIMP-print")) {
|
|
memmove(c + 17, c + 15, strlen(c) - 14);
|
|
memmove(c, "CUPS + GIMP-Print", 17);
|
|
} else if (c = strstr(currmod, "Series CUPS")) {
|
|
memmove(c + 12, c + 11, strlen(c) - 10);
|
|
memmove(c, "Series, CUPS", 12);
|
|
} else if (!((strstr(currmod, "PostScript")) ||
|
|
(strstr(currmod, "Postscript")) ||
|
|
(strstr(currmod, "POSTSCRIPT")))) {
|
|
memmove(currmod + strlen(currmod), ", PostScript", 13);
|
|
}
|
|
// Put data to stdout when "all" is chosen or when the manufacturer
|
|
// matches the given one.
|
|
if ((currfile) && ((all) || !strcasecmp(currmake,make)))
|
|
printf("%s|%s|%s|%s\n",currfile,currmake,currmod,currlang);
|
|
}
|
|
} else if (makelist) { // list all manufacturers
|
|
ppdlist = getPPDList();
|
|
if (!ppdlist) return 1;
|
|
for (attr = ppdlist->attrs, last = NULL; // go through all entries
|
|
attr != NULL;
|
|
attr = attr->next)
|
|
if (attr->name && strcmp(attr->name, "ppd-make") == 0)
|
|
// only search for manufacturerer entriees
|
|
if (last == NULL ||
|
|
strcasecmp(last->values[0].string.text,
|
|
attr->values[0].string.text) != 0)
|
|
// Do not take the same manufacturer twice
|
|
{
|
|
// Put found manufacturer to stdout
|
|
printf("%s\n",attr->values[0].string.text);
|
|
last = attr;
|
|
}
|
|
} else { // Help!
|
|
fprintf(stderr,"Usage:\n");
|
|
fprintf(stderr,"------\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," poll_ppd_base\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," This help page\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," poll_ppd_base -a\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," List all PPD files\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," poll_ppd_base -ml\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," List of all printer manufacturers supported by the PPD files installed\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," poll_ppd_base -m <manufacturers name>\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr," List of all supported printer models of this manufacturer\n");
|
|
fprintf(stderr,"\n");
|
|
fprintf(stderr,"ONLY WORKS WITH CUPS DAEMON RUNNING!\n");
|
|
fprintf(stderr,"\n");
|
|
return(1);
|
|
}
|
|
return(0);
|
|
}
|