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.
tdelibs/tdeprint/cups/cupsdoprint.c

258 lines
5.7 KiB

/*
* This file is part of the KDE libraries
* Copyright (c) 2001 Michael Goffioul <tdeprint@swing.be>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License version 2 as published by the Free Software Foundation.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
**/
#include <config.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <cups/cups.h>
#include <cups/ipp.h>
#define BUFSIZE 1024
#define BUFSIZE2 32
#define USE_LOG 0
/* global variables */
char passwd[BUFSIZE2] = {0};
int pwd_asked = 0;
#if USE_LOG
FILE *debugF = NULL;
#endif
/* utility functions */
static void error(const char* msg)
{
fprintf(stderr, "%s\n", msg);
#if USE_LOG
if (debugF != NULL) fclose(debugF);
#endif
exit(-1);
}
static void usage()
{
error("usage: cupsdoprint [-H host[:port]][-P dest][-J name][-o opt=value[,...]][-U login[:password]] files...");
}
static char * shell_quote(const char *s)
{
char *result;
char *p;
p = result = malloc(strlen(s)*4+3);
*p++ = '\'';
while(*s)
{
if (*s == '\'')
{
*p++ = '\'';
*p++ = '\\';
*p++ = '\'';
*p++ = '\'';
s++;
}
else
{
*p++ = *s++;
}
}
*p++ = '\'';
*p = '\0';
return result;
}
static const char* getPasswordCB(const char* prompt)
{
char buf[ 256 ] = {0}, *c;
char *_user = shell_quote( cupsUser() ), *_passwd = NULL;
FILE *output;
snprintf( buf, sizeof( buf )-1, "dcop kded tdeprintd requestPassword %s %s %d %d",
_user,
cupsServer(),
ippPort(),
pwd_asked );
free( _user );
_user = NULL;
output = popen( buf, "r" );
if ( output != NULL )
{
while ( fgets( buf, sizeof( buf )-1, output ) )
{
_user = _passwd = NULL;
if ( strcmp( buf, "::" ) != 0 )
{
c = strchr( buf, ':' );
if ( c != NULL )
{
*c = '\0';
_user = buf;
_passwd = ++c;
c = strchr( c, ':' );
if ( c != NULL )
{
*c = '\0';
/* retrieve password sequence number */
pwd_asked = atoi( ++c );
/* update CUPS with current username */
cupsSetUser( _user );
/* copy password to a non temporary location */
strlcpy( passwd, _passwd, BUFSIZE2 );
_passwd = passwd;
}
else
_passwd = NULL;
}
}
}
pclose( output );
}
else
return NULL;
/* erase buffer containing unencrypted password, for security */
memset( buf, 0, 256 );
/* if OK, _passwd should point to global passwd variable, otherwise it should be NULL */
return _passwd;
}
/* main function */
int main(int argc, char* argv[])
{
int c, port = -1;
char printer[BUFSIZE] = {0}, jobname[BUFSIZE] = {0}, host[BUFSIZE] = {0};
char login[BUFSIZE2] = {0};
char *a;
cups_option_t *options = NULL;
int num_options = 0;
const char* files[100] = {0};
int num_files = 0;
int jobID = 0;
#if USE_LOG
debugF = fopen("/tmp/cupsdoprint.debug","w");
if (debugF == NULL)
error("unable to open log file");
#endif
while ((c=getopt(argc, argv, "P:J:H:o:U:?")) != -1)
{
#if USE_LOG
fprintf(debugF,"%c: %s\n",c,optarg);
#endif
switch (c)
{
case 'P':
strlcpy(printer, optarg, BUFSIZE);
if ((a=strchr(printer, '/')) != NULL)
error("This utility doesn't support printer instances");
break;
case 'J':
strlcpy(jobname, optarg, BUFSIZE);
break;
case 'H':
strlcpy(host, optarg, BUFSIZE);
if ((a=strchr(host, ':')) != NULL)
{
*a = 0;
port = atoi(++a);
if (port == 0)
error("Wrong port value");
}
break;
case 'U':
strlcpy(login, optarg, BUFSIZE2);
if ((a=strchr(login, ':')) != NULL)
{
*a = 0;
strlcpy(passwd, ++a, BUFSIZE2);
}
break;
case 'o':
#if USE_LOG
fprintf(debugF,"Parsing options (n=%d)\n",num_options);
#endif
num_options = cupsParseOptions(optarg, num_options, &options);
#if USE_LOG
fprintf(debugF,"Options parsed (n=%d)\n",num_options);
#endif
break;
case '?':
default:
usage();
break;
}
}
/* check the printer */
if (!*printer)
{
printer[BUFSIZE-1] = '\0';
if (getenv("PRINTER") != NULL)
strlcpy(printer, getenv("PRINTER"), BUFSIZE-1);
else
error("No printer specified (and PRINTER variable is empty)");
}
/* CUPS settings */
if (host[0] != 0) cupsSetServer(host);
if (port > 0) ippSetPort(port);
if (login[0] != 0) cupsSetUser(login);
if (jobname[0] == 0) strcpy(jobname,"TDE Print System");
cupsSetPasswordCB(getPasswordCB);
/* check for files */
if (optind < 1 || optind >= argc)
error("This utility doesn't support printing from STDIN");
else
for (c=optind; c<argc; c++)
{
if (access(argv[c], R_OK) != 0)
{
fprintf(stderr, "%s: ", argv[c]);
error("file not found or not readable");
}
else
files[num_files++] = strdup(argv[c]);
}
#if USE_LOG
fprintf(debugF,"Processed options:\n");
for (c=0; c<num_options; c++)
fprintf(debugF,"%s = %s\n",options[c].name,options[c].value);
#endif
/* print files */
jobID = cupsPrintFiles(printer, num_files, files, jobname, num_options, options);
/* erase unemcrypted password for security */
memset( passwd, 0, BUFSIZE2 );
/* check job creation status */
if (jobID <= 0)
error(ippErrorString(cupsLastError()));
#if USE_LOG
fclose(debugF);
#endif
return 0;
}