From f3d8c8467f57a047d6ac2d691e8ec4304da0e794 Mon Sep 17 00:00:00 2001 From: Fedor Date: Sun, 24 May 2009 03:23:07 -0400 Subject: [PATCH] p910nd ver 0.93 --- release/src/router/p910nd/COPYING | 339 +++++++++++++++++++ release/src/router/p910nd/Makefile | 37 +++ release/src/router/p910nd/banner.pl | 9 + release/src/router/p910nd/client.pl | 58 ++++ release/src/router/p910nd/p910nd.8 | 93 ++++++ release/src/router/p910nd/p910nd.c | 609 ++++++++++++++++++++++++++++++++++ release/src/router/p910nd/p910nd.conf | 4 + release/src/router/p910nd/p910nd.init | 359 ++++++++++++++++++++ release/src/router/p910nd/p910nd.spec | 56 ++++ 9 files changed, 1564 insertions(+) create mode 100644 release/src/router/p910nd/COPYING create mode 100644 release/src/router/p910nd/Makefile create mode 100755 release/src/router/p910nd/banner.pl create mode 100755 release/src/router/p910nd/client.pl create mode 100644 release/src/router/p910nd/p910nd.8 create mode 100644 release/src/router/p910nd/p910nd.c create mode 100644 release/src/router/p910nd/p910nd.conf create mode 100755 release/src/router/p910nd/p910nd.init create mode 100644 release/src/router/p910nd/p910nd.spec diff --git a/release/src/router/p910nd/COPYING b/release/src/router/p910nd/COPYING new file mode 100644 index 0000000000..a43ea2126f --- /dev/null +++ b/release/src/router/p910nd/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/release/src/router/p910nd/Makefile b/release/src/router/p910nd/Makefile new file mode 100644 index 0000000000..dce54a70ed --- /dev/null +++ b/release/src/router/p910nd/Makefile @@ -0,0 +1,37 @@ +include ../common.mak + +# Comment out line bellow if you don't want to use +# libwrap (hosts.{allow,deny} access control) +#LIBWRAP = -lwrap +ifneq ("$(LIBWRAP)", "") +LIBWRAP += -DUSE_LIBWRAP +endif + +# If you don't have it in /var/lock/subsys, uncomment and define +CFLAGS += -DLOCKFILE_DIR=\"/var/lock\" + +CFLAGS += -O2 -Wall + +ifeq ($(STATIC),1) +CFLAGS += -static +endif + +CFLAGS += -I$(SRCBASE) -I$(SRCBASE)/include -I. -I$(TOP)/shared + +PROG = p910nd +BINDIR = /usr/sbin + +$(PROG): p910nd.c + $(CC) -o $@ $^ $(CFLAGS) $(LIBWRAP) + +strip: $(PROG) + @$(STRIP) -s $(PROG) + +install: $(PROG) + mkdir -p $(INSTALLDIR)$(BINDIR) + @install $(PROG) $(INSTALLDIR)$(BINDIR) + @$(STRIP) -s $(INSTALLDIR)$(BINDIR)/$(PROG) + +.PHONY: clean +clean: + rm -f *.o $(PROG) diff --git a/release/src/router/p910nd/banner.pl b/release/src/router/p910nd/banner.pl new file mode 100755 index 0000000000..5a238c80a4 --- /dev/null +++ b/release/src/router/p910nd/banner.pl @@ -0,0 +1,9 @@ +#!/usr/bin/perl +while (1) +{ + exit 0 if read(STDIN,$c,1) == 0; + last if ($cl eq "\031" && $c eq "\001"); + $cl = $c; +} +kill 'STOP',$$; +exit 0 diff --git a/release/src/router/p910nd/client.pl b/release/src/router/p910nd/client.pl new file mode 100755 index 0000000000..0b0e4c3606 --- /dev/null +++ b/release/src/router/p910nd/client.pl @@ -0,0 +1,58 @@ +#!/usr/bin/perl + +# edit this to the printer hostname +$them = 'ken'; +$port = 9101; + +open(STDIN, "$ARGV[0]") if $#ARGV >= 0; + +use Socket; +#use Sys::Hostname; + +#$hostname = hostname; + +($name, $aliases, $proto) = getprotobyname('tcp'); +($name, $aliases, $port) = getservbyname($port, 'tcp') + unless $port =~ /^\d+$/; + +#$thisaddr = inet_aton($hostname); +#defined($thisaddr) or &errexit("inet_aton: cannot resolve $hostname\n"); + +$thataddr = inet_aton($them); +defined($thataddr) or &errexit("inet_aton: cannot resolve $them\n"); + +socket(S, PF_INET, SOCK_STREAM, $proto) or &errexit("socket: $!\n"); + +#$this = sockaddr_in(0, $thisaddr); +#bind(S, $this) || &errexit("bind: $!\n"); + +$that = sockaddr_in($port, $thataddr); +connect(S, $that) || &errexit("connect: $!\n"); + +select(S); $| = 1; select(STDOUT); + +$buffer = ''; +while (1) +{ + $rin = ''; + vec($rin, fileno(S), 1) = 1; + $nfound = select($rout=$rin, $wout=$rin, undef, undef); + if (vec($rout, fileno(S), 1)) { + print STDERR "$buffer\n" if + defined($nread = sysread(S, $buffer, 8192)); + } + if (vec($wout, fileno(S), 1)) { + $nread = read(STDIN, $buffer, 8192); + last if $nread == 0; + &errexit("write: $!\n") unless + defined($written = syswrite(S,$buffer,$nread)); + } +} +close(S); +exit 0; + +sub errexit +{ + print STDERR @_; + exit 2; +} diff --git a/release/src/router/p910nd/p910nd.8 b/release/src/router/p910nd/p910nd.8 new file mode 100644 index 0000000000..ff170bfaba --- /dev/null +++ b/release/src/router/p910nd/p910nd.8 @@ -0,0 +1,93 @@ +.TH P910ND 8 "1 January 2008" +.SH NAME +p910nd \- port 9100+n printer daemon +.SH SYNOPSIS +.B p910nd +[\fB-f device\fR] +[\fB-i bindaddr\fR] +[\fB-bv\fR] +[\fB0|1|2\fR] +.SH DESCRIPTION +.I p910nd +is a small daemon that copies any data received on the port +it is listening on to the corresponding printer port. +It is primarily intended for diskless Linux hosts running as printer drivers +but there is no reason why it could not be used on diskful hosts. +Port 9100 is copied to /dev/lp0, 9101 to /dev/lp1 and 9102 to /dev/lp2. +The default is port 9100 to /dev/lp0. +.LP +The \fB-f\fR option can be used to specify a different printer device, +e.g. /dev/usblp0. +.LP +The \fB-i\fR option can be used to specify binding to one address instead +of all interfaces which is the default. +.LP +The \fB-b\fR option turns on bidirectional copying. +.LP +The \fB-v\fR option shows the version number. +.SH INSTALLATION +.I p910nd +can be run as a standalone daemon or from (x)inetd. +It will automatically detect if it is running under (x)inetd. +.LP +A sample SysVinit script, +.IR p910nd.sh , +is provided for operation as a daemon. +.I p910nd +will change its name under ps to match the printer port, i.e. +.I p9100d, p9101d +and +.IR p9102d . +.LP +When running under (x)inetd, the +.I /etc/inetd.conf +entry should look something like this (with tcpwrappers protection): +.sp +.nf +p9101 stream tcp nowait root /usr/sbin/tcpd /sbin/p910nd +.fi +.sp +Don't forget to add an entry in +.I /etc/services +for the corresponding port. +.LP +If operating with lprng, use the host%port syntax for the +printer device to send jobs to it. +.LP +If operating with CUPS, this is supported as the AppSocket +protocol, also known as the JetDirect (probably TM) protocol. +.LP +If operating with classic Berkeley lpd, a sample client, +.IR client.pl , +is provided. +This should be installed as the ifilter (if=) in /etc/printcap. +.I banner.pl +should be installed as the ofilter (of=) in /etc/printcap. +It may be necessary to create a dummy spool file for lpd (lp=). +This file will be opened but not written to. +The corresponding C versions are left as an exercise for the reader. +.LP +When running under inetd, more than one instance could be started. +To avoid problems with multiple instances attempting to access the +printer at the same time, make sure that only one client is active +at any one time. This can be done by designating one host as the +spooler and sending all jobs to this host. You will probably +need to set up an intermediate queue anyway to provide print job filtering. +.LP +If compiled with USE_LIBWRAP and linked with -lwrap, it uses the libwrap +library (tcpwrappers). Access control can be done with /etc/hosts.allow +and /etc/hosts.deny. The service name is p910nd. +.SH DIAGNOSTICS +.I p910nd +logs error messages to syslog. +.SH "SEE ALSO" +printcap(5), hosts_access(5) +.SH FILES +/var/run/p9100d.pid, /var/lock/subsys/p9100d, /etc/hosts.allow, /etc/hosts.deny +.SH COPYRIGHT +.I p910nd +is under the GNU Public License Version 2 +.SH AUTHOR +Ken Yap (greenpossum ATSIGN users PERIOD sourceforge PERIOD net) +.SH DATE +Version 0.93 October 2008 diff --git a/release/src/router/p910nd/p910nd.c b/release/src/router/p910nd/p910nd.c new file mode 100644 index 0000000000..e32cca507d --- /dev/null +++ b/release/src/router/p910nd/p910nd.c @@ -0,0 +1,609 @@ +/* + * Port 9100+n daemon + * Accepts a connection from port 9100+n and copy stream to + * /dev/lpn, where n = 0,1,2. + * + * GPLv2 license, read COPYING + * + * Run standalone as: p910nd [0|1|2] + * + * Run under inetd as: + * p910n stream tcp nowait root /usr/sbin/tcpd p910nd [0|1|2] + * where p910n is an /etc/services entry for + * port 9100, 9101 or 9102 as the case may be. + * root can be replaced by any uid with rw permission on /dev/lpn + * + * Port 9100+n will then be passively opened + * n defaults to 0 + * + * Version 0.93 + * Fix open call to include mode, required for O_CREAT + * + * Version 0.92 + * Patches by Dave Brown. Use raw I/O syscalls instead of + * stdio buffering. Buffer system to handle talkative bidi + * devices better on low-powered hosts. + * + * Version 0.91 + * Patch by Hans Harder. Close printer device after each use to + * avoid crashing with hotpluggable devices going away. + * Don't wait 10 seconds after successful open. + * + * Version 0.9 + * Patch by Kostas Liakakis to keep retrying every 10 seconds + * if EBUSY is returned by open_printer, apparently NetBSD + * does this if the printer is not on. + * Patch by Albert Bartoszko (al_bin@vp_pl), August 2006 + * Work with hotpluggable devices + * Improve Makefile + * + * (The last two patches conflict somewhat, Liakakis's patch + * retries opening the device every 10 seconds until successful, + * whereas Bartoszko's patch exits if the printer device cannot be opened. + * The problem is with a hotpluggable device, that device node may + * not appear again. + * + * I have opted for Liakakis's behaviour. Let me know if this can + * be improved. Perhaps we need another option that chooses the + * behaviour. - Ken) + * + * Version 0.8 + * Allow specifying address to bind to + * + * Version 0.7 + * Bidirectional data transfer + * + * Version 0.6 + * Arne Bernin fixed some cast warnings, corrected the version number + * and added a -v option to print the version. + * + * Version 0.5 + * -DUSE_LIBWRAP and -lwrap enables hosts_access (tcpwrappers) checking. + * + * Version 0.4 + * Ken Yap (greenpossum@users.sourceforge.net), April 2001 + * Placed under GPL. + * + * Added -f switch to specify device which overrides /dev/lpn. + * But number is still required get distinct ports and locks. + * + * Added locking so that two invocations of the daemon under inetd + * don't try to open the printer at the same time. This can happen + * even if there is one host running clients because the previous + * client can exit after it has sent all data but the printer has not + * finished printing and inetd starts up a new daemon when the next + * request comes in too soon. + * + * Various things could be Linux specific. I don't + * think there is much demand for this program outside of PCs, + * but if you port it to other distributions or platforms, + * I'd be happy to receive your patches. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_LIBWRAP +#include "tcpd.h" +int allow_severity, deny_severity; +extern int hosts_ctl(char *daemon, char *client_name, char *client_addr, char *client_user); +#endif + +#define BASEPORT 9100 +#define PIDFILE "/var/run/p910%cd.pid" +#ifdef LOCKFILE_DIR +#define LOCKFILE LOCKFILE_DIR "/p910%cd" +#else +#define LOCKFILE "/var/lock/subsys/p910%cd" +#endif +#ifndef PRINTERFILE +#define PRINTERFILE "/dev/lp%c" +#endif +#define LOGOPTS LOG_ERR + +#define BUFFER_SIZE 8192 + +/* Circular buffer used for each direction. */ +typedef struct { + int detectEof; /* If nonzero, EOF is marked when read returns 0 bytes. */ + int infd; /* Input file descriptor. */ + int outfd; /* Output file descriptor. */ + int startidx; /* Index of the start of valid data. */ + int endidx; /* Index of the end of valid data. */ + int bytes; /* The number of bytes currently buffered. */ + int totalin; /* Total bytes that have been read. */ + int totalout; /* Total bytes that have been written. */ + int eof; /* Nonzero indicates the input file has reached EOF. */ + int err; /* Nonzero indicates an error detected on the output file. */ + char buffer[BUFFER_SIZE]; /* Buffered data goes here. */ +} Buffer_t; + +static char *progname; +static char version[] = "Version 0.93"; +static char copyright[] = "Copyright (c) 2008 Ken Yap, GPLv2"; +static int lockfd = -1; +static char *device = 0; +static int bidir = 0; +static char *bindaddr = 0; + +void usage(void) +{ + fprintf(stderr, "%s %s %s\n", progname, version, copyright); + fprintf(stderr, "Usage: %s [-f device] [-i bindaddr] [-bv] [0|1|2]\n", progname); + exit(1); +} + +void show_version(void) +{ + fprintf(stdout, "%s %s\n", progname, version); +} + +int open_printer(int lpnumber) +{ + int lp; + char lpname[sizeof(PRINTERFILE)]; + +#ifdef TESTING + (void)snprintf(lpname, sizeof(lpname), "/dev/tty"); +#else + (void)snprintf(lpname, sizeof(lpname), PRINTERFILE, lpnumber); +#endif + if (device == 0) + device = lpname; + if ((lp = open(device, bidir ? O_RDWR : O_WRONLY)) == -1) { + if (errno != EBUSY) + syslog(LOGOPTS, "%s: %m\n", device); + syslog(LOGOPTS, "%s: %m, will try opening later\n", device); + } + return (lp); +} + +int get_lock(int lpnumber) +{ + char lockname[sizeof(LOCKFILE)]; + struct flock lplock; + + (void)snprintf(lockname, sizeof(lockname), LOCKFILE, lpnumber); + if ((lockfd = open(lockname, O_CREAT | O_RDWR, 0666)) < 0) { + syslog(LOGOPTS, "%s: %m\n", lockname); + return (0); + } + memset(&lplock, 0, sizeof(lplock)); + lplock.l_type = F_WRLCK; + lplock.l_pid = getpid(); + if (fcntl(lockfd, F_SETLKW, &lplock) < 0) { + syslog(LOGOPTS, "%s: %m\n", lockname); + return (0); + } + return (1); +} + +void free_lock(void) +{ + if (lockfd >= 0) + (void)close(lockfd); +} + +/* Initializes the buffer, at the start. */ +void initBuffer(Buffer_t * b, int infd, int outfd, int detectEof) +{ + b->detectEof = detectEof; + b->infd = infd; + b->outfd = outfd; + b->startidx = 0; + b->endidx = 0; + b->bytes = 0; + b->totalin = 0; + b->totalout = 0; + b->eof = 0; + b->err = 0; +} + +/* Sets the readfds and writefds (used by select) based on current buffer state. */ +void prepBuffer(Buffer_t * b, fd_set * readfds, fd_set * writefds) +{ + if (!b->err && b->bytes != 0) { + FD_SET(b->outfd, writefds); + } + if (!b->eof && b->bytes < sizeof(b->buffer)) { + FD_SET(b->infd, readfds); + } +} + +/* Reads data into a buffer from its input file. */ +ssize_t readBuffer(Buffer_t * b) +{ + int avail; + ssize_t result = 1; + /* If err, the data will not be written, so no need to store it. */ + if (b->bytes == 0 || b->err) { + /* The buffer is empty. */ + b->startidx = b->endidx = 0; + avail = sizeof(b->buffer); + } else if (b->bytes == sizeof(b->buffer)) { + /* The buffer is full. */ + avail = 0; + } else if (b->endidx > b->startidx) { + /* The buffer is not wrapped: from endidx to end of buffer is free. */ + avail = sizeof(b->buffer) - b->endidx; + } else { + /* The buffer is wrapped: gap between endidx and startidx is free. */ + avail = b->startidx - b->endidx; + } + if (avail) { + result = read(b->infd, b->buffer + b->endidx, avail); + if (result > 0) { + /* Some data was read. Update accordingly. */ + b->endidx += result; + b->totalin += result; + b->bytes += result; + if (b->endidx == sizeof(b->buffer)) { + /* Time to wrap the buffer. */ + b->endidx = 0; + } + } else if (result < 0 || b->detectEof) { + /* Mark end-of-file on input error, or on zero return if detectEof. */ + b->eof = 1; + } + } + /* Return the value returned by read(), which is -1, 0, or #bytes read. */ + return result; +} + +/* Writes data from a buffer to the output file. */ +ssize_t writeBuffer(Buffer_t * b) +{ + int avail; + ssize_t result = 1; + if (b->bytes == 0 || b->err) { + /* Buffer is empty. */ + avail = 0; + } else if (b->endidx > b->startidx) { + /* Buffer is not wrapped. Can write all the data. */ + avail = b->endidx - b->startidx; + } else { + /* Buffer is wrapped. Can only write the top (first) part. */ + avail = sizeof(b->buffer) - b->startidx; + } + if (avail) { + result = write(b->outfd, b->buffer + b->startidx, avail); + if (result < 0) { + /* Mark the output file in an error condition. */ + syslog(LOGOPTS, "write: %m\n"); + b->err = 1; + } else { + /* Zero or more bytes were written. */ + b->startidx += result; + b->totalout += result; + b->bytes -= result; + if (b->startidx == sizeof(b->buffer)) { + /* Unwrap the buffer. */ + b->startidx = 0; + } + } + } + /* Return the write() result, -1 (error), or #bytes written. */ + return result; +} + +/* Copy network data from file descriptor fd (network) to lp (printer) until EOS */ +/* If bidir, also copy data from printer (lp) to network (fd). */ +int copy_stream(int fd, int lp) +{ + int result; + Buffer_t networkToPrinterBuffer; + initBuffer(&networkToPrinterBuffer, fd, lp, 1); + + if (bidir) { + struct timeval now; + struct timeval then; + struct timeval timeout; + int timer = 0; + Buffer_t printerToNetworkBuffer; + initBuffer(&printerToNetworkBuffer, lp, fd, 0); + fd_set readfds; + fd_set writefds; + /* Initially read from both streams, don't write to either. */ + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_SET(lp, &readfds); + FD_SET(fd, &readfds); + /* Finish when no longer reading fd, and no longer writing to lp. */ + /* Although the printer to network stream may not be finished, that does not matter. */ + while ((FD_ISSET(fd, &readfds)) || (FD_ISSET(lp, &writefds))) { + int maxfd = lp > fd ? lp : fd; + if (timer) { + /* Delay after reading from the printer, so the */ + /* return stream cannot dominate. */ + /* Don't read from the printer until the timer expires. */ + gettimeofday(&now, 0); + if ((now.tv_sec > then.tv_sec) || (now.tv_sec == then.tv_sec && now.tv_usec > then.tv_usec)) { + timer = 0; + } else { + timeout.tv_sec = then.tv_sec; + timeout.tv_usec = then.tv_usec; + FD_CLR(lp, &readfds); + } + } + if (timer) { + result = select(maxfd + 1, &readfds, &writefds, 0, &timeout); + } else { + result = select(maxfd + 1, &readfds, &writefds, 0, 0); + } + if (result < 0) + return (result); + if (FD_ISSET(fd, &readfds)) { + /* Read network data. */ + result = readBuffer(&networkToPrinterBuffer); + } + if (FD_ISSET(lp, &readfds)) { + /* Read printer data, but pace it more slowly. */ + result = readBuffer(&printerToNetworkBuffer); + if (result >= 0) { + gettimeofday(&then, 0); + // wait 100 msec before reading again. + then.tv_usec += 100000; + if (then.tv_usec > 1000000) { + then.tv_usec -= 1000000; + then.tv_sec++; + } + timer = 1; + } + } + if (FD_ISSET(lp, &writefds)) { + /* Write data to printer. */ + result = writeBuffer(&networkToPrinterBuffer); + } + if (FD_ISSET(fd, &writefds)) { + /* Write data to network. */ + result = writeBuffer(&printerToNetworkBuffer); + /* If socket write error, stop reading from printer */ + if (result < 0) + networkToPrinterBuffer.eof = 1; + } + /* Prepare for next iteration. */ + FD_ZERO(&readfds); + FD_ZERO(&writefds); + prepBuffer(&networkToPrinterBuffer, &readfds, &writefds); + prepBuffer(&printerToNetworkBuffer, &readfds, &writefds); + } + syslog(LOG_NOTICE, + "Finished job: %d bytes received, %d bytes sent\n", + networkToPrinterBuffer.totalout, printerToNetworkBuffer.totalout); + return (0); + } else { + /* Unidirectional: simply read from network, and write to printer. */ + while ((result = readBuffer(&networkToPrinterBuffer)) > 0) { + (void)writeBuffer(&networkToPrinterBuffer); + } + syslog(LOG_NOTICE, "Finished job: %d bytes received\n", networkToPrinterBuffer.totalout); + return (result); + } +} + +void one_job(int lpnumber) +{ + int lp; + struct sockaddr_in client; + socklen_t clientlen = sizeof(client); + + if (getpeername(0, (struct sockaddr *)&client, &clientlen) >= 0) + syslog(LOG_NOTICE, "Connection from %s port %hu\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); + if (get_lock(lpnumber) == 0) + return; + /* Make sure lp device is open... */ + while ((lp = open_printer(lpnumber)) == -1) + sleep(10); + if (copy_stream(0, lp) < 0) + syslog(LOGOPTS, "copy_stream: %m\n"); + close(lp); + free_lock(); +} + +void server(int lpnumber) +{ + struct rlimit resourcelimit; +#ifdef USE_GETPROTOBYNAME + struct protoent *proto; +#endif + int netfd, fd, lp, one = 1; + socklen_t clientlen; + struct sockaddr_in netaddr, client; + char pidfilename[sizeof(PIDFILE)]; + FILE *f; + int ipret; + +#ifndef TESTING + switch (fork()) { + case -1: + syslog(LOGOPTS, "fork: %m\n"); + exit(1); + case 0: /* child */ + break; + default: /* parent */ + exit(0); + } + /* Now in child process */ + resourcelimit.rlim_max = 0; + if (getrlimit(RLIMIT_NOFILE, &resourcelimit) < 0) { + syslog(LOGOPTS, "getrlimit: %m\n"); + exit(1); + } + for (fd = 0; fd < resourcelimit.rlim_max; ++fd) + (void)close(fd); + if (setsid() < 0) { + syslog(LOGOPTS, "setsid: %m\n"); + exit(1); + } + (void)chdir("/"); + (void)umask(022); + fd = open("/dev/null", O_RDWR); /* stdin */ + (void)dup(fd); /* stdout */ + (void)dup(fd); /* stderr */ + (void)snprintf(pidfilename, sizeof(pidfilename), PIDFILE, lpnumber); + if ((f = fopen(pidfilename, "w")) == NULL) { + syslog(LOGOPTS, "%s: %m\n", pidfilename); + exit(1); + } + (void)fprintf(f, "%d\n", getpid()); + (void)fclose(f); + if (get_lock(lpnumber) == 0) + exit(1); +#endif +#ifdef USE_GETPROTOBYNAME + if ((proto = getprotobyname("tcp")) == NULL) { + syslog(LOGOPTS, "Cannot find protocol for TCP!\n"); + exit(1); + } + if ((netfd = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0) +#else + if ((netfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) +#endif + { + syslog(LOGOPTS, "socket: %m\n"); + exit(1); + } + if (setsockopt(netfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) + < 0) { + syslog(LOGOPTS, "setsocketopt: %m\n"); + exit(1); + } + netaddr.sin_family = AF_INET; + netaddr.sin_port = htons(BASEPORT + lpnumber - '0'); + if (bindaddr == 0) { + netaddr.sin_addr.s_addr = htonl(INADDR_ANY); + } else { + ipret = inet_pton(AF_INET, bindaddr, &netaddr.sin_addr.s_addr); + if (ipret < 0) { + syslog(LOGOPTS, "inet_pton: %m\n"); + exit(1); + } else if (ipret == 0) { + syslog(LOGOPTS, "inet_pton: invalid bind IP address\n"); + exit(1); + } + } + memset(netaddr.sin_zero, 0, sizeof(netaddr.sin_zero)); + if (bind(netfd, (struct sockaddr *)&netaddr, sizeof(netaddr)) < 0) { + syslog(LOGOPTS, "bind: %m\n"); + exit(1); + } + if (listen(netfd, 5) < 0) { + syslog(LOGOPTS, "listen: %m\n"); + exit(1); + } + clientlen = sizeof(client); + memset(&client, 0, sizeof(client)); + while ((fd = accept(netfd, (struct sockaddr *)&client, &clientlen)) >= 0) { +#ifdef USE_LIBWRAP + if (hosts_ctl("p910nd", STRING_UNKNOWN, inet_ntoa(client.sin_addr), STRING_UNKNOWN) == 0) { + syslog(LOGOPTS, + "Connection from %s port %hd rejected\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); + close(fd); + continue; + } +#endif + syslog(LOG_NOTICE, "Connection from %s port %hu accepted\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); + /*write(fd, "Printing", 8); */ + + /* Make sure lp device is open... */ + while ((lp = open_printer(lpnumber)) == -1) + sleep(10); + + if (copy_stream(fd, lp) < 0) + syslog(LOGOPTS, "copy_stream: %m\n"); + (void)close(fd); + (void)close(lp); + } + syslog(LOGOPTS, "accept: %m\n"); + free_lock(); + exit(1); +} + +int is_standalone(void) +{ + struct sockaddr_in bind_addr; + socklen_t ba_len; + + /* + * Check to see if a socket was passed to us from (x)inetd. + * + * Use getsockname() to determine if descriptor 0 is indeed a socket + * (and thus we are probably a child of (x)inetd) or if it is instead + * something else and we are running standalone. + */ + ba_len = sizeof(bind_addr); + if (getsockname(0, (struct sockaddr *)&bind_addr, &ba_len) == 0) + return (0); /* under (x)inetd */ + if (errno != ENOTSOCK) /* strange... */ + syslog(LOGOPTS, "getsockname: %m\n"); + return (1); +} + +int main(int argc, char *argv[]) +{ + int c, lpnumber; + char *p; + + if (argc <= 0) /* in case not provided in (x)inetd config */ + progname = "p910nd"; + else { + progname = argv[0]; + if ((p = strrchr(progname, '/')) != 0) + progname = p + 1; + } + lpnumber = '0'; + while ((c = getopt(argc, argv, "bi:f:v")) != EOF) { + switch (c) { + case 'b': + bidir = 1; + break; + case 'f': + device = optarg; + break; + case 'i': + bindaddr = optarg; + break; + case 'v': + show_version(); + break; + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + if (argc > 0) { + if (isdigit(argv[0][0])) + lpnumber = argv[0][0]; + } + /* change the n in argv[0] to match the port so ps will show that */ + if ((p = strstr(progname, "p910n")) != NULL) + p[4] = lpnumber; + + /* We used to pass (LOG_PERROR|LOG_PID|LOG_LPR|LOG_ERR) to syslog, but + * syslog ignored the LOG_PID and LOG_PERROR option. I.e. the intention + * was to add both options but the effect was to have neither. + * I disagree with the intention to add PERROR. --Stef */ + openlog(p, LOG_PID, LOG_LPR); + if (is_standalone()) + server(lpnumber); + else + one_job(lpnumber); + return (0); +} diff --git a/release/src/router/p910nd/p910nd.conf b/release/src/router/p910nd/p910nd.conf new file mode 100644 index 0000000000..d205fa075a --- /dev/null +++ b/release/src/router/p910nd/p910nd.conf @@ -0,0 +1,4 @@ +# Printer number, if not 0 +P910ND_NUM="" +# Additional daemon arguments, see man 8 p910nd +P910ND_OPTS="" diff --git a/release/src/router/p910nd/p910nd.init b/release/src/router/p910nd/p910nd.init new file mode 100755 index 0000000000..224ee53e47 --- /dev/null +++ b/release/src/router/p910nd/p910nd.init @@ -0,0 +1,359 @@ +#!/bin/bash +# +# LSB system startup script for service/daemon p910nd +# Copyright (C) 1995--2005 Kurt Garloff, SUSE / Novell Inc. +# Copyright (C) 2008 Ken Yap +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or (at +# your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, +# USA. +# +# /etc/init.d/p910nd +# and its symbolic link +# /(usr/)sbin/rcp910nd +# +# Template system startup script for some example service/daemon p910nd +# +# LSB compatible service control script; see http://www.linuxbase.org/spec/ +# +# Note: This template uses functions rc_XXX defined in /etc/rc.status on +# UnitedLinux/SUSE/Novell based Linux distributions. If you want to base your +# script on this template and ensure that it works on non UL based LSB +# compliant Linux distributions, you either have to provide the rc.status +# functions from UL or change the script to work without them. +# See skeleton.compat for a template that works with other distros as well. +# +# chkconfig: 35 90 10 +# description: p910nd daemon providing network printer access +# +### BEGIN INIT INFO +# Provides: p910nd +# Required-Start: $syslog +# Should-Start: +# Required-Stop: $syslog +# Should-Stop: +# Default-Start: 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: p910nd daemon providing network printer access +# Description: Start p910nd to provide port 9100+n printer service +### END INIT INFO +# +# Any extensions to the keywords given above should be preceeded by +# X-VendorTag- according to LSB. +# +# Notes on Required-Start/Should-Start: +# * There are two different issues that are solved by Required-Start +# and Should-Start +# (a) Hard dependencies: This is used by the runlevel editor to determine +# which services absolutely need to be started to make the start of +# this service make sense. Example: nfsserver should have +# Required-Start: $portmap +# Also, required services are started before the dependent ones. +# The runlevel editor will warn about such missing hard dependencies +# and suggest enabling. During system startup, you may expect an error, +# if the dependency is not fulfilled. +# (b) Specifying the init script ordering, not real (hard) dependencies. +# This is needed by insserv to determine which service should be +# started first (and at a later stage what services can be started +# in parallel). The tag Should-Start: is used for this. +# It tells, that if a service is available, it should be started +# before. If not, never mind. +# * When specifying hard dependencies or ordering requirements, you can +# use names of services (contents of their Provides: section) +# or pseudo names starting with a $. The following ones are available +# according to LSB (1.1): +# $local_fs all local file systems are mounted +# (most services should need this!) +# $remote_fs all remote file systems are mounted +# (note that /usr may be remote, so +# many services should Require this!) +# $syslog system logging facility up +# $network low level networking (eth card, ...) +# $named hostname resolution available +# $netdaemons all network daemons are running +# The $netdaemons pseudo service has been removed in LSB 1.2. +# For now, we still offer it for backward compatibility. +# These are new (LSB 1.2): +# $time the system time has been set correctly +# $portmap SunRPC portmapping service available +# UnitedLinux/SUSE/Novell extensions: +# $ALL indicates that a script should be inserted +# at the end +# * The services specified in the stop tags +# (Required-Stop/Should-Stop) +# specify which services need to be still running when this service +# is shut down. Often the entries there are just copies or a subset +# from the respective start tag. +# * Should-Start/Stop are now part of LSB as of 2.0, +# formerly SUSE/Unitedlinux used X-UnitedLinux-Should-Start/-Stop. +# insserv does support both variants. +# * X-UnitedLinux-Default-Enabled: yes/no is used at installation time +# (%fillup_and_insserv macro in %post of many RPMs) to specify whether +# a startup script should default to be enabled after installation. +# +# Note on runlevels: +# 0 - halt/poweroff 6 - reboot +# 1 - single user 2 - multiuser without network exported +# 3 - multiuser w/ network (text mode) 5 - multiuser w/ network and X11 (xdm) +# +# Note on script names: +# http://www.linuxbase.org/spec/refspecs/LSB_1.3.0/gLSB/gLSB/scrptnames.html +# A registry has been set up to manage the init script namespace. +# http://www.lanana.org/ +# Please use the names already registered or register one or use a +# vendor prefix. + + +# Check for missing binaries (stale symlinks should not happen) +# Note: Special treatment of stop for LSB conformance +P910ND_BIN=/usr/sbin/p910nd +test -x $P910ND_BIN || { echo "$P910ND_BIN not installed"; + if [ "$1" = "stop" ]; then exit 0; + else exit 5; fi; } + +# Check for existence of needed config file and read it +P910ND_CONFIG=/etc/sysconfig/p910nd +test -r $P910ND_CONFIG || { echo "$P910ND_CONFIG not found"; + if [ "$1" = "stop" ]; then exit 0; + else exit 6; fi; } + +# Read config +. $P910ND_CONFIG + +# Source LSB init functions +# providing start_daemon, killproc, pidofproc, +# log_success_msg, log_failure_msg and log_warning_msg. +# This is currently not used by UnitedLinux based distributions and +# not needed for init scripts for UnitedLinux only. If it is used, +# the functions from rc.status should not be sourced or used. +#. /lib/lsb/init-functions + +# Shell functions sourced from /etc/rc.status: +# rc_check check and set local and overall rc status +# rc_status check and set local and overall rc status +# rc_status -v be verbose in local rc status and clear it afterwards +# rc_status -v -r ditto and clear both the local and overall rc status +# rc_status -s display "skipped" and exit with status 3 +# rc_status -u display "unused" and exit with status 3 +# rc_failed set local and overall rc status to failed +# rc_failed set local and overall rc status to +# rc_reset clear both the local and overall rc status +# rc_exit exit appropriate to overall rc status +# rc_active checks whether a service is activated by symlinks + +# Use the SUSE rc_ init script functions; +# emulate them on LSB, RH and other systems + +# Default: Assume sysvinit binaries exist +start_daemon() { /sbin/start_daemon ${1+"$@"}; } +killproc() { /sbin/killproc ${1+"$@"}; } +pidofproc() { /sbin/pidofproc ${1+"$@"}; } +checkproc() { /sbin/checkproc ${1+"$@"}; } +if test -e /etc/rc.status; then + # SUSE rc script library + . /etc/rc.status +else + export LC_ALL=POSIX + _cmd=$1 + declare -a _SMSG + if test "${_cmd}" = "status"; then + _SMSG=(running dead dead unused unknown reserved) + _RC_UNUSED=3 + else + _SMSG=(done failed failed missed failed skipped unused failed failed reserved) + _RC_UNUSED=6 + fi + if test -e /lib/lsb/init-functions; then + # LSB + . /lib/lsb/init-functions + echo_rc() + { + if test ${_RC_RV} = 0; then + log_success_msg " [${_SMSG[${_RC_RV}]}] " + else + log_failure_msg " [${_SMSG[${_RC_RV}]}] " + fi + } + # TODO: Add checking for lockfiles + checkproc() { return pidofproc ${1+"$@"} >/dev/null 2>&1; } + elif test -e /etc/init.d/functions; then + # RHAT + . /etc/init.d/functions + echo_rc() + { + #echo -n " [${_SMSG[${_RC_RV}]}] " + if test ${_RC_RV} = 0; then + success " [${_SMSG[${_RC_RV}]}] " + else + failure " [${_SMSG[${_RC_RV}]}] " + fi + } + checkproc() { return status ${1+"$@"}; } + start_daemon() { return daemon ${1+"$@"}; } + else + # emulate it + echo_rc() { echo " [${_SMSG[${_RC_RV}]}] "; } + fi + rc_reset() { _RC_RV=0; } + rc_failed() + { + if test -z "$1"; then + _RC_RV=1; + elif test "$1" != "0"; then + _RC_RV=$1; + fi + return ${_RC_RV} + } + rc_check() + { + return rc_failed $? + } + rc_status() + { + rc_failed $? + if test "$1" = "-r"; then _RC_RV=0; shift; fi + if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi + if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi + if test "$1" = "-v"; then echo_rc; shift; fi + if test "$1" = "-r"; then _RC_RV=0; shift; fi + return ${_RC_RV} + } + rc_exit() { exit ${_RC_RV}; } + rc_active() + { + if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi + if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi + return 1 + } +fi + +# Reset status of this service +rc_reset + +# Return values acc. to LSB for all commands but status: +# 0 - success +# 1 - generic or unspecified error +# 2 - invalid or excess argument(s) +# 3 - unimplemented feature (e.g. "reload") +# 4 - user had insufficient privileges +# 5 - program is not installed +# 6 - program is not configured +# 7 - program is not running +# 8--199 - reserved (8--99 LSB, 100--149 distrib, 150--199 appl) +# +# Note that starting an already running service, stopping +# or restarting a not-running service as well as the restart +# with force-reload (in case signaling is not supported) are +# considered a success. + +case "$1" in + start) + echo -n "Starting p910nd " + ## Start daemon with startproc(8). If this fails + ## the return value is set appropriately by startproc. + startproc $P910ND_BIN $P910ND_OPTS $P910ND_NUM + + # Remember status and be verbose + rc_status -v + ;; + stop) + echo -n "Shutting down p910nd " + ## Stop daemon with killproc(8) and if this fails + ## killproc sets the return value according to LSB. + + killproc -TERM $P910ND_BIN + + # Remember status and be verbose + rc_status -v + ;; + try-restart|condrestart) + ## Do a restart only if the service was active before. + ## Note: try-restart is now part of LSB (as of 1.9). + ## RH has a similar command named condrestart. + if test "$1" = "condrestart"; then + echo "${attn} Use try-restart ${done}(LSB)${attn} rather than condrestart ${warn}(RH)${norm}" + fi + $0 status + if test $? = 0; then + $0 restart + else + rc_reset # Not running is not a failure. + fi + # Remember status and be quiet + rc_status + ;; + restart) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + $0 stop + $0 start + + # Remember status and be quiet + rc_status + ;; + force-reload) + ## Signal the daemon to reload its config. Most daemons + ## do this on signal 1 (SIGHUP). + ## If it does not support it, restart the service if it + ## is running. + + echo -n "Reload service p910nd " + ## if it supports it: + #killproc -HUP $P910ND_BIN + #touch /var/run/p910nd.pid + #rc_status -v + + ## Otherwise: + $0 try-restart + rc_status + ;; + reload) + ## Like force-reload, but if daemon does not support + ## signaling, do nothing (!) + + # If it supports signaling: + echo -n "Reload service p910nd " + #killproc -HUP $P910ND_BIN + #touch /var/run/p910nd.pid + #rc_status -v + + ## Otherwise if it does not support reload: + rc_failed 3 + rc_status -v + ;; + status) + echo -n "Checking for service p910nd " + ## Check status with checkproc(8), if process is running + ## checkproc will return with exit status 0. + + # Return value is slightly different for the status command: + # 0 - service up and running + # 1 - service dead, but /var/run/ pid file exists + # 2 - service dead, but /var/lock/ lock file exists + # 3 - service not running (unused) + # 4 - service status unknown :-( + # 5--199 reserved (5--99 LSB, 100--149 distro, 150--199 appl.) + + # NOTE: checkproc returns LSB compliant status values. + checkproc $P910ND_BIN + # NOTE: rc_status knows that we called this init script with + # "status" option and adapts its messages accordingly. + rc_status -v + ;; + *) + echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}" + exit 1 + ;; +esac +rc_exit diff --git a/release/src/router/p910nd/p910nd.spec b/release/src/router/p910nd/p910nd.spec new file mode 100644 index 0000000000..2f59423225 --- /dev/null +++ b/release/src/router/p910nd/p910nd.spec @@ -0,0 +1,56 @@ +Summary: p910nd is a small daemon that copies any data received to the corresponding printer port. +Name: p910nd +Version: 0.93 +Release: 1 +URL: http://etherboot.sourceforge.net/p910nd +Vendor: Ken Yap +License: GPL v2 +Source0: http://etherboot.sourceforge.net/p910nd/%{name}-%{version}.tar.gz +BuildArchitectures: i386 x86_64 +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Group: Networking + +%description +p910nd implements the port 9100 network printer protocol which simply +copies any incoming data on the port to the printer (and in the reverse +direction, if bidirectional mode is selected). Both parallel and USB +printers are supported. This protocol was used in HP's printers and is +called JetDirect (probably TM). p910nd is particularly useful for +diskless hosts and embedded devices because it does not require any disk +space for spooling as this is done at the sending host. + +%pre + +%prep +rm -fr %{buildroot} +%setup -n p910nd-%{version} + +%build +make + +%install +%makeinstall + +%post +insserv /etc/init.d/p910nd + +%preun +insserv -r /etc/init.d/p910nd + +%postun + +%clean +rm -fr %{buildroot} + +%files +%defattr(755, root, root) +/etc/sysconfig/p910nd +/etc/init.d/p910nd +/usr/sbin/p910nd +%{_mandir}/man8/p910nd.8.gz + +%changelog +* Fri Jan 04 2008 Ken Yap +- 0.92: First spec file +* Mon Feb 09 2009 Ken Yap +- 0.93: Fix up open with mode for call with O_CREAT -- 2.11.4.GIT