1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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;
}
|