ngetty-1.10000755000000000000000000000000011376744046011320 5ustar rootrootngetty-1.1/CHANGES0000644000000000000000000000575411376744046012405 0ustar rootrootThu May 25 07:20:02 UTC 2010 fixed fmt_number.h shorter splitmem.c fixed sstip.bin in Makefile updated README.upstart nwho, cleanutmp, dumputmp (see lib.h HAVE_C_UTMP[X]) dumputmp, nwho print ip (V4 or V6) Version 1.1 Tue Dec 16 20:09:24 UTC 2008 Version 1.0 Thu Oct 16 11:28:15 UTC 2008 option -ll for nwho Version 0.5-rc1 Mon Jun 30 07:41:48 UTC 2008 small and fast sortpfd() Makefile test time/utmp functions some comments in ngetty-helper.c Mon Jun 23 17:31:27 UTC 2008 option login-buffer opitons -D -N -C for ngetty-argv updated manual page better test-helper.c Sat May 24 06:02:29 UTC 2008 Makefile; make FLAG_DEBUG=yes options months, days /etc/ngetty/setup convert XXX=tz=AUTO to XXX=tz=number updated manual page May be some distro will try as default on tty1 and tty2 their working gettys and on tty3, tty4, ... ngetty On i386 with dietlibc try also 'make ngetty.i386' Version 0.4 Wed Apr 16 14:14:29 UTC 2008 ngetty-helper checks /etc/localtime before parsing it option tz Thu Apr 10 18:35:56 UTC 2008 ngetty-XXX.spec (thx Blair Lowe) utmpdump --> dumputmp (avoid conflicts with Sys-V-Init) Sun Apr 6 12:12:39 UTC 2008 ngetty: Are there rice between SIGCHLD and poll() ? It's don't use setjmp(), longjmp() any more. Tue Apr 1 11:55:03 UTC 2008 If ngetty receives SIGCHLD it restart failed tty devices Sun Mar 23 09:37:46 UTC 2008 added installation script and README.install for binary packages. Freue Ostern Maria! added check for syscall vhangup() Fri Mar 22 18:49:36 UTC 2008 updated man page (SIGNALS) fixed Makefile to support 'make -jX' (thx G. Lango) Fri Mar 21 06:07:02 UTC 2008 ngetty-helper exits if stdout or stderr are open added test-helper.c (mainly for developers) options clear and newline updated manual page Version-0.3 Tue Mar 18 08:27:11 UTC 2008 new opt_get scheme; see opts_do.c ngetty-helper.tiny (does not support escapes \d \t \u \U) ngetty-helper.c; option print Sat Mar 15 12:56:57 UTC 2008 ngetty-helper.c: option: login-argv ngetty-argv.c: new program Makefile: make install prefix=/some/dir (thx to Blair Lowe) updated man page Fri Mar 8 16:15:31 UTC 2008 ngetty-helper.c: options: allow, deny safe_io.c (thanks to R.L. Horn) Wed Mar 5 20:49:54 UTC 2008 ngetty.8: login-prog example ngetty-helper.c: updated Copyright Mon Feb 25 17:09:05 UTC 2008 CLEAR_STRING marco in lib.h get_uptime.c; tryboottime.c Sat Feb 23 15:20:34 UTC 2008 check_first.c; trysysinfo.c Thu Feb 22 11:44:03 UTC 2008 some changes in Makefile Tue Feb 12 08:41:34 EET 2008 fmt_number.h; scan_number.h Thu Jan 24 18:09:09 EET 2008 string.h is removed from all headers Makefile: make all creates ngetty.8.gz Thu Jan 24 15:53:29 EET 2008 Version-0.2 http://riemann.fmi.uni-sofia.bg/ngetty/guarantee.html Mon Jan 21 11:24:15 EET 2008 added nwho Mon Jan 21 00:30:37 EET 2008 monor changes; only repackeged to use string byte routines. ngetty-helper option echo-off Mon Dec 10 14:58:33 EET 2007 fixed a typo in Makefile. (thanks to Giorgio Lando) mailing list ngetty@... updated http-link in ngetty.8 ngetty-1.1/COPYING0000644000000000000000000004310310577262363012432 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 Lesser 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 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) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) year 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 Lesser General Public License instead of this License. ngetty-1.1/Conf0000644000000000000000000000010710635156647012206 0ustar rootroot# options format: # [ttyX]=option[=value] #=debug =environ=,TERM=linux ngetty-1.1/Makefile0000644000000000000000000001574411376212642013042 0ustar rootroot## next is statically build in ngetty-helper. Do not change !!! NGETTY_DIR = /etc/ngetty DESTDIR = / prefix = ${DESTDIR} sbin_prefix = ${prefix}/sbin etc_prefix = ${prefix}/etc ngetty_prefix = ${etc_prefix}/ngetty usrbin_prefix = ${prefix}/usr/bin mandir = ${prefix}/usr/share/man man8dir = ${mandir}/man8 ### next are aditinal options for make install # P = -o root -g root CC = gcc CFLAGS = -Wall -Os LDFLAGS = -s FLAG_DEBUG = no ALL_EXEC = ngetty ngetty.tiny ngetty.sortpfd \ ngetty-helper ngetty-helper.tiny ngetty-argv \ cleanutmp dumputmp nwho ALL_MAN = ngetty.8.gz ngetty-helper.8.gz ngetty-argv.8.gz ifeq ($(FLAG_DEBUG),no) CCC_ = @echo ' CC $< ' ; CCL_ = @echo ' CL $< -> $@ ' ; C = @ else CCC_ = CCL_ = C = endif CC_C = $(CC) $(CFLAGS) CC_L = $(CC) $(CFLAGS) $(LDFLAGS) CCC = $(CCC_) $(CC_C) CCL = $(CCL_) $(CC_L) STR = $(C) strip -R .comment -R .note ifeq (${prefix},/) prefix = endif MYARCH:=$(shell uname -m | sed -e 's/i[4-9]86/i386/' -e 's/armv[3-6]t\?e\?[lb]/arm/') ALL = $(ALL_EXEC) $(ALL_MAN) all: $(ALL) %.o: %.c lib.h utmp_struct.h all_defs.h sysinfo_defs.h boottime_defs.h $(CCC) -c $< STR_O = $(patsubst %.c,%.o,$(wildcard str_*.c s*mem.c out_*.c)) FMT_O = $(patsubst %.c,%.o,$(wildcard fmt_*.c)) SCAN_O = $(patsubst %.c,%.o,$(wildcard x_atoi.c)) DJB_O = $(STR_O) $(SCAN_O) $(FMT_O) UTMP_O = $(patsubst %.c,%.o,$(wildcard *_io.c *_do.c *_users.c *_devlog.c)) TIME_O = $(patsubst %.c,%.o,$(wildcard *gmtime.c get_up*.c)) MISC_O = $(patsubst %.c,%.o,$(wildcard first_*.c fork_*.c check_*)) ALL_O = $(UTMP_O) $(TIME_O) $(MISC_O) opts_make: opts_make.c str_defs.h fmt_defs.h lib.a vhangup_defs.h lib.a $(CCL) -o $@ $< lib.a all_defs.h: $(patsubst %.o,%.c,$(ALL_O)) tzmap.c ngetty-helper.c $(C) ./get_headers $@ -Gsys/stat.h -Gtime.h \ -Lstr_defs.h -Lfmt_defs.h -Lscan_defs.h -Lutmp_struct.h $^ > $@ fmt_defs.h: fmt_*.c $(C) ./get_headers $@ $^ > $@ scan_defs.h: x_atoi.c const_io.c $(C) ./get_headers $@ $^ > $@ str_defs.h: str_*.c splitmem.c out_*.c const_io.c $(C) ./get_headers $@ $^ > $@ utmp_defs.h: utmp_do.c $(C) sed -n -e '/EXTRACT_START/,/EXTRACT_END/p' $< > $@ opts_defs.h: opts_make ./opts_make | sed -n -e '/ O[odmt]/p' > opts__defs.h ./opts_make > $@ sysinfo_defs.h: trysysinfo.c $(C) ( ( rm -f $@Z; $(CC_L) -o $@Z $< && ./$@Z ) > /dev/null 2>&1 \ && echo '#define HAVE_SYSTEM_SYSINFO' || true ) > $@ $(C) rm -f $@Z; cat $@ boottime_defs.h: tryboottime.c $(C) ( ( rm -f $@Z; $(CC_L) -o $@Z $< && ./$@Z ) > /dev/null 2>&1 \ && echo '#define HAVE_SYSTEM_BOOTTIME' || true ) > $@ $(C) rm -f $@Z; cat $@ vhangup_defs.h: tryvhangup.c $(C) ( ( rm -f $@Z; $(CC_L) -o $@Z $< ) > /dev/null 2>&1 && \ echo '#define HAVE_SYSTEM_VHANGUP' || true ) > $@ $(C) rm -f $@Z; cat $@ lib.a: $(patsubst fmt_time.o,,$(DJB_O)) $(ALL_O) ar cr lib.a $^ tzmap.a: tzmap.o fmt_time.o ar cr $@ $^ tzmap_mmap.a: tzmap_mmap.o ar cr $@ $^ ngetty_h = all_defs.h sortpfd.h sig_action.h ngetty-helper_h = tzmap.a opts_defs.h lib.a diet_flags = -isystem /opt/diet/include -D__dietlibc__ \ -Os -mpreferred-stack-boundary=2 -falign-functions=1 -falign-jumps=1 \ -falign-loops=1 -fomit-frame-pointer -DNGETTY_TINY -DNGETTY_$(MYARCH) system-$(MYARCH).o: system-$(MYARCH).S $(CCC_) $(CC) $(diet_flags) -c $< ngetty.$(MYARCH): ngetty.c $(ngetty_h) system-$(MYARCH).o $(CCL_) $(CC) -nostdlib $(diet_flags) system-$(MYARCH).o \ -s -Wl,-N -o $@ $< $(STR) $@ ngetty: ngetty.c $(ngetty_h) $(C) $(CC) --version || true; uname -a || true $(C) echo "ARCH = $(MYARCH)"; echo "CC = $(CC)"; \ echo "CFLAGS = $(CFLAGS)"; echo "LDFLAGS = $(LDFLAGS)"; $(CCL) -DNGETTY_SELFPIPE -o $@ $< $(STR) $@ ngetty.sortpfd: ngetty.c $(ngetty_h) $(CCL) -DNGETTY_SELFPIPE -DNGETTY_SORT -o $@ $< $(STR) $@ ngetty.tiny: ngetty.c $(ngetty_h) $(CCL) -DNGETTY_TINY -o $@ $< $(STR) $@ ngetty-helper: ngetty-helper.c $(ngetty-helper_h) $(CCL) -DNGETTY_HOME=\"$(NGETTY_DIR)\" -o $@ $< lib.a tzmap.a $(STR) $@ ngetty-helper.tiny: ngetty-helper.c $(ngetty-helper_h) $(CCL) -DNGETTY_HOME=\"$(NGETTY_DIR)\" -DDONT_NEED_ESC_TIME -DDONT_NEED_ESC_USERS -o $@ $< lib.a $(STR) $@ %: %.c $(CCL) -o $@ $^ $(STR) $@ tzmap_mmap.c: tzmap.c $(C) ( echo '#define TZ_MMAP'; echo '#include "tzmap.c"' ) > $@ all_defs.h: str_defs.h scan_defs.h fmt_defs.h utmp_defs.h cleanutmp: lib.a ngetty-argv: lib.a dumputmp: tzmap_mmap.a lib.a nwho: tzmap_mmap.a lib.a str_%.o: str_defs.h splitmem.c fmt_%.o: fmt_defs.h fmt_time.o: opts_defs.h tzmap.o: opts_defs.h ngetty.8.gz: ngetty.8 ngetty-helper dumputmp ngetty-argv gzip -9 < $< > $@ $(C) ls -la /var/run/utmp* /dev/tty1 /dev/vc/1 2>/dev/null || true ./dumputmp < /var/run/utmp | head || true date '+%nCurrent time: %Y-%m-%d %T %Z %z' ./ngetty-argv :-N:-a1:./ngetty-helper::TestTime || true ngetty-%.8.gz: $(C) echo '.so ngetty.8' | gzip -9 > $@ install_other: $(ALL) install -m 755 $(P) -d $(usrbin_prefix) install -m 755 $(P) nwho dumputmp $(usrbin_prefix) install -m 2711 -o root -g utmp cleanutmp $(usrbin_prefix) || \ install -m 755 $(P) cleanutmp $(usrbin_prefix) install -m 755 $(P) ngetty.sortpfd ngetty.tiny ngetty-helper.tiny $(sbin_prefix) install: $(ALL) install -m 755 $(P) -d $(sbin_prefix) install -m 755 $(P) -d $(etc_prefix) install -m 700 $(P) -d $(ngetty_prefix) install -m 755 $(P) -d $(man8dir) install -m 755 $(P) ngetty ngetty-helper ngetty-argv $(sbin_prefix) install -m 644 $(P) ngetty.8.gz ngetty-*.8.gz $(man8dir) install -m 600 $(P) sample.Conf $(ngetty_prefix) install -m 755 $(P) contrib/setup $(ngetty_prefix) install -m 644 $(P) Version $(ngetty_prefix) test -f $(ngetty_prefix)/Conf || \ install -m 600 $(P) Conf $(ngetty_prefix) @echo @echo ' If you want to install some additional programs do:' @echo ' make install_other' clean: rm -f $(ALL) *.o *.a *.s *_defs.h *.hZ a.out tzmap_mmap.c \ *.c.orig test-helper opts_make ngetty.$(MYARCH) sstrip.* elf_print* rm -rf PACKAGE distclean: make clean rm -rf d dietlibc withdiet: @echo ' Please, start: make CC="diet -Os gcc"' dietlibc/bin-$(MYARCH)/diet: cvs -d :pserver:cvs@cvs.fefe.de:/cvs -z9 co dietlibc cd dietlibc && make dietbuild: dietlibc/bin-$(MYARCH)/diet DIETHOME=$(CURDIR)/dietlibc make CC="./$< -Os gcc -nostdinc" AUTHORS_SITE = http://riemann.fmi.uni-sofia.bg sstrip.bin: sstrip.c $(CCL) -DNV_PRINT_ELF_HEADER -o elf_print $^ ./elf_print < elf_print > elf_defs.h $(CCL) -o $@ $^ rm -f elf_print* sstrip.c: rm -f $@ wget -O $@ $(AUTHORS_SITE)/programs/$@ sstrip: $(ALL_EXEC) sstrip.bin ./sstrip.bin $(ALL_EXEC) ngetty.$(MYARCH) || true TAR=tar TAR_OPT= MY_NAME=$(notdir $(CURDIR)) GZIP_PR = 7za a -tgzip -si -so -bd Z tar: cd .. && $(TAR) -cv $(TAR_OPT) \ --owner=root --group=root --exclude $(MY_NAME)/dietlibc $(MY_NAME) | \ $(GZIP_PR) > $(MY_NAME).tar.gz packit: ( echo $(MY_NAME); date -u ) > Version make clean tar TAR=tar.f TAR_OPT=--sort package: make all install install_other DESTDIR=PACKAGE P= install ngetty.$(MYARCH) PACKAGE/sbin || true install contrib/*install* PACKAGE cd PACKAGE && tar -cvzf /tmp/$(MY_NAME)-$(MYARCH).tar.gz \ --owner=root --group=root * rpm: $(MY_NAME).spec rpmbuild -ba --clean $< ngetty-1.1/README0000644000000000000000000000162610770204447012255 0ustar rootrootSee http://riemann.fmi.uni-sofia.bg/ngetty/ ngetty is a daemon that starts login sessions on virtual console terminals, on demand. It is a good replacement for all those getty processes started from init that, most of the time, are only taking up memory. When compiled statically with dietlibc, the ngetty binary size is only about 2k and uses considerably less memory than a getty. I wrote ngetty inspired by logind. Many thanks Andre! logind source: http://anbadeol.googlepages.com/logind.html Quick install: 0. read the ngetty.8 manual page 1. browse lib.h (check if the LOGIN path is correct!) 2. edit Makefile to taste 3. build: make If dietlibc is available: make CC='diet -Os gcc -W' To build dietlibc try: make dietbuild 4. install: make install 5. if you want to some additional programs do: make install_other 6. see init.d/ngetty, /etc/ngetty/Conf, /etc/ngetty/sample.Conf. Nikola Vladov ngetty-1.1/README.upstart0000644000000000000000000000104311375176215013752 0ustar rootrootIf upstart (http://en.wikipedia.org/wiki/Upstart) is the default init (PID 1) save next -------------------------------- # ngetty start on runlevel [2345] stop on shutdown respawn exec /sbin/ngetty 1 2 3 4 5 6 -------------------------------- in /etc/init/ngetty.tmp and then type: mv /etc/init/ngetty.tmp /etc/init/ngetty.conf If you have running tty stop them before above "mv" with: stop tty1 stop tty2 ... See also: http://upstart.ubuntu.com/getting-started.html If someone uses ngetty with upstart and has more experience let me know. ngetty-1.1/Version0000644000000000000000000000005011376744054012741 0ustar rootrootngetty-1.1 Tue May 25 12:53:00 UTC 2010 ngetty-1.1/check_first.c0000644000000000000000000000246610760566561014037 0ustar rootroot#include #include "sysinfo_defs.h" #include "boottime_defs.h" #if !defined(HAVE_SYSTEM_SYSINFO) && !defined(HAVE_SYSTEM_BOOTTIME) int check_first(char *lock, struct stat *st) { return 0; } #else #include #include #include #include extern int get_uptime(time_t *t); int check_first(char *lock, struct stat *st) /*EXTRACT_INCL*/{ int k; /* If a stat error other than "no such file" occurs, I don't know what went wrong, so I'll proceed with caution by denying the autologin request. */ if ((k=stat(lock, st)) && errno != ENOENT) return 0; if (k==0) { time_t uptime; if (get_uptime(&uptime)) return 0; /* If there's been an autologin granted since the last boot, deny this and any subsequent attempts. Note that this test is skipped if the LOCK file doesn't exist. */ if (time(0) - uptime < st->st_mtime) return 0; } /* Create the LOCK file. The mtime of this file provides a persistent record of the last time that an autologin request was granted. Deny the autologin request if either the file open or file close fails. */ if ((k=open(lock, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0 || close(k)) return 0; /* All tests are okay, so grant the autologin request. */ return 1; } #endif ngetty-1.1/cleanutmp.c0000644000000000000000000000271311375752740013535 0ustar rootroot/* cleanutmp.c chown root.utmp cleanutmp chmod 2711 cleanutmp */ #include #include #include #include #include "lib.h" void ops(int n, const char *s0, const char *s1) { write(2,s0,str_len(s0)); write(2,s1,str_len(s1)); write(2,"\n",1); _exit(n); } #ifdef USE_LIBC_UTMP int main () { struct utmp_type *ut, u; setutent(); while (f_getutent()) { if (ut->ut_type != USER_PROCESS) continue; if (kill(ut->ut_pid, 0) && errno == ESRCH) { u = *ut; u.ut_type = DEAD_PROCESS; u.ut_tv.tv_sec = time(0); f_setutent(); if (0==f_pututline(&u)) ops(2,"error writing to: ", Utmp_File); f_updwtmp(Wtmp_File, &u); } } f_endutent(); return 0; } #else int main() { int fd,wfd; struct utmp_type ut[1]; off_t pos=0; if ((fd = open(Utmp_File,O_RDWR)) <0 && (fd = open(Utmp_File,O_RDONLY)) <0) ops(1,"error opening: ", Utmp_File); while (utmp_io(fd,ut,F_RDLCK)) { pos += UTMP_SIZE; if (ut->ut_type != USER_PROCESS) continue; if (kill(ut->ut_pid, 0) && errno == ESRCH) { ut->ut_type = DEAD_PROCESS; ut->ut_tv.tv_sec = time(0); pos -= UTMP_SIZE; if (lseek(fd, pos, SEEK_SET) != pos || !utmp_io(fd,ut,F_WRLCK)) ops(2,"error writing to: ", Utmp_File); pos += UTMP_SIZE; wfd=open(Wtmp_File, O_WRONLY|O_APPEND); write(wfd, ut, UTMP_SIZE); close(wfd); } } close(fd); return 0; } #endif ngetty-1.1/const_io.c0000644000000000000000000000046711016331323013344 0ustar rootroot#include #include int const_io(int (*op)(), int fd, void *buf, int len) /*EXTRACT_INCL*/{ char *x = buf; while (len > 0) { int ret = op(fd, x, len); if (ret <= 0) { if (ret && errno == EINTR) continue; break; } x += ret; len -= ret; } return len; } ngetty-1.1/contrib0000755000000000000000000000000011016052350012735 5ustar rootrootngetty-1.1/contrib/README.install0000644000000000000000000000027010771446546015365 0ustar rootrootTo install the package XXX.tar.gz do: mkdir /tmp/ngetty cd /tmp/ngetty tar -xvzf /path/to/XXX.tar.gz env -i ./install.sh See first if the paths in install.sh are correct! Nikola ngetty-1.1/contrib/install.sh0000755000000000000000000000222411002345412015020 0ustar rootroot#!/bin/sh -x export PATH=/bin:/usr/bin if [ "$DESTDIR" = "" ] ; then P="-o root -g root" fi prefix="$DESTDIR" mandir="$prefix/usr/share/man" man8dir="$mandir/man8" sbin_prefix="$prefix/sbin" etc_prefix="$prefix/etc" ngetty_prefix="$etc_prefix/ngetty" usrbin_prefix="$prefix/usr/bin" ### ----- stop editing here ----- if test ! -f ./etc/ngetty/Conf -o ! -x ./sbin/ngetty ; then echo go out exit 1 fi umask 022 mk_dir () { test -d $2 || install -m $1 $P -d $2 } mk_dir 755 $usrbin_prefix mk_dir 755 $sbin_prefix mk_dir 755 $man8dir mk_dir 755 $etc_prefix install -m 700 $P -d $ngetty_prefix install -m 755 $P ./usr/bin/* $usrbin_prefix install -m 2711 -o root -g utmp ./usr/bin/cleanutmp $usrbin_prefix || \ install -m 755 $P ./usr/bin/cleanutmp $usrbin_prefix install -m 755 $P ./sbin/* $sbin_prefix install -m 644 $P ./usr/share/man/man8/* $man8dir install -m 755 $P ./etc/ngetty/setup $ngetty_prefix install -m 644 $P ./etc/ngetty/Version $ngetty_prefix install -m 600 $P ./etc/ngetty/sample.Conf $ngetty_prefix test -f $ngetty_prefix/Conf || \ install -m 600 $P ./etc/ngetty/Conf $ngetty_prefix cd /etc/ngetty && test -x setup && ./setup ngetty-1.1/contrib/setup0000755000000000000000000000101011016052340014071 0ustar rootroot#!/bin/sh export PATH=/bin:/usr/bin test -f Conf.sed || exit 111 umask 077 z=`date '+%z %Z'` tz=`echo "$z" | awk '{ hour = substr($1, 1, 3); min = substr($1, 4, 2); if (hour < 0) min = -min; print (hour *60 +min) *60; }'` echo 'AUTO time zone: '$z' -> '$tz # merges lines ending with slash (/) like bash sed -e '1i# Auto-generated file. Do not edit! :a /[^\\]\\$/{ N s/\\\n// ta } s/^\([a-z0-9/]*=tz=\)AUTO$/\1'$tz'/ /^$/d /^[ # ]/d s/\\\\$/\\/ ' Conf.sed > 'Conf.__#*tmp*#' && mv 'Conf.__#*tmp*#' Confngetty-1.1/dumputmp.c0000644000000000000000000000320511376732562013416 0ustar rootroot#include #include #include "lib.h" #define S(a,b) str_copy(a,b) #define SN(a,b) str_copynz(a,b,sizeof(b)) #define N(a,b,c,d) fmt_nmb_(a,b,c,d) int main(int argc, char **argv) { struct tm *tm; time_t tmp_time; char buf[1024]; char *p; #ifdef USE_LIBC_UTMP struct utmp_type *ut; if (argc>1) f_utmpname(argv[1]); f_setutent(); #else struct utmp_type ut[1]; int fd=0; if (argc>1) { fd = open(argv[1], O_RDONLY); if (fd == -1) { write(1,buf,S(buf,"error open()\n")); _exit(1); } } #endif write(1,buf,S(buf,"type pid id user line host ip date " "[term exit]\n")); while (f_getutent()) { tmp_time = ut->ut_tv.tv_sec; tmp_time += get_tz(tmp_time); tm=nv_gmtime(&tmp_time); p = buf; *p++ = '['; p += N(p, ut->ut_type, 1,0); p +=S(p,"] ["); p += N(p, ut->ut_pid, 5,0); p +=S(p,"] ["); p += fmt_str_(p,ut->ut_id,4); p +=S(p,"] ["); p += SN(p, ut->ut_user); p +=S(p,"] ["); p += SN(p, ut->ut_line); p +=S(p,"] ["); p += SN(p, ut->ut_host); p +=S(p,"] ["); p += fmt_utmp_ip(p, (char *)ut->ut_addr_v6); p +=S(p,"] ["); p += fmt_ulong(p, (1900 +tm->tm_year) % 100); *p++ = '-'; p += N(p, 1+tm->tm_mon,2,1); *p++ = '-'; p += N(p, tm->tm_mday, 2,1); *p++ = ' '; p += N(p, tm->tm_hour, 2,1); *p++ = ':'; p += N(p, tm->tm_min, 2,1); *p++ = ':'; p += N(p, tm->tm_sec, 2,1); if (argc>2) { p +=S(p,"] ["); p += fmt_ulong(p,ut->ut_exit.e_termination); *p++ = ' '; p += fmt_ulong(p,ut->ut_exit.e_exit); } p +=S(p,"]\n"); write(1,buf, p-buf); } f_endutent(); return 0; } ngetty-1.1/fmt_nmb_.c0000644000000000000000000000041510746057707013325 0ustar rootrootunsigned int fmt_nmb_(char *b, unsigned long u, char len, char fill) /*EXTRACT_INCL*/ { unsigned char k=len; char ch = (fill)?'0':' '; do { if (k == 0) break; b[--k] = '0' + u%10; u /= 10; } while (u); while (k) b[--k] = ch; return len; } ngetty-1.1/fmt_number.h0000644000000000000000000000055311376252434013704 0ustar rootroot#define fmt_number_macro(f,type,base) \ unsigned int f(char *s, type u) {\ type tmp=u;\ unsigned int len=0;\ do { tmp /=base; ++len; } while(tmp);\ if (s) {\ s +=len;\ do {\ unsigned char c = u%base;\ if (base <= 10) *--s = c+'0';\ else *--s = (c<10) ? c+'0' : c-10+'a';\ u /=base;\ } while (u);\ }\ return len;\ } ngetty-1.1/fmt_str_.c0000644000000000000000000000026510746047044013355 0ustar rootroot#include "str_defs.h" unsigned int fmt_str_(char *b, char *s, unsigned int len) /*EXTRACT_INCL*/{ unsigned int k = str_add(b,s,len); while (k #define Z(X) #define sn(X) tod = X; goto no void fmt_time(char *fmt) /*EXTRACT_INCL*/{ uint32_t day, mon, year, tod; uint32_t tm_wday, tm_sec, tm_min, tm_hour; #if 0 uint32_t yday=0; #endif char buf[16], *m; time_t now = time(0); now += get_tz(now); tod = (uint32_t)now % 86400; day = (uint32_t)now / 86400; tm_wday = ((day+4) % 7); tm_sec = tod%60; tod /= 60; tm_min = tod%60; tm_hour = tod/60; year = 4*day + 2; year /= 1461; day += 671; day %= 1461; /* day 0 is march 1, 1972 */ Z(if (day < 306) yday = 1); if (day == 1460) { day = 365; Z(yday = 59); } else { day %= 365; Z(yday += (day + 59) % 365); } day *= 10; mon = (day + 5) / 306; day = day + 5 - 306 * mon; day /= 10; if (mon >= 10) mon -= 10; else mon += 2; /* day 0,1,30, mon 0..11, year 1970=0,1,2 */ year += 1970; day += 1; for (; (*buf=*fmt); ++fmt) { tod = 1; m = Oo[Omonths] + 3*mon; switch (*buf) { no: if (tod<10) out_char('0'); tod = fmt_ulong(buf,tod); break; case 'Y': sn(year); case 'm': sn(mon +1); case 'd': sn(day); case 'H': sn(tm_hour); case 'M': sn(tm_min); case 'S': sn(tm_sec); case 'a': m = Oo[Odays] + 3*tm_wday; case 'b': tod = str_copynz(buf,m,3); } buf[tod] = 0; out_puts(buf); } } ngetty-1.1/fmt_ulong.c0000644000000000000000000000022610754326340013525 0ustar rootroot#include "fmt_number.h" fmt_number_macro(fmt_ulong, unsigned long, 10) #if 0 unsigned int fmt_ulong(char *s, unsigned long u) /*EXTRACT_INCL*/ #endif ngetty-1.1/fmt_utmp_ip.c0000644000000000000000000000176111376737517014100 0ustar rootroot#include "fmt_defs.h" #include /* ip must be int32_t aligned */ unsigned int fmt_utmp_ip(char *buf, const char ip[16]) /*EXTRACT_INCL*/{ unsigned int temp, k, pos0=0, len0=0, pos1=0, compr=0; int32_t *u = (void *)ip; char *s = buf; if (u[1]==0 && u[2]==0 && u[3]==0) { if (u[0]) { for (k=0; k<4; k++) { s += fmt_ulong(s, (unsigned char)ip[k]); if (k<3) *s++ = '.'; } } } else { for (k=0; k<16; k+=2) { if (ip[k]==0 && ip[k+1]==0) { if (!compr) { compr=1; pos1=k; } if (k==14) { k=16; goto last; } } else if (compr) { last: if ((temp=k-pos1) > len0) { len0=temp; pos0=pos1; } compr=0; } } for (k=0; k<16; k+=2) { if (pos0==k && len0) { if (k==0) *s++ = ':'; *s++ = ':'; k += len0-2; continue; } temp = ((unsigned long) (unsigned char) ip[k] << 8) + (unsigned long) (unsigned char) ip[k+1]; s += fmt_xlong(s, temp); if (k<14) *s++ = ':'; } } *s = 0; return s-buf; } ngetty-1.1/fmt_xlong.c0000644000000000000000000000022611376251607013534 0ustar rootroot#include "fmt_number.h" fmt_number_macro(fmt_xlong, unsigned long, 16) #if 0 unsigned int fmt_xlong(char *s, unsigned long u) /*EXTRACT_INCL*/ #endif ngetty-1.1/fork_and_exec.c0000644000000000000000000000051310746152535014325 0ustar rootroot#include #include #include extern char **environ; void fork_and_exec(char *line) /*EXTRACT_INCL*/{ if (line) { char *qq[4] = { "/bin/sh", "-c", line, 0 }; pid_t pid=fork(); if (pid==-1) return; if (pid==0) { execve(*qq,qq,environ); _exit(127); } waitpid(pid,0,0); } } ngetty-1.1/get_headers0000755000000000000000000000117010766516675013605 0ustar rootroot#!/bin/sh [ $# -lt 2 ] && exit 1 export PATH=/bin:/usr/bin name=`echo $1 | sed -e 's/\./__DOT__/g' -e 's/\//__SLASH__/g'` shift echo '#ifndef' AUTO_FILE__$$__$name echo '#define' AUTO_FILE__$$__$name echo '/* '`date`' */' while test $# -gt 0; do case $1 in -L*) echo $1 | sed -e 's/^../#include "/' -e 's/$/"/' ; shift;; -G*) echo $1 | sed -e 's/^../#include /' ; shift;; -I*) echo $1 | sed -e 's/^../#include /'; shift;; *) break;; esac done if [ $# -gt 0 ] ; then sed -n -e 's/\(.*\) \/\*EXTRACT_INCL\*\/.*/extern \1;/p' \ -e 's/ \/\*EXTRACT_UNMOD\*\/.*//p' $@ fi echo '#endif' ngetty-1.1/get_uptime.c0000644000000000000000000000122510760573632013702 0ustar rootroot#include "sysinfo_defs.h" #include "boottime_defs.h" #include #include #ifdef HAVE_SYSTEM_SYSINFO #include int get_uptime(time_t *uptime) /*EXTRACT_INCL*/{ struct sysinfo info; if (sysinfo(&info)) return -1; *uptime = info.uptime; return 0; } #else #ifdef HAVE_SYSTEM_BOOTTIME #include #include int get_uptime(time_t *uptime) { struct timeval res = { 0, 0 }; int req[2] = { CTL_KERN, KERN_BOOTTIME }; size_t res_len = sizeof res; if (sysctl(req, 2, &res, &res_len, 0, 0) >= 0 && res.tv_sec > 0) { *uptime = res.tv_sec; return 0; } return -1; } #endif #endif ngetty-1.1/init.d0000755000000000000000000000000011031630505012463 5ustar rootrootngetty-1.1/init.d/ngetty0000755000000000000000000000213211030377223014004 0ustar rootroot#!/bin/sh # To set correct TERM edit /etc/ngetty/Conf. Examples: #=environ=,TERM=linux #=environ=,TERM=vt100,OTHER_ENV=123,PATH=/usr/bin:/bin,HOME=/ # It's possible to start ngetty also by init. Comment the lines # for getty in /etc/inittab and add a line for ngetty. Example: # # # Run gettys in standard runlevels # # 1:2345:respawn:/sbin/mingetty tty1 # ... # # 6:2345:respawn:/sbin/mingetty tty6 # # # Run ngetty in standard runlevels # ng:2345:respawn:/sbin/ngetty 1 2 3 4 5 6 # cmdline="ngetty 8 9 10" pid="/var/run/ngetty-8-9-10.pid" exe="/sbin/ngetty" starter="/sbin/ngetty-argv" case $1 in start) cd / if [ -f $pid ] ; then echo May be one ngetty is running now echo If not, remove the file $pid exit 1 fi if [ -x /sbin/ngetty-helper ] ; then $starter " -D -S -e -p$pid -- $exe $cmdline" user null else echo $0: Unable to find /sbin/ngetty-helper exit 1; fi ;; stop) pkill -fx "$cmdline" rm -f $pid ;; status) [ -f $pid ] && read n < $pid [ $? -eq 0 ] && echo ngetty PID is: $n ;; *) echo "Usage: $0 start|stop|status" exit 1 esac ngetty-1.1/lib.h0000644000000000000000000000172711376725645012331 0ustar rootroot#ifndef LIB_H #define LIB_H /* Pathname of the login(1) program. */ #define LOGIN "/bin/login" /* Start ngetty with ohter appl: /sbin/ngetty -H/path/to/helper 1 2 3 */ // #define NEED_HELPER_OPTION /* Define one of the next to use libc utmp() or utmpx() functions */ // #define HAVE_C_UTMP // #define HAVE_C_UTMPX /* Poll only nonnegative fd */ // #define NGETTY_SORT /* ----- stop changes here ----- */ /* Pathname of the ngetty-helper program. */ #define NGETTY_HELPER "/sbin/ngetty-helper" extern char **environ; #define GLOBAL_fstat_READ(fd,st,s, len,max_len, plus) \ fstat(fd,&st) || (unsigned int)(len=st.st_size) > max_len || \ (s=alloca(len+plus))==0 || const_io((int(*)())read,fd,s,len) #define GLOBAL_split_plus(aa,s,ch, len,plus) do { /* aa must be 0 !!! */ \ len=splitmem(aa,s,ch); \ if (aa) break; \ aa=alloca((len+plus) * sizeof(char*)); } while(1) #define GLOBAL_split(aa,s,ch, len) GLOBAL_split_plus(aa,s,ch, len,1) #include "all_defs.h" #endif ngetty-1.1/ngetty-1.1.spec0000644000000000000000000000251411122004620014034 0ustar rootrootSummary: getty replacement - one single daemon for all consoles Name: ngetty Version: 1.1 Release: 1 Group: System Environment/Daemons Packager: Blair Lowe Source: http://riemann.fmi.uni-sofia.bg/ngetty/ngetty-%{version}.tar.gz URL: http://riemann.fmi.uni-sofia.bg/ngetty/ License: GPL Prefix: / BuildRoot: %{_tmppath}/%{name}-%{version}-root %description Ngetty is a daemon that starts login sessions on virtual console terminals, on demand. It is a good replacement for all those getty processes started from init that, most of the time, are only taking up memory. When compiled statically with dietlibc, the ngetty binary size is only about 2k and uses considerably less memory than a getty. You have to edit /etc/inittab to make ngetty default. See the manual page or the examples on ngetty home page. %prep %setup -q %build make CC='diet -Os gcc -W' prefix=${RPM_BUILD_ROOT} %install make install install_other prefix=${RPM_BUILD_ROOT} %clean rm -rf ${RPM_BUILD_ROOT} %post ( cd /etc/ngetty && test -x setup && ./setup ) || true %postun %files %defattr(-,root,root) /sbin /usr /etc %doc README %changelog * Thu Apr 10 2008 Nikola Vladov - remove /usr prefix - add option for dietlibc * Fri Mar 12 2008 Blair Lowe - Create rpm for Nikola Vladov ngetty-1.1/ngetty-argv.c0000644000000000000000000000673211376207741014016 0ustar rootroot#include #include #include #include #include #include #include #include #include "lib.h" #define UUU "unable to " void w(char *s) { write(2, s, str_len(s)); } void e(char *x0, char *x1) { w("\nngetty-argv: "); w(x0); w(x1); w("\n"); sleep(1); } /* sleep is needed to see the erros. see the option clear also */ unsigned int expand_string(char *tmp, char *string, char *user, char *tty) { char *s=string, *pos=tmp, *exp, ch, found_one = 0; for (; (ch=*s); s++) { if (ch == '%') { found_one = 1; ch = s[1]; exp = user; switch (ch) { case 'T': exp = tty; case 'U': pos += (tmp) ? str_copy(pos, exp) : str_len(exp); ++s; break; case '%': /* %%U -> %U */ ++s; default: ch = *s; goto non_special; } } else { non_special: if (tmp) *pos = ch; ++pos; } } if (found_one) { if (tmp==0) return pos - tmp + 1; else *pos = 0; } return 0; } int main(int argc, char **argv) { char **arg=0, **ee, **aa, *in=0, *s, ch; char *user, *tty, flagsetsid=0, flagdaemon=0, flagtty=0, *flagpid=0; unsigned long n; uid_t uid=0; gid_t gid=0; if (argc<2) { usage: e("usage:\n\tngetty-argv [Options][--]ArgvString [user [tty]]\n\n", "\tArgvString:\t:/bin/sleep:hacker_sleep:39:other:args...\n" "\tOptions:\t:-D:-S:-N:-C:-u123:-g59:-a45:-s3:-d/tmp:-r/var/tmp\n" "\tOptions:\t:-e,HOME=/,TERM=linux:-p/var/run/ngetty.pid\n" "\tExample:\t:-u106:-g506:-d/var/qmail:--:./bin/qmail-qread:queue\n"); return 100; } user =(argc>2) ? argv[2] : ""; tty =(argc>3) ? argv[3] : ""; do { n = expand_string(in, argv[1], user, tty); if (n==0) break; in = alloca(n); } while (1); if (in==0) in=argv[1]; ch = *in++; /* don't use '%' as split char */ if (ch == 0 || *in == 0) goto usage; GLOBAL_split_plus(arg,in,ch, n,5); if (n < 2) goto usage; for (aa=arg; (s=*aa); aa++) { if (*s != '-') break; s += 2; n=x_atoi(s); switch (s[-1]) { case 'e': ee = 0; ch = *s++; if (ch) GLOBAL_split(ee,s,ch, n); environ = ee; break; case 'D': flagdaemon=1; break; case 'S': flagsetsid=1; break; case 'N': flagtty=1; break; case 'C': flagtty=2; break; case 'p': if (*s) flagpid=s; break; case 'g': gid = n; break; case 'u': uid = n; break; case 'a': alarm(n); break; case 's': sleep(n); break; case 'd': if (chdir(s)) { e(s, ": chdir error"); return 100; } break; case 'r': if (chroot(s)) { e(s, ": chroot error"); return 100; } break; case '-': aa++; goto do_it; default: e(s-2, " : unknown option"); return 1; } } do_it: if (flagdaemon) { int pid; while ((pid=fork()) <0) sleep(1); if (pid) _exit(0); } if (flagsetsid) setsid(); if (flagtty==1) ioctl(0, TIOCNOTTY, (void *)1); if (flagtty==2) ioctl(0, TIOCSCTTY, (void *)1); if (flagpid) { int fd = open(flagpid, O_RDWR | O_TRUNC | O_CREAT, 0644); if (fd>=0) { char tmp[3*sizeof(unsigned long)]; n=fmt_ulong(tmp, getpid()); tmp[n] = '\n'; write(fd, tmp, n+1); close(fd); } } if (uid || gid) { if (gid==0) gid = uid; if (setgroups(1,&gid) || setgid(gid) || setuid(uid)) { e(UUU, "set uidgid"); return 100; } } s = *aa++; if (s==0 || *aa==0) return 0; if (aa[0][0] == 0) aa[0] = s; execve(s, aa, environ); e(s, ": exec error"); return 127; } ngetty-1.1/ngetty-helper.c0000644000000000000000000002004311376202705014320 0ustar rootroot#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "lib.h" #include "opts_defs.h" /* most of the functions here (like str_copy, fmt_ulong) have manual pages in libowfat; http://www.fefe.de/ see also opts_defs.h for o[Oxxx]; man ngetty */ /* see out_put.c; man buffer */ #define outs(X) out_puts(X) #define GO_out "go out!" static struct utsname uts; static struct stat st; static char *tty, *o_opt, o_endchar; char **Oo = o; /* see opts_defs.h */ static void tty_flush() { ioctl(0, TCFLSH, TCIFLUSH); } /* Format of o[Oprint]: ab:cq:09:AZ:...; man ngetty return -1 if 'ch' does not belongs to the set o[Oprint]; 0 success */ static int char_allow(unsigned char ch) { unsigned char c0, c1, *x = (unsigned char *)o[Oprint]; again: c0 = x[0]; if (!c0) return -1; c1 = x[1]; if (!c1) return -1; if (c0 <= ch && ch <= c1) return 0; if (x[2] == ':') { x += 3; goto again; } return -1; } /* print maximal 'len' chars from 's'; see strncpy, snprintf, printf */ static void out_max(char *s, unsigned int len) { char c = 0; if (s == uts.nodename && !o[Olonghostname]) c = '.'; while (len && *s && *s != c) { out_char(*s); ++s; --len; } } #define Out_MAX(X) x=X; len=sizeof(X); goto system /* print string with escapes; man ngetty; man issue */ static void output_special_char(char *s, int len) { char *last = s + len; while (s < last) { char *x, c; if (*s != '\\') { out_char(*s); ++s; continue; } if (++s == last) return; c = *s++; switch (c) { case 's': Out_MAX(uts.sysname); case 'n': Out_MAX(uts.nodename); case 'r': Out_MAX(uts.release); case 'v': Out_MAX(uts.version); case 'm': Out_MAX(uts.machine); case 'o': Out_MAX(uts.domainname); system: out_max(x,len); break; case 'l': outs(tty); break; #ifndef DONT_NEED_ESC_TIME case 't': x = "H:M:S"; goto do_time; case 'd': x = (o[Odatestring]) ? "a b d Y" : "Y-m-d"; do_time: fmt_time(x); break; #endif #ifndef DONT_NEED_ESC_USERS case 'u': case 'U': { char ubuf[8 + 3*sizeof(unsigned long)], *x = ubuf; unsigned long usrs = utmp_users(); x += fmt_ulong(x, usrs); if (c=='U') { x += str_copynz(x, " users", 10); if (usrs==1) --x; } *x = 0; outs(ubuf); } break; #endif default: if (s+1 < last) { unsigned char uch = (unsigned char)c-'0'; if (uch < 4) { /* XXX \0xy is not tested */ c = (uch<<6) | ((s[0]-'0')<<3) | (s[1]-'0'); s += 2; } } out_char(c); } } } /* print string 's' with escapes; man ngetty */ static void Out_sp_ch(char *s) { output_special_char(s, str_len(s)); } /* exception: print string 's' and exit with status 'i' */ void error(char *s,int i) { struct timespec ts = { 2, 500111222 }; Out_sp_ch("\nngetty-helper: \\d \\t \\l: "); outs(s); out_char('\n'); out_flush(); nanosleep(&ts, 0); tty_flush(); _exit(i); } /* print /etc/issue and login prompt; man issue */ static void do_prompt() { int fd,len; char *s; Out_sp_ch(o[Onewline]); s = o[Oissuefile]; if (s[0] && (fd=open(s, O_RDONLY)) >= 0) { if (GLOBAL_fstat_READ(fd,st,s, len,64000, 1)) _exit(1); close(fd); output_special_char(s, len); } Out_sp_ch(o[Ologinprompt]); out_flush(); } /* get login name in logname. max length = last-logname man ngetty; options: login-buffer, timeout */ static void get_logname(char *logname, char *last) { char *c; alarm(x_atoi(o[Otimeout])); for (;;) { for (c=logname;; c++) { if (c == last) error("login name too long",11); if (read(0,c,1)<1) { if (errno==EINTR || errno==EIO || errno==ENOENT) _exit(0); error("received strange error",9); } if (*c == '\n' || *c == '\r') { *c=0; break; } if (char_allow((unsigned char)*c)) error("bad character in login name",10); } /* end read */ if (*logname == '-') error("username may not start with a dash",13); if (*logname) break; do_prompt(); } alarm(0); } /* parse string; store it in o[XXX]; see opts_defs.h; /etc/ngetty/Conf */ static char *opt_get(char *s, int len) { if (*o_opt == *s) { char *x = o_opt; if (!str_diffn(x,s,len) && x[len] == o_endchar) { if (o[Odebug] && s != tty) { outs(x - 1); out_char('\n'); } return x+len+1; } } return 0; } /* return 1 if user is in s, otherwise 0; Format of s: ,ab,uvw,MlqR, ... ,last */ static char in_list(char *s, const char *user) { char ch; int len; if (s==0 || *s==0 || user==0) return 0; len = str_len(user); ch = *s++; again: if (!str_diffn(s,user,len)) if (s[len]==ch || s[len]==0) return 1; while (*s && *s != ch) s++; if (*s++) goto again; return 0; } /* set controlling tty */ static void set_ctty() { if (setsid() == -1 || ioctl(0, TIOCSCTTY, (void *)1)) error(GO_out, 111); } int main(int argc,char *argv[]) { int fd,len; char *s; struct termios term; if (argc < 2) _exit(100); o[Oautologinfirst] = o[Onoclearfirst] = o[Oautologinname] = ""; o[Oissuefile] = "/etc/issue"; o[Ologinprog] = LOGIN; o[Oprint] = "az:AZ:09:,.:__"; o[Otimeout] = "180"; o[Ologinprompt] = "\\n login: "; o[Onewline] = "\n"; o[Oclear] = "\033c"; #ifndef DONT_NEED_ESC_TIME o[Omonths] = "JanFebMarAprMayJunJulAugSepOctNovDec"; o[Odays] = "SunMonTueWedThuFriSat"; o[Otz] = "/etc/localtime"; #endif tty = argv[1]; uname(&uts); if (dup(0) !=1 || dup(0) !=2 || ioctl(0,TCGETS,&term)) error(GO_out, 100); if (!str_diffn(tty, "/dev/", 5)) tty += 5; if ((fd = open(NGETTY_HOME "/Conf", O_RDONLY)) >=0) { char **aa=0, *q; int tty_len = str_len(tty); /* 40 bytes for Months or Days */ if (GLOBAL_fstat_READ(fd,st,s, len,64000, 40)) _exit(1); close(fd); if (st.st_uid || st.st_gid || (st.st_mode & 07177)) len = 0; s[len]=0; GLOBAL_split(aa,s,'\n', len); for (; *aa; aa++) { s=aa[0]; if (*s==0 || *s=='#' || *s=='\t' || *s==' ') continue; o_endchar = '='; if (*s=='=') o_opt = s+1; else { o_opt = s; if (!(o_opt = opt_get(tty, tty_len))) continue; } for (len=0, q=(char *)P_opt; len < MAX_options; len++) { int k = P_len[len]; if (len >= MAX_equal) o_endchar = 0; if ((s = opt_get(q, k))) { o[len] = s; break; } q += k; } } } if ((s=o[Onice])) nice(x_atoi(s)); if ((s=o[Oenviron])) { char **ee=0, ch=*s++; if (ch) GLOBAL_split(ee,s,ch, len); environ=ee; } if (argc>2 && argv[2][0] == 'l') { /* get logname and execve() login */ char *loginargv[]={ o[Ologinprog], "--", 0, 0, 0 }; fork_and_exec(o[OshB]); s = o[Oautologinfirst]; if (*s && !check_first(s,&st)) o[Oautologinname] = ""; s = o[Oautologinname]; if (*s) { loginargv[1] = "-f"; loginargv[2] = s; } else { o[Oissuefile] = ""; if (!o[Onousername]) { char *last, *buf = o[Ologinbuffer]; if (buf) last = buf + str_len(buf); else { buf = alloca(41); last = buf + 40; } loginargv[2] = buf; get_logname(buf, last); } } if (o[Oechooff]) { term.c_lflag &= ~(ECHO|ISIG); ioctl(0, TCSETS, &term); } if ((s=o[Ologinargv])) { loginargv[1] = s; /* change '--' or '-f' with login-argv */ loginargv[3] = tty; } s = loginargv[2]; if (in_list(o[Odeny],s) || (o[Oallow] && in_list(o[Oallow],s)==0)) error("login is disabled",14); out_flush(); tty_flush(); utmp_do(1,tty); if ((s=o[Ochroot])) chroot(s); if ((s=o[Ochdir])) chdir(s); set_ctty(); execve(*loginargv, loginargv, environ); } else { /* print /etc/issue and exit */ char *clear = o[Oclear]; tty_flush(); fork_and_exec(o[OshA]); if ((s=o[Odelay])) { struct timespec ts = { x_atoi(s), 100200300 }; nanosleep(&ts, 0); } s = o[Onoclearfirst]; if (*s && check_first(s,&st)) clear = ""; Out_sp_ch(clear); utmp_do(0,tty); do_prompt(); #ifdef HAVE_SYSTEM_VHANGUP if (!o[Onohangup]) { set_ctty(); vhangup(); } #endif } _exit(0); } ngetty-1.1/ngetty.80000644000000000000000000003521011376204130012764 0ustar rootroot.TH NGETTY 8 "May 2010" . .SH NAME . .BR ngetty \- daemon for virtual console terminals . .SH SYNOPSIS .BR ngetty [ tty1 | vc/1 | 1 ] [ /dev/tty2 | vc/2 | 2 ] ... .br .BR ngetty-helper /dev/ttyX [ login ] .br .BR ngetty-argv :options:child:[name]:args [user [tty]] . .SH DESCRIPTION . .B ngetty is a daemon that starts login sessions on virtual console terminals, on demand. It opens the virtual console terminals specified by the .I tty... arguments, displays a .IR /etc/issue message, prints the login prompt on each terminal and waits for user name. On user action, .B ngetty executes .BR login (1) in a new process with the terminal the user is typing in as the controlling terminal. .PP .BR login (1) then prompts for a password to login with the system and finally, if the login succeeds, executes the user's login shell. .PP When the user logs out, .B ngetty restarts the corresponding virtual console terminal. .PP .PP Actually almost the whole work is done by a .B ngetty-helper program. It makes .IR /var/run/utmp , .IR /var/log/wtmp records, prints .IR /etc/issue , hostname, login prompt, waits for user name. .B ngetty invokes the .B ngetty-helper by need. . .SH HISTORY . The traditional way to enable logins on virtual console terminals is to start a bunch of .BR getty (8) programs, one for each virtual console terminal, from .BR init (8). As most users rarely login on virtual console terminals nowadays, preferring graphical logins instead, it seems wasteful to have all those .BR getty (8) processes doing nothing but wasting memory. Alternatively, .B ngetty manages logins on any number of virtual console terminals from a single, light, process. . .SH INVOCATION . .B ngetty does not use stdin, stdout or stderr and closes them. .PP When running .B ngetty in the background, remember to disassociate it from the current controlling terminal by making it the process group leader of a new session, e.g.: .PP .RS 4 setsid ngetty tty... & .br ngetty-argv :-D:-S:-e:--:/sbin/ngetty::1:2:3:4 .RE .PP To start .B ngetty from .BR init (8), add something like this to .IR /etc/inittab : .PP .RS ng:2345:respawn:/sbin/ngetty tty1 tty2 ... tty6 .RE .PP If .B ngetty-argv is available use it to start ngetty from .IR /etc/inittab . See the example bellow. . .SH DIAGNOSTICS . If .B ngetty can not open one of the virtual console terminals specified in the .I tty... arguments, most likely because that .I tty device node does not exist, no greeting message will be displayed on that terminal, obviously, and .B ngetty will simply go on, ignoring the offending terminal. Create the missing .I tty device and send SIGCHLD to ngetty. Then it will reopen the new .IR tty . Instead of sending SIGCHLD you can login and logout on some working .IR tty . This also forces ngetty to reopen the new .IR tty . . .PP .B ngetty uses .B ngetty-helper program. It's path is hard-coded in .BR ngetty . Never remove .B ngetty-helper program nor move it to other location. .PP If, on user action, .B ngetty-helper can not execute .BR login (1), in all likelihood because the compiled-in .B LOGIN path does not match your system's .BR login (1) path, .B ngetty restarts the terminal and redisplays the greeting message. .PP In any case, .B ngetty does not output error messages. .PP .SH OPTIONS It's possible to set different options for .B ngetty\-helper program in file .IR /etc/ngetty/Conf . If the option begin with "=" it's applied for all tty. If it start with a tty name it's applied only on current tty. Examples: .PP .RS .B # options format: .br .B # [ttyX]=option[=value] .br .B #=debug .br =environ=,TERM=linux .br tty3=long-hostname .br tty1=clear=\e033c .br =newline= .br =timeout=180 .br tty1=timeout=60 .br tty1=delay=1 .RE .PP For security reasons .B ngetty-helper evaluate the file .IR /etc/ngetty/Conf only if it has mode: .PP .RS -rw------- root root /etc/ngetty/Conf .RE . .PP .B ngetty-helper recognizes the following options which might be embedded in the .I /etc/ngetty/Conf file: .TP .B # tty5=login-prog=/bin/login.test If a line starts with .BR # , .B space or .B tab it is a comment. .TP .B debug If debug is set .B ngetty-helper write on terminal all successfully applied options. Set this on the fist line of .IR /etc/ngetty/Conf file. .TP .B date-string Escape \fB\\d\fP (current day) in .IR /etc/issue as: .br \fBFri Jun 01 2007\fP. Default is: \fB2007-06-01\fP. .TP .B days=string Abbreviation for week days (21 bytes). Default is: .br .B =days=SunMonTueWedThuFriSat .TP .B months=string Abbreviation for months (36 bytes). Default is: .br .B =months=JanFebMarAprMayJunJulAugSepOctNovDec .TP .B tz=string Change the timezone offset. If the string starts with slash it's the name of tzfile. The string is positive number if the local time zone is east of the Prime Meridian and negative if it is west. Default is .IR /etc/localtime . Examples: .br \fB=tz=-18000\fP -0500 .br \fB=tz=7200\fP +0200 .br \fB=tz=/etc/localtime\fP .br \fB=tz=AUTO\fP .TP .B echo-off Turn the echo off just before starting /bin/login. It's similar to \fBstty -echo\fP. .TP .B newline=string Print this \fBstring\fP before writing out .IR /etc/issue . (default is \fB\e012\fP). Example: .br .B tty3=newline=\e012I am \el\e012 .TP .B clear=string Clear the screen before prompting for the login name with the \fBstring\fP (default is \fP\e033c\fP). Examples: .br .B tty1=clear= .br .B tty3=clear=\e033[H\e033[J .TP .B noclear-first=/etc/ngetty/.noclear Do not clear the screen before prompting for the login name the first time after reboot. Example: .br .B tty1=noclear-first=/etc/ngetty/.noclear.tty1 .TP .B nohangup Do not call vhangup() to disable writing to this tty by other applications. .TP .B long\-hostname By default the hostname is only printed until the first dot. With this option enabled, the full text from gethostname() is shown. . .TP .B nousername Do not ask for user name. Exec login(1) immediately. Example: .br .B =nousername .br \fB=login-prompt= Press ENTER to activate \el\bP . .TP .B deny=,black,list,users... Disable login process for some users. The first char after "deny=" is split char. Example: .br .B tty1=deny=,root,nobody,guest .TP .B allow=,white,list,users... Enable login process only for the users. The first char after "allow=" is split char. Example: .br .B =clear= .br .B =allow=,root,operator . .TP .B print=an:CM:PY:04:69 Accept only these chars in user name. Default is to accept only "\fB,-._ 0-9 a-z A-Z\fP". It's possible to insert here the output of .br .B printf 'tty3=print=az:AZ:\eABC\eXYZ:__' .br Here \fBABC\fP and \fBXYZ\fP are octal numbers. Examples: .br .B tty1=print=az:AZ .br .B tty2=print=az:AZ:__:,.:09 .TP .B issue-file=/etc/issue Change the issue file. Disable printing of the issue file with: .br .B =issue-file= .TP .B login-prog=/bin/login Change the login app. It's possible to use fgetty's .IR /bin/login1 application with: .br .B =echo-off .br .B =login-prog=/bin/login1 .TP .B login-buffer=string Read login name over the \fBstring\fP. Default string is 40 bytes long. Example: .br .B =login-buffer=12345678901234567 .TP .B login-prompt=\en login: Change the login prompt string. Example: .br \fB=login-prompt=\e033[1;33m\el\e033[0;39m \en login: \fP .TP .B nice=10 Change the priority by calling nice(). .TP .B delay=5 Sleep this many seconds before printing the file /etc/issue. .TP .B timeout=180 Wait at most this many seconds for user name. .TP .B chdir=/home Change into this directory before calling the login prog. .TP .B chroot=/chroot Call chroot() with this directory name. .TP .B autologin-name=username Log the specified user automatically in without asking for a login name and password. Check the \-f option from .B /bin/login for this. Example: .br .B tty1=autologin-name=maria .TP .B autologin-first=/etc/ngetty/.autologin Log in automatically only the first time after reboot without asking for a login name and password. Example: .br .B tty1=autologin-name=maria .br .B tty1=autologin-first=/etc/ngetty/.autologin .TP .B environ=,TERM=linux Replace the environ. The first char after "environ=" is split char. Examples: .br .B =environ=,TERM=vt100,PATH=/bin:/usr/bin,HOME=/ .br .B tty3=environ=,TERM=linux,TTY=/dev/tty3 .TP .B sh-A=line Exec this line before printing .IR /etc/issue . The line is executed using .B /bin/sh -c .IR line . It's good idea to use the full paths here. Example: .br .B tty4=sh-A=exec /bin/ps e -u root .br .B tty4=delay=8 .TP .B sh-B=line Similar to option .B sh-A. This is executed before asking for username. .TP .B login-argv=any_string Ngetty starts login application with options .br \fBlogin -- XYZ\fP # default .br \fBlogin -f XYZ\fP # if autologin-name=XYZ .br With this option it's possible to start login appl with \fBany_string\fP instead of \fB\--\fP or \fB-f\fP. Using the program \fBngetty-argv\fP(8) one can start arbitrary program with different arguments. Two very dangerous examples are (never try them): .br .B tty4=login-prog=/sbin/ngetty-argv .br .B tty5=login-prog=/sbin/ngetty-argv .br .B tty4=login-argv=,/bin/login,,-f,%U .br .B tty5=login-argv=:-C:/bin/bash:-bash . .PP .SH "WARNING" If ngetty-helper finds stdout or stderr open it exits immediately with error 100. Ngetty invokes it correctly. See also the program test-helper.c in source package. .PP Do not edit the file .IR /etc/ngetty/Conf directly. Put the configurations in .IR /etc/ngetty/Conf.sed (the same syntax and permissions as .IR /etc/ngetty/Conf ) and after editing it, execute: .PP .RS .B cd /etc/ngetty && ./setup .RE .PP The script .I /etc/ngetty/setup removes comments, merges lines ending with a backslash and expands the string \fB=tz=AUTO\fP to numeric number. Then it updates .IR /etc/ngetty/Conf . .PP .SH "SIGNALS" If ngetty receives SIGTERM it kill all child's PID (first with SIGTERM and then with SIGKILL) and exit immediately. It does not change UID, GID and mode of the controlling tty devices. It does not catch the other signals. Sending SIGCHLD to ngetty forces it to reread his internal cache tables and to restart failed tty devices. . .PP .SH "ISSUE ESCAPES" .B ngetty-helper recognizes the following escapes sequences which might be embedded after \fBlogin-prompt=\fP, \fBnewline=\fP, \fBclear=\fP or in the .I /etc/issue file: .IP \fB\ed\fP insert current day (localtime), .IP \fB\el\fP insert line on which .B ngetty is running, .IP \fB\em\fP inserts machine architecture (uname -m), .IP \fB\en\fP inserts machine's network node hostname (uname -n), .IP \fB\eo\fP inserts domain name, .IP \fB\er\fP inserts operating system release (uname -r), .IP \fB\et\fP insert current time (localtime), .IP \fB\es\fP inserts operating system name, .IP \fB\eu\fP insert the number of users which are currently logged in, .IP \fB\eU\fP insert the string "1 user" or " users", where is the number of users currently logged in, .IP \fB\ev\fP inserts operating system version (uname -v). .IP \fB\eXYZ\fP inserts a letter with octal code XYZ. .PP .SH EXAMPLE "\fBLinux\ eos\ i386\ #1\ Tue\ Mar\ 19\ 21:54:09\ MET\ 1996\fP" was produced by putting "\fB\\s\ \\n\ \\m\ \\v\fP" into .IR /etc/issue . . .PP .SH "NGETTY-ARGV" The program \fBngetty-argv\fP(8) splits argv[1] on strings, expands \fB%U\fP and \fB%T\fP to username and tty and then start the the application. The first char after "login-argv=" is split char. In the examples above every user logs on tty4 without password and tty5 is always root. To understand better how \fBngetty-argv\fP works try as non-root: .br .PP .B ngetty-argv ':/bin/echo:echo:%U: on %T' usr tty3 .br .B ngetty-argv ':/bin/sleep:-hacker:39:I am %U on %T' 123 X .PP .TP One can put also options for ngetty-argv at the beginning. .IP \fB--\fP last option .IP \fB-u503\fP setuid to 503 .IP \fB-g230\fP setgid to 230 .IP .br \fB-a120\fP exec alarm(120) before starting child .IP \fB-s10\fP sleep 10 secs before starting child .IP \fB-d/X/YZ\fP chdir(/X/YZ) before starting child .IP \fB-r/A/BC\fP chroot(/A/BC) before starting child .IP \fB-D\fP start the child in background and exit .IP \fB-N -C\fP NOTTY | SCTTY controlling tty .IP \fB-S\fP like \fBsetsid\fP(8) .IP \fB-e,HOME=/,TERM=linux\fP same as \fBenviron=\fP above .IP \fB-p/path/to/pid.file\fP write the child pid here . .PP One possible example for \fB/etc/ngetty/Conf\fP is: .RS 4 .br tty9=clear= .br tty9=issue-file= .br tty9=login-prompt=\en \ed \et qmail-qread: .br tty9=login-prog=/sbin/ngetty-argv .br tty9=login-argv=:-u106:-g503:-d/var/qmail:-- .br :./bin/qmail-qread:qread .RE .PP Another example is setting the TTY environ automatically: .RS 4 =login-prog=/sbin/ngetty-argv .br =login-argv=:-e,TTY=/dev/%T,TERM=linux:-- .br :/bin/login:login-%T:--:%U .RE . .PP I recommend using \fBngetty-argv \fP in .IR /etc/inittab also. Put as last argument runlevel string. Then ps will show \fBngetty-2345\fP instead of \fBngetty\fP. Next start tty1 ... tty6 on runlevels 2345. .RS 4 ng:\fB2345\fP:respawn:/sbin/ngetty-argv .br .-e.-S.-d/.-s1.--./sbin/%U.%U-%T.1.2.3.4.5.6 .br ngetty \fB2345\fP .RE . .PP On a terminal (in scripts) start ngetty with .RS 4 ngetty-argv .-N.-S.-e./sbin/%U.%U.8.9.10 ngetty .br ngetty-argv .-D.-S.-e./sbin/%U.%U.8.9.10 ngetty .RE .PP This program is a hack written for \fBngetty-helper\fP. There is no additional code in ngetty-helper and it's possible to start a program with any args. It is like a filter between ngetty-helper and login application. One can easy modify it without touching ngetty-helper. It's similar to DJB well known \fBargv0\fP(1) and \fBsetuidgid\fP(8). You can write own such programs and use them instead of ngetty-argv. . .SH FILES .TS tab (@); l l. /etc/ngetty/Conf@ \fBngetty-helper\fP configuration file /etc/ngetty/Conf.sed@ private setup file /etc/ngetty/setup@ updates \fBConf.sed -> Conf\fP /etc/issue@ printed before the login prompt /var/run/utmp@ the system status file /var/log/wtmp@ the system logging file /etc/inittab@ \fBinit\fP(8) configuration file .TE . .PP .SH SEE ALSO . .BR getty (8) .BR fgetty (8) .BR mingetty (8) .br .BR login (1) .BR nlogin (1) .BR argv0 (1) .BR setuidgid (8) .BR stty (1) .br http://sites.google.com/site/anbadeol/logind . .SH AUTHOR . Nikola Vladov .br http://riemann.fmi.uni-sofia.bg/ngetty/ . .SH COPYRIGHT . Copyright 2007,2008,2010 Nikola Vladov .PP 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. .PP 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. ngetty-1.1/ngetty.c0000644000000000000000000001450011032225003013025 0ustar rootroot/* * ngetty.c - daemon for virtual console terminals * * Copyright 2007 Andre Oliveira * Copyright 2007,2008 Nikola Vladov * * 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. */ /* * Synopsis: ngetty tty... * * ngetty open()s the virtual console terminals specified as arguments and * poll()s them for user input. Once input is available on one of the * terminals, it fork()s and exec()s the ngetty-helper programs with that * terminal set up as the controlling terminal. ngetty-helper make * utmp/wtmp records, print /etc/issue, ask for user name and then * exec()s login(1) program. When a ngetty session terminates, * the sig_handler() restarts the corresponding terminal. */ #include #include #include #include #include #include #include "lib.h" #include "sig_action.h" #ifdef NEED_HELPER_OPTION static char *helper; #else #define helper NGETTY_HELPER #endif struct tty_name { char *tty; /* original ttyname */ char tmp[23]; /* expanded ttyname; /dev/ttyX or /dev/vc/X */ char st; }; typedef struct tty_name tty_name_; typedef struct pollfd pollfd_; static tty_name_ *tty; /* Number of managed terminals (argc - 1). */ static int npfd; /* * Poll data for the terminals. * When polling for input on a terminal, the fd field stores its * file descriptor, as customary. After fork()ing, though, the parent * process closes the terminal and stores the child's _negative_ pid * in the fd field, so that poll() ignores that entry and * main() knows every child's pid. */ static pollfd_ *pfd; static void nano_sleep(int n) { /* sleep n.5 secs */ struct timespec ts = { n, 500111222 }; nanosleep(&ts, 0); } static void max_copy(char *out,const char *in) { int len; for (len=0; len<10; len++) { if (!(out[len]=in[len])) break; } out[len] = 0; } /* * Exec NGETTY_HELPER. */ static void exechelper(int i, char *login) { pollfd_ *xx = pfd + i; int pid; while ((pid=fork()) < 0) nano_sleep(0); if (pid==0) { tty_name_ *tt = tty + i; char *a1 = (tt->tmp[0]) ? tt->tmp : tt->tty; char *arg[4] = { helper, a1, login, 0 }; #ifndef NGETTY_SELFPIPE if (xx->fd) #endif dup2(xx->fd, 0); i = npfd + 8; while (--i) close(i); execve(*arg, arg, environ); nano_sleep(5); _exit(127); } close(xx->fd); xx->fd = -pid; } /* * Open virtual console terminal i. * * In case of failure, most likely because the device node does not exist, * poll() will simply ignore this entry and users get a blank screen and * locked keyboard on this console. That's enough error reporting. ;-) * No need to add code to check all syscalls' return values. * * Linux does not implement revoke(); the *BSD do. */ void opentty(int k) { tty_name_ *tt = tty + k; char *path = tt->tty, *m = tt->tmp, st; int fd; if (*path != '/') { max_copy(m, "/dev/vc/"); if ('0'<=*path && *path<='9') { max_copy(m+8, path); if (chown(m,0,0)) { m[5]='t'; m[6]='t'; m[7]='y'; } } else { if (path[0]==0) { fd = -1; goto do_it; } max_copy(m+5, path); } path = m; } else m[0] = 0; chown(path, 0, 0); chmod(path, 0600); #ifdef HAVE_REVOKE revoke(path); #endif fd = open(path, O_RDWR | O_NOCTTY); if (fd > npfd + 4) _exit(100); do_it: pfd[k].fd = fd; if (fd < 0) st = 0; else { st = tt->st ^ 1; if (st) exechelper(k,0); } tt->st = st; } #ifndef NGETTY_SELFPIPE static int volatile poll_timeout; #endif /* * SIG handler. */ static void sig_handler(int sig) { if (sig == SIGTERM) { int k; again: for (k = 0; k < npfd; k++) { int pid = -pfd[k].fd; if (pid > 1) kill(pid, sig); } nano_sleep(0); if (sig == SIGKILL) _exit(0); sig = SIGKILL; goto again; } #ifdef NGETTY_SELFPIPE write(1,"",1); #else poll_timeout = 1; #endif } static void set_handler() { struct sigaction sa; sigset_t *mask = &sa.sa_mask; sigemptyset(mask); sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; sa.sa_handler = sig_handler; sigaction(SIGTERM, &sa, 0); sigaction(SIGCHLD, &sa, 0); } #ifdef NGETTY_SORT #include "sortpfd.h" #define SORT_x_PFD k = sortpfd() #define KK_selfpipe k+1 #define KK k #else #define SORT_x_PFD #define KK_selfpipe argc #define KK npfd #endif #ifdef NGETTY_SELFPIPE #define DO_x_POLL poll(pfd-1, KK_selfpipe, -1) #else #define DO_x_POLL poll(pfd, KK, poll_timeout); poll_timeout = 512*1024 #endif /* * Synopsis: ngetty tty... * * Since each terminal's struct pollfd only takes up 8 bytes, just * alloca()te the array on the stack, instead of using the bloated malloc(). */ int main(int argc, char **argv) { int i,k; #ifdef NGETTY_SELFPIPE int pi[6]; #endif #ifdef NEED_HELPER_OPTION if ((helper=argv[1]) && helper[0] == '-' && helper[1] == 'H') { argv++; argc--; helper += 2; } else helper = NGETTY_HELPER; #endif npfd = argc - 1; tty = alloca(npfd * sizeof(tty_name_)); if (tty==0) _exit(111); pfd = alloca(argc * sizeof(pollfd_)); if (pfd==0) _exit(111); #ifdef NGETTY_SELFPIPE pfd->fd = 0; pfd->events = POLLIN; pfd++; #endif for (k = 0; k < npfd; k++) { tty[k].tty = *++argv; tty[k].st = 0; pfd[k].fd = -1; pfd[k].events = POLLIN; } for (k = 0; k < 127; k++) close(k); #ifdef NGETTY_SELFPIPE if (pipe(pi) || pi[0] != 0 || pi[1] != 1) _exit(111); for (k=0; k<2; k++) fcntl(k, F_SETFL, fcntl(k,F_GETFL,0) | O_NONBLOCK); #endif set_handler(); again: while ((i = waitpid(-1, NULL, WNOHANG)) > 1) for (k = 0; k < npfd; k++) if (pfd[k].fd == -i) { pfd[k].fd = -1; break; } for (k = 0; k < npfd; k++) if (pfd[k].fd == -1) opentty(k); SORT_x_PFD; i = DO_x_POLL; if (i==-1) { if (errno != EINTR) sig_handler(SIGTERM); /* poll failed, what to do? */ } else { for (i = 0; i < KK; i++) if (pfd[i].revents) exechelper(i,"login"); } #ifdef NGETTY_SELFPIPE read(0, pi, sizeof pi); #endif goto again; return 1; } ngetty-1.1/nv_gmtime.c0000644000000000000000000000151010744744012013514 0ustar rootroot#include struct tm *nv_gmtime(const time_t *t) /*EXTRACT_INCL*/{ static struct tm tm; unsigned long day, mon, year, yday=0, tod; tod = (unsigned long)(*t) % 86400; day = (unsigned long)(*t) / 86400; tm.tm_wday = ((day+4) % 7); tm.tm_sec = tod%60; tod /= 60; tm.tm_min = tod%60; tm.tm_hour = tod/60; year = 4*day + 2; year /= 1461; day += 671; day %= 1461; /* day 0 is march 1, 1972 */ if (day < 306) yday = 1; if (day == 1460) { day = 365; yday = 59; } else { day %= 365; yday += (day + 59) % 365; } day *= 10; mon = (day + 5) / 306; day = day + 5 - 306 * mon; day /= 10; if (mon >= 10) mon -= 10; else mon += 2; /* day 0,1,30, mon 0..11, year 1970=0,1,2 */ tm.tm_year = year+70; tm.tm_mon = mon; tm.tm_mday = day+1; tm.tm_yday = yday; return &tm; } ngetty-1.1/nwho.c0000644000000000000000000000572211376722756012530 0ustar rootroot/* nwho.c */ #include #include #include #include #include "lib.h" #define S(a,b) str_copy(a,b) #define SN(a,b,c) str_copynz(a,b,c) #define SF(a,b,c) fmt_str_(a,b,c) #define N(a,b,c,d) fmt_nmb_(a,b,c,d) void usage(char *buf) { write(1,buf,str_copy(buf, "usage: nwho [-alpquw] [file]\n")); _exit(1); } int main(int argc, char **argv) { struct tm *tm; struct stat st; char *montab = "JanFebMarAprMayJunJulAugSepOctNovDec"; char buf[1024]; time_t id; char *ipasc, mesg, *p; unsigned char flagaddr = 0; char flagpid = 0; char flagcheck = 1; char flagup = 0; char flagmesg = 0; #ifdef USE_LIBC_UTMP struct utmp_type *ut; #else struct utmp_type ut[1]; int fd; #endif argc--; argv++; while (argc>0) { p = argv[0]; if (*p != '-') break; for (++p; *p; ++p) switch (*p) { case 'q': flagcheck = 0; break; case 'l': ++flagaddr; break; case 'p': flagpid = 1; break; case 'u': flagup = 1; break; case 'w': flagmesg = 1; break; case 'a': flagup=1; flagpid=1; ++flagaddr; flagmesg=1; break; default: usage(buf); } argc--; argv++; } #ifdef USE_LIBC_UTMP if (argc>0) f_utmpname(argv[0]); setutent(); #else if (argc>0) p = argv[0]; else p = Utmp_File; fd = open(p, O_RDONLY); if (fd == -1) {write(1,"error open input\n",17); _exit(1);} #endif while (f_getutent()) { if (ut->ut_type != USER_PROCESS) continue; if (flagcheck) if (kill(ut->ut_pid, 0) && errno == ESRCH) continue; id = ut->ut_tv.tv_sec; id += get_tz(id); tm = nv_gmtime(&id); mesg = '?'; id = -1; S(buf, "/dev/"); buf[5 + SN(buf+5, ut->ut_line, sizeof(ut->ut_line))] = '\0'; if (!stat(buf, &st)) { if ((st.st_mode & 0020) == 0020) mesg = '+'; else mesg = '-'; id = (time(0) - st.st_mtime)/60; } /*----------------------------------------------*/ p = buf; p += SF(p, ut->ut_user,12); if (flagmesg) { *p++ = mesg; *p++ = ' ';} p += SF(p, ut->ut_line, 7); *p++ = ' '; if (flagpid) { p += N(p, ut->ut_pid, 5,0); *p++ = ' ';} p += SN(p, montab + (tm->tm_mon)*3, 3); *p++ = ' '; p += N(p, tm->tm_mday, 2,0); *p++ = ' '; p += N(p, tm->tm_hour, 2,0); *p++ = ':'; p += N(p, tm->tm_min, 2,1); *p++ = ' '; if (flagup) { if (id >= 24*60) { id /= 60; p += N(p, id/24, 3,0); p += S(p,"d+"); p += N(p, id%24, 2,1); p += S(p,"h "); } else if (id > 0) { p += N(p, id/60, 2,0); *p++ = ':'; p += N(p, id%60, 2,1); *p++ = ' '; } else if (id == 0) { p += SF(p," .",6); } else p += SF(p," ?",6); } *p++ = '('; ipasc = p; p += fmt_utmp_ip(p, (char *)ut->ut_addr_v6); if (flagaddr>1 || (flagaddr && str_diffn(ipasc, ut->ut_host, sizeof(ut->ut_host)))) { *p++ = '='; p += SN(p,ut->ut_host,90); } *p++ = ')'; *p++ = '\n'; write(1,buf, p-buf); } f_endutent(); return 0; } ngetty-1.1/opts_make.c0000644000000000000000000000411111030156307013502 0ustar rootroot#include #include "str_defs.h" #include "fmt_defs.h" #include "vhangup_defs.h" struct xx { char *a,*b,*c; }; char buf[8192], *p = buf; unsigned char opt_len[512]; #define s(X) p += str_copy(p, X) #define f(X) p += fmt_ulong(p, X) #define sfs(a,b,c) s(a); f(b); s(c) #define X(a,b,c) {#a,#b,#c} struct xx o[] = { X(pri,nt,=), X(cl,ear,=), X(all,ow,=), X(de,ny,=), X(env,iron,=), X(new,line,=), X(sh,-A,=), X(sh,-B,=), X(t,z,=), X(day,s,=), X(month,s,=), X(ni,ce,=), X(ch,dir,=), X(de,lay,=), X(ch,root,=), X(time,out,=), X(issue,-file,=), X(login,-buffer,=), X(login,-prog,=), X(login,-argv,=), X(login,-prompt,=), X(noclear,-first,=), X(autologin,-name,=), X(autologin,-first,=), X(de,bu,g), X(echo,-o,ff), #ifdef HAVE_SYSTEM_VHANGUP X(no,han,gup), #endif X(no,user,name), X(date,-str,ing), X(long,-host,name), {0,0,0} }; int main() { struct xx *x = o; int n,k, o_len; s("/* this file is auto generated. do not edit! */\n\n" "#ifndef NGETTY_opts_defs_h\n" "#define NGETTY_opts_defs_h\n\n"); #ifdef HAVE_SYSTEM_VHANGUP s("#define HAVE_SYSTEM_VHANGUP\n\n"); #endif for (o_len=0, n=0, k=0, x=o; x->a; x++, n++) { char *t = x->b; int m = str_len(x->a) + str_len(x->b); if (*t=='-') t++; s("#define O"); s(x->a); s(t); if (x->c[0] != '=') { s(x->c); m += str_len(x->c); } else k++; opt_len[n] = m; o_len += m; sfs("\t", n, "\n"); } sfs("\n#define MAX_equal\t", k, "\n"); sfs("#define MAX_options\t", n, "\n"); s("\nstatic char *o[MAX_options];\n" "extern char ** Oo;\n\n"); sfs("const char P_opt[", o_len, "] = {\n"); for (x=o,n=0; x->a; x++, n++) { char *t = "\"\t/* ="; s("\t\""), s(x->a); s(x->b); if (x->c[0] != '=') { s(x->c); t = "\"\t/* "; } sfs(t, n, " */\n"); } s("};\n\n"); s("const unsigned char P_len[MAX_options] = {\n"); for (k=0; k #include "str_defs.h" static char buf_space[256]; static int buf_pos; void out_flush() /*EXTRACT_INCL*/ { const_io((int(*)())write, 1, buf_space, buf_pos); buf_pos=0; } void out_char(char ch) /*EXTRACT_INCL*/ { if (buf_pos == sizeof(buf_space)) out_flush(); buf_space[buf_pos] = ch; buf_pos++; } void out_puts(char *s) /*EXTRACT_INCL*/ { while (*s) { out_char(*s); ++s; } } ngetty-1.1/sample.Conf0000644000000000000000000000270311030156307013451 0ustar rootroot# Do not edit /etc/ngetty/sample.Conf! Next install/update overwrite it. # Create private /etc/ngetty/Conf.sed with: # cd /etc/ngetty # echo '# private ngetty setup' > Conf.sed # chown root.root Conf.sed # chmod 600 Conf.sed # After editing Conf.sed exec: # cd /etc/ngetty && ./setup # less /etc/ngetty/Conf # Next install/update overwrite the file /etc/ngetty/setup also. # # See ngetty(8) for the syntax of Conf. The file Conf.sed have # the same syntax as Conf. It supports also continuation of the lines # ending with backslash (\) like bash. # The program ./setup converts Conf.sed to Conf. #---------------------------------------------------------------- # options format: # [ttyX]=option[=value] #=debug #=environ=,TERM=linux #tty5=environ=,TERM=linux,TTY=/dev/tty5 #tty1=sh-A=/etc/ngetty/tty1-A #=sh-B=/etc/ngetty/ttyX-B #=date-string #=nousername #=long-hostname #=clear=\033c #=newline= #tty1=noclear-first=/etc/ngetty/.noclear #=echo-off #=nohangup #=autologin-first=/etc/ngetty/.autologin #=autologin-name=username #=print=az:AZ:09:,.:__ #=deny=:root:mail:nobody #=allow=,root,operator #=login-prog=/bin/login #=login-argv=:options:--:program:name:args #=login-prompt=\n login: #=login-prompt=\d \t (\l)\012\n login: #=timeout=180 #=delay=3 #=nice=5 #=issue-file=/etc/issue #=chdir=/home #=chroot=/chroot #=tz=-7200 #=tz=/etc/localtime #=tz=AUTO #=months=JanFebMarAprMayJunJulAugSepOctNovDec #=days=SunMonTueWedThuFriSat #=login-buffer=1234567890123456 ngetty-1.1/sig_action.h0000644000000000000000000000113011000211741013631 0ustar rootroot#include #ifdef NGETTY_TINY #if defined(__linux__) && defined(__dietlibc__) #ifdef NGETTY_i386 extern int system__errno; #define errno system__errno #endif #if defined(__i386__) || defined(__x86_64__) #define sigemptyset(set) \ do { \ set->sig[0]=0; \ if (_NSIG_WORDS>1) set->sig[1]=0; \ if (_NSIG_WORDS>2) { \ set->sig[2]=0; \ set->sig[3]=0; \ } \ } while(0) int __rt_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact, long nr); #define sigaction(signum, act, oldact) \ __rt_sigaction(signum, act, oldact, _NSIG/8) #endif #endif #endif ngetty-1.1/sortpfd.h0000644000000000000000000000065111032224625013214 0ustar rootrootstatic void swap_bytes(void *a, void *b, int len) { char *x = a, *y = b, z; while (len--) { z = *x; *x = *y; *y = z; ++x; ++y; } } static int sortpfd() { int l=0, r=npfd-1; again: while (l <= r && pfd[l].fd >= 0) ++l; while (l <= r && pfd[r].fd < 0) --r; if (l < r) { swap_bytes(pfd+l, pfd+r, sizeof(pollfd_)); swap_bytes(tty+l, tty+r, sizeof(tty_name_)); goto again; } return l; } ngetty-1.1/splitmem.c0000644000000000000000000000041111375034346013363 0ustar rootrootunsigned int splitmem(char **v, char *s, char c) /*EXTRACT_INCL*/ { char **w=v; unsigned int n=1; if (w) *w++=s; while (*s) { ++s; if (s[-1] != c) continue; ++n; if (w==0) continue; *w++=s; s[-1]=0; } if (w) *w=0; return n; } ngetty-1.1/str_add.c0000644000000000000000000000023610746035270013154 0ustar rootrootunsigned int str_add(char *d, const char *s, unsigned int u) /*EXTRACT_INCL*/ { unsigned int l=0; for (l=0; s[l] && l #define S(x) syscall(x,x) #define S__(x) syscall(x,__##x) S(nanosleep) S(fork) S(dup2) S(close) S(execve) S(chown) S(chmod) S(open) S(kill) S(waitpid) S(poll) S__(rt_sigaction) /* ------------------------------------------------------- */ #if 0 .text .global __unified_syscall_256 .type __unified_syscall_256,@function __unified_syscall_256: movzwl %ax,%eax jmp __unified_return .size __unified_syscall_256,.-__unified_syscall_256 #endif ngetty-1.1/test-helper.c0000644000000000000000000000121311031445013013750 0ustar rootroot#include #include #include #include /* A) $0 ./ngetty-helper /dev/ttyX [login] B) $0 "-H" /dev/ttyX C) $0 "-O" /dev/ttyX */ int main(int argc , char **argv, char **env) { int k; char *x; if (argc<3) _exit(100); ioctl(0, TIOCNOTTY, 0); for (k=0; k<6; k++) close(k); if (0 != open(argv[2], O_RDWR | O_NOCTTY)) _exit(111); x = argv[1]; if (x[0] != '-') { argv++; execve(*argv, argv, env); _exit(127); } ++x; switch (*x) { case 'O': if (fork()) _exit(0); case 'H': setsid(); ioctl(0, TIOCSCTTY, 0); sleep(15); vhangup(); } _exit(0); } ngetty-1.1/tryboottime.c0000644000000000000000000000064610760601721014116 0ustar rootroot#include #include #include #include int main() { #if defined(CTL_KERN) && defined(KERN_BOOTTIME) /* FreeBSD specific: fetch sysctl "kern.boottime". */ struct timeval res = { 0, 0 }; int req[2] = { CTL_KERN, KERN_BOOTTIME }; size_t res_len = sizeof res; if (sysctl(req, 2, &res, &res_len, 0, 0) >= 0 && res.tv_sec > 0) return 0; #else return -1; #endif } ngetty-1.1/trysysinfo.c0000644000000000000000000000013010760023557013757 0ustar rootroot#include int main() { struct sysinfo info; return sysinfo(&info); } ngetty-1.1/tryvhangup.c0000644000000000000000000000007410771722461013746 0ustar rootroot#include int main() { vhangup(); _exit(0); } ngetty-1.1/tzmap.c0000644000000000000000000000340111016334202012650 0ustar rootroot#include #include #include // #define TZ_MMAP static unsigned char *T; static int L=-1; static time_t left, right, tz; static time_t parse(unsigned char *x) {return (x[0]<<24) | (x[1]<<16) | (x[2]<<8) | x[3];} static time_t parse_localtime(time_t t) { unsigned char *tmp,*x,tzh_typecnt; int i,tzh_timecnt; if (!T || L<44 || parse(T) != 1415211366) goto ready; tzh_timecnt = parse(T+32) & 0xfff; tzh_typecnt = parse(T+36); i = 44 + 4*tzh_timecnt; if (i + tzh_timecnt + 6*tzh_typecnt > L) goto ready; x =T +i; tmp =x; for (i=tzh_timecnt; 0= tzh_typecnt) goto ready; tz = parse(x +tzh_timecnt +6*x[i]); return tz; } ready: right=left; return 0; } #ifndef TZ_MMAP #include #include #include "scan_defs.h" #include "opts__defs.h" time_t get_tz(time_t t) /*EXTRACT_INCL*/{ struct stat st; int fd; char *tzfile = Oo[Otz]; if (*tzfile != '/') return x_atoi(tzfile); if (left <= t && t < right) return tz; fd=open(tzfile,O_RDONLY); if (fd>=0) { if (fstat(fd, &st)) goto error; L = st.st_size; T = alloca(L); if (!T) goto error; if (const_io((int(*)())read,fd,T,L)) { error: close(fd); return 0; } close(fd); } return parse_localtime(t); } #else #include time_t get_tz(time_t t) { int fd; if (left <= t && t < right) return tz; if (!T) { char *map; if ((fd=open("/etc/localtime",O_RDONLY))>=0) { L=lseek(fd,0,SEEK_END); map=mmap(0,L,PROT_READ,MAP_SHARED,fd,0); if (map==(char*)-1) map=0; close(fd); T=(unsigned char *)map; } } return parse_localtime(t); } #endif ngetty-1.1/utmp_do.c0000644000000000000000000000361011375752714013212 0ustar rootroot#include "lib.h" #define SD(A,B) !str_diffn(A, B, sizeof(A)) #define SC(A,B) str_copynz(A, B, sizeof(A)) #if 0 /*EXTRACT_START*/ SC(u.ut_line, line); if (u.ut_id[0]==0) SC(u.ut_id, p); if (login) { u.ut_type=LOGIN_PROCESS; u.ut_pid=getpid(); p="LOGIN"; } else { if (u.ut_type == DEAD_PROCESS) do_wtmp =0; u.ut_type=DEAD_PROCESS; p=""; } SC(u.ut_user,p); SC(u.ut_host,""); u.ut_tv.tv_sec = time(0); /*EXTRACT_END*/ #endif #ifdef USE_LIBC_UTMP void utmp_do(int login, char *line) { struct utmp_type u, *ut; char foundone=0, do_wtmp=1; char *p; p=line; while (str_len(p) > sizeof u.ut_id) p++; str_copynz((char *)&u,"",sizeof(u)); f_setutent(); while (f_getutent()) if ((INIT_PROCESS <= ut->ut_type && ut->ut_type <= DEAD_PROCESS && SD(ut->ut_id, p)) || SD(ut->ut_line, line)) { u = *ut; foundone=1; break; } #include "utmp_defs.h" if (foundone || login) { f_setutent(); /* comment this ? */ f_pututline(&u); } f_endutent(); if (do_wtmp) f_updwtmp(Wtmp_File, &u); } #else #include #include /* line tty5 */ void utmp_do(int login, char *line) /*EXTRACT_INCL*/{ struct utmp_type u; char foundone=0, do_wtmp=1; int fd=open(Utmp_File, O_RDWR); off_t pos=0; char *p; p=line; while (str_len(p) > sizeof u.ut_id) p++; while (utmp_io(fd, &u, F_RDLCK)) { if ((INIT_PROCESS <= u.ut_type && u.ut_type <= DEAD_PROCESS && SD(u.ut_id, p)) || SD(u.ut_line, line)) { foundone=1; break; } pos += UTMP_SIZE; } if (!foundone) { str_copynz((char *)&u,"",sizeof(u)); pos = lseek(fd,0,SEEK_END); if (pos<0) pos =0; pos = pos - (pos % (UTMP_SIZE)); } #include "utmp_defs.h" if (foundone || login) if (lseek(fd,pos,SEEK_SET) == pos) utmp_io(fd,&u,F_WRLCK); close(fd); if (do_wtmp) { fd=open(Wtmp_File, O_WRONLY|O_APPEND); write(fd, &u, UTMP_SIZE); close(fd); } } #endif ngetty-1.1/utmp_io.c0000644000000000000000000000110211375714230013200 0ustar rootroot#include #include #include #include "lib.h" /* type: F_RDLCK or F_WRLCK */ struct utmp_type *utmp_io(int fd, struct utmp_type *ut, int type) /*EXTRACT_INCL*/ { struct flock fl; int len; fl.l_whence = SEEK_CUR; fl.l_start = 0; fl.l_len = UTMP_SIZE; fl.l_pid = 0; fl.l_type = type; if (fcntl(fd, F_SETLKW, &fl)) return 0; len = const_io((type==F_WRLCK) ? (int(*)())write : (int(*)())read, fd, ut, UTMP_SIZE); fl.l_start = -UTMP_SIZE; fl.l_type = F_UNLCK; fcntl(fd, F_SETLK, &fl); return (len) ? 0 : ut; } ngetty-1.1/utmp_struct.h0000644000000000000000000000212311375752566014144 0ustar rootroot#ifndef UTMP_STRUCT_H #define UTMP_STRUCT_H #include "lib.h" #if defined(HAVE_C_UTMP) && defined(HAVE_C_UTMPX) #error define olny one of HAVE_C_UTMP, HAVE_C_UTMPX in lib.h #endif #undef USE_LIBC_UTMP #if defined(HAVE_C_UTMP) || defined(HAVE_C_UTMPX) #define USE_LIBC_UTMP #endif #ifndef USE_LIBC_UTMP #define f_endutent() close(fd) #define f_getutent() utmp_io(fd, ut, F_RDLCK) #endif #ifndef HAVE_C_UTMPX #include #define utmp_type utmp #define Utmp_File _PATH_UTMP #define Wtmp_File _PATH_WTMP #endif #ifdef HAVE_C_UTMP #define f_setutent setutent #define f_endutent endutent #define f_getutent() (ut = getutent()) #define f_pututline pututline #define f_updwtmp updwtmp #define f_utmpname utmpname #endif #ifdef HAVE_C_UTMPX #define __USE_GNU #include #define Utmp_File _PATH_UTMPX #define Wtmp_File _PATH_WTMPX #define utmp_type utmpx #define f_setutent setutxent #define f_endutent endutxent #define f_getutent() (ut = getutxent()) #define f_pututline pututxline #define f_updwtmp updwtmpx #define f_utmpname utmpxname #endif #define UTMP_SIZE sizeof(struct utmp_type) #endif ngetty-1.1/utmp_users.c0000644000000000000000000000054511375752520013750 0ustar rootroot#include #include #include "lib.h" unsigned long utmp_users() /*EXTRACT_INCL*/ { unsigned long u=0; #ifdef USE_LIBC_UTMP struct utmp_type *ut; f_setutent(); #else struct utmp_type ut[1]; int fd = open(Utmp_File, O_RDONLY); #endif while (f_getutent()) if (ut->ut_type == USER_PROCESS) u++; f_endutent(); return u; } ngetty-1.1/x_atoi.c0000644000000000000000000000040110770213505013005 0ustar rootroot int x_atoi(const char *src) /*EXTRACT_INCL*/ { register const char *s; register int dest=0; register unsigned char c; s=src; if (*s=='-' || *s=='+') ++s; while ((c=*s-'0')<10) { ++s; dest=dest*10 + c; } return (*src=='-') ? -dest : dest; }