/*
- * "$Id: lpd.c,v 1.18 2000/03/21 04:03:23 mike Exp $"
+ * "$Id: lpd.c,v 1.19 2000/04/19 21:25:57 mike Exp $"
*
* Line Printer Daemon backend for the Common UNIX Printing System (CUPS).
*
* Send the command...
*/
+ fprintf(stderr, "DEBUG: Sending command string (%d bytes)...\n", bytes);
+
if (send(fd, buf, bytes, 0) < bytes)
return (-1);
* Read back the status from the command and return it...
*/
+ fprintf(stderr, "DEBUG: Reading command status...\n");
+
if (recv(fd, &status, 1, 0) < 1)
return (-1);
break;
}
+ fprintf(stderr, "INFO: Connected on port %d...\n", port);
+
/*
* Next, open the print file and figure out its size...
*/
/*
- * End of "$Id: lpd.c,v 1.18 2000/03/21 04:03:23 mike Exp $".
+ * End of "$Id: lpd.c,v 1.19 2000/04/19 21:25:57 mike Exp $".
*/
-H1 { font-family: sans-serif; }
-H2 { font-family: sans-serif; }
+H1 { font-family: sans-serif }
+H2 { font-family: sans-serif }
TH { text-align: left }
+
/*
- * "$Id: form-tree.c,v 1.2 2000/04/18 19:41:11 mike Exp $"
+ * "$Id: form-tree.c,v 1.3 2000/04/19 21:25:58 mike Exp $"
*
* CUPS form document tree routines for the Common UNIX Printing
* System (CUPS).
#include "form.h"
+/*
+ * Local functions...
+ */
+
+static int compare_attr(attr_t *a0, attr_t *a1);
+static int compare_elements(char **e0, char **e1);
+static int parse_attr(tree_t *t, FILE *fp);
+static int parse_element(tree_t *t, FILE *fp);
+
+
+/*
+ * Local globals...
+ */
+
+static char *elements[] =
+ {
+ "",
+ "!--",
+ "ARC",
+ "BOX",
+ "BR",
+ "B",
+ "CUPSFORM",
+ "DEFVAR",
+ "FONT",
+ "H1",
+ "H2",
+ "H3",
+ "H4",
+ "H5",
+ "H6",
+ "HEAD",
+ "IMG",
+ "I",
+ "LINE",
+ "PAGE",
+ "PIE",
+ "POLY",
+ "PRE",
+ "P",
+ "RECT",
+ "TEXT",
+ "TT",
+ "VAR"
+ };
+
+
/*
* 'formDelete()' - Delete a node and its children.
*/
*/
tree_t * /* O - New tree node */
-formNew(element_t e, /* I - Element type */
- tree_t *p) /* I - Parent node */
+formNew(tree_t *p) /* I - Parent node */
{
+ tree_t *t; /* New tree node */
+
+
+ /*
+ * Allocate the new node...
+ */
+
+ if ((t = (tree_t *)calloc(sizeof(tree_t), 1)) == NULL)
+ return (NULL);
+
+ /*
+ * Set/copy attributes...
+ */
+
+ if (p == NULL)
+ {
+ t->bg[0] = 1.0;
+ t->bg[1] = 1.0;
+ t->bg[2] = 1.0;
+ t->halign = HALIGN_LEFT;
+ t->valign = VALIGN_MIDDLE;
+ t->typeface = "Courier";
+ t->size = 12.0;
+ }
+ else
+ {
+ memcpy(t, p, sizeof(tree_t));
+
+ t->prev = NULL;
+ t->next = NULL;
+ t->child = NULL;
+ t->last_child = NULL;
+ t->parent = NULL;
+ t->num_attrs = 0;
+ t->attrs = NULL;
+ t->data = NULL;
+ }
+
+ /*
+ * Return the new node...
+ */
+
+ return (t);
}
formRead(FILE *fp, /* I - File to read from */
tree_t *p) /* I - Parent node */
{
+ int ch, /* Character from file */
+ closech, /* Closing character */
+ have_whitespace; /* Leading whitespace? */
+ static char s[10240]; /* String from file */
+ uchar *ptr, /* Pointer in string */
+ glyph[16], /* Glyph name (&#nnn;) */
+ *glyphptr; /* Pointer in glyph string */
+ tree_t *tree, /* "top" of this tree */
+ *t, /* New tree node */
+ *prev, /* Previous tree node */
+ *temp; /* Temporary looping var */
+ uchar *face, /* Typeface for FONT tag */
+ *color, /* Color for FONT tag */
+ *size; /* Size for FONT tag */
+
+
+ /*
+ * Start off with no previous tree node...
+ */
+
+ prev = NULL;
+ tree = NULL;
+
+ /*
+ * Parse data until we hit end-of-file...
+ */
+
+ while ((ch = getc(fp)) != EOF)
+ {
+ /*
+ * Ignore leading whitespace...
+ */
+
+ have_whitespace = 0;
+ closech = '/';
+
+ if (p == NULL || !p->preformatted)
+ {
+ while (isspace(ch))
+ {
+ have_whitespace = 1;
+ ch = getc(fp);
+ }
+
+ if (ch == EOF)
+ break;
+ }
+
+ /*
+ * Allocate a new tree node - use calloc() to get zeroed data...
+ */
+
+ t = formNew(p);
+
+ /*
+ * See what the character was...
+ */
+
+ if (ch == '<')
+ {
+ /*
+ * Markup char; grab the next char to see if this is a /...
+ */
+
+ ch = getc(fp);
+ if (ch == ' ')
+ {
+ /*
+ * Illegal lone "<"! Ignore it...
+ */
+
+ free(t);
+ continue;
+ }
+
+ if (ch != '/')
+ ungetc(ch, fp);
+
+ if (parse_element(t, fp) < 0)
+ {
+ free(t);
+ break;
+ }
+
+ if ((closech = getc(fp)) == '/')
+ getc(fp);
+
+ /*
+ * If this is the matching close mark, or if we are starting the same
+ * element, or if we've completed a list, we're done!
+ */
+
+ if (ch == '/')
+ {
+ /*
+ * Close element; find matching element...
+ */
+
+ for (temp = p; temp != NULL; temp = temp->p)
+ if (temp->element == t->element)
+ break;
+
+ free(t);
+
+ if (temp != NULL)
+ break;
+ else
+ continue;
+ }
+ }
+ else if (t->preformatted)
+ {
+ /*
+ * Read a pre-formatted string into the current tree node...
+ */
+
+ ptr = s;
+ while (ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
+ {
+ if (ch == '&')
+ {
+ for (glyphptr = glyph;
+ (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
+ glyphptr ++)
+ if (!isalnum(ch))
+ break;
+ else
+ *glyphptr = ch;
+
+ *glyphptr = '\0';
+ if (atoi(glyph) > 0)
+ ch = atoi(glyph);
+ else if (strcmp(glyph, "lt") == 0)
+ ch = '<';
+ else if (strcmp(glyph, "gt") == 0)
+ ch = '>';
+ else if (strcmp(glyph, "quot") == 0)
+ ch = '\'';
+ else if (strcmp(glyph, "nbsp") == 0)
+ ch = ' ';
+ else
+ ch = '&';
+ }
+
+ if (ch != 0)
+ *ptr++ = ch;
+
+ if (ch == '\n')
+ break;
+
+ ch = getc(fp);
+ }
+
+ *ptr = '\0';
+
+ if (ch == '<')
+ ungetc(ch, fp);
+
+ t->element = ELEMENT_FRAGMENT;
+ t->data = strdup(s);
+ }
+ else
+ {
+ /*
+ * Read the next string fragment...
+ */
+
+ ptr = s;
+ if (have_whitespace)
+ *ptr++ = ' ';
+
+ while (!isspace(ch) && ch != '<' && ch != EOF && ptr < (s + sizeof(s) - 1))
+ {
+ if (ch == '&')
+ {
+ for (glyphptr = glyph;
+ (ch = getc(fp)) != EOF && (glyphptr - glyph) < 15;
+ glyphptr ++)
+ if (!isalnum(ch))
+ break;
+ else
+ *glyphptr = ch;
+
+ *glyphptr = '\0';
+ if (atoi(glyph) > 0)
+ ch = atoi(glyph);
+ else if (strcmp(glyph, "lt") == 0)
+ ch = '<';
+ else if (strcmp(glyph, "gt") == 0)
+ ch = '>';
+ else if (strcmp(glyph, "quot") == 0)
+ ch = '\'';
+ else if (strcmp(glyph, "nbsp") == 0)
+ ch = ' ';
+ else
+ ch = '&';
+ }
+
+ if (ch != 0)
+ *ptr++ = ch;
+
+ ch = getc(fp);
+ }
+
+ if (isspace(ch))
+ *ptr++ = ' ';
+
+ *ptr = '\0';
+
+ if (ch == '<')
+ ungetc(ch, fp);
+
+ t->element = ELEMENT_FRAGMENT;
+ t->data = strdup(s);
+ }
+
+ /*
+ * If the p tree pointer is not NULL and this is the first
+ * entry we've read, set the child pointer...
+ */
+
+ if (p != NULL && prev == NULL)
+ p->child = t;
+
+ if (p != NULL)
+ p->last_child = t;
+
+ /*
+ * Do the prev/next links...
+ */
+
+ t->parent = p;
+ t->prev = prev;
+ if (prev != NULL)
+ prev->next = t;
+ else
+ tree = t;
+
+ prev = t;
+
+ /*
+ * Do child stuff as needed...
+ */
+
+ if (closech == '>')
+ t->child = formRead(t, fp);
+ }
+
+ return (tree);
}
/*
- * End of "$Id: form-tree.c,v 1.2 2000/04/18 19:41:11 mike Exp $".
+ * 'compare_attr()' - Compare two attributes.
+ */
+
+static int /* O - -1 if a0 < a1, etc. */
+compare_attr(attr_t *a0, /* I - First attribute */
+ attr_t *a1) /* I - Second attribute */
+{
+ return (strcasecmp(a0->name, a1->name));
+}
+
+
+/*
+ * 'compare_elements()' - Compare two elements.
+ */
+
+static int /* O - -1 if e0 < e1, etc. */
+compare_elements(char **e0, /* I - First element */
+ char **e1) /* I - Second element */
+{
+ return (strcasecmp(*e0, *e1));
+}
+
+
+/*
+ * 'parse_attr()' - Parse an element attribute string.
+ */
+
+static int /* O - -1 on error, 0 on success */
+parse_attr(tree_t *t, /* I - Current tree node */
+ FILE *fp) /* I - Input file */
+{
+ char name[1024], /* Name of attr */
+ value[10240], /* Value of attr */
+ *ptr; /* Temporary pointer */
+ int ch; /* Character from file */
+
+
+ ptr = name;
+ while ((ch = getc(fp)) != EOF)
+ if (isalnum(ch))
+ {
+ if (ptr < (name + sizeof(name) - 1))
+ *ptr++ = ch;
+ }
+ else
+ break;
+
+ *ptr = '\0';
+
+ while (isspace(ch) || ch == '\r')
+ ch = getc(fp);
+
+ switch (ch)
+ {
+ default :
+ ungetc(ch, fp);
+ return (formSetAttr(t, name, NULL));
+ case EOF :
+ return (-1);
+ case '=' :
+ ptr = value;
+ ch = getc(fp);
+
+ while (isspace(ch) || ch == '\r')
+ ch = getc(fp);
+
+ if (ch == EOF)
+ return (-1);
+
+ if (ch == '\'')
+ {
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\'')
+ break;
+ else if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = ch;
+
+ *ptr = '\0';
+ }
+ else if (ch == '\"')
+ {
+ while ((ch = getc(fp)) != EOF)
+ if (ch == '\"')
+ break;
+ else if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = ch;
+
+ *ptr = '\0';
+ }
+ else
+ {
+ *ptr++ = ch;
+ while ((ch = getc(fp)) != EOF)
+ if (isspace(ch) || ch == '>' || ch == '/' || ch == '\r')
+ break;
+ else if (ptr < (value + sizeof(value) - 1))
+ *ptr++ = ch;
+
+ *ptr = '\0';
+ if (ch == '>' || ch == '/')
+ ungetc(ch, fp);
+ }
+
+ return (formSetAttr(t, name, value));
+ }
+}
+
+
+/*
+ * 'parse_element()' - Parse an element.
+ */
+
+static int /* O - -1 on error or ELEMENT_nnnn */
+parse_element(tree_t *t, /* I - Current tree node */
+ FILE *fp) /* I - Input file */
+{
+ int ch; /* Character from file */
+ char element[255], /* Element string... */
+ *eptr, /* Current character... */
+ comment[10240], /* Comment string */
+ *cptr, /* Current char... */
+ **temp; /* Element variable entry */
+
+
+ eptr = element;
+
+ while ((ch = getc(fp)) != EOF && eptr < (element + sizeof(element) - 1))
+ if (ch == '>' || ch == '/' || isspace(ch))
+ break;
+ else
+ *eptr++ = ch;
+
+ *eptr = '\0';
+
+ if (ch == EOF)
+ return (ELEMENT_ERROR);
+
+ eptr = element;
+ temp = bsearch(&mptr, elements, sizeof(elements) / sizeof(elements[0]),
+ sizeof(elements[0]),
+ (int (*)(const void *, const void *))compare_elements);
+
+ if (temp == NULL)
+ {
+ /*
+ * Unrecognized element stuff...
+ */
+
+ t->element = ELEMENT_COMMENT;
+ strcpy(comment, element);
+ cptr = comment + strlen(comment);
+ }
+ else
+ {
+ t->element = (element_t)((char **)temp - elements);
+ cptr = comment;
+ }
+
+ if (t->element == ELEMENT_COMMENT)
+ {
+ while (ch != EOF && ch != '>' && cptr < (comment + sizeof(comment) - 1))
+ {
+ *cptr++ = ch;
+ ch = getc(fp);
+ }
+
+ *cptr = '\0';
+ t->data = strdup(comment);
+ }
+ else
+ {
+ while (ch != EOF && ch != '>' && ch != '/')
+ {
+ if (!isspace(ch))
+ {
+ ungetc(ch, fp);
+ parse_variable(t, fp);
+ }
+
+ ch = getc(fp);
+ }
+
+ if (ch != EOF)
+ ungetc(ch, fp);
+ }
+
+ return (t->element);
+}
+
+
+/*
+ * End of "$Id: form-tree.c,v 1.3 2000/04/19 21:25:58 mike Exp $".
*/
/*
- * "$Id: form.h,v 1.2 2000/04/18 19:41:11 mike Exp $"
+ * "$Id: form.h,v 1.3 2000/04/19 21:25:59 mike Exp $"
*
* CUPS form header file for the Common UNIX Printing System (CUPS).
*
typedef enum
{
- ELEMENT_COMMENT = -2, /* <!-- .... --> */
- ELEMENT_FILE, /* Pseudo element, not in file, but above */
+ ELEMENT_FILE = -1, /* Pseudo element, not in file, but above */
+ ELEMENT_FRAGMENT, /* Text fragment */
+ ELEMENT_COMMENT, /* <!-- .... --> */
ELEMENT_ARC,
ELEMENT_BOX,
ELEMENT_BR,
float x, y, w, h; /* Position and size in points */
float bg[3], fg[3]; /* Colors of element */
float thickness; /* Thickness of lines */
+ int preformatted; /* Preformatted text? */
float size; /* Height of text in points */
char *typeface; /* Typeface of text */
style_t style; /* Style of text */
extern void formDelete(tree_t *t);
extern char *formGetAttr(tree_t *t, const char *name);
-extern tree_t *formNew(element_t e, tree_t *p);
+extern tree_t *formNew(tree_t *p);
extern tree_t *formRead(FILE *fp, tree_t *p);
extern void formSetAttr(tree_t *t, const char *name, const char *value);
extern void formWrite(tree_t *p);
/*
- * End of "$Id: form.h,v 1.2 2000/04/18 19:41:11 mike Exp $".
+ * End of "$Id: form.h,v 1.3 2000/04/19 21:25:59 mike Exp $".
*/
#
-# "$Id: Makefile,v 1.20 2000/03/30 05:19:27 mike Exp $"
+# "$Id: Makefile,v 1.21 2000/04/19 21:25:59 mike Exp $"
#
# GNU Ghostscript makefile for the Common UNIX Printing System (CUPS).
#
zupath.o \
zusparam.o \
zvmem2.o \
- zvmem.o \
+ zvmem.o
OBJS = $(LIBOBJS) genarch.o pstoraster.o
pstoraster.o: arch.h ../config.h ../Makedefs
#
-# End of "$Id: Makefile,v 1.20 2000/03/30 05:19:27 mike Exp $".
+# End of "$Id: Makefile,v 1.21 2000/04/19 21:25:59 mike Exp $".
#
#
-# "$Id: Makefile,v 1.25 2000/03/30 05:19:28 mike Exp $"
+# "$Id: Makefile,v 1.26 2000/04/19 21:26:00 mike Exp $"
#
# Scheduler Makefile for the Common UNIX Printing System (CUPS).
#
CUPSDOBJS = auth.o banners.o cert.o classes.o client.o conf.o devices.o \
dirsvc.o main.o ipp.o listen.o job.o log.o ppds.o printers.o
MIMEOBJS = filter.o mime.o type.o
-OBJS = $(CUPSDOBJS) $(MIMEOBJS) cups-polld.o testmime.o testspeed.o
+OBJS = $(CUPSDOBJS) $(MIMEOBJS) cups-lpd.o cups-polld.o testmime.o \
+ testspeed.o
#
# Make everything...
#
-all: cupsd cups-polld libmime.a testmime testspeed
+all: cupsd cups-lpd cups-polld libmime.a testmime testspeed
#
#
clean:
- $(RM) $(OBJS) cupsd cups-polld libmime.a testmime testspeed
+ $(RM) $(OBJS) cupsd cups-lpd cups-polld libmime.a testmime testspeed
#
$(INSTALL_BIN) cupsd $(SBINDIR)
$(CHMOD) g-rwx,o-rwx $(SBINDIR)/cupsd
-$(MKDIR) $(SERVERBIN)/daemon
+ $(INSTALL_BIN) cups-lpd $(SERVERBIN)/daemon
$(INSTALL_BIN) cups-polld $(SERVERBIN)/daemon
-$(MKDIR) $(SERVERROOT)/certs
-$(MKDIR) $(SERVERROOT)/interfaces
../cups/language.h ../cups/string.h
+#
+# Make the line printer daemon, "cups-lpd".
+#
+
+cups-lpd: cups-lpd.o ../cups/$(LIBCUPS)
+ echo Linking $@...
+ $(CC) $(LDFLAGS) -o cups-lpd cups-lpd.o $(LIBS)
+
+cups-lpd.o: ../cups/cups.h ../cups/http.h ../cups/ipp.h \
+ ../cups/language.h ../cups/string.h
+
+
#
# Make the polling daemon, "cups-polld".
#
#
-# End of "$Id: Makefile,v 1.25 2000/03/30 05:19:28 mike Exp $".
+# End of "$Id: Makefile,v 1.26 2000/04/19 21:26:00 mike Exp $".
#
--- /dev/null
+/*
+ * "$Id: cups-lpd.c,v 1.1 2000/04/19 21:26:00 mike Exp $"
+ *
+ * Line Printer Daemon interface for the Common UNIX Printing System (CUPS).
+ *
+ * Copyright 1997-2000 by Easy Software Products, all rights reserved.
+ *
+ * These coded instructions, statements, and computer programs are the
+ * property of Easy Software Products and are protected by Federal
+ * copyright law. Distribution and use rights are outlined in the file
+ * "LICENSE.txt" which should have been included with this file. If this
+ * file is missing or damaged please contact Easy Software Products
+ * at:
+ *
+ * Attn: CUPS Licensing Information
+ * Easy Software Products
+ * 44141 Airport View Drive, Suite 204
+ * Hollywood, Maryland 20636-3111 USA
+ *
+ * Voice: (301) 373-9603
+ * EMail: cups-info@cups.org
+ * WWW: http://www.cups.org
+ *
+ * Contents:
+ *
+ */
+
+/*
+ * Include necessary headers...
+ */
+
+#include <cups/cups.h>
+#include <cups/string.h>
+#include <cups/language.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+
+/*
+ * LPD "mini-daemon" for CUPS. This program must be used in conjunction
+ * with inetd or another similar program that monitors ports and starts
+ * daemons for each client connection. A typical configuration is:
+ *
+ * printer stream tcp nowait lp /usr/lib/cups/daemon/cups-lpd cups-lpd
+ *
+ * This daemon implements most of RFC 1179 (the unofficial LPD specification)
+ * except for:
+ *
+ * - This daemon does not check to make sure that the source port is
+ * between 721 and 731, since it isn't necessary for proper
+ * functioning, and port-based security is no security at all!
+ *
+ * - The "Print any waiting jobs" command is a no-op.
+ *
+ * The LPD-to-IPP mapping is as defined in RFC 2569.
+ */
+
+/*
+ * Prototypes...
+ */
+
+int recv_print_job(const char *dest);
+int send_short_state(const char *dest, const char *list);
+int send_long_state(const char *dest, const char *list);
+int remove_jobs(const char *dest, const char *agent, const char *list);
+
+
+/*
+ * 'main()' - Process an incoming LPD request...
+ */
+
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line arguments */
+ char *argv[]) /* I - Command-line arguments */
+{
+ char line[1024], /* Command string */
+ command, /* Command code */
+ *dest, /* Pointer to destination */
+ *list, /* Pointer to list */
+ *agent, /* Pointer to user */
+ status; /* Status for client */
+
+
+ /*
+ * Don't buffer the output...
+ */
+
+ setbuf(stdout, NULL);
+
+ /*
+ * RFC1179 specifies that only 1 daemon command can be received for
+ * every connection.
+ */
+
+ if (fgets(line, sizeof(line), stdin) == NULL)
+ {
+ /*
+ * Unable to get command from client! Send an error status and return.
+ */
+
+ putchar(1);
+ return (1);
+ }
+
+ /*
+ * The first byte is the command byte. After that will be the queue name,
+ * resource list, and/or user name.
+ */
+
+ command = line[0];
+ dest = line + 1;
+
+ for (list = dest + 1; *list && !isspace(*list); list ++);
+
+ while (isspace(*list))
+ *list++ = '\0';
+
+ /*
+ * Do the command...
+ */
+
+ switch (command)
+ {
+ default : /* Unknown command */
+ putchar(1);
+
+ status = 1;
+ break;
+
+ case 0x01 : /* Print any waiting jobs */
+ putchar(0);
+
+ status = 0;
+ break;
+
+ case 0x02 : /* Receive a printer job */
+ putchar(0);
+
+ status = recv_print_job(dest);
+ break;
+
+ case 0x03 : /* Send queue state (short) */
+ putchar(0);
+
+ status = send_short_state(dest, list);
+ break;
+
+ case 0x04 : /* Send queue state (long) */
+ putchar(0);
+
+ status = send_long_state(dest, list);
+ break;
+
+ case 0x05 : /* Remove jobs */
+ putchar(0);
+
+ /*
+ * Grab the agent and skip to the list of users and/or jobs.
+ */
+
+ agent = list;
+
+ for (; *list && !isspace(*list); list ++);
+ while (isspace(*list))
+ *list++ = '\0';
+
+ status = remove_jobs(dest, agent, list);
+ break;
+ }
+
+ return (status);
+}
+
+
+/*
+ * 'recv_print_job()' - Receive a print job from the client.
+ */
+
+int /* O - Command status */
+recv_print_job(const char *dest) /* I - Destination */
+{
+ int i; /* Looping var */
+ int status; /* Command status */
+ FILE *fp; /* Temporary file */
+ char filename[1024]; /* Filename */
+ int bytes; /* Bytes received */
+ char line[1024], /* Line from file/stdin */
+ command, /* Command from line */
+ *count, /* Number of bytes */
+ *name; /* Name of file */
+ int num_data; /* Number of data files */
+ char data[32][256]; /* Data files */
+ const char *tmpdir; /* Temporary directory */
+ char user[1024], /* User name */
+ title[1024], /* Job title */
+ docname[1024]; /* Document name */
+ http_t *http; /* HTTP server connection */
+ cups_lang_t *language; /* Language information */
+ ipp_t *request, /* IPP request */
+ *response; /* IPP response */
+ char uri[HTTP_MAX_URI]; /* Printer URI */
+
+
+ status = 0;
+ num_data = 0;
+ if ((tmpdir = getenv("TMP")) == NULL)
+ tmpdir = "/var/tmp";
+
+ while (fgets(line, sizeof(line), stdin) != NULL)
+ {
+ if (strlen(line) < 2)
+ {
+ status = 1;
+ break;
+ }
+
+ command = line[0];
+ count = line + 1;
+
+ for (name = count + 1; *name && !isspace(*name); name ++);
+ while (isspace(*name))
+ *name++ = '\0';
+
+ switch (command)
+ {
+ default :
+ case 0x01 : /* Abort */
+ status = 1;
+ break;
+ case 0x02 : /* Receive control file */
+ if (strlen(name) < 2)
+ {
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ snprintf(filename, sizeof(filename), "%s/%06d-0", tmpdir, getpid());
+ break;
+ case 0x03 : /* Receive data file */
+ if (strlen(name) < 2)
+ {
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ name[strlen(name) - 1] = '\0'; /* Strip LF */
+ strncpy(data[num_data], name, sizeof(data[0]) - 1);
+ data[num_data][sizeof(data[0]) - 1] = '\0';
+
+ num_data ++;
+ snprintf(filename, sizeof(filename), "%s/%06d-%d", tmpdir, getpid(),
+ num_data);
+ break;
+ }
+
+ putchar(status);
+
+ if (status)
+ break;
+
+ /*
+ * Try opening the temp file...
+ */
+
+ if ((fp = fopen(filename, "wb")) == NULL)
+ {
+ putchar(1);
+ status = 1;
+ break;
+ }
+
+ /*
+ * Copy the data or control file from the client...
+ */
+
+ for (i = atoi(count); i > 0; i -= bytes)
+ {
+ if (i > sizeof(line))
+ bytes = sizeof(line);
+ else
+ bytes = i;
+
+ if ((bytes = fread(line, 1, bytes, stdin)) > 0)
+ bytes = fwrite(line, 1, bytes, fp);
+
+ if (bytes < 1)
+ {
+ status = 1;
+ break;
+ }
+ }
+
+ /*
+ * Read trailing nul...
+ */
+
+ if (!status)
+ {
+ fread(line, 1, 1, stdin);
+ status = line[0];
+ }
+
+ /*
+ * Close the file and send an acknowledgement...
+ */
+
+ fclose(fp);
+
+ putchar(status);
+
+ if (status)
+ break;
+ }
+
+ if (!status)
+ {
+ /*
+ * Process the control file and print stuff...
+ */
+
+ snprintf(filename, sizeof(filename), "%s/%06d-0", tmpdir, getpid());
+ if ((fp = fopen(filename, "rb")) == NULL)
+ status = 1;
+ else if ((http = httpConnect(cupsServer(), ippPort())) == NULL)
+ status = 1;
+ else
+ {
+ language = cupsLangDefault();
+ title[0] = '\0';
+ user[0] = '\0';
+ docname[0] = '\0';
+
+ while (fgets(line, sizeof(line), fp) != NULL)
+ {
+ /*
+ * Strip the trailing newline...
+ */
+
+ if (line[0])
+ line[strlen(line) - 1] = '\0';
+
+ /*
+ * Process control lines...
+ */
+
+ switch (line[0])
+ {
+ case 'J' : /* Job name */
+ strcpy(title, line + 1);
+ break;
+ case 'N' : /* Document name */
+ strcpy(docname, line + 1);
+ break;
+ case 'P' : /* User identification */
+ strcpy(user, line + 1);
+ break;
+ case 'c' : /* Plot CIF file */
+ case 'd' : /* Print DVI file */
+ case 'f' : /* Print formatted file */
+ case 'g' : /* Plot file */
+ case 'l' : /* Print file leaving control characters (raw) */
+ case 'n' : /* Print ditroff output file */
+ case 'o' : /* Print PostScript output file */
+ case 'p' : /* Print file with 'pr' format (prettyprint) */
+ case 'r' : /* File to print with FORTRAN carriage control */
+ case 't' : /* Print troff output file */
+ case 'v' : /* Print raster file */
+ /*
+ * Verify that we have a username...
+ */
+
+ if (!user[0])
+ {
+ status = 1;
+ break;
+ }
+
+ /*
+ * Figure out which file we are printing...
+ */
+
+ for (i = 0; i < num_data; i ++)
+ if (strcmp(data[i], line + 1) == 0)
+ break;
+
+ if (i >= num_data)
+ {
+ status = 1;
+ break;
+ }
+
+ /*
+ * Build an IPP_PRINT_JOB request...
+ */
+
+ if ((request = ippNew()) == NULL)
+ {
+ status = 1;
+ break;
+ }
+
+ request->request.op.operation_id = IPP_PRINT_JOB;
+ request->request.op.request_id = 1;
+
+ snprintf(uri, sizeof(uri), "ipp://%s:%d/printers/%s",
+ cupsServer(), ippPort(), dest);
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
+ "attributes-charset", NULL,
+ cupsLangEncoding(language));
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
+ "attributes-natural-language", NULL,
+ language != NULL ? language->language : "C");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
+ "printer-uri", NULL, uri);
+
+ if (line[0] == 'l')
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+ "document-format", NULL, "application/vnd.cups-raw");
+ else
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+ "document-format", NULL, "application/octet-stream");
+
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, user);
+
+ if (title[0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "job-name", NULL, title);
+
+ if (docname[0])
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "document-name", NULL, docname);
+
+ if (line[0] == 'p')
+ ippAddBoolean(request, IPP_TAG_JOB, "prettyprint", 1);
+
+ snprintf(filename, sizeof(filename), "%s/%06d-%d", tmpdir,
+ getpid(), i + 1);
+
+ /*
+ * Do the request...
+ */
+
+ snprintf(uri, sizeof(uri), "/printers/%s", dest);
+
+ if ((response = cupsDoFileRequest(http, request, uri, filename)) == NULL)
+ status = 1;
+ else if (response->request.status.status_code > IPP_OK_CONFLICT)
+ status = 1;
+
+ if (response != NULL)
+ ippDelete(response);
+ break;
+ }
+
+ if (status)
+ break;
+ }
+
+ fclose(fp);
+ httpClose(http);
+ cupsLangFree(language);
+ }
+ }
+
+ /*
+ * Clean up all temporary files and return...
+ */
+
+ for (i = -1; i < num_data; i ++)
+ {
+ snprintf(filename, sizeof(filename), "%s/%06d-%d", tmpdir, getpid(), i + 1);
+ unlink(filename);
+ }
+
+ return (status);
+}
+
+
+/*
+ * 'send_short_state()' - Send the short queue state.
+ */
+
+int /* O - Command status */
+send_short_state(const char *dest, /* I - Destination */
+ const char *list) /* I - List of jobs or users */
+{
+ puts("Sorry, not yet implemented!");
+ return (1);
+}
+
+
+/*
+ * 'send_long_state()' - Send the long queue state.
+ */
+
+int /* O - Command status */
+send_long_state(const char *dest, /* I - Destination */
+ const char *list) /* I - List of jobs or users */
+{
+ puts("Sorry, not yet implemented!");
+ return (1);
+}
+
+
+/*
+ * 'remove_jobs()' - Cancel one or more jobs.
+ */
+
+int /* O - Command status */
+remove_jobs(const char *dest, /* I - Destination */
+ const char *agent, /* I - User agent */
+ const char *list) /* I - List of jobs or users */
+{
+ return (1);
+}
+
+
+/*
+ * End of "$Id: cups-lpd.c,v 1.1 2000/04/19 21:26:00 mike Exp $".
+ */