aboutsummaryrefslogtreecommitdiff
path: root/printutils/lpd.c
blob: ed3d9d100ff0be56e35bb8731ef687110932b8b8 (plain)
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;
}