diff options
Diffstat (limited to 'printutils')
-rw-r--r-- | printutils/lpd.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/printutils/lpd.c b/printutils/lpd.c new file mode 100644 index 000000000..ed3d9d100 --- /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; +} |