summaryrefslogtreecommitdiff
path: root/printutils/lpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'printutils/lpd.c')
-rw-r--r--printutils/lpd.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/printutils/lpd.c b/printutils/lpd.c
new file mode 100644
index 0000000..ed3d9d1
--- /dev/null
+++ b/printutils/lpd.c
@@ -0,0 +1,79 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * micro lpd - a small non-queueing lpd
+ *
+ * Copyright (C) 2008 by Vladimir Dronnikov <dronnikov@gmail.com>
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+#include "libbb.h"
+
+int lpd_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
+int lpd_main(int argc, char *argv[])
+{
+ char *s;
+
+ // goto spool directory
+ // spool directory contains either links to real printer devices or just simple files
+ // these links or files are called "queues"
+ if (!argv[1])
+ bb_show_usage();
+
+ xchdir(argv[1]);
+
+ xdup2(1, 2);
+
+ // read command
+ s = xmalloc_reads(STDIN_FILENO, NULL);
+
+ // N.B. we keep things simple
+ // only "receive job" command is meaningful here...
+ if (2 == *s) {
+ char *queue;
+
+ // parse command: "\x2QUEUE_NAME\n"
+ queue = s + 1;
+ *strchrnul(s, '\n') = '\0';
+
+ while (1) {
+ // signal OK
+ write(STDOUT_FILENO, "", 1);
+ // get subcommand
+ s = xmalloc_reads(STDIN_FILENO, NULL);
+ if (!s)
+ return EXIT_SUCCESS; // EOF (probably)
+ // valid s must be of form: SUBCMD | LEN | SP | FNAME
+ // N.B. we bail out on any error
+ // control or data file follows
+ if (2 == s[0] || 3 == s[0]) {
+ int fd;
+ size_t len;
+ // 2: control file (ignoring), 3: data file
+ fd = -1;
+ if (3 == s[0])
+ fd = xopen(queue, O_RDWR | O_APPEND);
+ // get data length
+ *strchrnul(s, ' ') = '\0';
+ len = xatou(s + 1);
+ // dump exactly len bytes to file, or die
+ bb_copyfd_exact_size(STDIN_FILENO, fd, len);
+ close(fd); // NB: can do close(-1). Who cares?
+ free(s);
+ // got no ACK? -> bail out
+ if (safe_read(STDIN_FILENO, s, 1) <= 0 || s[0]) {
+ // don't talk to peer - it obviously
+ // don't follow the protocol
+ return EXIT_FAILURE;
+ }
+ } else {
+ // any other subcommand aborts receiving job
+ // N.B. abort subcommand itself doesn't contain
+ // fname so it failed earlier...
+ break;
+ }
+ }
+ }
+
+ printf("Command %02x not supported\n", (unsigned char)*s);
+ return EXIT_FAILURE;
+}