home *** CD-ROM | disk | FTP | other *** search
- /*
- * "lpr" program for systems that don't have lpd but can talk to a system
- * that does using TCP or DECnet
- *
- * Copyright (C) 1990, 1991 Keith Moore
-
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 1,
- * as published by the Free Software Foundation.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Written by Keith Moore, December 1990
- * Email: moore@cs.utk.edu (Internet) moore@utkvx (BITNET)
- * Snail: Box 16320 / Knoxville TN 37996 / USA
- */
-
- /* TO DO:
- * - send troff font names
- * - add support for /etc/printcap files.
- * - special hacks for Imagen and/or PostScript printers (maybe)
- * - support -i (indent) and -w (page width) options
- * - handle huge files too big to read into memory (UNIX systems only)
- * - recognize ditroff, raster, cifplot, and FORTRAN output files (maybe)
- * - handle multiple lpd servers -- try each until we find one that's up.
- * - allow printer names of the form printer@host or host::printer,
- * - add an option to specify job-id (for use when using this program
- * as the back-end to another print spooling system -- you can keep the
- * job-ids the same on both systems if you're lucky).
- * - add an option to wait until the job is actually printed -- this is
- * not easy to do but is very useful when this program is being used
- * as the back-end to another kind of print spooler.
- */
-
- /*
- * #define MAIN_PROGRAM here so common.h will allocate storage for the
- * variables defined there instead of making them external references.
- */
-
- #define MAIN_PROGRAM
- #include "config.h"
- #include "common.h"
- #include "patchlevel.h"
- #include <stdio.h>
- #include <ctype.h>
-
- #ifdef unix
- #include <sys/types.h>
- #include <sys/stat.h>
- #define EXIT_OK 0
- #define EXIT_FAIL 1
- #endif
-
- #ifdef vms
- #include <types.h>
- #include <stat.h>
- #define EXIT_OK 0
- #define EXIT_FAIL 2
- #endif
-
- #define VERSION 1
-
- /*
- * options...not all of which are supported
- */
- char *printer; /* name of remote print queue */
- char *lpd_server; /* name of the remote printer server */
- char file_type = '?'; /* kind of file to be printed */
- char *title = NULL; /* page headings for pr */
- char *jobtitle = NULL; /* job name */
- char *jobclass = NULL; /* job class */
- int num_copies = 1; /* number of copies to print */
- int indent = 0; /* # of spaces to indent */
- int page_width = 72; /* page width for pr */
- char *fontnames[4]; /* names of troff fonts */
- int lflag = 0; /* if lpq, list in long format */
- int rflag = 0; /* if 1, remove file after spooling */
- int mflag = 0; /* if 1, send mail on completion */
- int hflag = 0; /* if 1, omit burst page */
-
- /* debug option flag is declared in common.h */
-
- #define min(a,b) ((a) < (b) ? (a) : (b))
- char *getenv ();
- char *calloc ();
- char *realloc ();
- char *strrchr ();
-
- /*
- * debugging routines
- */
-
- void
- dump_buf (fp, prefix, buf, size)
- FILE *fp; char *prefix; char *buf; unsigned size;
- {
- if (size > 0)
- fprintf (fp, "%s", prefix);
- while (size > 0){
- if (*buf >= ' ' && *buf <= '~')
- putc (*buf, fp);
- else if (*buf == '\n') {
- fprintf (fp, "\\n");
- if (size > 1)
- fprintf (fp, "\n%*s", strlen (prefix), "");
- }
- else
- fprintf (fp, "\\%03o", *buf & 0xff);
- ++buf;
- --size;
- }
- fprintf (fp, "\n");
- }
-
-
- int
- x_read (fd, buf, size)
- int fd; char *buf; unsigned size;
- {
- int nread = read (fd, (char *) buf, size);
- if (debug)
- dump_buf (stderr, "<<<", buf, nread);
- return nread;
- }
-
- int
- x_write (fd, buf, size)
- int fd; char *buf; unsigned size;
- {
- if (debug)
- dump_buf (stderr, ">>>", buf, size);
- return write (fd, (char *) buf, size);
- }
-
- int
- y_write (fd, buf, size)
- int fd; char *buf; unsigned size;
- {
- if (debug)
- fprintf (stderr, ">>> (%d bytes)\n", size);
- return write (fd, (char *) buf, size);
- }
-
-
- /*
- * parse an option with an optional argument (which may be NULL)
- * return 1 if optional argument used, else 0
- * (one of these days I'll start using getopt())
- */
- int
- real_option (opt, arg)
- char *opt; char *arg;
- {
- if (opt[1] && opt[2] == '\0') {
- /* single letter options */
- switch (opt[1]) {
- /*
- * file types
- */
- case 'l': /* text file with embedded control chars */
- file_type = 'l';
- lflag++; /* or -l (long) option for lpq */
- return 0;
- case 'f': /* Fortran output file with carraige control */
- file_type = 'r';
- return 0;
- case 'c': /* cifplot (Caltech Intermediate Form) file */
- case 'd': /* TeX .dvi file */
- case 'g': /* UNIX plot file */
- case 'n': /* ditroff output file */
- case 'o': /* PostScript file ??? */
- case 'p': /* text file (add page headers using pr) */
- case 't': /* C/A/T troff output file*/
- case 'v': /* Versatec output file */
- file_type = opt[1];
- return 0;
- /*
- * job options
- */
- case 'P': /* -P printer */
- case 'q': /* -q queue (same thing) */
- printer = arg;
- return 1;
- case 'S': /* specify name of printer server */
- lpd_server = arg;
- return 1;
- case '#': /* num copies */
- if (arg && isdigit (*arg)) {
- num_copies = atoi (arg);
- return 1;
- }
- break;
- case 'C': /* job class (default: local hostname) */
- jobclass = arg;
- return 1;
- case 'J': /* job title (default: first file name) */
- jobtitle = arg;
- return 1;
- case 'i': /* indent output (default: 8 chars) */
- if (arg && isdigit (*arg)) {
- indent = atoi (arg);
- return 1;
- }
- else {
- indent = 8;
- return 0;
- }
- case '1': /* troff font names */
- case '2':
- case '3':
- case '4':
- fontnames[opt[1]-'1']=arg;
- return 1;
- case 'w': /* cols -- page width for pr */
- if (arg && isdigit (*arg)) {
- page_width = atoi (arg);
- return 1;
- }
- case 'r': /* remove file after spooling */
- rflag = 1;
- return 0;
- case 'm': /* send mail upon completion */
- mflag = 1;
- return 0;
- case 'h': /* don't print the burst page */
- hflag = 1;
- return 0;
- case 's': /* don't copy file -- symlink it */
- fprintf (stderr,
- "lpr: The -s (symlink) option is not supported\n");
- fprintf (stderr,
- "All files will be copied to the remote server\n");
- return 0;
- }
- }
- if (strcmp (opt, "-debug") == 0) {
- debug = 1;
- fprintf (stderr, "standalone lpr version %d.%d\n",
- VERSION, PATCHLEVEL);
- return 0;
- }
- fprintf (stderr, "lpr: warning: illegal option %s\n", opt);
- return 0;
- }
-
- int
- option (opt, optarg)
- char *opt; char *optarg;
- {
- /*
- * This hack is used to notice whether the argument for an option
- * is appended to the option itself (e.g. "-Pprinter" rather than
- * "-P" "printer". If this is the case, and the option accepts an
- * argument, split the arg into two args and call real_option().
- * otherwise just pass our args to real_option().
- */
-
- if (opt[2] && strchr ("SP#CJTi1234qw", opt[1])) {
- char temp[3];
- temp[0] = '-';
- temp[1] = opt[1];
- temp[2] = '\0';
- real_option (temp, opt + 2);
- return 0;
- }
- else
- return real_option (opt, optarg);
- }
-
- /*
- * keep up with files to be deleted (for when using -r)
- * This is so we don't delete files until we *know* that the job
- * has been successfully submitted.
- */
-
- struct delete_list {
- char *name;
- struct delete_list *next;
- } *head = NULL;
-
- void
- mark_for_delete (name)
- char *name;
- {
- struct delete_list *ptr = (struct delete_list *)
- calloc (1, sizeof (struct delete_list));
- if (!ptr) {
- perror ("calloc");
- return;
- }
- ptr->next = head;
- ptr->name = name;
- head = ptr;
- }
-
- void
- delete_marked_files ()
- {
- struct delete_list *ptr;
- for (ptr = head; ptr; ptr=ptr->next) {
- if (ptr->name)
- if (unlink (ptr->name) < 0) {
- fprintf (stderr, "lpr: could not delete %s\n", ptr->name);
- perror ("unlink");
- }
- }
- }
-
- /*
- * buffer management
- */
- struct buffer {
- char *ptr; /* points to current append point */
- int size; /* how big is the buffer now? */
- char text[1]; /* (extensible) array of bytes in the buffer */
- };
-
- /*
- * Create an empty buffer
- */
-
- struct buffer *
- create_buffer (initial_size)
- unsigned int initial_size;
- {
- struct buffer *buf;
-
- if (initial_size <= 0)
- initial_size = 1000;
- if ((buf = (struct buffer *)
- calloc (1, sizeof (struct buffer) + initial_size - 1)) == NULL)
- return NULL;
- buf->ptr = &(buf->text[0]);
- buf->size = initial_size;
- return buf;
- }
-
- /*
- * Ensure there is enough room in the buffer for "more" more bytes
- */
- struct buffer *
- enlarge_buffer (buf, more)
- struct buffer *buf;
- int more;
- {
- int offset = buf->ptr - &(buf->text[0]);
- int spaceleft = buf->size - offset;
-
- if (more > spaceleft) {
- int newsize = sizeof (struct buffer) + (buf->size * 2) - 1;
- buf = (struct buffer *) realloc ((char *) buf, newsize);
- if (buf == NULL) {
- perror ("enlarge_buffer(): realloc failed");
- return NULL;
- }
- buf->ptr = &(buf->text[0]) + offset;
- buf->size = newsize;
- }
- return buf;
- }
-
- /*
- * Append up to max_size bytes from an open file to buffer
- */
-
- struct buffer *
- read_file_into_buffer (buf, fd, max_size)
- struct buffer *buf;
- int fd;
- unsigned max_size;
- {
- int real_size = 0;
-
- while (max_size > 0) {
- int foo = min (max_size, max_net_read);
- if ((buf = enlarge_buffer (buf, foo)) == NULL)
- return NULL;
- if ((foo = read (fd, buf->ptr, foo)) < 0)
- return NULL;
- if (foo == 0)
- break;
- buf->ptr += foo;
- max_size -= foo;
- real_size += foo;
- }
- return buf;
- }
-
- /*
- * Append a NUL-terminated string to the buffer
- */
-
- struct buffer *
- append_string_to_buffer (buf, string, length)
- struct buffer *buf;
- char *string;
- int length;
- {
- if ((buf = enlarge_buffer (buf, length)) == NULL) {
- fprintf (stderr, "lpr: file too big to fit in memory\n");
- exit (EXIT_FAIL);
- }
- strncpy (buf->ptr, string, length);
- buf->ptr += length;
- return buf;
- }
-
- /*
- * Write out the entire contents of buffer to the file fd.
- */
-
- int
- send_file_from_buffer (fd, buf)
- int fd; struct buffer *buf;
- {
- char *wptr = buf->text;
- while (wptr < buf->ptr) {
- unsigned int foo = min (buf->ptr - wptr, max_net_write);
- if ((foo = y_write (fd, wptr, foo)) < 0)
- return EOF;
- wptr += foo;
- }
- return 0;
- }
-
- /*
- * free up a buffer
- */
-
- void
- free_buffer (buf)
- struct buffer *buf;
- {
- if (buf)
- cfree (buf);
- }
-
- int
- buffer_size (buf)
- struct buffer *buf;
- {
- if (buf)
- return (buf->ptr - buf->text);
- return EOF;
- }
-
- /*
- * Look at a file buffer and guess what kind of file it is. This is called
- * when we aren't given an explicit file type option.
- */
-
- char
- guess_file_type (buf, fname)
- struct buffer *buf; char *fname;
- {
- char *ptr = buf->text;
- if (ptr[0] == '%' && ptr[1] == '!')
- return 'f'; /* print PostScript as plain file */
- if (ptr[0] == '\367' && ptr[1] == 2) {
- fprintf (stderr, "lpr: %s is a TeX .dvi file, assuming -d\n", fname);
- return 'd'; /* TeX .dvi file */
- }
- if (ptr[0] == '\100' && ptr[1] == '\357') {
- fprintf (stderr, "lpr: %s is a C/A/T troff output file, assuming -t\n",
- fname);
- return 't'; /* C/A/T troff file */
- }
- return 'f'; /* default file type is plain file */
- }
-
- int
- check_for_bogus_file (buf, type, filename)
- struct buffer *buf; char type; char *filename;
- {
- char *ptr = buf->text;
-
- if (buf->ptr == buf->text) {
- fprintf (stderr, "lpr: skipping zero-length file %s\n", filename);
- return EOF;
- }
-
- if (ptr[0] == '\037' && ptr[1] == '\235') {
- fprintf (stderr, "lpr: %s is a compressed file -- ignoring it\n",
- filename);
- return EOF;
- }
- if (type == 'd') {
- if (ptr[0] == '\367' && ptr[1] == '\002') {
- /* sometimes .dvi files have trailing NULs when they
- shouldn't have. Remove these from the buffer and
- check that the .dvi file ends with a \337 byte. */
- if (buf->ptr[-1] == '\0') {
- while (buf->ptr[-1] == '\0')
- --(buf->ptr);
- }
- if (buf->ptr[-1] == '\337')
- return 0;
- }
- fprintf (stderr, "lpr: %s is not a valid .dvi file", filename);
- return EOF;
- }
- if (memcmp (ptr, "!<arch>\n", 8) == 0) {
- fprintf (stderr, "lpr: %s is a UNIX library archive -- ignoring it",
- filename);
- return EOF;
- }
- return 0;
- }
-
-
- /*
- * Send a command to the remote server and wait for a response. Return
- * the first byte of the response, or EOF on error.
- */
-
- int
- send_command (fd, buf, size)
- int fd; char *buf; unsigned int size;
- {
- char x[1];
- if (x_write (fd, buf, size) != size)
- return EOF;
- if (x_read (fd, x, 1) != 1)
- return EOF;
- return *x;
- }
-
-
- /*
- * structure used to keep track of print jobs
- */
- struct job {
- int jobid; /* integer job id 1-999 */
- int fd; /* fd of lpd socket */
- int control_file_number; /* current file number */
- int data_file_number; /* data_file_number */
- struct buffer *cfile; /* buffer to build control file */
- };
-
- /*
- * add a record to a control file
- */
- void
- control (job, cmd, arg)
- struct job *job; char cmd; char *arg;
- {
- char buf[512];
- sprintf (buf, "%c%s\n", cmd, arg);
- job->cfile = append_string_to_buffer (job->cfile, buf, strlen (buf));
- }
-
-
- /*
- * create a print job. Return a job ptr on success or NULL on error.
- */
- struct job *
- open_job (queuename)
- char *queuename;
- {
- struct job *job;
- char buf[512];
- char x;
-
- if ((job = (struct job *) calloc (1, sizeof (struct job))) == NULL)
- return NULL;
- /*
- * generate a job #. Really, this should be maintained on a
- * per-(host,queue) basis, so we won't have naming conflicts.
- * for now, we just generate something pseudo-random.
- */
- job->jobid = time (0) % 1000;
- job->fd = open_lpd (lpd_server);
- if (job->fd < 0) {
- free (job);
- return NULL;
- }
-
- sprintf (buf, "\2%s\n", queuename);
- if ((x = send_command (job->fd, buf, strlen (buf))) != 0) {
- if (isprint (x)) {
- int foo;
- *buf = x;
- foo = x_read (job->fd, buf+1, sizeof(buf)-1);
- fprintf (stderr,
- "lpr: server %s refused job with message:\n",
- lpd_server);
- fprintf (stderr, "%.*s", foo+1, buf);
- }
- else {
- fprintf (stderr,
- "lpr: server %s refused job for printer %s\n",
- lpd_server, queuename);
- }
- close (job->fd);
- free (job);
- return NULL;
- }
-
- job->control_file_number = 0;
- job->data_file_number = 0;
- job->cfile = create_buffer (1000);
-
- control (job, 'H', hostname);
- control (job, 'P', username);
- if (hflag == 0) {
- control (job, 'J', jobtitle);
- control (job, 'C', jobclass);
- }
- control (job, 'L', username);
- if (title)
- control (job, 'T', title);
- if (mflag)
- control (job, 'M', email_address);
- return job;
- }
-
- void
- concoct_file_name (c, job, str)
- char c; struct job *job; char *str;
- {
- int x = c == 'd' ? job->data_file_number++ : job->control_file_number++;
- sprintf (str, "%cf%c%03d%s", c,
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"[x],
- job->jobid, hostname);
- }
-
- /*
- * Send a file to be printed. Return 1 on success and 0 on error.
- * (i.e. # of files sent).
- * print diagnostic messages to stderr as necessary
- * If file == NULL, print standard input
- */
- int
- send_print_file (job, file, file_type)
- struct job *job; char *file; char file_type;
- {
- int estimated_size; /* how big we think the file is */
- int max_size; /* max size to print */
- int real_size;
- int fd = EOF; /* fd of file */
- struct buffer *dfile = NULL; /* buffer to read file into */
- char *reason = NULL; /* reason file xfer failed */
- char data_file_name[512]; /* name of temporary data file */
- char buf[512];
- int x;
- int i;
-
- /*
- * open the file and find out how big it is
- * estimated_size is used to determine how much space to allocate.
- * max_size is used to decide how much to read in. Under VMS
- * we don't ever want to read too much, because we might get
- * unwanted garbage at the end of a fixed-length record file.
- */
- if (file) {
- struct stat sbuf;
- if (stat (file, &sbuf) < 0) {
- perror (file);
- return 0;
- }
- max_size = estimated_size = sbuf.st_size;
- if ((fd = open (file, 0)) < 0) {
- perror (file);
- return 0;
- }
- }
- else {
- struct stat sbuf;
- file = "standard input"; /* for page headers, error messages */
- estimated_size = 64000;
- max_size = 5*1024*1024; /* 5 megabytes */
- fd = 0;
- #ifdef unix
- /*
- * UNIX-specific performance optimization:
- * If standard input is an ordinary file, get size estimate
- * with fstat()
- */
- if (fstat (fd, &sbuf) < 0) {
- if ((sbuf.st_mode & S_IFMT) == S_IFREG)
- estimated_size = sbuf.st_size;
- }
- #endif
- }
-
- /*
- * create a buffer and read the file into it.
- */
- concoct_file_name ('d', job, data_file_name);
- if ((dfile = create_buffer (estimated_size)) == NULL) {
- reason = "file too big to fit in memory";
- goto abort;
- }
- if ((dfile = read_file_into_buffer (dfile, fd, max_size)) == NULL) {
- reason = "error reading file";
- goto abort;
- }
-
- /*
- * file transfer successful. Add this file to the print job,
- * clean up, and return.
- */
- if (file_type == '?')
- file_type = guess_file_type (dfile, file);
- /*
- * check for bogus file formats. Refuse to print anything that
- * is obviously bogus.
- */
- if (check_for_bogus_file (dfile, file_type, file))
- goto okay;
-
- /*
- * transfer the file to the server, with error checking
- */
- sprintf (buf, "\3%d %s\n", buffer_size(dfile), data_file_name);
- if ((x = send_command (job->fd, buf, strlen (buf))) != 0) {
- switch (x) {
- case 1:
- break;
- case 2:
- reason = "not enough disk space on server (or file is too large)";
- break;
- case EOF:
- reason = "connection to printer server broken";
- break;
- default:
- if (isprint (x)) {
- *buf = x;
- x = x_read (job->fd, buf + 1, sizeof (buf) - 1);
- buf[x+1] = '\0';
- reason = buf;
- }
- }
- goto abort;
- }
- if (send_file_from_buffer (job->fd, dfile) != 0)
- goto abort;
- if (send_command (job->fd, "", 1) < 0)
- goto abort;
-
- if (file_type == 'p' && !title)
- control (job, 'P', file);
- for (i = 0; i < num_copies; ++i)
- control (job, file_type, data_file_name);
- control (job, 'U', data_file_name);
- control (job, 'N', file);
- okay:
- free_buffer (dfile);
- close (fd);
- return 1;
-
-
- /*
- * file transfer failed. print error message and clean up
- */
- abort:
- fprintf (stderr, "lpr: unable to send file %s to print server %s\n",
- file, lpd_server);
- if (reason)
- fprintf (stderr, "reason: %s\n", reason);
- if (dfile)
- free_buffer (dfile);
- if (fd > 0)
- close (fd);
- return 0;
- }
-
- /*
- * send the control file. Return 0 on success, nonzero on error.
- */
- send_control_file (job)
- struct job *job;
- {
- char buf[512];
- char control_file_name[512];
-
- concoct_file_name ('c', job, control_file_name);
- sprintf (buf, "\2%d %s\n", job->cfile->ptr - job->cfile->text,
- control_file_name);
- if (send_command (job->fd, buf, strlen (buf)) < 0)
- return 1;
- if (send_file_from_buffer (job->fd, job->cfile) != 0)
- return 1;
- if (send_command (job->fd, "", 1) < 0)
- return 1;
- return 0;
- }
-
- /*
- * close a job normally and delete its resources
- */
- int
- close_job (job)
- struct job *job;
- {
- int x;
- if (job == NULL)
- return EOF;
- x = send_control_file (job);
- if (job->cfile)
- free_buffer (job->cfile);
- close (job->fd);
- cfree (job);
- return x;
- }
-
- /*
- * abort a job and delete its resources
- */
- void
- abort_job (job)
- struct job *job;
- {
- if (job == NULL)
- return;
- x_write (job->fd, "\1\n", 2);
- close (job->fd);
- if (job->cfile)
- free_buffer (job->cfile);
- cfree (job);
- }
-
-
- char *
- get_lpd_server ()
- {
- FILE *fp;
- static char *buf[512];
-
- if ((fp = fopen ("/etc/LPD_SERVER", "r")) == (FILE *) NULL)
- return NULL;
- if (fscanf (fp, " %511s", buf) != 1)
- return NULL;
- return (char *) buf;
- }
-
-
- /*
- * Dummy main program exists to find out what name we are being called
- * by (under UNIX, anyway) and act appropriately. This program has
- * multiple personalities...
- */
-
- main (argc, argv)
- int argc; char **argv;
- {
- #ifdef unix
- char *progname = NULL;
- char *strrchr ();
- #endif
- char *p;
-
- /*
- * inherit some defaults from the environment
- */
-
- printer = getenv ("PRINTER");
- if (printer == NULL)
- printer = "lp";
- lpd_server = getenv ("LPD_SERVER");
- if (lpd_server == NULL)
- lpd_server = get_lpd_server ();
-
- sysdep ();
-
- #ifdef unix
- /*
- * look at the last component of the name we were invoked with
- * and determine how to behave.
- */
- progname = strrchr (argv[0], '/');
- if (progname == NULL)
- progname = argv[0];
- else
- progname++;
-
- if (strcmp (progname, "lpq") == 0)
- return (lpq (argc, argv));
- else if (strcmp (progname, "lprm") == 0)
- return (lprm (argc, argv));
- #endif
-
- /*
- * if first argument is -remove or -delete, behave as lprm
- * if first argumetn is -showqueue, behave as lpq
- */
-
- if (argc > 1) {
- if (strcmp (argv[1], "-remove") == 0)
- return (lprm (argc-1, argv+1));
- else if (strcmp (argv[1], "-delete") == 0)
- return (lprm (argc-1, argv+1));
- else if (strcmp (argv[1], "-showqueue") == 0)
- return (lpq (argc-1, argv+1));
- }
-
- return (lpr (argc, argv));
- }
-
- /*
- * queue one or more files for printing
- */
-
- lpr (argc, argv)
- int argc; char **argv;
- {
- struct job *job = NULL;
- int i;
- int file_args = 0;
- int files_printed = 0;
-
- jobclass = hostname;
- jobtitle = NULL;
-
- for (i = 1; i < argc; ++i) {
- if (*argv[i] == '-')
- i += option (argv[i], argv[i+1]);
- else {
- if (!jobtitle) {
- char *ptr = strrchr (argv[i], '/');
- jobtitle = ptr ? ptr + 1 : argv[i];
- }
- if (job == NULL && (job = open_job (printer)) == NULL)
- exit (EXIT_FAIL);
- file_args++;
- if (send_print_file (job, argv[i], file_type)) {
- files_printed++;
- if (rflag)
- mark_for_delete (argv[i]);
- }
- }
- }
- if (file_args == 0) {
- if (!jobtitle)
- jobtitle = "stdin";
- if ((job = open_job (printer)) == NULL)
- exit (EXIT_FAIL);
- files_printed += send_print_file (job, 0, file_type);
- }
- if (files_printed > 0) {
- if (close_job (job)) {
- delete_marked_files ();
- exit (EXIT_OK);
- }
- else
- exit (EXIT_FAIL);
- }
- else
- exit (EXIT_FAIL);
- exit (EXIT_OK);
- }
-
- /*
- * print contents of printer queue
- * "lpq -l" prints in long format
- */
-
- lpq (argc, argv)
- int argc; char **argv;
- {
- int i;
- char buf[512];
- int fd;
- int x;
-
- for (i = 1; i < argc ; ++i) {
- if (*argv[i] == '-')
- i += option (argv[i], argv[i+1]);
- else
- break;
- }
-
- if ((fd = open_lpd (lpd_server)) < 0)
- exit (EXIT_FAIL);
-
- if (lflag)
- sprintf (buf, "\004%s", printer);
- else
- sprintf (buf, "\003%s", printer);
-
- for (; i < argc; ++i) {
- strcat (buf, " ");
- strcat (buf, argv[i]);
- }
-
- strcat (buf, "\n");
- if (x_write (fd, buf, strlen (buf)) != 0) {
- while ((x = x_read (fd, buf, sizeof buf)) > 0)
- fwrite (buf, sizeof (char), x, stdout);
- }
- close (fd);
- return 0;
- }
-
- /*
- * remove jobs from queue
- */
-
- lprm (argc, argv)
- int argc; char **argv;
- {
- int fd;
- int i;
- char buf[512];
- int x;
- int response_length = 0;
- int remove_all = 0;
-
- for (i = 1; i < argc; ++i) {
- if (strcmp (argv[i], "-") == 0)
- remove_all++;
- else if (*argv[i] == '-')
- i += option (argv[i], argv[i+1]);
- else
- break;
- }
-
- if ((fd = open_lpd (lpd_server)) < 0)
- exit (EXIT_FAIL);
-
- /*
- * If user asks to remove all queued files with "lprm -",
- * need to check to see if user is privileged to do so.
- * Allow root to remove all queued files, but any other
- * user will just remove his/her own queued files.
- * (remote server will only delete files queued by this system)
- *
- * "-all" is a magic user name which means delete all
- * entries from this system.
- */
- if (remove_all) {
- #ifdef unix
- if (strcmp (username, "root") == 0)
- sprintf (buf, "\005%s %s", printer, "-all");
- else
- sprintf (buf, "\005%s %s %s", printer, username, username);
- #else
- sprintf (buf, "\005%s %s %s", printer, username, username);
- #endif
- }
- else {
- sprintf (buf, "\005%s %s", printer, username);
- }
-
- for (; i < argc; ++i) {
- strcat (buf, " ");
- strcat (buf, argv[i]);
- }
- strcat (buf, "\n");
- if (x_write (fd, buf, strlen (buf)) != 0) {
- while ((x = x_read (fd, buf, sizeof buf)) > 0) {
- fwrite (buf, sizeof (char), x, stdout);
- response_length += x;
- }
- }
- close (fd);
-
- /* If response_length is zero, assume the remove command failed.
- Otherwise we should have received some confirmation message */
-
- if (response_length == 0)
- return 1;
- return 0;
- }
-