123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- #include "libbb.h"
- static char *sane(char *str)
- {
- char *s = str;
- char *p = s;
- while (*s) {
- if (isalnum(*s) || '-' == *s || '_' == *s) {
- *p++ = *s;
- }
- s++;
- }
- *p = '\0';
- return str;
- }
- static char *xmalloc_read_stdin(void)
- {
-
- size_t max = 4 * 1024;
- return xmalloc_reads(STDIN_FILENO, &max);
- }
- int lpd_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
- int lpd_main(int argc UNUSED_PARAM, char *argv[])
- {
- int spooling = spooling;
- char *s, *queue;
- char *filenames[2];
-
- if (*++argv)
- xchdir(*argv++);
-
- xdup2(STDOUT_FILENO, STDERR_FILENO);
-
- memset(filenames, 0, sizeof(filenames));
-
- s = queue = xmalloc_read_stdin();
-
- if (2 != *queue) {
- unsupported_cmd:
- printf("Command %02x %s\n",
- (unsigned char)s[0], "is not supported");
- goto err_exit;
- }
-
- queue++;
-
-
- if (!*sane(queue))
- return EXIT_FAILURE;
-
- spooling = chdir(queue) + 1;
-
- while (1) {
- char *fname;
- int fd;
-
-
- int expected_len, real_len;
-
- safe_write(STDOUT_FILENO, "", 1);
-
-
-
- s = xmalloc_read_stdin();
- if (!s) {
- char *p, *q, var[2];
-
- if (!spooling || !*argv)
- return EXIT_SUCCESS;
-
- if (spooling != 7)
- goto err_exit;
-
-
- var[1] = '\0';
-
- q = xmalloc_xopen_read_close(filenames[0], NULL);
- unlink(filenames[0]);
-
-
- xsetenv("DATAFILE", filenames[1]);
-
- while ((p = strchr(q, '\n')) != NULL && isalpha(*q)) {
- *p++ = '\0';
-
-
-
- if (*q != 'l') {
- var[0] = *q++;
- xsetenv(var, q);
- }
- q = p;
- }
-
-
- bb_daemon_helper(DAEMON_DEVNULL_STDIO);
- BB_EXECVP_or_die(argv);
- }
-
-
- if (2 != s[0] && 3 != s[0])
- goto unsupported_cmd;
- if (spooling & (1 << (s[0]-1))) {
- puts("Duplicated subcommand");
- goto err_exit;
- }
-
- chomp(s);
- fname = strchr(s, ' ');
- if (!fname) {
- puts("No or bad filename");
- goto err_exit;
- }
- *fname++ = '\0';
-
- expected_len = bb_strtou(s + 1, NULL, 10);
- if (errno || expected_len < 0) {
- puts("Bad length");
- goto err_exit;
- }
- if (2 == s[0] && expected_len > 16 * 1024) {
-
-
- puts("File is too big");
- goto err_exit;
- }
-
- if (spooling) {
-
-
- sane(fname);
- fd = open3_or_warn(fname, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL, 0200);
- if (fd < 0)
- goto err_exit;
- filenames[s[0] - 2] = xstrdup(fname);
- } else {
-
-
- fd = -1;
- if (3 == s[0])
- fd = xopen(queue, O_RDWR | O_APPEND);
- }
-
- safe_write(STDOUT_FILENO, "", 1);
-
- real_len = bb_copyfd_size(STDIN_FILENO, fd, expected_len);
- if (real_len != expected_len) {
- printf("Expected %d but got %d bytes\n",
- expected_len, real_len);
- goto err_exit;
- }
-
-
- if (safe_read(STDIN_FILENO, &s[1], 1) != 1 || s[1] != 0) {
-
-
-
- goto err_exit;
- }
- if (spooling) {
-
- fchmod(fd, 0600);
-
-
- spooling |= (1 << (s[0]-1));
- }
- free(s);
- close(fd);
-
-
- }
- err_exit:
-
- if (spooling) {
- #define i spooling
- for (i = 2; --i >= 0; )
- if (filenames[i])
- unlink(filenames[i]);
- }
- return EXIT_FAILURE;
- }
|