diff -Naur busybox.orig/include/applets.h busybox/include/applets.h
--- busybox.orig/include/applets.h	2008-02-19 18:41:14 +0000
+++ busybox/include/applets.h	2008-02-21 18:52:18 +0000
@@ -227,6 +227,8 @@
 USE_LOGNAME(APPLET_NOFORK(logname, logname, _BB_DIR_USR_BIN, _BB_SUID_NEVER, logname))
 USE_LOGREAD(APPLET(logread, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_LOSETUP(APPLET(losetup, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_LPQ(APPLET_ODDNAME(lpq, lpqr, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lpq))
+USE_LPR(APPLET_ODDNAME(lpr, lpqr, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lpr))
 USE_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_NEVER, ls))
 USE_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
diff -Naur busybox.orig/include/usage.h busybox/include/usage.h
--- busybox.orig/include/usage.h	2008-02-19 18:41:14 +0000
+++ busybox/include/usage.h	2008-02-21 18:52:18 +0000
@@ -2051,6 +2051,24 @@
        "with an optional offset (-o 12345). Encryption is not yet supported.\n" \
        "losetup -f will show the first loop free loop device\n\n"
 
+#define lpq_trivial_usage \
+       "[-P lp[@host[:port]]] [-d JOBID] [-f] [-s]"
+#define lpq_full_usage \
+       "Options:" \
+       "\n	-P	lp service to connect to (else uses $PRINTER)" \
+       "\n	-d	Delete job" \
+       "\n	-f	Force any waiting job to be printed" \
+       "\n	-s	Short display" \
+
+#define lpr_trivial_usage \
+       "-P lp[@host[:port]] -U USERNAME -J TITLE -V -m -h [filename ...]"
+#define lpr_full_usage \
+       "Options:" \
+       "\n	-P	lp service to connect to (else uses $PRINTER)"\
+       "\n	-m	Send mail to LOGNAME@HOSTNAME" \
+       "\n	-h	Banner or header for this job" \
+       "\n	-V	Verbose" \
+
 #define ls_trivial_usage \
        "[-1Aa" USE_FEATURE_LS_TIMESTAMPS("c") "Cd" \
 	USE_FEATURE_LS_TIMESTAMPS("e") USE_FEATURE_LS_FILETYPES("F") "iln" \
diff -Naur busybox.orig/networking/Config.in busybox/networking/Config.in
--- busybox.orig/networking/Config.in	2008-02-17 06:50:48 +0000
+++ busybox/networking/Config.in	2008-02-21 18:52:18 +0000
@@ -560,6 +560,20 @@
 	help
 	  Support long options for the ipcalc applet.
 
+config LPR
+	bool "lpr"
+	default n
+	help
+	  Lpr uses a spooling daemon to print the named files when facilities
+	  become available. If no names appear, the standard input is assumed.
+
+config LPQ
+	bool "lpq"
+	depends on LPR
+	default n
+	help
+	  Spool queue examination and manipulation program
+
 config NAMEIF
 	bool "nameif"
 	default n
diff -Naur busybox.orig/networking/Kbuild busybox/networking/Kbuild
--- busybox.orig/networking/Kbuild	2008-02-17 06:50:48 +0000
+++ busybox/networking/Kbuild	2008-02-21 18:52:18 +0000
@@ -21,6 +21,8 @@
 lib-$(CONFIG_INETD)        += inetd.o
 lib-$(CONFIG_IP)           += ip.o
 lib-$(CONFIG_IPCALC)       += ipcalc.o
+lib-$(CONFIG_LPR)          += lpr.o 
+lib-$(CONFIG_LPQ)          += lpr.o
 lib-$(CONFIG_NAMEIF)       += nameif.o
 lib-$(CONFIG_NC)           += nc.o
 lib-$(CONFIG_NETSTAT)      += netstat.o
diff -Naur busybox.orig/networking/lpr.c busybox/networking/lpr.c
--- busybox.orig/networking/lpr.c	1970-01-01 00:00:00 +0000
+++ busybox/networking/lpr.c	2008-02-21 20:22:33 +0000
@@ -0,0 +1,237 @@
+/*
+  this is a *very* resticted form of lpq
+  since we do not read /etc/printcap (and never will)
+  we can only do things rfc1179 allows:
+  - show print jobs for a given queue long/short form
+  - remove a job from a given queue
+*/
+
+#include "libbb.h"
+
+#define ENABLE_FEATURE_LPR_BANNER 0
+#define ENABLE_FEATURE_LPR_MAIL 0
+#define ENABLE_FEATURE_LPR_VERBOSE 0
+
+/*
+  LPD returns 0 on success
+  else read and dump error message and exit
+*/
+static void get_response_or_die(const char *errmsg)
+{
+	char buf;
+
+	if (1 != safe_read(STDOUT_FILENO, &buf, 1) || '\0' != buf) {
+		bb_copyfd_eof(STDOUT_FILENO, STDERR_FILENO);
+		bb_error_msg_and_die(errmsg);
+	}
+}
+
+int lpqr_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE;
+int lpqr_main(int argc, char *argv[])
+{
+	enum {
+		OPT_P		= 1 << 0, // -P <queue>
+		OPT_U		= 1 << 1, // -U <username>
+#if ENABLE_FEATURE_LPR_VERBOSE
+		LPR_V		= 1 << 2, // -V -- be verbose
+#endif
+#if ENABLE_FEATURE_LPR_BANNER
+		LPR_h		= 1 << 3, // -h banner or header for this job    
+		LPR_C		= 1 << 4, // -C <class> job classification
+		LPR_J		= 1 << 5, // -J <title> is the jobtitle for the banner page*/
+#endif
+#if ENABLE_FEATURE_LPR_MAIL
+		LPR_m		= 1 << 6, // -m send mail to user@hostname
+#endif
+		LPQ_SHORT_FMT	= 1 << 2, // -s -- short listing format
+		LPQ_DELETE	= 1 << 3, // -d -- delete job(s)
+		LPQ_FORCE	= 1 << 4, // -f -- force waiting job(s) to be printed
+	};
+
+#if ENABLE_FEATURE_LPR_BANNER
+	char *job_title;	// max 79 char
+	char *printer_class;	// printer class, max 32 char
+#endif
+
+	const char *queue;
+	char *server = (char *)"localhost:515";
+	// N.B. IMHO getenv("USER") can be way easily spoofed!
+	//char *user = getenv("USER");
+	char *user = bb_getpwuid(NULL, -1, getuid());
+	unsigned opts;
+
+	int fd;
+
+	// parse options
+	// TODO: set opt_complementary: s,d,f are mutually exclusive
+	opts = getopt32(argv,
+		USE_LPQ( (/*lp*/'r' == applet_name[2]) ? )"P:U:VhC:J:m" USE_LPQ( : "P:U:sdf")
+		, &queue, &user
+#if ENABLE_FEATURE_LPR_BANNER
+		, &printer_class, &job_title
+#endif
+	);
+	argv += optind;
+
+	// if queue is not specified -> use $PRINTER
+	if (!(opts & OPT_P))
+		queue = getenv("PRINTER");
+	// if queue is still not specified ->
+	if (!queue) {
+		// ... queue defaults to "lp"
+		// server defaults to "localhost:515"
+		queue = "lp";
+	// if queue is specified ->
+	} else {
+		// queue name is to the left of '@'
+		char *s = strchr(queue, '@');
+		if (s) {
+			// server name is to the right of '@'
+			*s++ = '\0';
+			server = s;
+		}
+	}
+
+while (0) bb_error_msg_and_die("U[%s] P[%s] S[%s]", user, queue, server);
+
+	// do connect
+	fd = create_and_connect_stream_or_die(server, 0);
+	// play with descriptors to save space: fdprintf > printf
+	xdup2(STDOUT_FILENO, fd+1);
+	xmove_fd(fd, STDOUT_FILENO);
+
+#ifdef ENABLE_LPQ
+	//
+	// LPQ ------------------------
+	//
+	if (/*lp*/'q' == applet_name[2]) {
+		char cmd;
+		// force printing of every job still in queue
+		if (opts & LPQ_FORCE) {
+			cmd = 1;
+			goto command;
+		// delete job(s)
+		} else if (opts & LPQ_DELETE) {
+			while (*argv) {
+				printf("\005%s %s %s\n", queue, user, *argv);
+				bb_copyfd_eof(STDIN_FILENO, STDERR_FILENO);
+				argv++;
+			}
+		// dump current jobs status
+		// N.B. periodical polling should be achieved via "watch -n delay lpq"
+		// UNIX-way...
+		} else {
+			cmd = (opts & LPQ_SHORT_FMT) ? 3 : 4;
+command:
+			printf("%c%s\n", cmd, queue);
+			bb_copyfd_eof(STDIN_FILENO, STDERR_FILENO);
+		}
+	//
+	// LPR ------------------------
+	//
+	} else
+#endif
+	{
+		int seqnr = 0;
+		char *hostname = xzalloc(MAXHOSTNAMELEN+1);
+		gethostname(hostname, MAXHOSTNAMELEN);
+
+		// no files given on command line? -> use stdin
+		if (!*argv)
+			*--argv = (char *)"-";
+
+#if ENABLE_FEATURE_LPR_VERBOSE
+		if (opts & LPR_V)
+			bb_error_msg("connect to server");
+#endif
+
+		printf("\002%s\n", queue);
+		get_response_or_die("set queue failed");
+
+		/* handle filenames */
+		/* rfc say SHOULD be a 3 digit job number */
+		/* since its only a possible UNIQ name i use 6 for now */
+		/* no complains, so it seems to be ok */
+		/*
+		   we use pid%1000*1000+cnt so the number should be fairly uniq
+		 */
+
+		while (*argv) {
+			bool stdin_dumped = 0;
+			struct stat st;
+			char *s;
+			char *controlfilename;
+
+			// stat data file
+			// N.B. if data file is stdin we need to dump it first!
+			if (LONE_DASH(*argv)) {
+				char template[] = "lprXXXXXX";
+				fd = mkstemp(template);
+				if (fd < 0)
+					bb_perror_msg_and_die("cannot create temp file %s", template);
+				*argv = template;
+				bb_copyfd_eof(STDIN_FILENO, fd);
+				close(fd);
+				stdin_dumped = 1;
+			}
+			xstat(*argv, &st);
+			fd = xopen(*argv, O_RDONLY);
+
+			// construct control file
+			s = xasprintf(
+				"H%s\nP%s\nl%s\n"
+#if ENABLE_FEATURE_LPR_BANNER
+				"J%s\nC%s\nL%s\n"
+#endif
+#if ENABLE_FEATURE_LPR_BANNER
+				"M%s\n"
+#endif
+				, hostname, user, basename(*argv)
+#if ENABLE_FEATURE_LPR_BANNER
+				, (opts & LPR_J) ? job_title : *argv
+				, (opts & LPR_C) ? printer_class : NULL
+				, (opts & LPR_h) ? user : NULL
+#endif
+#if ENABLE_FEATURE_LPR_MAIL
+				, (opts & LPR_m) ? user : NULL
+#endif
+			);
+
+			// send control file
+			controlfilename = xasprintf("cfA%03d%03d%s", ++seqnr, getpid() % 1000, hostname);
+#if ENABLE_FEATURE_LPR_VERBOSE
+			if (opts & LPR_V)
+				bb_error_msg("send control file");
+#endif
+			printf("\002%u %s\n", strlen(s), controlfilename);
+			printf("%s", s);
+			get_response_or_die("send control file");
+
+			// send data file
+#if ENABLE_FEATURE_LPR_VERBOSE
+			if (opts & LPR_V)
+				bb_error_msg("send data file");
+#endif
+			*controlfilename = 'd';
+			printf( "\003%u %s\n", (size_t)st.st_size, controlfilename);
+			if (bb_copyfd_eof(fd, STDOUT_FILENO) < 0)
+				goto bail;
+			close(fd);
+			if (full_write(STDOUT_FILENO, "", 1) != 1)
+bail:
+				bb_perror_msg_and_die("send data file");
+			get_response_or_die("send data file");
+
+			// delete temporary file if we dumped stdin
+			if (stdin_dumped)
+				xunlink(*argv);
+
+			// next, please!
+			free(s);
+			free(controlfilename);
+			argv++;
+		}
+	}
+
+	return EXIT_SUCCESS;
+}
