From: nekral-guest Date: Sun, 7 Oct 2007 11:44:02 +0000 (+0000) Subject: [svn-upgrade] Integrating new upstream version, shadow (19990709) X-Git-Tag: 19990709~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=45c6603cc86c5881b00ac40e0f9fe548c30ff6be;p=shadow [svn-upgrade] Integrating new upstream version, shadow (19990709) --- diff --git a/ABOUT-NLS b/ABOUT-NLS new file mode 100644 index 00000000..28d38c76 --- /dev/null +++ b/ABOUT-NLS @@ -0,0 +1,226 @@ +Notes on the Free Translation Project +************************************* + + Free software is going international! The Free Translation Project +is a way to get maintainers of free software, translators, and users all +together, so that will gradually become able to speak many languages. +A few packages already provide translations for their messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do *not* +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work at translations should contact the appropriate team. + + When reporting bugs in the `intl/' directory or bugs which may be +related to internationalization, you should tell about the version of +`gettext' which is used. The information can be found in the +`intl/VERSION' file, in internationalized packages. + +One advise in advance +===================== + + If you want to exploit the full power of internationalization, you +should configure it using + + ./configure --with-included-gettext + +to force usage of internationalizing routines provided within this +package, despite the existence of internationalizing capabilities in the +operating system where this package is being installed. So far, only +the `gettext' implementation in the GNU C library version 2 provides as +many features (such as locale alias or message inheritance) as the +implementation here. It is also not possible to offer this additional +functionality on top of a `catgets' implementation. Future versions of +GNU `gettext' will very likely convey even more functionality. So it +might be a good idea to change to GNU `gettext' as soon as possible. + + So you need not provide this option if you are using GNU libc 2 or +you have installed a recent copy of the GNU gettext package with the +included `libintl'. + +INSTALL Matters +=============== + + Some packages are "localizable" when properly installed; the +programs they contain can be made to speak your own native language. +Most such packages use GNU `gettext'. Other packages have their own +ways to internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system provides +usable `catgets' (if using this is selected by the installer) or +`gettext' functions. If neither is available, the GNU `gettext' own +library will be used. This library is wholly contained within this +package, usually in the `intl/' subdirectory, so prior installation of +the GNU `gettext' package is *not* required. Installers may use +special options at configuration time for changing the default +behaviour. The commands: + + ./configure --with-included-gettext + ./configure --with-catgets + ./configure --disable-nls + +will respectively bypass any pre-existing `catgets' or `gettext' to use +the internationalizing routines provided within this package, enable +the use of the `catgets' functions (if found on the locale system), or +else, *totally* disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl.a' file and +will decide to use this. This might be not what is desirable. You +should use the more recent version of the GNU `gettext' library. I.e. +if the file `intl/VERSION' shows that the library which comes with this +package is more recent, you should use + + ./configure --with-included-gettext + +to prevent auto-detection. + + By default the configuration process will not test for the `catgets' +function and therefore they will not be used. The reasons are already +given above: the emulation on top of `catgets' cannot provide all the +extensions provided by the GNU `gettext' library. If you nevertheless +want to use the `catgets' functions use + + ./configure --with-catgets + +to enable the test for `catgets' (this causes no harm if `catgets' is +not available on your system). If you really select this option we +would like to hear about the reasons because we cannot think of any +good one ourself. + + Internationalized packages have usually many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +Using This Package +================== + + As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +ISO 639 `LL' two-letter code prior to using the programs in the +package. For example, let's suppose that you speak German. At the +shell prompt, merely execute `setenv LANG de' (in `csh'), +`export LANG; LANG=de' (in `sh') or `export LANG=de' (in `bash'). This +can be done from your `.login' or `.profile' file, once and for all. + + An operating system might already offer message localization for +many of its programs, while other programs have been installed locally +with the full capabilities of GNU `gettext'. Just using `gettext' +extended syntax for `LANG' would break proper localization of already +available operating system programs. In this case, users should set +both `LANGUAGE' and `LANG' variables in their environment, as programs +using GNU `gettext' give preference to `LANGUAGE'. For example, some +Swedish users would rather read translations in German than English for +when Swedish is not available. This is easily accomplished by setting +`LANGUAGE' to `sv:de' while leaving `LANG' to `sv'. + +Translating Teams +================= + + For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list, courtesy of Linux +International. You may reach your translation team at the address +`LL@li.org', replacing LL by the two-letter ISO 639 code for your +language. Language codes are *not* the same as the country codes given +in ISO 3166. The following translation teams exist, as of December +1997: + + Chinese `zh', Czech `cs', Danish `da', Dutch `nl', English `en', + Esperanto `eo', Finnish `fi', French `fr', German `de', Hungarian + `hu', Irish `ga', Italian `it', Indonesian `id', Japanese `ja', + Korean `ko', Latin `la', Norwegian `no', Persian `fa', Polish + `pl', Portuguese `pt', Russian `ru', Slovenian `sl', Spanish `es', + Swedish `sv', and Turkish `tr'. + +For example, you may reach the Chinese translation team by writing to +`zh@li.org'. + + If you'd like to volunteer to *work* at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is *not* the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +*actively* in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `translation@iro.umontreal.ca' to reach the +coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skill are praised more than +programming skill, here. + +Available Packages +================== + + Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of December +1997. The matrix shows, in regard of each package, for which languages +PO files have been submitted to translation coordination. + + Ready PO files cs da de en es fi fr it ja ko nl no pl pt ru sl sv + .----------------------------------------------------. + bash | [] [] [] | 3 + bison | [] [] [] | 3 + clisp | [] [] [] [] | 4 + cpio | [] [] [] [] [] [] | 6 + diffutils | [] [] [] [] [] | 5 + enscript | [] [] [] [] [] [] | 6 + fileutils | [] [] [] [] [] [] [] [] [] [] | 10 + findutils | [] [] [] [] [] [] [] [] [] | 9 + flex | [] [] [] [] | 4 + gcal | [] [] [] [] [] | 5 + gettext | [] [] [] [] [] [] [] [] [] [] [] | 12 + grep | [] [] [] [] [] [] [] [] [] [] | 10 + hello | [] [] [] [] [] [] [] [] [] [] [] | 11 + id-utils | [] [] [] | 3 + indent | [] [] [] [] [] | 5 + libc | [] [] [] [] [] [] [] | 7 + m4 | [] [] [] [] [] [] | 6 + make | [] [] [] [] [] [] | 6 + music | [] [] | 2 + ptx | [] [] [] [] [] [] [] [] | 8 + recode | [] [] [] [] [] [] [] [] [] | 9 + sh-utils | [] [] [] [] [] [] [] [] | 8 + sharutils | [] [] [] [] [] [] | 6 + tar | [] [] [] [] [] [] [] [] [] [] [] | 11 + texinfo | [] [] [] | 3 + textutils | [] [] [] [] [] [] [] [] [] | 9 + wdiff | [] [] [] [] [] [] [] [] | 8 + `----------------------------------------------------' + 17 languages cs da de en es fi fr it ja ko nl no pl pt ru sl sv + 27 packages 6 4 25 1 18 1 26 2 1 12 20 9 19 7 4 7 17 179 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If December 1997 seems to be old, you may fetch a more recent copy +of this `ABOUT-NLS' file on most GNU archive sites. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..5a55194b --- /dev/null +++ b/Makefile.am @@ -0,0 +1,6 @@ +## Process this file with automake to produce Makefile.in + +AUTOMAKE_OPTIONS = 1.0 foreign ansi2knr + +SUBDIRS = intl po man lib libmisc src \ + contrib debian doc etc old redhat diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 00000000..257f5764 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,350 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +AUTOMAKE_OPTIONS = 1.0 foreign ansi2knr + +SUBDIRS = intl po man lib libmisc src \ + contrib debian doc etc old redhat +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = ABOUT-NLS Makefile.am Makefile.in acconfig.h aclocal.m4 \ +ansi2knr.1 ansi2knr.c config.guess config.h.in config.sub configure \ +configure.in install-sh ltconfig ltmain.sh missing mkinstalldirs \ +stamp-h.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: all-recursive-am all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status + +$(ACLOCAL_M4): configure.in + cd $(srcdir) && $(ACLOCAL) + +config.status: $(srcdir)/configure + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +config.h: stamp-h + @: +stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES= CONFIG_HEADERS=config.h \ + $(SHELL) ./config.status + @echo timestamp > stamp-h +$(srcdir)/config.h.in: $(srcdir)/stamp-h.in +$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h + cd $(top_srcdir) && $(AUTOHEADER) + @echo timestamp > $(srcdir)/stamp-h.in + +mostlyclean-hdr: + +clean-hdr: + +distclean-hdr: + -rm -f config.h + +maintainer-clean-hdr: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + done; \ + for subdir in $$rev; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + (cd $$subdir && $(MAKE) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + -rm -rf $(distdir) + GZIP=$(GZIP) $(TAR) zxf $(distdir).tar.gz + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + dc_install_base=`cd $(distdir)/=inst && pwd`; \ + cd $(distdir)/=build \ + && ../configure --with-included-gettext --srcdir=.. --prefix=$$dc_install_base \ + && $(MAKE) \ + && $(MAKE) dvi \ + && $(MAKE) check \ + && $(MAKE) install \ + && $(MAKE) installcheck \ + && $(MAKE) dist + -rm -rf $(distdir) + @echo "========================"; \ + echo "$(distdir).tar.gz is ready for distribution"; \ + echo "========================" +dist: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +dist-all: distdir + -chmod -R a+r $(distdir) + GZIP=$(GZIP) $(TAR) chozf $(distdir).tar.gz $(distdir) + -rm -rf $(distdir) +distdir: $(DISTFILES) + -rm -rf $(distdir) + mkdir $(distdir) + -chmod 777 $(distdir) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done + for subdir in $(SUBDIRS); do \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + done +info: info-recursive +dvi: dvi-recursive +check: all-am + $(MAKE) check-recursive +installcheck: installcheck-recursive +all-recursive-am: config.h + $(MAKE) all-recursive + +all-am: Makefile config.h + +install-exec: install-exec-recursive + @$(NORMAL_INSTALL) + +install-data: install-data-recursive + @$(NORMAL_INSTALL) + +install: install-recursive + @: + +uninstall: uninstall-recursive + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: installdirs-recursive + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic + +clean-am: clean-hdr clean-tags clean-generic mostlyclean-am + +distclean-am: distclean-hdr distclean-tags distclean-generic clean-am + +maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \ + maintainer-clean-generic distclean-am + +mostlyclean: mostlyclean-recursive mostlyclean-am + +clean: clean-recursive clean-am + +distclean: distclean-recursive distclean-am + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-recursive maintainer-clean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + -rm -f config.status + +.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \ +install-data-recursive uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info dvi \ +installcheck all-recursive-am all-am install-exec install-data install \ +uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 00000000..8e18ad9d --- /dev/null +++ b/acconfig.h @@ -0,0 +1,154 @@ +/* $Id: acconfig.h,v 1.12 1999/06/07 16:40:43 marekm Exp $ */ + + + +/* Define to enable password aging. */ +#undef AGING + +/* Define if struct passwd has pw_age. */ +#undef ATT_AGE + +/* Define if struct passwd has pw_comment. */ +#undef ATT_COMMENT + +/* Define to support JFH's auth. methods. UNTESTED. */ +#undef AUTH_METHODS + +/* Define if struct passwd has pw_quota. */ +#undef BSD_QUOTA + +/* Define if you have secure RPC. */ +#undef DES_RPC + +/* Define to support 16-character passwords. */ +#undef DOUBLESIZE + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Path for faillog file. */ +#undef FAILLOG_FILE + +/* Define if you want my getgrent routines. */ +#undef GETGRENT + +/* Define to libshadow_getpass to use our own version of getpass(). */ +#undef getpass + +/* Define if you want my getpwent routines. */ +#undef GETPWENT + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Defined if you have libcrack. */ +#undef HAVE_LIBCRACK + +/* Defined if you have the ts&szs cracklib. */ +#undef HAVE_LIBCRACK_HIST + +/* Defined if it includes *Pw functions. */ +#undef HAVE_LIBCRACK_PW + +/* Defined if you have libcrypt. */ +#undef HAVE_LIBCRYPT + +/* Define if struct lastlog has ll_host */ +#undef HAVE_LL_HOST + +/* Working shadow group support in libc? */ +#undef HAVE_SHADOWGRP + +/* Define to 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define to support TCFS. */ +#undef HAVE_TCFS + +/* Path for lastlog file. */ +#undef LASTLOG_FILE + +/* Define to support /etc/login.access login access control. */ +#undef LOGIN_ACCESS + +/* Location of system mail spool directory. */ +#undef MAIL_SPOOL_DIR + +/* Name of user's mail spool file if stored in user's home directory. */ +#undef MAIL_SPOOL_FILE + +/* Define to support the MD5-based password hashing algorithm. */ +#undef MD5_CRYPT + +/* Define to use ndbm. */ +#undef NDBM + +/* Define to enable the new readpass() that echoes asterisks. */ +#undef NEW_READPASS + +/* Define to support OPIE one-time password logins. */ +#undef OPIE + +/* Package name. */ +#undef PACKAGE + +/* Define if pam_strerror() needs two arguments (Linux-PAM 0.59). */ +#undef PAM_STRERROR_NEEDS_TWO_ARGS + +/* Path to passwd program. */ +#undef PASSWD_PROGRAM + +/* Define if the compiler understands function prototypes. */ +#undef PROTOTYPES + +/* Define if login should support the -r flag for rlogind. */ +#undef RLOGIN + +/* Define to the ruserok() "success" return value (0 or 1). */ +#undef RUSEROK + +/* Define to support the shadow group file. */ +#undef SHADOWGRP + +/* Define to support the shadow password file. */ +#undef SHADOWPWD + +/* Define to support S/Key logins. */ +#undef SKEY + +/* Define to support /etc/suauth su access control. */ +#undef SU_ACCESS + +/* Define to support SecureWare(tm) long passwords. */ +#undef SW_CRYPT + +/* Define if you want gdbm for TCFS. */ +#undef TCFS_GDBM_SUPPORT + +/* Define to support Pluggable Authentication Modules. */ +#undef USE_PAM + +/* Define to use syslog(). */ +#undef USE_SYSLOG + +/* Define if you have ut_host in struct utmp. */ +#undef UT_HOST + +/* Path for utmp file. */ +#undef _UTMP_FILE + +/* Define to ut_name if struct utmp has ut_name (not ut_user). */ +#undef ut_user + +/* Version. */ +#undef VERSION + +/* Path for wtmp file. */ +#undef _WTMP_FILE + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 00000000..aea062ce --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,868 @@ +dnl aclocal.m4 generated automatically by aclocal 1.3 + +dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +dnl This Makefile.in is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. + +# Do all the work for Automake. This macro actually does too much -- +# some checks are only needed if your package does certain things. +# But this isn't really a big deal. + +# serial 1 + +dnl Usage: +dnl AM_INIT_AUTOMAKE(package,version, [no-define]) + +AC_DEFUN(AM_INIT_AUTOMAKE, +[AC_REQUIRE([AM_PROG_INSTALL]) +PACKAGE=[$1] +AC_SUBST(PACKAGE) +VERSION=[$2] +AC_SUBST(VERSION) +dnl test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi +ifelse([$3],, +AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE") +AC_DEFINE_UNQUOTED(VERSION, "$VERSION")) +AC_REQUIRE([AM_SANITY_CHECK]) +AC_REQUIRE([AC_ARG_PROGRAM]) +dnl FIXME This is truly gross. +missing_dir=`cd $ac_aux_dir && pwd` +AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) +AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) +AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) +AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) +AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir) +AC_REQUIRE([AC_PROG_MAKE_SET])]) + + +# serial 1 + +AC_DEFUN(AM_PROG_INSTALL, +[AC_REQUIRE([AC_PROG_INSTALL]) +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' +AC_SUBST(INSTALL_SCRIPT)dnl +]) + +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "[$]*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "[$]*" != "X $srcdir/configure conftestfile" \ + && test "[$]*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) + +dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY) +dnl The program must properly implement --version. +AC_DEFUN(AM_MISSING_PROG, +[AC_MSG_CHECKING(for working $2) +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if ($2 --version) < /dev/null > /dev/null 2>&1; then + $1=$2 + AC_MSG_RESULT(found) +else + $1="$3/missing $2" + AC_MSG_RESULT(missing) +fi +AC_SUBST($1)]) + +# Like AC_CONFIG_HEADER, but automatically create stamp file. + +AC_DEFUN(AM_CONFIG_HEADER, +[AC_PREREQ([2.12]) +AC_CONFIG_HEADER([$1]) +dnl When config.status generates a header, we must update the stamp-h file. +dnl This file resides in the same directory as the config header +dnl that is generated. We must strip everything past the first ":", +dnl and everything past the last "/". +AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl +ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>, +<>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>, +<>; do + case " <<$>>CONFIG_HEADERS " in + *" <<$>>am_file "*<<)>> + echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx + ;; + esac + am_indx=`expr "<<$>>am_indx" + 1` +done<<>>dnl>>) +changequote([,]))]) + + +# serial 1 + +AC_DEFUN(AM_C_PROTOTYPES, +[AC_REQUIRE([AM_PROG_CC_STDC]) +AC_REQUIRE([AC_PROG_CPP]) +AC_MSG_CHECKING([for function prototypes]) +if test "$am_cv_prog_cc_stdc" != no; then + AC_MSG_RESULT(yes) + AC_DEFINE(PROTOTYPES) + U= ANSI2KNR= +else + AC_MSG_RESULT(no) + U=_ ANSI2KNR=./ansi2knr + # Ensure some checks needed by ansi2knr itself. + AC_HEADER_STDC + AC_CHECK_HEADERS(string.h) +fi +AC_SUBST(U)dnl +AC_SUBST(ANSI2KNR)dnl +]) + + +# serial 1 + +# @defmac AC_PROG_CC_STDC +# @maindex PROG_CC_STDC +# @ovindex CC +# If the C compiler in not in ANSI C mode by default, try to add an option +# to output variable @code{CC} to make it so. This macro tries various +# options that select ANSI C on some system or another. It considers the +# compiler to be in ANSI C mode if it handles function prototypes correctly. +# +# If you use this macro, you should check after calling it whether the C +# compiler has been set to accept ANSI C; if not, the shell variable +# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source +# code in ANSI C, you can make an un-ANSIfied copy of it by using the +# program @code{ansi2knr}, which comes with Ghostscript. +# @end defmac + +AC_DEFUN(AM_PROG_CC_STDC, +[AC_REQUIRE([AC_PROG_CC]) +AC_BEFORE([$0], [AC_C_INLINE]) +AC_BEFORE([$0], [AC_C_CONST]) +dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require +dnl a magic option to avoid problems with ANSI preprocessor commands +dnl like #elif. +dnl FIXME: can't do this because then AC_AIX won't work due to a +dnl circular dependency. +dnl AC_BEFORE([$0], [AC_PROG_CPP]) +AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C) +AC_CACHE_VAL(am_cv_prog_cc_stdc, +[am_cv_prog_cc_stdc=no +ac_save_CC="$CC" +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + AC_TRY_COMPILE( +[#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +], [ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; +], +[am_cv_prog_cc_stdc="$ac_arg"; break]) +done +CC="$ac_save_CC" +]) +if test -z "$am_cv_prog_cc_stdc"; then + AC_MSG_RESULT([none needed]) +else + AC_MSG_RESULT($am_cv_prog_cc_stdc) +fi +case "x$am_cv_prog_cc_stdc" in + x|xno) ;; + *) CC="$CC $am_cv_prog_cc_stdc" ;; +esac +]) + + +# serial 24 AM_PROG_LIBTOOL +AC_DEFUN(AM_PROG_LIBTOOL, +[AC_REQUIRE([AM_ENABLE_SHARED])dnl +AC_REQUIRE([AM_ENABLE_STATIC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_RANLIB])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AM_PROG_LD])dnl +AC_REQUIRE([AM_PROG_NM])dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +dnl +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Check for any special flags to pass to ltconfig. +libtool_flags= +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$silent" = yes && libtool_flags="$libtool_flags --silent" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + CFLAGS="$CFLAGS -belf" + ;; +esac + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| AC_MSG_ERROR([libtool configure failed]) +]) + +# AM_ENABLE_SHARED - implement the --enable-shared flag +# Usage: AM_ENABLE_SHARED[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AM_ENABLE_SHARED, +[define([AM_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(shared, +changequote(<<, >>)dnl +<< --enable-shared build shared libraries [default=>>AM_ENABLE_SHARED_DEFAULT] +changequote([, ])dnl +[ --enable-shared=PKGS only build shared libraries if the current package + appears as an element in the PKGS list], +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_shared=AM_ENABLE_SHARED_DEFAULT)dnl +]) + +# AM_DISABLE_SHARED - set the default shared flag to --disable-shared +AC_DEFUN(AM_DISABLE_SHARED, +[AM_ENABLE_SHARED(no)]) + +# AM_DISABLE_STATIC - set the default static flag to --disable-static +AC_DEFUN(AM_DISABLE_STATIC, +[AM_ENABLE_STATIC(no)]) + +# AM_ENABLE_STATIC - implement the --enable-static flag +# Usage: AM_ENABLE_STATIC[(DEFAULT)] +# Where DEFAULT is either `yes' or `no'. If omitted, it defaults to +# `yes'. +AC_DEFUN(AM_ENABLE_STATIC, +[define([AM_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE(static, +changequote(<<, >>)dnl +<< --enable-static build static libraries [default=>>AM_ENABLE_STATIC_DEFAULT] +changequote([, ])dnl +[ --enable-static=PKGS only build shared libraries if the current package + appears as an element in the PKGS list], +[p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac], +enable_static=AM_ENABLE_STATIC_DEFAULT)dnl +]) + + +# AM_PROG_LD - find the path to the GNU or non-GNU linker +AC_DEFUN(AM_PROG_LD, +[AC_ARG_WITH(gnu-ld, +[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]], +test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no) +AC_REQUIRE([AC_PROG_CC]) +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by GCC]) + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | [A-Za-z]:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(ac_cv_path_LD, +[if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$ac_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_SUBST(LD) +AM_PROG_LD_GNU +]) + +AC_DEFUN(AM_PROG_LD_GNU, +[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi]) +]) + +# AM_PROG_NM - find the path to a BSD-compatible name lister +AC_DEFUN(AM_PROG_NM, +[AC_MSG_CHECKING([for BSD-compatible nm]) +AC_CACHE_VAL(ac_cv_path_NM, +[case "$NM" in +/* | [A-Za-z]:\\*) + ac_cv_path_NM="$NM" # Let the user override the test with a path. + ;; +*) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + else + ac_cv_path_NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm + ;; +esac]) +NM="$ac_cv_path_NM" +AC_MSG_RESULT([$NM]) +AC_SUBST(NM) +]) + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 5 + +AC_DEFUN(AM_WITH_NLS, + [AC_MSG_CHECKING([whether NLS is requested]) + dnl Default is enabled NLS + AC_ARG_ENABLE(nls, + [ --disable-nls do not use Native Language Support], + USE_NLS=$enableval, USE_NLS=yes) + AC_MSG_RESULT($USE_NLS) + AC_SUBST(USE_NLS) + + USE_INCLUDED_LIBINTL=no + + dnl If we use NLS figure out what method + if test "$USE_NLS" = "yes"; then + AC_DEFINE(ENABLE_NLS) + AC_MSG_CHECKING([whether included gettext is requested]) + AC_ARG_WITH(included-gettext, + [ --with-included-gettext use the GNU gettext library included here], + nls_cv_force_use_gnu_gettext=$withval, + nls_cv_force_use_gnu_gettext=no) + AC_MSG_RESULT($nls_cv_force_use_gnu_gettext) + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + dnl User does not insist on using GNU NLS library. Figure out what + dnl to use. If gettext or catgets are available (in this order) we + dnl use this. Else we have to fall back to GNU NLS library. + dnl catgets is only used if permitted by option --with-catgets. + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + AC_CHECK_HEADER(libintl.h, + [AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc, + [AC_TRY_LINK([#include ], [return (int) gettext ("")], + gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)]) + + if test "$gt_cv_func_gettext_libc" != "yes"; then + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CACHE_CHECK([for gettext in libintl], + gt_cv_func_gettext_libintl, + [AC_CHECK_LIB(intl, gettext, + gt_cv_func_gettext_libintl=yes, + gt_cv_func_gettext_libintl=no)], + gt_cv_func_gettext_libintl=no)]) + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + AC_DEFINE(HAVE_GETTEXT) + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + AC_CHECK_FUNCS(dcgettext) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + INSTOBJEXT=.mo + fi + fi + ]) + + if test "$CATOBJEXT" = "NONE"; then + AC_MSG_CHECKING([whether catgets can be used]) + AC_ARG_WITH(catgets, + [ --with-catgets use catgets functions if available], + nls_cv_use_catgets=$withval, nls_cv_use_catgets=no) + AC_MSG_RESULT($nls_cv_use_catgets) + + if test "$nls_cv_use_catgets" = "yes"; then + dnl No gettext in C library. Try catgets next. + AC_CHECK_LIB(i, main) + AC_CHECK_FUNC(catgets, + [AC_DEFINE(HAVE_CATGETS) + INTLOBJS="\$(CATOBJS)" + AC_PATH_PROG(GENCAT, gencat, no)dnl + if test "$GENCAT" != "no"; then + AC_PATH_PROG(GMSGFMT, gmsgfmt, no) + if test "$GMSGFMT" = "no"; then + AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no) + fi + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.cat + INSTOBJEXT=.cat + DATADIRNAME=lib + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi]) + fi + fi + + if test "$CATOBJEXT" = "NONE"; then + dnl Neither gettext nor catgets in included in the C library. + dnl Fall back on GNU gettext library. + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + dnl Mark actions used to generate GNU NLS library. + INTLOBJS="\$(GETTOBJS)" + AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_SUBST(MSGFMT) + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl) + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(USE_INCLUDED_LIBINTL) + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLDEPS) + AC_SUBST(INTLLIBS) + AC_SUBST(INTLOBJS) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +AC_DEFUN(AM_GNU_GETTEXT, + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_C_CONST])dnl + AC_REQUIRE([AC_C_INLINE])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + + AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h sys/param.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \ +strdup __argz_count __argz_stringify __argz_next]) + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + AC_CHECK_FUNCS(stpcpy) + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + AC_DEFINE(HAVE_STPCPY) + fi + + AM_LC_MESSAGES + AM_WITH_NLS + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl The reference to in the installed file + dnl must be resolved because we cannot expect the users of this + dnl to define HAVE_LOCALE_H. + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include " + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header . Take care yourself. */" + fi + AC_SUBST(INCLUDE_LOCALE_H) + + dnl Determine which catalog format we have (if any is needed) + dnl For now we know about two different formats: + dnl Linux libc-5 and the normal X/Open format + test -d intl || mkdir intl + if test "$CATOBJEXT" = ".cat"; then + AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen) + + dnl Transform the SED scripts while copying because some dumb SEDs + dnl cannot handle comments. + sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed + fi + dnl po2tbl.sed is always needed. + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed + + dnl In the intl/Makefile.in we have a special dependency which makes + dnl only sense for gettext. We comment this out for non-gettext + dnl packages. + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + AC_SUBST(GT_NO) + AC_SUBST(GT_YES) + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl *** For now the libtool support in intl/Makefile is not for real. + l= + AC_SUBST(l) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN(AM_PATH_PROG_WITH_TEST, +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +# serial 1 + +AC_DEFUN(AM_LC_MESSAGES, + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES) + fi + fi]) + diff --git a/ansi2knr.1 b/ansi2knr.1 new file mode 100644 index 00000000..f9ee5a63 --- /dev/null +++ b/ansi2knr.1 @@ -0,0 +1,36 @@ +.TH ANSI2KNR 1 "19 Jan 1996" +.SH NAME +ansi2knr \- convert ANSI C to Kernighan & Ritchie C +.SH SYNOPSIS +.I ansi2knr +[--varargs] input_file [output_file] +.SH DESCRIPTION +If no output_file is supplied, output goes to stdout. +.br +There are no error messages. +.sp +.I ansi2knr +recognizes function definitions by seeing a non-keyword identifier at the left +margin, followed by a left parenthesis, with a right parenthesis as the last +character on the line, and with a left brace as the first token on the +following line (ignoring possible intervening comments). It will recognize a +multi-line header provided that no intervening line ends with a left or right +brace or a semicolon. These algorithms ignore whitespace and comments, except +that the function name must be the first thing on the line. +.sp +The following constructs will confuse it: +.br + - Any other construct that starts at the left margin and follows the +above syntax (such as a macro or function call). +.br + - Some macros that tinker with the syntax of the function header. +.sp +The --varargs switch is obsolete, and is recognized only for +backwards compatibility. The present version of +.I ansi2knr +will always attempt to convert a ... argument to va_alist and va_dcl. +.SH AUTHOR +L. Peter Deutsch wrote the original ansi2knr and +continues to maintain the current version; most of the code in the current +version is his work. ansi2knr also includes contributions by Francois +Pinard and Jim Avera . diff --git a/ansi2knr.c b/ansi2knr.c new file mode 100644 index 00000000..80086856 --- /dev/null +++ b/ansi2knr.c @@ -0,0 +1,574 @@ +/* Copyright (C) 1989, 1997 Aladdin Enterprises. All rights reserved. */ + +/*$Id: ansi2knr.c,v 1.9 1998/04/03 21:56:52 tromey Exp $*/ +/* Convert ANSI C function definitions to K&R ("traditional C") syntax */ + +/* +ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY. No author or distributor accepts responsibility to anyone for the +consequences of using it or for whether it serves any particular purpose or +works at all, unless he says so in writing. Refer to the GNU General Public +License (the "GPL") for full details. + +Everyone is granted permission to copy, modify and redistribute ansi2knr, +but only under the conditions described in the GPL. A copy of this license +is supposed to have been given to you along with ansi2knr so you can know +your rights and responsibilities. It should be in a file named COPYLEFT, +or, if there is no file named COPYLEFT, a file named COPYING. Among other +things, the copyright notice and this notice must be preserved on all +copies. + +We explicitly state here what we believe is already implied by the GPL: if +the ansi2knr program is distributed as a separate set of sources and a +separate executable file which are aggregated on a storage medium together +with another program, this in itself does not bring the other program under +the GPL, nor does the mere fact that such a program or the procedures for +constructing it invoke the ansi2knr executable bring any other part of the +program under the GPL. +*/ + +/* + * Usage: + ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]] + * --filename provides the file name for the #line directive in the output, + * overriding input_file (if present). + * If no input_file is supplied, input is read from stdin. + * If no output_file is supplied, output goes to stdout. + * There are no error messages. + * + * ansi2knr recognizes function definitions by seeing a non-keyword + * identifier at the left margin, followed by a left parenthesis, + * with a right parenthesis as the last character on the line, + * and with a left brace as the first token on the following line + * (ignoring possible intervening comments). + * It will recognize a multi-line header provided that no intervening + * line ends with a left or right brace or a semicolon. + * These algorithms ignore whitespace and comments, except that + * the function name must be the first thing on the line. + * The following constructs will confuse it: + * - Any other construct that starts at the left margin and + * follows the above syntax (such as a macro or function call). + * - Some macros that tinker with the syntax of the function header. + */ + +/* + * The original and principal author of ansi2knr is L. Peter Deutsch + * . Other authors are noted in the change history + * that follows (in reverse chronological order): + lpd 97-12-08 made input_file optional; only closes input and/or + output file if not stdin or stdout respectively; prints + usage message on stderr rather than stdout; adds + --filename switch (changes suggested by + ) + lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with + compilers that don't understand void, as suggested by + Tom Lane + lpd 96-01-15 changed to require that the first non-comment token + on the line following a function header be a left brace, + to reduce sensitivity to macros, as suggested by Tom Lane + + lpd 95-06-22 removed #ifndefs whose sole purpose was to define + undefined preprocessor symbols as 0; changed all #ifdefs + for configuration symbols to #ifs + lpd 95-04-05 changed copyright notice to make it clear that + including ansi2knr in a program does not bring the entire + program under the GPL + lpd 94-12-18 added conditionals for systems where ctype macros + don't handle 8-bit characters properly, suggested by + Francois Pinard ; + removed --varargs switch (this is now the default) + lpd 94-10-10 removed CONFIG_BROKETS conditional + lpd 94-07-16 added some conditionals to help GNU `configure', + suggested by Francois Pinard ; + properly erase prototype args in function parameters, + contributed by Jim Avera ; + correct error in writeblanks (it shouldn't erase EOLs) + lpd 89-xx-xx original version + */ + +/* Most of the conditionals here are to make ansi2knr work with */ +/* or without the GNU configure machinery. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include + +#if HAVE_CONFIG_H + +/* + For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h). + This will define HAVE_CONFIG_H and so, activate the following lines. + */ + +# if STDC_HEADERS || HAVE_STRING_H +# include +# else +# include +# endif + +#else /* not HAVE_CONFIG_H */ + +/* Otherwise do it the hard way */ + +# ifdef BSD +# include +# else +# ifdef VMS + extern int strlen(), strncmp(); +# else +# include +# endif +# endif + +#endif /* not HAVE_CONFIG_H */ + +#if STDC_HEADERS +# include +#else +/* + malloc and free should be declared in stdlib.h, + but if you've got a K&R compiler, they probably aren't. + */ +# ifdef MSDOS +# include +# else +# ifdef VMS + extern char *malloc(); + extern void free(); +# else + extern char *malloc(); + extern int free(); +# endif +# endif + +#endif + +/* + * The ctype macros don't always handle 8-bit characters correctly. + * Compensate for this here. + */ +#ifdef isascii +# undef HAVE_ISASCII /* just in case */ +# define HAVE_ISASCII 1 +#else +#endif +#if STDC_HEADERS || !HAVE_ISASCII +# define is_ascii(c) 1 +#else +# define is_ascii(c) isascii(c) +#endif + +#define is_space(c) (is_ascii(c) && isspace(c)) +#define is_alpha(c) (is_ascii(c) && isalpha(c)) +#define is_alnum(c) (is_ascii(c) && isalnum(c)) + +/* Scanning macros */ +#define isidchar(ch) (is_alnum(ch) || (ch) == '_') +#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_') + +/* Forward references */ +char *skipspace(); +int writeblanks(); +int test1(); +int convert1(); + +/* The main program */ +int +main(argc, argv) + int argc; + char *argv[]; +{ FILE *in = stdin; + FILE *out = stdout; + char *filename = 0; +#define bufsize 5000 /* arbitrary size */ + char *buf; + char *line; + char *more; + char *usage = + "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n"; + /* + * In previous versions, ansi2knr recognized a --varargs switch. + * If this switch was supplied, ansi2knr would attempt to convert + * a ... argument to va_alist and va_dcl; if this switch was not + * supplied, ansi2knr would simply drop any such arguments. + * Now, ansi2knr always does this conversion, and we only + * check for this switch for backward compatibility. + */ + int convert_varargs = 1; + + while ( argc > 1 && argv[1][0] == '-' ) { + if ( !strcmp(argv[1], "--varargs") ) { + convert_varargs = 1; + argc--; + argv++; + continue; + } + if ( !strcmp(argv[1], "--filename") && argc > 2 ) { + filename = argv[2]; + argc -= 2; + argv += 2; + continue; + } + fprintf(stderr, "Unrecognized switch: %s\n", argv[1]); + fprintf(stderr, usage); + exit(1); + } + switch ( argc ) + { + default: + fprintf(stderr, usage); + exit(0); + case 3: + out = fopen(argv[2], "w"); + if ( out == NULL ) { + fprintf(stderr, "Cannot open output file %s\n", argv[2]); + exit(1); + } + /* falls through */ + case 2: + in = fopen(argv[1], "r"); + if ( in == NULL ) { + fprintf(stderr, "Cannot open input file %s\n", argv[1]); + exit(1); + } + if ( filename == 0 ) + filename = argv[1]; + /* falls through */ + case 1: + break; + } + if ( filename ) + fprintf(out, "#line 1 \"%s\"\n", filename); + buf = malloc(bufsize); + line = buf; + while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) + { +test: line += strlen(line); + switch ( test1(buf) ) + { + case 2: /* a function header */ + convert1(buf, out, 1, convert_varargs); + break; + case 1: /* a function */ + /* Check for a { at the start of the next line. */ + more = ++line; +f: if ( line >= buf + (bufsize - 1) ) /* overflow check */ + goto wl; + if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL ) + goto wl; + switch ( *skipspace(more, 1) ) + { + case '{': + /* Definitely a function header. */ + convert1(buf, out, 0, convert_varargs); + fputs(more, out); + break; + case 0: + /* The next line was blank or a comment: */ + /* keep scanning for a non-comment. */ + line += strlen(line); + goto f; + default: + /* buf isn't a function header, but */ + /* more might be. */ + fputs(buf, out); + strcpy(buf, more); + line = buf; + goto test; + } + break; + case -1: /* maybe the start of a function */ + if ( line != buf + (bufsize - 1) ) /* overflow check */ + continue; + /* falls through */ + default: /* not a function */ +wl: fputs(buf, out); + break; + } + line = buf; + } + if ( line != buf ) + fputs(buf, out); + free(buf); + if ( out != stdout ) + fclose(out); + if ( in != stdin ) + fclose(in); + return 0; +} + +/* Skip over space and comments, in either direction. */ +char * +skipspace(p, dir) + register char *p; + register int dir; /* 1 for forward, -1 for backward */ +{ for ( ; ; ) + { while ( is_space(*p) ) + p += dir; + if ( !(*p == '/' && p[dir] == '*') ) + break; + p += dir; p += dir; + while ( !(*p == '*' && p[dir] == '/') ) + { if ( *p == 0 ) + return p; /* multi-line comment?? */ + p += dir; + } + p += dir; p += dir; + } + return p; +} + +/* + * Write blanks over part of a string. + * Don't overwrite end-of-line characters. + */ +int +writeblanks(start, end) + char *start; + char *end; +{ char *p; + for ( p = start; p < end; p++ ) + if ( *p != '\r' && *p != '\n' ) + *p = ' '; + return 0; +} + +/* + * Test whether the string in buf is a function definition. + * The string may contain and/or end with a newline. + * Return as follows: + * 0 - definitely not a function definition; + * 1 - definitely a function definition; + * 2 - definitely a function prototype (NOT USED); + * -1 - may be the beginning of a function definition, + * append another line and look again. + * The reason we don't attempt to convert function prototypes is that + * Ghostscript's declaration-generating macros look too much like + * prototypes, and confuse the algorithms. + */ +int +test1(buf) + char *buf; +{ register char *p = buf; + char *bend; + char *endfn; + int contin; + + if ( !isidfirstchar(*p) ) + return 0; /* no name at left margin */ + bend = skipspace(buf + strlen(buf) - 1, -1); + switch ( *bend ) + { + case ';': contin = 0 /*2*/; break; + case ')': contin = 1; break; + case '{': return 0; /* not a function */ + case '}': return 0; /* not a function */ + default: contin = -1; + } + while ( isidchar(*p) ) + p++; + endfn = p; + p = skipspace(p, 1); + if ( *p++ != '(' ) + return 0; /* not a function */ + p = skipspace(p, 1); + if ( *p == ')' ) + return 0; /* no parameters */ + /* Check that the apparent function name isn't a keyword. */ + /* We only need to check for keywords that could be followed */ + /* by a left parenthesis (which, unfortunately, is most of them). */ + { static char *words[] = + { "asm", "auto", "case", "char", "const", "double", + "extern", "float", "for", "if", "int", "long", + "register", "return", "short", "signed", "sizeof", + "static", "switch", "typedef", "unsigned", + "void", "volatile", "while", 0 + }; + char **key = words; + char *kp; + int len = endfn - buf; + + while ( (kp = *key) != 0 ) + { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) + return 0; /* name is a keyword */ + key++; + } + } + return contin; +} + +/* Convert a recognized function definition or header to K&R syntax. */ +int +convert1(buf, out, header, convert_varargs) + char *buf; + FILE *out; + int header; /* Boolean */ + int convert_varargs; /* Boolean */ +{ char *endfn; + register char *p; + /* + * The breaks table contains pointers to the beginning and end + * of each argument. + */ + char **breaks; + unsigned num_breaks = 2; /* for testing */ + char **btop; + char **bp; + char **ap; + char *vararg = 0; + + /* Pre-ANSI implementations don't agree on whether strchr */ + /* is called strchr or index, so we open-code it here. */ + for ( endfn = buf; *(endfn++) != '('; ) + ; +top: p = endfn; + breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); + if ( breaks == 0 ) + { /* Couldn't allocate break table, give up */ + fprintf(stderr, "Unable to allocate break table!\n"); + fputs(buf, out); + return -1; + } + btop = breaks + num_breaks * 2 - 2; + bp = breaks; + /* Parse the argument list */ + do + { int level = 0; + char *lp = NULL; + char *rp; + char *end = NULL; + + if ( bp >= btop ) + { /* Filled up break table. */ + /* Allocate a bigger one and start over. */ + free((char *)breaks); + num_breaks <<= 1; + goto top; + } + *bp++ = p; + /* Find the end of the argument */ + for ( ; end == NULL; p++ ) + { switch(*p) + { + case ',': + if ( !level ) end = p; + break; + case '(': + if ( !level ) lp = p; + level++; + break; + case ')': + if ( --level < 0 ) end = p; + else rp = p; + break; + case '/': + p = skipspace(p, 1) - 1; + break; + default: + ; + } + } + /* Erase any embedded prototype parameters. */ + if ( lp ) + writeblanks(lp + 1, rp); + p--; /* back up over terminator */ + /* Find the name being declared. */ + /* This is complicated because of procedure and */ + /* array modifiers. */ + for ( ; ; ) + { p = skipspace(p - 1, -1); + switch ( *p ) + { + case ']': /* skip array dimension(s) */ + case ')': /* skip procedure args OR name */ + { int level = 1; + while ( level ) + switch ( *--p ) + { + case ']': case ')': level++; break; + case '[': case '(': level--; break; + case '/': p = skipspace(p, -1) + 1; break; + default: ; + } + } + if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) + { /* We found the name being declared */ + while ( !isidfirstchar(*p) ) + p = skipspace(p, 1) + 1; + goto found; + } + break; + default: + goto found; + } + } +found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) + { if ( convert_varargs ) + { *bp++ = "va_alist"; + vararg = p-2; + } + else + { p++; + if ( bp == breaks + 1 ) /* sole argument */ + writeblanks(breaks[0], p); + else + writeblanks(bp[-1] - 1, p); + bp--; + } + } + else + { while ( isidchar(*p) ) p--; + *bp++ = p+1; + } + p = end; + } + while ( *p++ == ',' ); + *bp = p; + /* Make a special check for 'void' arglist */ + if ( bp == breaks+2 ) + { p = skipspace(breaks[0], 1); + if ( !strncmp(p, "void", 4) ) + { p = skipspace(p+4, 1); + if ( p == breaks[2] - 1 ) + { bp = breaks; /* yup, pretend arglist is empty */ + writeblanks(breaks[0], p + 1); + } + } + } + /* Put out the function name and left parenthesis. */ + p = buf; + while ( p != endfn ) putc(*p, out), p++; + /* Put out the declaration. */ + if ( header ) + { fputs(");", out); + for ( p = breaks[0]; *p; p++ ) + if ( *p == '\r' || *p == '\n' ) + putc(*p, out); + } + else + { for ( ap = breaks+1; ap < bp; ap += 2 ) + { p = *ap; + while ( isidchar(*p) ) + putc(*p, out), p++; + if ( ap < bp - 1 ) + fputs(", ", out); + } + fputs(") ", out); + /* Put out the argument declarations */ + for ( ap = breaks+2; ap <= bp; ap += 2 ) + (*ap)[-1] = ';'; + if ( vararg != 0 ) + { *vararg = 0; + fputs(breaks[0], out); /* any prior args */ + fputs("va_dcl", out); /* the final arg */ + fputs(bp[0], out); + } + else + fputs(breaks[0], out); + } + free((char *)breaks); + return 0; +} diff --git a/config.guess b/config.guess new file mode 100755 index 00000000..6010014b --- /dev/null +++ b/config.guess @@ -0,0 +1,975 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. +# +# This file 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# Please send patches to the Autoconf mailing list . +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <$dummy.s + .globl main + .ent main +main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + ${CC-cc} $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + arm32:NetBSD:*:*) + echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + macppc:NetBSD:*:*) + echo powerpc-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >$dummy.c + int main (argc, argv) int argc; char **argv; { + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + ${CC-cc} $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ] ; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + ${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'` + if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 ) + sed 's/^ //' << EOF >$dummy.c + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (${CC-cc} $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + ${CC-cc} $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*T3E:*:*:*) + echo t3e-cray-unicosmk${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | i?86:BSD/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # uname on the ARM produces all sorts of strangeness, and we need to + # filter it out. + case "$UNAME_MACHINE" in + armv*) ;; + arm* | sa110*) UNAME_MACHINE="arm" ;; + esac + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. + ld_help_string=`ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;; + i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;; + sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + sed 's/^ //' <$dummy.s + .globl main + .ent main + main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + LIBC="" + ${CC-cc} $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + + objdump --private-headers $dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >$dummy.c </dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +main(argc, argv) + int argc; + char *argv[]; +{ +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + ${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i?86:UnixWare:*:*) + if /bin/uname -X 2>/dev/null >/dev/null ; then + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + fi + echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION} + exit 0 ;; + pc:*:*:*) + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +${CC-cc} $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/config.h.in b/config.h.in new file mode 100644 index 00000000..24cc620d --- /dev/null +++ b/config.h.in @@ -0,0 +1,456 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to empty if the keyword does not work. */ +#undef const + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define to the type of elements in the array set by `getgroups'. + Usually this is either `int' or `gid_t'. */ +#undef GETGROUPS_T + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if your struct stat has st_rdev. */ +#undef HAVE_ST_RDEV + +/* Define if you have the strftime function. */ +#undef HAVE_STRFTIME + +/* Define if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define if utime(file, NULL) sets file's timestamp to the present. */ +#undef HAVE_UTIME_NULL + +/* Define as __inline if that's what the C compiler calls it. */ +#undef inline + +/* Define to `int' if doesn't define. */ +#undef mode_t + +/* Define to `long' if doesn't define. */ +#undef off_t + +/* Define to `int' if doesn't define. */ +#undef pid_t + +/* Define if you need to in order for stat and other things to work. */ +#undef _POSIX_SOURCE + +/* Define as the return type of signal handlers (int or void). */ +#undef RETSIGTYPE + +/* Define if the `setpgrp' function takes no argument. */ +#undef SETPGRP_VOID + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define if your declares struct tm. */ +#undef TM_IN_SYS_TIME + +/* Define to `int' if doesn't define. */ +#undef uid_t + +/* Define if you do not have , index, bzero, etc.. */ +#undef USG + +/* Define to enable password aging. */ +#undef AGING + +/* Define if struct passwd has pw_age. */ +#undef ATT_AGE + +/* Define if struct passwd has pw_comment. */ +#undef ATT_COMMENT + +/* Define if struct passwd has pw_quota. */ +#undef BSD_QUOTA + +/* Define if you have secure RPC. */ +#undef DES_RPC + +/* Define to 1 if NLS is requested. */ +#undef ENABLE_NLS + +/* Path for faillog file. */ +#undef FAILLOG_FILE + +/* Define to libshadow_getpass to use our own version of getpass(). */ +#undef getpass + +/* Define as 1 if you have catgets and don't want to use GNU gettext. */ +#undef HAVE_CATGETS + +/* Define as 1 if you have gettext and don't want to use GNU gettext. */ +#undef HAVE_GETTEXT + +/* Define if your locale.h file contains LC_MESSAGES. */ +#undef HAVE_LC_MESSAGES + +/* Defined if you have libcrack. */ +#undef HAVE_LIBCRACK + +/* Defined if you have the ts&szs cracklib. */ +#undef HAVE_LIBCRACK_HIST + +/* Defined if it includes *Pw functions. */ +#undef HAVE_LIBCRACK_PW + +/* Defined if you have libcrypt. */ +#undef HAVE_LIBCRYPT + +/* Define if struct lastlog has ll_host */ +#undef HAVE_LL_HOST + +/* Working shadow group support in libc? */ +#undef HAVE_SHADOWGRP + +/* Define to 1 if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define to support TCFS. */ +#undef HAVE_TCFS + +/* Path for lastlog file. */ +#undef LASTLOG_FILE + +/* Define to support /etc/login.access login access control. */ +#undef LOGIN_ACCESS + +/* Location of system mail spool directory. */ +#undef MAIL_SPOOL_DIR + +/* Name of user's mail spool file if stored in user's home directory. */ +#undef MAIL_SPOOL_FILE + +/* Define to support the MD5-based password hashing algorithm. */ +#undef MD5_CRYPT + +/* Define to enable the new readpass() that echoes asterisks. */ +#undef NEW_READPASS + +/* Define to support OPIE one-time password logins. */ +#undef OPIE + +/* Package name. */ +#undef PACKAGE + +/* Define if pam_strerror() needs two arguments (Linux-PAM 0.59). */ +#undef PAM_STRERROR_NEEDS_TWO_ARGS + +/* Path to passwd program. */ +#undef PASSWD_PROGRAM + +/* Define if the compiler understands function prototypes. */ +#undef PROTOTYPES + +/* Define if login should support the -r flag for rlogind. */ +#undef RLOGIN + +/* Define to the ruserok() "success" return value (0 or 1). */ +#undef RUSEROK + +/* Define to support the shadow group file. */ +#undef SHADOWGRP + +/* Define to support the shadow password file. */ +#undef SHADOWPWD + +/* Define to support S/Key logins. */ +#undef SKEY + +/* Define to support /etc/suauth su access control. */ +#undef SU_ACCESS + +/* Define if you want gdbm for TCFS. */ +#undef TCFS_GDBM_SUPPORT + +/* Define to support Pluggable Authentication Modules. */ +#undef USE_PAM + +/* Define to use syslog(). */ +#undef USE_SYSLOG + +/* Define if you have ut_host in struct utmp. */ +#undef UT_HOST + +/* Path for utmp file. */ +#undef _UTMP_FILE + +/* Define to ut_name if struct utmp has ut_name (not ut_user). */ +#undef ut_user + +/* Version. */ +#undef VERSION + +/* Path for wtmp file. */ +#undef _WTMP_FILE + +/* Define if you have the __argz_count function. */ +#undef HAVE___ARGZ_COUNT + +/* Define if you have the __argz_next function. */ +#undef HAVE___ARGZ_NEXT + +/* Define if you have the __argz_stringify function. */ +#undef HAVE___ARGZ_STRINGIFY + +/* Define if you have the a64l function. */ +#undef HAVE_A64L + +/* Define if you have the dcgettext function. */ +#undef HAVE_DCGETTEXT + +/* Define if you have the fchmod function. */ +#undef HAVE_FCHMOD + +/* Define if you have the fchown function. */ +#undef HAVE_FCHOWN + +/* Define if you have the fsync function. */ +#undef HAVE_FSYNC + +/* Define if you have the getcwd function. */ +#undef HAVE_GETCWD + +/* Define if you have the getgroups function. */ +#undef HAVE_GETGROUPS + +/* Define if you have the gethostname function. */ +#undef HAVE_GETHOSTNAME + +/* Define if you have the getpagesize function. */ +#undef HAVE_GETPAGESIZE + +/* Define if you have the getspnam function. */ +#undef HAVE_GETSPNAM + +/* Define if you have the gettimeofday function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define if you have the getusershell function. */ +#undef HAVE_GETUSERSHELL + +/* Define if you have the getutent function. */ +#undef HAVE_GETUTENT + +/* Define if you have the initgroups function. */ +#undef HAVE_INITGROUPS + +/* Define if you have the lckpwdf function. */ +#undef HAVE_LCKPWDF + +/* Define if you have the memcpy function. */ +#undef HAVE_MEMCPY + +/* Define if you have the memset function. */ +#undef HAVE_MEMSET + +/* Define if you have the mkdir function. */ +#undef HAVE_MKDIR + +/* Define if you have the munmap function. */ +#undef HAVE_MUNMAP + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the putgrent function. */ +#undef HAVE_PUTGRENT + +/* Define if you have the putpwent function. */ +#undef HAVE_PUTPWENT + +/* Define if you have the putspent function. */ +#undef HAVE_PUTSPENT + +/* Define if you have the rename function. */ +#undef HAVE_RENAME + +/* Define if you have the rmdir function. */ +#undef HAVE_RMDIR + +/* Define if you have the setenv function. */ +#undef HAVE_SETENV + +/* Define if you have the setgroups function. */ +#undef HAVE_SETGROUPS + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the sgetgrent function. */ +#undef HAVE_SGETGRENT + +/* Define if you have the sgetpwent function. */ +#undef HAVE_SGETPWENT + +/* Define if you have the sgetspent function. */ +#undef HAVE_SGETSPENT + +/* Define if you have the sigaction function. */ +#undef HAVE_SIGACTION + +/* Define if you have the snprintf function. */ +#undef HAVE_SNPRINTF + +/* Define if you have the stpcpy function. */ +#undef HAVE_STPCPY + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strchr function. */ +#undef HAVE_STRCHR + +/* Define if you have the strdup function. */ +#undef HAVE_STRDUP + +/* Define if you have the strerror function. */ +#undef HAVE_STRERROR + +/* Define if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define if you have the updwtmp function. */ +#undef HAVE_UPDWTMP + +/* Define if you have the updwtmpx function. */ +#undef HAVE_UPDWTMPX + +/* Define if you have the header file. */ +#undef HAVE_ARGZ_H + +/* Define if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_GSHADOW_H + +/* Define if you have the header file. */ +#undef HAVE_LASTLOG_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_LOCALE_H + +/* Define if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define if you have the header file. */ +#undef HAVE_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_NL_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define if you have the header file. */ +#undef HAVE_RPC_KEY_PROT_H + +/* Define if you have the header file. */ +#undef HAVE_SGTTY_H + +/* Define if you have the header file. */ +#undef HAVE_SHADOW_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_DIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_ULIMIT_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_USERSEC_H + +/* Define if you have the header file. */ +#undef HAVE_UTIME_H + +/* Define if you have the header file. */ +#undef HAVE_UTMP_H + +/* Define if you have the header file. */ +#undef HAVE_UTMPX_H + +/* Define if you have the i library (-li). */ +#undef HAVE_LIBI + +/* Define if you have the inet library (-linet). */ +#undef HAVE_LIBINET + +/* Define if you have the nsl library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the socket library (-lsocket). */ +#undef HAVE_LIBSOCKET diff --git a/config.sub b/config.sub new file mode 100755 index 00000000..8e0adacb --- /dev/null +++ b/config.sub @@ -0,0 +1,965 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc. +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple) + os= + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ + | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 \ + | alpha | alphaev5 | alphaev56 | alphapca56 | alphaev6 \ + | alphapca57 | alphaev7 | we32k | ns16k | clipper \ + | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ + | mips64 | mipsel | mips64el | mips64orion | mips64orionel \ + | mipstx39 | mipstx39el | armv[34][lb] \ + | sparc | sparclet | sparclite | sparc64 | v850) + basic_machine=$basic_machine-unknown + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[34567]86) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ + | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \ + | alpha-* | alphaev5-* | alphaev56-* | alphapca56-* \ + | alphaev6-* | alphapca57-* | alphaev7-* | we32k-* | cydra-* \ + | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | mips64-* | mipsel-* | armv[34][lb]-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mipstx39-* | mipstx39el-* \ + | f301-* | armv*-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netwinder) + basic_machine=armv4l-corel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + np1) + basic_machine=np1-gould + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | k6 | 6x86) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | k6-* | 6x86-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -rhapsody* \ + | -openstep*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -xenix) + os=-xenix + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-corel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f301-fujitsu) + os=-uxpv + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -hpux*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/configure b/configure new file mode 100755 index 00000000..7ec4164a --- /dev/null +++ b/configure @@ -0,0 +1,6506 @@ +#! /bin/sh + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help + --enable-shared build shared libraries [default=yes] + --enable-shared=PKGS only build shared libraries if the current package + appears as an element in the PKGS list" +ac_help="$ac_help + --enable-static build static libraries [default=yes] + --enable-static=PKGS only build shared libraries if the current package + appears as an element in the PKGS list" +ac_help="$ac_help + --with-gnu-ld assume the C compiler uses GNU ld [default=no]" +ac_help="$ac_help + --enable-desrpc try to use secure RPC in login (default if found)" +ac_help="$ac_help + --enable-readpass include code to enter passwords that echoes asterisks" +ac_help="$ac_help + --enable-shadowgrp enable shadow group support [default=yes]" +ac_help="$ac_help + --with-libcrack try to use libcrack (default if found)" +ac_help="$ac_help + --with-libcrypt try to use libcrypt (default if found)" +ac_help="$ac_help + --with-libopie use libopie for OPIE support" +ac_help="$ac_help + --with-libpam use libpam for PAM support" +ac_help="$ac_help + --with-libskey use libskey for S/Key support" +ac_help="$ac_help + --with-libtcfs use libtcfs for TCFS support" +ac_help="$ac_help + --disable-nls do not use Native Language Support" +ac_help="$ac_help + --with-included-gettext use the GNU gettext library included here" +ac_help="$ac_help + --with-catgets use catgets functions if available" + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.12" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=lib/dialchk.c + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:586: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + for ac_prog in ginstall installbsd scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + # OSF/1 installbsd also uses dspmsg, but is usable. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 +echo "configure:639: checking whether build environment is sane" >&5 +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + if test "$*" != "X $srcdir/configure conftestfile" \ + && test "$*" != "X conftestfile $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { echo "configure: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" 1>&2; exit 1; } + fi + + test "$2" = conftestfile + ) +then + # Ok. + : +else + { echo "configure: error: newly created file is older than distributed files! +Check your system clock" 1>&2; exit 1; } +fi +rm -f conftest* +echo "$ac_t""yes" 1>&6 +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:696: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + +PACKAGE=shadow + +VERSION=19990709 + +if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then + { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } +fi +cat >> confdefs.h <> confdefs.h <&6 +echo "configure:742: checking for working aclocal" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (aclocal --version) < /dev/null > /dev/null 2>&1; then + ACLOCAL=aclocal + echo "$ac_t""found" 1>&6 +else + ACLOCAL="$missing_dir/missing aclocal" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 +echo "configure:755: checking for working autoconf" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoconf --version) < /dev/null > /dev/null 2>&1; then + AUTOCONF=autoconf + echo "$ac_t""found" 1>&6 +else + AUTOCONF="$missing_dir/missing autoconf" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working automake""... $ac_c" 1>&6 +echo "configure:768: checking for working automake" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (automake --version) < /dev/null > /dev/null 2>&1; then + AUTOMAKE=automake + echo "$ac_t""found" 1>&6 +else + AUTOMAKE="$missing_dir/missing automake" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 +echo "configure:781: checking for working autoheader" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (autoheader --version) < /dev/null > /dev/null 2>&1; then + AUTOHEADER=autoheader + echo "$ac_t""found" 1>&6 +else + AUTOHEADER="$missing_dir/missing autoheader" + echo "$ac_t""missing" 1>&6 +fi + +echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 +echo "configure:794: checking for working makeinfo" >&5 +# Run test in a subshell; some versions of sh will print an error if +# an executable is not found, even if stderr is redirected. +# Redirect stdin to placate older versions of autoconf. Sigh. +if (makeinfo --version) < /dev/null > /dev/null 2>&1; then + MAKEINFO=makeinfo + echo "$ac_t""found" 1>&6 +else + MAKEINFO="$missing_dir/missing makeinfo" + echo "$ac_t""missing" 1>&6 +fi + + + + + + +test "$prefix" = "NONE" && prefix="/usr" +test "$prefix" = "/usr" && exec_prefix="" +test "$CFLAGS" = "" && CFLAGS="-O2 -Wall" +test "$LDFLAGS" = "" && LDFLAGS="-s" + +ALL_LINGUAS="el pl" + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:821: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:850: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:898: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:932: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:937: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:961: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" + fi +else + GCC= + test "${CFLAGS+set}" = set || CFLAGS="-g" +fi + +echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6 +echo "configure:989: checking for POSIXized ISC" >&5 +if test -d /etc/conf/kconfig.d && + grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1 +then + echo "$ac_t""yes" 1>&6 + ISC=yes # If later tests want to check for ISC. + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + if test "$GCC" = yes; then + CC="$CC -posix" + else + CC="$CC -Xp" + fi +else + echo "$ac_t""no" 1>&6 + ISC= +fi + +echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 +echo "configure:1010: checking whether ln -s works" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata +if ln -s X conftestdata 2>/dev/null +then + rm -f conftestdata + ac_cv_prog_LN_S="ln -s" +else + ac_cv_prog_LN_S=ln +fi +fi +LN_S="$ac_cv_prog_LN_S" +if test "$ac_cv_prog_LN_S" = "ln -s"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +for ac_prog in 'bison -y' byacc +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1035: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_YACC="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +YACC="$ac_cv_prog_YACC" +if test -n "$YACC"; then + echo "$ac_t""$YACC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + + + + +echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6 +echo "configure:1068: checking for ${CC-cc} option to accept ANSI C" >&5 +if eval "test \"`echo '$''{'am_cv_prog_cc_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + am_cv_prog_cc_stdc=no +ac_save_CC="$CC" +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + cat > conftest.$ac_ext < +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; + +int main() { + +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + +; return 0; } +EOF +if { (eval echo configure:1121: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + am_cv_prog_cc_stdc="$ac_arg"; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done +CC="$ac_save_CC" + +fi + +if test -z "$am_cv_prog_cc_stdc"; then + echo "$ac_t""none needed" 1>&6 +else + echo "$ac_t""$am_cv_prog_cc_stdc" 1>&6 +fi +case "x$am_cv_prog_cc_stdc" in + x|xno) ;; + *) CC="$CC $am_cv_prog_cc_stdc" ;; +esac + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1145: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1166: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext < +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1183: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + + + +echo $ac_n "checking for function prototypes""... $ac_c" 1>&6 +echo "configure:1208: checking for function prototypes" >&5 +if test "$am_cv_prog_cc_stdc" != no; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define PROTOTYPES 1 +EOF + + U= ANSI2KNR= +else + echo "$ac_t""no" 1>&6 + U=_ ANSI2KNR=./ansi2knr + # Ensure some checks needed by ansi2knr itself. + echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1221: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1234: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1301: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + + for ac_hdr in string.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1328: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1338: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +fi + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_shared=yes ;; +no) enable_shared=no ;; +*) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_shared=yes +fi + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + p=${PACKAGE-default} +case "$enableval" in +yes) enable_static=yes ;; +no) enable_static=no ;; +*) + enable_static=no + # Look at the argument we got. We use all the common list separators. + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:," + for pkg in $enableval; do + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$ac_save_ifs" + ;; +esac +else + enable_static=yes +fi + + +# Make sure we can run config.sub. +if $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:1419: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`$ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`$ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:1442: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + + +ac_prog=ld +if test "$ac_cv_prog_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC""... $ac_c" 1>&6 +echo "configure:1481: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | A-Za-z:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld""... $ac_c" 1>&6 +echo "configure:1499: checking for GNU ld" >&5 +else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 +echo "configure:1502: checking for non-GNU ld" >&5 +fi +if eval "test \"`echo '$''{'ac_cv_path_LD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + ac_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" +else + ac_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$ac_cv_path_LD" +if test -n "$LD"; then + echo "$ac_t""$LD" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +test -z "$LD" && { echo "configure: error: no acceptable ld found in \$PATH" 1>&2; exit 1; } + +echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6 +echo "configure:1538: checking if the linker ($LD) is GNU ld" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + ac_cv_prog_gnu_ld=yes +else + ac_cv_prog_gnu_ld=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6 + + +echo $ac_n "checking for BSD-compatible nm""... $ac_c" 1>&6 +echo "configure:1554: checking for BSD-compatible nm" >&5 +if eval "test \"`echo '$''{'ac_cv_path_NM'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$NM" in +/* | A-Za-z:\\*) + ac_cv_path_NM="$NM" # Let the user override the test with a path. + ;; +*) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + ac_cv_path_NM="$ac_dir/nm -p" + else + ac_cv_path_NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm + ;; +esac +fi + +NM="$ac_cv_path_NM" +echo "$ac_t""$NM" 1>&6 + + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Check for any special flags to pass to ltconfig. +libtool_flags= +test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared" +test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static" +test "$silent" = yes && libtool_flags="$libtool_flags --silent" +test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc" +test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld" + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case "$host" in +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 1606 "configure"' > conftest.$ac_ext + if { (eval echo configure:1607: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + CFLAGS="$CFLAGS -belf" + ;; +esac + +# Actually configure libtool. ac_aux_dir is where install-sh is found. +CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \ +LD="$LD" NM="$NM" RANLIB="$RANLIB" LN_S="$LN_S" \ +${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig \ +$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \ +|| { echo "configure: error: libtool configure failed" 1>&2; exit 1; } + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 +echo "configure:1643: checking for $ac_hdr that defines DIR" >&5 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include <$ac_hdr> +int main() { +DIR *dirp = 0; +; return 0; } +EOF +if { (eval echo configure:1656: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 +echo "configure:1681: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldir $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -ldir" +else + echo "$ac_t""no" 1>&6 +fi + +else +echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 +echo "configure:1722: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lx $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lx" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:1764: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +#include +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1777: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext < +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:1844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6 +echo "configure:1868: checking for sys/wait.h that is POSIX.1 compatible" >&5 +if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif +int main() { +int s; +wait (&s); +s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; +; return 0; } +EOF +if { (eval echo configure:1889: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_sys_wait_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_sys_wait_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6 +if test $ac_cv_header_sys_wait_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_SYS_WAIT_H 1 +EOF + +fi + +for ac_hdr in fcntl.h limits.h unistd.h sys/time.h utmp.h utmpx.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1913: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1923: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in termios.h termio.h sgtty.h sys/ioctl.h syslog.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1953: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1963: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in paths.h usersec.h utime.h ulimit.h sys/resource.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:1993: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2003: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_hdr in gshadow.h shadow.h lastlog.h rpc/key_prot.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2033: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2043: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:2071: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:2125: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 +echo "configure:2146: checking for uid_t in sys/types.h" >&5 +if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "uid_t" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_uid_t=yes +else + rm -rf conftest* + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_type_uid_t" 1>&6 +if test $ac_cv_type_uid_t = no; then + cat >> confdefs.h <<\EOF +#define uid_t int +EOF + + cat >> confdefs.h <<\EOF +#define gid_t int +EOF + +fi + +echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:2180: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking for pid_t""... $ac_c" 1>&6 +echo "configure:2213: checking for pid_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_pid_t=yes +else + rm -rf conftest* + ac_cv_type_pid_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_pid_t" 1>&6 +if test $ac_cv_type_pid_t = no; then + cat >> confdefs.h <<\EOF +#define pid_t int +EOF + +fi + +echo $ac_n "checking for mode_t""... $ac_c" 1>&6 +echo "configure:2246: checking for mode_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_mode_t=yes +else + rm -rf conftest* + ac_cv_type_mode_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_mode_t" 1>&6 +if test $ac_cv_type_mode_t = no; then + cat >> confdefs.h <<\EOF +#define mode_t int +EOF + +fi + +echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6 +echo "configure:2279: checking for st_rdev in struct stat" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +int main() { +struct stat s; s.st_rdev; +; return 0; } +EOF +if { (eval echo configure:2292: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_st_rdev=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_st_rdev=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_st_rdev" 1>&6 +if test $ac_cv_struct_st_rdev = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ST_RDEV 1 +EOF + +fi + +echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6 +echo "configure:2313: checking whether stat file-mode macros are broken" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include + +#if defined(S_ISBLK) && defined(S_IFDIR) +# if S_ISBLK (S_IFDIR) +You lose. +# endif +#endif + +#if defined(S_ISBLK) && defined(S_IFCHR) +# if S_ISBLK (S_IFCHR) +You lose. +# endif +#endif + +#if defined(S_ISLNK) && defined(S_IFREG) +# if S_ISLNK (S_IFREG) +You lose. +# endif +#endif + +#if defined(S_ISSOCK) && defined(S_IFREG) +# if S_ISSOCK (S_IFREG) +You lose. +# endif +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "You lose" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_header_stat_broken=yes +else + rm -rf conftest* + ac_cv_header_stat_broken=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_header_stat_broken" 1>&6 +if test $ac_cv_header_stat_broken = yes; then + cat >> confdefs.h <<\EOF +#define STAT_MACROS_BROKEN 1 +EOF + +fi + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:2369: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#include +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:2383: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + +echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 +echo "configure:2404: checking whether struct tm is in sys/time.h or time.h" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +int main() { +struct tm *tp; tp->tm_sec; +; return 0; } +EOF +if { (eval echo configure:2417: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_tm=time.h +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_tm=sys/time.h +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_tm" 1>&6 +if test $ac_cv_struct_tm = sys/time.h; then + cat >> confdefs.h <<\EOF +#define TM_IN_SYS_TIME 1 +EOF + +fi + + +echo $ac_n "checking for pw_age in struct passwd""... $ac_c" 1>&6 +echo "configure:2439: checking for pw_age in struct passwd" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_passwd_pw_age'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + struct passwd pw; pw.pw_age = ""; +; return 0; } +EOF +if { (eval echo configure:2451: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_passwd_pw_age=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_passwd_pw_age=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_passwd_pw_age" 1>&6 + +if test "$ac_cv_struct_passwd_pw_age" = "yes"; then + cat >> confdefs.h <<\EOF +#define ATT_AGE 1 +EOF + +fi + +echo $ac_n "checking for pw_comment in struct passwd""... $ac_c" 1>&6 +echo "configure:2473: checking for pw_comment in struct passwd" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_passwd_pw_comment'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + struct passwd pw; pw.pw_comment = ""; +; return 0; } +EOF +if { (eval echo configure:2485: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_passwd_pw_comment=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_passwd_pw_comment=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_passwd_pw_comment" 1>&6 + +if test "$ac_cv_struct_passwd_pw_comment" = "yes"; then + cat >> confdefs.h <<\EOF +#define ATT_COMMENT 1 +EOF + +fi + +echo $ac_n "checking for pw_quota in struct passwd""... $ac_c" 1>&6 +echo "configure:2507: checking for pw_quota in struct passwd" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_passwd_pw_quota'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + struct passwd pw; pw.pw_quota = ""; +; return 0; } +EOF +if { (eval echo configure:2519: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_passwd_pw_quota=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_passwd_pw_quota=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_passwd_pw_quota" 1>&6 + +if test "$ac_cv_struct_passwd_pw_quota" = "yes"; then + cat >> confdefs.h <<\EOF +#define BSD_QUOTA 1 +EOF + +fi + +if test "$ac_cv_header_utmp_h" = "yes"; then + echo $ac_n "checking for ut_host in struct utmp""... $ac_c" 1>&6 +echo "configure:2542: checking for ut_host in struct utmp" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_utmp_ut_host'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + struct utmp ut; char *cp = ut.ut_host; +; return 0; } +EOF +if { (eval echo configure:2554: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_utmp_ut_host=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_utmp_ut_host=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_utmp_ut_host" 1>&6 + + if test "$ac_cv_struct_utmp_ut_host" = "yes"; then + cat >> confdefs.h <<\EOF +#define UT_HOST 1 +EOF + + fi + + echo $ac_n "checking for ut_user in struct utmp""... $ac_c" 1>&6 +echo "configure:2576: checking for ut_user in struct utmp" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_utmp_ut_user'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + struct utmp ut; char *cp = ut.ut_user; +; return 0; } +EOF +if { (eval echo configure:2588: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_utmp_ut_user=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_utmp_ut_user=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_utmp_ut_user" 1>&6 + + if test "$ac_cv_struct_utmp_ut_user" = "no"; then + cat >> confdefs.h <<\EOF +#define ut_user ut_name +EOF + + fi +fi + +if test "$ac_cv_header_lastlog_h" = "yes"; then + echo $ac_n "checking for ll_host in struct lastlog""... $ac_c" 1>&6 +echo "configure:2612: checking for ll_host in struct lastlog" >&5 +if eval "test \"`echo '$''{'ac_cv_struct_lastlog_ll_host'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + struct lastlog ll; char *cp = ll.ll_host; +; return 0; } +EOF +if { (eval echo configure:2624: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_struct_lastlog_ll_host=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_struct_lastlog_ll_host=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_struct_lastlog_ll_host" 1>&6 + + if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_LL_HOST 1 +EOF + + fi +fi + +echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 +echo "configure:2647: checking type of array argument to getgroups" >&5 +if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_type_getgroups=cross +else + cat > conftest.$ac_ext < +#define NGID 256 +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +main() +{ + gid_t gidset[NGID]; + int i, n; + union { gid_t gval; long lval; } val; + + val.lval = -1; + for (i = 0; i < NGID; i++) + gidset[i] = val.gval; + n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, + gidset); + /* Exit non-zero if getgroups seems to require an array of ints. This + happens when gid_t is short but getgroups modifies an array of ints. */ + exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0); +} + +EOF +if { (eval echo configure:2680: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_type_getgroups=gid_t +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_type_getgroups=int +fi +rm -fr conftest* +fi + +if test $ac_cv_type_getgroups = cross; then + cat > conftest.$ac_ext < +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "getgroups.*int.*gid_t" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_getgroups=gid_t +else + rm -rf conftest* + ac_cv_type_getgroups=int +fi +rm -f conftest* + +fi +fi + +echo "$ac_t""$ac_cv_type_getgroups" 1>&6 +cat >> confdefs.h <&6 +echo "configure:2719: checking whether ${CC-cc} needs -traditional" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_pattern="Autoconf.*'x'" + cat > conftest.$ac_ext < +Autoconf TIOCGETP +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +else + rm -rf conftest* + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat > conftest.$ac_ext < +Autoconf TCGETA +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "$ac_pattern" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi + +echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6 + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 +echo "configure:2765: checking return type of signal handlers" >&5 +if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#include +#ifdef signal +#undef signal +#endif +#ifdef __cplusplus +extern "C" void (*signal (int, void (*)(int)))(int); +#else +void (*signal ()) (); +#endif + +int main() { +int i; +; return 0; } +EOF +if { (eval echo configure:2787: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_type_signal=void +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_type_signal=int +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_type_signal" 1>&6 +cat >> confdefs.h <&6 +echo "configure:2806: checking whether utime accepts a null argument" >&5 +if eval "test \"`echo '$''{'ac_cv_func_utime_null'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + rm -f conftestdata; > conftestdata +# Sequent interprets utime(file, 0) to mean use start of epoch. Wrong. +if test "$cross_compiling" = yes; then + ac_cv_func_utime_null=no +else + cat > conftest.$ac_ext < +#include +main() { +struct stat s, t; +exit(!(stat ("conftestdata", &s) == 0 && utime("conftestdata", (long *)0) == 0 +&& stat("conftestdata", &t) == 0 && t.st_mtime >= s.st_mtime +&& t.st_mtime - s.st_mtime < 120)); +} +EOF +if { (eval echo configure:2827: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_func_utime_null=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_utime_null=no +fi +rm -fr conftest* +fi + +rm -f core core.* *.core +fi + +echo "$ac_t""$ac_cv_func_utime_null" 1>&6 +if test $ac_cv_func_utime_null = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_UTIME_NULL 1 +EOF + +fi + +echo $ac_n "checking for strftime""... $ac_c" 1>&6 +echo "configure:2851: checking for strftime" >&5 +if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char strftime(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_strftime) || defined (__stub___strftime) +choke me +#else +strftime(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_strftime=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_strftime=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_STRFTIME 1 +EOF + +else + echo "$ac_t""no" 1>&6 +# strftime is in -lintl on SCO UNIX. +echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 +echo "configure:2901: checking for strftime in -lintl" >&5 +ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_STRFTIME 1 +EOF + +LIBS="-lintl $LIBS" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +for ac_func in a64l fchmod fchown fsync getgroups gethostname getspnam +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2949: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2977: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in gettimeofday getusershell getutent initgroups lckpwdf +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3004: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3032: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in memcpy memset setgroups sigaction strchr updwtmp updwtmpx +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3059: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + +for ac_func in mkdir putgrent putpwent putspent rename rmdir +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3115: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3143: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +LIBOBJS="$LIBOBJS ${ac_func}.o" +fi +done + + +for ac_func in sgetgrent sgetpwent sgetspent +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3172: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3200: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +LIBOBJS="$LIBOBJS ${ac_func}.o" +fi +done + + +for ac_func in snprintf strcasecmp strdup strerror strstr +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3229: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +LIBOBJS="$LIBOBJS ${ac_func}.o" +fi +done + + + +echo $ac_n "checking for setpgrp""... $ac_c" 1>&6 +echo "configure:3285: checking for setpgrp" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setpgrp'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char setpgrp(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_setpgrp) || defined (__stub___setpgrp) +choke me +#else +setpgrp(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_setpgrp=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_setpgrp=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'setpgrp`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + +echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6 +echo "configure:3333: checking whether setpgrp takes no argument" >&5 +if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_func_setpgrp_void=no +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_setpgrp_void=yes +fi +rm -fr conftest* +fi + + +fi + +echo "$ac_t""$ac_cv_func_setpgrp_void" 1>&6 +if test $ac_cv_func_setpgrp_void = yes; then + cat >> confdefs.h <<\EOF +#define SETPGRP_VOID 1 +EOF + +fi + + +if test "$ac_cv_header_shadow_h" = "yes"; then +echo $ac_n "checking for working shadow group support""... $ac_c" 1>&6 +echo "configure:3383: checking for working shadow group support" >&5 +if eval "test \"`echo '$''{'ac_cv_libc_shadowgrp'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_libc_shadowgrp=no +else + cat > conftest.$ac_ext < +main() +{ + struct sgrp *sg = sgetsgent("test:x::"); + /* NYS libc on Red Hat 3.0.3 has broken shadow group support */ + return !sg || !sg->sg_adm || !sg->sg_mem; +} + +EOF +if { (eval echo configure:3403: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_libc_shadowgrp=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_libc_shadowgrp=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_libc_shadowgrp" 1>&6 + +if test "$ac_cv_libc_shadowgrp" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_SHADOWGRP 1 +EOF + +fi +fi + +echo $ac_n "checking location of shared mail directory""... $ac_c" 1>&6 +echo "configure:3428: checking location of shared mail directory" >&5 +for maildir in /var/spool/mail /var/mail /usr/spool/mail /usr/mail NONE; do + if test "$maildir" = "NONE"; then + echo "$ac_t""None" 1>&6 + elif test -d $maildir; then + cat >> confdefs.h <&6 + break + fi +done + +echo $ac_n "checking location of user mail file""... $ac_c" 1>&6 +echo "configure:3443: checking location of user mail file" >&5 +for mailfile in Mailbox mailbox Mail mail .mail NONE; do + if test "$mailfile" = "NONE"; then + echo "$ac_t""None" 1>&6 + elif test -f $HOME/$mailfile; then + cat >> confdefs.h <&6 + break + fi +done + +echo $ac_n "checking location of utmp""... $ac_c" 1>&6 +echo "configure:3458: checking location of utmp" >&5 +for utmpdir in /var/run /var/adm /usr/adm /etc NONE; do + if test "$utmpdir" = "NONE"; then + echo "configure: warning: utmp file not found" 1>&2 + elif test -f $utmpdir/utmp; then + cat >> confdefs.h <&6 + break + fi +done + +echo $ac_n "checking location of faillog/lastlog/wtmp""... $ac_c" 1>&6 +echo "configure:3473: checking location of faillog/lastlog/wtmp" >&5 +for logdir in /var/log /var/adm /usr/adm /etc; do + if test -d $logdir; then + cat >> confdefs.h <> confdefs.h <> confdefs.h <&6 + break + fi +done + +echo $ac_n "checking location of the passwd program""... $ac_c" 1>&6 +echo "configure:3494: checking location of the passwd program" >&5 +if test -f /usr/bin/passwd; then + passwd_dir=/usr/bin +else + passwd_dir=/bin +fi +cat >> confdefs.h <&6 + +cat >> confdefs.h <<\EOF +#define SHADOWPWD 1 +EOF + +cat >> confdefs.h <<\EOF +#define USG 1 +EOF + +cat >> confdefs.h <<\EOF +#define AGING 1 +EOF + +cat >> confdefs.h <<\EOF +#define USE_SYSLOG 1 +EOF + +cat >> confdefs.h <<\EOF +#define RLOGIN 1 +EOF + +cat >> confdefs.h <<\EOF +#define RUSEROK 0 +EOF + +cat >> confdefs.h <<\EOF +#define LOGIN_ACCESS 1 +EOF + +cat >> confdefs.h <<\EOF +#define SU_ACCESS 1 +EOF + + +cat >> confdefs.h <<\EOF +#define getpass libshadow_getpass +EOF + + +# Check whether --enable-desrpc or --disable-desrpc was given. +if test "${enable_desrpc+set}" = set; then + enableval="$enable_desrpc" + : +fi + +# Check whether --enable-readpass or --disable-readpass was given. +if test "${enable_readpass+set}" = set; then + enableval="$enable_readpass" + : +fi + +# Check whether --enable-shadowgrp or --disable-shadowgrp was given. +if test "${enable_shadowgrp+set}" = set; then + enableval="$enable_shadowgrp" + : +fi + + +# Check whether --with-libcrack or --without-libcrack was given. +if test "${with_libcrack+set}" = set; then + withval="$with_libcrack" + : +fi + +# Check whether --with-libcrypt or --without-libcrypt was given. +if test "${with_libcrypt+set}" = set; then + withval="$with_libcrypt" + : +fi + +# Check whether --with-libopie or --without-libopie was given. +if test "${with_libopie+set}" = set; then + withval="$with_libopie" + : +fi + +# Check whether --with-libpam or --without-libpam was given. +if test "${with_libpam+set}" = set; then + withval="$with_libpam" + : +fi + +# Check whether --with-libskey or --without-libskey was given. +if test "${with_libskey+set}" = set; then + withval="$with_libskey" + : +fi + +# Check whether --with-libtcfs or --without-libtcfs was given. +if test "${with_libtcfs+set}" = set; then + withval="$with_libtcfs" + : +fi + + + +echo $ac_n "checking for inet_ntoa""... $ac_c" 1>&6 +echo "configure:3602: checking for inet_ntoa" >&5 +if eval "test \"`echo '$''{'ac_cv_func_inet_ntoa'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char inet_ntoa(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_inet_ntoa) || defined (__stub___inet_ntoa) +choke me +#else +inet_ntoa(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_inet_ntoa=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_inet_ntoa=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'inet_ntoa`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for inet_ntoa in -linet""... $ac_c" 1>&6 +echo "configure:3648: checking for inet_ntoa in -linet" >&5 +ac_lib_var=`echo inet'_'inet_ntoa | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-linet $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo inet | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + +fi + +echo $ac_n "checking for socket""... $ac_c" 1>&6 +echo "configure:3697: checking for socket" >&5 +if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_socket) || defined (__stub___socket) +choke me +#else +socket(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3725: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_socket=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_socket=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 +echo "configure:3743: checking for socket in -lsocket" >&5 +ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + +fi + +echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 +echo "configure:3792: checking for gethostbyname" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +gethostbyname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3820: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_gethostbyname=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gethostbyname=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:3838: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + +fi + + + +if test "$enable_desrpc" != "no" -a "$ac_cv_header_rpc_key_prot_h" = "yes" ; then + echo $ac_n "checking for getsecretkey""... $ac_c" 1>&6 +echo "configure:3890: checking for getsecretkey" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getsecretkey'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char getsecretkey(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_getsecretkey) || defined (__stub___getsecretkey) +choke me +#else +getsecretkey(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3918: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_getsecretkey=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_getsecretkey=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'getsecretkey`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define DES_RPC 1 +EOF + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for getsecretkey in -lrpcsvc""... $ac_c" 1>&6 +echo "configure:3939: checking for getsecretkey in -lrpcsvc" >&5 +ac_lib_var=`echo rpcsvc'_'getsecretkey | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lrpcsvc $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define DES_RPC 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +fi + +fi + +if test "$enable_readpass" = "yes" ; then + cat >> confdefs.h <<\EOF +#define NEW_READPASS 1 +EOF + +fi + +if test "$enable_shadowgrp" != "no"; then + cat >> confdefs.h <<\EOF +#define SHADOWGRP 1 +EOF + +fi + + +if test "$with_libcrypt" != "no"; then + echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6 +echo "configure:4002: checking for crypt in -lcrypt" >&5 +ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcrypt $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LIBCRYPT 1 +EOF + LIBCRYPT=-lcrypt +else + echo "$ac_t""no" 1>&6 +fi + +fi + +if test "$enable_md5crypt" = "yes"; then + LIBOBJS="$LIBOBJS md5.o md5crypt.o" + cat >> confdefs.h <<\EOF +#define MD5_CRYPT 1 +EOF + +fi + + +if test "$with_libcrack" != "no"; then + echo "checking cracklib flavour, don't be surprised by the results" + echo $ac_n "checking for FascistCheck in -lcrack""... $ac_c" 1>&6 +echo "configure:4058: checking for FascistCheck in -lcrack" >&5 +ac_lib_var=`echo crack'_'FascistCheck | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcrack $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LIBCRACK 1 +EOF + LIBCRACK=-lcrack +else + echo "$ac_t""no" 1>&6 +fi + + echo $ac_n "checking for FascistHistory in -lcrack""... $ac_c" 1>&6 +echo "configure:4101: checking for FascistHistory in -lcrack" >&5 +ac_lib_var=`echo crack'_'FascistHistory | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcrack $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LIBCRACK_HIST 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + + echo $ac_n "checking for FascistHistoryPw in -lcrack""... $ac_c" 1>&6 +echo "configure:4144: checking for FascistHistoryPw in -lcrack" >&5 +ac_lib_var=`echo crack'_'FascistHistoryPw | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcrack $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_LIBCRACK_PW 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi + +fi + + +if test "$with_libskey" = "yes"; then + echo $ac_n "checking for skeychallenge in -lskey""... $ac_c" 1>&6 +echo "configure:4191: checking for skeychallenge in -lskey" >&5 +ac_lib_var=`echo skey'_'skeychallenge | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lskey $LIBCRYPT $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define SKEY 1 +EOF + LIBSKEY=-lskey +else + echo "$ac_t""no" 1>&6 +fi + +elif test "$with_libopie" = "yes"; then + echo $ac_n "checking for opiechallenge in -lopie""... $ac_c" 1>&6 +echo "configure:4235: checking for opiechallenge in -lopie" >&5 +ac_lib_var=`echo opie'_'opiechallenge | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lopie $LIBCRYPT $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define OPIE 1 +EOF + LIBSKEY=-lopie +else + echo "$ac_t""no" 1>&6 +fi + +fi + + +if test "$with_libtcfs" = "yes"; then + echo $ac_n "checking for tcfs_encrypt_key in -ltcfs""... $ac_c" 1>&6 +echo "configure:4282: checking for tcfs_encrypt_key in -ltcfs" >&5 +ac_lib_var=`echo tcfs'_'tcfs_encrypt_key | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ltcfs -lgdbm $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_TCFS 1 +EOF + cat >> confdefs.h <<\EOF +#define TCFS_GDBM_SUPPORT 1 +EOF + LIBTCFS="-ltcfs -lgdbm" +else + echo "$ac_t""no" 1>&6 +fi + +fi + + +if test "$with_libpam" = "yes"; then + LIBPAM="-lpam -lpam_misc -ldl" + cat >> confdefs.h <<\EOF +#define USE_PAM 1 +EOF + + echo $ac_n "checking whether pam_strerror needs two arguments""... $ac_c" 1>&6 +echo "configure:4337: checking whether pam_strerror needs two arguments" >&5 +if eval "test \"`echo '$''{'ac_cv_pam_strerror_needs_two_args'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { + pam_handle_t *pamh; pam_strerror(pamh, PAM_SUCCESS); +; return 0; } +EOF +if { (eval echo configure:4349: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_pam_strerror_needs_two_args=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_pam_strerror_needs_two_args=no + +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_pam_strerror_needs_two_args" 1>&6 + if test "$ac_cv_pam_strerror_needs_two_args" = "yes"; then + cat >> confdefs.h <<\EOF +#define PAM_STRERROR_NEEDS_TWO_ARGS 1 +EOF + + fi +fi + +LTLIBOBJS=`echo "$LIBOBJS" | sed 's/\.o/.lo/g'` + + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:4376: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <&6 +echo "configure:4416: checking for size_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +#if STDC_HEADERS +#include +#include +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_size_t=yes +else + rm -rf conftest* + ac_cv_type_size_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_size_t" 1>&6 +if test $ac_cv_type_size_t = no; then + cat >> confdefs.h <<\EOF +#define size_t unsigned +EOF + +fi + +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 +echo "configure:4451: checking for working alloca.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +char *p = alloca(2 * sizeof(int)); +; return 0; } +EOF +if { (eval echo configure:4463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ac_cv_header_alloca_h=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_alloca_h=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_alloca_h" 1>&6 +if test $ac_cv_header_alloca_h = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA_H 1 +EOF + +fi + +echo $ac_n "checking for alloca""... $ac_c" 1>&6 +echo "configure:4484: checking for alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +char *alloca (); +# endif +# endif +# endif +#endif + +int main() { +char *p = (char *) alloca(1); +; return 0; } +EOF +if { (eval echo configure:4512: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + ac_cv_func_alloca_works=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_func_alloca_works=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_func_alloca_works" 1>&6 +if test $ac_cv_func_alloca_works = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_ALLOCA 1 +EOF + +fi + +if test $ac_cv_func_alloca_works = no; then + # The SVR3 libPW and SVR4 libucb both contain incompatible functions + # that cause trouble. Some versions do not even contain alloca or + # contain a buggy version. If you still want to use their alloca, + # use ar to extract alloca.o from them instead of compiling alloca.c. + ALLOCA=alloca.o + cat >> confdefs.h <<\EOF +#define C_ALLOCA 1 +EOF + + +echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 +echo "configure:4544: checking whether alloca needs Cray hooks" >&5 +if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <&5 | + egrep "webecray" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_os_cray=yes +else + rm -rf conftest* + ac_cv_os_cray=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_os_cray" 1>&6 +if test $ac_cv_os_cray = yes; then +for ac_func in _getb67 GETB67 getb67; do + echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:4574: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <&6 +fi + +done +fi + +echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 +echo "configure:4629: checking stack direction for C alloca" >&5 +if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_c_stack_direction=0 +else + cat > conftest.$ac_ext < addr) ? 1 : -1; +} +main () +{ + exit (find_stack_direction() < 0); +} +EOF +if { (eval echo configure:4656: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_c_stack_direction=1 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_c_stack_direction=-1 +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_c_stack_direction" 1>&6 +cat >> confdefs.h <&6 +echo "configure:4681: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4691: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + +for ac_func in getpagesize +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:4720: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:4748: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + +echo $ac_n "checking for working mmap""... $ac_c" 1>&6 +echo "configure:4773: checking for working mmap" >&5 +if eval "test \"`echo '$''{'ac_cv_func_mmap_fixed_mapped'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_func_mmap_fixed_mapped=no +else + cat > conftest.$ac_ext < +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# endif + +/* Assume that all systems that can run configure have sys/param.h. */ +# ifndef HAVE_SYS_PARAM_H +# define HAVE_SYS_PARAM_H 1 +# endif + +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +#ifdef __cplusplus +extern "C" { void *malloc(unsigned); } +#else +char *malloc(); +#endif + +int +main() +{ + char *data, *data2, *data3; + int i, pagesize; + int fd; + + pagesize = getpagesize(); + + /* + * First, make a file with some known garbage in it. + */ + data = malloc(pagesize); + if (!data) + exit(1); + for (i = 0; i < pagesize; ++i) + *(data + i) = rand(); + umask(0); + fd = creat("conftestmmap", 0600); + if (fd < 0) + exit(1); + if (write(fd, data, pagesize) != pagesize) + exit(1); + close(fd); + + /* + * Next, try to mmap the file at a fixed address which + * already has something else allocated at it. If we can, + * also make sure that we see the same garbage. + */ + fd = open("conftestmmap", O_RDWR); + if (fd < 0) + exit(1); + data2 = malloc(2 * pagesize); + if (!data2) + exit(1); + data2 += (pagesize - ((int) data2 & (pagesize - 1))) & (pagesize - 1); + if (data2 != mmap(data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + exit(1); + + /* + * Finally, make sure that changes to the mapped area + * do not percolate back to the file as seen by read(). + * (This is a bug on some variants of i386 svr4.0.) + */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = malloc(pagesize); + if (!data3) + exit(1); + if (read(fd, data3, pagesize) != pagesize) + exit(1); + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + exit(1); + close(fd); + unlink("conftestmmap"); + exit(0); +} + +EOF +if { (eval echo configure:4921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + ac_cv_func_mmap_fixed_mapped=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_mmap_fixed_mapped=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$ac_cv_func_mmap_fixed_mapped" 1>&6 +if test $ac_cv_func_mmap_fixed_mapped = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_MMAP 1 +EOF + +fi + + + for ac_hdr in argz.h limits.h locale.h nl_types.h malloc.h string.h \ +unistd.h sys/param.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:4949: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:4959: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <&6 +fi +done + + for ac_func in getcwd munmap putenv setenv setlocale strchr strcasecmp \ +strdup __argz_count __argz_stringify __argz_next +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:4989: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5017: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + + if test "${ac_cv_func_stpcpy+set}" != "set"; then + for ac_func in stpcpy +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:5046: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5074: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + fi + if test "${ac_cv_func_stpcpy}" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_STPCPY 1 +EOF + + fi + + if test $ac_cv_header_locale_h = yes; then + echo $ac_n "checking for LC_MESSAGES""... $ac_c" 1>&6 +echo "configure:5108: checking for LC_MESSAGES" >&5 +if eval "test \"`echo '$''{'am_cv_val_LC_MESSAGES'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return LC_MESSAGES +; return 0; } +EOF +if { (eval echo configure:5120: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + am_cv_val_LC_MESSAGES=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + am_cv_val_LC_MESSAGES=no +fi +rm -f conftest* +fi + +echo "$ac_t""$am_cv_val_LC_MESSAGES" 1>&6 + if test $am_cv_val_LC_MESSAGES = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_LC_MESSAGES 1 +EOF + + fi + fi + echo $ac_n "checking whether NLS is requested""... $ac_c" 1>&6 +echo "configure:5141: checking whether NLS is requested" >&5 + # Check whether --enable-nls or --disable-nls was given. +if test "${enable_nls+set}" = set; then + enableval="$enable_nls" + USE_NLS=$enableval +else + USE_NLS=yes +fi + + echo "$ac_t""$USE_NLS" 1>&6 + + + USE_INCLUDED_LIBINTL=no + + if test "$USE_NLS" = "yes"; then + cat >> confdefs.h <<\EOF +#define ENABLE_NLS 1 +EOF + + echo $ac_n "checking whether included gettext is requested""... $ac_c" 1>&6 +echo "configure:5161: checking whether included gettext is requested" >&5 + # Check whether --with-included-gettext or --without-included-gettext was given. +if test "${with_included_gettext+set}" = set; then + withval="$with_included_gettext" + nls_cv_force_use_gnu_gettext=$withval +else + nls_cv_force_use_gnu_gettext=no +fi + + echo "$ac_t""$nls_cv_force_use_gnu_gettext" 1>&6 + + nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext" + if test "$nls_cv_force_use_gnu_gettext" != "yes"; then + nls_cv_header_intl= + nls_cv_header_libgt= + CATOBJEXT=NONE + + ac_safe=`echo "libintl.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for libintl.h""... $ac_c" 1>&6 +echo "configure:5180: checking for libintl.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:5190: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libc""... $ac_c" 1>&6 +echo "configure:5207: checking for gettext in libc" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +int main() { +return (int) gettext ("") +; return 0; } +EOF +if { (eval echo configure:5219: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + gt_cv_func_gettext_libc=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + gt_cv_func_gettext_libc=no +fi +rm -f conftest* +fi + +echo "$ac_t""$gt_cv_func_gettext_libc" 1>&6 + + if test "$gt_cv_func_gettext_libc" != "yes"; then + echo $ac_n "checking for bindtextdomain in -lintl""... $ac_c" 1>&6 +echo "configure:5235: checking for bindtextdomain in -lintl" >&5 +ac_lib_var=`echo intl'_'bindtextdomain | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for gettext in libintl""... $ac_c" 1>&6 +echo "configure:5270: checking for gettext in libintl" >&5 +if eval "test \"`echo '$''{'gt_cv_func_gettext_libintl'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo $ac_n "checking for gettext in -lintl""... $ac_c" 1>&6 +echo "configure:5275: checking for gettext in -lintl" >&5 +ac_lib_var=`echo intl'_'gettext | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lintl $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + gt_cv_func_gettext_libintl=yes +else + echo "$ac_t""no" 1>&6 +gt_cv_func_gettext_libintl=no +fi + +fi + +echo "$ac_t""$gt_cv_func_gettext_libintl" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + fi + + if test "$gt_cv_func_gettext_libc" = "yes" \ + || test "$gt_cv_func_gettext_libintl" = "yes"; then + cat >> confdefs.h <<\EOF +#define HAVE_GETTEXT 1 +EOF + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5333: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + if test "$MSGFMT" != "no"; then + for ac_func in dcgettext +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:5367: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5395: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5422: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5454: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + CATOBJEXT=.gmo + DATADIRNAME=share +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CATOBJEXT=.mo + DATADIRNAME=lib +fi +rm -f conftest* + INSTOBJEXT=.mo + fi + fi + +else + echo "$ac_t""no" 1>&6 +fi + + + if test "$CATOBJEXT" = "NONE"; then + echo $ac_n "checking whether catgets can be used""... $ac_c" 1>&6 +echo "configure:5517: checking whether catgets can be used" >&5 + # Check whether --with-catgets or --without-catgets was given. +if test "${with_catgets+set}" = set; then + withval="$with_catgets" + nls_cv_use_catgets=$withval +else + nls_cv_use_catgets=no +fi + + echo "$ac_t""$nls_cv_use_catgets" 1>&6 + + if test "$nls_cv_use_catgets" = "yes"; then + echo $ac_n "checking for main in -li""... $ac_c" 1>&6 +echo "configure:5530: checking for main in -li" >&5 +ac_lib_var=`echo i'_'main | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-li $LIBS" +cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo i | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <&6 +fi + + echo $ac_n "checking for catgets""... $ac_c" 1>&6 +echo "configure:5573: checking for catgets" >&5 +if eval "test \"`echo '$''{'ac_cv_func_catgets'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char catgets(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_catgets) || defined (__stub___catgets) +choke me +#else +catgets(); +#endif + +; return 0; } +EOF +if { (eval echo configure:5601: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_catgets=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_catgets=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'catgets`\" = yes"; then + echo "$ac_t""yes" 1>&6 + cat >> confdefs.h <<\EOF +#define HAVE_CATGETS 1 +EOF + + INTLOBJS="\$(CATOBJS)" + # Extract the first word of "gencat", so it can be a program name with args. +set dummy gencat; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5623: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GENCAT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GENCAT" in + /*) + ac_cv_path_GENCAT="$GENCAT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GENCAT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GENCAT" && ac_cv_path_GENCAT="no" + ;; +esac +fi +GENCAT="$ac_cv_path_GENCAT" +if test -n "$GENCAT"; then + echo "$ac_t""$GENCAT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + if test "$GENCAT" != "no"; then + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5655: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="no" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test "$GMSGFMT" = "no"; then + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5688: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="no" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + fi + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5723: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.cat + INSTOBJEXT=.cat + DATADIRNAME=lib + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi +else + echo "$ac_t""no" 1>&6 +fi + + fi + fi + + if test "$CATOBJEXT" = "NONE"; then + nls_cv_use_gnu_gettext=yes + fi + fi + + if test "$nls_cv_use_gnu_gettext" = "yes"; then + INTLOBJS="\$(GETTOBJS)" + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5781: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_MSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$MSGFMT" in + /*) + ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then + ac_cv_path_MSGFMT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="msgfmt" + ;; +esac +fi +MSGFMT="$ac_cv_path_MSGFMT" +if test -n "$MSGFMT"; then + echo "$ac_t""$MSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "gmsgfmt", so it can be a program name with args. +set dummy gmsgfmt; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5815: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_GMSGFMT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$GMSGFMT" in + /*) + ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_path_GMSGFMT="$ac_dir/$ac_word" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" + ;; +esac +fi +GMSGFMT="$ac_cv_path_GMSGFMT" +if test -n "$GMSGFMT"; then + echo "$ac_t""$GMSGFMT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + # Extract the first word of "xgettext", so it can be a program name with args. +set dummy xgettext; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:5847: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_path_XGETTEXT'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + case "$XGETTEXT" in + /*) + ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then + ac_cv_path_XGETTEXT="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" + ;; +esac +fi +XGETTEXT="$ac_cv_path_XGETTEXT" +if test -n "$XGETTEXT"; then + echo "$ac_t""$XGETTEXT" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + + USE_INCLUDED_LIBINTL=yes + CATOBJEXT=.gmo + INSTOBJEXT=.mo + DATADIRNAME=share + INTLDEPS='$(top_builddir)/intl/libintl.a' + INTLLIBS=$INTLDEPS + LIBS=`echo $LIBS | sed -e 's/-lintl//'` + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + + if test "$XGETTEXT" != ":"; then + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + echo "$ac_t""found xgettext program is not GNU xgettext; ignore it" 1>&6 + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + else + DATADIRNAME=share + nls_cv_header_intl=intl/libintl.h + nls_cv_header_libgt=intl/libgettext.h + fi + + + + + # If this is used in GNU gettext we have to set USE_NLS to `yes' + # because some of the sources are only built for this goal. + if test "$PACKAGE" = gettext; then + USE_NLS=yes + USE_INCLUDED_LIBINTL=yes + fi + + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + + + + + + + + + + + + + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + echo $ac_n "checking for catalogs to be installed""... $ac_c" 1>&6 +echo "configure:5940: checking for catalogs to be installed" >&5 + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + echo "$ac_t""$LINGUAS" 1>&6 + fi + + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + if test $ac_cv_header_locale_h = yes; then + INCLUDE_LOCALE_H="#include " + else + INCLUDE_LOCALE_H="\ +/* The system does not provide the header . Take care yourself. */" + fi + + + test -d intl || mkdir intl + if test "$CATOBJEXT" = ".cat"; then + ac_safe=`echo "linux/version.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for linux/version.h""... $ac_c" 1>&6 +echo "configure:5968: checking for linux/version.h" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:5978: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + msgformat=linux +else + echo "$ac_t""no" 1>&6 +msgformat=xopen +fi + + + sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed + fi + sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \ + $srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed + + if test "$PACKAGE" = "gettext"; then + GT_NO="#NO#" + GT_YES= + else + GT_NO= + GT_YES="#YES#" + fi + + + + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + + + l= + + + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS </dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.12" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "libmisc/Makefile man/Makefile lib/Makefile src/Makefile Makefile + contrib/Makefile debian/Makefile doc/Makefile etc/Makefile + intl/Makefile intl/po2tbl.sed po/Makefile.in + etc/pam.d/Makefile old/Makefile + redhat/Makefile redhat/shadow-utils.spec config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@PACKAGE@%$PACKAGE%g +s%@VERSION@%$VERSION%g +s%@ACLOCAL@%$ACLOCAL%g +s%@AUTOCONF@%$AUTOCONF%g +s%@AUTOMAKE@%$AUTOMAKE%g +s%@AUTOHEADER@%$AUTOHEADER%g +s%@MAKEINFO@%$MAKEINFO%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@LN_S@%$LN_S%g +s%@YACC@%$YACC%g +s%@CPP@%$CPP%g +s%@U@%$U%g +s%@ANSI2KNR@%$ANSI2KNR%g +s%@host@%$host%g +s%@host_alias@%$host_alias%g +s%@host_cpu@%$host_cpu%g +s%@host_vendor@%$host_vendor%g +s%@host_os@%$host_os%g +s%@RANLIB@%$RANLIB%g +s%@LD@%$LD%g +s%@NM@%$NM%g +s%@LIBTOOL@%$LIBTOOL%g +s%@LIBOBJS@%$LIBOBJS%g +s%@LIBCRYPT@%$LIBCRYPT%g +s%@LIBCRACK@%$LIBCRACK%g +s%@LIBSKEY@%$LIBSKEY%g +s%@LIBTCFS@%$LIBTCFS%g +s%@LIBPAM@%$LIBPAM%g +s%@LTLIBOBJS@%$LTLIBOBJS%g +s%@ALLOCA@%$ALLOCA%g +s%@USE_NLS@%$USE_NLS%g +s%@MSGFMT@%$MSGFMT%g +s%@GMSGFMT@%$GMSGFMT%g +s%@XGETTEXT@%$XGETTEXT%g +s%@GENCAT@%$GENCAT%g +s%@USE_INCLUDED_LIBINTL@%$USE_INCLUDED_LIBINTL%g +s%@CATALOGS@%$CATALOGS%g +s%@CATOBJEXT@%$CATOBJEXT%g +s%@DATADIRNAME@%$DATADIRNAME%g +s%@GMOFILES@%$GMOFILES%g +s%@INSTOBJEXT@%$INSTOBJEXT%g +s%@INTLDEPS@%$INTLDEPS%g +s%@INTLLIBS@%$INTLLIBS%g +s%@INTLOBJS@%$INTLOBJS%g +s%@POFILES@%$POFILES%g +s%@POSUB@%$POSUB%g +s%@INCLUDE_LOCALE_H@%$INCLUDE_LOCALE_H%g +s%@GT_NO@%$GT_NO%g +s%@GT_YES@%$GT_YES%g +s%@MKINSTALLDIRS@%$MKINSTALLDIRS%g +s%@l@%$l%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF + +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +srcdir=$ac_given_srcdir +while test -n "$ac_sources"; do + set $ac_dests; ac_dest=$1; shift; ac_dests=$* + set $ac_sources; ac_source=$1; shift; ac_sources=$* + + echo "linking $srcdir/$ac_source to $ac_dest" + + if test ! -r $srcdir/$ac_source; then + { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; } + fi + rm -f $ac_dest + + # Make relative symlinks. + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'` + if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then + # The dest file is in a subdirectory. + test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir" + ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dest_dir_suffix. + ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dest_dir_suffix= ac_dots= + fi + + case "$srcdir" in + [/$]*) ac_rel_source="$srcdir/$ac_source" ;; + *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;; + esac + + # Make a symlink if possible; otherwise try a hard link. + if ln -s $ac_rel_source $ac_dest 2>/dev/null || + ln $srcdir/$ac_source $ac_dest; then : + else + { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; } + fi +done +EOF +cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF +test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h +case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac +echo timestamp > stamp-h +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + + diff --git a/configure.in b/configure.in new file mode 100644 index 00000000..7fec19d3 --- /dev/null +++ b/configure.in @@ -0,0 +1,313 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(lib/dialchk.c) +AM_INIT_AUTOMAKE(shadow, 19990709) +AM_CONFIG_HEADER(config.h) + +dnl Some hacks... +test "$prefix" = "NONE" && prefix="/usr" +test "$prefix" = "/usr" && exec_prefix="" +test "$CFLAGS" = "" && CFLAGS="-O2 -Wall" +test "$LDFLAGS" = "" && LDFLAGS="-s" + +ALL_LINGUAS="el pl" + +dnl Checks for programs. +AC_PROG_CC +AC_ISC_POSIX +dnl AC_PROG_INSTALL +AC_PROG_LN_S +dnl AC_PROG_MAKE_SET +AC_PROG_YACC +dnl AC_ARG_PROGRAM +AM_C_PROTOTYPES +AM_PROG_LIBTOOL + +dnl Checks for libraries. + +dnl Checks for header files. +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(fcntl.h limits.h unistd.h sys/time.h utmp.h utmpx.h) +AC_CHECK_HEADERS(termios.h termio.h sgtty.h sys/ioctl.h syslog.h) +AC_CHECK_HEADERS(paths.h usersec.h utime.h ulimit.h sys/resource.h) +AC_CHECK_HEADERS(gshadow.h shadow.h lastlog.h rpc/key_prot.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_UID_T +AC_TYPE_OFF_T +AC_TYPE_PID_T +AC_TYPE_MODE_T +AC_STRUCT_ST_RDEV +AC_HEADER_STAT +AC_HEADER_TIME +AC_STRUCT_TM + +AC_CACHE_CHECK(for pw_age in struct passwd, +ac_cv_struct_passwd_pw_age, AC_TRY_COMPILE([#include ], +[ struct passwd pw; pw.pw_age = ""; ], +ac_cv_struct_passwd_pw_age=yes, ac_cv_struct_passwd_pw_age=no)) + +if test "$ac_cv_struct_passwd_pw_age" = "yes"; then + AC_DEFINE(ATT_AGE) +fi + +AC_CACHE_CHECK(for pw_comment in struct passwd, +ac_cv_struct_passwd_pw_comment, AC_TRY_COMPILE([#include ], +[ struct passwd pw; pw.pw_comment = ""; ], +ac_cv_struct_passwd_pw_comment=yes, ac_cv_struct_passwd_pw_comment=no)) + +if test "$ac_cv_struct_passwd_pw_comment" = "yes"; then + AC_DEFINE(ATT_COMMENT) +fi + +AC_CACHE_CHECK(for pw_quota in struct passwd, +ac_cv_struct_passwd_pw_quota, AC_TRY_COMPILE([#include ], +[ struct passwd pw; pw.pw_quota = ""; ], +ac_cv_struct_passwd_pw_quota=yes, ac_cv_struct_passwd_pw_quota=no)) + +if test "$ac_cv_struct_passwd_pw_quota" = "yes"; then + AC_DEFINE(BSD_QUOTA) +fi + +if test "$ac_cv_header_utmp_h" = "yes"; then + AC_CACHE_CHECK(for ut_host in struct utmp, + ac_cv_struct_utmp_ut_host, AC_TRY_COMPILE([#include ], + [ struct utmp ut; char *cp = ut.ut_host; ], + ac_cv_struct_utmp_ut_host=yes, ac_cv_struct_utmp_ut_host=no)) + + if test "$ac_cv_struct_utmp_ut_host" = "yes"; then + AC_DEFINE(UT_HOST) + fi + + AC_CACHE_CHECK(for ut_user in struct utmp, + ac_cv_struct_utmp_ut_user, AC_TRY_COMPILE([#include ], + [ struct utmp ut; char *cp = ut.ut_user; ], + ac_cv_struct_utmp_ut_user=yes, ac_cv_struct_utmp_ut_user=no)) + + if test "$ac_cv_struct_utmp_ut_user" = "no"; then + AC_DEFINE(ut_user, ut_name) + fi +fi + +if test "$ac_cv_header_lastlog_h" = "yes"; then + AC_CACHE_CHECK(for ll_host in struct lastlog, + ac_cv_struct_lastlog_ll_host, AC_TRY_COMPILE([#include ], + [ struct lastlog ll; char *cp = ll.ll_host; ], + ac_cv_struct_lastlog_ll_host=yes, ac_cv_struct_lastlog_ll_host=no)) + + if test "$ac_cv_struct_lastlog_ll_host" = "yes"; then + AC_DEFINE(HAVE_LL_HOST) + fi +fi + +dnl Checks for library functions. +AC_TYPE_GETGROUPS +AC_PROG_GCC_TRADITIONAL +AC_TYPE_SIGNAL +AC_FUNC_UTIME_NULL +AC_FUNC_STRFTIME +dnl Disabled for now, strtoday.c has problems with year 2000 or later +dnl AC_CHECK_FUNCS(strptime) +AC_CHECK_FUNCS(a64l fchmod fchown fsync getgroups gethostname getspnam) +AC_CHECK_FUNCS(gettimeofday getusershell getutent initgroups lckpwdf) +AC_CHECK_FUNCS(memcpy memset setgroups sigaction strchr updwtmp updwtmpx) + +AC_REPLACE_FUNCS(mkdir putgrent putpwent putspent rename rmdir) +AC_REPLACE_FUNCS(sgetgrent sgetpwent sgetspent) +AC_REPLACE_FUNCS(snprintf strcasecmp strdup strerror strstr) + +AC_CHECK_FUNC(setpgrp) +AC_FUNC_SETPGRP + +if test "$ac_cv_header_shadow_h" = "yes"; then +AC_CACHE_CHECK(for working shadow group support, +ac_cv_libc_shadowgrp, AC_TRY_RUN( +[ +#include +main() +{ + struct sgrp *sg = sgetsgent("test:x::"); + /* NYS libc on Red Hat 3.0.3 has broken shadow group support */ + return !sg || !sg->sg_adm || !sg->sg_mem; +} +], +ac_cv_libc_shadowgrp=yes,ac_cv_libc_shadowgrp=no,ac_cv_libc_shadowgrp=no)) + +if test "$ac_cv_libc_shadowgrp" = "yes"; then + AC_DEFINE(HAVE_SHADOWGRP) +fi +fi + +AC_MSG_CHECKING(location of shared mail directory) +for maildir in /var/spool/mail /var/mail /usr/spool/mail /usr/mail NONE; do + if test "$maildir" = "NONE"; then + AC_MSG_RESULT(None) + elif test -d $maildir; then + AC_DEFINE_UNQUOTED(MAIL_SPOOL_DIR, "$maildir") + AC_MSG_RESULT($maildir) + break + fi +done + +AC_MSG_CHECKING(location of user mail file) +for mailfile in Mailbox mailbox Mail mail .mail NONE; do + if test "$mailfile" = "NONE"; then + AC_MSG_RESULT(None) + elif test -f $HOME/$mailfile; then + AC_DEFINE_UNQUOTED(MAIL_SPOOL_FILE, "$mailfile") + AC_MSG_RESULT($mailfile) + break + fi +done + +AC_MSG_CHECKING(location of utmp) +for utmpdir in /var/run /var/adm /usr/adm /etc NONE; do + if test "$utmpdir" = "NONE"; then + AC_MSG_WARN(utmp file not found) + elif test -f $utmpdir/utmp; then + AC_DEFINE_UNQUOTED(_UTMP_FILE, "$utmpdir/utmp") + AC_MSG_RESULT($utmpdir) + break + fi +done + +AC_MSG_CHECKING(location of faillog/lastlog/wtmp) +for logdir in /var/log /var/adm /usr/adm /etc; do + if test -d $logdir; then + AC_DEFINE_UNQUOTED(_WTMP_FILE, "$logdir/wtmp") + AC_DEFINE_UNQUOTED(LASTLOG_FILE, "$logdir/lastlog") + AC_DEFINE_UNQUOTED(FAILLOG_FILE, "$logdir/faillog") + AC_MSG_RESULT($logdir) + break + fi +done + +AC_MSG_CHECKING(location of the passwd program) +if test -f /usr/bin/passwd; then + passwd_dir=/usr/bin +else + passwd_dir=/bin +fi +AC_DEFINE_UNQUOTED(PASSWD_PROGRAM, "$passwd_dir/passwd") +AC_MSG_RESULT($passwd_dir) + +dnl XXX - quick hack, should disappear before anyone notices :). +AC_DEFINE(SHADOWPWD) +AC_DEFINE(USG) +AC_DEFINE(AGING) +AC_DEFINE(USE_SYSLOG) +AC_DEFINE(RLOGIN) +AC_DEFINE(RUSEROK, 0) +AC_DEFINE(LOGIN_ACCESS) +AC_DEFINE(SU_ACCESS) + +dnl Use our own version of getpass(), which handles long passwords +dnl (unlike many systems which have a limit of 8 characters), and can +dnl be interrupted with Ctrl-C (unlike Linux libc). +AC_DEFINE(getpass, libshadow_getpass) + +AC_ARG_ENABLE(desrpc, [ --enable-desrpc try to use secure RPC in login (default if found)]) +dnl AC_ARG_ENABLE(md5crypt, [ --enable-md5crypt include MD5-compatible crypt function]) +AC_ARG_ENABLE(readpass, [ --enable-readpass include code to enter passwords that echoes asterisks]) +AC_ARG_ENABLE(shadowgrp, [ --enable-shadowgrp enable shadow group support [default=yes]]) + +AC_ARG_WITH(libcrack, [ --with-libcrack try to use libcrack (default if found)]) +AC_ARG_WITH(libcrypt, [ --with-libcrypt try to use libcrypt (default if found)]) +AC_ARG_WITH(libopie, [ --with-libopie use libopie for OPIE support]) +AC_ARG_WITH(libpam, [ --with-libpam use libpam for PAM support]) +AC_ARG_WITH(libskey, [ --with-libskey use libskey for S/Key support]) +AC_ARG_WITH(libtcfs, [ --with-libtcfs use libtcfs for TCFS support]) + +dnl Check for some functions in libc first, only if not found check for +dnl other libraries. This should prevent linking libnsl if not really +dnl needed (Linux glibc, Irix), but still link it if needed (Solaris). + +AC_CHECK_FUNC(inet_ntoa, [], AC_CHECK_LIB(inet, inet_ntoa)) +AC_CHECK_FUNC(socket, [], AC_CHECK_LIB(socket, socket)) +AC_CHECK_FUNC(gethostbyname, [], AC_CHECK_LIB(nsl, gethostbyname)) + +dnl XXX - getsecretkey() causes login to hang for 5 minutes on at least +dnl one RH 4.0 system. Use --disable-desrpc if you have this problem. +dnl Reported by Mohan Khurana . + +if test "$enable_desrpc" != "no" -a "$ac_cv_header_rpc_key_prot_h" = "yes" ; then + AC_CHECK_FUNC(getsecretkey, AC_DEFINE(DES_RPC), + AC_CHECK_LIB(rpcsvc, getsecretkey, AC_DEFINE(DES_RPC))) +fi + +if test "$enable_readpass" = "yes" ; then + AC_DEFINE(NEW_READPASS) +fi + +if test "$enable_shadowgrp" != "no"; then + AC_DEFINE(SHADOWGRP) +fi + +AC_SUBST(LIBCRYPT) +if test "$with_libcrypt" != "no"; then + AC_CHECK_LIB(crypt, crypt, [AC_DEFINE(HAVE_LIBCRYPT) LIBCRYPT=-lcrypt]) +fi + +if test "$enable_md5crypt" = "yes"; then + LIBOBJS="$LIBOBJS md5.o md5crypt.o" + AC_DEFINE(MD5_CRYPT) +fi + +AC_SUBST(LIBCRACK) +if test "$with_libcrack" != "no"; then + echo "checking cracklib flavour, don't be surprised by the results" + AC_CHECK_LIB(crack, FascistCheck, AC_DEFINE(HAVE_LIBCRACK) LIBCRACK=-lcrack) + AC_CHECK_LIB(crack, FascistHistory, AC_DEFINE(HAVE_LIBCRACK_HIST)) + AC_CHECK_LIB(crack, FascistHistoryPw, AC_DEFINE(HAVE_LIBCRACK_PW)) +fi + +AC_SUBST(LIBSKEY) +if test "$with_libskey" = "yes"; then + AC_CHECK_LIB(skey, skeychallenge, AC_DEFINE(SKEY) LIBSKEY=-lskey, , $LIBCRYPT) +elif test "$with_libopie" = "yes"; then + AC_CHECK_LIB(opie, opiechallenge, AC_DEFINE(OPIE) LIBSKEY=-lopie, , $LIBCRYPT) +fi + +AC_SUBST(LIBTCFS) +if test "$with_libtcfs" = "yes"; then + AC_CHECK_LIB(tcfs, tcfs_encrypt_key, AC_DEFINE(HAVE_TCFS) AC_DEFINE(TCFS_GDBM_SUPPORT) LIBTCFS="-ltcfs -lgdbm", , -lgdbm) +fi + +AC_SUBST(LIBPAM) +if test "$with_libpam" = "yes"; then + dnl AC_CHECK_LIB(pam, pam_start, AC_DEFINE(USE_PAM) LIBPAM=-lpam) + dnl the above doesn't work as there is no libpam.a (only .so) + dnl XXX - libpam_misc is probably Linux-PAM specific + LIBPAM="-lpam -lpam_misc -ldl" + AC_DEFINE(USE_PAM) + AC_CACHE_CHECK(whether pam_strerror needs two arguments, + ac_cv_pam_strerror_needs_two_args, + AC_TRY_COMPILE( + [#include ], + [ pam_handle_t *pamh; pam_strerror(pamh, PAM_SUCCESS); ], + ac_cv_pam_strerror_needs_two_args=yes, + ac_cv_pam_strerror_needs_two_args=no + ) + ) + if test "$ac_cv_pam_strerror_needs_two_args" = "yes"; then + AC_DEFINE(PAM_STRERROR_NEEDS_TWO_ARGS) + fi +fi + +LTLIBOBJS=`echo "$LIBOBJS" | sed 's/\.o/.lo/g'` +AC_SUBST(LTLIBOBJS) +dnl LTALLOCA=`echo "$ALLOCA" | sed 's/\.o/.lo/g'` +dnl AC_SUBST(LTALLOCA) + +AM_GNU_GETTEXT +dnl AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl) + +AC_OUTPUT(libmisc/Makefile man/Makefile lib/Makefile src/Makefile Makefile + contrib/Makefile debian/Makefile doc/Makefile etc/Makefile + intl/Makefile intl/po2tbl.sed po/Makefile.in + etc/pam.d/Makefile old/Makefile + redhat/Makefile redhat/shadow-utils.spec, + echo timestamp > stamp-h) + diff --git a/contrib/Makefile.am b/contrib/Makefile.am new file mode 100644 index 00000000..05aabfef --- /dev/null +++ b/contrib/Makefile.am @@ -0,0 +1,5 @@ +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + +EXTRA_DIST = README adduser.c adduser-old.c adduser.sh adduser2.sh \ + atudel pwdauth.c rpasswd.c shadow-anonftp.patch udbachk.v012.tgz diff --git a/contrib/Makefile.in b/contrib/Makefile.in new file mode 100644 index 00000000..d043b882 --- /dev/null +++ b/contrib/Makefile.in @@ -0,0 +1,196 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +EXTRA_DIST = README adduser.c adduser-old.c adduser.sh adduser2.sh \ + atudel pwdauth.c rpasswd.c shadow-anonftp.patch udbachk.v012.tgz +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = README Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps contrib/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = contrib + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir info dvi installcheck install-exec install-data \ +install uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/README b/contrib/README new file mode 100644 index 00000000..c4d1bc03 --- /dev/null +++ b/contrib/README @@ -0,0 +1,10 @@ +People keep sending various adduser programs and scripts... They are +all in this directory. I haven't tested them, use at your own risk. +Anyway, the best one I've seen so far is adduser-3.x from Debian. + +atudel is a perl script to remove at jobs owned by the specified user +(atrm in at-2.9 for Linux can't do that). + +udbachk.tgz is a passwd/group/shadow file integrity checker. + +--marekm diff --git a/contrib/adduser-old.c b/contrib/adduser-old.c new file mode 100644 index 00000000..f924b36e --- /dev/null +++ b/contrib/adduser-old.c @@ -0,0 +1,300 @@ +/**** +** 03/17/96 +** hacked a bit more, removed unused code, cleaned up for gcc -Wall. +** --marekm +** +** 02/26/96 +** modified to call shadow utils (useradd,chage,passwd) on shadowed +** systems - Cristian Gafton, gafton@sorosis.ro +** +** 6/27/95 +** shadow-adduser 1.4: +** +** now it copies the /etc/skel dir into the person's dir, +** makes the mail folders, changed some defaults and made a 'make +** install' just for the hell of it. +** +** Greg Gallagher +** CIN.Net +** +** 1/28/95 +** shadow-adduser 1.3: +** +** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart +** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced. +** It was such a stupid bug that I would have never seen it myself. +** +** Brandon +***** +** 01/27/95 +** +** shadow-adduser 1.2: +** I took the C source from adduser-shadow (credits are below) and made +** it a little more worthwhile. Many small changes... Here's +** the ones I can remember: +** +** Removed support for non-shadowed systems (if you don't have shadow, +** use the original adduser, don't get this shadow version!) +** Added support for the correct /etc/shadow fields (Min days before +** password change, max days before password change, Warning days, +** and how many days from expiry date does the account go invalid) +** The previous version just left all of those fields blank. +** There is still one field left (expiry date for the account, period) +** which I have left blank because I do not use it and didn't want to +** spend any more time on this. I'm sure someone will put it in and +** tack another plethora of credits on here. :) +** Added in the password date field, which should always reflect the last +** date the password was changed, for expiry purposes. "passwd" always +** updates this field, so the adduser program should set it up right +** initially (or a user could keep thier initial password forever ;) +** The number is in days since Jan 1st, 1970. +** +** Have fun with it, and someone please make +** a real version(this is still just a hack) +** for us all to use (and Email it to me???) +** +** Brandon +** photon@usis.com +** +***** +** adduser 1.0: add a new user account (For systems not using shadow) +** With a nice little interface and a will to do all the work for you. +** +** Craig Hagan +** hagan@opine.cs.umass.edu +** +** Modified to really work, look clean, and find unused uid by Chris Cappuccio +** chris@slinky.cs.umass.edu +** +***** +** +** 01/19/95 +** +** FURTHER modifications to enable shadow passwd support (kludged, but +** no more so than the original) by Dan Crowson - dcrowson@mo.net +** +** Search on DAN for all changes... +** +***** +** +** cc -O -o adduser adduser.c +** Use gcc if you have it... (political reasons beyond my control) (chris) +** +** I've gotten this program to work with success under Linux (without +** shadow) and SunOS 4.1.3. I would assume it should work pretty well +** on any system that uses no shadow. (chris) +** +** If you have no crypt() then try +** cc -DNO_CRYPT -O -o adduser adduser.c xfdes.c +** I'm not sure how login operates with no crypt()... I guess +** the same way we're doing it here. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_SHELL "/bin/bash" /* because BASH is your friend */ +#define DEFAULT_HOME "/home" +#define USERADD_PATH "/usr/sbin/useradd" +#define CHAGE_PATH "/usr/sbin/chage" +#define PASSWD_PATH "/usr/bin/passwd" +#define DEFAULT_GROUP 100 + +#define DEFAULT_MAX_PASS 60 +#define DEFAULT_WARN_PASS 10 +/* if you use this feature, you will get a lot of complaints from users + who rarely use their accounts :) (something like 3 months would be + more reasonable) --marekm */ +#define DEFAULT_USER_DIE /* 10 */ 0 + +void main() +{ + char foo[32]; + char uname[9],person[32],dir[32],shell[32]; + unsigned int group,min_pass,max_pass,warn_pass,user_die; + /* the group and uid of the new user */ + int bad=0,done=0,correct=0,gets_warning=0; + char cmd[255]; + struct group *grp; + + /* flags, in order: + * bad to see if the username is in /etc/passwd, or if strange stuff has + * been typed if the user might be put in group 0 + * done allows the program to exit when a user has been added + * correct loops until a password is found that isn't in /etc/passwd + * gets_warning allows the fflush to be skipped for the first gets + * so that output is still legible + */ + + /* The real program starts HERE! */ + + if(geteuid()!=0) + { + printf("It seems you don't have access to add a new user. Try\n"); + printf("logging in as root or su root to gain super-user access.\n"); + exit(1); + } + + /* Sanity checks + */ + + if (!(grp=getgrgid(DEFAULT_GROUP))){ + printf("Error: the default group %d does not exist on this system!\n", + DEFAULT_GROUP); + printf("adduser must be recompiled.\n"); + exit(1); + }; + + while(!correct) { /* loop until a "good" uname is chosen */ + while(!done) { + printf("\nLogin to add (^C to quit): "); + if(gets_warning) /* if the warning was already shown */ + fflush(stdout); /* fflush stdout, otherwise set the flag */ + else + gets_warning=1; + + gets(uname); + if(!strlen(uname)) { + printf("Empty input.\n"); + done=0; + continue; + }; + + /* what I saw here before made me think maybe I was running DOS */ + /* might this be a solution? (chris) */ + if (getpwnam(uname) != NULL) { + printf("That name is in use, choose another.\n"); + done=0; + } else + done=1; + }; /* done, we have a valid new user name */ + + /* all set, get the rest of the stuff */ + printf("\nEditing information for new user [%s]\n",uname); + + printf("\nFull Name [%s]: ",uname); + gets(person); + if (!strlen(person)) { + bzero(person,sizeof(person)); + strcpy(person,uname); + }; + + do { + bad=0; + printf("GID [%d]: ",DEFAULT_GROUP); + gets(foo); + if (!strlen(foo)) + group=DEFAULT_GROUP; + else + if (isdigit (*foo)) { + group = atoi(foo); + if (! (grp = getgrgid (group))) { + printf("unknown gid %s\n",foo); + group=DEFAULT_GROUP; + bad=1; + }; + } else + if ((grp = getgrnam (foo))) + group = grp->gr_gid; + else { + printf("unknown group %s\n",foo); + group=DEFAULT_GROUP; + bad=1; + } + if (group==0){ /* You're not allowed to make root group users! */ + printf("Creation of root group users not allowed (must be done by hand)\n"); + group=DEFAULT_GROUP; + bad=1; + }; + } while(bad); + + + fflush(stdin); + + printf("\nIf home dir ends with a / then [%s] will be appended to it\n",uname); + printf("Home Directory [%s/%s]: ",DEFAULT_HOME,uname); + fflush(stdout); + gets(dir); + if (!strlen(dir)) { /* hit return */ + sprintf(dir,"%s/%s",DEFAULT_HOME,uname); + fflush(stdin); + } else + if (dir[strlen(dir)-1]=='/') + sprintf(dir,"%s%s",dir,uname); + + printf("\nShell [%s]: ",DEFAULT_SHELL); + fflush(stdout); + gets(shell); + if (!strlen(shell)) + sprintf(shell,"%s",DEFAULT_SHELL); + + printf("\nMin. Password Change Days [0]: "); + gets(foo); + min_pass=atoi(foo); + + printf("Max. Password Change Days [%d]: ",DEFAULT_MAX_PASS); + gets(foo); + if (strlen(foo) > 1) + max_pass = atoi(foo); + else + max_pass = DEFAULT_MAX_PASS; + + printf("Password Warning Days [%d]: ",DEFAULT_WARN_PASS); + gets(foo); + warn_pass = atoi(foo); + if (warn_pass==0) + warn_pass = DEFAULT_WARN_PASS; + + printf("Days after Password Expiry for Account Locking [%d]: ",DEFAULT_USER_DIE); + gets(foo); + user_die = atoi(foo); + if (user_die == 0) + user_die = DEFAULT_USER_DIE; + + printf("\nInformation for new user [%s] [%s]:\n",uname,person); + printf("Home directory: [%s] Shell: [%s]\n",dir,shell); + printf("GID: [%d]\n",group); + printf("MinPass: [%d] MaxPass: [%d] WarnPass: [%d] UserExpire: [%d]\n", + min_pass,max_pass,warn_pass,user_die); + printf("\nIs this correct? [y/N]: "); + fflush(stdout); + gets(foo); + + done=bad=correct=(foo[0]=='y'||foo[0]=='Y'); + + if(bad!=1) + printf("\nUser [%s] not added\n",uname); + } + + bzero(cmd,sizeof(cmd)); + sprintf(cmd,"%s -g %d -d %s -s %s -c \"%s\" -m -k /etc/skel %s", + USERADD_PATH,group,dir,shell,person,uname); + printf("Calling useradd to add new user:\n%s\n",cmd); + if(system(cmd)){ + printf("User add failed!\n"); + exit(errno); + }; + bzero(cmd,sizeof(cmd)); + sprintf(cmd,"%s -m %d -M %d -W %d -I %d %s", CHAGE_PATH, + min_pass,max_pass,warn_pass,user_die,uname); + printf("%s\n",cmd); + if(system(cmd)){ + printf("There was an error setting password expire values\n"); + exit(errno); + }; + bzero(cmd,sizeof(cmd)); + sprintf(cmd,"%s %s",PASSWD_PATH,uname); + system(cmd); + printf("\nDone.\n"); +} + diff --git a/contrib/adduser.c b/contrib/adduser.c new file mode 100644 index 00000000..f303a41d --- /dev/null +++ b/contrib/adduser.c @@ -0,0 +1,502 @@ +/**** +** 04/21/96 +** hacked even more, replaced gets() with something slightly harder to buffer +** overflow. Added support for setting a default quota on new account, with +** edquota -p. Other cleanups for security, I let some users run adduser suid +** root to add new accounts. (overflow checks, clobber environment, valid +** shell checks, restrictions on gid + home dir settings). + +** Added max. username length. Used syslog() a bit for important events. +** Support to immediately expire account with passwd -e. + +** Called it version 2.0! Because I felt like it! + +** -- Chris, chris@ferret.lmh.ox.ac.uk + +** 03/17/96 +** hacked a bit more, removed unused code, cleaned up for gcc -Wall. +** --marekm +** +** 02/26/96 +** modified to call shadow utils (useradd,chage,passwd) on shadowed +** systems - Cristian Gafton, gafton@sorosis.ro +** +** 6/27/95 +** shadow-adduser 1.4: +** +** now it copies the /etc/skel dir into the person's dir, +** makes the mail folders, changed some defaults and made a 'make +** install' just for the hell of it. +** +** Greg Gallagher +** CIN.Net +** +** 1/28/95 +** shadow-adduser 1.3: +** +** Basically a bug-fix on my additions in 1.2. Thanx to Terry Stewart +** (stew@texas.net) for pointing out one of the many idiotic bugs I introduced. +** It was such a stupid bug that I would have never seen it myself. +** +** Brandon +***** +** 01/27/95 +** +** shadow-adduser 1.2: +** I took the C source from adduser-shadow (credits are below) and made +** it a little more worthwhile. Many small changes... Here's +** the ones I can remember: +** +** Removed support for non-shadowed systems (if you don't have shadow, +** use the original adduser, don't get this shadow version!) +** Added support for the correct /etc/shadow fields (Min days before +** password change, max days before password change, Warning days, +** and how many days from expiry date does the account go invalid) +** The previous version just left all of those fields blank. +** There is still one field left (expiry date for the account, period) +** which I have left blank because I do not use it and didn't want to +** spend any more time on this. I'm sure someone will put it in and +** tack another plethora of credits on here. :) +** Added in the password date field, which should always reflect the last +** date the password was changed, for expiry purposes. "passwd" always +** updates this field, so the adduser program should set it up right +** initially (or a user could keep thier initial password forever ;) +** The number is in days since Jan 1st, 1970. +** +** Have fun with it, and someone please make +** a real version(this is still just a hack) +** for us all to use (and Email it to me???) +** +** Brandon +** photon@usis.com +** +***** +** adduser 1.0: add a new user account (For systems not using shadow) +** With a nice little interface and a will to do all the work for you. +** +** Craig Hagan +** hagan@opine.cs.umass.edu +** +** Modified to really work, look clean, and find unused uid by Chris Cappuccio +** chris@slinky.cs.umass.edu +** +***** +** +** 01/19/95 +** +** FURTHER modifications to enable shadow passwd support (kludged, but +** no more so than the original) by Dan Crowson - dcrowson@mo.net +** +** Search on DAN for all changes... +** +***** +** +** cc -O -o adduser adduser.c +** Use gcc if you have it... (political reasons beyond my control) (chris) +** +** I've gotten this program to work with success under Linux (without +** shadow) and SunOS 4.1.3. I would assume it should work pretty well +** on any system that uses no shadow. (chris) +** +** If you have no crypt() then try +** cc -DNO_CRYPT -O -o adduser adduser.c xfdes.c +** I'm not sure how login operates with no crypt()... I guess +** the same way we're doing it here. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMMEDIATE_CHANGE /* Expire newly created password, must be changed + * immediately upon next login */ +#define HAVE_QUOTAS /* Obvious */ +#define EXPIRE_VALS_SET /* If defined, 'normal' users can't change + * password expiry values (if running suid root) */ + +#define HAVE_GETUSERSHELL /* FIXME: Isn't this defined in config.h too? */ +#define LOGGING /* If we want to log various things to syslog */ +#define MAX_USRNAME 8 /* Longer usernames seem to work on my system.... + * But they're probably a poor idea */ + + +#define DEFAULT_SHELL "/bin/bash" /* because BASH is your friend */ +#define DEFAULT_HOME "/home" +#define USERADD_PATH "/usr/sbin/useradd" +#define CHAGE_PATH "/usr/bin/chage" +#define PASSWD_PATH "/usr/bin/passwd" +#define EDQUOTA_PATH "/usr/sbin/edquota" +#define QUOTA_DEFAULT "defuser" +#define DEFAULT_GROUP 100 + +#define DEFAULT_MIN_PASS 0 +#define DEFAULT_MAX_PASS 100 +#define DEFAULT_WARN_PASS 14 +#define DEFAULT_USER_DIE 366 + +void safeget (char *, int); + +void +main (void) +{ + char foo[32]; + char usrname[32], person[32], dir[32], shell[32]; + unsigned int group, min_pass, max_pass, warn_pass, user_die; + /* the group and uid of the new user */ + int bad = 0, done = 0, correct = 0, olduid; + char cmd[255]; + struct group *grp; + + /* flags, in order: + * bad to see if the username is in /etc/passwd, or if strange stuff has + * been typed if the user might be put in group 0 + * done allows the program to exit when a user has been added + * correct loops until a username is found that isn't in /etc/passwd + */ + + /* The real program starts HERE! */ + + if (geteuid () != 0) + { + printf ("It seems you don't have access to add a new user. Try\n"); + printf ("logging in as root or su root to gain super-user access.\n"); + exit (1); + } + + /* Sanity checks + */ + +#ifdef LOGGING + openlog ("adduser", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH); + syslog (LOG_INFO, "invoked by user %s\n", getpwuid (getuid ())->pw_name); +#endif + + if (!(grp = getgrgid (DEFAULT_GROUP))) + { + printf ("Error: the default group %d does not exist on this system!\n", + DEFAULT_GROUP); + printf ("adduser must be recompiled.\n"); +#ifdef LOGGING + syslog (LOG_ERR, "warning: failed. no such default group\n"); + closelog (); +#endif + exit (1); + }; + + while (!correct) + { /* loop until a "good" usrname is chosen */ + while (!done) + { + printf ("\nLogin to add (^C to quit): "); + fflush (stdout); + + safeget (usrname, sizeof (usrname)); + + if (!strlen (usrname)) + { + printf ("Empty input.\n"); + done = 0; + continue; + }; + + /* what I saw here before made me think maybe I was running DOS */ + /* might this be a solution? (chris) */ + if (strlen (usrname) > MAX_USRNAME) + { + printf ("That name is longer than the maximum of %d characters. Choose another.\n", MAX_USRNAME); + done = 0; + } + else if (getpwnam (usrname) != NULL) + { + printf ("That name is in use, choose another.\n"); + done = 0; + } + else if (strchr (usrname, ' ') != NULL) + { + printf ("No spaces in username!!\n"); + done = 0; + } + else + done = 1; + }; /* done, we have a valid new user name */ + + /* all set, get the rest of the stuff */ + printf ("\nEditing information for new user [%s]\n", usrname); + + printf ("\nFull Name [%s]: ", usrname); + fflush (stdout); + safeget (person, sizeof (person)); + if (!strlen (person)) + { + bzero (person, sizeof (person)); + strcpy (person, usrname); + }; + + if (getuid () == 0) + { + do + { + bad = 0; + printf ("GID [%d]: ", DEFAULT_GROUP); + fflush (stdout); + safeget (foo, sizeof (foo)); + if (!strlen (foo)) + group = DEFAULT_GROUP; + else if (isdigit (*foo)) + { + group = atoi (foo); + if (!(grp = getgrgid (group))) + { + printf ("unknown gid %s\n", foo); + group = DEFAULT_GROUP; + bad = 1; + }; + } + else if ((grp = getgrnam (foo))) + group = grp->gr_gid; + else + { + printf ("unknown group %s\n", foo); + group = DEFAULT_GROUP; + bad = 1; + } + if (group == 0) + { /* You're not allowed to make root group users! */ + printf ("Creation of root group users not allowed (must be done by hand)\n"); + group = DEFAULT_GROUP; + bad = 1; + }; + } + while (bad); + } + else + { + printf ("Group will be default of: %d\n", DEFAULT_GROUP); + group = DEFAULT_GROUP; + } + + if (getuid () == 0) + { + printf ("\nIf home dir ends with a / then '%s' will be appended to it\n", usrname); + printf ("Home Directory [%s/%s]: ", DEFAULT_HOME, usrname); + fflush (stdout); + safeget (dir, sizeof (dir)); + if (!strlen (dir)) + { /* hit return */ + sprintf (dir, "%s/%s", DEFAULT_HOME, usrname); + } + else if (dir[strlen (dir) - 1] == '/') + sprintf (dir, "%s%s", dir, usrname); + } + else + { + printf ("\nHome directory will be %s/%s\n", DEFAULT_HOME, usrname); + sprintf (dir, "%s/%s", DEFAULT_HOME, usrname); + } + + printf ("\nShell [%s]: ", DEFAULT_SHELL); + fflush (stdout); + safeget (shell, sizeof (shell)); + if (!strlen (shell)) + sprintf (shell, "%s", DEFAULT_SHELL); + else + { + char *sh; + int ok = 0; +#ifdef HAVE_GETUSERSHELL + setusershell (); + while ((sh = getusershell ()) != NULL) + if (!strcmp (shell, sh)) + ok = 1; + endusershell (); +#endif + if (!ok) + { + if (getuid () == 0) + printf ("Warning: root allowed non standard shell\n"); + else + { + printf ("Shell NOT in /etc/shells, DEFAULT used\n"); + sprintf (shell, "%s", DEFAULT_SHELL); + } + } + } + +#ifdef EXPIRE_VALS_SET + if (getuid () == 0) + { +#endif + printf ("\nMin. Password Change Days [%d]: ", DEFAULT_MIN_PASS); + fflush (stdout); + safeget (foo, sizeof (foo)); + if (strlen (foo) > 1) + min_pass = DEFAULT_MIN_PASS; + else + min_pass = atoi (foo); + + printf ("Max. Password Change Days [%d]: ", DEFAULT_MAX_PASS); + fflush (stdout); + safeget (foo, sizeof (foo)); + if (strlen (foo) > 1) + max_pass = atoi (foo); + else + max_pass = DEFAULT_MAX_PASS; + + printf ("Password Warning Days [%d]: ", DEFAULT_WARN_PASS); + fflush (stdout); + safeget (foo, sizeof (foo)); + warn_pass = atoi (foo); + if (warn_pass == 0) + + warn_pass = DEFAULT_WARN_PASS; + + printf ("Days after Password Expiry for Account Locking [%d]: ", DEFAULT_USER_DIE); + fflush (stdout); + safeget (foo, sizeof (foo)); + user_die = atoi (foo); + if (user_die == 0) + user_die = DEFAULT_USER_DIE; + +#ifdef EXPIRE_VALS_SET + } + else + { + printf ("\nSorry, account expiry values are set.\n"); + user_die = DEFAULT_USER_DIE; + warn_pass = DEFAULT_WARN_PASS; + max_pass = DEFAULT_MAX_PASS; + min_pass = DEFAULT_MIN_PASS; + } +#endif + + printf ("\nInformation for new user [%s] [%s]:\n", usrname, person); + printf ("Home directory: [%s] Shell: [%s]\n", dir, shell); + printf ("GID: [%d]\n", group); + printf ("MinPass: [%d] MaxPass: [%d] WarnPass: [%d] UserExpire: [%d]\n", + min_pass, max_pass, warn_pass, user_die); + printf ("\nIs this correct? [y/N]: "); + fflush (stdout); + safeget (foo, sizeof (foo)); + + done = bad = correct = (foo[0] == 'y' || foo[0] == 'Y'); + + if (bad != 1) + printf ("\nUser [%s] not added\n", usrname); + } + + /* Clobber the environment, I run this suid root sometimes to let + * non root privileged accounts add users --chris */ + + *environ = NULL; + + bzero (cmd, sizeof (cmd)); + sprintf (cmd, "%s -g %d -d %s -s %s -c \"%s\" -m -k /etc/skel %s", + USERADD_PATH, group, dir, shell, person, usrname); + printf ("Calling useradd to add new user:\n%s\n", cmd); + if (system (cmd)) + { + printf ("User add failed!\n"); +#ifdef LOGGING + syslog (LOG_ERR, "could not add new user\n"); + closelog (); +#endif + exit (errno); + }; + + olduid = getuid (); /* chage, passwd, edquota etc. require ruid = root + */ + setuid (0); + + bzero (cmd, sizeof (cmd)); + + /* Chage runs suid root. => we need ruid root to run it with + * anything other than chage -l + */ + + sprintf (cmd, "%s -m %d -M %d -W %d -I %d %s", CHAGE_PATH, + min_pass, max_pass, warn_pass, user_die, usrname); + printf ("%s\n", cmd); + if (system (cmd)) + { + printf ("There was an error setting password expire values\n"); +#ifdef LOGGING + syslog (LOG_ERR, "password expire values could not be set\n"); +#endif + }; + + /* I want to add a user completely with one easy command --chris */ + +#ifdef HAVE_QUOTAS + bzero (cmd, sizeof (cmd)); + sprintf (cmd, "%s -p %s -u %s", EDQUOTA_PATH, QUOTA_DEFAULT, usrname); + printf ("%s\n", cmd); + if (system (cmd)) + { + printf ("\nWarning: error setting quota\n"); +#ifdef LOGGING + syslog (LOG_ERR, "warning: account created but NO quotas set!\n"); +#endif /* LOGGING */ + } + else + printf ("\nDefault quota set.\n"); +#endif /* HAVE_QUOTAS */ + + bzero (cmd, sizeof (cmd)); + sprintf (cmd, "%s %s", PASSWD_PATH, usrname); + if (system (cmd)) + { + printf ("\nWarning: error setting password\n"); +#ifdef LOGGING + syslog (LOG_ERR, "warning: password set failed!\n"); +#endif + } +#ifdef IMMEDIATE_CHANGE + bzero (cmd, sizeof (cmd)); + sprintf (cmd, "%s -e %s", PASSWD_PATH, usrname); + if (system (cmd)) + { + printf ("\nWarning: error expiring password\n"); +#ifdef LOGGING + syslog (LOG_ERR, "warning: password expire failed!\n"); +#endif /* LOGGING */ + } +#endif /* IMMEDIATE_CHANGE */ + + setuid (olduid); + +#ifdef LOGGING + closelog (); +#endif + + printf ("\nDone.\n"); +} + +void +safeget (char *buf, int maxlen) +{ + int c, i = 0, bad = 0; + char *bstart = buf; + while ((c = getc (stdin)) != EOF && (c != '\n') && (++i < maxlen)) + { + bad = (!isalnum (c) && (c != '_') && (c != ' ')); + *(buf++) = (char) c; + } + *buf = '\0'; + + if (bad) + { + printf ("\nString contained banned character. Please stick to alphanumerics.\n"); + *bstart = '\0'; + } +} + diff --git a/contrib/adduser.sh b/contrib/adduser.sh new file mode 100755 index 00000000..0efb27a3 --- /dev/null +++ b/contrib/adduser.sh @@ -0,0 +1,90 @@ +#!/bin/sh +# adduser script for use with shadow passwords and useradd command. +# by Hrvoje Dogan , Dec 1995. + +echo -n "Login name for new user []:" +read LOGIN +if [ -z $LOGIN ] +then echo "Come on, man, you can't leave the login field empty...";exit +fi +echo +echo -n "User id for $LOGIN [ defaults to next available]:" +read ID +GUID="-u $ID" +if [ -z $ID ] +then GUID="" +fi + +echo +echo -n "Initial group for $LOGIN [users]:" +read GID +GGID="-g $GID" +if [ -z $GID ] +then GGID="" +fi + +echo +echo -n "Additional groups for $LOGIN []:" +read AGID +GAGID="-G $AGID" +if [ -z $AGID ] +then GAGID="" +fi + +echo +echo -n "$LOGIN's home directory [/home/$LOGIN]:" +read HME +GHME="-d $HME" +if [ -z $HME ] +then GHME="" +fi + +echo +echo -n "$LOGIN's shell [/bin/bash]:" +read SHL +GSHL="-s $SHL" +if [ -z $SHL ] +then GSHL="" +fi + +echo +echo -n "$LOGIN's account expiry date (MM/DD/YY) []:" +read EXP +GEXP="-e $EXP" +if [ -z $EXP ] +then GEXP="" +fi +echo +echo OK, I'm about to make a new account. Here's what you entered so far: +echo New login name: $LOGIN +if [ -z $GUID ] +then echo New UID: [Next available] +else echo New UID: $UID +fi +if [ -z $GGID ] +then echo Initial group: users +else echo Initial group: $GID +fi +if [ -z $GAGID ] +then echo Additional groups: [none] +else echo Additional groups: $AGID +fi +if [ -z $GHME ] +then echo Home directory: /home/$LOGIN +else echo Home directory: $HME +fi +if [ -z $GSHL ] +then echo Shell: /bin/bash +else echo Shell: $SHL +fi +if [ -z $GEXP ] +then echo Expiry date: [no expiration] +else echo Expiry date: $EXP +fi +echo "This is it... if you want to bail out, you'd better do it now." +read FOO +echo Making new account... +/usr/sbin/useradd $GHME -m $GEXP $GGID $GAGID $GSHL $GUID $LOGIN +/usr/bin/chfn $LOGIN +/usr/bin/passwd $LOGIN +echo "Done..." diff --git a/contrib/adduser2.sh b/contrib/adduser2.sh new file mode 100755 index 00000000..a2b36b25 --- /dev/null +++ b/contrib/adduser2.sh @@ -0,0 +1,743 @@ +#!/bin/bash +# +# adduser Interactive user adding program. +# +# Copyright (C) 1996 Petri Mattila, Prihateam Networks +# petri@prihateam.fi +# +# 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, or (at your option) +# any later version. +# +# Changes: +# 220496 v0.01 Initial version +# 230496 v0.02 More checks, embolden summary +# 240496 Even more checks +# 250496 Help with ? +# 040596 v0.03 Cleanups +# 050596 v0.04 Bug fixes, expire date checks +# 070596 v0.05 Iso-latin-1 names +# + +## Defaults + +# default groups +def_group="users" +def_other_groups="" + +# default home directory +def_home_dir=/home/users + +# default shell +def_shell=/bin/tcsh + +# Defaul expiration date (mm/dd/yy) +def_expire="" + +# default dates +def_pwd_min=0 +def_pwd_max=90 +def_pwd_warn=14 +def_pwd_iact=14 + + +# possible UIDs +uid_low=1000 +uid_high=64000 + +# skel directory +skel=/etc/skel + +# default mode for home directory +def_mode=711 + +# Regex, that the login name must meet, only ANSI characters +login_regex='^[0-9a-zA-Z_-]*$' + +# Regex, that the user name must meet +# ANSI version +##name_regex='^[0-9a-zA-Z_-\ ]*$' +# ISO-LATIN-1 version +name_regex='^[0-9a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöùúûüýþÿ_-\ ]*$' + +# set PATH +export PATH="/bin:/sbin:/usr/bin:/usr/sbin" + +# Some special characters +case "$TERM" in + vt*|ansi*|con*|xterm*|linux*) + S='' # start embolden + E='' # end embolden + ;; + *) + S='' + E='' + ;; +esac + + +## Functions + +check_root() { + if test "$EUID" -ne 0 + then + echo "You must be root to run this program." + exit 1 + fi +} + +check_user() { + local usr pwd uid gid name home sh + + cat /etc/passwd | ( + while IFS=":" read usr pwd uid gid name home sh + do + if test "$1" = "${usr}" + then + return 1 + fi + done + return 0 + ) +} + +check_group() { + local read grp pwd gid members + + cat /etc/group | ( + while IFS=":" read grp pwd gid members + do + if test "$1" = "${grp}" + then + return 1 + fi + done + return 0 + ) +} + +check_other_groups() { + local grp check IFS + + check="$1" + IFS="," + + set ${check} + for grp + do + if check_group "${grp}" + then + echo "Group ${grp} does not exist." + return 1 + fi + done + return 0 +} + +check_uid() { + local usr pwd uid gid name home sh + + cat /etc/passwd | ( + while IFS=":" read usr pwd uid gid name home sh + do + if test "$1" = "${uid}" + then + return 1 + fi + done + return 0 + ) +} + +read_yn() { + local ans ynd + + ynd="$1" + + while : + do + read ans + case "${ans}" in + "") return ${ynd} ;; + [nN]) return 1 ;; + [yY]) return 0 ;; + *) echo -n "Y or N, please ? " ;; + esac + done +} + +read_login() { + echo + while : + do + echo -n "Login: ${def_login:+[${def_login}] }" + read login + + if test "${login}" = '?' + then + less /etc/passwd + echo + continue + fi + + if test -z "${login}" -a -n "${def_login}" + then + login="${def_login}" + echo "Using ${login}" + return + fi + + if test "${#login}" -gt 8 + then + echo "Login must be at most 8 characters long" + continue + fi + + if test "${#login}" -lt 2 + then + echo "Login must be at least 2 characters long" + continue + fi + + if ! expr "${login}" : "${login_regex}" &> /dev/null + then + echo "Please use letters, numbers and special characters _-,." + continue + fi + + if ! check_user "${login}" + then + echo "Username ${login} is already in use" + continue + fi + + def_login="${login}" + return + done +} + +read_name () { + echo + while : + do + echo -n "Real name: ${def_name:+[${def_name}] }" + read name + + if test "${name}" = '?' + then + less /etc/passwd + echo + continue + fi + + if test -z "${name}" -a -n "${def_name}" + then + name="${def_name}" + echo "Using ${name}" + fi + + if test "${#name}" -gt 32 + then + echo "Name should be at most 32 characters long" + continue + fi + + if ! expr "${name}" : "${name_regex}" &> /dev/null + then + echo "Please use letters, numbers, spaces and special characters ,._-" + continue + fi + + def_name="${name}" + return + done +} + +read_home() { + local x + + echo + while : + do + echo -n "Home Directory: [${def_home_dir}/${login}] " + read home + + if test -z "${home}" + then + home="${def_home_dir}/${login}" + echo "Using ${home}" + fi + + if ! expr "${home}" : '^[0-9a-zA-Z,._-\/]*$' &> /dev/null + then + echo "Please use letters, numbers, spaces and special characters ,._-/" + continue + fi + + x="$(basename ${home})" + if test "${x}" != "${login}" + then + echo "Warning: you are about to use different login name and home directory." + fi + + x="$(dirname ${home})" + if ! test -d "${x}" + then + echo "Directory ${x} does not exist." + echo "If you still want to use it, please make it manually." + continue + fi + + def_home_dir="${x}" + return + done +} + +read_shell () { + local x + + echo + while : + do + echo -n "Shell: [${def_shell}] " + read shell + + if test -z "${shell}" + then + shell="${def_shell}" + echo "Using ${shell}" + fi + + for x in $(cat /etc/shells) + do + if test "${x}" = "${shell}" + then + def_shell="${shell}" + return + fi + done + + echo "Possible shells are:" + cat /etc/shells + done +} + +read_group () { + echo + while : + do + echo -n "Group: [${def_group}] " + read group + + if test -z "${group}" + then + group="${def_group}" + echo "Using ${group}" + fi + + if test "${group}" = '?' + then + less /etc/group + echo + continue + fi + + if check_group "${group}" + then + echo "Group ${group} does not exist." + continue + fi + + def_group="${group}" + return + done +} + +read_other_groups () { + echo + while : + do + echo -n "Other groups: [${def_og:-none}] " + read other_groups + + if test "${other_groups}" = '?' + then + less /etc/group + echo + continue + fi + + if test -z "${other_groups}" + then + if test -n "${def_og}" + then + other_groups="${def_og}" + echo "Using ${other_groups}" + else + echo "No other groups" + return + fi + fi + + + if ! check_other_groups "${other_groups}" + then + continue + fi + + def_og="${other_groups}" + return + done +} + +read_uid () { + echo + while : + do + echo -n "uid: [first free] " + read uid + + if test -z "${uid}" + then + echo "Using first free UID." + return + fi + + if test "${uid}" = '?' + then + less /etc/passwd + echo + continue + fi + + if ! expr "${uid}" : '^[0-9]+$' &> /dev/null + then + echo "Please use numbers only." + continue + fi + if test "${uid}" -lt "${uid_low}" + then + echo "UID must be greater than ${uid_low}" + continue + fi + if test "${uid}" -gt "${uid_high}" + then + echo "UID must be smaller than ${uid_high}" + continue + fi + if ! check_uid "${uid}" + then + echo "UID ${uid} is already in use" + continue + fi + + return + done +} + +read_max_valid_days() { + echo + while : + do + echo -en "Maximum days between password changes: [${def_pwd_max}] " + read max_days + + if test -z "${max_days}" + then + max_days="${def_pwd_max}" + echo "Using ${max_days}" + return + fi + + if ! expr "${max_days}" : '^[0-9]+$' &> /dev/null + then + echo "Please use numbers only." + continue + fi + if test "${max_days}" -lt 7 + then + echo "Warning: you are using a value shorter than a week." + fi + + def_pwd_max="${max_days}" + return + done +} + +read_min_valid_days() { + echo + while : + do + echo -en "Minimum days between password changes: [${def_pwd_min}] " + read min_days + + if test -z "${min_days}" + then + min_days="${def_pwd_min}" + echo "Using ${min_days}" + return + fi + + if ! expr "${min_days}" : '^[0-9]+$' &> /dev/null + then + echo "Please use numbers only." + continue + fi + if test "${min_days}" -gt 7 + then + echo "Warning: you are using a value longer than a week." + fi + + def_pwd_min="${min_days}" + return + done +} + +read_warning_days() { + echo + while : + do + echo -en "Number of warning days before password expires: [${def_pwd_warn}] " + read warn_days + + if test -z "${warn_days}" + then + warn_days="${def_pwd_warn}" + echo "Using ${warn_days}" + fi + + if ! expr "${warn_days}" : '^[0-9]+$' &> /dev/null + then + echo "Please use numbers only." + continue + fi + if test "${warn_days}" -gt 14 + then + echo "Warning: you are using a value longer than two week." + fi + + def_pwd_warn="${warn_days}" + return + done +} + + +read_inactive_days() { + echo + while : + do + echo -en "Number of usable days after expiration: [${def_pwd_iact}] " + read iact_days + + if test -z "${iact_days}" + then + iact_days="${def_pwd_iact}" + echo "Using ${iact_days}" + return + fi + if ! expr "${iact_days}" : '^[0-9]+$' &> /dev/null + then + echo "Please use numbers only." + continue + fi + if test "${iact_days}" -gt 14 + then + echo "Warning: you are using a value that is more than two weeks." + fi + + def_pwd_iact="${iact_days}" + return + done +} + +read_expire_date() { + local ans + + echo + while : + do + echo -en "Expire date of this account (mm/dd/yy): [${def_expire:-never}] " + read ans + + if test -z "${ans}" + then + if test -z "${def_expire}" + then + ans="never" + else + ans="${def_expire}" + echo "Using ${def_expire}" + fi + fi + + if test "${ans}" = "never" + then + echo "Account will never expire." + def_expire="" + expire="" + return + fi + + if ! expr "${ans}" : '^[0-9][0-9]/[0-9][0-9]/[0-9][0-9]$' &> /dev/null + then + echo "Please use format mm/dd/yy" + continue + fi + + if ! expire_date="$(date -d ${ans} '+%A, %B %d %Y')" + then + continue + fi + + def_expire="${expire}" + return + done +} + +read_passwd_yn() { + echo -en "\nDo you want to set password [Y/n] ? " + if read_yn 0 + then + set_pwd="YES" + else + set_pwd="" + fi +} + + +print_values() { + +clear +cat << EOM + +Login: ${S}${login}${E} +Group: ${S}${group}${E} +Other groups: ${S}${other_groups:-[none]}${E} + +Real Name: ${S}${name}${E} + +uid: ${S}${uid:-[first free]}${E} +home: ${S}${home}${E} +shell: ${S}${shell}${E} + +Account expiration date: ${S}${expire_date:-never}${E} +Minimum days between password changes: ${S}${min_days}${E} +Maximum days between password changes: ${S}${max_days}${E} +Number of usable days after expiration: ${S}${iact_days}${E} +Number of warning days before expiration: ${S}${warn_days}${E} + +${S}${set_pwd:+Set password for this account.}${E} + +EOM +} + +set_user() { + if ! useradd \ + -c "${name}" \ + -d "${home}" \ + -g "${group}" \ + -s "${shell}" \ + ${expire:+-e ${expire}} \ + ${uid:+-u ${uid}} \ + ${other_groups:+-G ${other_groups}} \ + ${login} + then + echo "Error ($?) in useradd...exiting..." + exit 1 + fi +} + +set_aging() { + if ! passwd \ + -x ${max_days} \ + -n ${min_days} \ + -w ${warn_days} \ + -i ${iact_days} \ + ${login} + then + echo "Error ($?) in setting password aging...exiting..." + exit 1 + fi +} + +set_password() { + if test -n "${set_pwd}" + then + echo + passwd ${login} + echo + fi +} + +set_system() { + if test -d "${home}" + then + echo "Directory ${home} already exists." + echo "Skeleton files not copied." + return + fi + + echo -n "Copying skeleton files..." + ( + mkdir ${home} + cd ${skel} && cp -af . ${home} + chmod ${def_mode} ${home} + chown -R ${login}:${group} ${home} + ) + echo "done." + + ## Add your own stuff here: + echo -n "Setting up other files..." + ( + mailbox="/var/spool/mail/${login}" + touch ${mailbox} + chown "${login}:mail" ${mailbox} + chmod 600 ${mailbox} + ) + echo "done." +} + + +read_values() { + clear + echo -e "\nPlease answer the following questions about the new user to be added." + + while : + do + read_login + read_name + read_group + read_other_groups + read_home + read_shell + read_uid + read_expire_date + read_max_valid_days + read_min_valid_days + read_warning_days + read_inactive_days + read_passwd_yn + + print_values + + echo -n "Is this correct [N/y] ? " + read_yn 1 && return + done +} + + +main() { + check_root + read_values + set_user + set_aging + set_system + set_password +} + + +## Run it 8-) +main + +# End. diff --git a/contrib/atudel b/contrib/atudel new file mode 100755 index 00000000..0ca87833 --- /dev/null +++ b/contrib/atudel @@ -0,0 +1,85 @@ +#!/usr/bin/perl +# +# Copyright (c) 1996 Brian R. Gaeke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Brian R. Gaeke. +# 4. The name of the author, Brian R. Gaeke, may not be used to endorse +# or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY BRIAN R. GAEKE ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL BRIAN R. GAEKE BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# Additionally: +# +# This software is provided without support and without any obligation +# on the part of Brian R. Gaeke to assist in its use, correction, +# modification or enhancement. +# +####################################################################### +# +# this is atudel, version 2, by Brian R. Gaeke +# + +require "getopts.pl"; +&Getopts('v'); +$username = shift(@ARGV); +&usage unless $username; + +sub usage +{ + print STDERR "atudel - remove all at jobs owned by a user\n"; + print STDERR "usage: $0 [-v] username\n"; + exit(1); +} + +# odd. unless getpwnam($uname) doesn't seem to work for $uname eq "root" on +# my linux system. but this does. +die "user $username does not exist; stopping" + unless defined(getpwnam($username)); + +print "searching for at jobs owned by user $username ..." if $opt_v; + +chdir "/var/spool/atjobs" || + die "can't chdir to /var/spool/atjobs: $!\nstopping"; +opendir(DIR,".") || die "can't opendir(/var/spool/atjobs): $!\nstopping"; +@files = grep(!/^\./,grep(-f,readdir(DIR))); +closedir DIR; + +foreach $x (@files) +{ + $owner = (getpwuid((stat($x))[4]))[0]; + push(@nuke_bait,$x) if $owner eq $username; +} + +if (@nuke_bait) +{ + print "removed jobIDs: @{nuke_bait}.\n" if $opt_v; + unlink @nuke_bait; +} +elsif ($opt_v) +{ + print "\n"; +} + +exit 0; diff --git a/contrib/pwdauth.c b/contrib/pwdauth.c new file mode 100644 index 00000000..1bedf6bb --- /dev/null +++ b/contrib/pwdauth.c @@ -0,0 +1,308 @@ +/* + * pwdauth.c - program to verify a given username/password pair. + * + * Run it with username in argv[1] (may be omitted - default is the + * current user), and send it the password over a pipe on stdin. + * Exit status: 0 - correct password, 1 - wrong password, >1 - other + * errors. For use with shadow passwords, this program should be + * installed setuid root. + * + * This can be used, for example, by xlock - you don't have to install + * this large and complex (== possibly insecure) program setuid root, + * just modify it to run this simple program to do the authentication. + * + * Recent versions (xlockmore-3.9) are cleaner, and drop privileges as + * soon as possible after getting the user's encrypted password. + * Using this program probably doesn't make it more secure, and has one + * disadvantage: since we don't get the encrypted user's password at + * startup (but at the time the user is authenticated), it is not clear + * how we should handle errors (like getpwnam() returning NULL). + * - fail the authentication? Problem: no way to unlock (other than kill + * the process from somewhere else) if the NIS server stops responding. + * - succeed and unlock? Problem: it's too easy to unlock by unplugging + * the box from the network and waiting until NIS times out... + * + * This program is Copyright (C) 1996 Marek Michalkiewicz + * . + * + * It may be used and distributed freely for any purposes. There is no + * warranty - use at your own risk. I am not liable for any damages etc. + * If you improve it, please send me your changes. + */ + +static char rcsid[] = "$Id: pwdauth.c,v 1.2 1997/12/07 23:26:45 marekm Exp $"; + +/* + * Define USE_SYSLOG to use syslog() to log successful and failed + * authentication. This should be safe even if your system has + * the infamous syslog buffer overrun security problem... + */ +#define USE_SYSLOG + +/* + * Define HAVE_GETSPNAM to get shadow passwords using getspnam(). + * Some systems don't have getspnam(), but getpwnam() returns + * encrypted passwords only if running as root. + * + * According to the xlock source (not tested, except Linux) - + * define: Linux, Solaris 2.x, SVR4, ... + * undef: HP-UX with Secured Passwords, FreeBSD, NetBSD, QNX. + * Known not supported (yet): Ultrix, OSF/1, SCO. + */ +#define HAVE_GETSPNAM + +/* + * Define HAVE_PW_ENCRYPT to use pw_encrypt() instead of crypt(). + * pw_encrypt() is like the standard crypt(), except that it may + * support better password hashing algorithms. + * + * Define if linking with libshadow.a from the shadow password + * suite (Linux, SunOS 4.x?). + */ +#undef HAVE_PW_ENCRYPT + +/* + * Define HAVE_AUTH_METHODS to support the shadow suite specific + * extension: the encrypted password field contains a list of + * administrator defined authentication methods, separated by + * semicolons. This program only supports the standard password + * authentication method (a string that doesn't start with '@'). + */ +#undef HAVE_AUTH_METHODS + +/* + * FAIL_DELAY - number of seconds to sleep before exiting if the + * password was wrong, to slow down password guessing attempts. + */ +#define FAIL_DELAY 2 + +/* No user-serviceable parts below :-). */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_SYSLOG +#include +#ifndef LOG_AUTHPRIV +#define LOG_AUTHPRIV LOG_AUTH +#endif +#endif + +#ifdef HAVE_GETSPNAM +#include +#endif + +#ifdef HAVE_PW_ENCRYPT +extern char *pw_encrypt(); +#define crypt pw_encrypt +#endif + +/* + * Read the password (one line) from fp. We don't turn off echo + * because we expect input from a pipe. + */ +static char * +get_line(fp) + FILE *fp; +{ + static char buf[128]; + char *cp; + int ch; + + cp = buf; + while ((ch = getc(fp)) != EOF && ch != '\0' && ch != '\n') { + if (cp >= buf + sizeof buf - 1) + break; + *cp++ = ch; + } + *cp = '\0'; + return buf; +} + +/* + * Get the password file entry for the current user. If the name + * returned by getlogin() is correct (matches the current real uid), + * return the entry for that user. Otherwise, return the entry (if + * any) matching the current real uid. Return NULL on failure. + */ +static struct passwd * +get_my_pwent() +{ + uid_t uid = getuid(); + char *name = getlogin(); + + if (name && *name) { + struct passwd *pw = getpwnam(name); + + if (pw && pw->pw_uid == uid) + return pw; + } + return getpwuid(uid); +} + +/* + * Verify the password. The system-dependent shadow support is here. + */ +static int +password_auth_ok(pw, pass) + const struct passwd *pw; + const char *pass; +{ + int result; + char *cp; +#ifdef HAVE_AUTH_METHODS + char *buf; +#endif +#ifdef HAVE_GETSPNAM + struct spwd *sp; +#endif + + if (pw) { +#ifdef HAVE_GETSPNAM + sp = getspnam(pw->pw_name); + if (sp) + cp = sp->sp_pwdp; + else +#endif + cp = pw->pw_passwd; + } else + cp = "xx"; + +#ifdef HAVE_AUTH_METHODS + buf = strdup(cp); /* will be modified by strtok() */ + if (!buf) { + fprintf(stderr, "Out of memory.\n"); + exit(13); + } + cp = strtok(buf, ";"); + while (cp && *cp == '@') + cp = strtok(NULL, ";"); + + /* fail if no password authentication for this user */ + if (!cp) + cp = "xx"; +#endif + + if (*pass || *cp) + result = (strcmp(crypt(pass, cp), cp) == 0); + else + result = 1; /* user with no password */ + +#ifdef HAVE_AUTH_METHODS + free(buf); +#endif + return result; +} + +/* + * Main program. + */ +int +main(argc, argv) + int argc; + char **argv; +{ + struct passwd *pw; + char *pass, *name; + char myname[32]; + +#ifdef USE_SYSLOG + openlog("pwdauth", LOG_PID | LOG_CONS, LOG_AUTHPRIV); +#endif + pw = get_my_pwent(); + if (!pw) { +#ifdef USE_SYSLOG + syslog(LOG_ERR, "can't get login name for uid %d.\n", + (int) getuid()); +#endif + fprintf(stderr, "Who are you?\n"); + exit(2); + } + strncpy(myname, pw->pw_name, sizeof myname - 1); + myname[sizeof myname - 1] = '\0'; + name = myname; + + if (argc > 1) { + name = argv[1]; + pw = getpwnam(name); + } + + pass = get_line(stdin); + if (password_auth_ok(pw, pass)) { +#ifdef USE_SYSLOG + syslog(pw->pw_uid ? LOG_INFO : LOG_NOTICE, + "user `%s' entered correct password for `%.32s'.\n", + myname, name); +#endif + exit(0); + } +#ifdef USE_SYSLOG + /* be careful not to overrun the syslog buffer */ + syslog((!pw || pw->pw_uid) ? LOG_NOTICE : LOG_WARNING, + "user `%s' entered incorrect password for `%.32s'.\n", + myname, name); +#endif +#ifdef FAIL_DELAY + sleep(FAIL_DELAY); +#endif + fprintf(stderr, "Wrong password.\n"); + exit(1); +} + +#if 0 +/* + * You can use code similar to the following to run this program. + * Return values: >=0 - program exit status (use the + * macros to get the exit code, it is shifted left by 8 bits), + * -1 - check errno. + */ +int +verify_password(const char *username, const char *password) +{ + int pipe_fd[2]; + int pid, wpid, status; + + if (pipe(pipe_fd)) + return -1; + + if ((pid = fork()) == 0) { + char *arg[3]; + char *env[1]; + + /* child */ + close(pipe_fd[1]); + if (pipe_fd[0] != 0) { + if (dup2(pipe_fd[0], 0) != 0) + _exit(127); + close(pipe_fd[0]); + } + arg[0] = "/usr/bin/pwdauth"; + arg[1] = username; + arg[2] = NULL; + env[0] = NULL; + execve(arg[0], arg, env); + _exit(127); + } else if (pid == -1) { + /* error */ + close(pipe_fd[0]); + close(pipe_fd[1]); + return -1; + } + /* parent */ + close(pipe_fd[0]); + write(pipe_fd[1], password, strlen(password)); + write(pipe_fd[1], "\n", 1); + close(pipe_fd[1]); + + while ((wpid = wait(&status)) != pid) { + if (wpid == -1) + return -1; + } + return status; +} +#endif diff --git a/contrib/rpasswd.c b/contrib/rpasswd.c new file mode 100644 index 00000000..da6b77c0 --- /dev/null +++ b/contrib/rpasswd.c @@ -0,0 +1,591 @@ +/* rpasswd.c -- restricted `passwd' wrapper. + Copyright (C) 1996 Adam Solesby, Joshua Cowan + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This program is meant to be a wrapper for use with `sudo' and your + system's `passwd' program. It is *probably* secure, but there is no + warranty (see above). If you find errors or security holes, please + email me; please include a complete description of the problem in + your message in addition to any patches. */ + +/* This program currently assumes that the arguments given on the + command line are user names to pass to the `passwd' program; it loops + through the arguments calling `passwd' on each one. It might be + better to pass all remaining arguments after `--' to `passwd' (to + e.g., change the user's shell instead of the password by giving it + the `-s' option). */ + +/* Written by Adam Solesby . */ +/* Rewritten by Joshua Cowan . */ + +/* Usage: rpasswd USERNAME... + Enforce password-changing guidelines. + + --check[=file] check configuration information; if FILE is given, + use that instead of the standard configuration + file `./rpasswd.conf' + --help display this help and exit + --version output version information and exit + + You may never change a superuser's password with this command. + Changing certain other users' passwords may also be forbidden; for + details of who's passwords may not be changed, try `rpasswd --check'. */ + +/* TODO: + + - Make this more portable. It currently depends on several + GNU/Linux-specific features. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* This is the absolute path to the `passwd' program on your system. */ +#define _PATH_PASSWD "/usr/bin/passwd" + +/* This is the absolute path to the configuration file. */ +#define _PATH_RPASSWD_CONF "/etc/rpasswd.conf" + +/* Don't change the password of any user with a uid equal to or below + this number--no matter what the configuration file says. */ +#define UID_PWD_CHANGE_FLOOR 100 + +/* Everything past this point should probably be left alone. */ + +/* These are the facility and priority (respectively) used by the syslog + functions. */ +#define LOG_FACILITY LOG_AUTH +#define LOG_PRIORITY LOG_WARNING + +/* The name this program was run with. */ +char *program_name; + +/* The version information for this program. */ +char *version_string = "1.2"; + +/* If nonzero, display usage information and exit. */ +static int show_help; + +/* If nonzero, print the version on standard output then exit. */ +static int show_version; + +/* If nonzero, check the configuration file for errors and print the + list of restrictions on the standard output, then exit. */ +static int check_only; + +struct user_list +{ + char *name; + struct user_list *next; +}; + +struct config_info +{ + /* Don't change the password for any user with a uid less than or + equal to this number. */ + uid_t minimum_uid; + + /* Don't change the password for any user matching this list of user + names. */ + struct user_list *inviolate_user_names; +}; + +static const struct option long_options[] = +{ + {"check", optional_argument, 0, 10}, + {"version", no_argument, &show_version, 1}, + {"help", no_argument, &show_help, 1}, + {0, 0, 0, 0} +}; + +static struct config_info *get_config_info (); +static int dump_config_info (); +static void *xmalloc (); +static void *xrealloc (); +static void xsyslog (int, const char *, ...); +static void dal_error (int, int, const char *, ...); + +static void +usage (status) + int status; +{ + if (status != 0) + fprintf (stderr, "Try `%s --help' for more information.\n", + program_name); + else + { + printf ("Usage: %s USERNAME...\n", program_name); + fputs ("\ +Enforce password-changing guidelines.\n\ +\n\ + --check[=file] check configuration information; if FILE is given,\n\ + use that instead of the standard configuration file\n\ + `"_PATH_RPASSWD_CONF"'\n\ + --help display this help and exit\n\ + --version output version information and exit\n", + stdout); + + printf ("\n\ +You may never change a superuser's password with this command. Changing\n\ +certain other users' passwords may also be forbidden; for details of\n\ +who's passwords may not be changed, try `%s --check'.\n", + program_name); + } + + exit (status); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + char *executing_user_name; + char *config_file_name = _PATH_RPASSWD_CONF; + int opt; + struct config_info *config; + + /* Setting values of global variables. */ + program_name = argv[0]; + + while ((opt = getopt_long (argc, argv, "", long_options, 0)) + != EOF) + switch (opt) + { + case 0: + break; + + case 10: + check_only = 1; + if (optarg) + config_file_name = optarg; + break; + + default: + usage (1); + } + + if (show_version) + { + printf ("rpasswd %s\n", version_string); + return 0; + } + + if (show_help) + { + usage (0); + } + + if (check_only) + { + dump_config_info (config_file_name); + exit (0); + } + + if (optind >= argc) + { + fprintf (stderr, "%s: missing argument\n", program_name); + usage (1); + } + + /* FIXME: does `sudo' set the real user id to the effective user id? + If so, this won't work as intended: We want to get the name of the + user who ran `sudo'. I am reluctant to use `getlogin' for obvious + reasons, but it may be better than nothing. Maybe someone who + actually has `sudo' installed can tell me if this works, or how to + fix it if it doesn't. --JC */ + do + { + struct passwd *pwd; + uid_t uid = getuid (); + + pwd = getpwuid (uid); + + if (!pwd || !pwd->pw_name) + { + xsyslog (LOG_PRIORITY, + "Unknown user (uid #%d) attempted to change password for `%s'.", + uid, argv[optind]); + fprintf (stderr, "%s: you do not exist, go away\n", + program_name); + exit (1); + } + else + executing_user_name = pwd->pw_name; + } + while (0); + + config = get_config_info (config_file_name); + + for (; optind < argc; optind++) + { + int immutable_p = 0; + struct user_list *user_names = config->inviolate_user_names; + + /* Make sure we weren't given an illegal user name. */ + for (; user_names; user_names = user_names->next) + { + if (strcmp (argv[optind], user_names->name) + == 0) + { + immutable_p = 1; + break; + } + } + + if (!immutable_p) + { + struct passwd *pwd; + + pwd = getpwnam (argv[optind]); + + if (!pwd) + { + fprintf (stderr, "%s: invalid user `%s'\n", + program_name, argv[optind]); + + continue; + } + else if (pwd->pw_uid <= config->minimum_uid) + immutable_p = 1; + } + + if (immutable_p) + { + xsyslog (LOG_PRIORITY, + "`%s' attempted to change password for `%s'.", + executing_user_name, argv[optind]); + fprintf (stderr, + "You are not allowed to change the password for `%s'.\n", + argv[optind]); + } + else + { + int pid, status; + + pid = fork (); + switch (pid) + { + case -1: + dal_error (1, errno, "cannot fork"); + + case 0: + execl (_PATH_PASSWD, _PATH_PASSWD, "--", argv[optind], 0); + _exit (1); + + default: + while (wait (&status) != pid) + ; + + if (status & 0xFFFF) + dal_error (1, EIO, "%s", _PATH_PASSWD); + + break; + } + } + } + + exit (0); +} + +/* Get configuration information from FILE and return a pointer to a + `config_info' structure containing that information. It currently + does minimal checking of the validity of the information. + + This function never returns NULL, even when the configuration file is + empty. If the configuration file doesn't exist, it just exits with a + failed exit status. */ + +static struct config_info * +get_config_info (file) + const char *const file; +{ + FILE *config_file; + struct config_info *config; + char linebuf[BUFSIZ]; + unsigned int lineno = 0; + + config = (struct config_info *) xmalloc (sizeof (struct config_info)); + config->minimum_uid = (uid_t) 0; + config->inviolate_user_names = 0; + + config_file = fopen (file, "r"); + if (!config_file) + dal_error (1, errno, "%s", file); + + if (fseek (config_file, 0L, SEEK_SET)) + dal_error (1, errno, "%s", file); + + while (fgets (linebuf, BUFSIZ, config_file)) + { + int len, i, uid_found = 0; + + lineno++; + + len = strlen (linebuf); + + /* Chomp any whitespace off the end of the line. */ + while (isspace (linebuf[len - 1])) + linebuf[--len] = '\0'; + + /* If this line is empty or a comment, skip it and go to the next. */ + if (len == 0 || *linebuf == '#') + continue; + + for (i = 0; i < len; i++) + if (!isalnum (linebuf[i]) + && linebuf[i] != '.' + && linebuf[i] != '-' + && linebuf[i] != '_') + { + dal_error (1, 0, "%s:%u: invalid user name `%s'", + file, lineno, linebuf); + } + + /* Only accept positive integers as candidates for `minimum_uid'. */ + for (i = 0; i < len; i++) + if (!isdigit (linebuf[i])) + break; + + if (!uid_found && i == len) + { + unsigned long num; + + errno = 0; + num = strtoul (linebuf, 0, 10); + config->minimum_uid = (uid_t) num; + + if (errno || config->minimum_uid != num) + dal_error (1, 0, "%s:%u: `%s' out of range", + file, lineno, linebuf); + + uid_found = 1; + } + else + { + struct user_list *tail = config->inviolate_user_names; + struct user_list *user_names = 0; + + /* This could be more efficient, but makes the list of users + printed out with the `--check' switch easier to read. */ + + for (; tail; tail = tail->next) + { + if (strcmp (linebuf, tail->name) == 0) + break; + + user_names = tail; + } + + if (!tail) + { + tail = user_names; + + user_names = xmalloc (sizeof (struct user_list)); + user_names->name = strcpy (xmalloc (len + 1), linebuf); + user_names->next = 0; + + if (!config->inviolate_user_names) + config->inviolate_user_names = user_names; + else + tail->next = user_names; + } + } + } + + fclose (config_file); + + if (config->minimum_uid < UID_PWD_CHANGE_FLOOR) + config->minimum_uid = UID_PWD_CHANGE_FLOOR; + + return config; +} + +/* Dump the configuration info contained in FILE to the standard output. */ + +static int +dump_config_info (file) + char *file; +{ + struct config_info *config; + + config = get_config_info (file); + + printf ("\ +The lowest uid who's password may be changed is number %d. Changing +the following users' passwords is also forbidden:\n", + config->minimum_uid + 1); + + if (!config->inviolate_user_names) + { + printf ("\n (no users listed in configuration file `%s')\n", + file); + } + else + { + int column; + struct user_list *user_names = config->inviolate_user_names; + + for (column = 73; user_names; user_names = user_names->next) + { + int name_len = strlen (user_names->name); + + if (user_names->next) + name_len++; + + column += name_len; + + if (column > 72) + { + fputs ("\n ", stdout); + column = name_len + 2; + } + else if (column - name_len > 0) + { + fputc (' ', stdout); + column++; + } + + fputs (user_names->name, stdout); + + if (user_names->next) + fputc (',', stdout); + } + + fputc ('\n', stdout); + } + + return 0; +} + +static void * +xmalloc (n) + size_t n; +{ + void *ptr; + + ptr = malloc (n); + + if (!ptr) + { + fprintf (stderr, "%s: Memory exhausted\n", program_name); + exit (1); + } + + return ptr; +} + +static void * +xrealloc (ptr, n) + void *ptr; + size_t n; +{ + ptr = realloc (ptr, n); + + if (!ptr) + { + fprintf (stderr, "%s: Memory exhausted\n", program_name); + exit (1); + } + + return ptr; +} + +static void +xsyslog (int priority, const char *format, ...) +{ + va_list args; + static int logfd_opened = 0; + + if (!logfd_opened) + { + openlog (program_name, LOG_PID, LOG_FACILITY); + logfd_opened = 1; + } + + va_start (args, format); + vsyslog (priority, format, args); + va_end (args); +} + +/* Format and display MESSAGE on the standard error and send it to the + system logger. If ERRNUM is not 0, append the system error message + corresponding to ERRNUM to the output. If STATUS is not 0, exit with + an exit status of STATUS. */ + +static void +dal_error (int status, int errnum, const char *message, ...) +{ + va_list args; + size_t bufsize; + char *formatted_message; + + fflush (stdout); + + bufsize = strlen (message) * 2; + formatted_message = (char *) xmalloc (bufsize); + + va_start (args, message); + + while (1) + { + int printed; + printed = vsnprintf (formatted_message, bufsize, message, args); + + if ((size_t) printed < bufsize) + break; + + bufsize *= 2; + formatted_message = xrealloc (formatted_message, bufsize); + } + + va_end (args); + + if (errnum) + { + char *error_message = strerror (errnum); + + formatted_message + = xrealloc (formatted_message, + (strlen (formatted_message) + + strlen (error_message) + + 3)); + + strcat (formatted_message, ": "); + strcat (formatted_message, error_message); + } + + fprintf (stderr, "%s: %s\n", program_name, formatted_message); + + xsyslog (LOG_PRIORITY, "%s", formatted_message); + + free (formatted_message); + fflush (stderr); + + if (status) + { + closelog (); + exit (status); + } +} diff --git a/contrib/shadow-anonftp.patch b/contrib/shadow-anonftp.patch new file mode 100644 index 00000000..6938fe4f --- /dev/null +++ b/contrib/shadow-anonftp.patch @@ -0,0 +1,147 @@ +Hello Marek, + +I have created a diffile against the 980403 release that adds +functionality to newusers for automatic handling of users with only +anonomous ftp login (using the guestgroup feature in ftpaccess, which +means that the users home directory looks like '/home/user/./'). It also +adds a commandline argument to specify an initial directory structure +for such users, with a tarball normally containing the bin,lib,etc +directories used in the chrooted environment. + +I am using it to automatically create chunks of users with only ftp +access for a webserver. + +I have tried to follow your coding standards and I believe it is bug +free but.. well, who knows. :) It's not much code however. + +I hope you find it useful. Do what you like with it, feel free to ask if +anything is unclear. + +Best rgds, + Calle Karlsson + ckn@kash.se + +diff -uNr shadow-980403.orig/src/newusers.c shadow-980403/src/newusers.c +--- shadow-980403.orig/src/newusers.c Fri Jan 30 00:22:43 1998 ++++ shadow-980403/src/newusers.c Fri Apr 17 16:55:33 1998 +@@ -76,11 +76,35 @@ + static void + usage(void) + { +- fprintf(stderr, "Usage: %s [ input ]\n", Prog); ++ fprintf (stderr, "Usage: %s [-p prototype tarfile] [ input ]\n", Prog); ++ fprintf (stderr, "The prototype tarfile is only used for users\n"); ++ fprintf (stderr, "marked as anonymous ftp users. It must be a full pathname.\n"); + exit(1); + } + + /* ++ * createuserdir - create a directory and chmod it ++ */ ++ ++static int ++createuserdir (char * dir, int uid, int gid, int line) ++{ ++ if (mkdir (dir, 0777 & ~getdef_num("UMASK", 077))) { ++ fprintf (stderr, "%s: line %d: mkdir %s failed\n", ++ Prog, line, dir); ++ return -1; ++ } ++ ++ if (chown (dir, uid, gid)) { ++ fprintf (stderr, "%s: line %d: chown %s failed\n", ++ Prog, line, dir); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/* + * add_group - create a new group or add a user to an existing group + */ + +@@ -328,6 +352,8 @@ + main(int argc, char **argv) + { + char buf[BUFSIZ]; ++ char anonproto[BUFSIZ]; ++ int flag; + char *fields[8]; + int nfields; + char *cp; +@@ -340,12 +366,23 @@ + + Prog = Basename(argv[0]); + +- if (argc > 1 && argv[1][0] == '-') +- usage (); ++ * anonproto = '\0'; ++ ++ while ((flag = getopt (argc, argv, "p:h")) != EOF) { ++ switch (flag) { ++ case 'p': ++ STRFCPY(anonproto, optarg); ++ break; ++ case 'h': ++ default: ++ usage (); ++ break; ++ } ++ } + +- if (argc == 2) { +- if (! freopen (argv[1], "r", stdin)) { +- snprintf(buf, sizeof buf, "%s: %s", Prog, argv[1]); ++ if (optind < argc) { ++ if (! freopen (argv[optind], "r", stdin)) { ++ snprintf(buf, sizeof buf, "%s: %s", Prog, argv[optind]); + perror (buf); + exit (1); + } +@@ -499,15 +536,36 @@ + if (fields[6][0]) + newpw.pw_shell = fields[6]; + +- if (newpw.pw_dir[0] && access(newpw.pw_dir, F_OK)) { +- if (mkdir (newpw.pw_dir, +- 0777 & ~getdef_num("UMASK", 077))) +- fprintf (stderr, "%s: line %d: mkdir failed\n", +- Prog, line); +- else if (chown (newpw.pw_dir, +- newpw.pw_uid, newpw.pw_gid)) +- fprintf (stderr, "%s: line %d: chown failed\n", +- Prog, line); ++ if (newpw.pw_dir[0]) { ++ char * userdir = strdup (newpw.pw_dir); ++ char * anonpart; ++ int rc; ++ ++ if ((anonpart = strstr (userdir, "/./"))) { ++ * anonpart = '\0'; ++ anonpart += 2; ++ } ++ ++ if (access(userdir, F_OK)) ++ rc = createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line); ++ else ++ rc = 0; ++ ++ if (rc == 0 && anonpart) { ++ if (* anonproto) { ++ char cmdbuf [BUFSIZ]; ++ snprintf(cmdbuf, sizeof cmdbuf, ++ "cd %s; tar xf %s", ++ userdir, anonproto); ++ system (cmdbuf); ++ } ++ if (strlen (anonpart) > 1) { ++ strcat (userdir, anonpart); ++ if (access (userdir, F_OK)) ++ createuserdir (userdir, newpw.pw_uid, newpw.pw_gid, line); ++ } ++ } ++ free (userdir); + } + + /* diff --git a/contrib/udbachk.v012.tgz b/contrib/udbachk.v012.tgz new file mode 100644 index 00000000..82bd3204 Binary files /dev/null and b/contrib/udbachk.v012.tgz differ diff --git a/debian/FILES b/debian/FILES new file mode 100644 index 00000000..eb7d2375 --- /dev/null +++ b/debian/FILES @@ -0,0 +1,70 @@ + groups + groups.1 + id + id.1 + pw_auth.3 + scologin + shadow.3 + sulogin + sulogin.8 +login faillog +login faillog.5 +login faillog.8 +login lastlog +login lastlog.8 +login login +login login.1 +login login.access.5 +login login.defs.5 +login logoutd +login logoutd.8 +login newgrp +login newgrp.1 +login porttime.5 +passwd chage +passwd chage.1 +passwd chfn +passwd chfn.1 +passwd chpasswd +passwd chpasswd.8 +passwd chsh +passwd chsh.1 +passwd dpasswd +passwd dpasswd.8 +passwd expiry +passwd gpasswd +passwd gpasswd.1 +passwd groupadd +passwd groupadd.8 +passwd groupdel +passwd groupdel.8 +passwd groupmod +passwd groupmod.8 +passwd grpck +passwd grpck.8 +passwd grpconv +passwd grpunconv +passwd mkpasswd +passwd mkpasswd.8 +passwd newusers +passwd newusers.8 +passwd passwd +passwd passwd.1 +passwd passwd.5 +passwd pwauth.8 +passwd pwck +passwd pwck.8 +passwd pwconv +passwd pwconv.8 +passwd pwunconv +passwd pwunconv.8 +passwd shadow.5 +passwd useradd +passwd useradd.8 +passwd userdel +passwd userdel.8 +passwd usermod +passwd usermod.8 +secure-su su +secure-su su.1 +secure-su suauth.5 diff --git a/debian/Makefile.am b/debian/Makefile.am new file mode 100644 index 00000000..840a585a --- /dev/null +++ b/debian/Makefile.am @@ -0,0 +1,9 @@ +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + +EXTRA_DIST = FILES changelog checksums control login.conffiles \ + login.copyright login.postinst login.postrm login.preinst \ + login.prerm logoutd passwd.conffiles passwd.copyright \ + passwd.postinst porttime rules secure-su.README \ + secure-su.conffiles secure-su.copyright secure-su.postrm \ + secure-su.preinst securetty tar.c diff --git a/debian/Makefile.in b/debian/Makefile.in new file mode 100644 index 00000000..526be5ff --- /dev/null +++ b/debian/Makefile.in @@ -0,0 +1,200 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +EXTRA_DIST = FILES changelog checksums control login.conffiles \ + login.copyright login.postinst login.postrm login.preinst \ + login.prerm logoutd passwd.conffiles passwd.copyright \ + passwd.postinst porttime rules secure-su.README \ + secure-su.conffiles secure-su.copyright secure-su.postrm \ + secure-su.preinst securetty tar.c +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps debian/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = debian + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir info dvi installcheck install-exec install-data \ +install uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 00000000..7e264784 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,175 @@ +shadow (19990709) unstable; urgency=low + + * upstream upgrade, see CHANGES for more details. Note: this is + not the official Debian changelog entry - it is here only for + dpkg-buildpackage to work (so I can build and test this package + on my system). To the Debian maintainers: please feel free to + replace this entry with your own, and put your name (instead of + mine) in the debian/control Maintainer field. Thanks, and keep + up the good work! + + -- Marek Michalkiewicz Fri, 9 Jul 1999 19:40:00 +0200 + +shadow (980403-0.3.2) unstable; urgency=low + + * configure.in patched for utmpx.h (for arm) + + -- Jim Pick Sun, 4 Oct 1998 19:06:15 -0700 + +shadow (980403-0.3.1) frozen unstable; urgency=low + + * Non maintainer upload. + changes.{guess,sub} changed to recognize a Arm architecture. + + -- Turbo Fredriksson Fri, 14 Aug 1998 22:37:58 -0400 + +shadow (980403-0.3) frozen unstable; urgency=high + + * Non maintainer upload. + * src/login.c: Applied patch from to + fix security hole of login not checking the return code from setgid(), + initgroups() or setuid(). [#24710] + + -- James Troup Fri, 17 Jul 1998 18:56:31 +0100 + +shadow (980403-0.2) frozen unstable; urgency=low + + * (login.defs): fixed UMASK + (thanks to James Troup for noticing my screwup :) + * Pruned non-Debian changelog entries. + + -- Joel Klecker Mon, 11 May 1998 11:25:22 -0700 + +shadow (980403-0.1) frozen unstable; urgency=low + + * Non-maintainer release. + * New upstream release (18225). + * (debian/login.postinst) + * Use 'touch' instead of 'cat >' when creating /var/log/faillog + (15998,16187,21687). + * No longer fails if no previous configured version exists (11433). + * (gpasswd): now checks which user invoked it before calling setuid() (18132). + * (debian/passwd.postinst): removed bashism (13753). + * (groupmod): NULL dereference fixed upstream, as a result, it no longer + dumps core when changing group name (16893,17894). + * (useradd): no longer segfaults if /etc/default/useradd is missing (18628). + * (login.defs.1): now documents more options (13485). + * (source): includes 'missing' (13815,18133,21280). + * (login.1): + * Removed mention of "d_passwd(5)", which doesn't exist, + and login.defs.5 now documents /etc/dialups (15176). + * Added /etc/nologin to FILES section and reference nologin(5) (21695). + * The URL mentioned in Bug#15391 is no longer valid. + * (login.defs): no longer sets ULIMIT (17529). + * (login): + * No longer uses static buffers for group lines (17532). + * Doesn't seem to make assumptions about gid_t any longer (21767). + * (faillog.8): s-/usr/adm-/var/log-g (19974). + * (lastlog.8): notes that "some systems" use /var/log instead of + /usr/adm (21746). + * Install upstream changelog as 'changelog.gz' as per policy (20052). + * (secure-su): Changed /etc/suauth to reference the group 'root' + instead of 'wheel' (17593). + + -- Joel Klecker Thu, 30 Apr 1998 18:32:12 -0700 + +shadow (970616-1) unstable; urgency=low + + * Upstream upgrade. + * chage works (10561). + * Fix NIS behavior (5634,8734,10032,10545,10984,11160,12064). + * Wrote pwconv,pwunconv,grpconv,grpunconv manpage (10940). + * vipw fixes (10521,10696,11618,11924,12184,13001) + * Fixes for new automake. + * Compile with glibc2. (8627,8777,9824,11713,11719,12082,12108,11442). + * debian/rules fixes (8876,12468). + * /etc/login.defs: UMASK=002 (9102). + * chown /dev/vcs* on login (9421,13255). + * Added tty9-tty12 to /etc/securetty (11644). + * Provide template and manpage for /etc/limits (12289). + * Fix security hole in postinst (11769). + * login fills out ut_addr field in utmp (10701). + * shadowconfig.sh fixes (9189,9328,9386,10968,12452,12469). + * Overcome postinst bug in old shadow-passwd package (9939,12120). + * useradd default GROUP=100 (9244). + * Allow 8 bit chars in chfn (12367). + * secure-su - set HOME, use SHELL if set (11003,11189). + + -- Guy Maor Fri, 26 Sep 1997 19:23:42 -0500 + +shadow (970616) unstable; urgency=low + + * vipw preserves permissions on edited files (10521). + * various other bug fixes. + + -- Marek Michalkiewicz Mon, 16 Jun 1997 02:02:00 +0200 + +shadow (970601) unstable; urgency=low + + * Fix typo in libmisc/mail.c causing login to segfault. + + -- Marek Michalkiewicz Mon, 2 Jun 1997 07:33:00 +0200 + +shadow (970502-2) unstable; urgency=low + + * Fixes to shadow group support (grpconv didn't work). + + -- Marek Michalkiewicz Fri, 2 May 1997 15:48:00 +0200 + +shadow (970502-1) unstable; urgency=low + + * Upstream upgrade. + + -- Marek Michalkiewicz Fri, 2 May 1997 03:18:00 +0200 + +shadow (961025-2) frozen unstable; urgency=medium + + * Fix useradd -D segfault (8098, 8152, 8733). + * Fix shadowconfig - permfix only on xlock; /etc/init.d/xdm rewrite, chmod + (8102, 8320, 8333, 8708). + * Remove HOWTO from usr/doc/passwd as it's in linux-doc (8150). + * Fixes to su.1 (8153). + * login, passwd, su each conflict and replace with the old shadow-* + version. (8269, 8290, 8393, 8394). + * Put /etc/shells back in passwd (8328). + * Fixed login.postinst for upgrade from shadow-login (8392). + * Added -e to pwck for use in shadowconfig: reports only errors, no + warnings (8542). + * Wrote shadowconfig.8 (8588). + + -- Guy Maor Sat, 19 Apr 1997 02:34:59 -0500 + +shadow (961025-1) unstable; urgency=low + + * Upstream upgrade, new source format. + + -- Guy Maor Mon, 10 Feb 1997 02:56:56 -0600 + +shadow (960530-1) experimental; urgency=LOW + + * Added grpunconv script + * Changed prerm/postinst scripts to remove/create shadowed group + file + * Added vipw/vigr binaries + * Renamed package to shadow-passwd + * Added packages shadow-su and shadow-login + * Added 'Essential: yes' to be able to replace passwd and login + * Section now base for shadow-passwd and shadow-login + * Added /etc/shell conffile + * Added /etc/securetty conffile + * Added new conffile /etc/suauth. Set it up so only users in group 0 + can su to root. + +shadow (960810-1) base; urgency=LOW + + * Added useradd default file so that default group is no longer 1 + * Also corrected the useradd manpage + * Replaced grpunconv script by real binary which does correct + locking. + * Added 'source' field control file to control files + * Changed version naming in debian.rules + * New upstream version + +Local variables: +mode: debian-changelog +End: diff --git a/debian/checksums b/debian/checksums new file mode 100755 index 00000000..9d227c30 --- /dev/null +++ b/debian/checksums @@ -0,0 +1,7 @@ +#!/bin/sh +# This script is run from debian/rules to generate MD5 checksums +# for all files in the package. +# $Id: checksums,v 1.1 1997/12/14 21:05:37 marekm Exp $ +set -e +cd $1 +md5sum `find * -type f ! -regex "DEBIAN/.*"` >DEBIAN/md5sums +Standards-Version: 2.3.0.0 + +Package: login +Architecture: any +Pre-Depends: ${shlibs:Depends} +Conflicts: shadow-login +Replaces: shadow-login, shadow-passwd +Essential: yes +Section: base +Priority: required +Description: Sign on to the system. + login and newgrp change the user and group. + +Package: passwd +Architecture: any +Depends: ${shlibs:Depends}, login (>= 970502-1) +Conflicts: shadow-passwd +Replaces: shadow-passwd +Replaces: manpages (<=1.15-2) +Section: base +Priority: required +Description: Change and administer password and group data. + This package includes passwd, chsh, chfn, and many other programs to + maintain password and group data. + . + Shadow passwords are supported. See /usr/doc/passwd/README.Debian + +Package: secure-su +Architecture: any +Depends: ${shlibs:Depends}, login (>= 970502-1) +Conflicts: shadow-su +Replaces: shadow-su +Section: admin +Priority: optional +Description: su with more security options + secure-su offers more security options than the normal su, such as a + wheel group, and from-user and to-user specific restrictions. diff --git a/debian/login.conffiles b/debian/login.conffiles new file mode 100644 index 00000000..c1d83cba --- /dev/null +++ b/debian/login.conffiles @@ -0,0 +1,6 @@ +/etc/login.defs +/etc/login.access +/etc/securetty +/etc/porttime +/etc/limits +/etc/init.d/logoutd diff --git a/debian/login.copyright b/debian/login.copyright new file mode 100644 index 00000000..727bc1b7 --- /dev/null +++ b/debian/login.copyright @@ -0,0 +1,76 @@ +This is Debian/GNU Linux's prepackaged version of login and related +utilities. + +It was downloaded from: . + +This software is copyright 1988 - 1994, Julianne Frances Haugh. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of Julianne F. Haugh nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +This source code is currently archived on ftp.uu.net in the +comp.sources.misc portion of the USENET archives. You may also contact +the author, Julianne F. Haugh, at jfh@bga.com if you have +any questions regarding this package. + +THIS SOFTWARE IS BEING DISTRIBUTED AS-IS. THE AUTHORS DISCLAIM ALL +LIABILITY FOR ANY CONSEQUENCES OF USE. THE USER IS SOLELY RESPONSIBLE +FOR THE MAINTENANCE OF THIS SOFTWARE PACKAGE. THE AUTHORS ARE UNDER NO +OBLIGATION TO PROVIDE MODIFICATIONS OR IMPROVEMENTS. THE USER IS +ENCOURAGED TO TAKE ANY AND ALL STEPS NEEDED TO PROTECT AGAINST ACCIDENTAL +LOSS OF INFORMATION OR MACHINE RESOURCES. + +Special thanks are due to Chip Rosenthal for his fine testing efforts; +to Steve Simmons for his work in porting this code to BSD; and to Bill +Kennedy for his contributions of LaserJet printer time and energies. +Also, thanks for Dennis L. Mumaugh for the initial shadow password +information and to Tony Walton (olapw@olgb1.oliv.co.uk) for the System +V Release 4 changes. Effort in porting to SunOS has been contributed +by Dr. Michael Newberry (miken@cs.adfa.oz.au) and Micheal J. Miller, Jr. +(mke@kaberd.rain.com). Effort in porting to AT&T UNIX System V Release +4 has been provided by Andrew Herbert (andrew@werple.pub.uu.oz.au). +Special thanks to Marek Michalkiewicz (marekm@i17linuxb.ists.pwr.wroc.pl) +for taking over the Linux port of this software. + +Source files: login_access.c, login_desrpc.c, login_krb.c are derived +from the logdaemon-5.0 package, which is under the following license: + +/************************************************************************ +* Copyright 1995 by Wietse Venema. All rights reserved. Individual files +* may be covered by other copyrights (as noted in the file itself.) +* +* This material was originally written and compiled by Wietse Venema at +* Eindhoven University of Technology, The Netherlands, in 1990, 1991, +* 1992, 1993, 1994 and 1995. +* +* Redistribution and use in source and binary forms are permitted +* provided that this entire copyright notice is duplicated in all such +* copies. +* +* This software is provided "as is" and without any expressed or implied +* warranties, including, without limitation, the implied warranties of +* merchantibility and fitness for any particular purpose. +************************************************************************/ + diff --git a/debian/login.postinst b/debian/login.postinst new file mode 100644 index 00000000..32b19a06 --- /dev/null +++ b/debian/login.postinst @@ -0,0 +1,42 @@ +#!/bin/sh +set -e + +[ "$1" = configure -a "$2" ] \ + && dpkg --compare-versions $2 lt 961025 \ + || [ -z "$2" ] \ + || exit 0 + +if [ -f /etc/usertty ] ; then + cat > /etc/usertty$$ <> /etc/usertty$$ + mv -f /etc/usertty$$ /etc/usertty + + if egrep -vqn '^#|^ *$' /etc/usertty ; then cat < /dev/null diff --git a/debian/login.postrm b/debian/login.postrm new file mode 100644 index 00000000..48d537ef --- /dev/null +++ b/debian/login.postrm @@ -0,0 +1,6 @@ +#!/bin/sh +set -e + +if [ $1 = purge ]; then + update-rc.d logoutd remove >/dev/null +fi diff --git a/debian/login.preinst b/debian/login.preinst new file mode 100644 index 00000000..96637b51 --- /dev/null +++ b/debian/login.preinst @@ -0,0 +1,4 @@ +#!/bin/sh +set -e +dpkg --assert-support-predepends || +( echo -e "\nPlease upgrade to a newer version of dpkg\n"; exit 1; ) diff --git a/debian/login.prerm b/debian/login.prerm new file mode 100644 index 00000000..ba1301b3 --- /dev/null +++ b/debian/login.prerm @@ -0,0 +1,8 @@ +#!/bin/sh +set -e + +case $1 in + remove|upgrade|deconfigure) + /etc/init.d/logoutd stop + ;; +esac diff --git a/debian/logoutd b/debian/logoutd new file mode 100644 index 00000000..aec70877 --- /dev/null +++ b/debian/logoutd @@ -0,0 +1,42 @@ +#! /bin/sh +# start/stop logoutd + +set -e + +DAEMON=/usr/sbin/logoutd +test -f $DAEMON || exit 0 + +# Most people won't need logoutd(8) running, so we'll only run it if +# /etc/porttime has non-comment lines. +egrep -vq '^#|^ *$' /etc/porttime || exit 0 + +case "$1" in + start) + echo -n "Starting login time and port restriction enforcer: logoutd" + start-stop-daemon --start --quiet --exec $DAEMON + echo "." + ;; + stop) + echo -n "Stopping login time and port restriction enforcer: logoutd" + start-stop-daemon --stop --quiet --exec $DAEMON + echo "." + ;; + restart) + $0 stop + $0 start + ;; + reload) + echo -n "Reloading logoutd configuration..." + start-stop-daemon --stop --signal 1 --quiet --exec $DAEMON + echo "done." + ;; + force-reload) + $0 reload + ;; + *) + echo "Usage: /etc/init.d/logoutd start|stop" + exit 1 + ;; +esac + +exit 0 diff --git a/debian/passwd.conffiles b/debian/passwd.conffiles new file mode 100644 index 00000000..b6740ea5 --- /dev/null +++ b/debian/passwd.conffiles @@ -0,0 +1 @@ +/etc/shells diff --git a/debian/passwd.copyright b/debian/passwd.copyright new file mode 100644 index 00000000..e032df5f --- /dev/null +++ b/debian/passwd.copyright @@ -0,0 +1,55 @@ +This is Debian/GNU Linux's prepackaged version of the passwd +utilities. + +It was downloaded from: . + +This software is copyright 1988 - 1994, Julianne Frances Haugh. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of Julianne F. Haugh nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +This source code is currently archived on ftp.uu.net in the +comp.sources.misc portion of the USENET archives. You may also contact +the author, Julianne F. Haugh, at jfh@bga.com if you have +any questions regarding this package. + +THIS SOFTWARE IS BEING DISTRIBUTED AS-IS. THE AUTHORS DISCLAIM ALL +LIABILITY FOR ANY CONSEQUENCES OF USE. THE USER IS SOLELY RESPONSIBLE +FOR THE MAINTENANCE OF THIS SOFTWARE PACKAGE. THE AUTHORS ARE UNDER NO +OBLIGATION TO PROVIDE MODIFICATIONS OR IMPROVEMENTS. THE USER IS +ENCOURAGED TO TAKE ANY AND ALL STEPS NEEDED TO PROTECT AGAINST ACCIDENTAL +LOSS OF INFORMATION OR MACHINE RESOURCES. + +Special thanks are due to Chip Rosenthal for his fine testing efforts; +to Steve Simmons for his work in porting this code to BSD; and to Bill +Kennedy for his contributions of LaserJet printer time and energies. +Also, thanks for Dennis L. Mumaugh for the initial shadow password +information and to Tony Walton (olapw@olgb1.oliv.co.uk) for the System +V Release 4 changes. Effort in porting to SunOS has been contributed +by Dr. Michael Newberry (miken@cs.adfa.oz.au) and Micheal J. Miller, Jr. +(mke@kaberd.rain.com). Effort in porting to AT&T UNIX System V Release +4 has been provided by Andrew Herbert (andrew@werple.pub.uu.oz.au). +Special thanks to Marek Michalkiewicz (marekm@i17linuxb.ists.pwr.wroc.pl) +for taking over the Linux port of this software. diff --git a/debian/passwd.postinst b/debian/passwd.postinst new file mode 100644 index 00000000..ba2d5e26 --- /dev/null +++ b/debian/passwd.postinst @@ -0,0 +1,38 @@ +#!/bin/sh +set -e + +if [ configure != "$1" ] ; then + exit 0 +fi + +# passwd 961025-1 incorrectly did permfix on sulogin and xdm-shadow in +# shadowconfig +permfix () { + [ -f $1 ] || return 0 + chown root:root $1 + chmod 755 $1 +} +permfix /sbin/sulogin +permfix /usr/X11R6/bin/xdm-shadow + +grep -q '^shadow:[^:]*:42' /etc/group && exit 0 +groupadd -g 42 shadow || ( + cat <&2 'source and diff are obsolete - use dpkg-source -b'; false + +checkroot: + $(checkdir) +# test root = "`whoami`" + +.PHONY: binary binary-arch binary-indep clean checkroot + +# Local Variables: +# mode:Makefile diff --git a/debian/secure-su.README b/debian/secure-su.README new file mode 100644 index 00000000..723f37a0 --- /dev/null +++ b/debian/secure-su.README @@ -0,0 +1,4 @@ +The su from shellutils is diverted into /bin/secure-su. That +directory MUST be owned by root and have permissions 700. Otherwise +you will lost any security advantages you will gain by installing +secure-su as users can still invoke the old su. diff --git a/debian/secure-su.conffiles b/debian/secure-su.conffiles new file mode 100644 index 00000000..2853262a --- /dev/null +++ b/debian/secure-su.conffiles @@ -0,0 +1 @@ +/etc/suauth diff --git a/debian/secure-su.copyright b/debian/secure-su.copyright new file mode 100644 index 00000000..4e5a0ea7 --- /dev/null +++ b/debian/secure-su.copyright @@ -0,0 +1,54 @@ +This is Debian/GNU Linux's prepackaged version of secure-su. + +It was downloaded from: . + +This software is copyright 1988 - 1994, Julianne Frances Haugh. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of Julianne F. Haugh nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +This source code is currently archived on ftp.uu.net in the +comp.sources.misc portion of the USENET archives. You may also contact +the author, Julianne F. Haugh, at jfh@bga.com if you have +any questions regarding this package. + +THIS SOFTWARE IS BEING DISTRIBUTED AS-IS. THE AUTHORS DISCLAIM ALL +LIABILITY FOR ANY CONSEQUENCES OF USE. THE USER IS SOLELY RESPONSIBLE +FOR THE MAINTENANCE OF THIS SOFTWARE PACKAGE. THE AUTHORS ARE UNDER NO +OBLIGATION TO PROVIDE MODIFICATIONS OR IMPROVEMENTS. THE USER IS +ENCOURAGED TO TAKE ANY AND ALL STEPS NEEDED TO PROTECT AGAINST ACCIDENTAL +LOSS OF INFORMATION OR MACHINE RESOURCES. + +Special thanks are due to Chip Rosenthal for his fine testing efforts; +to Steve Simmons for his work in porting this code to BSD; and to Bill +Kennedy for his contributions of LaserJet printer time and energies. +Also, thanks for Dennis L. Mumaugh for the initial shadow password +information and to Tony Walton (olapw@olgb1.oliv.co.uk) for the System +V Release 4 changes. Effort in porting to SunOS has been contributed +by Dr. Michael Newberry (miken@cs.adfa.oz.au) and Micheal J. Miller, Jr. +(mke@kaberd.rain.com). Effort in porting to AT&T UNIX System V Release +4 has been provided by Andrew Herbert (andrew@werple.pub.uu.oz.au). +Special thanks to Marek Michalkiewicz (marekm@i17linuxb.ists.pwr.wroc.pl) +for taking over the Linux port of this software. diff --git a/debian/secure-su.postrm b/debian/secure-su.postrm new file mode 100644 index 00000000..aef1e6ab --- /dev/null +++ b/debian/secure-su.postrm @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +if [ remove = "$1" ] ; then + dpkg-divert --package secure-su --remove --rename \ + --divert /bin/secure-su/su /bin/su + dpkg-divert --package secure-su --remove --rename \ + --divert /usr/man/man1/gnu-su.1.gz /usr/man/man1/su.1.gz + rm /bin/secure-su/README.gz + rmdir /bin/secure-su || true +fi diff --git a/debian/secure-su.preinst b/debian/secure-su.preinst new file mode 100644 index 00000000..d5522c2e --- /dev/null +++ b/debian/secure-su.preinst @@ -0,0 +1,14 @@ +#!/bin/sh + +set -e + +if [ install = "$1" ] ; then + # dpkg-divert uses rename so can't do cross-device diversions. bleah. + [ -d /bin/secure-su ] || mkdir /bin/secure-su + chmod 700 /bin/secure-su + ln -sf ../../usr/doc/secure-su/README.gz /bin/secure-su/README.gz + dpkg-divert --package secure-su --add --rename \ + --divert /bin/secure-su/su /bin/su + dpkg-divert --package secure-su --add --rename \ + --divert /usr/man/man1/gnu-su.1.gz /usr/man/man1/su.1.gz +fi diff --git a/debian/securetty b/debian/securetty new file mode 100644 index 00000000..d66d2a63 --- /dev/null +++ b/debian/securetty @@ -0,0 +1,14 @@ +# /etc/securetty: list of terminals on which root is allowed to login. +# See securetty(5) and login(1). +tty1 +tty2 +tty3 +tty4 +tty5 +tty6 +tty7 +tty8 +tty9 +tty10 +tty11 +tty12 diff --git a/debian/tar.c b/debian/tar.c new file mode 100644 index 00000000..1f45eaa0 --- /dev/null +++ b/debian/tar.c @@ -0,0 +1,409 @@ +/* + * $Id: tar.c,v 1.2 1999/03/07 19:14:24 marekm Exp $ + * + * This is a wrapper for tar to ensure that all files within the + * newly created tar archive have the owner and group set to + * root:root. This makes it possible to build Debian packages + * without root privileges (normally needed to chown files). + * + * Assumptions: + * - the directory containing this program is listed in $PATH + * before the directory containing the real tar program (/bin) + * - the options passed to tar cause it to output the archive + * (not compressed) on standard output + * + * Written by Marek Michalkiewicz , + * public domain, no warranty, etc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef REAL_TAR +#define REAL_TAR "/bin/tar" +#endif + +#define RECORD_SIZE 512 + +union record { + char data[RECORD_SIZE]; + struct header { + char name[100]; /* NUL-terminated if NUL fits */ + char mode[8]; /* 0+ spaces, 1-6 octal digits, space, NUL */ + char uid[8]; /* format same as mode */ + char gid[8]; /* format same as mode */ + char size[12]; /* 0+ spaces, 1-11 octal digits, space */ + /* if '1' <= typeflag <= '6', ignore size */ + char mtime[12]; /* format same as size */ + char chksum[8]; /* 0+ spaces, 1-6 octal digits, NUL, space */ + char typeflag; + char linkname[100]; /* NUL-terminated if NUL fits */ +/* XXX - for GNU tar, magic is "ustar " (no NUL) and version is " \0" */ + char magic[6]; /* must be TMAGIC (NUL term.) */ + char version[2]; /* must be TVERSION */ + char uname[32]; /* NUL-terminated */ + char gname[32]; /* NUL-terminated */ + char devmajor[8]; + char devminor[8]; +#ifdef GNU_TAR_FORMAT + char atime[12]; + char ctime[12]; + char offset[12]; + char longnames[4]; + char pad; + struct sparse { + char offset[12]; + char numbytes[12]; + } sp[4]; + char isextended; + char realsize[12]; +#else +/* if prefix[0] != NUL then filename = prefix/name else filename = name */ + char prefix[155]; /* NUL-terminated if NUL fits */ +#endif + } h; +#ifdef GNU_TAR_FORMAT + struct exthdr { + struct sparse sp[21]; + char isextended; + } xh; +#endif +}; + +static union record tarbuf; +static int infd = -1, outfd = -1; + +int main(int, char **); +static ssize_t xread(int, char *, size_t); +static ssize_t xwrite(int, const char *, size_t); +static int block_is_eof(void); +static void block_read(void); +static void block_write(void); +static void verify_magic(void); +static void verify_checksum(void); +static void update_checksum(void); +static void set_owner(const char *); +static void set_group(const char *); +static void process_archive(void); + + +int +main(int argc, char **argv) +{ + int pipefd[2]; + pid_t pid; + const char *real_tar; + int status; + + real_tar = getenv("REAL_TAR"); + if (!real_tar) + real_tar = REAL_TAR; + if (pipe(pipefd)) { + perror("pipe"); + exit(1); + } + pid = fork(); + if (pid == 0) { /* child */ + /* redirect stdout to the pipe */ + if (dup2(pipefd[1], STDOUT_FILENO) != 1) { + perror("dup2"); + _exit(126); + } + close(pipefd[0]); + close(pipefd[1]); + /* run the real tar program */ + execv(real_tar, argv); + if (errno == ENOENT) { + perror("execve"); + _exit(127); + } else { + perror("execve"); + _exit(126); + } + } else if (pid < 0) { /* error */ + perror("fork"); + exit(1); + } + /* parent */ + close(pipefd[1]); + /* read from pipefd[0], modify tar headers, write to stdout ... */ + infd = pipefd[0]; + outfd = STDOUT_FILENO; + process_archive(); + /* wait for the tar subprocess to finish, and return its exit status */ + status = 1; + if (waitpid(pid, &status, 0) == -1) { + perror("waitpid"); + exit(1); + } + if (WIFSIGNALED(status)) { + kill(getpid(), WTERMSIG(status)); + exit(1); + } + exit(WEXITSTATUS(status)); +} + +/* EINTR-safe versions of read() and write() - they don't really help much + as GNU tar itself (version 1.11.8 at least) is not EINTR-safe, but it + doesn't hurt... Also, these functions never return errors - instead, + they print an error message to stderr, and exit(1). End of file is + indicated by returning the number of bytes actually read. */ + +static ssize_t +xread(int fd, char *buf, size_t count) +{ + ssize_t n; + size_t left; + + left = count; + do { + n = read(fd, buf, left); + if ((n < 0) && (errno == EINTR)) + continue; + if (n <= 0) + break; + left -= n; + buf += n; + } while (left > 0); + if (count > left) + return count - left; + if (n < 0) { + perror("read"); + exit(1); + } + return 0; +} + + +static ssize_t +xwrite(int fd, const char *buf, size_t count) +{ + ssize_t n; + size_t left; + + left = count; + do { + n = write(fd, buf, left); + if (n < 0) { + if (errno == EINTR) + continue; + /* any other write errors are fatal */ + perror("write"); + exit(1); + } + left -= n; + buf += n; + } while (left > 0); + return count; +} + + +static int +block_is_eof(void) +{ + unsigned int i; + + for (i = 0; i < sizeof(tarbuf.data); i++) { + if (tarbuf.data[i]) + return 0; + } + return 1; +} + + +static void +block_read(void) +{ + ssize_t nread; + + nread = xread(infd, tarbuf.data, RECORD_SIZE); + if (nread != RECORD_SIZE) { + fprintf(stderr, "unexpected end of file\n"); + exit(1); + } +} + + +static void +block_write(void) +{ + xwrite(outfd, tarbuf.data, RECORD_SIZE); +} + + +static void +verify_magic(void) +{ + /* only check that magic starts with "ustar" - works for + standard UNIX tar as well as GNU tar formats. */ + if (strncmp(tarbuf.h.magic, "ustar", 5) != 0) { + fprintf(stderr, "bad tar header magic\n"); + exit(1); + } +} + + +static void +verify_checksum(void) +{ + unsigned int i; + int csum; + + if (sscanf(tarbuf.h.chksum, "%o", &csum) != 1) { + fprintf(stderr, "bad tar checksum format\n"); + exit(1); + } + memset(tarbuf.h.chksum, ' ', sizeof(tarbuf.h.chksum)); + for (i = 0; i < sizeof(tarbuf.data); i++) + csum -= (unsigned char) tarbuf.data[i]; + if (csum) { + fprintf(stderr, "bad tar checksum value\n"); + exit(1); + } +} + + +static void +update_checksum(void) +{ + unsigned int i; + int csum; + + memset(tarbuf.h.chksum, ' ', sizeof(tarbuf.h.chksum)); + csum = 0; + for (i = 0; i < sizeof(tarbuf.data); i++) + csum += (unsigned char) tarbuf.data[i]; + snprintf(tarbuf.h.chksum, sizeof(tarbuf.h.chksum), "%6o", csum); +} + + +static void +set_owner(const char *username) +{ + const struct passwd *pw; + + pw = getpwnam(username); + memset(tarbuf.h.uname, 0, sizeof(tarbuf.h.uname)); + snprintf(tarbuf.h.uname, sizeof(tarbuf.h.uname), "%s", username); + snprintf(tarbuf.h.uid, sizeof(tarbuf.h.uid), "%6o ", (int) (pw ? pw->pw_uid : 0)); +} + + +static void +set_group(const char *groupname) +{ + const struct group *gr; + + gr = getgrnam(groupname); + memset(tarbuf.h.gname, 0, sizeof(tarbuf.h.gname)); + snprintf(tarbuf.h.gname, sizeof(tarbuf.h.gname), "%s", groupname); + snprintf(tarbuf.h.gid, sizeof(tarbuf.h.gid), "%6o ", (int) (gr ? gr->gr_gid : 0)); +} + + +static void +process_archive(void) +{ + ssize_t nread; + long size; + + size = 0; + for (;;) { + /* read the header or data block */ + block_read(); + /* copy data blocks, if any */ + if (size > 0) { + block_write(); + size -= RECORD_SIZE; + continue; + } + if (block_is_eof()) { + /* eof marker */ + block_write(); + break; + } + + verify_magic(); + verify_checksum(); + + /* process the header */ + switch (tarbuf.h.typeflag) { + case LNKTYPE: + case SYMTYPE: + case CHRTYPE: + case BLKTYPE: + case DIRTYPE: + case FIFOTYPE: + /* no data blocks - ignore size */ + break; + case REGTYPE: + case AREGTYPE: + case CONTTYPE: + default: + if (sscanf(tarbuf.h.size, "%lo", &size) != 1) { + fprintf(stderr, "bad size format\n"); + exit(1); + } + break; + } + + /* XXX - for now, just chown all files to root:root. */ + set_owner("root"); + set_group("root"); + + update_checksum(); + /* write the modified header */ + block_write(); + } + /* eof marker detected, copy anything beyond it */ + for (;;) { + nread = xread(infd, tarbuf.data, RECORD_SIZE); + if (nread == 0) + break; /* end of file */ + xwrite(outfd, tarbuf.data, (size_t) nread); + } +} + +#if 0 +/* permission specification file format, fixperms-1.00 compatible: + type filename owner group mode [linkname | major minor] [# comment] + + type: + - = regular file + l = link + d = directory + c = char dev + b = block dev + p = fifo + s = socket + + filename - absolute pathname, wildcards ok [not for fixperms] + linkname - only for type l + major, minor - only for type c or b + owner group - numeric, or names [not for fixperms] + + XXX not yet implemented +*/ + +struct permspec { + char *name; + uid_t uid; + gid_t gid; + mode_t mode; + char *uname; + char *gname; + char *linkname; + dev_t dev; + struct permspec *next; +}; +#endif diff --git a/doc/ANNOUNCE b/doc/ANNOUNCE new file mode 100644 index 00000000..e4c24101 --- /dev/null +++ b/doc/ANNOUNCE @@ -0,0 +1,48 @@ +$Id: ANNOUNCE,v 1.3 1998/01/29 23:22:25 marekm Exp $ + +[ This is the original comp.os.linux.announce posting (only the + author's name and e-mail address has been updated), kept here + for historical reasons. Many things have changed since then. + Linux distributions are using it, and the mailing list address + has been changed. See README.linux (in the same directory) + for more up to date information. --marekm ] + +This is a new beta release of the Shadow Password Suite for Linux. +Many bugs have been reported (and fixed!), and the package is now +under a BSD-style copyright. It was written by Julianne F. Haugh +, and the Linux port is now maintained by me. + +Again, this is beta software which may still have some bugs, please +treat it as such. Please don't install it if you don't know what +you're doing. Please test it as much as you can, and report any +bugs - if you report them, they will be fixed! If all goes well, +Shadow should be stable enough for general use within a few months. +Once it is stable, Linux distributions can start using it - there +are no copyright problems anymore. + +Thanks to Greg Gallagher there is now +a developers mailing list, shadow-list@neptune.cin.net. Send the +command "subscribe" to shadow-list-request@neptune.cin.net (NOT to +the mailing list itself!) to subscribe if you are interested. + + +LSM entry follows: + +Begin3 +Title: Shadow Password Suite +Version: 3.3.3-951218 +Entered-date: 18DEC95 +Description: +Keywords: login passwd security shadow +Author: jfh@tab.com (Julie Haugh) +Maintained-by: marekm@i17linuxb.ists.pwr.wroc.pl (Marek Michalkiewicz) +Primary-site: sunsite.unc.edu /pub/Linux/system/Admin + 220K shadow-951218.tar.gz +Alternate-site: ftp.ists.pwr.wroc.pl /pub/linux/shadow +Original-site: ftp.uu.net ? +Platforms: +Copying-policy: BSD-like +End + +Marek Michalkiewicz +marekm@i17linuxb.ists.pwr.wroc.pl diff --git a/doc/CHANGES b/doc/CHANGES new file mode 100644 index 00000000..e9a36efc --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1,625 @@ +$Id: CHANGES,v 1.27 1999/07/09 18:02:43 marekm Exp $ + +shadow-19990607 => shadow-19990709 + +- added PAM support to chfn and chsh (thanks to Thorsten Kukuk) +- fixed a bug in newgrp if the user is in >= 17 groups +- added @LIBSKEY@ to LDADD for all programs (for some reason, + almost all programs need it if skey/opie support is enabled) +- changed grpconv/grpunconv to compile with --disable-shadowgrp +- changed faillog to do something (assume -p) with no options specified +- updated version of the udbachk passwd/shadow/group file integrity + checker (contrib/udbachk.v012.tgz) + +shadow-19990307 => shadow-19990607 + +- upgraded to libtool-1.2, latest config.{guess,sub} +- added missing #include "defines.h" in libmisc/login_desrpc.c - thanks + to almost everyone for reporting it :-) +- moved PAM-related defines to pam_defs.h +- added some braces to if/else to avoid egcs warnings +- started adding PAM support to login (based on util-linux, not finished yet) +- changed "!" to "x" for pw_passwd in src/newusers.c +- a few more Y2K fixes +- added contrib/udbachk.tgz (passwd/shadow/group file integrity checker), + thanks to Sami Kerola +- Debian: made /etc/{limits,login.access,login.defs,porttime,securetty} + files all mode 0600 (Bug#38729 - login: /etc/limits is world readable) +- updated mailing list information (moved again, now hosted by SuSE), + updated README.mirrors, other minor documentation updates +- made getpass work with redirected stdin +- new readpass echoing asterisks disabled by default by popular demand + (can be enabled at compile time: ./configure --enable-readpass) +- the random number of asterisks in readpass is now more random + (random number generator initialization was missing) +- commented out --enable-md5crypt (obsolete) in configure.in +- when checking for libskey, link with -lcrypt if libcrypt is available + (otherwise the configure test for libskey fails - libskey needs libcrypt) +- added Package/Version ident strings (so you can use the RCS "ident" + command to check any binary, which version of shadow it comes from) + +shadow-981228 => shadow-19990307 + +- added support for setting process priority in /etc/limits +- i18n: updated Greek translation +- i18n: added Polish translation by Arkadiusz Miskiewicz +- documented the -p option in useradd.8 and usermod.8 man pages +- some "const" gcc warning fixes +- attempt to fix lib/snprintf.c compilation problems +- added restart/reload/force-reload to /etc/init.d/logoutd (found by lintian) +- always require password for root logins (even with NO_PASSWORD_CONSOLE) +- workaround for RedHat's CREATE_HOME feature in /etc/login.defs +- changed to Y2K compatible version numbering +- more Y2K fixes, use the ISO 8601 date format (yyyy-mm-dd) for default + values of user-entered dates (you can still enter dates in any format + supported by GNU date) +- oops, added doc/README.nls to list of files to distribute +- added missing sanitize_env() call to src/login.c +- debian/rules installs /bin/login non-setuid by default, just in case... +- build Debian packages with cracklib support (depends on cracklib-runtime) + +shadow-980724 => shadow-981228 + +- login now clears the username in argv[] (in case someone types the + password instead of username, by mistake) +- i18n support, Greek translation (Nikos Mavroyanopoulos), see README.nls +- updated author's e-mail address (jfh@tab.com -> jfh@bga.com) +- new getpass() replacement that displays *'s (Pavel Machek) +- no password required when logging in from ttys listed under + NO_PASSWORD_CONSOLE in login.defs (Pavel Machek) +- fixed limits code so RLIMIT_AS should work +- upgraded to Debian 2.0 +- built a new machine (P2 350MHz, 64MB RAM) so the thing can be compiled + in reasonable time again +- upgraded to automake-1.3, libtool-1.0h (also new config.guess and + config.sub that work on i686) +- usermod fixed to handle group names starting with digits (not recommended) + +shadow-980626 => shadow-980724 + +- security: login no longer gives you a root shell if setgid() + or initgroups() or setuid() fails for any reason, discovered + by Ted Hickman +- remove libshadow.so -> libshadow.so.x.x symlink after install +- a few int -> uid_t type cleanups +- fail immediately (don't retry) in *_lock() if euid != 0 +- added sample PAM config files etc/pam.d/{passwd,su} +- preliminary PAM support in su (untested - use at your own risk, + comments and patches welcome!) +- cleanup and more comments in OPIE code (Algis Rudys) +- added support for TCFS (Transparent Cryptographic File System) + (use ./configure --with-libtcfs, see http://tcfs.dia.unisa.it/ + for more info), thanks to Aniello Del Sorbo + +shadow-980529 => shadow-980626 + +- fixed bug in commonio_lock() (infinite recursion if lckpwdf() not + used and database cannot be locked), thanks to Jonathan Hankins +- fixed bug in copy_tree() (NUL-terminate readlink() results), + thanks to Lutz Schwalowsky +- no need to press Enter after Ctrl-C to interrupt password prompt +- removed a few harmless gcc warnings +- secure RPC login disabled if not found (glibc 2.0) +- faillog.8: changed /usr/adm -> /var/log +- pwconv.8: documented that it may fail on invalid password files + +shadow-980417 => shadow-980529 + +- fixed "interesting" strzero() bug introduced by me in 980417: + strzero(cp) didn't work as intended (the macro used a local + variable called "cp" - oops...); Leonard N. Zubkoff was the + first person to report it - thanks! +- fixed usermod -e to accept empty argument (like useradd), + thanks to Martin Bene +- several changes from Debian 980403-0.2, see debian/changelog +- added contrib/shadow-anonftp.patch (not yet merged, sorry...) + thanks to Calle Karlsson + +shadow-980403 => shadow-980417 + +- fixed login session limits (again - broken since 980130) +- more symbolic constants for exit status values +- fixed logoutd to work with 8-character usernames in utmp + (no room for terminating NUL!) +- various fixes to make the code more glibc2-friendly +- updated doc/cracklib26.diff (fix for empty gecos, etc.) +- updated the files in redhat/ from shadow-utils-970616-11.src.rpm + (RH 5.0 updates) + +shadow-980130 => shadow-980403 + +- security: su now creates the sulog file (if enabled and doesn't + already exist) with umask 077 +- hopefully removed arbitrary group size limits (not yet for + shadow groups though - sgetsgent() still needs a rewrite, + but I don't want to delay this release any longer...) +- fixed NULL dereference in groupmod -n + +shadow-971215 => shadow-980130 + +- Debian binary packages can be built without root privileges + (tar wrapper - debian/tar.c) +- new subdir "redhat" (needs more work, see redhat/README) +- in several places, exit(127) if exec fails with ENOENT, and + exit(126) on other errors (as in ksh and bash) +- renamed getpass() and md5_crypt() to libshadow_* to avoid name + conflicts with libc functions - md5_crypt() is also in libcrypt.a + on Linux/PPC, thanks to Anton Gluck +- handle crypt() returning NULL (possible according to Single Unix + Spec) more gracefully (exit instead of SIGSEGV) +- fixed bug in putgrent() that showed up when realloc() moved the + buffer while expanding it, thanks to Floody +- fixed bug in login session limits (with a limit set to N logins, + only N-1 logins were allowed), thanks to Floody +- upgraded to libtool-1.0h (now recognizes GNU ld on Debian 1.3.1) +- newer config.guess and config.sub (should work on x86 for x > 5) +- removed doc/automake-1.0.diff (obsoleted by automake-1.2) +- added doc/cracklib26.diff (some patches for cracklib-2.6) +- documented more (not all yet) login.defs(5) settings +- replaced more exit status numeric values with #defines +- shadow-utils.spec now generated from shadow-utils.spec.in + (so I don't have to edit version numbers for every new release) +- groupadd -f option, based on RedHat's shadow-utils-970616-9 patch + ("force" - exit(0) if the group already exists); other RedHat- + specific options not added yet (best done in a perl script that + runs useradd/usermod/groupadd - see Debian's adduser-3.x) +- added -O option (override login.defs values) to useradd and groupadd +- if usermod can't update the group file(s), exit(10) but update the + password file(s) anyway (as documented by Solaris man page) +- useradd should no longer set sp_expire to the current date (oops) +- configure.in: added --enable-desrpc, check for gethostbyname in libc + before trying libnsl (necessary for Solaris; not for Linux or Irix, + even though libnsl may be present), fixed pw_age/pw_comment/pw_quota + detection, setpgrp vs. setpgid, other minor tweaks +- various */Makefile.am tweaks +- login.defs: added FAKE_SHELL - program to run instead of the login + shell, with the real shell in argv[0] (Frank Denis) +- login.defs: ignore case in yes/no settings +- more E_* defines instead of hardcoded numbers for exit() +- added sanitize_env() for setuid programs +- login_desrpc() checks for getnetname() errors +- new password is not "too similar" if it is long enough +- replacement strstr() was static, no one noticed :-) +- {pw,spw}_lock() and {pw,spw}_unlock() track the lock count and call + lckpwdf() and ulckpwdf() as needed, *_lock_first() hack removed +- login sets $REMOTEHOST for remote logins +- added newgrp -l option (Single Unix Spec, same as "-") +- EXPERIMENTAL shared lib support using libtool (libshadow.so saves about + 200K of disk space on Linux/x86), enabled by default if supported by + the system, use ./configure --disable-shared if it causes any problems. + Warning: libshadow.so is intended for internal use by this package + only - binary compatibility with future releases is not guaranteed. + There should be no need to link any other programs with libshadow.so - + the libshadow.so -> libshadow.so.x.x symlink is unnecessary. +- pam_strerror() takes one or two arguments, depending on the Linux-PAM + version (!) - added check to configure; fixed do_pam_passwd prototype +- libmisc/login_access.c should compile on Linux/PPC and Solaris +- added information about the new ftp site to doc/README.mirrors + +shadow-971001 => shadow-971215 + +- added workaround for NYS libc 5.3.12 (RedHat 4.2) bug to grpck +- updated the RPM .spec file +- renamed rlogin() to do_rlogin() to avoid Linux/PPC build problem + (glibc defines something else named "rlogin" in utmpbits.h ?) +- added MD5 checksums in Debian packages +- added -p and -g options to vipw (edit the password or group file + respectively, regardless of the command name in argv[0]) +- removed old DBM support (NDBM code is still there) +- fixed a bug in gpasswd: current username was incorrectly identified as + "root" because of setuid(0) done too early. It may be a security hole + when using shadow groups - if "root" is listed as a group administrator, + any user can add/remove members in that group. Thanks to Jesse Thilo. +- gpasswd now logs which user (root or group admin) made the changes +- passwd now uses $PATH to search for the chfn, chsh, gpasswd commands +- newgrp and add_groups() allocate supplementary group lists dynamically +- moved check_shell() from src/chsh.c to libmisc/chkshell.c +- CHFN_RESTRICT in login.defs can now specify exactly which fields may be + changed by regular users (any combination of letters "frwh") +- fixed contrib/pwdauth.c segfault with non-existent usernames +- minor change in lib/getdef.c to handle quotes better (Juergen Heinzl) +- new date parsing code (from GNU date) used by useradd, usermod, chage +- upgraded to automake-1.2, added libtool-0.7 (no libshadow.so yet) +- converted code to ANSI C, added ansi2knr (untested - use gcc!) +- fixed useradd -G segfault (one '*' that shouldn't be there) +- allow 8-bit characters in chfn +- added support for RLIMIT_AS (max address space) in libmisc/limits.c +- changed the handling of NIS plus entries in password files +- some more tweaking in various debian/* files +- logoutd uses getutent() instead of reading utmp file directly +- fixed lckpwdf() called twice (and failing) when changing password + if the user is not listed in /etc/shadow (Mike Pakovic) +- erase and kill characters left unchanged if not defined in login.defs + +shadow-970616 => shadow-971001 + +- Debian: mkpasswd no longer installed (dbm files not supported) +- chpasswd checks for shadow/non-shadow at run time, too +- added chpasswd -e (input file with encrypted passwords) - Jay Soffian +- changed libmisc/login_access.c as suggested by Dave Hagewood +- replaced sprintf() with snprintf() in several places +- added lib/snprintf.[ch] (from XFree86) for systems without snprintf() +- minor tweaks in contrib/adduser.c (/usr/local -> /usr) +- non-root users can only run su with a terminal on stdin +- temporarily disabled DES_RPC because getsecretkey() causes login to hang + for 5 minutes on at least one RH 4.0 system. Not sure if this is a bug + in libc, or system misconfiguration. Needs further investigation. +- check for strerror() and -lrpcsvc (should compile on SunOS again) +- fixed free() called twice in libmisc/mail.c +- added information about mirror sites (doc/README.mirrors) +- updated pwconv.8 and pwunconv.8 man pages +- "make install" now installs pwconv, pwunconv, grpconv, grpunconv +- pwauth.8 no longer installed (AUTH_METHODS not supported by default) +- corrected su.1 man page ($SHELL not used) +- no need for --with-md5crypt if the MD5-based crypt() is already in libc + (or another library specified in /etc/ld.so.preload - Linux ld.so 1.8.0+) +- cleaned up PASS_MAX in getpass() (127 always assumed) +- default editor for vipw changed from /bin/ae to a real editor :) + +shadow-970601 => shadow-970616 + +- fixed execlp call (missing NULL) in src/vipw.c +- vipw now preserves permissions on edited files +- commented out the xdm-shadow hack in shadowconfig +- improved RedHat spec file (Timo Karjalainen) +- updated mailing list information +- added information about the shadow paper (doc/README.shadow-paper) +- renamed doc/console.c.spec (confused RPM) + +shadow-970502-2 => shadow-970601 + +- fixed a typo in libmisc/mail.c causing login to segfault + if MAIL_CHECK_ENAB=yes (sorry!) +- patches for OPIE support (Algis Rudys) (untested) +- programs that modify /etc/passwd or /etc/shadow will use + lckpwdf() if available +- now compiles with PAM support! (still untested) +- cosmetic error message changes (prefixed by argv[0]:) + +shadow-970216 => shadow-970502-2 + +- shadow group support fixes (grpconv didn't work - for some + reason, putsgent() returns 1 instead of 0 on success; + now -1 = failure, anything else = success) +- upgraded to autoconf-2.12 +- pwconv and pwunconv now follow other UN*X systems and SVID3 + (modify files in place), original versions moved to "old" +- scologin.c moved to "old" (it was only for SCO Xenix) so + people stop sending patches for scologin.c gcc warnings :) +- don't use the MD5* functions in libmisc/salt.c (glibc has + the new md5 crypt(), but no and MD5* functions!) +- support for MkLinux, Solaris, JIS, Qmail (Frank Denis) +- "passwd -S -a" now really works +- support for Debian, vipw, a few fixes (Guy Maor) +- src/login.c radius bug fix (Rafal Maszkowski) +- ISSUE_FILE_ENAB -> ISSUE_FILE in the sample /etc/login.defs +- fixes for glibc and DES_RPC (Thorsten Kukuk) +- limits.5 man page (Luca Berra) +- expiry will work setgid shadow too, removed euid 0 check +- added check for a64l() to configure (glibc) + +shadow-961025 => shadow-970216 + +- major rewrite of *io.c (no more 4 copies of almost identical code) +- use fsync() (if available) instead of sync() when updating password files +- use fchmod() and fchown() if available +- keep the NIS "plus on a line by itself" entries at end of passwd/group +- configure checks location of passwd/chfn/chsh programs (/usr/bin or /bin) +- passwd -S -a: list information about all users (root only) +- passwd -k: change only expired passwords +- passwd -q: quiet mode +- first attempt at PAM support in passwd +- passwd updates the non-shadow password if /etc/shadow exists but the + user has no shadow password +- passwd logs who changed the password, added hook to allow non-root + administrators who can change passwords (not implemented yet) +- su sets $HOME even without the "-" option (suggested by Joey Hess) +- added -p (set encrypted password) option to useradd and usermod + (idea from hpux10 - undocumented option used internally by SAM) +- useradd -D -e does the right thing (set default expiration date) +- USERDEL_CMD in login.defs instead of hardcoded {ATRM,CRONTAB}_COMMAND + because there are just too many systems that need different commands +- removed #ifdef FAILLOG_LOCKTIME (now always enabled), warning: the + faillog file format has been changed (somewhere between 960129 and + 960810), please truncate the old file (if any) to zero length +- ISSUE_FILE (may be different from /etc/issue) instead of ISSUE_FILE_ENAB +- wtmp, lastlog, faillog file location guessed by configure +- separate checks for invalid user and group names, max username length + based on struct utmp (it's not always 8 characters) +- pwck and grpck now check for invalid user/group names +- pwck -q (quiet, report only serious problems) option added +- separate cleaner sgetpwent() without the NIS magic +- NIS entries ignored (never changed) by *io.c, pwck, grpck +- various code cleanups +- new get_my_pwent() function for getting my own username, uid etc. +- faillog opens the file read-write if possible (even if not root) +- passwd -S allowed for normal users (for their own uid only) +- handle the case of login denied to passwordless accounts better + ("Login incorrect" without "Password:" prompt looks strange) +- corrected author information and removed a copyright restriction + +shadow-960925 => shadow-961025 + +- fixed a few typos in shadow group code +- don't check for names starting with 'r' to determine if the shell + is restricted, use /etc/shells instead (for the "rc" shell) +- removed extra definition of LASTLOG_FILE in configure.in +- expiry no longer segfaults if no /etc/shadow +- userdel -r "can't remove mailbox" warning no longer printed on success +- useradd exit codes changed to match hpux10 man page +- fixed possible fd leak etc. in file locking code (lib/commonio.c) + +shadow-960920 => shadow-960925 + +- bug fixes to the new environment code using malloc +- use hardcoded names instead of basename(argv[0]) for openlog() in programs + that users can run (chage, chfn, chsh, gpasswd, login, newgrp, passwd, su) +- small fix to isexpired(), and use it in passwd as well +- use strftime() and strptime() if available +- added chmod 600 /etc/passwd- at the end of pwconv5 (backup file may + contain encrypted passwords!) +- pass size to change_field (chage, chfn, chsh) instead of assuming BUFSIZ + (nothing bad happened yet, just a cleanup) +- gpasswd should work with both shadow and non-shadow group passwords +- detect unsupported options if no shadow (gpasswd, useradd, usermod) +- passwd -e for sunos4 (ATT_AGE), untested +- read environment from file (ENVIRON_FILE in login.defs), idea from ssh +- small fix to l64a() +- passwd prints a message after password successfully changed (for things + like poppassd which run passwd and expect some output) +- passwd logs if password was changed by root (as opposed to a luser) +- passwd uses current uid if no username argument and getlogin() fails + +shadow-960910 => shadow-960920 + +- use malloc for environment variables, no more MAXENV (Juergen Heinzl) +- newusers should work with both shadow and non-shadow passwords + (still left to do: chpasswd, gpasswd) +- login-static no longer compiled by default +- more SYSLOG() macros + +shadow-960810 => shadow-960910 + +- updated README.linux to point to the new ftp site +- chfn and chsh optionally (CHFN_AUTH) prompt for password like util-linux +- man pages now closer to LDP standards (Ivan Nejgebauer) +- newgrp uses SYSLOG_SG_ENAB (not SU) as in the /etc/login.defs comments +- obscure.c fixed to compile with HAVE_LIBCRACK +- cosmetic message changes in age.c +- utmp open error check fixed in utmp.c +- grpunconv added (Michael Meskes) +- login reports invalid login time, not "Login incorrect" (Ivan Nejgebauer) +- logoutd sets OPOST before writing to the tty (Ivan Nejgebauer) +- sulogin: don't use syslog(), other minor changes (Ivan Nejgebauer) +- passwords can be changed if sp_max == -1 (now considered infinity) +- usermod: don't use sizeof(struct lastlog) when writing to faillog (ugh) +- started replacing lots of #ifdef USE_SYSLOG with cleaner macros +- contrib/rpasswd.c added (Joshua Cowan) +- PASS_MAX is 127 with MD5_CRYPT (not just for Linux - sunos4 too...) +- workarounds for a RedHat NYS libc getspnam() bug (if /etc/shadow + doesn't exist, it succeeds and returns sp_lstchg==0 instead of -1). + +shadow-960129 => shadow-960810 + +- automake, configure checks for libcrypt and libcrack (Janos Farkas) +- added --enable-shadowgrp to configure (shadow groups disabled by default) +- should compile on SunOS 4.1.x - but it does NOT mean that it works :-) +- login sets HUSHLOGIN=TRUE or FALSE (for shell startup scripts etc.) +- hopefully removed all the rcsid warnings +- contrib/atudel perl script to remove at jobs (thanks to Brian Gaeke) +- resource limits (Cristian Gafton) +- workaround for buggy init/getty(?) leaving junk in ut_host on RedHat +- more fixes in man pages +- pwck and grpck no longer suggest to run mkpasswd if *DBM not compiled in +- most programs (groupadd, groupdel, groupmod, grpck, login, passwd, pwck, + su, useradd, userdel, usermod) should now work with both shadow and + non-shadow passwords/groups (check for /etc/shadow and /etc/gshadow at + run time); a few programs still left to do +- mailbox mv/chown/rm in usermod/userdel (suggested by Cristian Gafton) +- new contrib/adduser.c from Chris Evans +- lots of other minor changes +- source tree reorganization, GNU autoconf, portability cleanups +- basename() renamed to Basename() to avoid name space confusion +- new programs to create /etc/shadow and /etc/gshadow: pwconv5, grpconv +- newgrp cleanup and a few fixes +- useradd uses PASS_MAX_DAYS, PASS_MIN_DAYS and PASS_WARN_AGE +- don't make the first group member the group admin by default + (define FIRST_MEMBER_IS_ADMIN to get the old gpasswd behaviour) +- password aging constants, NGROUPS_MAX and syslog stuff in only one + place (defines.h) instead of repeating it in all source files... +- added userdel -r safety check (refuse to remove the home directory + if it would result in removing some other user's home directory) +- usermod -u now correctly checks for non-unique uid (unless -o) +- sync() after updating password files, just to be more safe +- "make install" should install /etc/login.defs if it doesn't exist +- new option to control what happens if we can't cd to the home directory + (DEFAULT_HOME in /etc/login.defs) +- enter the home directory as the user, not as root (for NFS etc.) +- added check for Slackware bugs (nobody UID -1) in pwck and grpck +- new CONSOLE_GROUPS feature (thanks to pacman@tardis.mars.net), it is + possible to add specified groups (floppy etc.) for console logins +- new faillog feature: lock account for specified (per-user) time since + the last failure after exceeding the failure limit +- new man pages (gpasswd.1, login.access.5, suauth.5) +- fixes in man pages, renamed *.4 to *.5 +- new "contrib" directory (two adduser programs) +- changed some "system" to "feature" #ifdefs (autoconf someday...) +- sulogin no longer requires to be run from init, should work from rc + scripts too +- changes to prevent unshadowing with libc SHADOW_COMPAT (get info + using xx_locate(), modify it and call xx_update(), don't write back + anything returned by getpwnam() etc.) +- stupid bug fixed in lastlog.c +- don't move non-directories in "usermod -m" +- don't log unknown usernames (passwords mistyped for usernames) (lmain.c) +- macros to get around ancient compilers which don't like prototypes +- make more use of "const" (not everywhere yet) +- added #ifdef AUTH_METHODS - very few people use administrator defined + authentication methods because many programs are not aware of them; + not supporting them makes the code simpler +- new "save" and "restore" Makefile targets, thanks to Rafal Maszkowski +- sgetgrent() in libshadow.a is optional, some versions of libc have it, + see HAVE_SGETGRENT in config.h (grent.c) +- don't use continued lines in /etc/group, the standard getgr*() functions + don't support that (grent.c) +- removed the third main() argument (according to libc docs, not allowed by + POSIX.1 - use environ instead) (lmain.c, smain.c, newgrp.c, sulogin.c) +- login access control (lmain.c, login_access.c) +- added copyright notice to login_access.c (from logdaemon-5.0) +- detailed su access control (smain.c, suauth.c) - thanks to Chris Evans +- added closelog() in su before executing the shell (smain.c) +- getting current user name changed (smain.c) +- "x" instead of "*" in pw_passwd, consistent with pwconv (useradd.c) +- getpass() shouldn't return NULL except on errors (getpass.c) +- moved isexpired() to isexpired.c (now part of libshadow.a) from age.c +- SunOS4-like passwd -e (force change on next login) (isexpired.c, passwd.c) +- can use shadow support in new versions of Linux libc instead of libshadow.a, + see HAVE_SHADOWPWD, HAVE_SHADOWGRP in config.h.linux (shadow.c, gshadow.c) +- "no shadow password" not logged, the same /bin/login should work with both + shadow and non-shadow passwords (lmain.c) +- some cleanup in various places (lmain.c, passwd.c) +- new program to verify username/password pairs, for xlock etc.; it is not + installed by default, read the comments first (pwdauth.c) +- authentication programs run with empty environment for safety (pwauth.c) +- added missing fstat error checks (faillog.c, lastlog.c, setup.c, *io.c) +- common code separated from *io.c (commonio.c) +- ownership and permissions on password files are now preserved (we may try + to make more use of setgid and setuid non-root programs in the future) +- added (untested) MD5-based crypt() from FreeBSD (md5crypt.c), see + MD5_CRYPT in config.h.linux and MD5_CRYPT_ENAB in login.defs.linux +- termios/termio/sgtty macros cleaned up a bit + +shadow-951218 => shadow-960129 + +Emergency bug fix release - no new features since 951218. There are many +new changes, but this bug really can't wait until they are tested. + +Probably all previous versions of the shadow suite have a serious bug which +makes it possible to overwrite the stack by entering very long username at +the login prompt. This can give root access to any remote user! + +Changed the maximum size in login.c from BUFSIZ (1024) to 32 (to match +size of the array in lmain.c). Aaargh!!! + +shadow-951203 => shadow-951218 + +Changes: +- Linux utmp handling fixes (utmp.c) +- last failure date printing fixes (failure.c) +- minor fix to compile with USE_CRACKLIB (obscure.c) +- eliminated the use of snprintf (env.c, lmain.c, login.c, shell.c, smain.c) +- basename.c added, replacing duplicated code in various places +- "su -" runs the shell with '-' in argv[0] again (smain.c) +- removing at/cron jobs cleaned up (userdel.c) +- /etc/gshadow should not be world-readable (sgroupio.c) +- if fflush() failed, files were not closed (*io.c) +- login prompt is now "hostname login: " on Linux (lmain.c, login.c) +- "save" and "restore" targets commented out (don't work) (Makefile.linux) +- some minor cleanups for gcc -Wall (unused variables etc.) +- removed README.FIRST (copyrights are OK now) +- updated ANNOUNCE, README.linux, WISHLIST +- as suggested, converted to RCS + +shadow-3.3.2-951127 => shadow-951203-jfh + +Changes: +- Added the BSD-style copyright to all of the files. Any files with the + old copyright have multiple copyright holders and need to be cleanroomed + to produce BSD-style copyrightable files, or I need to get the consent + of the others to change the copyright. +- Changed the ANNOUNCE file to not refer to the README.FIRST file. Now + that all of the files should have the correct copyright there is no need + to refer to that e-mail message. +- Changes SCCS strings to "%W% %U% %G%". Marek needs to either convert to + RCS or check into SCCS and then checkout. I'd suggest using RCS ;-) + + jfh@rpp386.cactus.org + +shadow-3.3.2-951106 => shadow-951127 + +Note: for now this code only supports Linux. All the #ifdef's are there +(and will be; support for at least SunOS 4.1.x would be nice) but: +- I had to fix some potential security problems resulting from sloppy + coding (no bounds checking), and it was easier for me to use snprintf() + (not available on many systems, unfortunately), I'll fix that later. + Old versions of Linux libc don't have snprintf() either, and the one + in libbsd.a ignores the max size - don't use it! (libc-4.6.27 is OK) +- I am lazy and only updated Makefile.linux and config.h.linux this time +- I don't have root access to non-Linux systems (this means no testing) +- this code needs some major reorganization, which will (hopefully) + make porting easier + +Changes: +- some code cleanup, prototypes.h, defines.h, Makefile and config.h changes +- login can be statically linked (not that I think it's a good idea, better + fix the telnetd, but paranoid people will like it :-) +- login is installed non-setuid by default +- check for NULL from getpass() +- wipe cleartext password from getpass() when no longer needed (pwauth.c) +- use standard "Password: " prompt by default (pwauth.c) +- hopefully fixed bogus sigaction() stuff (Linux only) (getpass.c) +- oops, setrlimit wants bytes, ulimit wants 512-byte units (lmain.c) +- Linux has +- print ll_host on Linux too (lmain.c) +- size checking in various places (setuid root programs, argh!) +- preserve TERM from getty (lmain.c) +- don't ignore SIGHUP (lmain.c) +- :%s/setenv/set_env/g (setenv(3) conflict) (env.c, lmain.c, login.c) +- remove LD_xxx (env.c) +- use bzero() instead of memset() for BSD portability and less #ifdef's + (if the system has no bzero(), implement it as a macro using memset()) +- the above fixes wrong order of memset() parameters (log.c) +- use getutent/pututline instead of doing it by hand (utmp.c) +- added the new settings to login.defs.linux +- added login_access.c to the distribution (not used yet) + +========== + +shadow-3.3.2 => shadow-3.3.2-951106 + +- added dummy pad.c and #ifdef'ed out references to pad_auth (pwauth.c) +- malloc/strdup error checking, hopefully no more core dumps... +- define HAVE_RLIMIT instead of HAVE_ULIMIT for Linux (config.h.linux) +- changed pathnames on Linux to conform to new FSSTND (/var/log etc.) +- larger buffer for cipher, for md5 crypt() if and when (encrypt.c, passwd.c) +- use POSIX termios whenever possible on Linux +- list.c, removed add_list/del_list from gpmain.c, user{add,del,mod}.c +- strtoday.c, removed duplicates from chage.c, useradd.c, usermod.c +- login -h only for root (lmain.c) +- login -r not needed for Linux (lmain.c) +- sample login.defs modified for Linux (login.defs.linux) +- swapped chfn USAGE and ADMUSAGE (chfn.c) +- added -u to passwd usage (passwd.c) +- no #! check necessary for Linux (shell.c) +- define OLD_CRON for some old incompatible Linux distributions (userdel.c) +- PASS_MAX is now 127 (not 8) for Linux (getpass.c) +- LOGIN_RETRIES, LOGIN_TIMEOUT, PASS_CHANGE_TRIES are no longer compiled in, + can now be set in login.defs, old values are used as defaults (lmain.c) +- unique uid/gid selection now more robust (useradd.c, groupadd.c) +- UID_MIN, UID_MAX, GID_MIN, GID_MAX in login.defs (useradd.c, groupadd.c) +- CRACKLIB_DICTPATH no longer compiled in, can be set in login.defs (passwd.c) +- PASS_ALWAYS_WARN: warn about weak passwords even for root (passwd.c) +- PASS_MAX_LEN, check truncated passwords again (obscure.c) +- check for weak passwords too if previous password was empty (obscure.c) +- CHFN_RESTRICT: don't let users change their full names (chfn.c) +- Linux has getusershell(), use it (chsh.c) +- check if the new shell is executable by the user (chsh.c) +- sleep before printing "Login incorrect", not the other way around (lmain.c) +- don't be picky about utmp only if any of -rfh flags given (lmain.c) +- do "wheel group" more like BSD does (smain.c) +- use getlogin() in su (smain.c) +- UMASK from login.defs defaults to 077, not 0 (lmain.c, newusers.c) +- #undef HAS_ATRM for Linux until atrm can do what we need (config.h.linux) +- Linux has most commands in /usr/bin, not /bin (age.c, passwd.c, userdel.c) +- ULIMIT from login.defs works on systems using setrlimit() too (lmain.c) +- LOGIN_STRING should work now (pwauth.c, getdef.c) +- kludge to avoid conflict with Linux (gshadow.h) +- mv Makefile Makefile.xenix ; mv config.h config.h.xenix - so that they are + not lost when you copy the right ones to Makefile and config.h + +========== + +shadow-3.3.2 + +Original version, received directly from the author. + diff --git a/doc/HOWTO b/doc/HOWTO new file mode 100644 index 00000000..01a90ed4 --- /dev/null +++ b/doc/HOWTO @@ -0,0 +1,1918 @@ +[ Note: the installation instructions in this document are somewhat + out of date - the package now uses GNU autoconf and is configured + just like most GNU packages: run ./configure then make. --marekm ] + + Linux Shadow Password HOWTO + Michael H. Jackson, mhjack@tscnet.com + v1.3, 3 April 1996 + + This document aims to describe how to obtain, install, and configure + the Linux password Shadow Suite. It also discusses obtaining, and + reinstalling other software and network daemons that require access to + user passwords. This other software is not actually part of the + Shadow Suite, but these programs will need to be recompiled to support + the Shadow Suite. This document also contains a programming example + for adding shadow support to a program. Answers to some of the more + frequently asked questions are included near the end of this document. + + 1. Introduction. + + This is the Linux Shadow-Password-HOWTO. This document describes why + and how to add shadow password support on a Linux system. Some + examples of how to use some of the Shadow Suite's features is also + included. + + When installing the Shadow Suite and when using many of the utility + programs, you must be logged in as root. When installing the Shadow + Suite you will be making changes to system software, and it is highly + recommended that you make backup copies of programs as indicated. I + also recommend that you read and understand all the instructions + before you begin. + + 1.1. Changes from the previous release. + + Additions: + Added a sub-section on why you might not want to install shadow + Added a sub-section on updating the xdm program + Added a section on how to put Shadow Suite features to work + Added a section containing frequently asked questions + + Corrections/Updates: + Corrected html references on Sunsite + Corrected section on wu-ftp to reflect adding -lshadow to the Makefile + Corrected minor spelling and verbiage errors + Changed section on wu-ftpd to support ELF + Updated to reflect security problems in various login programs + Updated to recommend the Linux Shadow Suite by Marek Michalkiewicz + + 1.2. New versions of this document. + + The latest released version of this document can always be retrieved + by anonymous FTP from: + + sunsite.unc.edu + + /pub/Linux/docs/HOWTO/Shadow-Password-HOWTO + + or: + + /pub/Linux/docs/HOWTO/other-formats/Shadow-Password-HOWTO{-html.tar,ps,dvi}.gz + + or via the World Wide Web from the Linux Documentation Project Web + Server , at page: Shadow- + Password-HOWTO or directly from me, . It will also be + posted to the newsgroup: comp.os.linux.answers + + This document is now packaged with the Shadow-YYDDMM packages. + + 1.3. Feedback. + + Please send any comments, updates, or suggestions to me: Michael H. + Jackson The sooner I get feedback, the sooner I + can update and correct this document. If you find any problems with + it, please mail me directly as I very rarely stay up-to-date on the + newsgroups. + + 2. Why shadow your passwd file? + + By default, most current Linux distributions do not contain the Shadow + Suite installed. This includes Slackware 2.3, Slackware 3.0, and + other popular distributions. One of the reasons for this is that the + copyright notices in the original Shadow Suite were not clear on + redistribution if a fee was charged. Linux uses a GNU Copyright + (sometimes refereed to as a Copyleft) that allows people to package it + into a convenient package (like a CD-ROM distribution) and charge a + fee for it. + + The current maintainer of the Shadow Suite, Marek Michalkiewicz + received the source code from the + original author under a BSD style copyright that allowed + redistribution. Now that the copyright issues are resolved, it is + expected that future distributions will contain password shadowing by + default. Until then, you will need to install it yourself. + + If you installed your distribution from a CD-ROM, you may find that, + even though the distribution did not have the Shadow Suite installed, + some of the files you need to install the Shadow Suite may be on the + CD-ROM. + + However, Shadow Suite versions 3.3.1, 3.3.1-2, and shadow-mk all have + security problems with their login program and several other suid root + programs that came with them, and should no longer be used. + + All of the necessary files may be obtained via anonymous FTP or + through the World Wide Web. + + On a Linux system without the Shadow Suite installed, user information + including passwords is stored in the /etc/passwd file. The password + is stored in an encrypted format. If you ask a cryptography expert, + however, he or she will tell you that the password is actually in an + encoded rather than encrypted format because when using crypt(3), the + text is set to null and the password is the key. Therefore, from here + on, I will use the term encoded in this document. + + The algorithm used to encode the password field is technically + referred to as a one way hash function. This is an algorithm that is + easy to compute in one direction, but very difficult to calculate in + the reverse direction. More about the actual algorithm used can be + found in section 2.4 or your crypt(3) manual page. + + When a user picks or is assigned a password, it is encoded with a + randomly generated value called the salt. This means that any + particular password could be stored in 4096 different ways. The salt + value is then stored with the encoded password. + + When a user logs in and supplies a password, the salt is first + retrieved from the stored encoded password. Then the supplied + password is encoded with the salt value, and then compared with the + encoded password. If there is a match, then the user is + authenticated. + + It is computationally difficult (but not impossible) to take a + randomly encoded password and recover the original password. However, + on any system with more than just a few users, at least some of the + passwords will be common words (or simple variations of common words). + + System crackers know all this, and will simply encrypt a dictionary of + words and common passwords using all possible 4096 salt values. Then + they will compare the encoded passwords in your /etc/passwd file with + their database. Once they have found a match, they have the password + for another account. This is referred to as a dictionary attack, and + is one of the most common methods for gaining or expanding + unauthorized access to a system. + + If you think about it, an 8 character password encodes to 4096 * 13 + character strings. So a dictionary of say 400,000 common words, + names, passwords, and simple variations would easily fit on a 4GB hard + drive. The attacker need only sort them, and then check for matches. + Since a 4GB hard drive can be had for under $1000.00, this is well + within the means of most system crackers. + + Also, if a cracker obtains your /etc/passwd file first, they only need + to encode the dictionary with the salt values actually contained in + your /etc/passwd file. This method is usable by your average teenager + with a couple of hundred spare Megabytes and a 486 class computer. + + Even without lots of drive space, utilities like crack(1) can usually + break at least a couple of passwords on a system with enough users + (assuming the users of the system are allowed to pick their own + passwords). + + The /etc/passwd file also contains information like user ID's and + group ID's that are used by many system programs. Therefore, the + /etc/passwd file must remain world readable. If you were to change + the /etc/passwd file so that nobody can read it, the first thing that + you would notice is that the ls -l command now displays user ID's + instead of names! + + The Shadow Suite solves the problem by relocating the passwords to + another file (usually /etc/shadow). The /etc/shadow file is set so + that it cannot be read by just anyone. Only root will be able to read + and write to the /etc/shadow file. Some programs (like xlock) don't + need to be able to change passwords, they only need to be able to + verify them. These programs can either be run suid root or you can + set up a group shadow that is allowed read only access to the + /etc/shadow file. Then the program can be run sgid shadow. + + By moving the passwords to the /etc/shadow file, we are effectively + keeping the attacker from having access to the encoded passwords with + which to perform a dictionary attack. + + Additionally, the Shadow Suite adds lots of other nice features: + + · A configuration file to set login defaults (/etc/login.defs) + + · Utilities for adding, modifying, and deleting user accounts and + groups + + · Password aging and expiration + + · Account expiration and locking + + · Shadowed group passwords (optional) + + · Double length passwords (16 character passwords) NOT RECOMMENDED + + · Better control over user's password selection + + · Dial-up passwords + + · Secondary authentication programs NOT RECOMMENDED + + Installing the Shadow Suite contributes toward a more secure system, + but there are many other things that can also be done to improve the + security of a Linux system, and there will eventually be a series of + Linux Security HOWTO's that will discuss other security measures and + related issues. + + For current information on other Linux security issues, including + warnings on known vulnerabilities see the Linux Security home page. + + + 2.1. Why you might NOT want to shadow your passwd file. + + There are a few circumstances and configurations in which installing + the Shadow Suite would NOT be a good idea: + + · The machine does not contain user accounts. + + · Your machine is running on a LAN and is using NIS (Network + Information Services) to get or supply user names and passwords to + other machines on the network. (This can actually be done, but is + beyond the scope of this document, and really won't increase + security much anyway) + + · Your machine is being used by terminal servers to verify users via + NFS (Network File System), NIS, or some other method. + + · Your machine runs other software that validates users, and there is + no shadow version available, and you don't have the source code. + + 2.2. Format of the /etc/passwd file + + A non-shadowed /etc/passwd file has the following format: + + username:passwd:UID:GID:full_name:directory:shell + + Where: + + username + The user (login) name + + passwd + The encoded password + + UID + Numerical user ID + + GID + Numerical default group ID + + full_name + The user's full name - Actually this field is called the GECOS + (General Electric Comprehensive Operating System) field and can + store information other than just the full name. The Shadow + commands and manual pages refer to this field as the comment + field. + + directory + User's home directory (Full pathname) + + shell + User's login shell (Full Pathname) + + For example: + + username:Npge08pfz4wuk:503:100:Full Name:/home/username:/bin/sh + + Where Np is the salt and ge08pfz4wuk is the encoded password. The + encoded salt/password could just as easily have been kbeMVnZM0oL7I and + the two are exactly the same password. There are 4096 possible encod­ + ings for the same password. (The example password in this case is + 'password', a really bad password). + + Once the shadow suite is installed, the /etc/passwd file would instead + contain: + + username:x:503:100:Full Name:/home/username:/bin/sh + + The x in the second field in this case is now just a place holder. + The format of the /etc/passwd file really didn't change, it just no + longer contains the encoded password. This means that any program + that reads the /etc/passwd file but does not actually need to verify + passwords will still operate correctly. + + The passwords are now relocated to the shadow file (usually + /etc/shadow file). + + 2.3. Format of the shadow file + + The /etc/shadow file contains the following information: + + username:passwd:last:may:must:warn:expire:disable:reserved + + Where: + + username + The User Name + + passwd + The Encoded password + last + Days since Jan 1, 1970 that password was last changed + + may + Days before password may be changed + + must + Days after which password must be changed + + warn + Days before password is to expire that user is warned + + expire + Days after password expires that account is disabled + + disable + Days since Jan 1, 1970 that account is disabled + + reserved + A reserved field + + The previous example might then be: + + username:Npge08pfz4wuk:9479:0:10000:::: + + 2.4. Review of crypt(3). + + From the crypt(3) manual page: + + "crypt is the password encryption function. It is based on the Data + Encryption Standard algorithm with variations intended (among other + things) to discourage use of hardware implementations of a key search. + + The key is a user's typed password. The encoded string is all NULLs + + The salt is a two-character string chosen from the set a-zA-Z0-9./. + This string is used to perturb the algorithm in one of 4096 different + ways. + + By taking the lowest 7 bits of each character of the key, a 56-bit key + is obtained. This 56-bit key is used to encrypt repeatedly a constant + string (usually a string consisting of all zeros). The returned value + points to the encrypted password, a series of 13 printable ASCII + characters (the first two characters represent the salt itself). The + return value points to static data whose content is overwritten by + each call. + + Warning: The key space consists of 2**56 equal 7.2e16 possible values. + Exhaustive searches of this key space are possible using massively + parallel computers. Software, such as crack(1), is available which + will search the portion of this key space that is generally used by + humans for passwords. Hence, password selection should, at minimum, + avoid common words and names. The use of a passwd(1) program that + checks for crackable passwords during the selection process is + recommended. + + The DES algorithm itself has a few quirks which make the use of the + crypt(3) interface a very poor choice for anything other than password + authentication. If you are planning on using the crypt(3) interface + for a cryptography project, don't do it: get a good book on encryption + and one of the widely available DES libraries." + + Most Shadow Suites contain code for doubling the length of the + password to 16 characters. Experts in des recommend against this, as + the encoding is simply applied first to the left half and then to the + right half of the longer password. Because of the way crypt works, + this may make for a less secure encoded password then if double length + passwords were not used in the first place. Additionally, it is less + likely that a user will be able to remember a 16 character password. + + There is development work under way that would allow the + authentication algorithm to be replaced with something more secure and + with support for longer passwords (specifically the MD5 algorithm) and + retain compatibility with the crypt method. + + If you are looking for a good book on encryption, I recommend: + + "Applied Cryptography: Protocols, Algorithms, and Source Code in C" + by Bruce Schneier + ISBN: 0-471-59756-2 + + 3. Getting the Shadow Suite. + + 3.1. History of the Shadow Suite for Linux + + DO NOT USE THE PACKAGES IN THIS SECTION, THEY HAVE SECURITY PROBLEMS + + The original Shadow Suite was written by Julianne F. Haugh + + There are several versions that have been used on Linux systems: + + · shadow-3.3.1 is the original. + + · shadow-3.3.1-2 is Linux specific patch made by Florian La Roche + and contains some further enhancements. + + · shadow-mk was specifically packaged for Linux. + + The shadow-mk package contains the shadow-3.3.1 package distributed by + Julianne F. Haugh with the shadow-3.3.1-2 patch installed, a few fixes + made by Mohan Kokal that make installation a lot + easier, a patch by Joseph R.M. Zbiciak for login1.c (login.secure) + that eliminates the -f, -h security holes in /bin/login, and some + other miscellaneous patches. + + The shadow.mk package was the previously recommended package, but + should be replaced due to a security problem with the login program. + + There are security problems with Shadow versions 3.3.1, 3.3.1-2, and + shadow-mk involving the login program. This login bug involves not + checking the length of a login name. This causes the buffer to + overflow causing crashes or worse. It has been rumored that this + buffer overflow can allow someone with an account on the system to use + this bug and the shared libraries to gain root access. I won't + discuss exactly how this is possible because there are a lot of Linux + systems that are affected, but systems with these Shadow Suites + installed, and most pre-ELF distributions without the Shadow Suite are + vulnerable! + + For more information on this and other Linux security issues, see the + Linux Security home page (Shared Libraries and login Program + Vulnerability) + + 3.2. Where to get the Shadow Suite. + + The only recommended Shadow Suite is still in BETA testing, however + the latest versions are safe in a production environment and don't + contain a vulnerable login program. + + The package uses the following naming convention: + + shadow-YYMMDD.tar.gz + + where YYMMDD is the issue date of the Suite. + + This version will eventually be Version 3.3.3 when it is released from + Beta testing, and is maintained by Marek Michalkiewicz + . It's available as: shadow- + current.tar.gz + . + + The following mirror sites have also been established: + + · ftp://ftp.icm.edu.pl/pub/Linux/shadow/shadow-current.tar.gz + + · ftp://iguana.hut.fi/pub/linux/shadow/shadow-current.tar.gz + + · ftp://ftp.cin.net/usr/ggallag/shadow/shadow-current.tar.gz + + · ftp://ftp.netural.com/pub/linux/shadow/shadow-current.tar.gz + + You should use the currently available version. + + You should NOT use a version older than shadow-960129 as they also + have the login security problem discussed above. + + When this document refers to the Shadow Suite I am referring to the + this package. It is assumed that this is the package that you are + using. + + For reference, I used shadow-960129 to make these installation + instructions. + + If you were previously using shadow-mk, you should upgrade to this + version and rebuild everything that you originally compiled. + + 3.3. What is included with the Shadow Suite. + + The Shadow Suite contains replacement programs for: + + su, login, passwd, newgrp, chfn, chsh, and id + + The package also contains the new programs: + + chage, newusers, dpasswd, gpasswd, useradd, userdel, usermod, + groupadd, groupdel, groupmod, groups, pwck, grpck, lastlog, pwconv, + and pwunconv + + Additionally, the library: libshadow.a is included for writing and/or + compiling programs that need to access user passwords. + + Also, manual pages for the programs are also included. + + There is also a configuration file for the login program which will be + installed as /etc/login.defs. + + 4. Compiling the programs. + + 4.1. Unpacking the archive. + + The first step after retrieving the package is unpacking it. The + package is in the tar (tape archive) format and compressed using gzip, + so first move it to /usr/src, then type: + + tar -xzvf shadow-current.tar.gz + + This will unpack it into the directory: /usr/src/shadow-YYMMDD + + 4.2. Configuring with the config.h file + + The first thing that you need to do is to copy over the Makefile and + the config.h file: + + cd /usr/src/shadow-YYMMDD + cp Makefile.linux Makefile + cp config.h.linux config.h + + You should then take a look at the config.h file. This file contains + definitions for some of the configuration options. If you are using + the recommended package, I recommend that you disable group shadow + support for your first time around. + + By default shadowed group passwords are enabled. To disable these + edit the config.h file, and change the #define SHADOWGRP to #undef + SHADOWGRP. I recommend that you disable them to start with, and then + if you really want group passwords and group administrators that you + enable it later and recompile. If you leave it enabled, you must + create the file /etc/gshadow. + + Enabling the long passwords option is NOT recommended as discussed + above. + + Do NOT change the setting: #undef AUTOSHADOW + + The AUTOSHADOW option was originally designed so that programs that + were shadow ignorant would still function. This sounds good in + theory, but does not work correctly. If you enable this option, and + the program runs as root, it may call getpwnam() as root, and later + write the modified entry back to the /etc/passwd file (with the no- + longer-shadowed password). Such programs include chfn and chsh. (You + can't get around this by swapping real and effective uid before + calling getpwnam() because root may use chfn and chsh too.) + + The same warning is also valid if you are building libc, it has a + SHADOW_COMPAT option which does the same thing. It should NOT be + used! If you start getting encoded passwords back in your /etc/passwd + file, this is the problem. + + If you are using a libc version prior to 4.6.27, you will need to make + a couple more changes to config.h and the Makefile. To config.h edit + and change: + + #define HAVE_BASENAME + + to: + + #undef HAVE_BASENAME + + And then in the Makefile, change: + + SOBJS = smain.o env.o entry.o susetup.o shell.o \ + sub.o mail.o motd.o sulog.o age.o tz.o hushed.o + + SSRCS = smain.c env.c entry.c setup.c shell.c \ + pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \ + tz.c hushed.c + + SOBJS = smain.o env.o entry.o susetup.o shell.o \ + sub.o mail.o motd.o sulog.o age.o tz.o hushed.o basename.o + + SSRCS = smain.c env.c entry.c setup.c shell.c \ + pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \ + tz.c hushed.c basename.c + + These changes add the code contained in basename.c which is contained + in libc 4.6.27 and later. + + 4.3. Making backup copies of your original programs. + + It would also be a good idea to track down and make backup copies of + the programs that the shadow suite will replace. On a Slackware 3.0 + system these are: + + · /bin/su + + · /bin/login + + · /usr/bin/passwd + + · /usr/bin/newgrp + + · /usr/bin/chfn + + · /usr/bin/chsh + + · /usr/bin/id + + The BETA package has a save target in the Makefile, but it's commented + out because different distributions place the programs in different + places. + + You should also make a backup copy of your /etc/passwd file, but be + careful to name it something else if you place it in the same + directory so you don't overwrite the passwd command. + + 4.4. Running make + + You need to be logged as root to do most of the installation. + + Run make to compile the executables in the package: + + make all + + You may see the warning: rcsid defined but not used. This is fine, it + just happens because the author is using a version control package. + + 5. Installing + + 5.1. Have a boot disk handy in case you break anything. + + If something goes terribly wrong, it would be handy to have a boot + disk. If you have a boot/root combination from your installation, + that will work, otherwise see the Bootdisk-HOWTO + , which + describes how to make a bootable disk. + + 5.2. Removing duplicate man pages + + You should also move the manual pages that are about to be replaced. + Even if you are brave enough install the Shadow Suite without making + backups, you will still want to remove the old manual pages. The new + manual pages won't normally overwrite the old ones because the old + ones are probably compressed. + + You can use a combination of: man -aW command and locate command to + locate the manual pages that need to be (re)moved. It's generally + easier to figure out which are the older pages before you run make + install. + + If you are using the Slackware 3.0 distribution, then the manual pages + you want to remove are: + + · /usr/man/man1/chfn.1.gz + + · /usr/man/man1/chsh.1.gz + + · /usr/man/man1/id.1.gz + + · /usr/man/man1/login.1.gz + + · /usr/man/man1/passwd.1.gz + + · /usr/man/man1/su.1.gz + + · /usr/man/man5/passwd.5.gz + + There may also be man pages of the same name in the /var/man/cat[1-9] + subdirectories that should also be deleted. + + 5.3. Running make install + + You are now ready to type: (do this as root) + + make install + + This will install the new and replacement programs and fix-up the file + permissions. It will also install the man pages. + + This also takes care of installing the Shadow Suite include files in + the correct places in /usr/include/shadow. + + Using the BETA package you must manually copy the file login.defs to + the /etc subdirectory and make sure that only root can make changes to + it. + + cp login.defs /etc + chmod 700 /etc/login.defs + + This file is the configuration file for the login program. You should + review and make changes to this file for your particular system. This + is where you decide which tty's root can login from, and set other + security policy settings (like password expiration defaults). + + 5.4. Running pwconv + + The next step is to run pwconv. This must also be done as root, and + is best done from the /etc subdirectory: + + cd /etc + /usr/sbin/pwconv + + pwconv takes your /etc/passwd file and strips out the fields to create + two files: /etc/npasswd and /etc/nshadow. + + A pwunconv program is also provided if you need to make a normal + /etc/passwd file out of an /etc/passwd and /etc/shadow combination. + + 5.5. Renaming npasswd and nshadow + + Now that you have run pwconv you have created the files /etc/npasswd + and /etc/nshadow. These need to be copied over to /etc/passwd and + /etc/shadow. We also want to make a backup copy of the original + /etc/passwd file, and make sure only root can read it. We'll put the + backup in root's home directory: + + cd /etc + cp passwd ~passwd + chmod 600 ~passwd + mv npasswd passwd + mv nshadow shadow + + You should also ensure that the file ownerships and permissions are + correct. If you are going to be using X-Windows, the xlock and xdm + programs need to be able to read the shadow file (but not write it). + + There are two ways that this can be done. You can set xlock to suid + root (xdm is usually run as root anyway). Or you can make the shadow + file owned by root with a group of shadow, but before you do this, + make sure that you have a shadow group (look in /etc/group). None of + the users on the system should actually be in the shadow group. + + chown root.root passwd + chown root.shadow shadow + chmod 0644 passwd + chmod 0640 shadow + + Your system now has the password file shadowed. You should now pop + over to another virtual terminal and verify that you can login. + + Really, do this now! + + If you can't, then something is wrong! To get back to a non-shadowed + state, do the following the following: + + cd /etc + cp ~passwd passwd + chmod 644 passwd + + You would then restore the files that you saved earlier to their + proper locations. + + 6. Other programs you may need to upgrade or patch + + Even though the shadow suite contains replacement programs for most + programs that need to access passwords, there are a few additional + programs on most systems that require access to passwords. + + If you are running a Debian Distribution (or even if you are not), you + can obtain Debian sources for the programs that need to be rebuild + from: ftp://ftp.debian.org/debian/stable/source/ + + The remainder of this section discusses how to upgrade adduser, + wu_ftpd, ftpd, pop3d, xlock, xdm and sudo so that they support the + shadow suite. + + See the section ``Adding Shadow Support to a C program'' for a + discussion on how to put shadow support into any other program that + needs it (although the program must then be run SUID root or SGID + shadow to be able to actually access the shadow file). + + 6.1. Slackware adduser program + + Slackware distributions (and possibly some others) contain a + interactive program for adding users called /sbin/adduser. A shadow + version of this program can be obtained from + ftp://sunsite.unc.edu/pub/Linux/ + system/Admin/accounts/adduser.shadow-1.4.tar.gz. + + I would encourage you to use the programs that are supplied with the + Shadow Suite (useradd, usermod, and userdel) instead of the slackware + adduser program. They take a little time to learn how to use, but + it's well worth the effort because you have much more control and they + perform proper file locking on the /etc/passwd and /etc/shadow file + (adduser doesn't). + + See the section on ``Putting the Shadow Suite to use'' for more + information. + + But if you gotta have it, here is what you do: + + tar -xzvf adduser.shadow-1.4.tar.gz + cd adduser + make clean + make adduser + chmod 700 adduser + cp adduser /sbin + + 6.2. The wu_ftpd Server + + Most Linux systems some with the wu_ftpd server. If your distribution + does not come with shadow installed, then your wu_ftpd will not be + compiled for shadow. wu_ftpd is launched from inetd/tcpd as a root + process. If you are running an old wu_ftpd daemon, you will want to + upgrade it anyway because older ones had a bug that would allow the + root account to be compromised (For more info see the Linux security + home page ). + + Fortunately, you only need to get the source code and recompile it + with shadow enabled. + + If you are not running an ELF system, The wu_ftp server can be found + on Sunsite as wu-ftp-2.4-fixed.tar.gz + + + Once you retrieve the server, put it in /usr/src, then type: + + cd /usr/src + tar -xzvf wu-ftpd-2.4-fixed.tar.gz + cd wu-ftpd-2.4-fixed + cp ./src/config/config.lnx.shadow ./src/config/config.lnx + + Then edit ./src/makefiles/Makefile.lnx, and change the line: + + LIBES = -lbsd -support + + to: + + LIBES = -lbsd -support -lshadow + + Now you are ready to run the build script and install: + + cd /usr/src/wu-ftpd-2.4-fixed + /usr/src/wu-ftp-2.4.fixed/build lnx + cp /usr/sbin/wu.ftpd /usr/sbin/wu.ftpd.old + cp ./bin/ftpd /usr/sbin/wu.ftpd + + This uses the Linux shadow configuration file, compiles and installs + the server. + + On my Slackware 2.3 system I also had to do the following before + running build: + + cd /usr/include/netinet + ln -s in_systm.h in_system.h + cd - + + Problems have been reported compiling this package under ELF systems, + but the Beta version of the next release works fine. It can be found + as wu-ftp-2.4.2-beta-10.tar.gz + + + Once you retrieve the server, put it in /usr/src, then type: + + cd /usr/src + tar -xzvf wu-ftpd-2.4.2-beta-9.tar.gz + cd wu-ftpd-beta-9 + cd ./src/config + + Then edit config.lnx, and change: + + #undef SHADOW.PASSWORD + + to: + + #define SHADOW.PASSWORD + + Then, + + cd ../Makefiles + + and edit the file Makefile.lnx and change: + + LIBES = -lsupport -lbsd # -lshadow + + to: + + LIBES = -lsupport -lbsd -lshadow + + Then build and install: + + cd .. + build lnx + cp /usr/sbin/wu.ftpd /usr/sbin/wu.ftpd.old + cp ./bin/ftpd /usr/sbin/wu.ftpd + + Note that you should check your /etc/inetd.conf file to make sure that + this is where your wu.ftpd server really lives. It has been reported + that some distributions place the server daemons in different places, + and then wu.ftpd in particular may be named something else. + + 6.3. Standard ftpd + + If you are running the standard ftpd server, I would recommend that + you upgrade to the wu_ftpd server. Aside from the known bug discussed + above, it's generally thought to be more secure. + + If you insist on the standard one, or you need NIS support, Sunsite + has ftpd-shadow-nis.tgz + + + 6.4. pop3d (Post Office Protocol 3) + + If you need to support the third Post Office Protocol (POP3), you will + need to recompile a pop3d program. pop3d is normally run by + inetd/tcpd as root. + + There are two versions available from Sunsite: + pop3d-1.00.4.linux.shadow.tar.gz + + and pop3d+shadow+elf.tar.gz + + + Both of these are fairly straight forward to install. + + 6.5. xlock + + If you install the shadow suite, and then run X Windows System and + lock the screen without upgrading your xlock, you will have to use + CNTL-ALT-Fx to switch to another tty, login, and kill the xlock + process (or use CNTL-ALT-BS to kill the X server). Fortunately it's + fairly easy to upgrade your xlock program. + + If you are running XFree86 Versions 3.x.x, you are probably using + xlockmore (which is a great screen-saver in addition to a lock). This + package supports shadow with a recompile. If you have an older xlock, + I recommend that you upgrade to this one. + + xlockmore-3.5.tgz is available at: + + + Basically, this is what you need to do: + + Get the xlockmore-3.7.tgz file and put it in /usr/src unpack it: + + tar -xzvf xlockmore-3.7.tgz + + Edit the file: /usr/X11R6/lib/X11/config/linux.cf, and change the + line: + + #define HasShadowPasswd NO + + to + + #define HasShadowPasswd YES + + Then build the executables: + + cd /usr/src/xlockmore + xmkmf + make depend + make + + Then move everything into place and update file ownerships and + permissions: + + cp xlock /usr/X11R6/bin/ + cp XLock /var/X11R6/lib/app-defaults/ + chown root.shadow /usr/X11R6/bin/xlock + chmod 2755 /usr/X11R6/bin/xlock + chown root.shadow /etc/shadow + chmod 640 /etc/shadow + + Your xlock will now work correctly. + + 6.6. xdm + + xdm is a program that presents a login screen for X-Windows. Some + systems start xdm when the system is told to goto a specified run + level (see /etc/inittab. + + With the Shadow Suite install, xdm will need to be updated. + Fortunately it's fairly easy to upgrade your xdm program. + + xdm.tar.gz is available at: + + + Get the xdm.tar.gz file and put it in /usr/src, then to unpack it: + + tar -xzvf xdm.tar.gz + + Edit the file: /usr/X11R6/lib/X11/config/linux.cf, and change the + line: + + #define HasShadowPasswd NO + + to + + #define HasShadowPasswd YES + + Then build the executables: + + cd /usr/src/xdm + xmkmf + make depend + make + + Then move everything into place: + + cp xdm /usr/X11R6/bin/ + + xdm is run as root so you don't need to change it file permissions. + + 6.7. sudo + + The program sudo allows a system administrator to let users run + programs that would normally require root access. This is handy + because it lets the administrator limit access to the root account + itself while still allowing users to do things like mounting drives. + + sudo needs to read passwords because it verifies the users password + when it's invoked. sudo already runs SUID root, so accessing the + /etc/shadow file is not a problem. + + sudo for the shadow suite, is available as at: + + + Warning: When you install sudo your /etc/sudoers file will be replaced + with a default one, so you need to make a backup of it if you have + added anything to the default one. (you could also edit the Makefile + and remove the line that copies the default file to /etc). + + The package is already setup for shadow, so all that's required is to + recompile the package (put it in /usr/src): + + cd /usr/src + tar -xzvf sudo-1.2-shadow.tgz + cd sudo-1.2-shadow + make all + make install + + 6.8. imapd (E-Mail pine package) + + imapd is an e-mail server similar to pop3d. imapd comes with the Pine + E-mail package. The documentation that comes with the package states + that the default for Linux systems is to include support for shadow. + However, I have found that this is not true. Furthermore, the build + script / Makefile combination on this package is makes it very + difficult to add the libshadow.a library at compile time, so I was + unable to add shadow support for imapd. + + If anyone has this figured out, please E-mail me, and I'll include the + solution here. + + 6.9. pppd (Point-to-Point Protocol Server) + + The pppd server can be setup to use several types of authentication: + Password Authentication Protocol (PAP) and Cryptographic Handshake + Authentication Protocol (CHAP). The pppd server usually reads the + password strings that it uses from /etc/ppp/chap-secrets and/or + /etc/ppp/pap-secrets. If you are using this default behavior of pppd, + it is not necessary to reinstall pppd. + + pppd also allows you to use the login parameter (either on the command + line, or in the configuration or options file). If the login option + is given, then pppd will use the /etc/passwd file for the username and + passwords for the PAP. This, of course, will no longer work now that + our password file is shadowed. For pppd-1.2.1d this requires adding + code for shadow support. + + The example given in the next section is adding shadow support to + pppd-1.2.1d (an older version of pppd). + + pppd-2.2.0 already contains shadow support. + + 7. Putting the Shadow Suite to use. + + This section discusses some of the things that you will want to know + now that you have the Shadow Suite installed on your system. More + information is contained in the manual pages for each command. + + 7.1. Adding, Modifying, and deleting users + + The Shadow Suite added the following command line oriented commands + for adding, modifying, and deleting users. You may also have + installed the adduser program. + + 7.1.1. useradd + + The useradd command can be used to add users to the system. You also + invoke this command to change the default settings. + + The first thing that you should do is to examine the default settings + and make changes specific to your system: + + useradd -D + + ______________________________________________________________________ + GROUP=1 + HOME=/home + INACTIVE=0 + EXPIRE=0 + SHELL= + SKEL=/etc/skel + ______________________________________________________________________ + + The defaults are probably not what you want, so if you started adding + users now you would have to specify all the information for each user. + However, we can and should change the default values. + + On my system: + + · I want the default group to be 100 + + · I want passwords to expire every 60 days + + · I don't want to lock an account because the password is expired + + · I want to default shell to be /bin/bash + + To make these changes I would use: + + useradd -D -g100 -e60 -f0 -s/bin/bash + + Now running useradd -D will give: + + ______________________________________________________________________ + GROUP=100 + HOME=/home + INACTIVE=0 + EXPIRE=60 + SHELL=/bin/bash + SKEL=/etc/skel + ______________________________________________________________________ + + Just in case you wanted to know, these defaults are stored in the file + /etc/default/useradd. + + Now you can use useradd to add users to the system. For example, to + add the user fred, using the defaults, you would use the following: + + useradd -m -c "Fred Flintstone" fred + + This will create the following entry in the /etc/passwd file: + + fred:*:505:100:Fred Flintstone:/home/fred:/bin/bash + + And the following entry in the /etc/shadow file: + + fred:!:0:0:60:0:0:0:0 + + fred's home directory will be created and the contents of /etc/skel + will be copied there because of the -m switch. + + Also, since we did not specify a UID, the next available one was used. + + fred's account is created, but fred still won't be able to login until + we unlock the account. We do this by changing the password. + + passwd fred + + ______________________________________________________________________ + Changing password for fred + Enter the new password (minimum of 5 characters) + Please use a combination of upper and lower case letters and numbers. + New Password: ******* + Re-enter new password: ******* + ______________________________________________________________________ + + Now the /etc/shadow will contain: + + fred:J0C.WDR1amIt6:9559:0:60:0:0:0:0 + + And fred will now be able to login and use the system. The nice thing + about useradd and the other programs that come with the Shadow Suite + is that they make changes to the /etc/passwd and /etc/shadow files + atomically. So if you are adding a user, and another user is changing + their password at the same time, both operations will be performed + correctly. + + You should use the supplied commands rather than directly editing + /etc/passwd and /etc/shadow. If you were editing the /etc/shadow + file, and a user were to change his password while you are editing, + and then you were to save the file you were editing, the user's + password change would be lost. + + Here is a small interactive script that adds users using useradd and + passwd: + + ______________________________________________________________________ + #!/bin/bash + # + # /sbin/newuser - A script to add users to the system using the Shadow + # Suite's useradd and passwd commands. + # + # Written my Mike Jackson as an example for the Linux + # Shadow Password Howto. Permission to use and modify is expressly granted. + # + # This could be modified to show the defaults and allow modification similar + # to the Slackware Adduser program. It could also be modified to disallow + # stupid entries. (i.e. better error checking). + # + ## + # Defaults for the useradd command + ## + GROUP=100 # Default Group + HOME=/home # Home directory location (/home/username) + SKEL=/etc/skel # Skeleton Directory + INACTIVE=0 # Days after password expires to disable account (0=never) + EXPIRE=60 # Days that a passwords lasts + SHELL=/bin/bash # Default Shell (full path) + ## + # Defaults for the passwd command + ## + PASSMIN=0 # Days between password changes + PASSWARN=14 # Days before password expires that a warning is given + ## + # Ensure that root is running the script. + ## + WHOAMI=`/usr/bin/whoami` + if [ $WHOAMI != "root" ]; then + echo "You must be root to add news users!" + exit 1 + fi + ## + # Ask for username and fullname. + ## + echo "" + echo -n "Username: " + read USERNAME + echo -n "Full name: " + read FULLNAME + # + echo "Adding user: $USERNAME." + # + # Note that the "" around $FULLNAME is required because this field is + # almost always going to contain at least on space, and without the "'s + # the useradd command would think that you we moving on to the next + # parameter when it reached the SPACE character. + # + /usr/sbin/useradd -c"$FULLNAME" -d$HOME/$USERNAME -e$EXPIRE \ + -f$INACTIVE -g$GROUP -m -k$SKEL -s$SHELL $USERNAME + ## + # Set password defaults + ## + /bin/passwd -n $PASSMIN -w $PASSWARN $USERNAME >/dev/null 2>&1 + ## + # Let the passwd command actually ask for password (twice) + ## + /bin/passwd $USERNAME + ## + # Show what was done. + ## + echo "" + echo "Entry from /etc/passwd:" + echo -n " " + grep "$USERNAME:" /etc/passwd + echo "Entry from /etc/shadow:" + echo -n " " + grep "$USERNAME:" /etc/shadow + echo "Summary output of the passwd command:" + echo -n " " + passwd -S $USERNAME + echo "" + ______________________________________________________________________ + + Using a script to add new users is really much more preferable than + editing the /etc/passwd or /etc/shadow files directly or using a + program like the Slackware adduser program. Feel free to use and + modify this script for your particular system. + + For more information on the useradd see the online manual page. + + 7.1.2. usermod + + The usermod program is used to modify the information on a user. The + switches are similar to the useradd program. + + Let's say that you want to change fred's shell, you would do the + following: + + usermod -s /bin/tcsh fred + + Now fred's /etc/passwd file entry would be change to this: + + fred:*:505:100:Fred Flintstone:/home/fred:/bin/tcsh + + Let's make fred's account expire on 09/15/97: + + usermod -e 09/15/97 fred + + Now fred's entry in /etc/shadow becomes: + + fred:J0C.WDR1amIt6:9559:0:60:0:0:10119:0 + + For more information on the usermod command see the online manual + page. + + 7.1.3. userdel + + userdel does just what you would expect, it deletes the user's + account. You simply use: + + userdel -r username + + The -r causes all files in the user's home directory to be removed + along with the home directory itself. Files located in other file + system will have to be searched for and deleted manually. + + If you want to simply lock the account rather than delete it, use the + passwd command instead. + + 7.2. The passwd command and passwd aging. + + The passwd command has the obvious use of changing passwords. + Additionally, it is used by the root user to: + + · Lock and unlock accounts (-l and -u) + + · Set the maximum number of days that a password remains valid (-x) + + · Set the minimum days between password changes (-n) + + · Sets the number of days of warning that a password is about to + expire (-w) + + · Sets the number of days after the password expires before the + account is locked (-i) + + · Allow viewing of account information in a clearer format (-S) + + For example, let look again at fred + + passwd -S fred + fred P 03/04/96 0 60 0 0 + + This means that fred's password is valid, it was last changed on + 03/04/96, it can be changed at any time, it expires after 60 days, + fred will not be warned, and and the account won't be disabled when + the password expires. + + This simply means that if fred logs in after the password expires, he + will be prompted for a new password at login. + + If we decide that we want to warn fred 14 days before his password + expires and make his account inactive 14 days after he lets it expire, + we would need to do the following: + + passwd -w14 -i14 fred + + Now fred is changed to: + fred P 03/04/96 0 60 14 14 + + For more information on the passwd command see the online manual page. + + 7.3. The login.defs file. + + The file /etc/login is the configuration file for the login program + and also for the Shadow Suite as a whole. + + /etc/login contains settings from what the prompts will look like to + what the default expiration will be when a user changes his password. + + The /etc/login.defs file is quite well documented just by the comments + that are contained within it. However, there are a few things to + note: + + · It contains flags that can be turned on or off that determine the + amount of logging that takes place. + + · It contains pointers to other configuration files. + + · It contains defaults assignments for things like password aging. + + From the above list you can see that this is a rather important file, + and you should make sure that it is present, and that the settings are + what you desire for your system. + + 7.4. Group passwords. + + The /etc/groups file may contain passwords that permit a user to + become a member of a particular group. This function is enabled if + you define the constant SHADOWGRP in the /usr/src/shadow- + YYMMDD/config.h file. + + If you define this constant and then compile, you must create an + /etc/gshadow file to hold the group passwords and the group + administrator information. + + When you created the /etc/shadow, you used a program called pwconv, + there no equivalent program to create the /etc/gshadow file, but it + really doesn't matter, it takes care of itself. + + To create the initial /etc/gshadow file do the following: + + touch /etc/gshadow + chown root.root /etc/gshadow + chmod 700 /etc/gshadow + + Once you create new groups, they will be added to the /etc/group and + the /etc/gshadow files. If you modify a group by adding or removing + users or changing the group password, the /etc/gshadow file will be + changed. + + The programs groups, groupadd, groupmod, and groupdel are provided as + part of the Shadow Suite to modify groups. + + The format of the /etc/group file is as follows: + + groupname:!:GID:member,member,... + + Where: + + groupname + The name of the group + + ! The field that normally holds the password, but that is now + relocated to the /etc/gshadow file. + + GID + The numerical group ID number + + member + List of group members + + The format of the /etc/gshadow file is as follows: + + groupname:password:admin,admin,...:member,member,... + + Where: + + groupname + The name of the group + + password + The encoded group password. + + admin + List of group administrators + + member + List of group members + + The command gpasswd is used only for adding or removing administrators + and members to or from a group. root or someone in the list of + administrators may add or remove group members. + + The groups password can be changed using the passwd command by root or + anyone listed as an administrator for the group. + + Despite the fact that there is not currently a manual page for + gpasswd, typing gpasswd without any parameters gives a listing of + options. It's fairly easy to grasp how it all works once you + understand the file formats and the concepts. + + 7.5. Consistency checking programs + + 7.5.1. pwck + + The program pwck is provided to provide a consistency check on the + /etc/passwd and /etc/shadow files. It will check each username and + verify that it has the following: + + · the correct number of fields + + · unique user name + + · valid user and group identifier + + · valid primary group + + · valid home directory + + · valid login shell + + It will also warn of any account that has no password. + + It's a good idea to run pwck after installing the Shadow Suite. It's + also a good idea to run it periodically, perhaps weekly or monthly. + If you use the -r option, you can use cron to run it on a regular + basis and have the report mailed to you. + + 7.5.2. grpck + + grpck is the consistency checking program for the /etc/group and + /etc/gshadow files. It performs the following checks: + + · the correct number of fields + + · unique group name + + · valid list of members and administrators + + It also has the -r option for automated reports. + + 7.6. Dial-up passwords. + + Dial-up passwords are another optional line of defense for systems + that allow dial-in access. If you have a system that allows many + people to connect locally or via a network, but you want to limit who + can dial in and connect, then dial-up passwords are for you. To + enable dial-up passwords, you must edit the file /etc/login.defs and + ensure that DIALUPS_CHECK_ENAB is set to yes. + + Two files contain the dial-up information, /etc/dialups which contains + the ttys (one per line, with the leading "/dev/" removed). If a tty + is listed then dial-up checks are performed. + + The second file is the /etc/d_passwd file. This file contains the + fully qualified path name of a shell, followed by an optional + password. + + If a user logs into a line that is listed in /etc/dialups, and his + shell is listed in the file /etc/d_passwd he will be allowed access + only by suppling the correct password. + + Another useful purpose for using dial-up passwords might be to setup a + line that only allows a certain type of connect (perhaps a PPP or UUCP + connection). If a user tries to get another type of connection (i.e. + a list of shells), he must know a password to use the line. + + Before you can use the dial-up feature, you must create the files. + + The command dpasswd is provided to assign passwords to the shells in + the /etc/d_passwd file. See the manual page for more information. + 8. Adding shadow support to a C program + + Adding shadow support to a program is actually fairly straightforward. + The only problem is that the program must be run by root (or SUID + root) in order for the the program to be able to access the + /etc/shadow file. + + This presents one big problem: very careful programming practices must + be followed when creating SUID programs. For instance, if a program + has a shell escape, this must not occur as root if the program is SUID + root. + + For adding shadow support to a program so that it can check passwords, + but otherwise does need to run as root, it's a lot safer to run the + program SUID shadow instead. The xlock program is an example of this. + + In the example given below, pppd-1.2.1d already runs SUID as root, so + adding shadow support should not make the program any more vulnerable. + + 8.1. Header files + + The header files should reside in /usr/include/shadow. There should + also be a /usr/include/shadow.h, but it will be a symbolic link to + /usr/include/shadow/shadow.h. + + To add shadow support to a program, you need to include the header + files: + + #include + #include + + It might be a good idea to use compiler directives to conditionally + compile the shadow code (I do in the example below). + + 8.2. libshadow.a library + + When you installed the Shadow Suite the libshadow.a file was created + and installed in /usr/lib. + + When compiling shadow support into a program, the linker needs to be + told to include the libshadow.a library into the link. + + This is done by: + + gcc program.c -o program -lshadow + + However, as we will see in the example below, most large programs use + a Makefile, and usually have a variable called LIBS=... that we will + modify. + + 8.3. Shadow Structure + + The libshadow.a library uses a structure called spwd for the + information it retrieves from the /etc/shadow file. This is the + definition of the spwd structure from the /usr/include/shadow/shadow.h + header file: + + ______________________________________________________________________ + struct spwd + { + char *sp_namp; /* login name */ + char *sp_pwdp; /* encrypted password */ + sptime sp_lstchg; /* date of last change */ + sptime sp_min; /* minimum number of days between changes */ + sptime sp_max; /* maximum number of days between changes */ + sptime sp_warn; /* number of days of warning before password + expires */ + sptime sp_inact; /* number of days after password expires + until the account becomes unusable. */ + sptime sp_expire; /* days since 1/1/70 until account expires + */ + unsigned long sp_flag; /* reserved for future use */ + }; + ______________________________________________________________________ + + The Shadow Suite can put things into the sp_pwdp field besides just + the encoded passwd. The password field could contain: + + username:Npge08pfz4wuk;@/sbin/extra:9479:0:10000:::: + + This means that in addition to the password, the program /sbin/extra + should be called for further authentication. The program called will + get passed the username and a switch that indicates why it's being + called. See the file /usr/include/shadow/pwauth.h and the source code + for pwauth.c for more information. + + What this means is that we should use the function pwauth to perform + the actual authentication, as it will take care of the secondary + authentication as well. The example below does this. + + The author of the Shadow Suite indicates that since most programs in + existence don't do this, and that it may be removed or changed in + future versions of the Shadow Suite. + + 8.4. Shadow Functions + + The shadow.h file also contains the function prototypes for the + functions contained in the libshadow.a library: + + ______________________________________________________________________ + extern void setspent __P ((void)); + extern void endspent __P ((void)); + extern struct spwd *sgetspent __P ((__const char *__string)); + extern struct spwd *fgetspent __P ((FILE *__fp)); + extern struct spwd *getspent __P ((void)); + extern struct spwd *getspnam __P ((__const char *__name)); + extern int putspent __P ((__const struct spwd *__sp, FILE *__fp)); + ______________________________________________________________________ + + The function that we are going to use in the example is: getspnam + which will retrieve for us a spwd structure for the supplied name. + + 8.5. Example + + This is an example of adding shadow support to a program that needs + it, but does not have it by default. + + This example uses the Point-to-Point Protocol Server (pppd-1.2.1d), + which has a mode in which it performs PAP authentication using user + names and passwords from the /etc/passwd file instead of the PAP or + CHAP files. You would not need to add this code to pppd-2.2.0 because + it's already there. + + This feature of pppd probably isn't used very much, but if you + installed the Shadow Suite, it won't work anymore because the + passwords are no longer stored in /etc/passwd. + + The code for authenticating users under pppd-1.2.1d is located in the + /usr/src/pppd-1.2.1d/pppd/auth.c file. + + The following code needs to be added to the top of the file where all + the other #include directives are. We have surrounded the #includes + with conditional directives (i.e. only include if we are compiling for + shadow support). + + ______________________________________________________________________ + #ifdef HAS_SHADOW + #include + #include + #endif + ______________________________________________________________________ + + The next thing to do is to modify the actual code. We are still + making changes to the auth.c file. + + Function auth.c before modifications: + + ______________________________________________________________________ + /* + * login - Check the user name and password against the system + * password database, and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Login failed. + * UPAP_AUTHACK: Login succeeded. + * In either case, msg points to an appropriate message. + */ + static int + login(user, passwd, msg, msglen) + char *user; + char *passwd; + char **msg; + int *msglen; + { + struct passwd *pw; + char *epasswd; + char *tty; + + if ((pw = getpwnam(user)) == NULL) { + return (UPAP_AUTHNAK); + } + /* + * XXX If no passwd, let them login without one. + */ + if (pw->pw_passwd == '\0') { + return (UPAP_AUTHACK); + } + + epasswd = crypt(passwd, pw->pw_passwd); + if (strcmp(epasswd, pw->pw_passwd)) { + return (UPAP_AUTHNAK); + } + + syslog(LOG_INFO, "user %s logged in", user); + + /* + * Write a wtmp entry for this user. + */ + tty = strrchr(devname, '/'); + if (tty == NULL) + tty = devname; + else + tty++; + logwtmp(tty, user, ""); /* Add wtmp login entry */ + logged_in = TRUE; + + return (UPAP_AUTHACK); + } + ______________________________________________________________________ + + The user's password is placed into pw->pw_passwd, so all we really + need to do is add the function getspnam. This will put the password + into spwd->sp_pwdp. + + We will add the function pwauth to perform the actual authentication. + This will automatically perform secondary authentication if the shadow + file is setup for it. + + Function auth.c after modifications to support shadow: + + ______________________________________________________________________ + /* + * login - Check the user name and password against the system + * password database, and login the user if OK. + * + * This function has been modified to support the Linux Shadow Password + * Suite if USE_SHADOW is defined. + * + * returns: + * UPAP_AUTHNAK: Login failed. + * UPAP_AUTHACK: Login succeeded. + * In either case, msg points to an appropriate message. + */ + static int + login(user, passwd, msg, msglen) + char *user; + char *passwd; + char **msg; + int *msglen; + { + struct passwd *pw; + char *epasswd; + char *tty; + + #ifdef USE_SHADOW + struct spwd *spwd; + struct spwd *getspnam(); + #endif + + if ((pw = getpwnam(user)) == NULL) { + return (UPAP_AUTHNAK); + } + + #ifdef USE_SHADOW + spwd = getspnam(user); + if (spwd) + pw->pw_passwd = spwd->sp-pwdp; + #endif + + /* + * XXX If no passwd, let NOT them login without one. + */ + if (pw->pw_passwd == '\0') { + return (UPAP_AUTHNAK); + } + #ifdef HAS_SHADOW + if ((pw->pw_passwd && pw->pw_passwd[0] == '@' + && pw_auth (pw->pw_passwd+1, pw->pw_name, PW_LOGIN, NULL)) + || !valid (passwd, pw)) { + return (UPAP_AUTHNAK); + } + #else + epasswd = crypt(passwd, pw->pw_passwd); + if (strcmp(epasswd, pw->pw_passwd)) { + return (UPAP_AUTHNAK); + } + #endif + + syslog(LOG_INFO, "user %s logged in", user); + + /* + * Write a wtmp entry for this user. + */ + tty = strrchr(devname, '/'); + if (tty == NULL) + tty = devname; + else + tty++; + logwtmp(tty, user, ""); /* Add wtmp login entry */ + logged_in = TRUE; + + return (UPAP_AUTHACK); + } + ______________________________________________________________________ + + Careful examination will reveal that we made another change as well. + The original version allowed access (returned UPAP_AUTHACK if there + was NO password in the /etc/passwd file. This is not good, because a + common use of this login feature is to use one account to allow access + to the PPP process and then check the username and password supplied + by PAP with the username in the /etc/passwd file and the password in + the /etc/shadow file. + + So if we had set the original version up to run as the shell for a + user i.e. ppp, then anyone could get a ppp connection by setting + their PAP to user ppp and a password of null. + + We fixed this also by returning UPAP_AUTHNAK instead of UPAP_AUTHACK + if the password field was empty. + + Interestingly enough, pppd-2.2.0 has the same problem. + + Next we need to modify the Makefile so that two things occur: + USE_SHADOW must be defined, and libshadow.a needs to be added to the + linking process. + + Edit the Makefile, and add: + + LIBS = -lshadow + + Then we find the line: + + COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t + + And change it to: + + COMPILE_FLAGS = -I.. -D_linux_=1 -DGIDSET_TYPE=gid_t -DUSE_SHADOW + + Now make and install. + + 9. Frequently Asked Questions. + + Q: I used to control which tty's root could log into using the file + /etc/securettys, but it doesn't seem to work anymore, what's going on? + + A: The file /etc/securettys does absolutely nothing now that the + Shadow Suite is installed. The tty's that root can use are now + located in the login configuration file /etc/login.defs. The entry in + this file may point to another file. + + Q: I installed the Shadow Suite, but now I can't login, what did I + miss? + + A: You probably installed the Shadow programs, but didn't run pwconv + or you forgot to copy /etc/npasswd to /etc/passwd and /etc/nshadow to + /etc/shadow. Also, you may need to copy login.defs to /etc. + + Q: In the section on xlock, it said to change the group ownership of + the /etc/shadow file to shadow. I don't have a shadow group, what do + I do? + + A: You can add one. Simply edit the /etc/group file, and insert a + line for the shadow group. You need to ensure that the group number + is not used by another group, and you need to insert it before the + nogroup entry. Or you can simply suid xlock to root. + + Q: Is there a mailing list for the Linux Shadow Password Suite? + + A: Yes, but it's for the development and beta testing of the next + Shadow Suite for Linux. You can get added to the list by mailing to: + shadow-list-request@neptune.cin.net with a subject of: subscribe. The + list is actually for discussions of the Linux shadow-YYMMSS series of + releases. You should join if you want to get involved in further + development or if you install the Suite on your system and want to get + information on newer releases. + + Q: I installed the Shadow Suite, but when I use the userdel command, I + get "userdel: cannot open shadow group file", what did I do wrong? + + A: You compiled the Shadow Suite with the SHADOWGRP option enabled, + but you don't have an /etc/gshadow file. You need to either edit the + config.h file and recompile, or create an /etc/group file. See the + section on shadow groups. + + Q: I installed the Shadow Suite but now I'm getting encoded passwords + back in my /etc/passwd file, what's wrong? + + A: You either enabled the AUTOSHADOW option in the Shadow config.h + file, or your libc was compiled with the SAHDOW_COMPAT option. You + need to determine which is the problem, and recompile. + + 10. Copyright Message. + + The Linux Shadow Password HOWTO is Copyright (c) 1996 Michael H. + Jackson. + + Permission is granted to make and distribute verbatim copies of this + document provided the copyright notice and this permission notice are + preserved on all copies. + + Permission is granted to copy and distribute modified versions of this + document under the conditions for verbatim copies above, provided a + notice clearly stating that the document is a modified version is also + included in the modified document. + + Permission is granted to copy and distribute translations of this + document into another language, under the conditions specified above + for modified versions. + + Permission is granted to convert this document into another media + under the conditions specified above for modified versions provided + the requirement to acknowledge the source document is fulfilled by + inclusion of an obvious reference to the source document in the new + media. Where there is any doubt as to what defines 'obvious' the + copyright owner reserves the right to decide. + + 11. Miscellaneous and Acknowledgments. + + The code examples for auth.c are taken from pppd-1.2.1d and + ppp-2.1.0e, Copyright (c) 1993 and The Australian National University + and Copyright (c) 1989 Carnegie Mellon University. + + Thanks to Marek Michalkiewicz for + writing and maintaining the Shadow Suite for Linux, and for his review + and comments on this document. + + Thanks to Ron Tidd for his helpful review and + testing. + + Thanks to everyone who has sent me feedback to help improve this + document. + + Please, if you have any comments or suggestions then mail them to me. + + regards + + Michael H. Jackson + diff --git a/doc/INSTALL b/doc/INSTALL new file mode 100644 index 00000000..3b50ea95 --- /dev/null +++ b/doc/INSTALL @@ -0,0 +1,176 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/doc/LICENSE b/doc/LICENSE new file mode 100644 index 00000000..718fbbb3 --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,118 @@ +NOTE: + This license has been obsoleted by the change to the BSD-style copyright. + You may continue to use this license if you wish, but you are under no + obligation to do so. + +(* +This document is freely plagiarised from the 'Artistic Licence', +distributed as part of the Perl v4.0 kit by Larry Wall, which is +available from most major archive sites. I stole it from CrackLib. + + $Id: LICENSE,v 1.2 1997/05/01 23:14:30 marekm Exp $ +*) + +This documents purpose is to state the conditions under which this +Package (See definition below) viz: "Shadow", the Shadow Password Suite +which is held by Julianne Frances Haugh, may be copied, such that the +copyright holder maintains some semblance of artistic control over the +development of the package, while giving the users of the package the +right to use and distribute the Package in a more-or-less customary +fashion, plus the right to make reasonable modifications. + +So there. + +*************************************************************************** + +Definitions: + + +A "Package" refers to the collection of files distributed by the +Copyright Holder, and derivatives of that collection of files created +through textual modification, or segments thereof. + +"Standard Version" refers to such a Package if it has not been modified, +or has been modified in accordance with the wishes of the Copyright +Holder. + +"Copyright Holder" is whoever is named in the copyright or copyrights +for the package. + +"You" is you, if you're thinking about copying or distributing this +Package. + +"Reasonable copying fee" is whatever you can justify on the basis of +media cost, duplication charges, time of people involved, and so on. +(You will not be required to justify it to the Copyright Holder, but +only to the computing community at large as a market that must bear the +fee.) + +"Freely Available" means that no fee is charged for the item itself, +though there may be fees involved in handling the item. It also means +that recipients of the item may redistribute it under the same +conditions they received it. + + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated +disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, +provided that you insert a prominent notice in each changed file stating +how and when AND WHY you changed that file, and provided that you do at +least ONE of the following: + +a) place your modifications in the Public Domain or otherwise make them +Freely Available, such as by posting said modifications to Usenet or an +equivalent medium, or placing the modifications on a major archive site +such as uunet.uu.net, or by allowing the Copyright Holder to include +your modifications in the Standard Version of the Package. + +b) use the modified Package only within your corporation or organization. + +c) rename any non-standard executables so the names do not conflict with +standard executables, which must also be provided, and provide separate +documentation for each non-standard executable that clearly documents +how it differs from the Standard Version. + +d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + +a) distribute a Standard Version of the executables and library files, +together with instructions (in the manual page or equivalent) on where +to get the Standard Version. + +b) accompany the distribution with the machine-readable source of the +Package with your modifications. + +c) accompany any non-standard executables with their corresponding +Standard Version executables, giving the non-standard executables +non-standard names, and clearly documenting the differences in manual +pages (or equivalent), together with instructions on where to get the +Standard Version. + +d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. +YOU MAY NOT CHARGE A FEE FOR THIS PACKAGE ITSELF. However, you may +distribute this Package in aggregate with other (possibly commercial) +programs as part of a larger (possibly commercial) software distribution +provided that YOU DO NOT ADVERTISE this package as a product of your +own. + +6. The name of the Copyright Holder may not be used to endorse or +promote products derived from this software without specific prior +written permission. + +7. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/doc/LSM b/doc/LSM new file mode 100644 index 00000000..2e2d843f --- /dev/null +++ b/doc/LSM @@ -0,0 +1,19 @@ +Begin3 +Title: Shadow Password Suite +Version: 19990709 +Entered-date: 09JUL99 +Description: Shadow password file utilities. This package includes + the programs necessary to convert traditional V7 UNIX + password files to the SVR4 shadow password format, and + additional tools to maintain password and group files + (that work with both shadow and non-shadow passwords). +Keywords: login passwd security shadow +Author: jfh@bga.com (Julianne F. Haugh) +Maintained-by: marekm@linux.org.pl (Marek Michalkiewicz) +Primary-site: piast.t19.ds.pwr.wroc.pl /pub/linux/shadow/ + 624K shadow-19990709.tar.gz +Alternate-site: ftp.ists.pwr.wroc.pl /pub/linux/shadow/ +Original-site: ftp.uu.net ? +Platforms: Linux, SunOS, ... +Copying-policy: FRS +End diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..487677a0 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,7 @@ +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + +EXTRA_DIST = ANNOUNCE CHANGES HOWTO LICENSE LSM README README.debian \ + README.limits README.linux README.mirrors README.nls README.pam \ + README.platforms README.shadow-paper README.sun4 \ + WISHLIST console.c.spec.txt cracklib26.diff diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 00000000..b756b137 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,198 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +EXTRA_DIST = ANNOUNCE CHANGES HOWTO LICENSE LSM README README.debian \ + README.limits README.linux README.mirrors README.nls README.pam \ + README.platforms README.shadow-paper README.sun4 \ + WISHLIST console.c.spec.txt cracklib26.diff +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = README INSTALL Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps doc/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = doc + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir info dvi installcheck install-exec install-data \ +install uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/README b/doc/README new file mode 100644 index 00000000..b94f3322 --- /dev/null +++ b/doc/README @@ -0,0 +1,253 @@ +[ $Id: README,v 1.3 1998/12/28 20:34:27 marekm Exp $ ] + +This is the explanatory document for Julianne Frances Haugh's login +replacement, release 3. This document was last updated 16 Feb 1997. + +This software is copyright 1988 - 1997, Julianne F. Haugh. All rights +reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of Julianne F. Haugh nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +This source code is currently archived on ftp.uu.net in the +comp.sources.misc portion of the USENET archives. You may also contact +the author, Julianne F. Haugh, at jfh@bga.com if you have any questions +regarding this package. + +THIS SOFTWARE IS BEING DISTRIBUTED AS-IS. THE AUTHORS DISCLAIM ALL +LIABILITY FOR ANY CONSEQUENCES OF USE. THE USER IS SOLELY RESPONSIBLE +FOR THE MAINTENANCE OF THIS SOFTWARE PACKAGE. THE AUTHORS ARE UNDER NO +OBLIGATION TO PROVIDE MODIFICATIONS OR IMPROVEMENTS. THE USER IS +ENCOURAGED TO TAKE ANY AND ALL STEPS NEEDED TO PROTECT AGAINST ACCIDENTAL +LOSS OF INFORMATION OR MACHINE RESOURCES. + +Special thanks are due to Chip Rosenthal for his fine testing efforts; +to Steve Simmons for his work in porting this code to BSD; and to Bill +Kennedy for his contributions of LaserJet printer time and energies. +Also, thanks for Dennis L. Mumaugh for the initial shadow password +information and to Tony Walton (olapw@olgb1.oliv.co.uk) for the System +V Release 4 changes. Effort in porting to SunOS has been contributed +by Dr. Michael Newberry (miken@cs.adfa.oz.au) and Micheal J. Miller, Jr. +(mke@kaberd.rain.com). Effort in porting to AT&T UNIX System V Release +4 has been provided by Andrew Herbert (andrew@werple.pub.uu.oz.au). +Special thanks to Marek Michalkiewicz (marekm@i17linuxb.ists.pwr.wroc.pl) +for taking over the Linux port of this software. + +New for Release 3.3: + User-defined authentication has been added. This allows you to + write programs to replace the password authentication method + which uses the crypt() function. + + The CrackLib password checking library is supported as of release + 3.3.0. It allows you to perform pro-active password checking as + each password is changed. + +Warning: + The newuser command will be removed in a later release. + The libsec.a library will be removed at some point after + version 3.3.3. + +This software is described in the 3rd USENIX Security Symposium +proceedings. These proceedings are available from + + USENIX Association + 2560 Ninth Street, Suite 215 + Berkeley, CA 94710 + +The current price is $30 for USENIX members and $39 for non-members. + +Begin by reading and editing the config.h file. All options are selected +by using #define's. A brief description for each available option appears +below. You may want to print this file out as it is LONG and you will +need to refer to it while editting config.h. You will also have to edit +the Makefile. The possible differences are documented there. Pay close +attention to the install: rule. Login now runs on about 30 different +varieties of UNIX that I have been made aware of. If you have any qualms, +you should run "make save" before running "make install". If something +breaks you can use "make restore" to put things back. In any case, you +should have a recent system backup as the potential for serious damage +exists. + +There are special Makefile and config.h files for SVR4, SunOS 4.1, and +Linux systems. If there is a major UNIX variant that you would like to +see supported, please send working Makefile and config.h files and I will +try to include then in the base distribution. + +Note that there are MANY options. As distributed most options are turned +on, which produces a really nice package. This is the system as used on +some of the authors' machines. There are many options which may be +selected at run time. You should refer to the login.5 manual page for +more information regarding these options. + +There are several files which you may have to replace. If your system has +a lastlog.h file, you should replace the one which I provide with your +system version. The pwd.h file that is produced by "make" must agree +exactly with the system supplied version. You should re-arrange the +fields or #define's until they match. The same is true for "shadow.h", +if you system provides one. You may want to replace large portions of +that file (or the entire file) with your system version. It is provided +for those systems which do NOT provide /usr/include/shadow.h. If you +do not have a the crypt() function in your library (perhaps because you +are located outside the United States), you may wish to look into the +UFC-crypt package which was posted to comp.sources.misc in volume 23, +issues 97 and 98. + +Login Defaults File - + This option selects the name of the file to read for the + run-time configurable options. The default value for + LOGINDEFS is "/etc/login.defs". + +Shadow [ unreadable ] Password Files - + This option utilizes an alternate, non-readable file to + contain the actual encrypted passwords. This is presumed + to increase system security by increasing the difficulty + with which system crackers obtain encrypted passwords. + + Select this option by defining the SHADOWPWD macro. + + This feature is optional, but only certain commands may + be compiled with this option disabled. + +Shadow Group Files - + This option utilizes an alternate, non-readable file to + contain encrypted group passwords and group administrator + information. + + This feature allows one or more users to be defined as + the administrators of a group for the purpose of adding + or deleting members and changing the group password. + + Select this option by defining the SHADOWGRP macro. You + must also create an emptry /etc/gshadow file. You must + select the SHADOWPWD option if you select SHADOWGRP. + +DBM Password Files - + This option utilizes the DBM database access routines to + increase the performance of user name and ID lookups in the + password file. You may select the NDBM database instead + and have DBM-style access to all user information files. + + Select this option by defining both the DBM and GETPWENT + macros. The FGETPWENT macro must also be defined or the + fgetpwent() library routine must be present. + +Double Length Passwords - + This option extends the maximum length of a user password + to 16 characters from eight. + + Select this option by defining the DOUBLESIZE macro. + Credit for this option is due Jonathan Bayer. + +Password Aging - + This option includes code to perform password aging. + Password aging is presumed to increase system security + by forcing users to change passwords on a regular + basis. The resolution on password age is in weeks for + non-shadow password systems and in days otherwise. + + Select this option by defining the AGING macro. + +Syslog - + This option causes the code to log various errors or + special conditions to the syslog daemon. The types of + information that are logged security violations, changes + to the user database, and program errors. + + Select syslog processing by defining the USE_SYSLOG + macro. + +Remote Login - + This option causes certain network login code to be + inserted to enable the "rlogin" and "telnet" commands to + work. To enable network logins, define the RLOGIN macro. + If your file includes a ut_host member, you must + also define the UT_HOST macro. Note that SVR4 has a + "utmpx" file to hold the ut_host member, so UT_HOST is + not required. + +Directory Reading Routines - + Three different macros are defined for opening and reading + directories. They are DIR_XENIX, DIR_BSD, and DIR_SYSV. + Refer to config.h for more details. + +Library Configuration Macros - + The following macros define the functions which are present + in your system library: + + HAVE_ULIMIT - Define if your UNIX supports ulimit() + GETPWENT - Define if you want my GETPWENT(3) routines + GETGRENT - Define if you want my GETGRENT(3) routines + NEED_AL64 - Define if library does not include a64l() + NEED_MKDIR - Define if system does not have mkdir() + NEED_RMDIR - Define if system does not have rmdir() + NEED_RENAME - Define if system does not have rename() + NEED_STRSTR - Define if library does not include strstr() + +Password File Information - + The following macros define the fields which are present in + your system password file. Because the system was compiled + to use the password file in its original form, these macros + must agree with the actual contents of the file. + + BSD_QUOTA - the pw_quota field exists + ATT_AGE - the pw_age field exists + ATT_COMMENT - the pw_comment field exists + +Signal Return Type - + Because different systems return different data types for + the signal() system call, you must define SIGTYPE to be + the data type your system uses. The default is "int", but + "void" is another popular value. + +SunOS 4.1.1 Notes: (mke@kaberd.rain.com) Michael J. Miller Jr. + +[ These notes were edited from the original. The standard Makefile + and config.h have notes indicating the changes required for SunOS. + Steve Allen at Lick has been working on cleaning up this platform. ] + +You'll need to do the following to get the shadow password dist to +compile on a sun 4.1.1 system. + +If using csh, then type 'rehash'. cd to the /etc directory and type +'pwconv'. This will create two files, nshadow and npasswd. +now type 'mkpasswd -f nshadow' and 'mkpasswd -f npasswd'. This will +create the shadow password file. + +Note: ftp will still use the old password file. Modified versions of + ftpd are available, or you may modify the version of ftpd from + any of the freely redistributable ftpd clones. + +Note: If you run suns pcnfs, be aware that it will still be looking at the + old password file as well. I may work out a patch for this, as I am + fairly certain the stuff on the sun side comes with source. + +Note: I have compiled this package with the standard c compiler and + suns unbundled c compiler at an optomization level of 2 in + both casses. Haven't tried gcc yet, so I don't know wether it + works. Same goes for suns C++ compiler. + +Note: Has been compiled on a sun 3/75 running sunos 4.1.1. Should compile + fine on sun 4's running 4.1.1, and may compile on suns running + 4.1. Have no idea what sort of success people will have that + are running 4.03 and older versions. diff --git a/doc/README.debian b/doc/README.debian new file mode 100644 index 00000000..43b749be --- /dev/null +++ b/doc/README.debian @@ -0,0 +1,68 @@ +Read this file first for a brief overview of the new versions of login +and passwd. + + +---Shadow passwords + +The command `shadowconfig on' will turn on shadow password support. +`shadowconfig off' will turn it back off. If you turn on shadow +password support, you'll gain the ability to set password ages and +expirations with chage(1). + +You may want to install the secure-su package which allows more +restrictions on su, for example a wheel group. + + +---General configuration + +Most of the configuration for the shadow utilities is in +/etc/login.defs. See login.defs(5). The defaults are quite +reasonable. + + +---MD5 Encryption + +If you set MD5_CRYPT_ENAB=yes in /etc/login.defs, passwords will be +encrypted with an MD5-based algorithm. It also supports of passwords +of unlimited length and longer salt strings. + + +---Login and resource control + +/etc/login.access and /etc/porttime control who may login to which +ports and when they may login. To enforce time restrictions, you'll +need to run logoutd. /etc/init.d/logoutd will start it on bootup if +there are non-comment lines in /etc/portttime. + +The lastlog and faillog commands will report the last time a user had +a successful and failed login, respectively. + +You may set per-user resource limits by editing /etc/limits. See +limits(5). + + +---Adding users and groups + +Though you may add users and groups with the SysV type commands, +useradd and groupadd, I recommend you add them with Debian adduser +version 3+. adduser gives you more configuration and conforms to the +Debian UID and GID allocation. + +Editing user and group parameters can be done with usermod and +groupmod. Removing users and groups can be done with userdel and +groupdel. + + +--- Group administration + +Local group allocation is much easier. With gpasswd(1) you can +designate users to administer groups. They can then securely add or +remove users from the group. + + +--- What to read next? + +Read the manpages, the other files in this directory, and the Shadow +Password HOWTO (included in the doc-linux package). A large portion +of these files deals with getting shadow installed. You can, of +course, ignore those parts. diff --git a/doc/README.limits b/doc/README.limits new file mode 100644 index 00000000..6551ad72 --- /dev/null +++ b/doc/README.limits @@ -0,0 +1,66 @@ + +ABOUT shadow-login limits: + +This code is merged into shadow login program from the original LShell 2.01 +written by Joel Katz. The port and some additional features have been added +by Cristian Gafton (gafton@sorosis.ro). + + +Changes: + - 96/04/16 + - {spaces,tabs} allowed within limits string + - Warn via syslog multiple default limits + - added few paragraphs to the login man page + - 96/04/14 + - code merged into lmain.c --cristiang + +TODO: - support groups in the limits file + (only usernames are supported at this momment :-( ) + +Setting user limits for shadow login program + +First, make a root-only-readable file (/etc/limits by default or LIMITS_FILE +defined config.h) that describes the resource limits you wish to impose. By +default no quotas are imposed on 'root'. In fact, there is no way to impose +limits via this procedure to root-equiv accounts (accounts with UID 0). + +Each line describes a limit for a user in the form: + + user LIMITS_STRING + +The LIMITS_STRING is a string of a concatenated list of resource limits. +Each limit consists of a letter identifier followed by a numerical limit. +The valid identifiers are: + + A: max address space (KB) + C: max core file size (KB) + D: max data size (KB) + F: maximum filesize (KB) + M: max locked-in-memory address space (KB) + N: max number of open files + R: max resident set size (KB) + S: max stack size (KB) + T: max CPU time (MIN) + U: max number of processes + L: max number of logins for this user + +For example, L2D2048N5 is a valid LIMITS_STRING. For reading convenience, +the following entries are equivalent: + +username L2D2048N5 +username L2 D2048 N5 + +Be aware that after the rest of the line is considered a limit +string, thus comments are not allowed. A invalid limits string will be +rejected (not considered) by the login program. + +The default entry is denoted by username '*'. If you have multiple 'default' +entries in your LIMITS_FILE, then the last one will be used as the default +entry. + +To completely disable limits for a user, a single dash (-) will do. + +Also, please note that all limit settings are set PER LOGIN. They are +not global, nor are they permanent. Perhaps global limits will come, but +for now this will have to do ;) + diff --git a/doc/README.linux b/doc/README.linux new file mode 100644 index 00000000..4159b0a7 --- /dev/null +++ b/doc/README.linux @@ -0,0 +1,162 @@ +$Id: README.linux,v 1.19 1999/06/07 16:40:44 marekm Exp $ + +This is the shadow suite hacked a bit for Linux. See CHANGES for +short description of changes. See also WISHLIST if you have too +much time on your hands :-). Now that copyright issues have been +resolved, the most important thing is testing. Please test this +code as much as you can, and report any problems. At this point, +I made so many changes that any bugs are probably mine. + +This package uses GNU autoconf, so it should be quite portable +- but it hasn't been tested much on anything but Linux/x86. +Long time ago, it has been reported to work on SunOS 4.1.x, +and recently there has been some success on Solaris 2.x and Irix. +I'd like to compile a current list of platforms this package is +known to work on - if you get it to work on some new OS (non-x86 +Linux, or non-Linux), please let me know. Please specify: host +type guessed by autoconf, libc version, distribution, changes +you needed to make (if any), etc. Please see README.platforms +for the current (incomplete - I know there are more...) list of +platforms this package is known to work on. + +There is a developers mailing list. It has moved again, and is +now hosted by SuSE - thanks to Thorsten Kukuk . +Send the command "subscribe shadow" to majordomo@suse.com to +subscribe if you are interested. To send mail to everyone on +the list, send it to shadow@suse.com. + +Before reporting bugs, please check if they still exist in my latest +development snapshot. Every few weeks I make a new version available +at the following URLs: +ftp://piast.t19.ds.pwr.wroc.pl/pub/linux/shadow/ +ftp://ftp.ists.pwr.wroc.pl/pub/linux/shadow/ +http://www.itnet.pl/amelektr/linux/shadow/ +(there are also mirror sites, see README.mirrors). + +After installation, please remember to remove any old binaries like +/bin/passwd (this version installs /usr/bin/passwd). If your passwd +program doesn't like the new /etc/login.defs settings, and complains +about "configuration error", this is most likely the problem. + +Current versions of the Linux C library (both libc 5.x and glibc 2.x) +have the shadow support, including MD5-based crypt(), built in. +Because of this, libshadow.a will build without these functions, +and the ones from libc will be used instead. Currently, libshadow.a +is for internal use only, so if you see -lshadow in a Makefile of +some other package, it is safe to remove it. + +Remember that shadow passwords will not make your system more secure +if your distribution has gaping holes which let any user become root. +Some distributions, especially the older ones, are much like SunOS 4.1 +without any security patches installed :-). Read the linux-security +mailing list archives, and plug all holes before attempting to install +the shadow suite. + +Very old versions of this package (shadow-3.3.x, shadow-mk) had a few +nasty security holes, too. Please use the latest version if possible. + +Encrypted passwords are not readable, but it is highly recommended +to use cracklib with a big dictionary to prevent users from choosing +weak passwords. This way if someone ever gets access to /etc/shadow +(for example, because of some not yet discovered bug), they will not +get half of the passwords using Crack... There is a configure option +to use cracklib, I haven't tested it myself but I'm told it works. + +The code feels like stabilizing now - while still BETA, it should +work quite well. Many bugs have been fixed, but there may be still +a few lurking. Again, please test it and report any problems. + +Thanks to Julianne Frances Haugh who wrote the thing +in the first place, sent me the latest version, and released it under +a "free" BSD-style license, so that it can be included in Linux +distributions (at least Debian 1.3 and Slackware 3.2 are already +doing that; Debian and Red Hat packaging standards are supported in +the standard source tree). David Frey , Michael +Meskes and Guy Maor have +done a lot of work to integrate shadow passwords into Debian Linux. + +Thanks to Bradley Glonka of Linux System Labs +(http://www.lsl.com/) for sending me a free Red Hat 4.2 CD-ROM, +making it possible to test this package on this distribution. + +Special thanks to Michael H. Jackson who wrote +the Linux Shadow Password HOWTO. Special thanks to Greg Gallagher + and Jon Lewis for maintaining the +developers mailing list for a long time. + +Thanks to Maciej 'Tycoon' Majchrowski +for ftp server space on piast.t19.ds.pwr.wroc.pl, and to Pawel Wiecek + for keeping bach.ists.pwr.wroc.pl up and running. + +Ian Jackson criticized the current shadow password +system (see the linux-security mailing list archives). We disagree on +some points, but this started a discussion on possible better solutions. +Theodore Ts'o has started a new project to implement +Pluggable Authentication Modules - a relatively new standard API which +makes it easier to add new authentication mechanisms (it's more than +just shadow passwords). See http://parc.power.net/morgan/Linux-PAM/ for +more information. (XXX - this URL has changed, I have to check where +PAM is now... -MM) + +Thanks to at least the following people for sending me patches, bug +reports and various comments. This list may be incomplete, I received +a lot of mail... + +John Adelsberger +Martin Bene +Luca Berra +Darcy Boese +Judd Bourgeois +Ulisses Alonso Camaro +Ed Carp +Rani Chouha +Joshua Cowan +Alan Curry +Frank Denis +Hrvoje Dogan +Chris Evans +Marc Ewing +Janos Farkas +Werner Fink +Floody +David Frey +Brian R. Gaeke +Cristian Gafton +Anton Gluck +Dave Hagewood +Jonathan Hankins +Juergen Heinzl +Joey Hess +Tim Hockin +David A. Holland +Andreas Jaeger +Timo Karjalainen +Calle Karlsson +Sami Kerola +Thorsten Kukuk +Jon Lewis +Pavel Machek +Guy Maor +Martin Mares +Rafal Maszkowski +Nikos Mavroyanopoulos +Michael Meskes +Arkadiusz Miskiewicz +Greg Mortensen +Mike Pakovic +Steve M. Robbins +Adam Rudnicki +Algis Rudys +Lutz Schwalowsky +Jay Soffian +Aniello Del Sorbo +Juha Virtanen +Michael Talbot-Wilson +Jesse Thilo +Shane Watts +Alexander O. Yuriev +Leonard N. Zubkoff + +If you want to be added here, or your e-mail address changes, +please let me know. Thanks. +-- Marek Michalkiewicz diff --git a/doc/README.mirrors b/doc/README.mirrors new file mode 100644 index 00000000..6d668021 --- /dev/null +++ b/doc/README.mirrors @@ -0,0 +1,57 @@ +Primary sites for the Shadow Password Suite for Linux: + +ftp://piast.t19.ds.pwr.wroc.pl/pub/linux/shadow/ +ftp://ftp.ists.pwr.wroc.pl/pub/linux/shadow/ +http://www.itnet.pl/amelektr/linux/shadow/ + +I upload latest versions here (and sometimes also to sunsite, but not +every new release). If you are not in Poland, these sites may be slow +for you - please use a mirror near you. + +Thanks to several people who offered to mirror this archive. Mirror +sites known to me (with addresses of people who submitted them to +this list) are listed below. If you want your site to be added here, +please let me know (specify the URL, and contact e-mail address). +If any of these sites become way out of date and should be removed, +or if they are good but the URL changes, please let me know too. + +Working mirrors that I know of, sorted by country (note: I removed +a few mirrors that didn't work when I tried to access them several +times - if any of them are still alive, please let me know): + +Brazil: + + ftp://ftp.athena.del.ufrj.br/pub/linux/shadow_password/ + Rafael Jorge Csura Szendrodi + +Czech Republic: + + ftp://ftp.gts.cz/pub/linux/security/shadow/ + Martin Mares + +Greece: + + ftp://linux.forthnet.gr/pub/linux/shadow/ + http://linux.forthnet.gr/pub/linux/shadow/ + Sotiris Tsimbonis + +Poland: + + ftp://xenium.pdi.net/pub/Crypto/shadow/ + Marcin E. Bednarz + + ftp://giswitch.sggw.waw.pl/pub/Linux/shadow/ + Marek Czajko + +Romania: + + ftp://ftp.kappa.ro/pub/Linux/Security/shadow/ + Mircea Damian + +United States: + + none? + +Thanks, +Marek Michalkiewicz +(or marekm@piast.t19.ds.pwr.wroc.pl, or marekm@bach.ists.pwr.wroc.pl) diff --git a/doc/README.nls b/doc/README.nls new file mode 100644 index 00000000..5a4ea285 --- /dev/null +++ b/doc/README.nls @@ -0,0 +1,30 @@ +I've added in password suite 980724 nls and locale support (currently +only for greek). Before compiling (configuring) you must have set the +environment variable LINGUAS=el for greek or LINGUAS="" just for english. +To see your language at login (to the other programs export LANG=el is +enough) when you enter your login add LANG=xx, where xx is your language. +An other way to accomplish it is change the variable ENVIRON_FILE in +/etc/login.defs from /etc/environment to .environment. Thus any user +can add, to his .environment file, his language eg. LANG=el. + +Nikos Mavroyanopoulos + nmav@i-net.paiko.gr + +Note: i18n support as of this release (981218) can have some rough +edges - because of the large number of files updated, there is always +a possibility that I have introduced some new bugs. There are also +potential security problems in GNU gettext (both the included one and +one found in glibc 2.0.x) related to environment variables (LANG, +LANGUAGE, LC_*, NLSPATH) when used in setuid programs. I have tried +to work around them in sanitize_env() but no guarantees. The problem +has been reported to the gettext maintainer. + +Also, you may not be able to legally distribute binaries compiled +with included gettext (GPL and BSD-like licenses are not compatible). +I believe that distribution in the same source archive is OK though +(it's a "mere aggregation of another work not based on the Program +with the Program" - here Program == gettext library - "on a volume of +a storage or distribution medium"). Please tell the FSF politely that +they should consider changing the gettext license to LGPL. Thanks! + +Marek diff --git a/doc/README.pam b/doc/README.pam new file mode 100644 index 00000000..222b5820 --- /dev/null +++ b/doc/README.pam @@ -0,0 +1,36 @@ + +About PAM support in the Shadow Password Suite + +Warning: this code is still considered ALPHA. It is still incomplete, +and needs more testing. Please let me know if it works, or if something +doesn't work. + +Use "./configure --with-libpam" to enable PAM support. Right now it only +works for the passwd and su applications. PAM support still needs to be +implemented in login. + +When compiled with PAM support enabled, the following traditional features +of the shadow suite are not implemented directly in the applications - +instead, they should be implemented in the PAM modules. + +passwd: + - administrator defined authentication methods + - TCFS support + - password expiration + - password strength checks + +su: + - wheel group + - console groups + - su access control (/etc/suauth) + - password expiration + - time restrictions + - resource limits + +Known problems: + - the pam_limits module doesn't work with su - it should be changed + to set the limits in pam_setcred() instead of pam_open_session() + (this version of su doesn't open any new sessions, like Solaris su + and unlike SimplePAMApps su) + - PAM support still needs to be implemented in login + diff --git a/doc/README.platforms b/doc/README.platforms new file mode 100644 index 00000000..a475af9e --- /dev/null +++ b/doc/README.platforms @@ -0,0 +1,33 @@ +# $Id: README.platforms,v 1.4 1999/06/07 16:40:44 marekm Exp $ +# +# This is the current (still incomplete) list of platforms this +# package has been verified to work on. Additions (preferably +# in the format as described below) are welcome. Thanks! +# +# V: last version reported to work +# H: host type +# L: Linux libc version +# D: Linux distribution, or other OS name and version +# C: changes (if any) +# R: reported by + +V: 980529 +H: sparc-unknown-linux-gnu +L: glibc-2.0.7 +D: Ultrapenguin-1.0.9 +C: had to explicitly disable desrpc. +R: Bjorn Christianson + +V: 980724 +H: i486-pc-linux-gnulibc1 +L: libc-5.4.33 +D: Debian-1.3.1.r6 +C: none (use dpkg-buildpackage) +R: Marek Michalkiewicz + +V: current +H: i686-pc-linux-gnu +L: glibc-2.0.7.19981211 +D: Debian-2.1 +C: none (use dpkg-buildpackage) +R: Marek Michalkiewicz diff --git a/doc/README.shadow-paper b/doc/README.shadow-paper new file mode 100644 index 00000000..bf4a83b2 --- /dev/null +++ b/doc/README.shadow-paper @@ -0,0 +1,25 @@ +Date: Fri, 06 Jun 1997 22:57:27 -0500 +From: Julie Haugh +To: marekm@piast.t19.ds.pwr.wroc.pl +CC: shadow-list@neptune.cin.net, debian-devel@lists.debian.org +Subject: Shadow Paper available from the web now. + +Greets, + +I've finally managed to key in my '92 security paper on Shadow. You can +find it at + + http://www.tab.com/~jfh/shadow-paper.html + +As I get some time to go over how things have changed in the last 5 +years I intend to update it. + +My next Shadow-related project is cleaning up the documentation I +started for the Trusted Subsystem evaluation I started a couple of +years ago. There are a few really worthwhile documents a system +administrator might enjoy in there. +-- +Julianne Frances Haugh Feminism: +mailto:jfh@tab.com The belief (considered radical by +http://www.tab.com/~jfh some) that women are people, too. + diff --git a/doc/README.sun4 b/doc/README.sun4 new file mode 100644 index 00000000..8c3f037e --- /dev/null +++ b/doc/README.sun4 @@ -0,0 +1,39 @@ +[ $Id: README.sun4,v 1.1.1.1 1996/08/10 07:59:52 marekm Exp $ ] + +You'll need to do the following to get the shadow password dist to +compile on a sun 4.1.1 system. + +copy Makefile.sun4 to Makefile, and make any system specific changes. + +copy config.h.sun4 config.h, and make any system specific changes. + +You may have to edit the pwd.h.m4 file by hand, as the sunos m4 may +not grok the pwd.h.m4 file corectly. If you have the /usr/5bin/m4, +substitute that. Be sure to delete the pwd.h file before typeing +'make' again, as there will be an empty one left from the failed attempt +to use the standard sunos m4. + +type 'make'. If everything goes well, then type 'make install' + +If using csh, then type 'rehash'. cd to the /etc directory and type +'pwconv'. This will create two files, nshadow and npasswd. +now type 'mkpasswd -f nshadow' and 'mkpasswd -f npasswd'. This will +create the shadow password file. + +Note: The shadow group stuff does not work with sunos. + +Note: ftp will still use the old password file. + +Note: if you run suns pcnfs, be aware that it will still be looking at the + old password file as well. I may work out a patch for this, as I am + fairly certain the stuff on the sun side comes with source. + +Note: I have compiled this package with the standard c compiler and + suns unbundled c compiler at an optomization level of 2 in + both casses. Haven't tried gcc yet, so I don't know wether it + works. Same goes for suns C++ compiler. + +Note: has been compiled on a sun 3/75 running sunos 4.1.1. Should compile + fine on sun 4's running 4.1.1, and may compile on suns running + 4.1. Have no idea what sort of success people will have that + are running 4.03 and older versions. diff --git a/doc/WISHLIST b/doc/WISHLIST new file mode 100644 index 00000000..6fc9f308 --- /dev/null +++ b/doc/WISHLIST @@ -0,0 +1,61 @@ +$Id: WISHLIST,v 1.22 1999/07/09 18:02:43 marekm Exp $ + +This is my wishlist for the shadow suite, in no particular order. Feel +free to do anything from this list and mail me the diffs :-). + +Patches in diff -u format, against the latest version (sometimes in the +"beta" directory) are preferred and make my job easier. Please, no +MIME, base64, quoted-printable, or HTML. For very big patches, or if +your mailer can corrupt them, please use gzip and uuencode. Thanks! + +New ideas to add to this list are welcome, too. --marekm + +- fix all the bugs, of course +- implement "su only" accounts (no logins, only su from other account) +- rewrite getdef.c to be more general? (no hardcoded names) +- update man pages to reflect all the changes (real programmers ... :-) +- patch for rlogind/telnetd to create utmp entry and fill in ut_addr +- fix the usermod -l bug properly [for now it's OK - #undef AUTH_METHODS] +- IMPORTANT: finish PAM support (passwd, su - done, untested; login - started) +- option to specify encrypted password in passwd (for yppasswdd, so it + doesn't need to know about shadow/non-shadow); should probably use a pipe + (less insecure than command line arguments) +- add support for changing NIS passwords +- clean up NDBM support, do it in the library and not in all programs +- add option to check passwords by piping them to external programs +- add functionality of the contrib/rpasswd.c wrapper to passwd +- option to generate pronounceable passwords (like on SCO), external program? +- poppassd (remote password change for eudora etc.) +- add support for passwd/shadow db files (glibc) +- better documentation +- su -l, -m, -p, -s options (as in GNU su) +- vipw: check password files for errors after editing +- clean up login utmp(x) handling code +- add "maximum time users allowed to stay logged in" limit option to logoutd +- "make" infinite loop on some systems? (Slackware 3.1, possibly others) +- handle quotes in /etc/environment like the shell does (but sshd doesn't...) +- write man pages: dialups.5, d_passwd.5 +- better utmpx support (logoutd, ...) +- better OPIE support (check access file, prompt for one-time password + with echo on, report number of logins left, etc.) +- init sometimes fails to remove the utmp entry on logout, why? + (init 2.74 - can't reproduce with 2.71 on Debian 1.3, works fine) +- new option for /etc/suauth: don't load user's environment (force "su -") + suggested by Ulisses Alonso Camaro +- clean up error messages - "program_name: text of error message\n" + (maybe some common code for common messages about failing to lock/open + something) +- don't use putgrent() even if available (glibc-2.0.100 bug) +- find out why recent releases won't compile on Solaris +- change logoutd to simply cat the contents of /etc/logoutd.mesg to the + luser's tty (no need to reload with SIGHUP) +- make the new getpass() replacement optional configurable at run time + (some people don't like the asterisks) +- newusers UID/GID selection algorithm should be the same as useradd + (and use UID_MIN, UID_MAX from login.defs) +- newusers should be able to copy /etc/skel to the new home directory + (like useradd) +- change makefiles to work with the latest automake +- include i18n files in Debian packages +- integrate the latest upstream version into the Debian distribution + (they still have shadow-980403, many bugs have been fixed since then) diff --git a/doc/console.c.spec.txt b/doc/console.c.spec.txt new file mode 100644 index 00000000..27830e7f --- /dev/null +++ b/doc/console.c.spec.txt @@ -0,0 +1,36 @@ +$Id: console.c.spec.txt,v 1.1 1997/06/16 00:02:41 marekm Exp $ + +Specification for console.c source file -- + +input values -- + tty -- character pointer to device name with leading "/dev/" + removed. + +return values -- + 0 -- false + 1 -- true + +int console (char * tty) + if "CONSOLE" string value is not present in login.defs + return true + + if the first character of "CONSOLE" string value is not "/" + treat the string as a ":" delimited list of device + names and search for the value of tty in that + tokenized list. + + if a match is found + return true + + return false + + if the file named by "CONSOLE" cannot be opened + return true + + scan the file looking for a match between the input line + and the value of tty + + if a match is found + return true + + return false diff --git a/doc/cracklib26.diff b/doc/cracklib26.diff new file mode 100644 index 00000000..09160b8c --- /dev/null +++ b/doc/cracklib26.diff @@ -0,0 +1,340 @@ +diff -ur orig/cracklib26_small/cracklib/fascist.c cracklib26_small/cracklib/fascist.c +--- orig/cracklib26_small/cracklib/fascist.c Mon Dec 15 02:56:55 1997 ++++ cracklib26_small/cracklib/fascist.c Sat Apr 4 22:14:45 1998 +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #define ISSKIP(x) (isspace(x) || ispunct(x)) + +@@ -460,28 +461,27 @@ + } + + char * +-FascistGecos(password, uid) ++FascistGecosPw(password, pwd) + char *password; +- int uid; ++ struct passwd *pwd; + { + int i; + int j; + int wc; + char *ptr; +- struct passwd *pwp; + char gbuffer[STRINGSIZE]; + char tbuffer[STRINGSIZE]; + char *uwords[STRINGSIZE]; + char longbuffer[STRINGSIZE * 2]; + +- if (!(pwp = getpwuid(uid))) ++ if (!pwd) + { + return ("you are not registered in the password file"); + } + + /* lets get really paranoid and assume a dangerously long gecos entry */ + +- strncpy(tbuffer, pwp->pw_name, STRINGSIZE); ++ strncpy(tbuffer, pwd->pw_name, STRINGSIZE); + tbuffer[STRINGSIZE-1] = '\0'; + if (GTry(tbuffer, password)) + { +@@ -490,12 +490,13 @@ + + /* it never used to be that you got passwd strings > 1024 chars, but now... */ + +- strncpy(tbuffer, pwp->pw_gecos, STRINGSIZE); ++ strncpy(tbuffer, pwd->pw_gecos, STRINGSIZE); + tbuffer[STRINGSIZE-1] = '\0'; + strcpy(gbuffer, Lowercase(tbuffer)); + + wc = 0; + ptr = gbuffer; ++ uwords[0] = (char *) 0; + + while (*ptr) + { +@@ -530,6 +531,8 @@ + *(ptr++) = '\0'; + } + } ++ if (!uwords[0]) ++ return ((char *) 0); /* empty gecos */ + #ifdef DEBUG + for (i = 0; uwords[i]; i++) + { +@@ -586,9 +589,10 @@ + } + + char * +-FascistLook(pwp, instring) ++FascistLookPw(pwp, instring, pwd) + PWDICT *pwp; + char *instring; ++ struct passwd *pwd; + { + int i; + char *ptr; +@@ -667,7 +671,7 @@ + return ("it looks like a National Insurance number."); + } + +- if (ptr = FascistGecos(password, getuid())) ++ if (ptr = FascistGecosPw(password, pwd ? pwd : getpwuid(getuid()))) + { + return (ptr); + } +@@ -715,9 +719,10 @@ + } + + char * +-FascistCheck(password, path) ++FascistCheckPw(password, path, pwd) + char *password; + char *path; ++ struct passwd *pwd; + { + static char lastpath[STRINGSIZE]; + static PWDICT *pwp; +@@ -750,5 +755,29 @@ + strncpy(lastpath, path, STRINGSIZE); + } + +- return (FascistLook(pwp, pwtrunced)); ++ return (FascistLookPw(pwp, pwtrunced, pwd)); ++} ++ ++char * ++FascistGecos(password, uid) ++ char *password; ++ int uid; ++{ ++ return (FascistGecosPw(password, getpwuid(uid))); ++} ++ ++char * ++FascistLook(pwp, instring) ++ PWDICT *pwp; ++ char *instring; ++{ ++ return (FascistLookPw(pwp, instring, (char *) 0)); ++} ++ ++char * ++FascistCheck(password, path) ++ char *password; ++ char *path; ++{ ++ return (FascistCheckPw(password, path, (char *) 0)); + } +diff -ur orig/cracklib26_small/cracklib/packer.h cracklib26_small/cracklib/packer.h +--- orig/cracklib26_small/cracklib/packer.h Mon Dec 15 00:09:30 1997 ++++ cracklib26_small/cracklib/packer.h Sat Jan 10 22:13:46 1998 +@@ -34,6 +34,7 @@ + FILE *dfp; + FILE *wfp; + ++ int canfree; + int32 flags; + #define PFOR_WRITE 0x0001 + #define PFOR_FLUSH 0x0002 +diff -ur orig/cracklib26_small/cracklib/packlib.c cracklib26_small/cracklib/packlib.c +--- orig/cracklib26_small/cracklib/packlib.c Fri Jul 9 22:22:58 1993 ++++ cracklib26_small/cracklib/packlib.c Sat Jan 10 22:28:49 1998 +@@ -16,7 +16,7 @@ + char *mode; + { + int32 i; +- static PWDICT pdesc; ++ PWDICT *pdesc; + char iname[STRINGSIZE]; + char dname[STRINGSIZE]; + char wname[STRINGSIZE]; +@@ -25,92 +25,94 @@ + FILE *ifp; + FILE *wfp; + +- if (pdesc.header.pih_magic == PIH_MAGIC) +- { +- fprintf(stderr, "%s: another dictionary already open\n", prefix); ++ if ((pdesc = (PWDICT *) malloc(sizeof(PWDICT))) == 0) + return ((PWDICT *) 0); +- } + +- memset(&pdesc, '\0', sizeof(pdesc)); ++ memset(pdesc, '\0', sizeof(*pdesc)); + + sprintf(iname, "%s.pwi", prefix); + sprintf(dname, "%s.pwd", prefix); + sprintf(wname, "%s.hwm", prefix); + +- if (!(pdesc.dfp = fopen(dname, mode))) ++ if (!(pdesc->dfp = fopen(dname, mode))) + { + perror(dname); ++ free(pdesc); + return ((PWDICT *) 0); + } + +- if (!(pdesc.ifp = fopen(iname, mode))) ++ if (!(pdesc->ifp = fopen(iname, mode))) + { +- fclose(pdesc.dfp); ++ fclose(pdesc->dfp); + perror(iname); ++ free(pdesc); + return ((PWDICT *) 0); + } + +- if (pdesc.wfp = fopen(wname, mode)) ++ if (pdesc->wfp = fopen(wname, mode)) + { +- pdesc.flags |= PFOR_USEHWMS; ++ pdesc->flags |= PFOR_USEHWMS; + } + +- ifp = pdesc.ifp; +- dfp = pdesc.dfp; +- wfp = pdesc.wfp; ++ ifp = pdesc->ifp; ++ dfp = pdesc->dfp; ++ wfp = pdesc->wfp; + + if (mode[0] == 'w') + { +- pdesc.flags |= PFOR_WRITE; +- pdesc.header.pih_magic = PIH_MAGIC; +- pdesc.header.pih_blocklen = NUMWORDS; +- pdesc.header.pih_numwords = 0; ++ pdesc->flags |= PFOR_WRITE; ++ pdesc->header.pih_magic = PIH_MAGIC; ++ pdesc->header.pih_blocklen = NUMWORDS; ++ pdesc->header.pih_numwords = 0; + +- fwrite((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp); ++ fwrite((char *) &pdesc->header, sizeof(pdesc->header), 1, ifp); + } else + { +- pdesc.flags &= ~PFOR_WRITE; ++ pdesc->flags &= ~PFOR_WRITE; + +- if (!fread((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp)) ++ if (!fread((char *) &pdesc->header, sizeof(pdesc->header), 1, ifp)) + { + fprintf(stderr, "%s: error reading header\n", prefix); + +- pdesc.header.pih_magic = 0; ++ pdesc->header.pih_magic = 0; + fclose(ifp); + fclose(dfp); ++ free(pdesc); + return ((PWDICT *) 0); + } + +- if (pdesc.header.pih_magic != PIH_MAGIC) ++ if (pdesc->header.pih_magic != PIH_MAGIC) + { + fprintf(stderr, "%s: magic mismatch\n", prefix); + +- pdesc.header.pih_magic = 0; ++ pdesc->header.pih_magic = 0; + fclose(ifp); + fclose(dfp); ++ free(pdesc); + return ((PWDICT *) 0); + } + +- if (pdesc.header.pih_blocklen != NUMWORDS) ++ if (pdesc->header.pih_blocklen != NUMWORDS) + { + fprintf(stderr, "%s: size mismatch\n", prefix); + +- pdesc.header.pih_magic = 0; ++ pdesc->header.pih_magic = 0; + fclose(ifp); + fclose(dfp); ++ free(pdesc); + return ((PWDICT *) 0); + } + +- if (pdesc.flags & PFOR_USEHWMS) ++ if (pdesc->flags & PFOR_USEHWMS) + { +- if (fread(pdesc.hwms, 1, sizeof(pdesc.hwms), wfp) != sizeof(pdesc.hwms)) ++ if (fread(pdesc->hwms, 1, sizeof(pdesc->hwms), wfp) != sizeof(pdesc->hwms)) + { +- pdesc.flags &= ~PFOR_USEHWMS; ++ pdesc->flags &= ~PFOR_USEHWMS; + } + } + } +- +- return (&pdesc); ++ pdesc->canfree = 1; ++ return (pdesc); + } + + int +@@ -159,8 +161,13 @@ + + fclose(pwp->ifp); + fclose(pwp->dfp); ++ if (pwp->wfp) ++ fclose(pwp->wfp); + +- pwp->header.pih_magic = 0; ++ if (pwp->canfree) ++ free(pwp); ++ else ++ pwp->header.pih_magic = 0; + + return (0); + } +@@ -307,6 +314,11 @@ + register char *this; + int idx; + ++/* ++ * comment in npasswd-2.0beta4 says this: ++ * This does not work under all circumstances, so don't bother ++ */ ++#if 0 + if (pwp->flags & PFOR_USEHWMS) + { + idx = string[0] & 0xff; +@@ -317,6 +329,10 @@ + lwm = 0; + hwm = PW_WORDS(pwp) - 1; + } ++#else ++ lwm = 0; ++ hwm = PW_WORDS(pwp); ++#endif + + #ifdef DEBUG + printf("---- %lu, %lu ----\n", lwm, hwm); +diff -ur orig/cracklib26_small/util/mkdict cracklib26_small/util/mkdict +--- orig/cracklib26_small/util/mkdict Fri Jul 9 22:23:03 1993 ++++ cracklib26_small/util/mkdict Sat Apr 4 22:31:45 1998 +@@ -14,9 +14,16 @@ + SORT="sort" + ###SORT="sort -T /tmp" + +-cat $* | ++### Use zcat to read compressed (as well as uncompressed) dictionaries. ++### Compressed dictionaries can save quite a lot of disk space. ++ ++CAT="gzip -cdf" ++###CAT="zcat" ++###CAT="cat" ++ ++$CAT $* | + tr '[A-Z]' '[a-z]' | +- tr -cd '[\012a-z0-9]' | ++ tr -cd '\012[a-z][0-9]' | + $SORT | + uniq | + grep -v '^#' | diff --git a/etc/Makefile.am b/etc/Makefile.am new file mode 100644 index 00000000..d0f6ce79 --- /dev/null +++ b/etc/Makefile.am @@ -0,0 +1,7 @@ +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + +EXTRA_DIST = limits login.access login.defs login.defs.linux \ + shells suauth + +SUBDIRS = pam.d diff --git a/etc/Makefile.in b/etc/Makefile.in new file mode 100644 index 00000000..76d8af86 --- /dev/null +++ b/etc/Makefile.in @@ -0,0 +1,285 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +EXTRA_DIST = limits login.access login.defs login.defs.linux \ + shells suauth + +SUBDIRS = pam.d +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: all-recursive all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps etc/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $(MAKEFLAGS); amf=$$2; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + done; \ + for subdir in $$rev; do \ + target=`echo $@ | sed s/-recursive//`; \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + (cd $$subdir && $(MAKE) tags); \ + done + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = etc + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done + for subdir in $(SUBDIRS); do \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + done +info: info-recursive +dvi: dvi-recursive +check: all-am + $(MAKE) check-recursive +installcheck: installcheck-recursive +all-am: Makefile + +install-exec: install-exec-recursive + @$(NORMAL_INSTALL) + +install-data: install-data-recursive + @$(NORMAL_INSTALL) + +install: install-recursive + @: + +uninstall: uninstall-recursive + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: installdirs-recursive + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean-am: mostlyclean-tags mostlyclean-generic + +clean-am: clean-tags clean-generic mostlyclean-am + +distclean-am: distclean-tags distclean-generic clean-am + +maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ + distclean-am + +mostlyclean: mostlyclean-recursive mostlyclean-am + +clean: clean-recursive clean-am + +distclean: distclean-recursive distclean-am + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-recursive maintainer-clean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: install-data-recursive uninstall-data-recursive \ +install-exec-recursive uninstall-exec-recursive installdirs-recursive \ +uninstalldirs-recursive all-recursive check-recursive \ +installcheck-recursive info-recursive dvi-recursive \ +mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info dvi \ +installcheck all-am install-exec install-data install uninstall all \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/etc/limits b/etc/limits new file mode 100644 index 00000000..fc741b1a --- /dev/null +++ b/etc/limits @@ -0,0 +1,28 @@ +# /etc/limits contains user resource limits. +# See limits(5). +# +# Format: +# +# +# default entry is '*' for username +# +# Valid flags are: +# A: max address space (KB) +# C: max core file size (KB) +# D: max data size (KB) +# F: maximum filesize (KB) +# M: max locked-in-memory address space (KB) [only for root on Linux 2.0.x] +# N: max number of open files +# R: max resident set size (KB) [no effect on Linux 2.0.x] +# S: max stack size (KB) +# T: max CPU time (MIN) +# U: max number of processes +# L: max number of logins for this user +# +# Examples: +# the default entry +#* L2 D6144 R2048 S2048 U32 N32 F16384 T5 C0 +# another way of suspending a user login +#guest L0 +# this account has no limits +#sysadm - diff --git a/etc/login.access b/etc/login.access new file mode 100644 index 00000000..60cbd63f --- /dev/null +++ b/etc/login.access @@ -0,0 +1,54 @@ +# $Id: login.access,v 1.2 1996/09/10 02:45:04 marekm Exp $ +# +# Login access control table. +# +# When someone logs in, the table is scanned for the first entry that +# matches the (user, host) combination, or, in case of non-networked +# logins, the first entry that matches the (user, tty) combination. The +# permissions field of that table entry determines whether the login will +# be accepted or refused. +# +# Format of the login access control table is three fields separated by a +# ":" character: +# +# permission : users : origins +# +# The first field should be a "+" (access granted) or "-" (access denied) +# character. +# +# The second field should be a list of one or more login names, group +# names, or ALL (always matches). A pattern of the form user@host is +# matched when the login name matches the "user" part, and when the +# "host" part matches the local machine name. +# +# The third field should be a list of one or more tty names (for +# non-networked logins), host names, domain names (begin with "."), host +# addresses, internet network numbers (end with "."), ALL (always +# matches) or LOCAL (matches any string that does not contain a "." +# character). +# +# If you run NIS you can use @netgroupname in host or user patterns; this +# even works for @usergroup@@hostgroup patterns. Weird. +# +# The EXCEPT operator makes it possible to write very compact rules. +# +# The group file is searched only when a name does not match that of the +# logged-in user. Only groups are matched in which users are explicitly +# listed: the program does not look at a user's primary group id value. +# +############################################################################## +# +# Disallow console logins to all but a few accounts. +# +#-:ALL EXCEPT wheel shutdown sync:console +# +# Disallow non-local logins to privileged accounts (group wheel). +# +#-:wheel:ALL EXCEPT LOCAL .win.tue.nl +# +# Some accounts are not allowed to login from anywhere: +# +#-:wsbscaro wsbsecr wsbspac wsbsym wscosor wstaiwde:ALL +# +# All other accounts are allowed to login from anywhere. +# diff --git a/etc/login.defs b/etc/login.defs new file mode 100644 index 00000000..7af8d118 --- /dev/null +++ b/etc/login.defs @@ -0,0 +1,214 @@ +# +# /etc/login.defs - Configuration control definitions for the login package. +# +# $Id: login.defs,v 1.2 1997/05/01 23:14:35 marekm Exp $ +# +# Three items must be defined: MAIL_DIR, ENV_SUPATH, and ENV_PATH. +# If unspecified, some arbitrary (and possibly incorrect) value will +# be assumed. All other items are optional - if not specified then +# the described action or option will be inhibited. +# +# Comment lines (lines beginning with "#") and blank lines are ignored. +# + +# +# Delay in seconds before being allowed another attempt after a login failure +# +FAIL_DELAY 5 + +# +# Enable additional passwords upon dialup lines specified in /etc/dialups. +# +DIALUPS_CHECK_ENAB yes + +# +# Enable logging and display of /usr/adm/faillog login failure info. +# +FAILLOG_ENAB yes + +# +# Enable display of unknown usernames when login failures are recorded. +# +LOG_UNKFAIL_ENAB yes + +# +# Enable logging and display of /usr/adm/lastlog login time info. +# +LASTLOG_ENAB yes + +# +# Enable checking and display of mailbox status upon login. +# +MAIL_CHECK_ENAB yes + +# +# Enable additional checks upon password changes. +# +OBSCURE_CHECKS_ENAB yes + +# +# Enable checking of time restrictions specified in /etc/porttime. +# +PORTTIME_CHECKS_ENAB yes + +# +# Enable setting of ulimit, umask, and niceness from passwd gecos field. +# +QUOTAS_ENAB yes + +# +# Enable "syslog" logging of su activity - in addition to sulog file logging. +# SYSLOG_SG_ENAB does the same for newgrp and sg. +# +SYSLOG_SU_ENAB no +SYSLOG_SG_ENAB no + +# +# If defined, either full pathname of a file containing device names or +# a ":" delimited list of device names. Root logins will be allowed only +# upon these devices. +# +CONSOLE /etc/consoles +#CONSOLE console:tty01:tty02:tty03:tty04 + +# +# If defined, all su activity is logged to this file. +# +SULOG_FILE /usr/adm/sulog + +# +# If defined, ":" delimited list of "message of the day" files to +# be displayed upon login. +# +MOTD_FILE /etc/motd +#MOTD_FILE /etc/motd:/usr/lib/news/news-motd + +# +# If defined, this file will be output before each login prompt. +# +#ISSUE_FILE /etc/issue + +# +# If defined, file which maps tty line to TERM environment parameter. +# Each line of the file is in a format something like "vt100 tty01". +# +TTYTYPE_FILE /etc/ttytype + +# +# If defined, login failures will be logged here in a utmp format. +# +FTMP_FILE /etc/ftmp + +# +# If defined, name of file whose presence which will inhibit non-root +# logins. The contents of this file should be a message indicating +# why logins are inhibited. +# +NOLOGINS_FILE /etc/nologins + +# +# If defined, the command name to display when running "su -". For +# example, if this is defined as "su" then a "ps" will display the +# command is "-su". If not defined, then "ps" would display the +# name of the shell actually being run, e.g. something like "-sh". +# +SU_NAME su + +# +# *REQUIRED* +# Directory where mailboxes reside, _or_ name of file, relative to the +# home directory. If you _do_ define both, MAIL_DIR takes precedence. +# MAILDIR is for Qmail +# +#MAILDIR Maildir +MAIL_DIR /usr/spool/mail +#MAIL_FILE .mail + +# +# If defined, file which inhibits all the usual chatter during the login +# sequence. If a full pathname, then hushed mode will be enabled if the +# user's name or shell are found in the file. If not a full pathname, then +# hushed mode will be enabled if the file exists in the user's home directory. +# +#HUSHLOGIN_FILE .hushlogin +HUSHLOGIN_FILE /etc/hushlogins + +# +# If defined, the presence of this value in an /etc/passwd "shell" field will +# disable logins for that user, although "su" will still be allowed. +# +NOLOGIN_STR NOLOGIN + +# +# If defined, either a TZ environment parameter spec or the +# fully-rooted pathname of a file containing such a spec. +# +ENV_TZ TZ=CST6CDT +#ENV_TZ /etc/tzname + +# +# If defined, an HZ environment parameter spec. +# +ENV_HZ HZ=50 + +# +# *REQUIRED* The default PATH settings, for superuser and normal users. +# +ENV_SUPATH PATH=/etc/local:/etc:/local/bin:/usr/bin:/bin +ENV_PATH PATH=/local/bin:/usr/bin:/bin + +# +# Terminal permissions +# +# TTYGROUP Login tty will be assigned this group ownership. +# TTYPERM Login tty will be set to this permission. +# +# If you have a "write" program which is "setgid" to a special group +# which owns the terminals, define TTYGROUP to the group number and +# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign +# TTYPERM to either 622 or 600. +# +#TTYGROUP 7 +#TTYPERM 0620 +TTYPERM 0622 + +# +# Login configuration initializations: +# +# ERASECHAR Terminal ERASE character ('\010' = backspace). +# KILLCHAR Terminal KILL character ('\025' = CTRL/U). +# UMASK Default "umask" value. +# ULIMIT Default "ulimit" value. +# +# The ERASECHAR and KILLCHAR are used only on System V machines. +# The ULIMIT is used only if the system supports it. +# +# Prefix these values with "0" to get octal, "0x" to get hexadecimal. +# +ERASECHAR 010 +KILLCHAR 025 +UMASK 022 +ULIMIT 2097152 + +# +# Password aging controls: +# +# PASS_MAX_DAYS Maximum number of days a password may be used. +# PASS_MIN_DAYS Minimum number of days allowed between password changes. +# PASS_MIN_LEN Minimum acceptable password length. +# PASS_WARN_AGE Number of days warning given before a password expires. +# +PASS_MAX_DAYS 99999 +PASS_MIN_DAYS 0 +PASS_MIN_LEN 5 +PASS_WARN_AGE 7 + +# +# Only allow group 0 members to "su" to root. +# +SU_WHEEL_ONLY no + +# +# If compiled with cracklib support, where are the dictionaries +# +#CRACKLIB_DICTPATH /usr/share/lib/pw_dict diff --git a/etc/login.defs.linux b/etc/login.defs.linux new file mode 100644 index 00000000..a5e5eb6a --- /dev/null +++ b/etc/login.defs.linux @@ -0,0 +1,340 @@ +# +# /etc/login.defs - Configuration control definitions for the login package. +# +# $Id: login.defs.linux,v 1.10 1999/03/07 19:14:33 marekm Exp $ +# +# Three items must be defined: MAIL_DIR, ENV_SUPATH, and ENV_PATH. +# If unspecified, some arbitrary (and possibly incorrect) value will +# be assumed. All other items are optional - if not specified then +# the described action or option will be inhibited. +# +# Comment lines (lines beginning with "#") and blank lines are ignored. +# +# Modified for Linux. --marekm + +# +# Delay in seconds before being allowed another attempt after a login failure +# +FAIL_DELAY 3 + +# +# Enable additional passwords upon dialup lines specified in /etc/dialups. +# +DIALUPS_CHECK_ENAB yes + +# +# Enable logging and display of /var/log/faillog login failure info. +# +FAILLOG_ENAB yes + +# +# Enable display of unknown usernames when login failures are recorded. +# +LOG_UNKFAIL_ENAB no + +# +# Enable logging of successful logins +# +LOG_OK_LOGINS no + +# +# Enable logging and display of /var/log/lastlog login time info. +# +LASTLOG_ENAB yes + +# +# Enable checking and display of mailbox status upon login. +# +# Disable if the shell startup files already check for mail +# ("mailx -e" or equivalent). +# +MAIL_CHECK_ENAB yes + +# +# Enable additional checks upon password changes. +# +OBSCURE_CHECKS_ENAB yes + +# +# Enable checking of time restrictions specified in /etc/porttime. +# +PORTTIME_CHECKS_ENAB yes + +# +# Enable setting of ulimit, umask, and niceness from passwd gecos field. +# +QUOTAS_ENAB yes + +# +# Enable "syslog" logging of su activity - in addition to sulog file logging. +# SYSLOG_SG_ENAB does the same for newgrp and sg. +# +SYSLOG_SU_ENAB yes +SYSLOG_SG_ENAB yes + +# +# If defined, either full pathname of a file containing device names or +# a ":" delimited list of device names. Root logins will be allowed only +# upon these devices. +# +CONSOLE /etc/securetty +#CONSOLE console:tty01:tty02:tty03:tty04 + +# +# If defined, all su activity is logged to this file. +# +#SULOG_FILE /var/log/sulog + +# +# If defined, ":" delimited list of "message of the day" files to +# be displayed upon login. +# +MOTD_FILE /etc/motd +#MOTD_FILE /etc/motd:/usr/lib/news/news-motd + +# +# If defined, this file will be output before each login prompt. +# +#ISSUE_FILE /etc/issue + +# +# If defined, file which maps tty line to TERM environment parameter. +# Each line of the file is in a format something like "vt100 tty01". +# +#TTYTYPE_FILE /etc/ttytype + +# +# If defined, login failures will be logged here in a utmp format. +# last, when invoked as lastb, will read /var/log/btmp, so... +# +FTMP_FILE /var/log/btmp + +# +# If defined, name of file whose presence which will inhibit non-root +# logins. The contents of this file should be a message indicating +# why logins are inhibited. +# +NOLOGINS_FILE /etc/nologin + +# +# If defined, the command name to display when running "su -". For +# example, if this is defined as "su" then a "ps" will display the +# command is "-su". If not defined, then "ps" would display the +# name of the shell actually being run, e.g. something like "-sh". +# +SU_NAME su + +# +# *REQUIRED* +# Directory where mailboxes reside, _or_ name of file, relative to the +# home directory. If you _do_ define both, MAIL_DIR takes precedence. +# QMAIL_DIR is for Qmail +# +#QMAIL_DIR Maildir +MAIL_DIR /var/spool/mail +#MAIL_FILE .mail + +# +# If defined, file which inhibits all the usual chatter during the login +# sequence. If a full pathname, then hushed mode will be enabled if the +# user's name or shell are found in the file. If not a full pathname, then +# hushed mode will be enabled if the file exists in the user's home directory. +# +HUSHLOGIN_FILE .hushlogin +#HUSHLOGIN_FILE /etc/hushlogins + +# +# If defined, the presence of this value in an /etc/passwd "shell" field will +# disable logins for that user, although "su" will still be allowed. +# +# XXX this does not seem to be implemented yet... --marekm +# no, it was implemented but I ripped it out ;-) -- jfh +NOLOGIN_STR NOLOGIN + +# +# If defined, either a TZ environment parameter spec or the +# fully-rooted pathname of a file containing such a spec. +# +#ENV_TZ TZ=CST6CDT +#ENV_TZ /etc/tzname + +# +# If defined, an HZ environment parameter spec. +# +# for Linux/x86 +ENV_HZ HZ=100 +# For Linux/Alpha... +#ENV_HZ HZ=1024 + +# +# *REQUIRED* The default PATH settings, for superuser and normal users. +# +# (they are minimal, add the rest in the shell startup files) +ENV_SUPATH PATH=/sbin:/bin:/usr/sbin:/usr/bin +ENV_PATH PATH=/bin:/usr/bin + +# +# Terminal permissions +# +# TTYGROUP Login tty will be assigned this group ownership. +# TTYPERM Login tty will be set to this permission. +# +# If you have a "write" program which is "setgid" to a special group +# which owns the terminals, define TTYGROUP to the group number and +# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign +# TTYPERM to either 622 or 600. +# +TTYGROUP tty +TTYPERM 0600 + +# +# Login configuration initializations: +# +# ERASECHAR Terminal ERASE character ('\010' = backspace). +# KILLCHAR Terminal KILL character ('\025' = CTRL/U). +# UMASK Default "umask" value. +# ULIMIT Default "ulimit" value. +# +# The ERASECHAR and KILLCHAR are used only on System V machines. +# The ULIMIT is used only if the system supports it. +# (now it works with setrlimit too; ulimit is in 512-byte units) +# +# Prefix these values with "0" to get octal, "0x" to get hexadecimal. +# +ERASECHAR 0177 +KILLCHAR 025 +UMASK 022 +#ULIMIT 2097152 + +# +# Password aging controls: +# +# PASS_MAX_DAYS Maximum number of days a password may be used. +# PASS_MIN_DAYS Minimum number of days allowed between password changes. +# PASS_MIN_LEN Minimum acceptable password length. +# PASS_WARN_AGE Number of days warning given before a password expires. +# +PASS_MAX_DAYS 99999 +PASS_MIN_DAYS 0 +PASS_MIN_LEN 5 +PASS_WARN_AGE 7 + +# +# If "yes", the user must be listed as a member of the first gid 0 group +# in /etc/group (called "root" on most Linux systems) to be able to "su" +# to uid 0 accounts. If the group doesn't exist or is empty, no one +# will be able to "su" to uid 0. +# +SU_WHEEL_ONLY no + +# +# If compiled with cracklib support, where are the dictionaries +# +CRACKLIB_DICTPATH /var/cache/cracklib/cracklib_dict + +# +# Min/max values for automatic uid selection in useradd +# +UID_MIN 1000 +UID_MAX 60000 + +# +# Min/max values for automatic gid selection in groupadd +# +GID_MIN 100 +GID_MAX 60000 + +# +# Max number of login retries if password is bad +# +LOGIN_RETRIES 5 + +# +# Max time in seconds for login +# +LOGIN_TIMEOUT 60 + +# +# Maximum number of attempts to change password if rejected (too easy) +# +PASS_CHANGE_TRIES 5 + +# +# Warn about weak passwords (but still allow them) if you are root. +# +PASS_ALWAYS_WARN yes + +# +# Number of significant characters in the password for crypt(). +# Default is 8, don't change unless your crypt() is better. +# Ignored if MD5_CRYPT_ENAB set to "yes". +# +#PASS_MAX_LEN 8 + +# +# Require password before chfn/chsh can make any changes. +# +CHFN_AUTH yes + +# +# Which fields may be changed by regular users using chfn - use +# any combination of letters "frwh" (full name, room number, work +# phone, home phone). If not defined, no changes are allowed. +# For backward compatibility, "yes" = "rwh" and "no" = "frwh". +# +CHFN_RESTRICT rwh + +# +# Password prompt (%s will be replaced by user name). +# +# XXX - it doesn't work correctly yet, for now leave it commented out +# to use the default which is just "Password: ". +#LOGIN_STRING "%s's Password: " + +# +# Only works if compiled with MD5_CRYPT defined: +# If set to "yes", new passwords will be encrypted using the MD5-based +# algorithm compatible with the one used by recent releases of FreeBSD. +# It supports passwords of unlimited length and longer salt strings. +# Set to "no" if you need to copy encrypted passwords to other systems +# which don't understand the new algorithm. Default is "no". +# +#MD5_CRYPT_ENAB no + +# +# List of groups to add to the user's supplementary group set +# when logging in on the console (as determined by the CONSOLE +# setting). Default is none. +# +# Use with caution - it is possible for users to gain permanent +# access to these groups, even when not logged in on the console. +# How to do it is left as an exercise for the reader... +# +#CONSOLE_GROUPS floppy:audio:cdrom + +# +# Should login be allowed if we can't cd to the home directory? +# Default in no. +# +DEFAULT_HOME yes + +# +# If this file exists and is readable, login environment will be +# read from it. Every line should be in the form name=value. +# +ENVIRON_FILE /etc/environment + +# +# If defined, this command is run when removing a user. +# It should remove any at/cron/print jobs etc. owned by +# the user to be removed (passed as the first argument). +# +#USERDEL_CMD /usr/sbin/userdel_local + +# +# If defined, either full pathname of a file containing device names or +# a ":" delimited list of device names. No password is required to log in +# on these devices. +# +#NO_PASSWORD_CONSOLE tty1:tty2:tty3:tty4:tty5:tty6 + diff --git a/etc/pam.d/Makefile.am b/etc/pam.d/Makefile.am new file mode 100644 index 00000000..c9041de6 --- /dev/null +++ b/etc/pam.d/Makefile.am @@ -0,0 +1,4 @@ +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + +EXTRA_DIST = passwd su diff --git a/etc/pam.d/Makefile.in b/etc/pam.d/Makefile.in new file mode 100644 index 00000000..465254c6 --- /dev/null +++ b/etc/pam.d/Makefile.in @@ -0,0 +1,195 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +EXTRA_DIST = passwd su +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps etc/pam.d/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = etc/pam.d + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir info dvi installcheck install-exec install-data \ +install uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/etc/pam.d/passwd b/etc/pam.d/passwd new file mode 100644 index 00000000..989d5b96 --- /dev/null +++ b/etc/pam.d/passwd @@ -0,0 +1,5 @@ +#%PAM-1.0 +#[For version 1.0 syntax, the above header is optional] +# $Id: passwd,v 1.1 1998/07/23 22:13:15 marekm Exp $ +# /etc/pam.d/passwd - sample PAM config file for the `passwd' service +password required pam_unix_passwd.so diff --git a/etc/pam.d/su b/etc/pam.d/su new file mode 100644 index 00000000..066be02e --- /dev/null +++ b/etc/pam.d/su @@ -0,0 +1,7 @@ +#%PAM-1.0 +#[For version 1.0 syntax, the above header is optional] +# $Id: su,v 1.1 1998/07/23 22:13:15 marekm Exp $ +# /etc/pam.d/su - sample PAM config file for the `su' service +auth sufficient pam_rootok.so +auth required pam_unix_auth.so +account required pam_unix_acct.so diff --git a/etc/shells b/etc/shells new file mode 100644 index 00000000..e7f0e538 --- /dev/null +++ b/etc/shells @@ -0,0 +1,10 @@ +# /etc/shells: valid login shells +/bin/ash +/bin/bash +/bin/csh +/bin/sh +/usr/bin/es +/usr/bin/ksh +/usr/bin/rc +/usr/bin/tcsh +/usr/bin/zsh diff --git a/etc/suauth b/etc/suauth new file mode 100644 index 00000000..85620c4f --- /dev/null +++ b/etc/suauth @@ -0,0 +1,4 @@ +# /etc/suauth - secure-su control file. See suauth(5) for full documentation. + +# Uncommenting this line will only allow members of group root to su to root. +# root:ALL EXCEPT GROUP root:DENY diff --git a/install-sh b/install-sh new file mode 100755 index 00000000..e8436696 --- /dev/null +++ b/install-sh @@ -0,0 +1,250 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/intl/ChangeLog b/intl/ChangeLog new file mode 100644 index 00000000..19895015 --- /dev/null +++ b/intl/ChangeLog @@ -0,0 +1,1086 @@ +1998-04-29 Ulrich Drepper + + * intl/localealias.c (read_alias_file): Use unsigned char for + local variables. Remove unused variable tp. + * intl/l10nflist.c (_nl_normalize_codeset): Use unsigned char * + for type of codeset. For loosing Solaris systems. + * intl/loadinfo.h: Adapt prototype of _nl_normalize_codeset. + * intl/bindtextdom.c (BINDTEXTDOMAIN): Don't define local variable + len if not needed. + Patches by Jim Meyering. + +1998-04-28 Ulrich Drepper + + * loadmsgcat.c (_nl_load_domain): Don't assign the element use_mmap if + mmap is not supported. + + * hash-string.h: Don't include . + +1998-04-27 Ulrich Drepper + + * textdomain.c: Use strdup is available. + + * localealias.c: Define HAVE_MEMPCPY so that we can use this + function. Define and use semapahores to protect modfication of + global objects when compiling for glibc. Add code to allow + freeing alias table. + + * l10nflist.c: Don't assume stpcpy not being a macro. + + * gettextP.h: Define internal_function macri if not already done. + Use glibc byte-swap macros instead of defining SWAP when compiled + for glibc. + (struct loaded_domain): Add elements to allow unloading. + + * Makefile.in (distclean): Don't remove libintl.h here. + + * bindtextdomain.c: Carry over changes from glibc. Use strdup if + available. + + * dcgettext.c: Don't assume stpcpy not being a macro. Mark internal + functions. Add memory freeing code for glibc. + + * dgettext.c: Update copyright. + + * explodename.c: Include stdlib.h and string.h only if they exist. + Use strings.h eventually. + + * finddomain.c: Mark internal functions. Use strdup if available. + Add memory freeing code for glibc. + +1997-10-10 20:00 Ulrich Drepper + + * libgettext.h: Fix dummy textdomain and bindtextdomain macros. + They should return reasonable values. + Reported by Tom Tromey . + +1997-09-16 03:33 Ulrich Drepper + + * libgettext.h: Define PARAMS also to `args' if __cplusplus is defined. + * intlh.inst.in: Likewise. + Reported by Jean-Marc Lasgouttes . + + * libintl.glibc: Update from current glibc version. + +1997-09-06 02:10 Ulrich Drepper + + * intlh.inst.in: Reformat copyright. + +1997-08-19 15:22 Ulrich Drepper + + * dcgettext.c (DCGETTEXT): Remove wrong comment. + +1997-08-16 00:13 Ulrich Drepper + + * Makefile.in (install-data): Don't change directory to install. + +1997-08-01 14:30 Ulrich Drepper + + * cat-compat.c: Fix copyright. + + * localealias.c: Don't define strchr unless !HAVE_STRCHR. + + * loadmsgcat.c: Update copyright. Fix typos. + + * l10nflist.c: Don't define strchr unless !HAVE_STRCHR. + (_nl_make_l10nflist): Handle sponsor and revision correctly. + + * gettext.c: Update copyright. + * gettext.h: Likewise. + * hash-string.h: Likewise. + + * finddomain.c: Remoave dead code. Define strchr only if + !HAVE_STRCHR. + + * explodename.c: Include . + + * explodename.c: Reformat copyright text. + (_nl_explode_name): Fix typo. + + * dcgettext.c: Define and use __set_errno. + (guess_category_value): Don't use setlocale if HAVE_LC_MESSAGES is + not defined. + + * bindtextdom.c: Pretty printing. + +1997-05-01 02:25 Ulrich Drepper + + * dcgettext.c (guess_category_value): Don't depend on + HAVE_LC_MESSAGES. We don't need the macro here. + Patch by Bruno Haible . + + * cat-compat.c (textdomain): DoN't refer to HAVE_SETLOCALE_NULL + macro. Instead use HAVE_LOCALE_NULL and define it when using + glibc, as in dcgettext.c. + Patch by Bruno Haible . + + * Makefile.in (CPPFLAGS): New variable. Reported by Franc,ois + Pinard. + +Mon Mar 10 06:51:17 1997 Ulrich Drepper + + * Makefile.in: Implement handling of libtool. + + * gettextP.h: Change data structures for use of generic lowlevel + i18n file handling. + +Wed Dec 4 20:21:18 1996 Ulrich Drepper + + * textdomain.c: Put parentheses around arguments of memcpy macro + definition. + * localealias.c: Likewise. + * l10nflist.c: Likewise. + * finddomain.c: Likewise. + * bindtextdom.c: Likewise. + Reported by Thomas Esken. + +Mon Nov 25 22:57:51 1996 Ulrich Drepper + + * textdomain.c: Move definition of `memcpy` macro to right + position. + +Fri Nov 22 04:01:58 1996 Ulrich Drepper + + * finddomain.c [!HAVE_STRING_H && !_LIBC]: Define memcpy using + bcopy if not already defined. Reported by Thomas Esken. + * bindtextdom.c: Likewise. + * l10nflist.c: Likewise. + * localealias.c: Likewise. + * textdomain.c: Likewise. + +Tue Oct 29 11:10:27 1996 Ulrich Drepper + + * Makefile.in (libdir): Change to use exec_prefix instead of + prefix. Reported by Knut-HåvardAksnes . + +Sat Aug 31 03:07:09 1996 Ulrich Drepper + + * l10nflist.c (_nl_normalize_codeset): We convert to lower case, + so don't prepend uppercase `ISO' for only numeric arg. + +Fri Jul 19 00:15:46 1996 Ulrich Drepper + + * l10nflist.c: Move inclusion of argz.h, ctype.h, stdlib.h after + definition of _GNU_SOURCE. Patch by Roland McGrath. + + * Makefile.in (uninstall): Fix another bug with `for' loop and + empty arguments. Patch by Jim Meyering. Correct name os + uninstalled files: no intl- prefix anymore. + + * Makefile.in (install-data): Again work around shells which + cannot handle mpty for list. Reported by Jim Meyering. + +Sat Jul 13 18:11:35 1996 Ulrich Drepper + + * Makefile.in (install): Split goal. Now depend on install-exec + and install-data. + (install-exec, install-data): New goals. Created from former + install goal. + Reported by Karl Berry. + +Sat Jun 22 04:58:14 1996 Ulrich Drepper + + * Makefile.in (MKINSTALLDIRS): New variable. Path to + mkinstalldirs script. + (install): use MKINSTALLDIRS variable or if the script is not present + try to find it in the $top_scrdir). + +Wed Jun 19 02:56:56 1996 Ulrich Drepper + + * l10nflist.c: Linux libc *partly* includes the argz_* functions. + Grr. Work around by renaming the static version and use macros + for renaming. + +Tue Jun 18 20:11:17 1996 Ulrich Drepper + + * l10nflist.c: Correct presence test macros of __argz_* functions. + + * l10nflist.c: Include based on test of it instead when + __argz_* functions are available. + Reported by Andreas Schwab. + +Thu Jun 13 15:17:44 1996 Ulrich Drepper + + * explodename.c, l10nflist.c: Define NULL for dumb systems. + +Tue Jun 11 17:05:13 1996 Ulrich Drepper + + * intlh.inst.in, libgettext.h (dcgettext): Rename local variable + result to __result to prevent name clash. + + * l10nflist.c, localealias.c, dcgettext.c: Define _GNU_SOURCE to + get prototype for stpcpy and strcasecmp. + + * intlh.inst.in, libgettext.h: Move declaration of + `_nl_msg_cat_cntr' outside __extension__ block to prevent warning + from gcc's -Wnested-extern option. + +Fri Jun 7 01:58:00 1996 Ulrich Drepper + + * Makefile.in (install): Remove comment. + +Thu Jun 6 17:28:17 1996 Ulrich Drepper + + * Makefile.in (install): Work around for another Buglix stupidity. + Always use an `else' close for `if's. Reported by Nelson Beebe. + + * Makefile.in (intlh.inst): Correct typo in phony rule. + Reported by Nelson Beebe. + +Thu Jun 6 01:49:52 1996 Ulrich Drepper + + * dcgettext.c (read_alias_file): Rename variable alloca_list to + block_list as the macro calls assume. + Patch by Eric Backus. + + * localealias.c [!HAVE_ALLOCA]: Define alloca as macro using + malloc. + (read_alias_file): Rename varriabe alloca_list to block_list as the + macro calls assume. + Patch by Eric Backus. + + * l10nflist.c: Correct conditional for inclusion. + Reported by Roland McGrath. + + * Makefile.in (all): Depend on all-@USE_INCLUDED_LIBINTL@, not + all-@USE_NLS@. + + * Makefile.in (install): intlh.inst comes from local dir, not + $(srcdir). + + * Makefile.in (intlh.inst): Special handling of this goal. If + used in gettext, this is really a rul to construct this file. If + used in any other package it is defined as a .PHONY rule with + empty body. + + * finddomain.c: Extract locale file information handling into + l10nfile.c. Rename local stpcpy__ function to stpcpy. + + * dcgettext.c (stpcpy): Add local definition. + + * l10nflist.c: Solve some portability problems. Patches partly by + Thomas Esken. Add local definition of stpcpy. + +Tue Jun 4 02:47:49 1996 Ulrich Drepper + + * intlh.inst.in: Don't depend including on + HAVE_LOCALE_H. Instead configure must rewrite this fiile + depending on the result of the configure run. + + * Makefile.in (install): libintl.inst is now called intlh.inst. + Add rules for updating intlh.inst from intlh.inst.in. + + * libintl.inst: Renamed to intlh.inst.in. + + * localealias.c, dcgettext.c [__GNUC__]: Define HAVE_ALLOCA to 1 + because gcc has __buitlin_alloca. + Reported by Roland McGrath. + +Mon Jun 3 00:32:16 1996 Ulrich Drepper + + * Makefile.in (installcheck): New goal to fulfill needs of + automake's distcheck. + + * Makefile.in (install): Reorder commands so that VERSION is + found. + + * Makefile.in (gettextsrcdir): Now use subdirectory intl/ in + @datadir@/gettext. + (COMSRCS): Add l10nfile.c. + (OBJECTS): Add l10nfile.o. + (DISTFILES): Rename to DISTFILE.normal. Remove $(DISTFILES.common). + (DISTFILE.gettext): Remove $(DISTFILES.common). + (all-gettext): Remove goal. + (install): If $(PACKAGE) = gettext install, otherwose do nothing. No + package but gettext itself should install libintl.h + headers. + (dist): Extend goal to work for gettext, too. + (dist-gettext): Remove goal. + + * dcgettext.c [!HAVE_ALLOCA]: Define macro alloca by using malloc. + +Sun Jun 2 17:33:06 1996 Ulrich Drepper + + * loadmsgcat.c (_nl_load_domain): Parameter is now comes from + find_l10nfile. + +Sat Jun 1 02:23:03 1996 Ulrich Drepper + + * l10nflist.c (__argz_next): Add definition. + + * dcgettext.c [!HAVE_ALLOCA]: Add code for handling missing alloca + code. Use new l10nfile handling. + + * localealias.c [!HAVE_ALLOCA]: Add code for handling missing + alloca code. + + * l10nflist.c: Initial revision. + +Tue Apr 2 18:51:18 1996 Ulrich Drepper + + * Makefile.in (all-gettext): New goal. Same as all-yes. + +Thu Mar 28 23:01:22 1996 Karl Eichwalder + + * Makefile.in (gettextsrcdir): Define using @datadir@. + +Tue Mar 26 12:39:14 1996 Ulrich Drepper + + * finddomain.c: Include . Reported by Roland McGrath. + +Sat Mar 23 02:00:35 1996 Ulrich Drepper + + * finddomain.c (stpcpy): Rename to stpcpy__ to prevent clashing + with external declaration. + +Sat Mar 2 00:47:09 1996 Ulrich Drepper + + * Makefile.in (all-no): Rename from all_no. + +Sat Feb 17 00:25:59 1996 Ulrich Drepper + + * gettextP.h [loaded_domain]: Array `successor' must now contain up + to 63 elements (because of codeset name normalization). + + * finddomain.c: Implement codeset name normalization. + +Thu Feb 15 04:39:09 1996 Ulrich Drepper + + * Makefile.in (all): Define to `all-@USE_NLS@'. + (all-yes, all_no): New goals. `all-no' is noop, `all-yes' + is former all. + +Mon Jan 15 21:46:01 1996 Howard Gayle + + * localealias.c (alias_compare): Increment string pointers in loop + of strcasecmp replacement. + +Fri Dec 29 21:16:34 1995 Ulrich Drepper + + * Makefile.in (install-src): Who commented this goal out ? :-) + +Fri Dec 29 15:08:16 1995 Ulrich Drepper + + * dcgettext.c (DCGETTEXT): Save `errno'. Failing system calls + should not effect it because a missing catalog is no error. + Reported by Harald Knig . + +Tue Dec 19 22:09:13 1995 Ulrich Drepper + + * Makefile.in (Makefile): Explicitly use $(SHELL) for running + shell scripts. + +Fri Dec 15 17:34:59 1995 Andreas Schwab + + * Makefile.in (install-src): Only install library and header when + we use the own implementation. Don't do it when using the + system's gettext or catgets functions. + + * dcgettext.c (find_msg): Must not swap domain->hash_size here. + +Sat Dec 9 16:24:37 1995 Ulrich Drepper + + * localealias.c, libintl.inst, libgettext.h, hash-string.h, + gettextP.h, finddomain.c, dcgettext.c, cat-compat.c: + Use PARAMS instead of __P. Suggested by Roland McGrath. + +Tue Dec 5 11:39:14 1995 Larry Schwimmer + + * libgettext.h: Use `#if !defined (_LIBINTL_H)' instead of `#if + !_LIBINTL_H' because Solaris defines _LIBINTL_H as empty. + +Mon Dec 4 15:42:07 1995 Ulrich Drepper + + * Makefile.in (install-src): + Install libintl.inst instead of libintl.h.install. + +Sat Dec 2 22:51:38 1995 Marcus Daniels + + * cat-compat.c (textdomain): + Reverse order in which files are tried you load. First + try local file, when this failed absolute path. + +Wed Nov 29 02:03:53 1995 Nelson H. F. Beebe + + * cat-compat.c (bindtextdomain): Add missing { }. + +Sun Nov 26 18:21:41 1995 Ulrich Drepper + + * libintl.inst: Add missing __P definition. Reported by Nelson Beebe. + + * Makefile.in: + Add dummy `all' and `dvi' goals. Reported by Tom Tromey. + +Sat Nov 25 16:12:01 1995 Franc,ois Pinard + + * hash-string.h: Capitalize arguments of macros. + +Sat Nov 25 12:01:36 1995 Ulrich Drepper + + * Makefile.in (DISTFILES): Prevent files names longer than 13 + characters. libintl.h.glibc->libintl.glibc, + libintl.h.install->libintl.inst. Reported by Joshua R. Poulson. + +Sat Nov 25 11:31:12 1995 Eric Backus + + * dcgettext.c: Fix bug in preprocessor conditionals. + +Sat Nov 25 02:35:27 1995 Nelson H. F. Beebe + + * libgettext.h: Solaris cc does not understand + #if !SYMBOL1 && !SYMBOL2. Sad but true. + +Thu Nov 23 16:22:14 1995 Ulrich Drepper + + * hash-string.h (hash_string): + Fix for machine with >32 bit `unsigned long's. + + * dcgettext.c (DCGETTEXT): + Fix horrible bug in loop for alternative translation. + +Thu Nov 23 01:45:29 1995 Ulrich Drepper + + * po2tbl.sed.in, linux-msg.sed, xopen-msg.sed: + Some further simplifications in message number generation. + +Mon Nov 20 21:08:43 1995 Ulrich Drepper + + * libintl.h.glibc: Use __const instead of const in prototypes. + + * Makefile.in (install-src): + Install libintl.h.install instead of libintl.h. This + is a stripped-down version. Suggested by Peter Miller. + + * libintl.h.install, libintl.h.glibc: Initial revision. + + * localealias.c (_nl_expand_alias, read_alias_file): + Protect prototypes in type casts by __P. + +Tue Nov 14 16:43:58 1995 Ulrich Drepper + + * hash-string.h: Correct prototype for hash_string. + +Sun Nov 12 12:42:30 1995 Ulrich Drepper + + * hash-string.h (hash_string): Add prototype. + + * gettextP.h: Fix copyright. + (SWAP): Add prototype. + +Wed Nov 8 22:56:33 1995 Ulrich Drepper + + * localealias.c (read_alias_file): Forgot sizeof. + Avoid calling *printf function. This introduces a big overhead. + Patch by Roland McGrath. + +Tue Nov 7 14:21:08 1995 Ulrich Drepper + + * finddomain.c, cat-compat.c: Wrong indentation in #if for stpcpy. + + * finddomain.c (stpcpy): + Define substitution function local. The macro was to flaky. + + * cat-compat.c: Fix typo. + + * xopen-msg.sed, linux-msg.sed: + While bringing message number to right place only accept digits. + + * linux-msg.sed, xopen-msg.sed: Now that the counter does not have + leading 0s we don't need to remove them. Reported by Marcus + Daniels. + + * Makefile.in (../po/cat-id-tbl.o): Use $(top_srdir) in + dependency. Reported by Marcus Daniels. + + * cat-compat.c: (stpcpy) [!_LIBC && !HAVE_STPCPY]: Define replacement. + Generally cleanup using #if instead of #ifndef. + + * Makefile.in: Correct typos in comment. By Franc,ois Pinard. + +Mon Nov 6 00:27:02 1995 Ulrich Drepper + + * Makefile.in (install-src): Don't install libintl.h and libintl.a + if we use an available gettext implementation. + +Sun Nov 5 22:02:08 1995 Ulrich Drepper + + * libgettext.h: Fix typo: HAVE_CATGETTS -> HAVE_CATGETS. Reported + by Franc,ois Pinard. + + * libgettext.h: Use #if instead of #ifdef/#ifndef. + + * finddomain.c: + Comments describing what has to be done should start with FIXME. + +Sun Nov 5 19:38:01 1995 Ulrich Drepper + + * Makefile.in (DISTFILES): Split. Use DISTFILES with normal meaning. + DISTFILES.common names the files common to both dist goals. + DISTFILES.gettext are the files only distributed in GNU gettext. + +Sun Nov 5 17:32:54 1995 Ulrich Drepper + + * dcgettext.c (DCGETTEXT): Correct searching in derived locales. + This was necessary since a change in _nl_find_msg several weeks + ago. I really don't know this is still not fixed. + +Sun Nov 5 12:43:12 1995 Ulrich Drepper + + * loadmsgcat.c (_nl_load_domain): Test for FILENAME == NULL. This + might mark a special condition. + + * finddomain.c (make_entry_rec): Don't make illegal entry as decided. + + * Makefile.in (dist): Suppress error message when ln failed. + Get files from $(srcdir) explicitly. + + * libgettext.h (gettext_const): Rename to gettext_noop. + +Fri Nov 3 07:36:50 1995 Ulrich Drepper + + * finddomain.c (make_entry_rec): + Protect against wrong locale names by testing mask. + + * libgettext.h (gettext_const): Add macro definition. + Capitalize macro arguments. + +Thu Nov 2 23:15:51 1995 Ulrich Drepper + + * finddomain.c (_nl_find_domain): + Test for pointer != NULL before accessing value. + Reported by Tom Tromey. + + * gettext.c (NULL): + Define as (void*)0 instad of 0. Reported by Franc,ois Pinard. + +Mon Oct 30 21:28:52 1995 Ulrich Drepper + + * po2tbl.sed.in: Serious typo bug fixed by Jim Meyering. + +Sat Oct 28 23:20:47 1995 Ulrich Drepper + + * libgettext.h: Disable dcgettext optimization for Solaris 2.3. + + * localealias.c (alias_compare): + Peter Miller reported that tolower in some systems is + even dumber than I thought. Protect call by `isupper'. + +Fri Oct 27 22:22:51 1995 Ulrich Drepper + + * Makefile.in (libdir, includedir): New variables. + (install-src): Install libintl.a and libintl.h in correct dirs. + +Fri Oct 27 22:07:29 1995 Ulrich Drepper + + * Makefile.in (SOURCES): Fix typo: intrl.compat.c -> intl-compat.c. + + * po2tbl.sed.in: Patch for buggy SEDs by Christian von Roques. + + * localealias.c: + Fix typo and superflous test. Reported by Christian von Roques. + +Fri Oct 6 11:52:05 1995 Ulrich Drepper + + * finddomain.c (_nl_find_domain): + Correct some remainder from the pre-CEN syntax. Now + we don't have a constant number of successors anymore. + +Wed Sep 27 21:41:13 1995 Ulrich Drepper + + * Makefile.in (DISTFILES): Add libintl.h.glibc. + + * Makefile.in (dist-libc): Add goal for packing sources for glibc. + (COMSRCS, COMHDRS): Splitted to separate sources shared with glibc. + + * loadmsgcat.c: Forget to continue #if line. + + * localealias.c: + [_LIBC]: Rename strcasecmp to __strcasecmp to keep ANSI C name + space clean. + + * dcgettext.c, finddomain.c: Better comment to last change. + + * loadmsgcat.c: + [_LIBC]: Rename fstat, open, close, read, mmap, and munmap to + __fstat, __open, __close, __read, __mmap, and __munmap resp + to keep ANSI C name space clean. + + * finddomain.c: + [_LIBC]: Rename stpcpy to __stpcpy to keep ANSI C name space clean. + + * dcgettext.c: + [_LIBC]: Rename getced and stpcpy to __getcwd and __stpcpy resp to + keep ANSI C name space clean. + + * libgettext.h: + Include sys/types.h for those old SysV systems out there. + Reported by Francesco Potorti`. + + * loadmsgcat.c (use_mmap): Define if compiled for glibc. + + * bindtextdom.c: Include all those standard headers + unconditionally if _LIBC is defined. + + * finddomain.c: Fix 2 times defiend -> defined. + + * textdomain.c: Include libintl.h instead of libgettext.h when + compiling for glibc. Include all those standard headers + unconditionally if _LIBC is defined. + + * localealias.c, loadmsgcat.c: Prepare to be compiled in glibc. + + * gettext.c: + Include libintl.h instead of libgettext.h when compiling for glibc. + Get NULL from stddef.h if we compile for glibc. + + * finddomain.c: Include libintl.h instead of libgettext.h when + compiling for glibc. Include all those standard headers + unconditionally if _LIBC is defined. + + * dcgettext.c: Include all those standard headers unconditionally + if _LIBC is defined. + + * dgettext.c: If compiled in glibc include libintl.h instead of + libgettext.h. + (locale.h): Don't rely on HAVE_LOCALE_H when compiling for glibc. + + * dcgettext.c: If compiled in glibc include libintl.h instead of + libgettext.h. + (getcwd): Don't rely on HAVE_GETCWD when compiling for glibc. + + * bindtextdom.c: + If compiled in glibc include libintl.h instead of libgettext.h. + +Mon Sep 25 22:23:06 1995 Ulrich Drepper + + * localealias.c (_nl_expand_alias): Don't call bsearch if NMAP <= 0. + Reported by Marcus Daniels. + + * cat-compat.c (bindtextdomain): + String used in putenv must not be recycled. + Reported by Marcus Daniels. + + * libgettext.h (__USE_GNU_GETTEXT): + Additional symbol to signal that we use GNU gettext + library. + + * cat-compat.c (bindtextdomain): + Fix bug with the strange stpcpy replacement. + Reported by Nelson Beebe. + +Sat Sep 23 08:23:51 1995 Ulrich Drepper + + * cat-compat.c: Include for stpcpy prototype. + + * localealias.c (read_alias_file): + While expand strdup code temporary variable `cp' hided + higher level variable with same name. Rename to `tp'. + + * textdomain.c (textdomain): + Avoid warning by using temporary variable in strdup code. + + * finddomain.c (_nl_find_domain): Remove unused variable `application'. + +Thu Sep 21 15:51:44 1995 Ulrich Drepper + + * localealias.c (alias_compare): + Use strcasecmp() only if available. Else use + implementation in place. + + * intl-compat.c: + Wrapper functions now call *__ functions instead of __*. + + * libgettext.h: Declare prototypes for *__ functions instead for __*. + + * cat-compat.c, loadmsgcat.c: + Don't use xmalloc, xstrdup, and stpcpy. These functions are not part + of the standard libc and so prevent libintl.a from being used + standalone. + + * bindtextdom.c: + Don't use xmalloc, xstrdup, and stpcpy. These functions are not part + of the standard libc and so prevent libintl.a from being used + standalone. + Rename to bindtextdomain__ if not used in GNU C Library. + + * dgettext.c: + Rename function to dgettext__ if not used in GNU C Library. + + * gettext.c: + Don't use xmalloc, xstrdup, and stpcpy. These functions are not part + of the standard libc and so prevent libintl.a from being used + standalone. + Functions now called gettext__ if not used in GNU C Library. + + * dcgettext.c, localealias.c, textdomain.c, finddomain.c: + Don't use xmalloc, xstrdup, and stpcpy. These functions are not part + of the standard libc and so prevent libintl.a from being used + standalone. + +Sun Sep 17 23:14:49 1995 Ulrich Drepper + + * finddomain.c: Correct some bugs in handling of CEN standard + locale definitions. + +Thu Sep 7 01:49:28 1995 Ulrich Drepper + + * finddomain.c: Implement CEN syntax. + + * gettextP.h (loaded_domain): Extend number of successors to 31. + +Sat Aug 19 19:25:29 1995 Ulrich Drepper + + * Makefile.in (aliaspath): Remove path to X11 locale dir. + + * Makefile.in: Make install-src depend on install. This helps + gettext to install the sources and other packages can use the + install goal. + +Sat Aug 19 15:19:33 1995 Ulrich Drepper + + * Makefile.in (uninstall): Remove stuff installed by install-src. + +Tue Aug 15 13:13:53 1995 Ulrich Drepper + + * VERSION.in: Initial revision. + + * Makefile.in (DISTFILES): + Add VERSION file. This is not necessary for gettext, but + for other packages using this library. + +Tue Aug 15 06:16:44 1995 Ulrich Drepper + + * gettextP.h (_nl_find_domain): + New prototype after changing search strategy. + + * finddomain.c (_nl_find_domain): + We now try only to find a specified catalog. Fall back to other + catalogs listed in the locale list is now done in __dcgettext. + + * dcgettext.c (__dcgettext): + Now we provide message fall back even to different languages. + I.e. if a message is not available in one language all the other + in the locale list a tried. Formerly fall back was only possible + within one language. Implemented by moving one loop from + _nl_find_domain to here. + +Mon Aug 14 23:45:50 1995 Ulrich Drepper + + * Makefile.in (gettextsrcdir): + Directory where source of GNU gettext library are made + available. + (INSTALL, INSTALL_DATA): Programs used for installing sources. + (gettext-src): New. Rule to install GNU gettext sources for use in + gettextize shell script. + +Sun Aug 13 14:40:48 1995 Ulrich Drepper + + * loadmsgcat.c (_nl_load_domain): + Use mmap for loading only when munmap function is + also available. + + * Makefile.in (install): Depend on `all' goal. + +Wed Aug 9 11:04:33 1995 Ulrich Drepper + + * localealias.c (read_alias_file): + Do not overwrite '\n' when terminating alias value string. + + * localealias.c (read_alias_file): + Handle long lines. Ignore the rest not fitting in + the buffer after the initial `fgets' call. + +Wed Aug 9 00:54:29 1995 Ulrich Drepper + + * gettextP.h (_nl_load_domain): + Add prototype, replacing prototype for _nl_load_msg_cat. + + * finddomain.c (_nl_find_domain): + Remove unneeded variable filename and filename_len. + (expand_alias): Remove prototype because functions does not + exist anymore. + + * localealias.c (read_alias_file): + Change type of fname_len parameter to int. + (xmalloc): Add prototype. + + * loadmsgcat.c: Better prototypes for xmalloc. + +Tue Aug 8 22:30:39 1995 Ulrich Drepper + + * finddomain.c (_nl_find_domain): + Allow alias name to be constructed from the four components. + + * Makefile.in (aliaspath): New variable. Set to preliminary value. + (SOURCES): Add localealias.c. + (OBJECTS): Add localealias.o. + + * gettextP.h: Add prototype for _nl_expand_alias. + + * finddomain.c: Aliasing handled in intl/localealias.c. + + * localealias.c: Aliasing for locale names. + + * bindtextdom.c: Better prototypes for xmalloc and xstrdup. + +Mon Aug 7 23:47:42 1995 Ulrich Drepper + + * Makefile.in (DISTFILES): gettext.perl is now found in misc/. + + * cat-compat.c (bindtextdomain): + Correct implementation. dirname parameter was not used. + Reported by Marcus Daniels. + + * gettextP.h (loaded_domain): + New fields `successor' and `decided' for oo, lazy + message handling implementation. + + * dcgettext.c: + Adopt for oo, lazy message handliing. + Now we can inherit translations from less specific locales. + (find_msg): New function. + + * loadmsgcat.c, finddomain.c: + Complete rewrite. Implement oo, lazy message handling :-). + We now have an additional environment variable `LANGUAGE' with + a higher priority than LC_ALL for the LC_MESSAGE locale. + Here we can set a colon separated list of specifications each + of the form `language[_territory[.codeset]][@modifier]'. + +Sat Aug 5 09:55:42 1995 Ulrich Drepper + + * finddomain.c (unistd.h): + Include to get _PC_PATH_MAX defined on system having it. + +Fri Aug 4 22:42:00 1995 Ulrich Drepper + + * finddomain.c (stpcpy): Include prototype. + + * Makefile.in (dist): Remove `copying instead' message. + +Wed Aug 2 18:52:03 1995 Ulrich Drepper + + * Makefile.in (ID, TAGS): Do not use $^. + +Tue Aug 1 20:07:11 1995 Ulrich Drepper + + * Makefile.in (TAGS, ID): Use $^ as command argument. + (TAGS): Give etags -o option t write to current directory, + not $(srcdir). + (ID): Use $(srcdir) instead os $(top_srcdir)/src. + (distclean): Remove ID. + +Sun Jul 30 11:51:46 1995 Ulrich Drepper + + * Makefile.in (gnulocaledir): + New variable, always using share/ for data directory. + (DEFS): Add GNULOCALEDIR, used in finddomain.c. + + * finddomain.c (_nl_default_dirname): + Set to GNULOCALEDIR, because it always has to point + to the directory where GNU gettext Library writes it to. + + * intl-compat.c (textdomain, bindtextdomain): + Undefine macros before function definition. + +Sat Jul 22 01:10:02 1995 Ulrich Drepper + + * libgettext.h (_LIBINTL_H): + Protect definition in case where this file is included as + libgettext.h on Solaris machines. Add comment about this. + +Wed Jul 19 02:36:42 1995 Ulrich Drepper + + * intl-compat.c (textdomain): Correct typo. + +Wed Jul 19 01:51:35 1995 Ulrich Drepper + + * dcgettext.c (dcgettext): Function now called __dcgettext. + + * dgettext.c (dgettext): Now called __dgettext and calls + __dcgettext. + + * gettext.c (gettext): + Function now called __gettext and calls __dgettext. + + * textdomain.c (textdomain): Function now called __textdomain. + + * bindtextdom.c (bindtextdomain): Function now called + __bindtextdomain. + + * intl-compat.c: Initial revision. + + * Makefile.in (SOURCES): Add intl-compat.c. + (OBJECTS): We always compile the GNU gettext library functions. + OBJECTS contains all objects but cat-compat.o, ../po/cat-if-tbl.o, + and intl-compat.o. + (GETTOBJS): Contains now only intl-compat.o. + + * libgettext.h: + Re-include protection matches dualistic character of libgettext.h. + For all functions in GNU gettext library define __ counter part. + + * finddomain.c (strchr): Define as index if not found in C library. + (_nl_find_domain): For relative paths paste / in between. + +Tue Jul 18 16:37:45 1995 Ulrich Drepper + + * loadmsgcat.c, finddomain.c: Add inclusion of sys/types.h. + + * xopen-msg.sed: Fix bug with `msgstr ""' lines. + A little bit better comments. + +Tue Jul 18 01:18:27 1995 Ulrich Drepper + + * Makefile.in: + po-mode.el, makelinks, combine-sh are now found in ../misc. + + * po-mode.el, makelinks, combine-sh, elisp-comp: + Moved to ../misc/. + + * libgettext.h, gettextP.h, gettext.h: Uniform test for __STDC__. + +Sun Jul 16 22:33:02 1995 Ulrich Drepper + + * Makefile.in (INSTALL, INSTALL_DATA): New variables. + (install-data, uninstall): Install/uninstall .elc file. + + * po-mode.el (Installation comment): + Add .pox as possible extension of .po files. + +Sun Jul 16 13:23:27 1995 Ulrich Drepper + + * elisp-comp: Complete new version by Franc,ois: This does not + fail when not compiling in the source directory. + +Sun Jul 16 00:12:17 1995 Ulrich Drepper + + * Makefile.in (../po/cat-id-tbl.o): + Use $(MAKE) instead of make for recursive make. + + * Makefile.in (.el.elc): Use $(SHELL) instead of /bin/sh. + (install-exec): Add missing dummy goal. + (install-data, uninstall): @ in multi-line shell command at + beginning, not in front of echo. Reported by Eric Backus. + +Sat Jul 15 00:21:28 1995 Ulrich Drepper + + * Makefile.in (DISTFILES): + Rename libgettext.perl to gettext.perl to fit in 14 chars + file systems. + + * gettext.perl: + Rename to gettext.perl to fit in 14 chars file systems. + +Thu Jul 13 23:17:20 1995 Ulrich Drepper + + * cat-compat.c: If !STDC_HEADERS try to include malloc.h. + +Thu Jul 13 20:55:02 1995 Ulrich Drepper + + * po2tbl.sed.in: Pretty printing. + + * linux-msg.sed, xopen-msg.sed: + Correct bugs with handling substitute flags in branches. + + * hash-string.h (hash_string): + Old K&R compilers don't under stand `unsigned char'. + + * gettext.h (nls_uint32): + Some old K&R compilers (eg HP) don't understand `unsigned int'. + + * cat-compat.c (msg_to_cat_id): De-ANSI-fy prototypes. + +Thu Jul 13 01:34:33 1995 Ulrich Drepper + + * Makefile.in (ELCFILES): New variable. + (DISTFILES): Add elisp-comp. + Add implicit rule for .el -> .elc compilation. + (install-data): install $ELCFILES + (clean): renamed po-to-tbl and po-to-msg to po2tbl and po2msg resp. + + * elisp-comp: Initial revision + +Wed Jul 12 16:14:52 1995 Ulrich Drepper + + * Makefile.in: + cat-id-tbl.c is now found in po/. This enables us to use an identical + intl/ directory in all packages. + + * dcgettext.c (dcgettext): hashing does not work for table size <= 2. + + * textdomain.c: fix typo (#if def -> #if defined) + +Tue Jul 11 18:44:43 1995 Ulrich Drepper + + * Makefile.in (stamp-cat-id): use top_srcdir to address source files + (DISTFILES,distclean): move tupdate.perl to src/ + + * po-to-tbl.sed.in: + add additional jump to clear change flag to recognize multiline strings + +Tue Jul 11 01:32:50 1995 Ulrich Drepper + + * textdomain.c: Protect inclusion of stdlib.h and string.h. + + * loadmsgcat.c: Protect inclusion of stdlib.h. + + * libgettext.h: Protect inclusion of locale.h. + Allow use in C++ programs. + Define NULL is not happened already. + + * Makefile.in (DISTFILES): ship po-to-tbl.sed.in instead of + po-to-tbl.sed. + (distclean): remove po-to-tbl.sed and tupdate.perl. + + * tupdate.perl.in: Substitute Perl path even in exec line. + Don't include entries without translation from old .po file. + +Tue Jul 4 00:41:51 1995 Ulrich Drepper + + * tupdate.perl.in: use "Updated: " in msgid "". + + * cat-compat.c: Fix typo (LOCALDIR -> LOCALEDIR). + Define getenv if !__STDC__. + + * bindtextdom.c: Protect stdlib.h and string.h inclusion. + Define free if !__STDC__. + + * finddomain.c: Change DEF_MSG_DOM_DIR to LOCALEDIR. + Define free if !__STDC__. + + * cat-compat.c: Change DEF_MSG_DOM_DIR to LOCALEDIR. + +Mon Jul 3 23:56:30 1995 Ulrich Drepper + + * Makefile.in: Use LOCALEDIR instead of DEF_MSG_DOM_DIR. + Remove unneeded $(srcdir) from Makefile.in dependency. + + * makelinks: Add copyright and short description. + + * po-mode.el: Last version for 0.7. + + * tupdate.perl.in: Fix die message. + + * dcgettext.c: Protect include of string.h. + + * gettext.c: Protect include of stdlib.h and further tries to get NULL. + + * finddomain.c: Some corrections in includes. + + * Makefile.in (INCLUDES): Prune list correct path to Makefile.in. + + * po-to-tbl.sed: Adopt for new .po file format. + + * linux-msg.sed, xopen-msg.sed: Adopt for new .po file format. + +Sun Jul 2 23:55:03 1995 Ulrich Drepper + + * tupdate.perl.in: Complete rewrite for new .po file format. + +Sun Jul 2 02:06:50 1995 Ulrich Drepper + + * First official release. This directory contains all the code + needed to internationalize own packages. It provides functions + which allow to use the X/Open catgets function with an interface + like the Uniforum gettext function. For system which does not + have neither of those a complete implementation is provided. diff --git a/intl/Makefile.in b/intl/Makefile.in new file mode 100644 index 00000000..4bdb186d --- /dev/null +++ b/intl/Makefile.in @@ -0,0 +1,214 @@ +# Makefile for directory with message catalog handling in GNU NLS Utilities. +# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +# +# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = .. +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +transform = @program_transform_name@ +libdir = $(exec_prefix)/lib +includedir = $(prefix)/include +datadir = $(prefix)/@DATADIRNAME@ +localedir = $(datadir)/locale +gnulocaledir = $(prefix)/share/locale +gettextsrcdir = @datadir@/gettext/intl +aliaspath = $(localedir):. +subdir = intl + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = @MKINSTALLDIRS@ + +l = @l@ + +AR = ar +CC = @CC@ +LIBTOOL = @LIBTOOL@ +RANLIB = @RANLIB@ + +DEFS = -DLOCALEDIR=\"$(localedir)\" -DGNULOCALEDIR=\"$(gnulocaledir)\" \ +-DLOCALE_ALIAS_PATH=\"$(aliaspath)\" @DEFS@ +CPPFLAGS = @CPPFLAGS@ +CFLAGS = @CFLAGS@ +LDFLAGS = @LDFLAGS@ + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +HEADERS = $(COMHDRS) libgettext.h loadinfo.h +COMHDRS = gettext.h gettextP.h hash-string.h +SOURCES = $(COMSRCS) intl-compat.c cat-compat.c +COMSRCS = bindtextdom.c dcgettext.c dgettext.c gettext.c \ +finddomain.c loadmsgcat.c localealias.c textdomain.c l10nflist.c \ +explodename.c +OBJECTS = @INTLOBJS@ bindtextdom.$lo dcgettext.$lo dgettext.$lo gettext.$lo \ +finddomain.$lo loadmsgcat.$lo localealias.$lo textdomain.$lo l10nflist.$lo \ +explodename.$lo +CATOBJS = cat-compat.$lo ../po/cat-id-tbl.$lo +GETTOBJS = intl-compat.$lo +DISTFILES.common = ChangeLog Makefile.in linux-msg.sed po2tbl.sed.in \ +xopen-msg.sed $(HEADERS) $(SOURCES) +DISTFILES.normal = VERSION +DISTFILES.gettext = libintl.glibc intlh.inst.in + +.SUFFIXES: +.SUFFIXES: .c .o .lo +.c.o: + $(COMPILE) $< +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) $< + +INCLUDES = -I.. -I. -I$(top_srcdir)/intl -I$(top_srcdir)/lib + +all: all-@USE_INCLUDED_LIBINTL@ + +all-yes: libintl.$la intlh.inst +all-no: + +libintl.a: $(OBJECTS) + rm -f $@ + $(AR) cru $@ $(OBJECTS) + $(RANLIB) $@ + +libintl.la: $(OBJECTS) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $(OBJECTS) \ + -version-info 1:0 -rpath $(libdir) + +../po/cat-id-tbl.$lo: ../po/cat-id-tbl.c $(top_srcdir)/po/$(PACKAGE).pot + cd ../po && $(MAKE) cat-id-tbl.$lo + +check: all + +# This installation goal is only used in GNU gettext. Packages which +# only use the library should use install instead. + +# We must not install the libintl.h/libintl.a files if we are on a +# system which has the gettext() function in its C library or in a +# separate library or use the catgets interface. A special case is +# where configure found a previously installed GNU gettext library. +# If you want to use the one which comes with this version of the +# package, you have to use `configure --with-included-gettext'. +install: install-exec install-data +install-exec: all + if test "$(PACKAGE)" = "gettext" \ + && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $(libdir) $(includedir); \ + else \ + $(top_srcdir)/mkinstalldirs $(libdir) $(includedir); \ + fi; \ + $(INSTALL_DATA) intlh.inst $(includedir)/libintl.h; \ + $(INSTALL_DATA) libintl.a $(libdir)/libintl.a; \ + else \ + : ; \ + fi +install-data: all + if test "$(PACKAGE)" = "gettext"; then \ + if test -r $(MKINSTALLDIRS); then \ + $(MKINSTALLDIRS) $(gettextsrcdir); \ + else \ + $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \ + fi; \ + $(INSTALL_DATA) VERSION $(gettextsrcdir)/VERSION; \ + dists="$(DISTFILES.common)"; \ + for file in $$dists; do \ + $(INSTALL_DATA) $(srcdir)/$$file $(gettextsrcdir)/$$file; \ + done; \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + dists="$(DISTFILES.common)"; \ + for file in $$dists; do \ + rm -f $(gettextsrcdir)/$$file; \ + done + +info dvi: + +$(OBJECTS): ../config.h libgettext.h +bindtextdom.$lo finddomain.$lo loadmsgcat.$lo: gettextP.h gettext.h loadinfo.h +dcgettext.$lo: gettextP.h gettext.h hash-string.h loadinfo.h + +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES) + +id: ID + +ID: $(HEADERS) $(SOURCES) + here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES) + + +mostlyclean: + rm -f *.a *.o *.lo core core.* + +clean: mostlyclean + +distclean: clean + rm -f Makefile ID TAGS po2msg.sed po2tbl.sed + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + + +# GNU gettext needs not contain the file `VERSION' but contains some +# other files which should not be distributed in other packages. +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: Makefile $(DISTFILES) + if test "$(PACKAGE)" = gettext; then \ + additional="$(DISTFILES.gettext)"; \ + else \ + additional="$(DISTFILES.normal)"; \ + fi; \ + for file in $(DISTFILES.common) $$additional; do \ + ln $(srcdir)/$$file $(distdir) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(distdir); \ + done + +dist-libc: + tar zcvf intl-glibc.tar.gz $(COMSRCS) $(COMHDRS) libintl.h.glibc + +Makefile: Makefile.in ../config.status + cd .. \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +# The dependency for intlh.inst is different in gettext and all other +# packages. Because we cannot you GNU make features we have to solve +# the problem while rewriting Makefile.in. +@GT_YES@intlh.inst: intlh.inst.in ../config.status +@GT_YES@ cd .. \ +@GT_YES@ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= \ +@GT_YES@ $(SHELL) ./config.status +@GT_NO@.PHONY: intlh.inst +@GT_NO@intlh.inst: + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/intl/VERSION b/intl/VERSION new file mode 100644 index 00000000..ee66b061 --- /dev/null +++ b/intl/VERSION @@ -0,0 +1 @@ +GNU gettext library from gettext-0.10.35 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c new file mode 100644 index 00000000..d9c3f349 --- /dev/null +++ b/intl/bindtextdom.c @@ -0,0 +1,203 @@ +/* Implementation of the bindtextdomain(3) function + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#else +# ifdef HAVE_MALLOC_H +# include +# else +void free (); +# endif +#endif + +#if defined HAVE_STRING_H || defined _LIBC +# include +#else +# include +# ifndef memcpy +# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num) +# endif +#endif + +#ifdef _LIBC +# include +#else +# include "libgettext.h" +#endif +#include "gettext.h" +#include "gettextP.h" + +/* @@ end of prolog @@ */ + +/* Contains the default location of the message catalogs. */ +extern const char _nl_default_dirname[]; + +/* List with bindings of specific domains. */ +extern struct binding *_nl_domain_bindings; + + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define BINDTEXTDOMAIN __bindtextdomain +# ifndef strdup +# define strdup(str) __strdup (str) +# endif +#else +# define BINDTEXTDOMAIN bindtextdomain__ +#endif + +/* Specify that the DOMAINNAME message catalog will be found + in DIRNAME rather than in the system locale data base. */ +char * +BINDTEXTDOMAIN (domainname, dirname) + const char *domainname; + const char *dirname; +{ + struct binding *binding; + + /* Some sanity checks. */ + if (domainname == NULL || domainname[0] == '\0') + return NULL; + + for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) + { + int compare = strcmp (domainname, binding->domainname); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It is not in the list. */ + binding = NULL; + break; + } + } + + if (dirname == NULL) + /* The current binding has be to returned. */ + return binding == NULL ? (char *) _nl_default_dirname : binding->dirname; + + if (binding != NULL) + { + /* The domain is already bound. If the new value and the old + one are equal we simply do nothing. Otherwise replace the + old binding. */ + if (strcmp (dirname, binding->dirname) != 0) + { + char *new_dirname; + + if (strcmp (dirname, _nl_default_dirname) == 0) + new_dirname = (char *) _nl_default_dirname; + else + { +#if defined _LIBC || defined HAVE_STRDUP + new_dirname = strdup (dirname); + if (new_dirname == NULL) + return NULL; +#else + size_t len = strlen (dirname) + 1; + new_dirname = (char *) malloc (len); + if (new_dirname == NULL) + return NULL; + + memcpy (new_dirname, dirname, len); +#endif + } + + if (binding->dirname != _nl_default_dirname) + free (binding->dirname); + + binding->dirname = new_dirname; + } + } + else + { + /* We have to create a new binding. */ +#if !defined _LIBC && !defined HAVE_STRDUP + size_t len; +#endif + struct binding *new_binding = + (struct binding *) malloc (sizeof (*new_binding)); + + if (new_binding == NULL) + return NULL; + +#if defined _LIBC || defined HAVE_STRDUP + new_binding->domainname = strdup (domainname); + if (new_binding->domainname == NULL) + return NULL; +#else + len = strlen (domainname) + 1; + new_binding->domainname = (char *) malloc (len); + if (new_binding->domainname == NULL) + return NULL; + memcpy (new_binding->domainname, domainname, len); +#endif + + if (strcmp (dirname, _nl_default_dirname) == 0) + new_binding->dirname = (char *) _nl_default_dirname; + else + { +#if defined _LIBC || defined HAVE_STRDUP + new_binding->dirname = strdup (dirname); + if (new_binding->dirname == NULL) + return NULL; +#else + len = strlen (dirname) + 1; + new_binding->dirname = (char *) malloc (len); + if (new_binding->dirname == NULL) + return NULL; + memcpy (new_binding->dirname, dirname, len); +#endif + } + + /* Now enqueue it. */ + if (_nl_domain_bindings == NULL + || strcmp (domainname, _nl_domain_bindings->domainname) < 0) + { + new_binding->next = _nl_domain_bindings; + _nl_domain_bindings = new_binding; + } + else + { + binding = _nl_domain_bindings; + while (binding->next != NULL + && strcmp (domainname, binding->next->domainname) > 0) + binding = binding->next; + + new_binding->next = binding->next; + binding->next = new_binding; + } + + binding = new_binding; + } + + return binding->dirname; +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__bindtextdomain, bindtextdomain); +#endif diff --git a/intl/cat-compat.c b/intl/cat-compat.c new file mode 100644 index 00000000..867d901b --- /dev/null +++ b/intl/cat-compat.c @@ -0,0 +1,262 @@ +/* Compatibility code for gettext-using-catgets interface. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#ifdef STDC_HEADERS +# include +# include +#else +char *getenv (); +# ifdef HAVE_MALLOC_H +# include +# endif +#endif + +#ifdef HAVE_NL_TYPES_H +# include +#endif + +#include "libgettext.h" + +/* @@ end of prolog @@ */ + +/* XPG3 defines the result of `setlocale (category, NULL)' as: + ``Directs `setlocale()' to query `category' and return the current + setting of `local'.'' + However it does not specify the exact format. And even worse: POSIX + defines this not at all. So we can use this feature only on selected + system (e.g. those using GNU C Library). */ +#ifdef _LIBC +# define HAVE_LOCALE_NULL +#endif + +/* The catalog descriptor. */ +static nl_catd catalog = (nl_catd) -1; + +/* Name of the default catalog. */ +static const char default_catalog_name[] = "messages"; + +/* Name of currently used catalog. */ +static const char *catalog_name = default_catalog_name; + +/* Get ID for given string. If not found return -1. */ +static int msg_to_cat_id PARAMS ((const char *msg)); + +/* Substitution for systems lacking this function in their C library. */ +#if !_LIBC && !HAVE_STPCPY +static char *stpcpy PARAMS ((char *dest, const char *src)); +#endif + + +/* Set currently used domain/catalog. */ +char * +textdomain (domainname) + const char *domainname; +{ + nl_catd new_catalog; + char *new_name; + size_t new_name_len; + char *lang; + +#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES \ + && defined HAVE_LOCALE_NULL + lang = setlocale (LC_MESSAGES, NULL); +#else + lang = getenv ("LC_ALL"); + if (lang == NULL || lang[0] == '\0') + { + lang = getenv ("LC_MESSAGES"); + if (lang == NULL || lang[0] == '\0') + lang = getenv ("LANG"); + } +#endif + if (lang == NULL || lang[0] == '\0') + lang = "C"; + + /* See whether name of currently used domain is asked. */ + if (domainname == NULL) + return (char *) catalog_name; + + if (domainname[0] == '\0') + domainname = default_catalog_name; + + /* Compute length of added path element. */ + new_name_len = sizeof (LOCALEDIR) - 1 + 1 + strlen (lang) + + sizeof ("/LC_MESSAGES/") - 1 + sizeof (PACKAGE) - 1 + + sizeof (".cat"); + + new_name = (char *) malloc (new_name_len); + if (new_name == NULL) + return NULL; + + strcpy (new_name, PACKAGE); + new_catalog = catopen (new_name, 0); + + if (new_catalog == (nl_catd) -1) + { + /* NLSPATH search didn't work, try absolute path */ + sprintf (new_name, "%s/%s/LC_MESSAGES/%s.cat", LOCALEDIR, lang, + PACKAGE); + new_catalog = catopen (new_name, 0); + + if (new_catalog == (nl_catd) -1) + { + free (new_name); + return (char *) catalog_name; + } + } + + /* Close old catalog. */ + if (catalog != (nl_catd) -1) + catclose (catalog); + if (catalog_name != default_catalog_name) + free ((char *) catalog_name); + + catalog = new_catalog; + catalog_name = new_name; + + return (char *) catalog_name; +} + +char * +bindtextdomain (domainname, dirname) + const char *domainname; + const char *dirname; +{ +#if HAVE_SETENV || HAVE_PUTENV + char *old_val, *new_val, *cp; + size_t new_val_len; + + /* This does not make much sense here but to be compatible do it. */ + if (domainname == NULL) + return NULL; + + /* Compute length of added path element. If we use setenv we don't need + the first byts for NLSPATH=, but why complicate the code for this + peanuts. */ + new_val_len = sizeof ("NLSPATH=") - 1 + strlen (dirname) + + sizeof ("/%L/LC_MESSAGES/%N.cat"); + + old_val = getenv ("NLSPATH"); + if (old_val == NULL || old_val[0] == '\0') + { + old_val = NULL; + new_val_len += 1 + sizeof (LOCALEDIR) - 1 + + sizeof ("/%L/LC_MESSAGES/%N.cat"); + } + else + new_val_len += strlen (old_val); + + new_val = (char *) malloc (new_val_len); + if (new_val == NULL) + return NULL; + +# if HAVE_SETENV + cp = new_val; +# else + cp = stpcpy (new_val, "NLSPATH="); +# endif + + cp = stpcpy (cp, dirname); + cp = stpcpy (cp, "/%L/LC_MESSAGES/%N.cat:"); + + if (old_val == NULL) + { +# if __STDC__ + stpcpy (cp, LOCALEDIR "/%L/LC_MESSAGES/%N.cat"); +# else + + cp = stpcpy (cp, LOCALEDIR); + stpcpy (cp, "/%L/LC_MESSAGES/%N.cat"); +# endif + } + else + stpcpy (cp, old_val); + +# if HAVE_SETENV + setenv ("NLSPATH", new_val, 1); + free (new_val); +# else + putenv (new_val); + /* Do *not* free the environment entry we just entered. It is used + from now on. */ +# endif + +#endif + + return (char *) domainname; +} + +#undef gettext +char * +gettext (msg) + const char *msg; +{ + int msgid; + + if (msg == NULL || catalog == (nl_catd) -1) + return (char *) msg; + + /* Get the message from the catalog. We always use set number 1. + The message ID is computed by the function `msg_to_cat_id' + which works on the table generated by `po-to-tbl'. */ + msgid = msg_to_cat_id (msg); + if (msgid == -1) + return (char *) msg; + + return catgets (catalog, 1, msgid, (char *) msg); +} + +/* Look through the table `_msg_tbl' which has `_msg_tbl_length' entries + for the one equal to msg. If it is found return the ID. In case when + the string is not found return -1. */ +static int +msg_to_cat_id (msg) + const char *msg; +{ + int cnt; + + for (cnt = 0; cnt < _msg_tbl_length; ++cnt) + if (strcmp (msg, _msg_tbl[cnt]._msg) == 0) + return _msg_tbl[cnt]._msg_number; + + return -1; +} + + +/* @@ begin of epilog @@ */ + +/* We don't want libintl.a to depend on any other library. So we + avoid the non-standard function stpcpy. In GNU C Library this + function is available, though. Also allow the symbol HAVE_STPCPY + to be defined. */ +#if !_LIBC && !HAVE_STPCPY +static char * +stpcpy (dest, src) + char *dest; + const char *src; +{ + while ((*dest++ = *src++) != '\0') + /* Do nothing. */ ; + return dest - 1; +} +#endif diff --git a/intl/dcgettext.c b/intl/dcgettext.c new file mode 100644 index 00000000..0f7bb486 --- /dev/null +++ b/intl/dcgettext.c @@ -0,0 +1,655 @@ +/* Implementation of the dcgettext(3) function. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#if defined __GNUC__ && !defined C_ALLOCA +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# if (defined HAVE_ALLOCA_H || defined _LIBC) && !defined C_ALLOCA +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +#endif + +#include +#ifndef errno +extern int errno; +#endif +#ifndef __set_errno +# define __set_errno(val) errno = (val) +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#else +char *getenv (); +# ifdef HAVE_MALLOC_H +# include +# else +void free (); +# endif +#endif + +#if defined HAVE_STRING_H || defined _LIBC +# ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +# endif +# include +#else +# include +#endif +#if !HAVE_STRCHR && !defined _LIBC +# ifndef strchr +# define strchr index +# endif +#endif + +#if defined HAVE_UNISTD_H || defined _LIBC +# include +#endif + +#include "gettext.h" +#include "gettextP.h" +#ifdef _LIBC +# include +#else +# include "libgettext.h" +#endif +#include "hash-string.h" + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ANSI C functions. This is required by the standard + because some ANSI C functions will require linking with this object + file and the name space must not be polluted. */ +# define getcwd __getcwd +# ifndef stpcpy +# define stpcpy __stpcpy +# endif +#else +# if !defined HAVE_GETCWD +char *getwd (); +# define getcwd(buf, max) getwd (buf) +# else +char *getcwd (); +# endif +# ifndef HAVE_STPCPY +static char *stpcpy PARAMS ((char *dest, const char *src)); +# endif +#endif + +/* Amount to increase buffer size by in each try. */ +#define PATH_INCR 32 + +/* The following is from pathmax.h. */ +/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define + PATH_MAX but might cause redefinition warnings when sys/param.h is + later included (as on MORE/BSD 4.3). */ +#if defined(_POSIX_VERSION) || (defined(HAVE_LIMITS_H) && !defined(__GNUC__)) +# include +#endif + +#ifndef _POSIX_PATH_MAX +# define _POSIX_PATH_MAX 255 +#endif + +#if !defined(PATH_MAX) && defined(_PC_PATH_MAX) +# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) +#endif + +/* Don't include sys/param.h if it already has been. */ +#if defined(HAVE_SYS_PARAM_H) && !defined(PATH_MAX) && !defined(MAXPATHLEN) +# include +#endif + +#if !defined(PATH_MAX) && defined(MAXPATHLEN) +# define PATH_MAX MAXPATHLEN +#endif + +#ifndef PATH_MAX +# define PATH_MAX _POSIX_PATH_MAX +#endif + +/* XPG3 defines the result of `setlocale (category, NULL)' as: + ``Directs `setlocale()' to query `category' and return the current + setting of `local'.'' + However it does not specify the exact format. And even worse: POSIX + defines this not at all. So we can use this feature only on selected + system (e.g. those using GNU C Library). */ +#ifdef _LIBC +# define HAVE_LOCALE_NULL +#endif + +/* Name of the default domain used for gettext(3) prior any call to + textdomain(3). The default value for this is "messages". */ +const char _nl_default_default_domain[] = "messages"; + +/* Value used as the default domain for gettext(3). */ +const char *_nl_current_default_domain = _nl_default_default_domain; + +/* Contains the default location of the message catalogs. */ +const char _nl_default_dirname[] = GNULOCALEDIR; + +/* List with bindings of specific domains created by bindtextdomain() + calls. */ +struct binding *_nl_domain_bindings; + +/* Prototypes for local functions. */ +static char *find_msg PARAMS ((struct loaded_l10nfile *domain_file, + const char *msgid)) internal_function; +static const char *category_to_name PARAMS ((int category)) internal_function; +static const char *guess_category_value PARAMS ((int category, + const char *categoryname)) + internal_function; + + +/* For those loosing systems which don't have `alloca' we have to add + some additional code emulating it. */ +#ifdef HAVE_ALLOCA +/* Nothing has to be done. */ +# define ADD_BLOCK(list, address) /* nothing */ +# define FREE_BLOCKS(list) /* nothing */ +#else +struct block_list +{ + void *address; + struct block_list *next; +}; +# define ADD_BLOCK(list, addr) \ + do { \ + struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ + /* If we cannot get a free block we cannot add the new element to \ + the list. */ \ + if (newp != NULL) { \ + newp->address = (addr); \ + newp->next = (list); \ + (list) = newp; \ + } \ + } while (0) +# define FREE_BLOCKS(list) \ + do { \ + while (list != NULL) { \ + struct block_list *old = list; \ + list = list->next; \ + free (old); \ + } \ + } while (0) +# undef alloca +# define alloca(size) (malloc (size)) +#endif /* have alloca */ + + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DCGETTEXT __dcgettext +#else +# define DCGETTEXT dcgettext__ +#endif + +/* Checking whether the binaries runs SUID must be done and glibc provides + easier methods therefore we make a difference here. */ +#ifdef _LIBC +# define ENABLE_SECURE __libc_enable_secure +# define DETERMINE_SECURE +#else +static int enable_secure; +# define ENABLE_SECURE (enable_secure == 1) +# define DETERMINE_SECURE \ + if (enable_secure == 0) \ + { \ + if (getuid () != geteuid () || getgid () != getegid ()) \ + enable_secure = 1; \ + else \ + enable_secure = -1; \ + } +#endif + +/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY + locale. */ +char * +DCGETTEXT (domainname, msgid, category) + const char *domainname; + const char *msgid; + int category; +{ +#ifndef HAVE_ALLOCA + struct block_list *block_list = NULL; +#endif + struct loaded_l10nfile *domain; + struct binding *binding; + const char *categoryname; + const char *categoryvalue; + char *dirname, *xdomainname; + char *single_locale; + char *retval; + int saved_errno = errno; + + /* If no real MSGID is given return NULL. */ + if (msgid == NULL) + return NULL; + + /* See whether this is a SUID binary or not. */ + DETERMINE_SECURE; + + /* If DOMAINNAME is NULL, we are interested in the default domain. If + CATEGORY is not LC_MESSAGES this might not make much sense but the + definition left this undefined. */ + if (domainname == NULL) + domainname = _nl_current_default_domain; + + /* First find matching binding. */ + for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) + { + int compare = strcmp (domainname, binding->domainname); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It is not in the list. */ + binding = NULL; + break; + } + } + + if (binding == NULL) + dirname = (char *) _nl_default_dirname; + else if (binding->dirname[0] == '/') + dirname = binding->dirname; + else + { + /* We have a relative path. Make it absolute now. */ + size_t dirname_len = strlen (binding->dirname) + 1; + size_t path_max; + char *ret; + + path_max = (unsigned int) PATH_MAX; + path_max += 2; /* The getcwd docs say to do this. */ + + dirname = (char *) alloca (path_max + dirname_len); + ADD_BLOCK (block_list, dirname); + + __set_errno (0); + while ((ret = getcwd (dirname, path_max)) == NULL && errno == ERANGE) + { + path_max += PATH_INCR; + dirname = (char *) alloca (path_max + dirname_len); + ADD_BLOCK (block_list, dirname); + __set_errno (0); + } + + if (ret == NULL) + { + /* We cannot get the current working directory. Don't signal an + error but simply return the default string. */ + FREE_BLOCKS (block_list); + __set_errno (saved_errno); + return (char *) msgid; + } + + stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname); + } + + /* Now determine the symbolic name of CATEGORY and its value. */ + categoryname = category_to_name (category); + categoryvalue = guess_category_value (category, categoryname); + + xdomainname = (char *) alloca (strlen (categoryname) + + strlen (domainname) + 5); + ADD_BLOCK (block_list, xdomainname); + + stpcpy (stpcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), + domainname), + ".mo"); + + /* Creating working area. */ + single_locale = (char *) alloca (strlen (categoryvalue) + 1); + ADD_BLOCK (block_list, single_locale); + + + /* Search for the given string. This is a loop because we perhaps + got an ordered list of languages to consider for the translation. */ + while (1) + { + /* Make CATEGORYVALUE point to the next element of the list. */ + while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') + ++categoryvalue; + if (categoryvalue[0] == '\0') + { + /* The whole contents of CATEGORYVALUE has been searched but + no valid entry has been found. We solve this situation + by implicitly appending a "C" entry, i.e. no translation + will take place. */ + single_locale[0] = 'C'; + single_locale[1] = '\0'; + } + else + { + char *cp = single_locale; + while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') + *cp++ = *categoryvalue++; + *cp = '\0'; + + /* When this is a SUID binary we must not allow accessing files + outside the dedicated directories. */ + if (ENABLE_SECURE + && (memchr (single_locale, '/', + _nl_find_language (single_locale) - single_locale) + != NULL)) + /* Ingore this entry. */ + continue; + } + + /* If the current locale value is C (or POSIX) we don't load a + domain. Return the MSGID. */ + if (strcmp (single_locale, "C") == 0 + || strcmp (single_locale, "POSIX") == 0) + { + FREE_BLOCKS (block_list); + __set_errno (saved_errno); + return (char *) msgid; + } + + + /* Find structure describing the message catalog matching the + DOMAINNAME and CATEGORY. */ + domain = _nl_find_domain (dirname, single_locale, xdomainname); + + if (domain != NULL) + { + retval = find_msg (domain, msgid); + + if (retval == NULL) + { + int cnt; + + for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) + { + retval = find_msg (domain->successor[cnt], msgid); + + if (retval != NULL) + break; + } + } + + if (retval != NULL) + { + FREE_BLOCKS (block_list); + __set_errno (saved_errno); + return retval; + } + } + } + /* NOTREACHED */ +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__dcgettext, dcgettext); +#endif + + +static char * +internal_function +find_msg (domain_file, msgid) + struct loaded_l10nfile *domain_file; + const char *msgid; +{ + size_t act = 0; + size_t top, bottom; + struct loaded_domain *domain; + + if (domain_file->decided == 0) + _nl_load_domain (domain_file); + + if (domain_file->data == NULL) + return NULL; + + domain = (struct loaded_domain *) domain_file->data; + + /* Locate the MSGID and its translation. */ + if (domain->hash_size > 2 && domain->hash_tab != NULL) + { + /* Use the hashing table. */ + nls_uint32 len = strlen (msgid); + nls_uint32 hash_val = hash_string (msgid); + nls_uint32 idx = hash_val % domain->hash_size; + nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); + nls_uint32 nstr = W (domain->must_swap, domain->hash_tab[idx]); + + if (nstr == 0) + /* Hash table entry is empty. */ + return NULL; + + if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len + && strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr - 1].offset)) == 0) + return (char *) domain->data + W (domain->must_swap, + domain->trans_tab[nstr - 1].offset); + + while (1) + { + if (idx >= domain->hash_size - incr) + idx -= domain->hash_size - incr; + else + idx += incr; + + nstr = W (domain->must_swap, domain->hash_tab[idx]); + if (nstr == 0) + /* Hash table entry is empty. */ + return NULL; + + if (W (domain->must_swap, domain->orig_tab[nstr - 1].length) == len + && strcmp (msgid, + domain->data + W (domain->must_swap, + domain->orig_tab[nstr - 1].offset)) + == 0) + return (char *) domain->data + + W (domain->must_swap, domain->trans_tab[nstr - 1].offset); + } + /* NOTREACHED */ + } + + /* Now we try the default method: binary search in the sorted + array of messages. */ + bottom = 0; + top = domain->nstrings; + while (bottom < top) + { + int cmp_val; + + act = (bottom + top) / 2; + cmp_val = strcmp (msgid, domain->data + + W (domain->must_swap, + domain->orig_tab[act].offset)); + if (cmp_val < 0) + top = act; + else if (cmp_val > 0) + bottom = act + 1; + else + break; + } + + /* If an translation is found return this. */ + return bottom >= top ? NULL : (char *) domain->data + + W (domain->must_swap, + domain->trans_tab[act].offset); +} + + +/* Return string representation of locale CATEGORY. */ +static const char * +internal_function +category_to_name (category) + int category; +{ + const char *retval; + + switch (category) + { +#ifdef LC_COLLATE + case LC_COLLATE: + retval = "LC_COLLATE"; + break; +#endif +#ifdef LC_CTYPE + case LC_CTYPE: + retval = "LC_CTYPE"; + break; +#endif +#ifdef LC_MONETARY + case LC_MONETARY: + retval = "LC_MONETARY"; + break; +#endif +#ifdef LC_NUMERIC + case LC_NUMERIC: + retval = "LC_NUMERIC"; + break; +#endif +#ifdef LC_TIME + case LC_TIME: + retval = "LC_TIME"; + break; +#endif +#ifdef LC_MESSAGES + case LC_MESSAGES: + retval = "LC_MESSAGES"; + break; +#endif +#ifdef LC_RESPONSE + case LC_RESPONSE: + retval = "LC_RESPONSE"; + break; +#endif +#ifdef LC_ALL + case LC_ALL: + /* This might not make sense but is perhaps better than any other + value. */ + retval = "LC_ALL"; + break; +#endif + default: + /* If you have a better idea for a default value let me know. */ + retval = "LC_XXX"; + } + + return retval; +} + +/* Guess value of current locale from value of the environment variables. */ +static const char * +internal_function +guess_category_value (category, categoryname) + int category; + const char *categoryname; +{ + const char *retval; + + /* The highest priority value is the `LANGUAGE' environment + variable. This is a GNU extension. */ + retval = getenv ("LANGUAGE"); + if (retval != NULL && retval[0] != '\0') + return retval; + + /* `LANGUAGE' is not set. So we have to proceed with the POSIX + methods of looking to `LC_ALL', `LC_xxx', and `LANG'. On some + systems this can be done by the `setlocale' function itself. */ +#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL + return setlocale (category, NULL); +#else + /* Setting of LC_ALL overwrites all other. */ + retval = getenv ("LC_ALL"); + if (retval != NULL && retval[0] != '\0') + return retval; + + /* Next comes the name of the desired category. */ + retval = getenv (categoryname); + if (retval != NULL && retval[0] != '\0') + return retval; + + /* Last possibility is the LANG environment variable. */ + retval = getenv ("LANG"); + if (retval != NULL && retval[0] != '\0') + return retval; + + /* We use C as the default domain. POSIX says this is implementation + defined. */ + return "C"; +#endif +} + +/* @@ begin of epilog @@ */ + +/* We don't want libintl.a to depend on any other library. So we + avoid the non-standard function stpcpy. In GNU C Library this + function is available, though. Also allow the symbol HAVE_STPCPY + to be defined. */ +#if !_LIBC && !HAVE_STPCPY +static char * +stpcpy (dest, src) + char *dest; + const char *src; +{ + while ((*dest++ = *src++) != '\0') + /* Do nothing. */ ; + return dest - 1; +} +#endif + + +#ifdef _LIBC +/* If we want to free all resources we have to do some work at + program's end. */ +static void __attribute__ ((unused)) +free_mem (void) +{ + struct binding *runp; + + for (runp = _nl_domain_bindings; runp != NULL; runp = runp->next) + { + free (runp->domainname); + if (runp->dirname != _nl_default_dirname) + /* Yes, this is a pointer comparison. */ + free (runp->dirname); + } + + if (_nl_current_default_domain != _nl_default_default_domain) + /* Yes, again a pointer comparison. */ + free ((char *) _nl_current_default_domain); +} + +text_set_element (__libc_subfreeres, free_mem); +#endif diff --git a/intl/dgettext.c b/intl/dgettext.c new file mode 100644 index 00000000..0510c2b0 --- /dev/null +++ b/intl/dgettext.c @@ -0,0 +1,59 @@ +/* Implementation of the dgettext(3) function + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined HAVE_LOCALE_H || defined _LIBC +# include +#endif + +#ifdef _LIBC +# include +#else +# include "libgettext.h" +#endif + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define DGETTEXT __dgettext +# define DCGETTEXT __dcgettext +#else +# define DGETTEXT dgettext__ +# define DCGETTEXT dcgettext__ +#endif + +/* Look up MSGID in the DOMAINNAME message catalog of the current + LC_MESSAGES locale. */ +char * +DGETTEXT (domainname, msgid) + const char *domainname; + const char *msgid; +{ + return DCGETTEXT (domainname, msgid, LC_MESSAGES); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__dgettext, dgettext); +#endif diff --git a/intl/explodename.c b/intl/explodename.c new file mode 100644 index 00000000..80a3111c --- /dev/null +++ b/intl/explodename.c @@ -0,0 +1,197 @@ +/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Ulrich Drepper , 1995. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +#if defined HAVE_STRING_H || defined _LIBC +# include +#else +# include +#endif +#include + +#include "loadinfo.h" + +/* On some strange systems still no definition of NULL is found. Sigh! */ +#ifndef NULL +# if defined __STDC__ && __STDC__ +# define NULL ((void *) 0) +# else +# define NULL 0 +# endif +#endif + +/* @@ end of prolog @@ */ + +char * +_nl_find_language (const char *name) +{ + while (name[0] != '\0' && name[0] != '_' && name[0] != '@' + && name[0] != '+' && name[0] != ',') + ++name; + + return (char *) name; +} + + +int +_nl_explode_name (name, language, modifier, territory, codeset, + normalized_codeset, special, sponsor, revision) + char *name; + const char **language; + const char **modifier; + const char **territory; + const char **codeset; + const char **normalized_codeset; + const char **special; + const char **sponsor; + const char **revision; +{ + enum { undecided, xpg, cen } syntax; + char *cp; + int mask; + + *modifier = NULL; + *territory = NULL; + *codeset = NULL; + *normalized_codeset = NULL; + *special = NULL; + *sponsor = NULL; + *revision = NULL; + + /* Now we determine the single parts of the locale name. First + look for the language. Termination symbols are `_' and `@' if + we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ + mask = 0; + syntax = undecided; + *language = cp = name; + cp = _nl_find_language (*language); + + if (*language == cp) + /* This does not make sense: language has to be specified. Use + this entry as it is without exploding. Perhaps it is an alias. */ + cp = strchr (*language, '\0'); + else if (cp[0] == '_') + { + /* Next is the territory. */ + cp[0] = '\0'; + *territory = ++cp; + + while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@' + && cp[0] != '+' && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= TERRITORY; + + if (cp[0] == '.') + { + /* Next is the codeset. */ + syntax = xpg; + cp[0] = '\0'; + *codeset = ++cp; + + while (cp[0] != '\0' && cp[0] != '@') + ++cp; + + mask |= XPG_CODESET; + + if (*codeset != cp && (*codeset)[0] != '\0') + { + *normalized_codeset = _nl_normalize_codeset (*codeset, + cp - *codeset); + if (strcmp (*codeset, *normalized_codeset) == 0) + free ((char *) *normalized_codeset); + else + mask |= XPG_NORM_CODESET; + } + } + } + + if (cp[0] == '@' || (syntax != xpg && cp[0] == '+')) + { + /* Next is the modifier. */ + syntax = cp[0] == '@' ? xpg : cen; + cp[0] = '\0'; + *modifier = ++cp; + + while (syntax == cen && cp[0] != '\0' && cp[0] != '+' + && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= XPG_MODIFIER | CEN_AUDIENCE; + } + + if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_')) + { + syntax = cen; + + if (cp[0] == '+') + { + /* Next is special application (CEN syntax). */ + cp[0] = '\0'; + *special = ++cp; + + while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_') + ++cp; + + mask |= CEN_SPECIAL; + } + + if (cp[0] == ',') + { + /* Next is sponsor (CEN syntax). */ + cp[0] = '\0'; + *sponsor = ++cp; + + while (cp[0] != '\0' && cp[0] != '_') + ++cp; + + mask |= CEN_SPONSOR; + } + + if (cp[0] == '_') + { + /* Next is revision (CEN syntax). */ + cp[0] = '\0'; + *revision = ++cp; + + mask |= CEN_REVISION; + } + } + + /* For CEN syntax values it might be important to have the + separator character in the file name, not for XPG syntax. */ + if (syntax == xpg) + { + if (*territory != NULL && (*territory)[0] == '\0') + mask &= ~TERRITORY; + + if (*codeset != NULL && (*codeset)[0] == '\0') + mask &= ~XPG_CODESET; + + if (*modifier != NULL && (*modifier)[0] == '\0') + mask &= ~XPG_MODIFIER; + } + + return mask; +} diff --git a/intl/finddomain.c b/intl/finddomain.c new file mode 100644 index 00000000..81ea29bf --- /dev/null +++ b/intl/finddomain.c @@ -0,0 +1,216 @@ +/* Handle list of needed message catalogs + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Written by Ulrich Drepper , 1995. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#if defined STDC_HEADERS || defined _LIBC +# include +#else +# ifdef HAVE_MALLOC_H +# include +# else +void free (); +# endif +#endif + +#if defined HAVE_STRING_H || defined _LIBC +# include +#else +# include +# ifndef memcpy +# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num) +# endif +#endif +#if !HAVE_STRCHR && !defined _LIBC +# ifndef strchr +# define strchr index +# endif +#endif + +#if defined HAVE_UNISTD_H || defined _LIBC +# include +#endif + +#include "gettext.h" +#include "gettextP.h" +#ifdef _LIBC +# include +#else +# include "libgettext.h" +#endif + +/* @@ end of prolog @@ */ +/* List of already loaded domains. */ +static struct loaded_l10nfile *_nl_loaded_domains; + + +/* Return a data structure describing the message catalog described by + the DOMAINNAME and CATEGORY parameters with respect to the currently + established bindings. */ +struct loaded_l10nfile * +internal_function +_nl_find_domain (dirname, locale, domainname) + const char *dirname; + char *locale; + const char *domainname; +{ + struct loaded_l10nfile *retval; + const char *language; + const char *modifier; + const char *territory; + const char *codeset; + const char *normalized_codeset; + const char *special; + const char *sponsor; + const char *revision; + const char *alias_value; + int mask; + + /* LOCALE can consist of up to four recognized parts for the XPG syntax: + + language[_territory[.codeset]][@modifier] + + and six parts for the CEN syntax: + + language[_territory][+audience][+special][,[sponsor][_revision]] + + Beside the first part all of them are allowed to be missing. If + the full specified locale is not found, the less specific one are + looked for. The various parts will be stripped off according to + the following order: + (1) revision + (2) sponsor + (3) special + (4) codeset + (5) normalized codeset + (6) territory + (7) audience/modifier + */ + + /* If we have already tested for this locale entry there has to + be one data set in the list of loaded domains. */ + retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, + strlen (dirname) + 1, 0, locale, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, domainname, 0); + if (retval != NULL) + { + /* We know something about this locale. */ + int cnt; + + if (retval->decided == 0) + _nl_load_domain (retval); + + if (retval->data != NULL) + return retval; + + for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) + { + if (retval->successor[cnt]->decided == 0) + _nl_load_domain (retval->successor[cnt]); + + if (retval->successor[cnt]->data != NULL) + break; + } + return cnt >= 0 ? retval : NULL; + /* NOTREACHED */ + } + + /* See whether the locale value is an alias. If yes its value + *overwrites* the alias name. No test for the original value is + done. */ + alias_value = _nl_expand_alias (locale); + if (alias_value != NULL) + { +#if defined _LIBC || defined HAVE_STRDUP + locale = strdup (alias_value); + if (locale == NULL) + return NULL; +#else + size_t len = strlen (alias_value) + 1; + locale = (char *) malloc (len); + if (locale == NULL) + return NULL; + + memcpy (locale, alias_value, len); +#endif + } + + /* Now we determine the single parts of the locale name. First + look for the language. Termination symbols are `_' and `@' if + we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ + mask = _nl_explode_name (locale, &language, &modifier, &territory, + &codeset, &normalized_codeset, &special, + &sponsor, &revision); + + /* Create all possible locale entries which might be interested in + generalization. */ + retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, + strlen (dirname) + 1, mask, language, territory, + codeset, normalized_codeset, modifier, special, + sponsor, revision, domainname, 1); + if (retval == NULL) + /* This means we are out of core. */ + return NULL; + + if (retval->decided == 0) + _nl_load_domain (retval); + if (retval->data == NULL) + { + int cnt; + for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) + { + if (retval->successor[cnt]->decided == 0) + _nl_load_domain (retval->successor[cnt]); + if (retval->successor[cnt]->data != NULL) + break; + } + } + + /* The room for an alias was dynamically allocated. Free it now. */ + if (alias_value != NULL) + free (locale); + + return retval; +} + + +#ifdef _LIBC +static void __attribute__ ((unused)) +free_mem (void) +{ + struct loaded_l10nfile *runp = _nl_loaded_domains; + + while (runp != NULL) + { + struct loaded_l10nfile *here = runp; + if (runp->data != NULL) + _nl_unload_domain ((struct loaded_domain *) runp->data); + runp = runp->next; + free (here); + } +} + +text_set_element (__libc_subfreeres, free_mem); +#endif diff --git a/intl/gettext.c b/intl/gettext.c new file mode 100644 index 00000000..d929f98d --- /dev/null +++ b/intl/gettext.c @@ -0,0 +1,70 @@ +/* Implementation of gettext(3) function. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef _LIBC +# define __need_NULL +# include +#else +# ifdef STDC_HEADERS +# include /* Just for NULL. */ +# else +# ifdef HAVE_STRING_H +# include +# else +# define NULL ((void *) 0) +# endif +# endif +#endif + +#ifdef _LIBC +# include +#else +# include "libgettext.h" +#endif + +/* @@ end of prolog @@ */ + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define GETTEXT __gettext +# define DGETTEXT __dgettext +#else +# define GETTEXT gettext__ +# define DGETTEXT dgettext__ +#endif + +/* Look up MSGID in the current default message catalog for the current + LC_MESSAGES locale. If not found, returns MSGID itself (the default + text). */ +char * +GETTEXT (msgid) + const char *msgid; +{ + return DGETTEXT (NULL, msgid); +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__gettext, gettext); +#endif diff --git a/intl/gettext.h b/intl/gettext.h new file mode 100644 index 00000000..3cd23d7d --- /dev/null +++ b/intl/gettext.h @@ -0,0 +1,105 @@ +/* Internal header for GNU gettext internationalization functions. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + + 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, 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 Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _GETTEXT_H +#define _GETTEXT_H 1 + +#include + +#if HAVE_LIMITS_H || _LIBC +# include +#endif + +/* @@ end of prolog @@ */ + +/* The magic number of the GNU message catalog format. */ +#define _MAGIC 0x950412de +#define _MAGIC_SWAPPED 0xde120495 + +/* Revision number of the currently used .mo (binary) file format. */ +#define MO_REVISION_NUMBER 0 + +/* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but + doing that would require that the configure script compile and *run* + the resulting executable. Locally running cross-compiled executables + is usually not possible. */ + +#if __STDC__ +# define UINT_MAX_32_BITS 4294967295U +#else +# define UINT_MAX_32_BITS 0xFFFFFFFF +#endif + +/* If UINT_MAX isn't defined, assume it's a 32-bit type. + This should be valid for all systems GNU cares about because + that doesn't include 16-bit systems, and only modern systems + (that certainly have ) have 64+-bit integral types. */ + +#ifndef UINT_MAX +# define UINT_MAX UINT_MAX_32_BITS +#endif + +#if UINT_MAX == UINT_MAX_32_BITS +typedef unsigned nls_uint32; +#else +# if USHRT_MAX == UINT_MAX_32_BITS +typedef unsigned short nls_uint32; +# else +# if ULONG_MAX == UINT_MAX_32_BITS +typedef unsigned long nls_uint32; +# else + /* The following line is intended to throw an error. Using #error is + not portable enough. */ + "Cannot determine unsigned 32-bit data type." +# endif +# endif +#endif + + +/* Header for binary .mo file format. */ +struct mo_file_header +{ + /* The magic number. */ + nls_uint32 magic; + /* The revision number of the file format. */ + nls_uint32 revision; + /* The number of strings pairs. */ + nls_uint32 nstrings; + /* Offset of table with start offsets of original strings. */ + nls_uint32 orig_tab_offset; + /* Offset of table with start offsets of translation strings. */ + nls_uint32 trans_tab_offset; + /* Size of hashing table. */ + nls_uint32 hash_tab_size; + /* Offset of first hashing entry. */ + nls_uint32 hash_tab_offset; +}; + +struct string_desc +{ + /* Length of addressed string. */ + nls_uint32 length; + /* Offset of string in file. */ + nls_uint32 offset; +}; + +/* @@ begin of epilog @@ */ + +#endif /* gettext.h */ diff --git a/intl/gettextP.h b/intl/gettextP.h new file mode 100644 index 00000000..00c52031 --- /dev/null +++ b/intl/gettextP.h @@ -0,0 +1,89 @@ +/* Header describing internals of gettext library + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Written by Ulrich Drepper , 1995. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _GETTEXTP_H +#define _GETTEXTP_H + +#include "loadinfo.h" + +/* @@ end of prolog @@ */ + +#ifndef PARAMS +# if __STDC__ +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif +#endif + +#ifndef internal_function +# define internal_function +#endif + +#ifndef W +# define W(flag, data) ((flag) ? SWAP (data) : (data)) +#endif + + +#ifdef _LIBC +# include +# define SWAP(i) bswap_32 (i) +#else +static nls_uint32 SWAP PARAMS ((nls_uint32 i)); + +static inline nls_uint32 +SWAP (i) + nls_uint32 i; +{ + return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); +} +#endif + + +struct loaded_domain +{ + const char *data; + int use_mmap; + size_t mmap_size; + int must_swap; + nls_uint32 nstrings; + struct string_desc *orig_tab; + struct string_desc *trans_tab; + nls_uint32 hash_size; + nls_uint32 *hash_tab; +}; + +struct binding +{ + struct binding *next; + char *domainname; + char *dirname; +}; + +struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, + char *__locale, + const char *__domainname)) + internal_function; +void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain)) + internal_function; +void _nl_unload_domain PARAMS ((struct loaded_domain *__domain)) + internal_function; + +/* @@ begin of epilog @@ */ + +#endif /* gettextP.h */ diff --git a/intl/hash-string.h b/intl/hash-string.h new file mode 100644 index 00000000..939e9582 --- /dev/null +++ b/intl/hash-string.h @@ -0,0 +1,59 @@ +/* Implements a string hashing function. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + + 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, 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 Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* @@ end of prolog @@ */ + +#ifndef PARAMS +# if __STDC__ +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif +#endif + +/* We assume to have `unsigned long int' value with at least 32 bits. */ +#define HASHWORDBITS 32 + + +/* Defines the so called `hashpjw' function by P.J. Weinberger + [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, + 1986, 1987 Bell Telephone Laboratories, Inc.] */ +static unsigned long int hash_string PARAMS ((const char *__str_param)); + +static inline unsigned long int +hash_string (str_param) + const char *str_param; +{ + unsigned long int hval, g; + const char *str = str_param; + + /* Compute the hash value for the given string. */ + hval = 0; + while (*str != '\0') + { + hval <<= 4; + hval += (unsigned long int) *str++; + g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); + if (g != 0) + { + hval ^= g >> (HASHWORDBITS - 8); + hval ^= g; + } + } + return hval; +} diff --git a/intl/intl-compat.c b/intl/intl-compat.c new file mode 100644 index 00000000..503efa0f --- /dev/null +++ b/intl/intl-compat.c @@ -0,0 +1,76 @@ +/* intl-compat.c - Stub functions to call gettext functions from GNU gettext + Library. + Copyright (C) 1995 Software Foundation, Inc. + +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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "libgettext.h" + +/* @@ end of prolog @@ */ + + +#undef gettext +#undef dgettext +#undef dcgettext +#undef textdomain +#undef bindtextdomain + + +char * +bindtextdomain (domainname, dirname) + const char *domainname; + const char *dirname; +{ + return bindtextdomain__ (domainname, dirname); +} + + +char * +dcgettext (domainname, msgid, category) + const char *domainname; + const char *msgid; + int category; +{ + return dcgettext__ (domainname, msgid, category); +} + + +char * +dgettext (domainname, msgid) + const char *domainname; + const char *msgid; +{ + return dgettext__ (domainname, msgid); +} + + +char * +gettext (msgid) + const char *msgid; +{ + return gettext__ (msgid); +} + + +char * +textdomain (domainname) + const char *domainname; +{ + return textdomain__ (domainname); +} diff --git a/intl/l10nflist.c b/intl/l10nflist.c new file mode 100644 index 00000000..30f5f645 --- /dev/null +++ b/intl/l10nflist.c @@ -0,0 +1,411 @@ +/* Handle list of needed message catalogs + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + Contributed by Ulrich Drepper , 1995. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + + +#if defined HAVE_STRING_H || defined _LIBC +# ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +# endif +# include +#else +# include +# ifndef memcpy +# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num) +# endif +#endif +#if !HAVE_STRCHR && !defined _LIBC +# ifndef strchr +# define strchr index +# endif +#endif + +#if defined _LIBC || defined HAVE_ARGZ_H +# include +#endif +#include +#include + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +#include "loadinfo.h" + +/* On some strange systems still no definition of NULL is found. Sigh! */ +#ifndef NULL +# if defined __STDC__ && __STDC__ +# define NULL ((void *) 0) +# else +# define NULL 0 +# endif +#endif + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ANSI C functions. This is required by the standard + because some ANSI C functions will require linking with this object + file and the name space must not be polluted. */ +# ifndef stpcpy +# define stpcpy(dest, src) __stpcpy(dest, src) +# endif +#else +# ifndef HAVE_STPCPY +static char *stpcpy PARAMS ((char *dest, const char *src)); +# endif +#endif + +/* Define function which are usually not available. */ + +#if !defined _LIBC && !defined HAVE___ARGZ_COUNT +/* Returns the number of strings in ARGZ. */ +static size_t argz_count__ PARAMS ((const char *argz, size_t len)); + +static size_t +argz_count__ (argz, len) + const char *argz; + size_t len; +{ + size_t count = 0; + while (len > 0) + { + size_t part_len = strlen (argz); + argz += part_len + 1; + len -= part_len + 1; + count++; + } + return count; +} +# undef __argz_count +# define __argz_count(argz, len) argz_count__ (argz, len) +#endif /* !_LIBC && !HAVE___ARGZ_COUNT */ + +#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY +/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's + except the last into the character SEP. */ +static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep)); + +static void +argz_stringify__ (argz, len, sep) + char *argz; + size_t len; + int sep; +{ + while (len > 0) + { + size_t part_len = strlen (argz); + argz += part_len; + len -= part_len + 1; + if (len > 0) + *argz++ = sep; + } +} +# undef __argz_stringify +# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep) +#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ + +#if !defined _LIBC && !defined HAVE___ARGZ_NEXT +static char *argz_next__ PARAMS ((char *argz, size_t argz_len, + const char *entry)); + +static char * +argz_next__ (argz, argz_len, entry) + char *argz; + size_t argz_len; + const char *entry; +{ + if (entry) + { + if (entry < argz + argz_len) + entry = strchr (entry, '\0') + 1; + + return entry >= argz + argz_len ? NULL : (char *) entry; + } + else + if (argz_len > 0) + return argz; + else + return 0; +} +# undef __argz_next +# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry) +#endif /* !_LIBC && !HAVE___ARGZ_NEXT */ + + +/* Return number of bits set in X. */ +static int pop PARAMS ((int x)); + +static inline int +pop (x) + int x; +{ + /* We assume that no more than 16 bits are used. */ + x = ((x & ~0x5555) >> 1) + (x & 0x5555); + x = ((x & ~0x3333) >> 2) + (x & 0x3333); + x = ((x >> 4) + x) & 0x0f0f; + x = ((x >> 8) + x) & 0xff; + + return x; +} + + +struct loaded_l10nfile * +_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, + territory, codeset, normalized_codeset, modifier, special, + sponsor, revision, filename, do_allocate) + struct loaded_l10nfile **l10nfile_list; + const char *dirlist; + size_t dirlist_len; + int mask; + const char *language; + const char *territory; + const char *codeset; + const char *normalized_codeset; + const char *modifier; + const char *special; + const char *sponsor; + const char *revision; + const char *filename; + int do_allocate; +{ + char *abs_filename; + struct loaded_l10nfile *last = NULL; + struct loaded_l10nfile *retval; + char *cp; + size_t entries; + int cnt; + + /* Allocate room for the full file name. */ + abs_filename = (char *) malloc (dirlist_len + + strlen (language) + + ((mask & TERRITORY) != 0 + ? strlen (territory) + 1 : 0) + + ((mask & XPG_CODESET) != 0 + ? strlen (codeset) + 1 : 0) + + ((mask & XPG_NORM_CODESET) != 0 + ? strlen (normalized_codeset) + 1 : 0) + + (((mask & XPG_MODIFIER) != 0 + || (mask & CEN_AUDIENCE) != 0) + ? strlen (modifier) + 1 : 0) + + ((mask & CEN_SPECIAL) != 0 + ? strlen (special) + 1 : 0) + + (((mask & CEN_SPONSOR) != 0 + || (mask & CEN_REVISION) != 0) + ? (1 + ((mask & CEN_SPONSOR) != 0 + ? strlen (sponsor) + 1 : 0) + + ((mask & CEN_REVISION) != 0 + ? strlen (revision) + 1 : 0)) : 0) + + 1 + strlen (filename) + 1); + + if (abs_filename == NULL) + return NULL; + + retval = NULL; + last = NULL; + + /* Construct file name. */ + memcpy (abs_filename, dirlist, dirlist_len); + __argz_stringify (abs_filename, dirlist_len, ':'); + cp = abs_filename + (dirlist_len - 1); + *cp++ = '/'; + cp = stpcpy (cp, language); + + if ((mask & TERRITORY) != 0) + { + *cp++ = '_'; + cp = stpcpy (cp, territory); + } + if ((mask & XPG_CODESET) != 0) + { + *cp++ = '.'; + cp = stpcpy (cp, codeset); + } + if ((mask & XPG_NORM_CODESET) != 0) + { + *cp++ = '.'; + cp = stpcpy (cp, normalized_codeset); + } + if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) + { + /* This component can be part of both syntaces but has different + leading characters. For CEN we use `+', else `@'. */ + *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; + cp = stpcpy (cp, modifier); + } + if ((mask & CEN_SPECIAL) != 0) + { + *cp++ = '+'; + cp = stpcpy (cp, special); + } + if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0) + { + *cp++ = ','; + if ((mask & CEN_SPONSOR) != 0) + cp = stpcpy (cp, sponsor); + if ((mask & CEN_REVISION) != 0) + { + *cp++ = '_'; + cp = stpcpy (cp, revision); + } + } + + *cp++ = '/'; + stpcpy (cp, filename); + + /* Look in list of already loaded domains whether it is already + available. */ + last = NULL; + for (retval = *l10nfile_list; retval != NULL; retval = retval->next) + if (retval->filename != NULL) + { + int compare = strcmp (retval->filename, abs_filename); + if (compare == 0) + /* We found it! */ + break; + if (compare < 0) + { + /* It's not in the list. */ + retval = NULL; + break; + } + + last = retval; + } + + if (retval != NULL || do_allocate == 0) + { + free (abs_filename); + return retval; + } + + retval = (struct loaded_l10nfile *) + malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len) + * (1 << pop (mask)) + * sizeof (struct loaded_l10nfile *))); + if (retval == NULL) + return NULL; + + retval->filename = abs_filename; + retval->decided = (__argz_count (dirlist, dirlist_len) != 1 + || ((mask & XPG_CODESET) != 0 + && (mask & XPG_NORM_CODESET) != 0)); + retval->data = NULL; + + if (last == NULL) + { + retval->next = *l10nfile_list; + *l10nfile_list = retval; + } + else + { + retval->next = last->next; + last->next = retval; + } + + entries = 0; + /* If the DIRLIST is a real list the RETVAL entry corresponds not to + a real file. So we have to use the DIRLIST separation mechanism + of the inner loop. */ + cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask; + for (; cnt >= 0; --cnt) + if ((cnt & ~mask) == 0 + && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) + && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) + { + /* Iterate over all elements of the DIRLIST. */ + char *dir = NULL; + + while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir)) + != NULL) + retval->successor[entries++] + = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt, + language, territory, codeset, + normalized_codeset, modifier, special, + sponsor, revision, filename, 1); + } + retval->successor[entries] = NULL; + + return retval; +} + +/* Normalize codeset name. There is no standard for the codeset + names. Normalization allows the user to use any of the common + names. */ +const char * +_nl_normalize_codeset (codeset, name_len) + const char *codeset; + size_t name_len; +{ + int len = 0; + int only_digit = 1; + char *retval; + char *wp; + size_t cnt; + + for (cnt = 0; cnt < name_len; ++cnt) + if (isalnum (codeset[cnt])) + { + ++len; + + if (isalpha (codeset[cnt])) + only_digit = 0; + } + + retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); + + if (retval != NULL) + { + if (only_digit) + wp = stpcpy (retval, "iso"); + else + wp = retval; + + for (cnt = 0; cnt < name_len; ++cnt) + if (isalpha (codeset[cnt])) + *wp++ = tolower (codeset[cnt]); + else if (isdigit (codeset[cnt])) + *wp++ = codeset[cnt]; + + *wp = '\0'; + } + + return (const char *) retval; +} + + +/* @@ begin of epilog @@ */ + +/* We don't want libintl.a to depend on any other library. So we + avoid the non-standard function stpcpy. In GNU C Library this + function is available, though. Also allow the symbol HAVE_STPCPY + to be defined. */ +#if !_LIBC && !HAVE_STPCPY +static char * +stpcpy (dest, src) + char *dest; + const char *src; +{ + while ((*dest++ = *src++) != '\0') + /* Do nothing. */ ; + return dest - 1; +} +#endif diff --git a/intl/libgettext.h b/intl/libgettext.h new file mode 100644 index 00000000..3a92960a --- /dev/null +++ b/intl/libgettext.h @@ -0,0 +1,182 @@ +/* Message catalogs for internationalization. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Because on some systems (e.g. Solaris) we sometimes have to include + the systems libintl.h as well as this file we have more complex + include protection above. But the systems header might perhaps also + define _LIBINTL_H and therefore we have to protect the definition here. */ + +#if !defined _LIBINTL_H || !defined _LIBGETTEXT_H +#ifndef _LIBINTL_H +# define _LIBINTL_H 1 +#endif +#define _LIBGETTEXT_H 1 + +/* We define an additional symbol to signal that we use the GNU + implementation of gettext. */ +#define __USE_GNU_GETTEXT 1 + +#include + +#if HAVE_LOCALE_H +# include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* @@ end of prolog @@ */ + +#ifndef PARAMS +# if __STDC__ || defined __cplusplus +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif +#endif + +#ifndef NULL +# if !defined __cplusplus || defined __GNUC__ +# define NULL ((void *) 0) +# else +# define NULL (0) +# endif +#endif + +#if !HAVE_LC_MESSAGES +/* This value determines the behaviour of the gettext() and dgettext() + function. But some system does not have this defined. Define it + to a default value. */ +# define LC_MESSAGES (-1) +#endif + + +/* Declarations for gettext-using-catgets interface. Derived from + Jim Meyering's libintl.h. */ +struct _msg_ent +{ + const char *_msg; + int _msg_number; +}; + + +#if HAVE_CATGETS +/* These two variables are defined in the automatically by po-to-tbl.sed + generated file `cat-id-tbl.c'. */ +extern const struct _msg_ent _msg_tbl[]; +extern int _msg_tbl_length; +#endif + + +/* For automatical extraction of messages sometimes no real + translation is needed. Instead the string itself is the result. */ +#define gettext_noop(Str) (Str) + +/* Look up MSGID in the current default message catalog for the current + LC_MESSAGES locale. If not found, returns MSGID itself (the default + text). */ +extern char *gettext PARAMS ((const char *__msgid)); +extern char *gettext__ PARAMS ((const char *__msgid)); + +/* Look up MSGID in the DOMAINNAME message catalog for the current + LC_MESSAGES locale. */ +extern char *dgettext PARAMS ((const char *__domainname, const char *__msgid)); +extern char *dgettext__ PARAMS ((const char *__domainname, + const char *__msgid)); + +/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY + locale. */ +extern char *dcgettext PARAMS ((const char *__domainname, const char *__msgid, + int __category)); +extern char *dcgettext__ PARAMS ((const char *__domainname, + const char *__msgid, int __category)); + + +/* Set the current default message catalog to DOMAINNAME. + If DOMAINNAME is null, return the current default. + If DOMAINNAME is "", reset to the default of "messages". */ +extern char *textdomain PARAMS ((const char *__domainname)); +extern char *textdomain__ PARAMS ((const char *__domainname)); + +/* Specify that the DOMAINNAME message catalog will be found + in DIRNAME rather than in the system locale data base. */ +extern char *bindtextdomain PARAMS ((const char *__domainname, + const char *__dirname)); +extern char *bindtextdomain__ PARAMS ((const char *__domainname, + const char *__dirname)); + +#if ENABLE_NLS + +/* Solaris 2.3 has the gettext function but dcgettext is missing. + So we omit this optimization for Solaris 2.3. BTW, Solaris 2.4 + has dcgettext. */ +# if !HAVE_CATGETS && (!HAVE_GETTEXT || HAVE_DCGETTEXT) + +# define gettext(Msgid) \ + dgettext (NULL, Msgid) + +# define dgettext(Domainname, Msgid) \ + dcgettext (Domainname, Msgid, LC_MESSAGES) + +# if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ >= 7 +/* This global variable is defined in loadmsgcat.c. We need a sign, + whether a new catalog was loaded, which can be associated with all + translations. */ +extern int _nl_msg_cat_cntr; + +# define dcgettext(Domainname, Msgid, Category) \ + (__extension__ \ + ({ \ + char *__result; \ + if (__builtin_constant_p (Msgid)) \ + { \ + static char *__translation__; \ + static int __catalog_counter__; \ + if (! __translation__ || __catalog_counter__ != _nl_msg_cat_cntr) \ + { \ + __translation__ = \ + dcgettext__ (Domainname, Msgid, Category); \ + __catalog_counter__ = _nl_msg_cat_cntr; \ + } \ + __result = __translation__; \ + } \ + else \ + __result = dcgettext__ (Domainname, Msgid, Category); \ + __result; \ + })) +# endif +# endif + +#else + +# define gettext(Msgid) (Msgid) +# define dgettext(Domainname, Msgid) (Msgid) +# define dcgettext(Domainname, Msgid, Category) (Msgid) +# define textdomain(Domainname) ((char *) Domainname) +# define bindtextdomain(Domainname, Dirname) ((char *) Dirname) + +#endif + +/* @@ begin of epilog @@ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/intl/linux-msg.sed b/intl/linux-msg.sed new file mode 100644 index 00000000..5918e720 --- /dev/null +++ b/intl/linux-msg.sed @@ -0,0 +1,100 @@ +# po2msg.sed - Convert Uniforum style .po file to Linux style .msg file +# Copyright (C) 1995 Free Software Foundation, Inc. +# Ulrich Drepper , 1995. +# +# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# The first directive in the .msg should be the definition of the +# message set number. We use always set number 1. +# +1 { + i\ +$set 1 # Automatically created by po2msg.sed + h + s/.*/0/ + x +} +# +# Mitch's old catalog format does not allow comments. +# +# We copy the original message as a comment into the .msg file. +# +/^msgid/ { + s/msgid[ ]*"// +# +# This does not work now with the new format. +# /"$/! { +# s/\\$// +# s/$/ ... (more lines following)"/ +# } + x +# The following nice solution is by +# Bruno + td +# Increment a decimal number in pattern space. +# First hide trailing `9' digits. + :d + s/9\(_*\)$/_\1/ + td +# Assure at least one digit is available. + s/^\(_*\)$/0\1/ +# Increment the last digit. + s/8\(_*\)$/9\1/ + s/7\(_*\)$/8\1/ + s/6\(_*\)$/7\1/ + s/5\(_*\)$/6\1/ + s/4\(_*\)$/5\1/ + s/3\(_*\)$/4\1/ + s/2\(_*\)$/3\1/ + s/1\(_*\)$/2\1/ + s/0\(_*\)$/1\1/ +# Convert the hidden `9' digits to `0's. + s/_/0/g + x + G + s/\(.*\)"\n\([0-9]*\)/$ #\2 Original Message:(\1)/p +} +# +# The .msg file contains, other then the .po file, only the translations +# but each given a unique ID. Starting from 1 and incrementing by 1 for +# each message we assign them to the messages. +# It is important that the .po file used to generate the cat-id-tbl.c file +# (with po-to-tbl) is the same as the one used here. (At least the order +# of declarations must not be changed.) +# +/^msgstr/ { + s/msgstr[ ]*"\(.*\)"/# \1/ +# Clear substitution flag. + tb +# Append the next line. + :b + N +# Look whether second part is continuation line. + s/\(.*\n\)"\(.*\)"/\1\2/ +# Yes, then branch. + ta + P + D +# Note that D includes a jump to the start!! +# We found a continuation line. But before printing insert '\'. + :a + s/\(.*\)\(\n.*\)/\1\\\2/ + P +# We cannot use D here. + s/.*\n\(.*\)/\1/ + tb +} +d diff --git a/intl/loadinfo.h b/intl/loadinfo.h new file mode 100644 index 00000000..1c4524ab --- /dev/null +++ b/intl/loadinfo.h @@ -0,0 +1,78 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef PARAMS +# if __STDC__ +# define PARAMS(args) args +# else +# define PARAMS(args) () +# endif +#endif + +/* Encoding of locale name parts. */ +#define CEN_REVISION 1 +#define CEN_SPONSOR 2 +#define CEN_SPECIAL 4 +#define XPG_NORM_CODESET 8 +#define XPG_CODESET 16 +#define TERRITORY 32 +#define CEN_AUDIENCE 64 +#define XPG_MODIFIER 128 + +#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) +#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) + + +struct loaded_l10nfile +{ + const char *filename; + int decided; + + const void *data; + + struct loaded_l10nfile *next; + struct loaded_l10nfile *successor[1]; +}; + + +extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, + size_t name_len)); + +extern struct loaded_l10nfile * +_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list, + const char *dirlist, size_t dirlist_len, int mask, + const char *language, const char *territory, + const char *codeset, + const char *normalized_codeset, + const char *modifier, const char *special, + const char *sponsor, const char *revision, + const char *filename, int do_allocate)); + + +extern const char *_nl_expand_alias PARAMS ((const char *name)); + +extern int _nl_explode_name PARAMS ((char *name, const char **language, + const char **modifier, + const char **territory, + const char **codeset, + const char **normalized_codeset, + const char **special, + const char **sponsor, + const char **revision)); + +extern char *_nl_find_language PARAMS ((const char *name)); diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c new file mode 100644 index 00000000..2c6a5650 --- /dev/null +++ b/intl/loadmsgcat.c @@ -0,0 +1,220 @@ +/* Load needed message catalogs. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +#if defined HAVE_UNISTD_H || defined _LIBC +# include +#endif + +#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ + || (defined _LIBC && defined _POSIX_MAPPED_FILES) +# include +# undef HAVE_MMAP +# define HAVE_MMAP 1 +#else +# undef HAVE_MMAP +#endif + +#include "gettext.h" +#include "gettextP.h" + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ISO C functions. This is required by the standard + because some ISO C functions will require linking with this object + file and the name space must not be polluted. */ +# define open __open +# define close __close +# define read __read +# define mmap __mmap +# define munmap __munmap +#endif + +/* We need a sign, whether a new catalog was loaded, which can be associated + with all translations. This is important if the translations are + cached by one of GCC's features. */ +int _nl_msg_cat_cntr = 0; + + +/* Load the message catalogs specified by FILENAME. If it is no valid + message catalog do nothing. */ +void +internal_function +_nl_load_domain (domain_file) + struct loaded_l10nfile *domain_file; +{ + int fd; + size_t size; + struct stat st; + struct mo_file_header *data = (struct mo_file_header *) -1; + int use_mmap = 0; + struct loaded_domain *domain; + + domain_file->decided = 1; + domain_file->data = NULL; + + /* If the record does not represent a valid locale the FILENAME + might be NULL. This can happen when according to the given + specification the locale file name is different for XPG and CEN + syntax. */ + if (domain_file->filename == NULL) + return; + + /* Try to open the addressed file. */ + fd = open (domain_file->filename, O_RDONLY); + if (fd == -1) + return; + + /* We must know about the size of the file. */ + if (fstat (fd, &st) != 0 + || (size = (size_t) st.st_size) != st.st_size + || size < sizeof (struct mo_file_header)) + { + /* Something went wrong. */ + close (fd); + return; + } + +#ifdef HAVE_MMAP + /* Now we are ready to load the file. If mmap() is available we try + this first. If not available or it failed we try to load it. */ + data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, + MAP_PRIVATE, fd, 0); + + if (data != (struct mo_file_header *) -1) + { + /* mmap() call was successful. */ + close (fd); + use_mmap = 1; + } +#endif + + /* If the data is not yet available (i.e. mmap'ed) we try to load + it manually. */ + if (data == (struct mo_file_header *) -1) + { + size_t to_read; + char *read_ptr; + + data = (struct mo_file_header *) malloc (size); + if (data == NULL) + return; + + to_read = size; + read_ptr = (char *) data; + do + { + long int nb = (long int) read (fd, read_ptr, to_read); + if (nb == -1) + { + close (fd); + return; + } + + read_ptr += nb; + to_read -= nb; + } + while (to_read > 0); + + close (fd); + } + + /* Using the magic number we can test whether it really is a message + catalog file. */ + if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED) + { + /* The magic number is wrong: not a message catalog file. */ +#ifdef HAVE_MMAP + if (use_mmap) + munmap ((caddr_t) data, size); + else +#endif + free (data); + return; + } + + domain_file->data + = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); + if (domain_file->data == NULL) + return; + + domain = (struct loaded_domain *) domain_file->data; + domain->data = (char *) data; + domain->use_mmap = use_mmap; + domain->mmap_size = size; + domain->must_swap = data->magic != _MAGIC; + + /* Fill in the information about the available tables. */ + switch (W (domain->must_swap, data->revision)) + { + case 0: + domain->nstrings = W (domain->must_swap, data->nstrings); + domain->orig_tab = (struct string_desc *) + ((char *) data + W (domain->must_swap, data->orig_tab_offset)); + domain->trans_tab = (struct string_desc *) + ((char *) data + W (domain->must_swap, data->trans_tab_offset)); + domain->hash_size = W (domain->must_swap, data->hash_tab_size); + domain->hash_tab = (nls_uint32 *) + ((char *) data + W (domain->must_swap, data->hash_tab_offset)); + break; + default: + /* This is an invalid revision. */ +#ifdef HAVE_MMAP + if (use_mmap) + munmap ((caddr_t) data, size); + else +#endif + free (data); + free (domain); + domain_file->data = NULL; + return; + } + + /* Show that one domain is changed. This might make some cached + translations invalid. */ + ++_nl_msg_cat_cntr; +} + + +#ifdef _LIBC +void +internal_function +_nl_unload_domain (domain) + struct loaded_domain *domain; +{ +#ifdef _POSIX_MAPPED_FILES + if (domain->use_mmap) + munmap ((caddr_t) domain->data, domain->mmap_size); + else +#endif /* _POSIX_MAPPED_FILES */ + free ((void *) domain->data); + + free (domain); +} +#endif diff --git a/intl/localealias.c b/intl/localealias.c new file mode 100644 index 00000000..861020dd --- /dev/null +++ b/intl/localealias.c @@ -0,0 +1,438 @@ +/* Handle aliases for locale names. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Written by Ulrich Drepper , 1995. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#ifdef __GNUC__ +# define alloca __builtin_alloca +# define HAVE_ALLOCA 1 +#else +# if defined HAVE_ALLOCA_H || defined _LIBC +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca +char *alloca (); +# endif +# endif +# endif +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#else +char *getenv (); +# ifdef HAVE_MALLOC_H +# include +# else +void free (); +# endif +#endif + +#if defined HAVE_STRING_H || defined _LIBC +# ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +# endif +# include +#else +# include +# ifndef memcpy +# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num) +# endif +#endif +#if !HAVE_STRCHR && !defined _LIBC +# ifndef strchr +# define strchr index +# endif +#endif + +#include "gettext.h" +#include "gettextP.h" + +/* @@ end of prolog @@ */ + +#ifdef _LIBC +/* Rename the non ANSI C functions. This is required by the standard + because some ANSI C functions will require linking with this object + file and the name space must not be polluted. */ +# define strcasecmp __strcasecmp + +# ifndef mempcpy +# define mempcpy __mempcpy +# endif +# define HAVE_MEMPCPY 1 + +/* We need locking here since we can be called from different places. */ +# include + +__libc_lock_define_initialized (static, lock); +#endif + +#ifndef internal_function +# define internal_function +#endif + +/* For those loosing systems which don't have `alloca' we have to add + some additional code emulating it. */ +#ifdef HAVE_ALLOCA +/* Nothing has to be done. */ +# define ADD_BLOCK(list, address) /* nothing */ +# define FREE_BLOCKS(list) /* nothing */ +#else +struct block_list +{ + void *address; + struct block_list *next; +}; +# define ADD_BLOCK(list, addr) \ + do { \ + struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ + /* If we cannot get a free block we cannot add the new element to \ + the list. */ \ + if (newp != NULL) { \ + newp->address = (addr); \ + newp->next = (list); \ + (list) = newp; \ + } \ + } while (0) +# define FREE_BLOCKS(list) \ + do { \ + while (list != NULL) { \ + struct block_list *old = list; \ + list = list->next; \ + free (old); \ + } \ + } while (0) +# undef alloca +# define alloca(size) (malloc (size)) +#endif /* have alloca */ + +#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED +# undef fgets +# define fgets(buf, len, s) fgets_unlocked (buf, len, s) +#endif +#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED +# undef feof +# define feof(s) feof_unlocked (s) +#endif + + +struct alias_map +{ + const char *alias; + const char *value; +}; + + +static char *string_space = NULL; +static size_t string_space_act = 0; +static size_t string_space_max = 0; +static struct alias_map *map; +static size_t nmap = 0; +static size_t maxmap = 0; + + +/* Prototypes for local functions. */ +static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) + internal_function; +static void extend_alias_table PARAMS ((void)); +static int alias_compare PARAMS ((const struct alias_map *map1, + const struct alias_map *map2)); + + +const char * +_nl_expand_alias (name) + const char *name; +{ + static const char *locale_alias_path = LOCALE_ALIAS_PATH; + struct alias_map *retval; + const char *result = NULL; + size_t added; + +#ifdef _LIBC + __libc_lock_lock (lock); +#endif + + do + { + struct alias_map item; + + item.alias = name; + + if (nmap > 0) + retval = (struct alias_map *) bsearch (&item, map, nmap, + sizeof (struct alias_map), + (int (*) PARAMS ((const void *, + const void *)) + ) alias_compare); + else + retval = NULL; + + /* We really found an alias. Return the value. */ + if (retval != NULL) + { + result = retval->value; + break; + } + + /* Perhaps we can find another alias file. */ + added = 0; + while (added == 0 && locale_alias_path[0] != '\0') + { + const char *start; + + while (locale_alias_path[0] == ':') + ++locale_alias_path; + start = locale_alias_path; + + while (locale_alias_path[0] != '\0' && locale_alias_path[0] != ':') + ++locale_alias_path; + + if (start < locale_alias_path) + added = read_alias_file (start, locale_alias_path - start); + } + } + while (added != 0); + +#ifdef _LIBC + __libc_lock_unlock (lock); +#endif + + return result; +} + + +static size_t +internal_function +read_alias_file (fname, fname_len) + const char *fname; + int fname_len; +{ +#ifndef HAVE_ALLOCA + struct block_list *block_list = NULL; +#endif + FILE *fp; + char *full_fname; + size_t added; + static const char aliasfile[] = "/locale.alias"; + + full_fname = (char *) alloca (fname_len + sizeof aliasfile); + ADD_BLOCK (block_list, full_fname); +#ifdef HAVE_MEMPCPY + mempcpy (mempcpy (full_fname, fname, fname_len), + aliasfile, sizeof aliasfile); +#else + memcpy (full_fname, fname, fname_len); + memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); +#endif + + fp = fopen (full_fname, "r"); + if (fp == NULL) + { + FREE_BLOCKS (block_list); + return 0; + } + + added = 0; + while (!feof (fp)) + { + /* It is a reasonable approach to use a fix buffer here because + a) we are only interested in the first two fields + b) these fields must be usable as file names and so must not + be that long + */ + char buf[BUFSIZ]; + char *alias; + char *value; + char *cp; + + if (fgets (buf, sizeof buf, fp) == NULL) + /* EOF reached. */ + break; + + /* Possibly not the whole line fits into the buffer. Ignore + the rest of the line. */ + if (strchr (buf, '\n') == NULL) + { + char altbuf[BUFSIZ]; + do + if (fgets (altbuf, sizeof altbuf, fp) == NULL) + /* Make sure the inner loop will be left. The outer loop + will exit at the `feof' test. */ + break; + while (strchr (altbuf, '\n') == NULL); + } + + cp = buf; + /* Ignore leading white space. */ + while (isspace (cp[0])) + ++cp; + + /* A leading '#' signals a comment line. */ + if (cp[0] != '\0' && cp[0] != '#') + { + alias = cp++; + while (cp[0] != '\0' && !isspace (cp[0])) + ++cp; + /* Terminate alias name. */ + if (cp[0] != '\0') + *cp++ = '\0'; + + /* Now look for the beginning of the value. */ + while (isspace (cp[0])) + ++cp; + + if (cp[0] != '\0') + { + size_t alias_len; + size_t value_len; + + value = cp++; + while (cp[0] != '\0' && !isspace (cp[0])) + ++cp; + /* Terminate value. */ + if (cp[0] == '\n') + { + /* This has to be done to make the following test + for the end of line possible. We are looking for + the terminating '\n' which do not overwrite here. */ + *cp++ = '\0'; + *cp = '\n'; + } + else if (cp[0] != '\0') + *cp++ = '\0'; + + if (nmap >= maxmap) + extend_alias_table (); + + alias_len = strlen (alias) + 1; + value_len = strlen (value) + 1; + + if (string_space_act + alias_len + value_len > string_space_max) + { + /* Increase size of memory pool. */ + size_t new_size = (string_space_max + + (alias_len + value_len > 1024 + ? alias_len + value_len : 1024)); + char *new_pool = (char *) realloc (string_space, new_size); + if (new_pool == NULL) + { + FREE_BLOCKS (block_list); + return added; + } + string_space = new_pool; + string_space_max = new_size; + } + + map[nmap].alias = memcpy (&string_space[string_space_act], + alias, alias_len); + string_space_act += alias_len; + + map[nmap].value = memcpy (&string_space[string_space_act], + value, value_len); + string_space_act += value_len; + + ++nmap; + ++added; + } + } + } + + /* Should we test for ferror()? I think we have to silently ignore + errors. --drepper */ + fclose (fp); + + if (added > 0) + qsort (map, nmap, sizeof (struct alias_map), + (int (*) PARAMS ((const void *, const void *))) alias_compare); + + FREE_BLOCKS (block_list); + return added; +} + + +static void +extend_alias_table () +{ + size_t new_size; + struct alias_map *new_map; + + new_size = maxmap == 0 ? 100 : 2 * maxmap; + new_map = (struct alias_map *) realloc (map, (new_size + * sizeof (struct alias_map))); + if (new_map == NULL) + /* Simply don't extend: we don't have any more core. */ + return; + + map = new_map; + maxmap = new_size; +} + + +#ifdef _LIBC +static void __attribute__ ((unused)) +free_mem (void) +{ + if (string_space != NULL) + free (string_space); + if (map != NULL) + free (map); +} +text_set_element (__libc_subfreeres, free_mem); +#endif + + +static int +alias_compare (map1, map2) + const struct alias_map *map1; + const struct alias_map *map2; +{ +#if defined _LIBC || defined HAVE_STRCASECMP + return strcasecmp (map1->alias, map2->alias); +#else + const unsigned char *p1 = (const unsigned char *) map1->alias; + const unsigned char *p2 = (const unsigned char *) map2->alias; + unsigned char c1, c2; + + if (p1 == p2) + return 0; + + do + { + /* I know this seems to be odd but the tolower() function in + some systems libc cannot handle nonalpha characters. */ + c1 = isupper (*p1) ? tolower (*p1) : *p1; + c2 = isupper (*p2) ? tolower (*p2) : *p2; + if (c1 == '\0') + break; + ++p1; + ++p2; + } + while (c1 == c2); + + return c1 - c2; +#endif +} diff --git a/intl/po2tbl.sed.in b/intl/po2tbl.sed.in new file mode 100644 index 00000000..b3bcca4d --- /dev/null +++ b/intl/po2tbl.sed.in @@ -0,0 +1,102 @@ +# po2tbl.sed - Convert Uniforum style .po file to lookup table for catgets +# Copyright (C) 1995 Free Software Foundation, Inc. +# Ulrich Drepper , 1995. +# +# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +1 { + i\ +/* Automatically generated by po2tbl.sed from @PACKAGE NAME@.pot. */\ +\ +#if HAVE_CONFIG_H\ +# include \ +#endif\ +\ +#include "libgettext.h"\ +\ +const struct _msg_ent _msg_tbl[] = { + h + s/.*/0/ + x +} +# +# Write msgid entries in C array form. +# +/^msgid/ { + s/msgid[ ]*\(".*"\)/ {\1/ + tb +# Append the next line + :b + N +# Look whether second part is continuation line. + s/\(.*\)"\(\n\)"\(.*"\)/\1\2\3/ +# Yes, then branch. + ta +# Because we assume that the input file correctly formed the line +# just read cannot be again be a msgid line. So it's safe to ignore +# it. + s/\(.*\)\n.*/\1/ + bc +# We found a continuation line. But before printing insert '\'. + :a + s/\(.*\)\(\n.*\)/\1\\\2/ + P +# We cannot use D here. + s/.*\n\(.*\)/\1/ +# Some buggy seds do not clear the `successful substitution since last ``t''' +# flag on `N', so we do a `t' here to clear it. + tb +# Not reached + :c + x +# The following nice solution is by +# Bruno + td +# Increment a decimal number in pattern space. +# First hide trailing `9' digits. + :d + s/9\(_*\)$/_\1/ + td +# Assure at least one digit is available. + s/^\(_*\)$/0\1/ +# Increment the last digit. + s/8\(_*\)$/9\1/ + s/7\(_*\)$/8\1/ + s/6\(_*\)$/7\1/ + s/5\(_*\)$/6\1/ + s/4\(_*\)$/5\1/ + s/3\(_*\)$/4\1/ + s/2\(_*\)$/3\1/ + s/1\(_*\)$/2\1/ + s/0\(_*\)$/1\1/ +# Convert the hidden `9' digits to `0's. + s/_/0/g + x + G + s/\(.*\)\n\([0-9]*\)/\1, \2},/ + s/\(.*\)"$/\1/ + p +} +# +# Last line. +# +$ { + i\ +};\ + + g + s/0*\(.*\)/int _msg_tbl_length = \1;/p +} +d diff --git a/intl/textdomain.c b/intl/textdomain.c new file mode 100644 index 00000000..88557460 --- /dev/null +++ b/intl/textdomain.c @@ -0,0 +1,108 @@ +/* Implementation of the textdomain(3) function. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Written by Ulrich Drepper , 1995. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +#if defined STDC_HEADERS || defined HAVE_STRING_H || defined _LIBC +# include +#else +# include +# ifndef memcpy +# define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num) +# endif +#endif + +#ifdef _LIBC +# include +#else +# include "libgettext.h" +#endif + +/* @@ end of prolog @@ */ + +/* Name of the default text domain. */ +extern const char _nl_default_default_domain[]; + +/* Default text domain in which entries for gettext(3) are to be found. */ +extern const char *_nl_current_default_domain; + + +/* Names for the libintl functions are a problem. They must not clash + with existing names and they should follow ANSI C. But this source + code is also used in GNU C Library where the names have a __ + prefix. So we have to make a difference here. */ +#ifdef _LIBC +# define TEXTDOMAIN __textdomain +# ifndef strdup +# define strdup(str) __strdup (str) +# endif +#else +# define TEXTDOMAIN textdomain__ +#endif + +/* Set the current default message catalog to DOMAINNAME. + If DOMAINNAME is null, return the current default. + If DOMAINNAME is "", reset to the default of "messages". */ +char * +TEXTDOMAIN (domainname) + const char *domainname; +{ + char *old; + + /* A NULL pointer requests the current setting. */ + if (domainname == NULL) + return (char *) _nl_current_default_domain; + + old = (char *) _nl_current_default_domain; + + /* If domain name is the null string set to default domain "messages". */ + if (domainname[0] == '\0' + || strcmp (domainname, _nl_default_default_domain) == 0) + _nl_current_default_domain = _nl_default_default_domain; + else + { + /* If the following malloc fails `_nl_current_default_domain' + will be NULL. This value will be returned and so signals we + are out of core. */ +#if defined _LIBC || defined HAVE_STRDUP + _nl_current_default_domain = strdup (domainname); +#else + size_t len = strlen (domainname) + 1; + char *cp = (char *) malloc (len); + if (cp != NULL) + memcpy (cp, domainname, len); + _nl_current_default_domain = cp; +#endif + } + + if (old != _nl_default_default_domain) + free (old); + + return (char *) _nl_current_default_domain; +} + +#ifdef _LIBC +/* Alias for function name in GNU C Library. */ +weak_alias (__textdomain, textdomain); +#endif diff --git a/intl/xopen-msg.sed b/intl/xopen-msg.sed new file mode 100644 index 00000000..b19c0bbd --- /dev/null +++ b/intl/xopen-msg.sed @@ -0,0 +1,104 @@ +# po2msg.sed - Convert Uniforum style .po file to X/Open style .msg file +# Copyright (C) 1995 Free Software Foundation, Inc. +# Ulrich Drepper , 1995. +# +# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# +# The first directive in the .msg should be the definition of the +# message set number. We use always set number 1. +# +1 { + i\ +$set 1 # Automatically created by po2msg.sed + h + s/.*/0/ + x +} +# +# We copy all comments into the .msg file. Perhaps they can help. +# +/^#/ s/^#[ ]*/$ /p +# +# We copy the original message as a comment into the .msg file. +# +/^msgid/ { +# Does not work now +# /"$/! { +# s/\\$// +# s/$/ ... (more lines following)"/ +# } + s/^msgid[ ]*"\(.*\)"$/$ Original Message: \1/ + p +} +# +# The .msg file contains, other then the .po file, only the translations +# but each given a unique ID. Starting from 1 and incrementing by 1 for +# each message we assign them to the messages. +# It is important that the .po file used to generate the cat-id-tbl.c file +# (with po-to-tbl) is the same as the one used here. (At least the order +# of declarations must not be changed.) +# +/^msgstr/ { + s/msgstr[ ]*"\(.*\)"/\1/ + x +# The following nice solution is by +# Bruno + td +# Increment a decimal number in pattern space. +# First hide trailing `9' digits. + :d + s/9\(_*\)$/_\1/ + td +# Assure at least one digit is available. + s/^\(_*\)$/0\1/ +# Increment the last digit. + s/8\(_*\)$/9\1/ + s/7\(_*\)$/8\1/ + s/6\(_*\)$/7\1/ + s/5\(_*\)$/6\1/ + s/4\(_*\)$/5\1/ + s/3\(_*\)$/4\1/ + s/2\(_*\)$/3\1/ + s/1\(_*\)$/2\1/ + s/0\(_*\)$/1\1/ +# Convert the hidden `9' digits to `0's. + s/_/0/g + x +# Bring the line in the format ` ' + G + s/^[^\n]*$/& / + s/\(.*\)\n\([0-9]*\)/\2 \1/ +# Clear flag from last substitution. + tb +# Append the next line. + :b + N +# Look whether second part is a continuation line. + s/\(.*\n\)"\(.*\)"/\1\2/ +# Yes, then branch. + ta + P + D +# Note that `D' includes a jump to the start!! +# We found a continuation line. But before printing insert '\'. + :a + s/\(.*\)\(\n.*\)/\1\\\2/ + P +# We cannot use the sed command `D' here + s/.*\n\(.*\)/\1/ + tb +} +d diff --git a/lib/Makefile.am b/lib/Makefile.am new file mode 100644 index 00000000..d9b8572f --- /dev/null +++ b/lib/Makefile.am @@ -0,0 +1,57 @@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +noinst_HEADERS = commonio.h defines.h dialchk.h dialup.h \ + faillog.h getdef.h groupio.h md5.h pam_defs.h port.h prototypes.h \ + pwauth.h pwio.h rcsid.h sgroupio.h shadowio.h snprintf.h \ + tcfsio.h + +localedir = $(datadir)/locale +DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@ + +# These files are unneeded for some reason, listed in +# order of appearance: +# +# sources which are not really needed (are they in libc???) +# sources for dbm support (not yet used) +# sources for LIBOBJS (which are normally in libc) +# misc header sources + +EXTRA_DIST = grdbm.c gsdbm.c pwdbm.c spdbm.c \ + grpack.c gspack.c pwpack.c sppack.c \ + gshadow_.h shadow_.h lastlog_.h snprintf.h + +EXTRA_libshadow_a_SOURCESS = grent.c pwent.c \ + mkdir.c rename.c rmdir.c strdup.c strcasecmp.c strerror.c strstr.c \ + putgrent.c putpwent.c putspent.c \ + sgetgrent.c sgetpwent.c sgetspent.c snprintf.c \ + md5.c md5crypt.c + +# We build libshadow for our tools. + +noinst_LIBRARIES = libshadow.a + +libshadow_a_SOURCES = commonio.c dialchk.c dialup.c encrypt.c \ + fputsx.c getdef.c getpass.c groupio.c gshadow.c lockpw.c port.c \ + pwauth.c pwio.c rad64.c sgroupio.c shadow.c shadowio.c utent.c \ + tcfsio.c + +libshadow_a_LIBADD = @LIBOBJS@ + +INCLUDES = -I$(top_srcdir)/lib + +# shared library support +libdir = ${exec_prefix}/lib +#lib_PROGRAMS = libshadow.la +lib_LTLIBRARIES = libshadow.la +libshadow_la_SOURCES = ${libshadow_a_SOURCES} +#libshadow_la_LIBADD = @LTLIBOBJS@ +#libshadow_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir) +libshadow_la_LDFLAGS = -version-info 0:0:0 + +# remove the libshadow.so -> libshadow.so.x.x symlink, because this +# library is for internal use by this package only. Shadow support +# is in libc and no one should be using -lshadow anymore. +install-exec-hook: + rm -f $(libdir)/libshadow.so + diff --git a/lib/Makefile.in b/lib/Makefile.in new file mode 100644 index 00000000..90a9b05d --- /dev/null +++ b/lib/Makefile.in @@ -0,0 +1,430 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +noinst_HEADERS = commonio.h defines.h dialchk.h dialup.h \ + faillog.h getdef.h groupio.h md5.h pam_defs.h port.h prototypes.h \ + pwauth.h pwio.h rcsid.h sgroupio.h shadowio.h snprintf.h \ + tcfsio.h + +localedir = $(datadir)/locale +DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@ + +# These files are unneeded for some reason, listed in +# order of appearance: +# +# sources which are not really needed (are they in libc???) +# sources for dbm support (not yet used) +# sources for LIBOBJS (which are normally in libc) +# misc header sources + +EXTRA_DIST = grdbm.c gsdbm.c pwdbm.c spdbm.c \ + grpack.c gspack.c pwpack.c sppack.c \ + gshadow_.h shadow_.h lastlog_.h snprintf.h + +EXTRA_libshadow_a_SOURCESS = grent.c pwent.c \ + mkdir.c rename.c rmdir.c strdup.c strcasecmp.c strerror.c strstr.c \ + putgrent.c putpwent.c putspent.c \ + sgetgrent.c sgetpwent.c sgetspent.c snprintf.c \ + md5.c md5crypt.c + +# We build libshadow for our tools. + +noinst_LIBRARIES = libshadow.a + +libshadow_a_SOURCES = commonio.c dialchk.c dialup.c encrypt.c \ + fputsx.c getdef.c getpass.c groupio.c gshadow.c lockpw.c port.c \ + pwauth.c pwio.c rad64.c sgroupio.c shadow.c shadowio.c utent.c \ + tcfsio.c + +libshadow_a_LIBADD = @LIBOBJS@ + +INCLUDES = -I$(top_srcdir)/lib + +# shared library support +libdir = ${exec_prefix}/lib +#lib_PROGRAMS = libshadow.la +lib_LTLIBRARIES = libshadow.la +libshadow_la_SOURCES = ${libshadow_a_SOURCES} +#libshadow_la_LIBADD = @LTLIBOBJS@ +#libshadow_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir) +libshadow_la_LDFLAGS = -version-info 0:0:0 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libshadow_a_DEPENDENCIES = @LIBOBJS@ +libshadow_a_OBJECTS = commonio.o dialchk.o dialup.o encrypt.o fputsx.o \ +getdef.o getpass.o groupio.o gshadow.o lockpw.o port.o pwauth.o pwio.o \ +rad64.o sgroupio.o shadow.o shadowio.o utent.o tcfsio.o +AR = ar +LTLIBRARIES = $(lib_LTLIBRARIES) + +libshadow_la_LIBADD = +libshadow_la_OBJECTS = commonio.lo dialchk.lo dialup.lo encrypt.lo \ +fputsx.lo getdef.lo getpass.lo groupio.lo gshadow.lo lockpw.lo port.lo \ +pwauth.lo pwio.lo rad64.lo sgroupio.lo shadow.lo shadowio.lo utent.lo \ +tcfsio.lo +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@ +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = Makefile.am Makefile.in md5.c md5crypt.c mkdir.c \ +putgrent.c putpwent.c putspent.c rename.c rmdir.c sgetgrent.c \ +sgetpwent.c sgetspent.c snprintf.c strcasecmp.c strdup.c strerror.c \ +strstr.c + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +SOURCES = $(libshadow_a_SOURCES) $(libshadow_la_SOURCES) +OBJECTS = $(libshadow_a_OBJECTS) $(libshadow_la_OBJECTS) + +all: Makefile $(LIBRARIES) $(LTLIBRARIES) $(HEADERS) + +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps lib/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libshadow.a: $(libshadow_a_OBJECTS) $(libshadow_a_DEPENDENCIES) + -rm -f libshadow.a + $(AR) cru libshadow.a $(libshadow_a_OBJECTS) $(libshadow_a_LIBADD) + $(RANLIB) libshadow.a + +mostlyclean-libLTLIBRARIES: + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + +distclean-libLTLIBRARIES: + +maintainer-clean-libLTLIBRARIES: + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(libdir) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + echo "$(LIBTOOL) --mode=install $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p"; \ + $(LIBTOOL) --mode=install $(INSTALL_DATA) $$p $(DESTDIR)$(libdir)/$$p; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \ + done + +libshadow.la: $(libshadow_la_OBJECTS) $(libshadow_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libshadow_la_LDFLAGS) $(libshadow_la_OBJECTS) $(libshadow_la_LIBADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = lib + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +commonio.o: commonio.c ../config.h rcsid.h defines.h gshadow_.h \ + commonio.h +dialchk.o: dialchk.c ../config.h rcsid.h defines.h gshadow_.h \ + prototypes.h dialup.h dialchk.h +dialup.o: dialup.c ../config.h rcsid.h prototypes.h defines.h gshadow_.h \ + dialup.h +encrypt.o: encrypt.c ../config.h rcsid.h prototypes.h defines.h \ + gshadow_.h +fputsx.lo fputsx.o: fputsx.c ../config.h defines.h gshadow_.h rcsid.h +getdef.lo getdef.o: getdef.c ../config.h rcsid.h prototypes.h defines.h \ + gshadow_.h getdef.h +getpass.lo getpass.o: getpass.c ../config.h rcsid.h defines.h gshadow_.h +groupio.lo groupio.o: groupio.c ../config.h rcsid.h prototypes.h \ + defines.h gshadow_.h commonio.h groupio.h +gshadow.lo gshadow.o: gshadow.c ../config.h rcsid.h prototypes.h \ + defines.h gshadow_.h +lockpw.lo lockpw.o: lockpw.c ../config.h +port.lo port.o: port.c ../config.h rcsid.h defines.h gshadow_.h port.h +putgrent.o: putgrent.c ../config.h prototypes.h defines.h gshadow_.h +pwauth.lo pwauth.o: pwauth.c ../config.h rcsid.h prototypes.h defines.h \ + gshadow_.h pwauth.h getdef.h +pwio.lo pwio.o: pwio.c ../config.h rcsid.h prototypes.h defines.h \ + gshadow_.h commonio.h pwio.h +rad64.lo rad64.o: rad64.c ../config.h rcsid.h +sgetgrent.o: sgetgrent.c ../config.h rcsid.h defines.h gshadow_.h +sgetpwent.o: sgetpwent.c ../config.h rcsid.h defines.h gshadow_.h +sgroupio.lo sgroupio.o: sgroupio.c ../config.h rcsid.h prototypes.h \ + defines.h gshadow_.h commonio.h sgroupio.h +shadowio.lo shadowio.o: shadowio.c ../config.h rcsid.h prototypes.h \ + defines.h gshadow_.h commonio.h shadowio.h +shadow.lo shadow.o: shadow.c ../config.h +tcfsio.lo tcfsio.o: tcfsio.c ../config.h +utent.lo utent.o: utent.c ../config.h + +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: install-libLTLIBRARIES + @$(NORMAL_INSTALL) + $(MAKE) install-exec-hook + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: uninstall-libLTLIBRARIES + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + $(mkinstalldirs) $(DATADIR)$(libdir) + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-libLTLIBRARIES \ + mostlyclean-tags mostlyclean-generic + +clean: clean-noinstLIBRARIES clean-compile clean-libtool \ + clean-libLTLIBRARIES clean-tags clean-generic \ + mostlyclean + +distclean: distclean-noinstLIBRARIES distclean-compile \ + distclean-libtool distclean-libLTLIBRARIES \ + distclean-tags distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-libLTLIBRARIES maintainer-clean-tags \ + maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile mostlyclean-libtool distclean-libtool \ +clean-libtool maintainer-clean-libtool mostlyclean-libLTLIBRARIES \ +distclean-libLTLIBRARIES clean-libLTLIBRARIES \ +maintainer-clean-libLTLIBRARIES uninstall-libLTLIBRARIES \ +install-libLTLIBRARIES tags mostlyclean-tags distclean-tags clean-tags \ +maintainer-clean-tags distdir info dvi installcheck install-exec \ +install-data install uninstall all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# remove the libshadow.so -> libshadow.so.x.x symlink, because this +# library is for internal use by this package only. Shadow support +# is in libc and no one should be using -lshadow anymore. +install-exec-hook: + rm -f $(libdir)/libshadow.so + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lib/commonio.c b/lib/commonio.c new file mode 100644 index 00000000..2bee8838 --- /dev/null +++ b/lib/commonio.c @@ -0,0 +1,739 @@ + +#include + +#include "rcsid.h" +RCSID("$Id: commonio.c,v 1.14 1998/07/23 22:13:15 marekm Exp $") + +#include "defines.h" +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SHADOW_H +#include +#endif + +#include "commonio.h" + +/* local function prototypes */ +static int check_link_count P_((const char *)); +static int do_lock_file P_((const char *, const char *)); +static FILE *fopen_set_perms P_((const char *, const char *, const struct stat *)); +static int create_backup P_((const char *, FILE *)); +static void free_linked_list P_((struct commonio_db *)); +static void add_one_entry P_((struct commonio_db *, struct commonio_entry *)); +static int name_is_nis P_((const char *)); +static int write_all P_((const struct commonio_db *)); +static struct commonio_entry *find_entry_by_name P_((struct commonio_db *, const char *)); + +#ifdef HAVE_LCKPWDF +static int lock_count = 0; +#endif + +static int +check_link_count(const char *file) +{ + struct stat sb; + + if (stat(file, &sb) != 0) + return 0; + + if (sb.st_nlink != 2) + return 0; + + return 1; +} + + +static int +do_lock_file(const char *file, const char *lock) +{ + int fd; + int pid; + int len; + int retval; + char buf[32]; + + if ((fd = open(file, O_CREAT|O_EXCL|O_WRONLY, 0600)) == -1) + return 0; + + pid = getpid(); + snprintf(buf, sizeof buf, "%d", pid); + len = strlen(buf) + 1; + if (write(fd, buf, len) != len) { + close(fd); + unlink(file); + return 0; + } + close(fd); + + if (link(file, lock) == 0) { + retval = check_link_count(file); + unlink(file); + return retval; + } + + if ((fd = open(lock, O_RDWR)) == -1) { + unlink(file); + errno = EINVAL; + return 0; + } + len = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (len <= 0) { + unlink(file); + errno = EINVAL; + return 0; + } + buf[len] = '\0'; + if ((pid = strtol(buf, (char **) 0, 10)) == 0) { + unlink(file); + errno = EINVAL; + return 0; + } + if (kill(pid, 0) == 0) { + unlink(file); + errno = EEXIST; + return 0; + } + if (unlink(lock) != 0) { + unlink(file); + return 0; + } + + retval = 0; + if (link(file, lock) == 0 && check_link_count(file)) + retval = 1; + + unlink(file); + return retval; +} + + +static FILE * +fopen_set_perms(const char *name, const char *mode, const struct stat *sb) +{ + FILE *fp; + mode_t mask; + + mask = umask(0777); + fp = fopen(name, mode); + umask(mask); + if (!fp) + return NULL; + +#ifdef HAVE_FCHOWN + if (fchown(fileno(fp), sb->st_uid, sb->st_gid)) + goto fail; +#else + if (chown(name, sb->st_mode)) + goto fail; +#endif + +#ifdef HAVE_FCHMOD + if (fchmod(fileno(fp), sb->st_mode & 0664)) + goto fail; +#else + if (chmod(name, sb->st_mode & 0664)) + goto fail; +#endif + return fp; + +fail: + fclose(fp); + unlink(name); + return NULL; +} + + +static int +create_backup(const char *backup, FILE *fp) +{ + struct stat sb; + struct utimbuf ub; + FILE *bkfp; + int c; + mode_t mask; + + if (fstat(fileno(fp), &sb)) + return -1; + + mask = umask(077); + bkfp = fopen(backup, "w"); + umask(mask); + if (!bkfp) + return -1; + + /* TODO: faster copy, not one-char-at-a-time. --marekm */ + rewind(fp); + while ((c = getc(fp)) != EOF) { + if (putc(c, bkfp) == EOF) + break; + } + if (c != EOF || fflush(bkfp)) { + fclose(bkfp); + return -1; + } + if (fclose(bkfp)) + return -1; + + ub.actime = sb.st_atime; + ub.modtime = sb.st_mtime; + utime(backup, &ub); + return 0; +} + + +static void +free_linked_list(struct commonio_db *db) +{ + struct commonio_entry *p; + + while (db->head) { + p = db->head; + db->head = p->next; + + if (p->line) + free(p->line); + + if (p->entry) + db->ops->free(p->entry); + + free(p); + } + db->tail = NULL; +} + + +int +commonio_setname(struct commonio_db *db, const char *name) +{ + strcpy(db->filename, name); + return 1; +} + + +int +commonio_present(const struct commonio_db *db) +{ + return (access(db->filename, F_OK) == 0); +} + + +int +commonio_lock_nowait(struct commonio_db *db) +{ + char file[1024]; + char lock[1024]; + + if (db->locked) + return 1; + + snprintf(file, sizeof file, "%s.%ld", db->filename, (long) getpid()); + snprintf(lock, sizeof lock, "%s.lock", db->filename); + if (do_lock_file(file, lock)) { + db->locked = 1; + return 1; + } + return 0; +} + + +int +commonio_lock(struct commonio_db *db) +{ + int i; + +#ifdef HAVE_LCKPWDF + /* + * only if the system libc has a real lckpwdf() - the one from + * lockpw.c calls us and would cause infinite recursion! + */ + if (db->use_lckpwdf) { + /* + * Call lckpwdf() on the first lock. + * If it succeeds, call *_lock() only once + * (no retries, it should always succeed). + */ + if (lock_count == 0) { + if (lckpwdf() == -1) + return 0; /* failure */ + } + if (!commonio_lock_nowait(db)) { + ulckpwdf(); + return 0; /* failure */ + } + lock_count++; + return 1; /* success */ + } +#endif + /* + * lckpwdf() not used - do it the old way. + */ +#ifndef LOCK_TRIES +#define LOCK_TRIES 15 +#endif + +#ifndef LOCK_SLEEP +#define LOCK_SLEEP 1 +#endif + for (i = 0; i < LOCK_TRIES; i++) { + if (i > 0) + sleep(LOCK_SLEEP); /* delay between retries */ + if (commonio_lock_nowait(db)) + return 1; /* success */ + /* no unnecessary retries on "permission denied" errors */ + if (geteuid() != 0) + return 0; + } + return 0; /* failure */ +} + + +int +commonio_unlock(struct commonio_db *db) +{ + char lock[1024]; + + if (db->isopen) { + db->readonly = 1; + if (!commonio_close(db)) + return 0; + } + if (db->locked) { + /* + * Unlock in reverse order: remove the lock file, + * then call ulckpwdf() (if used) on last unlock. + */ + db->locked = 0; + snprintf(lock, sizeof lock, "%s.lock", db->filename); + unlink(lock); +#ifdef HAVE_LCKPWDF + if (db->use_lckpwdf && lock_count > 0) { + lock_count--; + if (lock_count == 0) + ulckpwdf(); + } +#endif + return 1; + } + return 0; +} + + +static void +add_one_entry(struct commonio_db *db, struct commonio_entry *p) +{ + p->next = NULL; + p->prev = db->tail; + if (!db->head) + db->head = p; + if (db->tail) + db->tail->next = p; + db->tail = p; +} + + +static int +name_is_nis(const char *n) +{ + return (n[0] == '+' || n[0] == '-'); +} + + +/* + * New entries are inserted before the first NIS entry. Order is preserved + * when db is written out. + */ +#ifndef KEEP_NIS_AT_END +#define KEEP_NIS_AT_END 1 +#endif + +#if KEEP_NIS_AT_END +/* prototype */ +static void add_one_entry_nis P_((struct commonio_db *, struct commonio_entry *)); + +static void +add_one_entry_nis(struct commonio_db *db, struct commonio_entry *new) +{ + struct commonio_entry *p; + + for (p = db->head; p; p = p->next) { + if (name_is_nis(p->entry ? db->ops->getname(p->entry) : p->line)) { + new->next = p; + new->prev = p->prev; + if (p->prev) + p->prev->next = new; + else + db->head = new; + p->prev = new; + return; + } + } + add_one_entry(db, new); +} +#endif /* KEEP_NIS_AT_END */ + + +int +commonio_open(struct commonio_db *db, int mode) +{ + char buf[8192]; + char *cp; + char *line; + struct commonio_entry *p; + void *entry; + int flags = mode; + + mode &= ~O_CREAT; + + if (db->isopen || (mode != O_RDONLY && mode != O_RDWR)) { + errno = EINVAL; + return 0; + } + db->readonly = (mode == O_RDONLY); + if (!db->readonly && !db->locked) { + errno = EACCES; + return 0; + } + + db->head = db->tail = db->cursor = NULL; + db->changed = 0; + + db->fp = fopen(db->filename, db->readonly ? "r" : "r+"); + + /* + * If O_CREAT was specified and the file didn't exist, it will be + * created by commonio_close(). We have no entries to read yet. --marekm + */ + if (!db->fp) { + if ((flags & O_CREAT) && errno == ENOENT) { + db->isopen = 1; + return 1; + } + return 0; + } + + while (db->ops->fgets(buf, sizeof buf, db->fp)) { + if ((cp = strrchr(buf, '\n'))) + *cp = '\0'; + + if (!(line = strdup(buf))) + goto cleanup; + + if (name_is_nis(line)) { + entry = NULL; + } else if ((entry = db->ops->parse(line))) { + entry = db->ops->dup(entry); + if (!entry) + goto cleanup_line; + } + + p = (struct commonio_entry *) malloc(sizeof *p); + if (!p) + goto cleanup_entry; + + p->entry = entry; + p->line = line; + p->changed = 0; + + add_one_entry(db, p); + } + + db->isopen = 1; + return 1; + +cleanup_entry: + if (entry) + db->ops->free(entry); +cleanup_line: + free(line); +cleanup: + free_linked_list(db); + fclose(db->fp); + db->fp = NULL; + errno = ENOMEM; + return 0; +} + + +static int +write_all(const struct commonio_db *db) +{ + const struct commonio_entry *p; + void *entry; + + for (p = db->head; p; p = p->next) { + if (p->changed) { + entry = p->entry; + if (db->ops->put(entry, db->fp)) + return -1; + } else if (p->line) { + if (db->ops->fputs(p->line, db->fp) == EOF) + return -1; + if (putc('\n', db->fp) == EOF) + return -1; + } + } + return 0; +} + + +int +commonio_close(struct commonio_db *db) +{ + char buf[1024]; + int errors = 0; + struct stat sb; + + if (!db->isopen) { + errno = EINVAL; + return 0; + } + db->isopen = 0; + + if (!db->changed || db->readonly) { + fclose(db->fp); + db->fp = NULL; + goto success; + } + + memzero(&sb, sizeof sb); + if (db->fp) { + if (fstat(fileno(db->fp), &sb)) { + fclose(db->fp); + db->fp = NULL; + goto fail; + } + + /* + * Create backup file. + */ + snprintf(buf, sizeof buf, "%s-", db->filename); + + if (create_backup(buf, db->fp)) + errors++; + + if (fclose(db->fp)) + errors++; + + if (errors) { + db->fp = NULL; + goto fail; + } + } else { + /* + * Default permissions for new [g]shadow files. + * (passwd and group always exist...) + */ + sb.st_mode = 0400; + sb.st_uid = 0; + sb.st_gid = 0; + } + + snprintf(buf, sizeof buf, "%s+", db->filename); + + db->fp = fopen_set_perms(buf, "w", &sb); + if (!db->fp) + goto fail; + + if (write_all(db)) + errors++; + + if (fflush(db->fp)) + errors++; +#ifdef HAVE_FSYNC + if (fsync(fileno(db->fp))) + errors++; +#else + sync(); +#endif + if (fclose(db->fp)) + errors++; + + db->fp = NULL; + + if (errors) { + unlink(buf); + goto fail; + } + + if (rename(buf, db->filename)) + goto fail; + +success: + free_linked_list(db); + return 1; + +fail: + free_linked_list(db); + return 0; +} + + +static struct commonio_entry * +find_entry_by_name(struct commonio_db *db, const char *name) +{ + struct commonio_entry *p; + void *ep; + + for (p = db->head; p; p = p->next) { + ep = p->entry; + if (ep && strcmp(db->ops->getname(ep), name) == 0) + break; + } + return p; +} + + +int +commonio_update(struct commonio_db *db, const void *entry) +{ + struct commonio_entry *p; + void *nentry; + + if (!db->isopen || db->readonly) { + errno = EINVAL; + return 0; + } + if (!(nentry = db->ops->dup(entry))) { + errno = ENOMEM; + return 0; + } + p = find_entry_by_name(db, db->ops->getname(entry)); + if (p) { + db->ops->free(p->entry); + p->entry = nentry; + p->changed = 1; + db->cursor = p; + + db->changed = 1; + return 1; + } + /* not found, new entry */ + p = (struct commonio_entry *) malloc(sizeof *p); + if (!p) { + db->ops->free(nentry); + errno = ENOMEM; + return 0; + } + + p->entry = nentry; + p->line = NULL; + p->changed = 1; + +#if KEEP_NIS_AT_END + add_one_entry_nis(db, p); +#else + add_one_entry(db, p); +#endif + + db->changed = 1; + return 1; +} + + +void +commonio_del_entry(struct commonio_db *db, const struct commonio_entry *p) +{ + if (p == db->cursor) + db->cursor = p->next; + + if (p->prev) + p->prev->next = p->next; + else + db->head = p->next; + + if (p->next) + p->next->prev = p->prev; + else + db->tail = p->prev; + + db->changed = 1; +} + + +int +commonio_remove(struct commonio_db *db, const char *name) +{ + struct commonio_entry *p; + + if (!db->isopen || db->readonly) { + errno = EINVAL; + return 0; + } + p = find_entry_by_name(db, name); + if (!p) { + errno = ENOENT; + return 0; + } + + commonio_del_entry(db, p); + + if (p->line) + free(p->line); + + if (p->entry) + db->ops->free(p->entry); + + return 1; +} + + +const void * +commonio_locate(struct commonio_db *db, const char *name) +{ + struct commonio_entry *p; + + if (!db->isopen) { + errno = EINVAL; + return NULL; + } + p = find_entry_by_name(db, name); + if (!p) { + errno = ENOENT; + return NULL; + } + db->cursor = p; + return p->entry; +} + + +int +commonio_rewind(struct commonio_db *db) +{ + if (!db->isopen) { + errno = EINVAL; + return 0; + } + db->cursor = NULL; + return 1; +} + + +const void * +commonio_next(struct commonio_db *db) +{ + void *entry; + + if (!db->isopen) { + errno = EINVAL; + return 0; + } + if (db->cursor == NULL) + db->cursor = db->head; + else + db->cursor = db->cursor->next; + + while (db->cursor) { + entry = db->cursor->entry; + if (entry) + return entry; + + db->cursor = db->cursor->next; + } + return NULL; +} diff --git a/lib/commonio.h b/lib/commonio.h new file mode 100644 index 00000000..98da1640 --- /dev/null +++ b/lib/commonio.h @@ -0,0 +1,101 @@ +/* $Id: commonio.h,v 1.4 1998/01/29 23:22:27 marekm Exp $ */ + +/* + * Linked list entry. + */ +struct commonio_entry { + char *line; + void *entry; /* struct passwd, struct spwd, ... */ + struct commonio_entry *prev, *next; + int changed:1; +}; + +/* + * Operations depending on database type: passwd, group, shadow etc. + */ +struct commonio_ops { + /* + * Make a copy of the object (for example, struct passwd) + * and all strings pointed by it, in malloced memory. + */ + void * (*dup) P_((const void *)); + + /* + * free() the object including any strings pointed by it. + */ + void (*free) P_((void *)); + + /* + * Return the name of the object (for example, pw_name + * for struct passwd). + */ + const char * (*getname) P_((const void *)); + + /* + * Parse a string, return object (in static area - + * should be copied using the dup operation above). + */ + void * (*parse) P_((const char *)); + + /* + * Write the object to the file (this calls putpwent() + * for struct passwd, for example). + */ + int (*put) P_((const void *, FILE *)); + + /* + * fgets and fputs (can be replaced by versions that + * understand line continuation conventions). + */ + char * (*fgets) P_((char *, int, FILE *)); + int (*fputs) P_((const char *, FILE *)); +}; + +/* + * Database structure. + */ +struct commonio_db { + /* + * Name of the data file. + */ + char filename[1024]; + + /* + * Operations from above. + */ + struct commonio_ops *ops; + + /* + * Currently open file stream. + */ + FILE *fp; + + /* + * Head, tail, current position in linked list. + */ + struct commonio_entry *head, *tail, *cursor; + + /* + * Various flags. + */ + int changed:1; + int isopen:1; + int locked:1; + int readonly:1; + int use_lckpwdf:1; +}; + +extern int commonio_setname P_((struct commonio_db *, const char *)); +extern int commonio_present P_((const struct commonio_db *)); +extern int commonio_lock P_((struct commonio_db *)); +extern int commonio_lock_nowait P_((struct commonio_db *)); +extern int commonio_open P_((struct commonio_db *, int)); +extern const void *commonio_locate P_((struct commonio_db *, const char *)); +extern int commonio_update P_((struct commonio_db *, const void *)); +extern int commonio_remove P_((struct commonio_db *, const char *)); +extern int commonio_rewind P_((struct commonio_db *)); +extern const void *commonio_next P_((struct commonio_db *)); +extern int commonio_close P_((struct commonio_db *)); +extern int commonio_unlock P_((struct commonio_db *)); +extern void commonio_del_entry P_((struct commonio_db *, const struct commonio_entry *)); + diff --git a/lib/defines.h b/lib/defines.h new file mode 100644 index 00000000..99b65126 --- /dev/null +++ b/lib/defines.h @@ -0,0 +1,319 @@ +/* $Id: defines.h,v 1.14 1999/03/07 19:14:34 marekm Exp $ */ +/* some useful defines */ + +#ifndef _DEFINES_H_ +#define _DEFINES_H_ + +#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) + +/* Take care of NLS matters. */ + +#if HAVE_LOCALE_H +# include +#endif +#if !HAVE_SETLOCALE +# define setlocale(Category, Locale) /* empty */ +#endif + +#define gettext_noop(String) (String) +/* #define gettext_def(String) "#define String" */ + +#if ENABLE_NLS +# include +# define _(Text) gettext (Text) +#else +# undef bindtextdomain +# define bindtextdomain(Domain, Directory) /* empty */ +# undef textdomain +# define textdomain(Domain) /* empty */ +# define _(Text) Text +#endif + +#ifndef P_ +# ifdef PROTOTYPES +# define P_(x) x +# else +# define P_(x) () +# endif +#endif + +#if STDC_HEADERS +# include +# include +#else /* not STDC_HEADERS */ +# ifndef HAVE_STRCHR +# define strchr index +# define strrchr rindex +# endif +char *strchr(), *strrchr(), *strtok(); +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy((s), (d), (n)) +# endif +#endif /* not STDC_HEADERS */ + +/* Solaris 2.4 defines __SVR4, but not SVR4 -j. */ + +#ifdef __SVR4 +# ifndef SVR4 +# define SVR4 __SVR4 +# endif +#endif + +#include +#include +#if HAVE_SYS_WAIT_H +# include +#endif +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +#if HAVE_UNISTD_H +# include +#endif + +#if TIME_WITH_SYS_TIME +# include +# include +#else /* not TIME_WITH_SYS_TIME */ +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif /* not TIME_WITH_SYS_TIME */ + +#ifdef HAVE_MEMSET +# define memzero(ptr, size) memset((void *)(ptr), 0, (size)) +#else +# define memzero(ptr, size) bzero((char *)(ptr), (size)) +#endif +#define strzero(s) memzero(s, strlen(s)) /* warning: evaluates twice */ + +#ifdef HAVE_DIRENT_H /* DIR_SYSV */ +# include +# define DIRECT dirent +#else +# ifdef HAVE_SYS_NDIR_H /* DIR_XENIX */ +# include +# endif +# ifdef HAVE_SYS_DIR_H /* DIR_??? */ +# include +# endif +# ifdef HAVE_NDIR_H /* DIR_BSD */ +# include +# endif +# define DIRECT direct +#endif + +#ifdef SHADOWPWD +/* + * Possible cases: + * - /usr/include/shadow.h exists and includes the shadow group stuff. + * - /usr/include/shadow.h exists, but we use our own gshadow.h. + * - /usr/include/shadow.h doesn't exist, use our own shadow.h and gshadow.h. + */ +#if HAVE_SHADOW_H +#include +#if defined(SHADOWGRP) && !defined(GSHADOW) +#include "gshadow_.h" +#endif +#else /* not HAVE_SHADOW_H */ +#include "shadow_.h" +#ifdef SHADOWGRP +#include "gshadow_.h" +#endif +#endif /* not HAVE_SHADOW_H */ +#endif /* SHADOWPWD */ + +#include + +#ifndef NGROUPS_MAX +#ifdef NGROUPS +#define NGROUPS_MAX NGROUPS +#else +#define NGROUPS_MAX 64 +#endif +#endif + +#ifdef USE_SYSLOG +#include + +#ifndef LOG_WARN +#define LOG_WARN LOG_WARNING +#endif + +/* cleaner than lots of #ifdefs everywhere - use this as follows: + SYSLOG((LOG_CRIT, "user %s cracked root", user)); */ +#if HAVE_SETLOCALE +/* Temporarily set LC_TIME to "C" to avoid strange dates in syslog. + This is a workaround for a more general syslog(d) design problem - + syslogd should log the current system time for each event, and not + trust the formatted time received from the unix domain socket. -MM */ +#define SYSLOG(x) \ + do { \ + char *saved_locale = setlocale(LC_ALL, NULL); \ + if (saved_locale) \ + saved_locale = strdup(saved_locale); \ + if (saved_locale) \ + setlocale(LC_TIME, "C"); \ + syslog x ; \ + if (saved_locale) { \ + setlocale(LC_ALL, saved_locale); \ + free(saved_locale); \ + } \ + } while (0) +#else /* !HAVE_SETLOCALE */ +#define SYSLOG(x) syslog x +#endif /* !HAVE_SETLOCALE */ + +#else /* !USE_SYSLOG */ + +#define SYSLOG(x) /* empty */ +#define openlog(a,b,c) /* empty */ +#define closelog() /* empty */ + +#endif /* !USE_SYSLOG */ + +#ifndef F_OK +# define F_OK 0 +# define X_OK 1 +# define W_OK 2 +# define R_OK 4 +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif + +#ifdef STAT_MACROS_BROKEN +# define S_ISDIR(x) ((x) & S_IFMT) == S_IFDIR) +# define S_ISREG(x) ((x) & S_IFMT) == S_IFREG) +# define S_ISLNK(x) ((x) & S_IFMT) == S_IFLNK) +#endif + +#if HAVE_TERMIOS_H +# include +# define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio) +# define GTTY(fd, termio) tcgetattr(fd, termio) +# define TERMIO struct termios +# define USE_TERMIOS +#elif HAVE_TERMIO_H +# include +# include +# define STTY(fd, termio) ioctl(fd, TCSETA, termio) +# define GTTY(fd, termio) ioctl(fd, TCGETA, termio) +# define TEMRIO struct termio +# define USE_TERMIO +#elif HAVE_SGTTY_H +# include +# define STTY(fd, termio) stty(fd, termio) +# define GTTY(fd, termio) gtty(fd, termio) +# define TERMIO struct sgttyb +# define USE_SGTTY +#endif + +/* + * Password aging constants + * + * DAY - seconds / day + * WEEK - seconds / week + * SCALE - seconds / aging unit + */ + +/* Solaris defines this in shadow.h */ +#ifndef DAY +#define DAY (24L*3600L) +#endif + +#define WEEK (7*DAY) + +#ifdef ITI_AGING +#define SCALE 1 +#else +#define SCALE DAY +#endif + +/* Copy string pointed by B to array A with size checking. It was originally + in lmain.c but is _very_ useful elsewhere. Some setuid root programs with + very sloppy coding used to assume that BUFSIZ will always be enough... */ + + /* danger - side effects */ +#define STRFCPY(A,B) \ + (strncpy((A), (B), sizeof(A) - 1), (A)[sizeof(A) - 1] = '\0') + +/* get rid of a few ugly repeated #ifdefs in pwent.c and grent.c */ +/* XXX - this is ugly too, configure should test it and not check for + any hardcoded system names, if possible. --marekm */ +#if defined(SVR4) || defined(AIX) || defined(__linux__) +#define SETXXENT_TYPE void +#define SETXXENT_RET(x) return +#define SETXXENT_TEST(x) x; if (0) /* compiler should optimize this away */ +#else +#define SETXXENT_TYPE int +#define SETXXENT_RET(x) return(x) +#define SETXXENT_TEST(x) if (x) +#endif + +#ifndef PASSWD_FILE +#define PASSWD_FILE "/etc/passwd" +#endif + +#ifndef GROUP_FILE +#define GROUP_FILE "/etc/group" +#endif + +#ifdef SHADOWPWD +#ifndef SHADOW_FILE +#define SHADOW_FILE "/etc/shadow" +#endif +#endif + +#ifdef SHADOWGRP +#ifndef SGROUP_FILE +#define SGROUP_FILE "/etc/gshadow" +#endif +#endif + +#define PASSWD_PAG_FILE PASSWD_FILE ".pag" +#define GROUP_PAG_FILE GROUP_FILE ".pag" +#define SHADOW_PAG_FILE SHADOW_FILE ".pag" +#define SGROUP_PAG_FILE SGROUP_FILE ".pag" + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#ifdef sun /* hacks for compiling on SunOS */ +# ifndef SOLARIS +extern int fputs(); +extern char *strdup(); +extern char *strerror(); +# endif +#endif + +#ifndef HAVE_SNPRINTF +#include "snprintf.h" +#endif + +/* + * string to use for the pw_passwd field in /etc/passwd when using + * shadow passwords - most systems use "x" but there are a few + * exceptions, so it can be changed here if necessary. --marekm + */ +#ifndef SHADOW_PASSWD_STRING +#define SHADOW_PASSWD_STRING "x" +#endif + +#ifdef PAM_STRERROR_NEEDS_TWO_ARGS /* Linux-PAM 0.59+ */ +#define PAM_STRERROR(pamh, err) pam_strerror(pamh, err) +#else +#define PAM_STRERROR(pamh, err) pam_strerror(err) +#endif + +#endif /* _DEFINES_H_ */ diff --git a/lib/dialchk.c b/lib/dialchk.c new file mode 100644 index 00000000..5216a324 --- /dev/null +++ b/lib/dialchk.c @@ -0,0 +1,77 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: dialchk.c,v 1.5 1998/12/28 20:34:34 marekm Exp $") + +#include +#include "defines.h" +#include "prototypes.h" +#include "dialup.h" +#include "dialchk.h" + +/* + * Check for dialup password + * + * dialcheck tests to see if tty is listed as being a dialup + * line. If so, a dialup password may be required if the shell + * is listed as one which requires a second password. + */ + +int +dialcheck(const char *tty, const char *sh) +{ + struct dialup *dialup; + char *pass; + char *cp; + + setduent (); + + if (! isadialup (tty)) { + endduent (); + return (1); + } + if (! (dialup = getdushell (sh))) { + endduent (); + return (1); + } + endduent (); + + if (dialup->du_passwd[0] == '\0') + return (1); + + if (! (pass = getpass(_("Dialup Password:")))) + return (0); + + cp = pw_encrypt (pass, dialup->du_passwd); + strzero(pass); + return (strcmp (cp, dialup->du_passwd) == 0); +} diff --git a/lib/dialchk.h b/lib/dialchk.h new file mode 100644 index 00000000..9da2d31e --- /dev/null +++ b/lib/dialchk.h @@ -0,0 +1,16 @@ +/* $Id: dialchk.h,v 1.1 1997/12/07 23:26:49 marekm Exp $ */ +#ifndef _DIALCHK_H_ +#define _DIALCHK_H_ + +#include "defines.h" + +/* + * Check for dialup password + * + * dialcheck tests to see if tty is listed as being a dialup + * line. If so, a dialup password may be required if the shell + * is listed as one which requires a second password. + */ +extern int dialcheck P_((const char *tty, const char *sh)); + +#endif diff --git a/lib/dialup.c b/lib/dialup.c new file mode 100644 index 00000000..7965c1ae --- /dev/null +++ b/lib/dialup.c @@ -0,0 +1,169 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: dialup.c,v 1.3 1997/12/07 23:26:50 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include "dialup.h" + +static FILE *dialpwd; + +void +setduent(void) +{ + if (dialpwd) + rewind (dialpwd); + else + dialpwd = fopen (DIALPWD, "r"); +} + +void +endduent(void) +{ + if (dialpwd) + fclose (dialpwd); + + dialpwd = (FILE *) 0; +} + +struct dialup * +fgetduent(FILE *fp) +{ + static struct dialup dialup; /* static structure to point to */ + static char sh[128]; /* some space for a login shell */ + static char passwd[128]; /* some space for dialup password */ + char buf[BUFSIZ]; + char *cp; + char *cp2; + + if (! fp) + return 0; + + if (! fp || feof (fp)) + return ((struct dialup *) 0); + + while (fgets (buf, sizeof buf, fp) == buf && buf[0] == '#') + ; + + if (feof (fp)) + return ((struct dialup *) 0); + + if ((cp = strchr (buf, '\n'))) + *cp = '\0'; + + if (! (cp = strchr (buf, ':'))) + return ((struct dialup *) 0); + + if (cp - buf > sizeof sh) /* something is fishy ... */ + return ((struct dialup *) 0); + + *cp++ = '\0'; + (void) strcpy (sh, buf); + sh[cp - buf] = '\0'; + + if ((cp2 = strchr (cp, ':'))) + *cp2 = '\0'; + + if (strlen (cp) + 1 > sizeof passwd) /* something is REALLY fishy */ + return ((struct dialup *) 0); + + (void) strcpy (passwd, cp); + + dialup.du_shell = sh; + dialup.du_passwd = passwd; + + return (&dialup); +} + +struct dialup * +getduent(void) +{ + if (! dialpwd) + setduent (); + + return fgetduent (dialpwd); +} + +struct dialup * +getdushell(const char *sh) +{ + struct dialup *dialup; + + while ((dialup = getduent ())) { + if (strcmp (sh, dialup->du_shell) == 0) + return (dialup); + + if (strcmp (dialup->du_shell, "*") == 0) + return (dialup); + } + return ((struct dialup *) 0); +} + +int +isadialup(const char *tty) +{ + FILE *fp; + char buf[BUFSIZ]; + int dialup = 0; + + if (! (fp = fopen (DIALUPS, "r"))) + return (0); + + while (fgets (buf, sizeof buf, fp) == buf) { + if (buf[0] == '#') + continue; + + buf[strlen (buf) - 1] = '\0'; + + if (strcmp (buf, tty) == 0) { + dialup = 1; + break; + } + } + fclose (fp); + + return (dialup); +} + +int +putduent(const struct dialup *dial, FILE *fp) +{ + if (! fp || ! dial) + return -1; + + if (fprintf (fp, "%s:%s\n", dial->du_shell, dial->du_passwd) == EOF) + return -1; + + return 0; +} diff --git a/lib/dialup.h b/lib/dialup.h new file mode 100644 index 00000000..e261b14e --- /dev/null +++ b/lib/dialup.h @@ -0,0 +1,66 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Structure of the /etc/d_passwd file + * + * The d_passwd file contains the names of login shells which require + * dialup passwords. Each line contains the fully qualified path name + * for the shell, followed by an optional password. Each field is + * separated by a ':'. + * + * Structure of the /etc/dialups file + * + * The dialups file contains the names of ports which may be dialup + * lines. Each line consists of the last component of the path + * name. The leading "/dev/" string is removed. + * + * $Id: dialup.h,v 1.2 1997/05/01 23:14:39 marekm Exp $ + */ + +#ifndef _DIALUP_H +#define _DIALUP_H + +struct dialup { + char *du_shell; + char *du_passwd; +}; + +extern void setduent P_((void)); +extern void endduent P_((void)); +extern struct dialup *fgetduent P_((FILE *)); +extern struct dialup *getduent P_((void)); +extern struct dialup *getdushell P_((const char *)); +extern int putduent P_((const struct dialup *, FILE *)); +extern int isadialup P_((const char *)); + +#define DIALPWD "/etc/d_passwd" +#define DIALUPS "/etc/dialups" + +#endif diff --git a/lib/encrypt.c b/lib/encrypt.c new file mode 100644 index 00000000..42f04d66 --- /dev/null +++ b/lib/encrypt.c @@ -0,0 +1,123 @@ +/* + * Copyright 1990 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: encrypt.c,v 1.6 1999/03/07 19:14:35 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" + +extern char *crypt(); +extern char *libshadow_md5_crypt P_((const char *, const char *)); + +char * +pw_encrypt(const char *clear, const char *salt) +{ + static char cipher[128]; + char *cp; +#ifdef SW_CRYPT + static int count; +#endif + +#ifdef MD5_CRYPT + /* + * If the salt string from the password file or from crypt_make_salt() + * begins with the magic string, use the new algorithm. + */ + if (strncmp(salt, "$1$", 3) == 0) + return libshadow_md5_crypt(clear, salt); +#endif + +#ifdef SW_CRYPT + /* + * Copy over the salt. It is always the first two + * characters of the string. + */ + + cipher[0] = salt[0]; + cipher[1] = salt[1]; + cipher[2] = '\0'; + + /* + * Loop up to ten times on the cleartext password. + * This is because the input limit for passwords is + * 80 characters. + * + * The initial salt is that provided by the user, or the + * one generated above. The subsequent salts are gotten + * from the first two characters of the previous encrypted + * block of characters. + */ + + for (count = 0;count < 10;count++) { + cp = crypt(clear, salt); + if (!cp) { + perror("crypt"); + exit(1); + } + if (strlen(cp) != 13) + return cp; + strcat(cipher, cp + 2); + salt = cipher + 11 * count + 2; + + if (strlen(clear) > 8) + clear += 8; + else + break; + } +#else + cp = crypt(clear, salt); + if (!cp) { + /* + * Single Unix Spec: crypt() may return a null pointer, + * and set errno to indicate an error. The caller doesn't + * expect us to return NULL, so... + */ + perror("crypt"); + exit(1); + } + if (strlen(cp) != 13) + return cp; /* nonstandard crypt() in libc, better bail out */ + strcpy(cipher, cp); + +#ifdef DOUBLESIZE + if (strlen (clear) > 8) { + cp = crypt(clear + 8, salt); + if (!cp) { + perror("crypt"); + exit(1); + } + strcat(cipher, cp + 2); + } +#endif /* DOUBLESIZE */ +#endif /* SW_CRYPT */ + return cipher; +} diff --git a/lib/faillog.h b/lib/faillog.h new file mode 100644 index 00000000..028012c8 --- /dev/null +++ b/lib/faillog.h @@ -0,0 +1,55 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * faillog.h - login failure logging file format + * + * $Id: faillog.h,v 1.3 1997/05/01 23:14:39 marekm Exp $ + * + * The login failure file is maintained by login(1) and faillog(8) + * Each record in the file represents a separate UID and the file + * is indexed in that fashion. + */ + +#ifndef _FAILLOG_H +#define _FAILLOG_H + +struct faillog { + short fail_cnt; /* failures since last success */ + short fail_max; /* failures before turning account off */ + char fail_line[12]; /* last failure occured here */ + time_t fail_time; /* last failure occured then */ + /* + * If nonzero, the account will be re-enabled if there are no + * failures for fail_locktime seconds since last failure. + */ + long fail_locktime; +}; + +#endif diff --git a/lib/fputsx.c b/lib/fputsx.c new file mode 100644 index 00000000..17846110 --- /dev/null +++ b/lib/fputsx.c @@ -0,0 +1,80 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include "defines.h" + +#include "rcsid.h" +RCSID("$Id: fputsx.c,v 1.5 1999/06/07 16:40:44 marekm Exp $") + +char * +fgetsx(char *buf, int cnt, FILE *f) +{ + char *cp = buf; + char *ep; + + while (cnt > 0) { + if (fgets (cp, cnt, f) == 0) { + if (cp == buf) + return 0; + else + break; + } + if ((ep = strrchr (cp, '\\')) && *(ep + 1) == '\n') { + if ((cnt -= ep - cp) > 0) + *(cp = ep) = '\0'; + } else + break; + } + return buf; +} + +int +fputsx(const char *s, FILE *stream) +{ + int i; + + for (i = 0;*s;i++, s++) { + if (putc (*s, stream) == EOF) + return EOF; + +#if 0 /* The standard getgr*() can't handle that. --marekm */ + if (i > (BUFSIZ/2)) { + if (putc ('\\', stream) == EOF || + putc ('\n', stream) == EOF) + return EOF; + + i = 0; + } +#endif + } + return 0; +} diff --git a/lib/getdef.c b/lib/getdef.c new file mode 100644 index 00000000..ba979387 --- /dev/null +++ b/lib/getdef.c @@ -0,0 +1,400 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh and Chip Rosenthal + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: getdef.c,v 1.12 1999/03/07 19:14:36 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include +#include +#include "getdef.h" + +/* + * A configuration item definition. + */ + +struct itemdef { + const char *name; /* name of the item */ + char *value; /* value given, or NULL if no value */ +}; + +/* + * This list *must* be sorted by the "name" member. + */ + +#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0])) +static struct itemdef def_table[] = { + { "CHFN_AUTH", NULL }, + { "CHFN_RESTRICT", NULL }, + { "CONSOLE", NULL }, + { "CONSOLE_GROUPS", NULL }, + { "CRACKLIB_DICTPATH", NULL }, + { "CREATE_HOME", NULL }, + { "DEFAULT_HOME", NULL }, + { "DIALUPS_CHECK_ENAB", NULL }, + { "ENVIRON_FILE", NULL }, + { "ENV_HZ", NULL }, + { "ENV_PATH" , NULL }, + { "ENV_SUPATH", NULL }, + { "ENV_TZ", NULL }, + { "ERASECHAR", NULL }, + { "FAILLOG_ENAB", NULL }, + { "FAIL_DELAY", NULL }, + { "FAKE_SHELL", NULL }, + { "FTMP_FILE", NULL }, + { "GID_MAX", NULL }, + { "GID_MIN", NULL }, + { "HUSHLOGIN_FILE", NULL }, + { "ISSUE_FILE", NULL }, + { "KILLCHAR", NULL }, + { "LASTLOG_ENAB", NULL }, + { "LOGIN_RETRIES", NULL }, + { "LOGIN_STRING", NULL }, + { "LOGIN_TIMEOUT", NULL }, + { "LOG_OK_LOGINS", NULL }, + { "LOG_UNKFAIL_ENAB", NULL }, + { "MAIL_CHECK_ENAB", NULL }, + { "MAIL_DIR", NULL }, + { "MAIL_FILE", NULL }, + { "MD5_CRYPT_ENAB", NULL }, + { "MOTD_FILE", NULL }, + { "NOLOGINS_FILE", NULL }, + { "NOLOGIN_STR", NULL }, + { "NO_PASSWORD_CONSOLE", NULL }, + { "OBSCURE_CHECKS_ENAB", NULL }, + { "PASS_ALWAYS_WARN", NULL }, + { "PASS_CHANGE_TRIES", NULL }, + { "PASS_MAX_DAYS", NULL }, + { "PASS_MAX_LEN", NULL }, + { "PASS_MIN_DAYS", NULL }, + { "PASS_MIN_LEN", NULL }, + { "PASS_WARN_AGE", NULL }, + { "PORTTIME_CHECKS_ENAB", NULL }, + { "QMAIL_DIR", NULL }, + { "QUOTAS_ENAB", NULL }, + { "SULOG_FILE", NULL }, + { "SU_NAME", NULL }, + { "SU_WHEEL_ONLY", NULL }, +#ifdef USE_SYSLOG + { "SYSLOG_SG_ENAB", NULL }, + { "SYSLOG_SU_ENAB", NULL }, +#endif + { "TTYGROUP", NULL }, + { "TTYPERM", NULL }, + { "TTYTYPE_FILE", NULL }, + { "UID_MAX", NULL }, + { "UID_MIN", NULL }, + { "ULIMIT", NULL }, + { "UMASK", NULL }, + { "USERDEL_CMD", NULL }, +}; + +#ifndef LOGINDEFS +#define LOGINDEFS "/etc/login.defs" +#endif + +static char def_fname[] = LOGINDEFS; /* login config defs file */ +static int def_loaded = 0; /* are defs already loaded? */ + +extern long strtol(); + +/* local function prototypes */ +static struct itemdef *def_find P_((const char *)); +static void def_load P_((void)); + + +/* + * getdef_str - get string value from table of definitions. + * + * Return point to static data for specified item, or NULL if item is not + * defined. First time invoked, will load definitions from the file. + */ + +char * +getdef_str(const char *item) +{ + struct itemdef *d; + + if (!def_loaded) + def_load(); + + return ((d = def_find(item)) == NULL ? (char *)NULL : d->value); +} + + +/* + * getdef_bool - get boolean value from table of definitions. + * + * Return TRUE if specified item is defined as "yes", else FALSE. + */ + +int +getdef_bool(const char *item) +{ + struct itemdef *d; + + if (!def_loaded) + def_load(); + + if ((d = def_find(item)) == NULL || d->value == NULL) + return 0; + + return (strcasecmp(d->value, "yes") == 0); +} + + +/* + * getdef_num - get numerical value from table of definitions + * + * Returns numeric value of specified item, else the "dflt" value if + * the item is not defined. Octal (leading "0") and hex (leading "0x") + * values are handled. + */ + +int +getdef_num(const char *item, int dflt) +{ + struct itemdef *d; + + if (!def_loaded) + def_load(); + + if ((d = def_find(item)) == NULL || d->value == NULL) + return dflt; + + return (int) strtol(d->value, (char **)NULL, 0); +} + + +/* + * getdef_long - get long integer value from table of definitions + * + * Returns numeric value of specified item, else the "dflt" value if + * the item is not defined. Octal (leading "0") and hex (leading "0x") + * values are handled. + */ + +long +getdef_long(const char *item, long dflt) +{ + struct itemdef *d; + + if (!def_loaded) + def_load(); + + if ((d = def_find(item)) == NULL || d->value == NULL) + return dflt; + + return strtol(d->value, (char **)NULL, 0); +} + + +/* + * putdef_str - override the value read from /etc/login.defs + * (also used when loading the initial defaults) + */ + +int +putdef_str(const char *name, const char *value) +{ + struct itemdef *d; + char *cp; + + if (!def_loaded) + def_load(); + + /* + * Locate the slot to save the value. If this parameter + * is unknown then "def_find" will print an err message. + */ + if ((d = def_find(name)) == NULL) + return -1; + + /* + * Save off the value. + */ + if ((cp = strdup(value)) == NULL) { + fprintf(stderr, + _("Could not allocate space for config info.\n")); + SYSLOG((LOG_ERR, + "could not allocate space for config info")); + return -1; + } + + if (d->value) + free(d->value); + + d->value = cp; + return 0; +} + + +/* + * def_find - locate named item in table + * + * Search through a sorted table of configurable items to locate the + * specified configuration option. + */ + +static struct itemdef * +def_find(const char *name) +{ + int min, max, curr, n; + + /* + * Invariant - desired item in range [min:max]. + */ + + min = 0; + max = NUMDEFS-1; + + /* + * Binary search into the table. Relies on the items being + * sorted by name. + */ + + while (min <= max) { + curr = (min+max)/2; + + if (! (n = strcmp(def_table[curr].name, name))) + return &def_table[curr]; + + if (n < 0) + min = curr+1; + else + max = curr-1; + } + + /* + * Item was never found. + */ + + fprintf(stderr, _("configuration error - unknown item '%s' (notify administrator)\n"), name); + SYSLOG((LOG_CRIT, "unknown configuration item `%s'", name)); + return (struct itemdef *) NULL; +} + +/* + * def_load - load configuration table + * + * Loads the user-configured options from the default configuration file + */ + +static void +def_load(void) +{ + int i; + FILE *fp; + char buf[1024], *name, *value, *s; + + /* + * Open the configuration definitions file. + */ + if ((fp = fopen(def_fname, "r")) == NULL) { + SYSLOG((LOG_CRIT, "cannot open login definitions %s [%m]", + def_fname)); + return; + } + + /* + * Set the initialized flag. + * (do it early to prevent recursion in putdef_str()) + */ + ++def_loaded; + + /* + * Go through all of the lines in the file. + */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + + /* + * Trim trailing whitespace. + */ + for (i = strlen(buf)-1 ; i >= 0 ; --i) { + if (!isspace(buf[i])) + break; + } + buf[++i] = '\0'; + + /* + * Break the line into two fields. + */ + name = buf + strspn(buf, " \t"); /* first nonwhite */ + if (*name == '\0' || *name == '#') + continue; /* comment or empty */ + + s = name + strcspn(name, " \t"); /* end of field */ + if (*s == '\0') + continue; /* only 1 field?? */ + + *s++ = '\0'; + value = s + strspn(s, " \"\t"); /* next nonwhite */ + *(value + strcspn(value, "\"")) = '\0'; + + /* + * Store the value in def_table. + */ + putdef_str(name, value); + } + (void) fclose(fp); +} + + +#ifdef CKDEFS +int +main(int argc, char **argv) +{ + int i; + char *cp; + struct itemdef *d; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + def_load (); + + for (i = 0 ; i < NUMDEFS ; ++i) { + if ((d = def_find(def_table[i].name)) == NULL) + printf(_("error - lookup '%s' failed\n"), def_table[i].name); + else + printf("%4d %-24s %s\n", i+1, d->name, d->value); + } + for (i = 1;i < argc;i++) { + if ((cp = getdef_str (argv[1])) != NULL) + printf ("%s `%s'\n", argv[1], cp); + else + printf (_("%s not found\n"), argv[1]); + } + exit(0); +} +#endif diff --git a/lib/getdef.h b/lib/getdef.h new file mode 100644 index 00000000..3b14d5ae --- /dev/null +++ b/lib/getdef.h @@ -0,0 +1,11 @@ +#ifndef _GETDEF_H +#define _GETDEF_H + +/* getdef.c */ +extern int getdef_bool P_((const char *)); +extern long getdef_long P_((const char *, long)); +extern int getdef_num P_((const char *, int)); +extern char *getdef_str P_((const char *)); +extern int putdef_str P_((const char *, const char *)); + +#endif /* _GETDEF_H */ diff --git a/lib/getpass.c b/lib/getpass.c new file mode 100644 index 00000000..615462ff --- /dev/null +++ b/lib/getpass.c @@ -0,0 +1,268 @@ +/* + * Copyright 1990 - 1995, Julianne Frances Haugh + * Copyright 1998, Pavel Machek + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: getpass.c,v 1.9 1999/06/07 16:40:44 marekm Exp $") + +#include "defines.h" + +#include +#include + +/* new code, #undef if there are any problems... */ +#define USE_SETJMP 1 + +#ifdef USE_SETJMP +#include + +static sigjmp_buf intr; /* where to jump on SIGINT */ +#endif + +static int sig_caught; +#ifdef HAVE_SIGACTION +static struct sigaction sigact; +#endif + +/*ARGSUSED*/ +static RETSIGTYPE +sig_catch(int sig) +{ + sig_caught = 1; +#ifdef USE_SETJMP + siglongjmp(intr, 1); +#endif +} + +#define MAXLEN 127 + +#ifndef NEW_READPASS /* ./configure --enable-readpass */ +#define OLD_READPASS 1 +#endif + +#ifndef OLD_READPASS +static char * +readpass(FILE *fp) +{ + static char input[MAXLEN + 1], asterix[MAXLEN + 1]; + static char once; + char *cp, *ap, c; + int i; + + if (!once) { + srandom(time(0)*getpid()); + once = 1; + } + cp = input; + ap = asterix; + while (read(fileno(fp), &c, 1)) { + switch (c) { + case '\n': + case '\r': + goto endwhile; + case '\b': + case 127: + if (cp > input) { + cp--; ap--; + for (i = 0; i < (*ap); i++) { + putc('\b', stdout); + putc(' ', stdout); + putc('\b', stdout); + } + } else + putc('\a', stdout); /* BEL */ + break; + default: + *cp++ = c; + *ap++ = (random() % 4)+1; + for (i = 0; i < (*(ap-1)); i++) + putc('*', stdout); + break; + } + fflush(stdout); + if (cp == input + MAXLEN) + break; + } +endwhile: + *cp = 0; + putc('\n', stdout); + return input; +} +#else +static char * +readpass(FILE *fp) +{ + static char input[MAXLEN + 1]; + char *cp; + + if (fgets(input, sizeof input, fp) == input) { + if ((cp = strrchr(input, '\n'))) + *cp = '\0'; + else + input[sizeof input - 1] = '\0'; +#ifdef USE_SGTTY + putc('\n', stdout); +#endif + return input; + } + return NULL; +} +#endif + +char * +libshadow_getpass(const char *prompt) +{ + static char nostring[1] = ""; + static char *return_value; + volatile int tty_opened; + static FILE *fp; + volatile int is_tty; +#ifdef HAVE_SIGACTION + struct sigaction old_sigact; +#else + RETSIGTYPE (*old_signal)(); +#endif + TERMIO new_modes; + TERMIO old_modes; + + /* + * set a flag so the SIGINT signal can be re-sent if it + * is caught + */ + + sig_caught = 0; + return_value = NULL; + tty_opened = 0; + + /* + * if /dev/tty can't be opened, getpass() needs to read + * from stdin instead. + */ + + if ((fp = fopen ("/dev/tty", "r")) == 0) { + fp = stdin; + setbuf (fp, (char *) 0); + } else { + tty_opened = 1; + } + + /* + * the current tty modes must be saved so they can be + * restored later on. echo will be turned off, except + * for the newline character (BSD has to punt on this) + */ + + is_tty = 1; + if (GTTY(fileno(fp), &old_modes)) { + is_tty = 0; +#if 0 /* to make getpass work with redirected stdin */ + return_value = NULL; + goto out2; +#endif + } + +#ifdef USE_SETJMP + /* + * If we get a SIGINT, sig_catch() will jump here - + * no need to press Enter after Ctrl-C. + */ + if (sigsetjmp(intr, 1)) + goto out; +#endif + +#ifdef HAVE_SIGACTION + sigact.sa_handler = sig_catch; + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigaction(SIGINT, &sigact, &old_sigact); +#else + old_signal = signal (SIGINT, sig_catch); +#endif + + new_modes = old_modes; + +#ifdef USE_SGTTY + new_modes.sg_flags &= ~ECHO ; +#else +#ifdef OLD_READPASS + new_modes.c_lflag &= ~(ECHO|ECHOE|ECHOK); +#else + new_modes.c_lflag &= ~(ECHO|ECHOE|ECHOK|ICANON); +#endif + new_modes.c_lflag |= ECHONL; +#endif + + if (is_tty) { + if (STTY(fileno(fp), &new_modes)) + goto out; + } + + /* + * the prompt is output, and the response read without + * echoing. the trailing newline must be removed. if + * the fgets() returns an error, a NULL pointer is + * returned. + */ + + if ((fputs(prompt, stdout) != EOF) && (fflush(stdout) != EOF)) + return_value = readpass(fp); +out: + /* + * the old SIGINT handler is restored after the tty + * modes. then /dev/tty is closed if it was opened in + * the beginning. finally, if a signal was caught it + * is sent to this process for normal processing. + */ + + if (is_tty) { + if (STTY(fileno(fp), &old_modes)) + return_value = NULL; + } + +#ifdef HAVE_SIGACTION + (void) sigaction (SIGINT, &old_sigact, NULL); +#else + (void) signal (SIGINT, old_signal); +#endif +out2: + if (tty_opened) + (void) fclose (fp); + + if (sig_caught) { + kill(getpid(), SIGINT); + return_value = NULL; + } + if (!return_value) { + nostring[0] = '\0'; + return_value = nostring; + } + return return_value; +} diff --git a/lib/grdbm.c b/lib/grdbm.c new file mode 100644 index 00000000..b08c0f58 --- /dev/null +++ b/lib/grdbm.c @@ -0,0 +1,211 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifdef NDBM + +#include "rcsid.h" +RCSID("$Id: grdbm.c,v 1.3 1997/12/07 23:26:52 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" + +#include +extern DBM *gr_dbm; + +#define GRP_FRAG 256 + +/* + * gr_dbm_update + * + * Updates the DBM password files, if they exist. + */ + +int +gr_dbm_update(const struct group *gr) +{ + datum key; + datum content; + char data[BUFSIZ*8]; + char grpkey[60]; + char *cp; + int len; + int i; + int cnt; + static int once; + + if (! once) { + if (! gr_dbm) + setgrent (); + + once++; + } + if (! gr_dbm) + return 0; + + len = gr_pack (gr, data); + + if (len <= GRP_FRAG) { + content.dsize = len; + content.dptr = data; + + key.dsize = strlen (gr->gr_name); + key.dptr = gr->gr_name; + if (dbm_store (gr_dbm, key, content, DBM_REPLACE)) + return 0; + + key.dsize = sizeof gr->gr_gid; + key.dptr = (char *) &gr->gr_gid; + if (dbm_store (gr_dbm, key, content, DBM_REPLACE)) + return 0; + + } else { + content.dsize = sizeof cnt; + content.dptr = (char *) &cnt; + cnt = (len + (GRP_FRAG-1)) / GRP_FRAG; + + key.dsize = strlen (gr->gr_name); + key.dptr = gr->gr_name; + if (dbm_store (gr_dbm, key, content, DBM_REPLACE)) + return 0; + + key.dsize = sizeof gr->gr_gid; + key.dptr = (char *) &gr->gr_gid; + if (dbm_store (gr_dbm, key, content, DBM_REPLACE)) + return 0; + + for (cp = data, i = 0;i < cnt;i++) { + content.dsize = len > GRP_FRAG ? GRP_FRAG:len; + len -= content.dsize; + content.dptr = cp; + cp += content.dsize; + + key.dsize = sizeof i + strlen (gr->gr_name); + key.dptr = grpkey; + memcpy (grpkey, (char *) &i, sizeof i); + strcpy (grpkey + sizeof i, gr->gr_name); + if (dbm_store (gr_dbm, key, content, DBM_REPLACE)) + return 0; + + key.dsize = sizeof i + sizeof gr->gr_gid; + key.dptr = grpkey; + memcpy (grpkey, (char *) &i, sizeof i); + memcpy (grpkey + sizeof i, (char *) &gr->gr_gid, + sizeof gr->gr_gid); + if (dbm_store (gr_dbm, key, content, DBM_REPLACE)) + return 0; + } + } + return 1; +} + +/* + * gr_dbm_remove + * + * Deletes the DBM group file entries, if they exist. + */ + +int +gr_dbm_remove(const struct group *gr) +{ + datum key; + datum content; + char grpkey[60]; + int i; + int cnt; + int errors = 0; + static int once; + + if (! once) { + if (! gr_dbm) + setgrent (); + + once++; + } + if (! gr_dbm) + return 0; + + key.dsize = strlen (gr->gr_name); + key.dptr = (char *) gr->gr_name; + content = dbm_fetch (gr_dbm, key); + if (content.dptr == 0) + ++errors; + else { + if (content.dsize == sizeof (int)) { + memcpy ((char *) &cnt, content.dptr, sizeof cnt); + + for (i = 0;i < cnt;i++) { + key.dsize = sizeof i + strlen (gr->gr_name); + key.dptr = grpkey; + memcpy (grpkey, (char *) &i, sizeof i); + strcpy (grpkey + sizeof i, gr->gr_name); + if (dbm_delete (gr_dbm, key)) + ++errors; + } + } else { + if (dbm_delete (gr_dbm, key)) + ++errors; + } + } + key.dsize = sizeof gr->gr_gid; + key.dptr = (char *) &gr->gr_gid; + content = dbm_fetch (gr_dbm, key); + if (content.dptr == 0) + ++errors; + else { + if (content.dsize == sizeof (int)) { + memcpy ((char *) &cnt, content.dptr, sizeof cnt); + + for (i = 0;i < cnt;i++) { + key.dsize = sizeof i + sizeof gr->gr_gid; + key.dptr = grpkey; + memcpy (grpkey, (char *) &i, sizeof i); + memcpy (grpkey + sizeof i, (char *) &gr->gr_gid, + sizeof gr->gr_gid); + + if (dbm_delete (gr_dbm, key)) + ++errors; + } + } else { + if (dbm_delete (gr_dbm, key)) + ++errors; + } + } + return errors ? 0:1; +} + +int +gr_dbm_present(void) +{ + return (access(GROUP_PAG_FILE, F_OK) == 0); +} +#endif diff --git a/lib/groupio.c b/lib/groupio.c new file mode 100644 index 00000000..5e67f996 --- /dev/null +++ b/lib/groupio.c @@ -0,0 +1,185 @@ + +#include + +#include "rcsid.h" +RCSID("$Id: groupio.c,v 1.7 1998/01/29 23:22:28 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" + +#include "commonio.h" +#include "groupio.h" + +extern int putgrent P_((const struct group *, FILE *)); +extern struct group *sgetgrent P_((const char *)); + +struct group * +__gr_dup(const struct group *grent) +{ + struct group *gr; + int i; + + if (!(gr = (struct group *) malloc(sizeof *gr))) + return NULL; + *gr = *grent; + if (!(gr->gr_name = strdup(grent->gr_name))) + return NULL; + if (!(gr->gr_passwd = strdup(grent->gr_passwd))) + return NULL; + + for (i = 0; grent->gr_mem[i]; i++) + ; + gr->gr_mem = (char **) malloc((i + 1) * sizeof(char *)); + if (!gr->gr_mem) + return NULL; + for (i = 0; grent->gr_mem[i]; i++) { + gr->gr_mem[i] = strdup(grent->gr_mem[i]); + if (!gr->gr_mem[i]) + return NULL; + } + gr->gr_mem[i] = NULL; + return gr; +} + +static void * +group_dup(const void *ent) +{ + const struct group *gr = ent; + return __gr_dup(gr); +} + +static void +group_free(void *ent) +{ + struct group *gr = ent; + + free(gr->gr_name); + free(gr->gr_passwd); + while(*(gr->gr_mem)) { + free(*(gr->gr_mem)); + gr->gr_mem++; + } + free(gr); +} + +static const char * +group_getname(const void *ent) +{ + const struct group *gr = ent; + return gr->gr_name; +} + +static void * +group_parse(const char *line) +{ + return (void *) sgetgrent(line); +} + +static int +group_put(const void *ent, FILE *file) +{ + const struct group *gr = ent; + return (putgrent(gr, file) == -1) ? -1 : 0; +} + +static struct commonio_ops group_ops = { + group_dup, + group_free, + group_getname, + group_parse, + group_put, + fgetsx, + fputsx +}; + +static struct commonio_db group_db = { + GROUP_FILE, /* filename */ + &group_ops, /* ops */ + NULL, /* fp */ + NULL, /* head */ + NULL, /* tail */ + NULL, /* cursor */ + 0, /* changed */ + 0, /* isopen */ + 0, /* locked */ + 0, /* readonly */ + 0 /* use_lckpwdf */ +}; + +int +gr_name(const char *filename) +{ + return commonio_setname(&group_db, filename); +} + +int +gr_lock(void) +{ + return commonio_lock(&group_db); +} + +int +gr_open(int mode) +{ + return commonio_open(&group_db, mode); +} + +const struct group * +gr_locate(const char *name) +{ + return commonio_locate(&group_db, name); +} + +int +gr_update(const struct group *gr) +{ + return commonio_update(&group_db, (const void *) gr); +} + +int +gr_remove(const char *name) +{ + return commonio_remove(&group_db, name); +} + +int +gr_rewind(void) +{ + return commonio_rewind(&group_db); +} + +const struct group * +gr_next(void) +{ + return commonio_next(&group_db); +} + +int +gr_close(void) +{ + return commonio_close(&group_db); +} + +int +gr_unlock(void) +{ + return commonio_unlock(&group_db); +} + +void +__gr_set_changed(void) +{ + group_db.changed = 1; +} + +struct commonio_entry * +__gr_get_head(void) +{ + return group_db.head; +} + +void +__gr_del_entry(const struct commonio_entry *ent) +{ + commonio_del_entry(&group_db, ent); +} diff --git a/lib/groupio.h b/lib/groupio.h new file mode 100644 index 00000000..37792fbb --- /dev/null +++ b/lib/groupio.h @@ -0,0 +1,12 @@ +extern struct group *__gr_dup P_((const struct group *)); +extern void __gr_set_changed P_((void)); +extern int gr_close P_((void)); +extern const struct group *gr_locate P_((const char *)); +extern int gr_lock P_((void)); +extern int gr_name P_((const char *)); +extern const struct group *gr_next P_((void)); +extern int gr_open P_((int)); +extern int gr_remove P_((const char *)); +extern int gr_rewind P_((void)); +extern int gr_unlock P_((void)); +extern int gr_update P_((const struct group *)); diff --git a/lib/grpack.c b/lib/grpack.c new file mode 100644 index 00000000..9f4a1803 --- /dev/null +++ b/lib/grpack.c @@ -0,0 +1,95 @@ +/* + * Copyright 1990, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: grpack.c,v 1.3 1997/12/07 23:26:52 marekm Exp $") + +#include +#include + +#include "defines.h" + +int +gr_pack(const struct group *group, char *buf) +{ + char *cp; + int i; + + cp = buf; + strcpy (cp, group->gr_name); + cp += strlen (cp) + 1; + + strcpy (cp, group->gr_passwd); + cp += strlen (cp) + 1; + + memcpy (cp, (const char *) &group->gr_gid, sizeof group->gr_gid); + cp += sizeof group->gr_gid; + + for (i = 0;group->gr_mem[i];i++) { + strcpy (cp, group->gr_mem[i]); + cp += strlen (cp) + 1; + } + *cp++ = '\0'; + + return cp - buf; +} + +int +gr_unpack(char *buf, int len, struct group *group) +{ + char *org = buf; + int i; + + group->gr_name = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + group->gr_passwd = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + memcpy ((char *) &group->gr_gid, (char *) buf, sizeof group->gr_gid); + buf += sizeof group->gr_gid; + if (buf - org > len) + return -1; + + for (i = 0;*buf && i < 1024;i++) { + group->gr_mem[i] = buf; + buf += strlen (buf) + 1; + + if (buf - org > len) + return -1; + } + group->gr_mem[i] = (char *) 0; + return 0; +} diff --git a/lib/gsdbm.c b/lib/gsdbm.c new file mode 100644 index 00000000..a6da67ae --- /dev/null +++ b/lib/gsdbm.c @@ -0,0 +1,167 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#if defined(NDBM) && defined(SHADOWGRP) /*{*/ + +#include +#include +#include "prototypes.h" + +#include "rcsid.h" +RCSID("$Id: gsdbm.c,v 1.3 1997/12/07 23:26:53 marekm Exp $") + +#include +extern DBM *sg_dbm; + +#define GRP_FRAG 256 + +/* + * sg_dbm_update + * + * Updates the DBM password files, if they exist. + */ + +int +sg_dbm_update(const struct sgrp *sgr) +{ + datum key; + datum content; + char data[BUFSIZ*8]; + char sgrpkey[60]; + char *cp; + int len; + int i; + int cnt; + static int once; + + if (! once) { + if (! sg_dbm) + setsgent (); + + once++; + } + if (! sg_dbm) + return 0; + + len = sgr_pack (sgr, data); + + if (len <= GRP_FRAG) { + content.dsize = len; + content.dptr = data; + + key.dsize = strlen (sgr->sg_name); + key.dptr = sgr->sg_name; + if (dbm_store (sg_dbm, key, content, DBM_REPLACE)) + return 0; + } else { + content.dsize = sizeof cnt; + content.dptr = (char *) &cnt; + cnt = (len + (GRP_FRAG-1)) / GRP_FRAG; + + key.dsize = strlen (sgr->sg_name); + key.dptr = sgr->sg_name; + if (dbm_store (sg_dbm, key, content, DBM_REPLACE)) + return 0; + + for (cp = data, i = 0;i < cnt;i++) { + content.dsize = len > GRP_FRAG ? GRP_FRAG:len; + len -= content.dsize; + content.dptr = cp; + cp += content.dsize; + + key.dsize = sizeof i + strlen (sgr->sg_name); + key.dptr = sgrpkey; + memcpy (sgrpkey, (char *) &i, sizeof i); + strcpy (sgrpkey + sizeof i, sgr->sg_name); + if (dbm_store (sg_dbm, key, content, DBM_REPLACE)) + return 0; + } + } + return 1; +} + +/* + * sg_dbm_remove + * + * Deletes the DBM shadow group file entries, if they exist. + */ + +int +sg_dbm_remove(const char *name) +{ + datum key; + datum content; + char grpkey[60]; + int i; + int cnt; + int errors = 0; + static int once; + + if (! once) { + if (! sg_dbm) + setsgent (); + + once++; + } + if (! sg_dbm) + return 0; + + key.dsize = strlen (name); + key.dptr = name; + content = dbm_fetch (sg_dbm, key); + if (content.dptr == 0) + ++errors; + else { + if (content.dsize == sizeof (int)) { + memcpy ((char *) &cnt, content.dptr, sizeof cnt); + + for (i = 0;i < cnt;i++) { + key.dsize = sizeof i + strlen (name); + key.dptr = grpkey; + memcpy (grpkey, (char *) &i, sizeof i); + strcpy (grpkey + sizeof i, name); + if (dbm_delete (sg_dbm, key)) + ++errors; + } + } else { + if (dbm_delete (sg_dbm, key)) + ++errors; + } + } + return errors ? 0:1; +} + +int +sg_dbm_present(void) +{ + return (access(SGROUP_PAG_FILE, F_OK) == 0); +} +#endif /*} SHADOWGRP && NDBM */ diff --git a/lib/gshadow.c b/lib/gshadow.c new file mode 100644 index 00000000..8de925b8 --- /dev/null +++ b/lib/gshadow.c @@ -0,0 +1,528 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* Newer versions of Linux libc already have shadow support. */ +#if defined(SHADOWGRP) && !defined(HAVE_SHADOWGRP) /*{*/ + +#include "rcsid.h" +RCSID("$Id: gshadow.c,v 1.6 1998/04/02 21:51:43 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" + +#ifdef NDBM +#include +#include +DBM *sg_dbm; +int sg_dbm_mode = -1; +static int dbmopened; +static int dbmerror; +#endif + +#define MAXMEM 1024 + +static FILE *shadow; +static char sgrbuf[BUFSIZ*4]; +static char *members[MAXMEM+1]; +static char *admins[MAXMEM+1]; +static struct sgrp sgroup; + +extern char *fgetsx(); +extern int fputsx(); + +#define FIELDS 4 + +#ifdef USE_NIS +static int nis_used; +static int nis_ignore; +static enum { native, start, middle, native2 } nis_state; +static int nis_bound; +static char *nis_domain; +static char *nis_key; +static int nis_keylen; +static char *nis_val; +static int nis_vallen; +#define IS_NISCHAR(c) ((c)=='+') +#endif + +#ifdef USE_NIS + +/* + * __setsgNIS - turn on or off NIS searches + */ + +void +__setsgNIS(int flag) +{ + nis_ignore = ! flag; + + if (nis_ignore) + nis_used = 0; +} + +/* + * bind_nis - bind to NIS server + */ + +static int +bind_nis(void) +{ + if (yp_get_default_domain (&nis_domain)) + return -1; + + nis_bound = 1; + return 0; +} +#endif + +static char ** +list(char *s, char **l) +{ + int nmembers = 0; + + while (s && *s) { + l[nmembers++] = s; + if ((s = strchr (s, ','))) + *s++ = '\0'; + } + l[nmembers] = (char *) 0; + return l; +} + +void +setsgent(void) +{ +#ifdef NDBM + int mode; +#endif /* NDBM */ + +#ifdef USE_NIS + nis_state = native; +#endif + if (shadow) + rewind (shadow); + else + shadow = fopen(SGROUP_FILE, "r"); + + /* + * Attempt to open the DBM files if they have never been opened + * and an error has never been returned. + */ + +#ifdef NDBM + if (! dbmerror && ! dbmopened) { + char dbmfiles[BUFSIZ]; + + strcpy (dbmfiles, SGROUP_PAG_FILE); + + if (sg_dbm_mode == -1) + mode = O_RDWR; + else + mode = (sg_dbm_mode == O_RDWR) ? O_RDWR:O_RDONLY; + + if (access(dbmfiles, F_OK) || + (! (sg_dbm = dbm_open(SGROUP_FILE, mode, 0)))) + dbmerror = 1; + else + dbmopened = 1; + } +#endif /* NDBM */ +} + +void +endsgent(void) +{ + if (shadow) + (void) fclose (shadow); + + shadow = (FILE *) 0; +#ifdef NDBM + if (dbmopened && sg_dbm) { + dbm_close (sg_dbm); + dbmopened = 0; + sg_dbm = 0; + } +#endif +} + +struct sgrp * +sgetsgent(const char *string) +{ + char *fields[FIELDS]; + char *cp; + int i; + + strncpy (sgrbuf, string, (int) sizeof sgrbuf - 1); + sgrbuf[sizeof sgrbuf - 1] = '\0'; + + if ((cp = strrchr (sgrbuf, '\n'))) + *cp = '\0'; + + /* + * There should be exactly 4 colon separated fields. Find + * all 4 of them and save the starting addresses in fields[]. + */ + + for (cp = sgrbuf, i = 0;i < FIELDS && cp;i++) { + fields[i] = cp; + if ((cp = strchr (cp, ':'))) + *cp++ = '\0'; + } + + /* + * If there was an extra field somehow, or perhaps not enough, + * the line is invalid. + */ + + if (cp || i != FIELDS) +#ifdef USE_NIS + if (! IS_NISCHAR (fields[0][0])) + return 0; + else + nis_used = 1; +#else + return 0; +#endif + + sgroup.sg_name = fields[0]; + sgroup.sg_passwd = fields[1]; + sgroup.sg_adm = list (fields[2], admins); + sgroup.sg_mem = list (fields[3], members); + + return &sgroup; +} + +/* + * fgetsgent - convert next line in stream to (struct sgrp) + * + * fgetsgent() reads the next line from the provided stream and + * converts it to a (struct sgrp). NULL is returned on EOF. + */ + +struct sgrp * +fgetsgent(FILE *fp) +{ + char buf[sizeof sgrbuf]; + char *cp; + + if (! fp) + return (0); + +#ifdef USE_NIS + while (fgetsx (buf, sizeof buf, fp) != (char *) 0) +#else + if (fgetsx (buf, sizeof buf, fp) != (char *) 0) +#endif + { + if ((cp = strchr (buf, '\n'))) + *cp = '\0'; +#ifdef USE_NIS + if (nis_ignore && IS_NISCHAR (buf[0])) + continue; +#endif + return (sgetsgent (buf)); + } + return 0; +} + +/* + * getsgent - get a single shadow group entry + */ + +struct sgrp * +getsgent(void) +{ +#ifdef USE_NIS + int nis_1_group = 0; + struct sgrp *val; + char buf[BUFSIZ]; +#endif + if (! shadow) + setsgent (); + +#ifdef USE_NIS +again: + /* + * See if we are reading from the local file. + */ + + if (nis_state == native || nis_state == native2) { + + /* + * Get the next entry from the shadow group file. Return + * NULL right away if there is none. + */ + + if (! (val = fgetsgent (shadow))) + return 0; + + /* + * If this entry began with a NIS escape character, we have + * to see if this is just a single group, or if the entire + * map is being asked for. + */ + + if (IS_NISCHAR (val->sg_name[0])) { + if (val->sg_name[1]) + nis_1_group = 1; + else + nis_state = start; + } + + /* + * If this isn't a NIS group and this isn't an escape to go + * use a NIS map, it must be a regular local group. + */ + + if (nis_1_group == 0 && nis_state != start) + return val; + + /* + * If this is an escape to use an NIS map, switch over to + * that bunch of code. + */ + + if (nis_state == start) + goto again; + + /* + * NEEDSWORK. Here we substitute pieces-parts of this entry. + */ + + return 0; + } else { + if (nis_bound == 0) { + if (bind_nis ()) { + nis_state = native2; + goto again; + } + } + if (nis_state == start) { + if (yp_first (nis_domain, "gshadow.byname", &nis_key, + &nis_keylen, &nis_val, &nis_vallen)) { + nis_state = native2; + goto again; + } + nis_state = middle; + } else if (nis_state == middle) { + if (yp_next (nis_domain, "gshadow.byname", nis_key, + nis_keylen, &nis_key, &nis_keylen, + &nis_val, &nis_vallen)) { + nis_state = native2; + goto again; + } + } + return sgetsgent (nis_val); + } +#else + return (fgetsgent (shadow)); +#endif +} + +/* + * getsgnam - get a shadow group entry by name + */ + +struct sgrp * +getsgnam(const char *name) +{ + struct sgrp *sgrp; +#ifdef NDBM + datum key; + datum content; +#endif +#ifdef USE_NIS + char buf[BUFSIZ]; + static char save_name[16]; + int nis_disabled = 0; +#endif + + setsgent (); + +#ifdef NDBM + + /* + * If the DBM file are now open, create a key for this group and + * try to fetch the entry from the database. A matching record + * will be unpacked into a static structure and returned to + * the user. + */ + + if (dbmopened) { + key.dsize = strlen (name); + key.dptr = (void *) name; + + content = dbm_fetch (sg_dbm, key); + if (content.dptr != 0) { + memcpy (sgrbuf, content.dptr, content.dsize); + sgroup.sg_mem = members; + sgroup.sg_adm = admins; + sgr_unpack (sgrbuf, content.dsize, &sgroup); + return &sgroup; + } + } +#endif +#ifdef USE_NIS + if (nis_used) { +again: + + /* + * Search the gshadow.byname map for this group. + */ + + if (! nis_bound) + bind_nis (); + + if (nis_bound) { + char *cp; + + if (yp_match (nis_domain, "gshadow.byname", name, + strlen (name), &nis_val, &nis_vallen) == 0) { + if (cp = strchr (nis_val, '\n')) + *cp = '\0'; + + nis_state = middle; + if (sgrp = sgetsgent (nis_val)) { + strcpy (save_name, sgrp->sg_name); + nis_key = save_name; + nis_keylen = strlen (save_name); + } + return sgrp; + } + } + nis_state = native2; + } +#endif +#ifdef USE_NIS + if (nis_used) { + nis_ignore++; + nis_disabled++; + } +#endif + while ((sgrp = getsgent ()) != (struct sgrp *) 0) { + if (strcmp (name, sgrp->sg_name) == 0) + break; + } +#ifdef USE_NIS + nis_ignore--; +#endif + if (sgrp) + return sgrp; + return (0); +} + +/* + * putsgent - output shadow group entry in text form + * + * putsgent() converts the contents of a (struct sgrp) to text and + * writes the result to the given stream. This is the logical + * opposite of fgetsgent. + */ + +int +putsgent(const struct sgrp *sgrp, FILE *fp) +{ + char *buf, *cp; + int i; + size_t size; + + if (! fp || ! sgrp) + return -1; + + /* calculate the required buffer size */ + size = strlen(sgrp->sg_name) + strlen(sgrp->sg_passwd) + 10; + for (i = 0; sgrp->sg_adm && sgrp->sg_adm[i]; i++) + size += strlen(sgrp->sg_adm[i]) + 1; + for (i = 0; sgrp->sg_mem && sgrp->sg_mem[i]; i++) + size += strlen(sgrp->sg_mem[i]) + 1; + + buf = malloc(size); + if (!buf) + return -1; + cp = buf; + + /* + * Copy the group name and passwd. + */ + + strcpy (cp, sgrp->sg_name); + cp += strlen (cp); + *cp++ = ':'; + + strcpy (cp, sgrp->sg_passwd); + cp += strlen (cp); + *cp++ = ':'; + + /* + * Copy the administrators, separating each from the other + * with a ",". + */ + + for (i = 0;sgrp->sg_adm[i];i++) { + if (i > 0) + *cp++ = ','; + + strcpy (cp, sgrp->sg_adm[i]); + cp += strlen (cp); + } + *cp++ = ':'; + + /* + * Now do likewise with the group members. + */ + + for (i = 0;sgrp->sg_mem[i];i++) { + if (i > 0) + *cp++ = ','; + + strcpy (cp, sgrp->sg_mem[i]); + cp += strlen (cp); + } + *cp++ = '\n'; + *cp = '\0'; + + /* + * Output using the function which understands the line + * continuation conventions. + */ + + if (fputsx(buf, fp) == EOF) { + free(buf); + return -1; + } + + free(buf); + return 0; +} +#else +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif /*} SHADOWGRP */ diff --git a/lib/gshadow_.h b/lib/gshadow_.h new file mode 100644 index 00000000..b1cac557 --- /dev/null +++ b/lib/gshadow_.h @@ -0,0 +1,71 @@ +/* + * Copyright 1988 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: gshadow_.h,v 1.2 1997/05/01 23:14:41 marekm Exp $ + */ + +#ifndef _H_GSHADOW +#define _H_GSHADOW + +/* + * Shadow group security file structure + */ + +struct sgrp { + char *sg_name; /* group name */ + char *sg_passwd; /* group password */ + char **sg_adm; /* group administator list */ + char **sg_mem; /* group membership list */ +}; + +/* + * Shadow group security file functions. + */ + +#include /* for FILE */ + +#if __STDC__ +struct sgrp *getsgent (void); +struct sgrp *getsgnam (const char *); +struct sgrp *sgetsgent (const char *); +struct sgrp *fgetsgent (FILE *); +void setsgent (void); +void endsgent (void); +int putsgent (const struct sgrp *, FILE *); +#else +struct sgrp *getsgent (); +struct sgrp *getsgnam (); +struct sgrp *sgetsgent (); +struct sgrp *fgetsgent (); +void setsgent (); +void endsgent (); +int putsgent (); +#endif + +#define GSHADOW "/etc/gshadow" +#endif /* ifndef _H_GSHADOW */ diff --git a/lib/gspack.c b/lib/gspack.c new file mode 100644 index 00000000..fe76060b --- /dev/null +++ b/lib/gspack.c @@ -0,0 +1,150 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifdef SHADOWGRP /*{*/ + +#include "rcsid.h" +RCSID("$Id: gspack.c,v 1.3 1997/12/07 23:26:53 marekm Exp $") + +#include +#include "defines.h" + +/* + * sgr_pack - convert a shadow group structure to a packed + * shadow group record + * + * sgr_pack takes the shadow group structure and packs + * the components in a record. this record will be + * unpacked later by sgr_unpack. + */ + +int +sgr_pack(const struct sgrp *sgrp, char *buf) +{ + char *cp; + int i; + + /* + * The name and password are both easy - append each string + * to the buffer. These are always the first two strings + * in a record. + */ + + cp = buf; + strcpy (cp, sgrp->sg_name); + cp += strlen (cp) + 1; + + strcpy (cp, sgrp->sg_passwd); + cp += strlen (cp) + 1; + + /* + * The arrays of administrators and members are slightly + * harder. Each element is appended as a string, with a + * final '\0' appended to serve as a blank string. The + * number of elements is not known in advance, so the + * entire collection of administrators must be scanned to + * find the start of the members. + */ + + for (i = 0;sgrp->sg_adm[i];i++) { + strcpy (cp, sgrp->sg_adm[i]); + cp += strlen (cp) + 1; + } + *cp++ = '\0'; + + for (i = 0;sgrp->sg_mem[i];i++) { + strcpy (cp, sgrp->sg_mem[i]); + cp += strlen (cp) + 1; + } + *cp++ = '\0'; + + return cp - buf; +} + +/* + * sgr_unpack - convert a packed shadow group record to an + * unpacked record + * + * sgr_unpack converts a record which was packed by sgr_pack + * into the normal shadow group structure format. + */ + +int +sgr_unpack(char *buf, int len, struct sgrp *sgrp) +{ + char *org = buf; + int i; + + /* + * The name and password are both easy - they are the first + * two strings in the record. + */ + + sgrp->sg_name = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + sgrp->sg_passwd = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + /* + * The administrators and members are slightly more difficult. + * The arrays are lists of strings. Each list is terminated + * by a string of length zero. This string is detected by + * looking for an initial character of '\0'. + */ + + for (i = 0;*buf && i < 1024;i++) { + sgrp->sg_adm[i] = buf; + buf += strlen (buf) + 1; + + if (buf - org > len) + return -1; + } + sgrp->sg_adm[i] = (char *) 0; + if (! *buf) + buf++; + + for (i = 0;*buf && i < 1024;i++) { + sgrp->sg_mem[i] = buf; + buf += strlen (buf) + 1; + + if (buf - org > len) + return -1; + } + sgrp->sg_mem[i] = (char *) 0; + + return 0; +} +#endif /*}*/ diff --git a/lib/lastlog_.h b/lib/lastlog_.h new file mode 100644 index 00000000..8d459de6 --- /dev/null +++ b/lib/lastlog_.h @@ -0,0 +1,50 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * lastlog.h - structure of lastlog file + * + * $Id: lastlog_.h,v 1.2 1997/05/01 23:14:42 marekm Exp $ + * + * This file defines a lastlog file structure which should be sufficient + * to hold the information required by login. It should only be used if + * there is no real lastlog.h file. + */ + +#ifndef __LASTLOG_H +#define __LASTLOG_H + +struct lastlog { + time_t ll_time; + char ll_line[12]; + char ll_host[16]; +}; + +#define HAVE_LL_HOST +#endif /* _LASTLOG_H */ diff --git a/lib/lockpw.c b/lib/lockpw.c new file mode 100644 index 00000000..879dc983 --- /dev/null +++ b/lib/lockpw.c @@ -0,0 +1,114 @@ +/* + * Copyright 1992, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef HAVE_LCKPWDF + +#include "rcsid.h" +RCSID("$Id: lockpw.c,v 1.4 1998/01/29 23:22:28 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" + +#include "pwio.h" +#ifdef SHADOWPWD +#include "shadowio.h" +#endif + +/* + * lckpwdf - lock the password files + */ + +int +lckpwdf(void) +{ + int i; + + /* + * We have 15 seconds to lock the whole mess + */ + + for (i = 0;i < 15;i++) + if (pw_lock ()) + break; + else + sleep (1); + + /* + * Did we run out of time? + */ + + if (i == 15) + return -1; + + /* + * Nope, use any remaining time to lock the shadow password + * file. + */ + + for (;i < 15;i++) + if (spw_lock ()) + break; + else + sleep (1); + + /* + * Out of time yet? + */ + + if (i == 15) { + pw_unlock (); + return -1; + } + + /* + * Nope - and both files are now locked. + */ + + return 0; +} + +/* + * ulckpwdf - unlock the password files + */ + +int +ulckpwdf(void) +{ + + /* + * Unlock both files. + */ + + return (pw_unlock () && spw_unlock ()) ? 0:-1; +} +#else +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif diff --git a/lib/md5.c b/lib/md5.c new file mode 100644 index 00000000..766fafe8 --- /dev/null +++ b/lib/md5.c @@ -0,0 +1,261 @@ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ +#include + +#ifdef MD5_CRYPT +#include /* for memcpy() */ +#include "md5.h" + +#ifndef HIGHFIRST +#define byteReverse(buf, len) /* Nothing */ +#else +void byteReverse(unsigned char *buf, unsigned longs); + +#ifndef ASM_MD5 +/* + * Note: this code is harmless on little-endian machines. + */ +void +byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void +MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void +MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +#ifndef ASM_MD5 + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif +#endif /* MD5_CRYPT */ diff --git a/lib/md5.h b/lib/md5.h new file mode 100644 index 00000000..e264f686 --- /dev/null +++ b/lib/md5.h @@ -0,0 +1,27 @@ +#ifndef MD5_H +#define MD5_H + +#ifdef __alpha +typedef unsigned int uint32; +#else +typedef unsigned long uint32; +#endif + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); +void MD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct MD5Context MD5_CTX; + +#endif /* !MD5_H */ diff --git a/lib/md5crypt.c b/lib/md5crypt.c new file mode 100644 index 00000000..e1595aa2 --- /dev/null +++ b/lib/md5crypt.c @@ -0,0 +1,151 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + +/* + * Ported from FreeBSD to Linux, only minimal changes. --marekm + */ + +#include + +#ifdef MD5_CRYPT + +#include "rcsid.h" +RCSID("$Id: md5crypt.c,v 1.3 1998/01/29 23:22:29 marekm Exp $") + +#include +/* #include */ +#include +#include "md5.h" + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void +to64(char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char * +libshadow_md5_crypt(const char *pw, const char *salt) +{ + static char *magic = "$1$"; /* + * This string is magic for + * this algorithm. Having + * it this way, we can get + * get better later on + */ + static char passwd[120], *p; + static const char *sp,*ep; + unsigned char final[16]; + int sl,pl,i,j; + MD5_CTX ctx,ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if(!strncmp(sp,magic,strlen(magic))) + sp += strlen(magic); + + /* It stops at the first '$', max 8 chars */ + for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + MD5Init(&ctx); + + /* The password first, since that is what is most unknown */ + MD5Update(&ctx,pw,strlen(pw)); + + /* Then our magic string */ + MD5Update(&ctx,magic,strlen(magic)); + + /* Then the raw salt */ + MD5Update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1,pw,strlen(pw)); + MD5Update(&ctx1,sp,sl); + MD5Update(&ctx1,pw,strlen(pw)); + MD5Final(final,&ctx1); + for(pl = strlen(pw); pl > 0; pl -= 16) + MD5Update(&ctx,final,pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (j=0,i = strlen(pw); i ; i >>= 1) + if(i&1) + MD5Update(&ctx, final+j, 1); + else + MD5Update(&ctx, pw+j, 1); + + /* Now make the output string */ + strcpy(passwd,magic); + strncat(passwd,sp,sl); + strcat(passwd,"$"); + + MD5Final(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + MD5Init(&ctx1); + if(i & 1) + MD5Update(&ctx1,pw,strlen(pw)); + else + MD5Update(&ctx1,final,16); + + if(i % 3) + MD5Update(&ctx1,sp,sl); + + if(i % 7) + MD5Update(&ctx1,pw,strlen(pw)); + + if(i & 1) + MD5Update(&ctx1,final,16); + else + MD5Update(&ctx1,pw,strlen(pw)); + MD5Final(final,&ctx1); + } + + p = passwd + strlen(passwd); + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; + l = final[11] ; to64(p,l,2); p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; +} +#endif diff --git a/lib/mkdir.c b/lib/mkdir.c new file mode 100644 index 00000000..9e26b22a --- /dev/null +++ b/lib/mkdir.c @@ -0,0 +1,60 @@ +/* + * Copyright 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "rcsid.h" +RCSID("$Id: mkdir.c,v 1.4 1998/01/29 23:22:30 marekm Exp $") + +/* + * mkdir - create a directory + * + * mkdir is provided for systems which do not include the mkdir() + * system call. + */ + +int +mkdir(const char *dir, int mode) +{ + int status; + + if (fork()) { + while (wait(&status) != -1) + ; + + return status >> 8; + } + close(2); + open("/dev/null", O_WRONLY); + umask(0777 & ~ mode); + execl("/bin/mkdir", "mkdir", dir, 0); + _exit(127); + /*NOTREACHED*/ +} diff --git a/lib/pam_defs.h b/lib/pam_defs.h new file mode 100644 index 00000000..58d25c5c --- /dev/null +++ b/lib/pam_defs.h @@ -0,0 +1,21 @@ +#include +#include + +/* compatibility with different versions of Linux-PAM */ +#ifndef PAM_ESTABLISH_CRED +#define PAM_ESTABLISH_CRED PAM_CRED_ESTABLISH +#endif +#ifndef PAM_DELETE_CRED +#define PAM_DELETE_CRED PAM_CRED_DELETE +#endif +#ifndef PAM_NEW_AUTHTOK_REQD +#define PAM_NEW_AUTHTOK_REQD PAM_AUTHTOKEN_REQD +#endif +#ifndef PAM_DATA_SILENT +#define PAM_DATA_SILENT 0 +#endif +#ifdef PAM_STRERROR_NEEDS_TWO_ARGS /* Linux-PAM 0.59+ */ +#define PAM_STRERROR(pamh, err) pam_strerror(pamh, err) +#else +#define PAM_STRERROR(pamh, err) pam_strerror(err) +#endif diff --git a/lib/port.c b/lib/port.c new file mode 100644 index 00000000..6ffb9125 --- /dev/null +++ b/lib/port.c @@ -0,0 +1,439 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: port.c,v 1.3 1997/12/07 23:26:54 marekm Exp $") + +#include +#include +#include +#include "defines.h" +#include "port.h" + +extern int errno; + +static FILE *ports; + +/* + * portcmp - compare the name of a port to a /etc/porttime entry + * + * portcmp works like strcmp, except that if the last character + * in a failing match is a '*', the match is considered to have + * passed. The "*" match is suppressed whenever the port is "SU", + * which is the token the "su" command uses to validate access. + * A match returns 0, failure returns non-zero. + */ + +static int +portcmp(const char *pattern, const char *port) +{ + const char *orig = port; + + while (*pattern && *pattern == *port) + pattern++, port++; + + if (*pattern == 0 && *port == 0) + return 0; + if (orig[0] == 'S' && orig[1] == 'U' && orig[2] == '\0') + return 1; + + return *pattern == '*' ? 0:1; +} + +/* + * setportent - open /etc/porttime file or rewind + * + * the /etc/porttime file is rewound if already open, or + * opened for reading. + */ + +static void +setportent(void) +{ + if (ports) + rewind (ports); + else + ports = fopen (PORTS, "r"); +} + +/* + * endportent - close the /etc/porttime file + * + * the /etc/porttime file is closed and the ports variable set + * to NULL to indicate that the /etc/porttime file is no longer + * open. + */ + +static void +endportent(void) +{ + if (ports) + fclose (ports); + + ports = (FILE *) 0; +} + +/* + * getportent - read a single entry from /etc/porttime + * + * the next line in /etc/porttime is converted to a (struct port) + * and a pointer to a static (struct port) is returned to the + * invoker. NULL is returned on either EOF or error. errno is + * set to EINVAL on error to distinguish the two conditions. + */ + +static struct port * +getportent(void) +{ + static struct port port; /* static struct to point to */ + static char buf[BUFSIZ]; /* some space for stuff */ + static char *ttys[PORT_TTY+1]; /* some pointers to tty names */ + static char *users[PORT_IDS+1]; /* some pointers to user ids */ + static struct pt_time ptimes[PORT_TIMES+1]; /* time ranges */ + char *cp; /* pointer into line */ + int dtime; /* scratch time of day */ + int i, j; + int saveerr = errno; /* errno value on entry */ + + /* + * If the ports file is not open, open the file. Do not rewind + * since we want to search from the beginning each time. + */ + + if (! ports) + setportent (); + + if (! ports) { + errno = saveerr; + return 0; + } + + /* + * Common point for beginning a new line - + * + * - read a line, and NUL terminate + * - skip lines which begin with '#' + * - parse off the tty names + * - parse off a list of user names + * - parse off a list of days and times + */ + +again: + + /* + * Get the next line and remove the last character, which + * is a '\n'. Lines which begin with '#' are all ignored. + */ + + if (fgets (buf, sizeof buf, ports) == 0) { + errno = saveerr; + return 0; + } + if (buf[0] == '#') + goto again; + + /* + * Get the name of the TTY device. It is the first colon + * separated field, and is the name of the TTY with no + * leading "/dev". The entry '*' is used to specify all + * TTY devices. + */ + + buf[strlen (buf) - 1] = 0; + + port.pt_names = ttys; + for (cp = buf, j = 0;j < PORT_TTY;j++) { + port.pt_names[j] = cp; + while (*cp && *cp != ':' && *cp != ',') + cp++; + + if (! *cp) + goto again; /* line format error */ + + if (*cp == ':') /* end of tty name list */ + break; + + if (*cp == ',') /* end of current tty name */ + *cp++ = '\0'; + } + *cp++ = 0; + port.pt_names[j + 1] = (char *) 0; + + /* + * Get the list of user names. It is the second colon + * separated field, and is a comma separated list of user + * names. The entry '*' is used to specify all usernames. + * The last entry in the list is a (char *) 0 pointer. + */ + + if (*cp != ':') { + port.pt_users = users; + port.pt_users[0] = cp; + + for (j = 1;*cp != ':';cp++) { + if (*cp == ',' && j < PORT_IDS) { + *cp++ = 0; + port.pt_users[j++] = cp; + } + } + port.pt_users[j] = 0; + } else + port.pt_users = 0; + + if (*cp != ':') + goto again; + + *cp++ = 0; + + /* + * Get the list of valid times. The times field is the third + * colon separated field and is a list of days of the week and + * times during which this port may be used by this user. The + * valid days are 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', and 'Sa'. + * + * In addition, the value 'Al' represents all 7 days, and 'Wk' + * represents the 5 weekdays. + * + * Times are given as HHMM-HHMM. The ending time may be before + * the starting time. Days are presumed to wrap at 0000. + */ + + if (*cp == '\0') { + port.pt_times = 0; + return &port; + } + + port.pt_times = ptimes; + + /* + * Get the next comma separated entry + */ + + for (j = 0;*cp && j < PORT_TIMES;j++) { + + /* + * Start off with no days of the week + */ + + port.pt_times[j].t_days = 0; + + /* + * Check each two letter sequence to see if it is + * one of the abbreviations for the days of the + * week or the other two values. + */ + + for (i = 0;cp[i] && cp[i + 1] && isalpha (cp[i]);i += 2) { + switch ((cp[i] << 8) | (cp[i + 1])) { + case ('S' << 8) | 'u': + port.pt_times[j].t_days |= 01; + break; + case ('M' << 8) | 'o': + port.pt_times[j].t_days |= 02; + break; + case ('T' << 8) | 'u': + port.pt_times[j].t_days |= 04; + break; + case ('W' << 8) | 'e': + port.pt_times[j].t_days |= 010; + break; + case ('T' << 8) | 'h': + port.pt_times[j].t_days |= 020; + break; + case ('F' << 8) | 'r': + port.pt_times[j].t_days |= 040; + break; + case ('S' << 8) | 'a': + port.pt_times[j].t_days |= 0100; + break; + case ('W' << 8) | 'k': + port.pt_times[j].t_days |= 076; + break; + case ('A' << 8) | 'l': + port.pt_times[j].t_days |= 0177; + break; + default: + errno = EINVAL; + return 0; + } + } + + /* + * The default is 'Al' if no days were seen. + */ + + if (i == 0) + port.pt_times[j].t_days = 0177; + + /* + * The start and end times are separated from each + * other by a '-'. The times are four digit numbers + * representing the times of day. + */ + + for (dtime = 0;cp[i] && isdigit (cp[i]);i++) + dtime = dtime * 10 + cp[i] - '0'; + + if (cp[i] != '-' || dtime > 2400 || dtime % 100 > 59) + goto again; + port.pt_times[j].t_start = dtime; + cp = cp + i + 1; + + for (dtime = i = 0;cp[i] && isdigit (cp[i]);i++) + dtime = dtime * 10 + cp[i] - '0'; + + if ((cp[i] != ',' && cp[i]) || + dtime > 2400 || dtime % 100 > 59) + goto again; + + port.pt_times[j].t_end = dtime; + cp = cp + i + 1; + } + + /* + * The end of the list is indicated by a pair of -1's for the + * start and end times. + */ + + port.pt_times[j].t_start = port.pt_times[j].t_end = -1; + + return &port; +} + +/* + * getttyuser - get ports information for user and tty + * + * getttyuser() searches the ports file for an entry with a TTY + * and user field both of which match the supplied TTY and + * user name. The file is searched from the beginning, so the + * entries are treated as an ordered list. + */ + +static struct port * +getttyuser(const char *tty, const char *user) +{ + int i, j; + struct port *port; + + setportent (); + + while ((port = getportent ())) { + if (port->pt_names == 0 || port->pt_users == 0) + continue; + + for (i = 0;port->pt_names[i];i++) + if (portcmp (port->pt_names[i], tty) == 0) + break; + + if (port->pt_names[i] == 0) + continue; + + for (j = 0;port->pt_users[j];j++) + if (strcmp (user, port->pt_users[j]) == 0 || + strcmp (port->pt_users[j], "*") == 0) + break; + + if (port->pt_users[j] != 0) + break; + } + endportent (); + return port; +} + +/* + * isttytime - tell if a given user may login at a particular time + * + * isttytime searches the ports file for an entry which matches + * the user name and TTY given. + */ + +int +isttytime(const char *id, const char *port, time_t when) +{ + int i; + int dtime; + struct port *pp; + struct tm *tm; + + /* + * Try to find a matching entry for this user. Default to + * letting the user in - there are pleny of ways to have an + * entry to match all users. + */ + + if (! (pp = getttyuser (port, id))) + return 1; + + /* + * The entry is there, but has no time entries - don't + * ever let them login. + */ + + if (pp->pt_times == 0) + return 0; + + /* + * The current time is converted to HHMM format for + * comparision against the time values in the TTY entry. + */ + + tm = localtime (&when); + dtime = tm->tm_hour * 100 + tm->tm_min; + + /* + * Each time entry is compared against the current + * time. For entries with the start after the end time, + * the comparision is made so that the time is between + * midnight and either the start or end time. + */ + + for (i = 0;pp->pt_times[i].t_start != -1;i++) { + if (! (pp->pt_times[i].t_days & PORT_DAY(tm->tm_wday))) + continue; + + if (pp->pt_times[i].t_start <= pp->pt_times[i].t_end) { + if (dtime >= pp->pt_times[i].t_start && + dtime <= pp->pt_times[i].t_end) + return 1; + } else { + if (dtime >= pp->pt_times[i].t_start || + dtime <= pp->pt_times[i].t_end) + return 1; + } + } + + /* + * No matching time entry was found, user shouldn't + * be let in right now. + */ + + return 0; +} diff --git a/lib/port.h b/lib/port.h new file mode 100644 index 00000000..a02d6728 --- /dev/null +++ b/lib/port.h @@ -0,0 +1,81 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * port.h - structure of /etc/porttime + * + * $Id: port.h,v 1.2 1997/05/01 23:14:43 marekm Exp $ + * + * Each entry in /etc/porttime consists of a TTY device + * name or "*" to indicate all TTY devices, followed by + * a list of 1 or more user IDs or "*" to indicate all + * user names, followed by a list of zero or more valid + * login times. Login time entries consist of zero or + * more day names (Su, Mo, Tu, We, Th, Fr, Sa, Wk, Al) + * followed by a pair of time values in HHMM format + * separated by a "-". + */ + +/* + * PORTS - Name of system port access time file. + * PORT_IDS - Allowable number of IDs per entry. + * PORT_TTY - Allowable number of TTYs per entry. + * PORT_TIMES - Allowable number of time entries per entry. + * PORT_DAY - Day of the week to a bit value (0 = Sunday). + */ + +#define PORTS "/etc/porttime" +#define PORT_IDS 64 +#define PORT_TTY 64 +#define PORT_TIMES 24 +#define PORT_DAY(day) (1<<(day)) + +/* + * pt_names - pointer to array of device names in /dev/ + * pt_users - pointer to array of applicable user IDs. + * pt_times - pointer to list of allowable time periods. + */ + +struct port { + char **pt_names; + char **pt_users; + struct pt_time *pt_times; +}; + +/* + * t_days - bit array for each day of the week (0 = Sunday) + * t_start - starting time for this entry + * t_end - ending time for this entry + */ + +struct pt_time { + short t_days; + short t_start; + short t_end; +}; diff --git a/lib/prototypes.h b/lib/prototypes.h new file mode 100644 index 00000000..4fff4f9b --- /dev/null +++ b/lib/prototypes.h @@ -0,0 +1,213 @@ +/* + * prototypes.h + * + * Missing function prototypes + * + * Juha Virtanen, ; November 1995 + */ +/* + * $Id: prototypes.h,v 1.13 1999/07/09 18:02:43 marekm Exp $ + * + * Added a macro to work around ancient (non-ANSI) compilers, just in case + * someone ever tries to compile this with SunOS cc... --marekm + */ + +#ifndef _PROTOTYPES_H +#define _PROTOTYPES_H + +#include +#include +#include +#include + +#include "defines.h" + +/* addgrps.c */ +extern int add_groups P_((const char *)); +extern void add_cons_grps P_((void)); + +/* age.c */ +#ifdef SHADOWPWD +extern void agecheck P_((const struct passwd *pw, const struct spwd *sp)); +extern int expire P_((const struct passwd *pw, const struct spwd *sp)); +extern int isexpired P_((const struct passwd *pw, const struct spwd *sp)); +#else +extern void agecheck P_((const struct passwd *pw)); +extern int expire P_((const struct passwd *pw)); +extern int isexpired P_((const struct passwd *pw)); +#endif + +/* basename() renamed to Basename() to avoid libc name space confusion */ +/* basename.c */ +extern char *Basename P_((char *str)); + +/* chkshell.c */ +extern int check_shell P_((const char *)); + +/* chowndir.c */ +extern int chown_tree P_((const char *, uid_t, uid_t, gid_t, gid_t)); + +/* chowntty.c */ +extern void chown_tty P_((const char *, const struct passwd *)); + +/* console.c */ +extern int console P_((const char *tty)); +extern int is_listed P_((const char *cfgin, const char *tty, int def)); + +/* copydir.c */ +extern int copy_tree P_((const char *, const char *, uid_t, gid_t)); +extern int remove_tree P_((const char *)); + +/* encrypt.c */ +extern char *pw_encrypt P_((const char *, const char *)); + +/* entry.c */ +extern void entry P_((const char *name, struct passwd *pwent)); + +/* env.c */ +extern void addenv P_((const char *, const char *)); +extern void initenv P_((void)); +extern void set_env P_((int, char * const *)); +extern void sanitize_env P_((void)); + +/* fields.c */ +extern void change_field P_((char *buf, size_t maxsize, const char *prompt)); +extern int valid_field P_((const char *field, const char *illegal)); + +/* fputsx.c */ +extern char *fgetsx P_((char *, int, FILE *)); +extern int fputsx P_((const char *, FILE *)); + +/* grdbm.c */ +extern int gr_dbm_remove P_((const struct group *gr)); +extern int gr_dbm_update P_((const struct group *gr)); +extern int gr_dbm_present P_((void)); + +/* grent.c */ +extern int putgrent P_((const struct group *, FILE *)); + +/* grpack.c */ +extern int gr_pack P_((const struct group *group, char *buf)); +extern int gr_unpack P_((char *buf, int len, struct group *group)); + +#ifdef SHADOWGRP +/* gsdbm.c */ +extern int sg_dbm_remove P_((const char *name)); +extern int sg_dbm_update P_((const struct sgrp *sgr)); +extern int sg_dbm_present P_((void)); + +/* gspack.c */ +extern int sgr_pack P_((const struct sgrp *sgrp, char *buf)); +extern int sgr_unpack P_((char *buf, int len, struct sgrp *sgrp)); +#endif + +/* hushed.c */ +extern int hushed P_((const struct passwd *pw)); + +/* limits.c */ +extern void setup_limits P_((const struct passwd *)); + +/* list.c */ +extern char **add_list P_((char **list, const char *member)); +extern char **del_list P_((char **list, const char *member)); +extern char **dup_list P_((char * const *list)); +extern int is_on_list P_((char * const *list, const char *member)); +extern char **comma_to_list P_((const char *comma)); + +/* login.c */ +extern void login_prompt P_((const char *, char *, int)); + +/* login_desrpc.c */ +extern int login_desrpc P_((const char *)); + +/* mail.c */ +extern void mailcheck P_((void)); + +/* motd.c */ +extern void motd P_((void)); + +/* myname.c */ +extern struct passwd *get_my_pwent P_((void)); + +/* obscure.c */ +extern int obscure P_((const char *, const char *, const struct passwd *)); + +/* pam_pass.c */ +extern int do_pam_passwd P_((const char *, int, int)); + +/* port.c */ +extern int isttytime P_((const char *, const char *, time_t)); + +/* pwd2spwd.c */ +#ifdef SHADOWPWD +extern struct spwd *pwd_to_spwd P_((const struct passwd *pw)); +#endif + +/* pwdcheck.c */ +extern void passwd_check P_((const char *, const char *, const char *)); + +/* pwd_init.c */ +extern void pwd_init P_((void)); + +/* pwdbm.c */ +extern int pw_dbm_remove P_((const struct passwd *pw)); +extern int pw_dbm_update P_((const struct passwd *pw)); +extern int pw_dbm_present P_((void)); + +/* pwpack.c */ +extern int pw_pack P_((const struct passwd *passwd, char *buf)); +extern int pw_unpack P_((char *buf, int len, struct passwd *passwd)); + +/* rad64.c */ +extern int c64i P_((char c)); +extern int i64c P_((int i)); + +/* rlogin.c */ +extern int do_rlogin P_((const char *, char *, int, char *, int)); + +/* setugid.c */ +extern int setup_groups P_((const struct passwd *)); +extern int change_uid P_((const struct passwd *)); +extern int setup_uid_gid P_((const struct passwd *, int)); + +/* setup.c */ +extern void setup P_((struct passwd *info)); + +/* setupenv.c */ +extern void setup_env P_((struct passwd *)); + +/* shell.c */ +extern void shell P_((const char *file, const char *arg)); + +#ifdef SHADOWPWD +/* spdbm.c */ +extern int sp_dbm_remove P_((const char *user)); +extern int sp_dbm_update P_((const struct spwd *sp)); +extern int sp_dbm_present P_((void)); + +/* sppack.c */ +extern int spw_pack P_((const struct spwd *spwd, char *buf)); +extern int spw_unpack P_((char *buf, int len, struct spwd *spwd)); +#endif + +/* strtoday.c */ +extern long strtoday P_((const char *str)); + +/* ttytype.c */ +extern void ttytype P_((const char *line)); + +/* ulimit.c */ +extern void set_filesize_limit P_((int)); + +/* utmp.c */ +extern void checkutmp P_((int)); +extern void setutmp P_((const char *, const char *, const char *)); + +/* valid.c */ +extern int valid P_((const char *, const struct passwd *)); + +/* xmalloc.c */ +extern char *xmalloc P_((size_t size)); +extern char *xstrdup P_((const char *str)); + +#endif /* _PROTOTYPES_H */ diff --git a/lib/putgrent.c b/lib/putgrent.c new file mode 100644 index 00000000..6559cd92 --- /dev/null +++ b/lib/putgrent.c @@ -0,0 +1,75 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include "prototypes.h" +#include "defines.h" + +int +putgrent(const struct group *g, FILE *f) +{ + char *buf, *cp; + int i; + size_t size; + + if (!g || !f) + return -1; + + /* calculate the required buffer size (40 is added for the + numeric GID, colons, newline, and terminating NUL). */ + size = strlen(g->gr_name) + strlen(g->gr_passwd) + 40; + for (i = 0; g->gr_mem && g->gr_mem[i]; i++) + size += strlen(g->gr_mem[i]) + 1; + + buf = malloc(size); + if (!buf) + return -1; + + sprintf(buf, "%s:%s:%ld:", g->gr_name, g->gr_passwd, (long) g->gr_gid); + cp = buf + strlen(buf); + for (i = 0; g->gr_mem && g->gr_mem[i]; i++) { + if (i > 0) + *cp++ = ','; + strcpy(cp, g->gr_mem[i]); + cp += strlen(cp); + } + *cp++ = '\n'; + *cp = '\0'; + + if (fputsx(buf, f) == EOF || ferror(f)) { + free(buf); + return -1; + } + + free(buf); + return 0; +} diff --git a/lib/putpwent.c b/lib/putpwent.c new file mode 100644 index 00000000..bdc011c3 --- /dev/null +++ b/lib/putpwent.c @@ -0,0 +1,72 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: putpwent.c,v 1.3 1997/12/07 23:26:54 marekm Exp $") + +#include "defines.h" +#include +#include + +/* + * putpwent - Output a (struct passwd) in character format + * + * putpwent() writes out a (struct passwd) in the format it appears + * in in flat ASCII files. + * + * (Author: Dr. Micheal Newberry) + */ + +int +putpwent(const struct passwd *p, FILE *f) +{ + int status; + +#if defined(SUN) || defined(BSD) || defined(SUN4) + status = fprintf (f, "%s:%s:%d:%d:%s,%s:%s:%s\n", + p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid, + p->pw_gecos, p->pw_comment, p->pw_dir, p->pw_shell) == EOF; +#else + status = fprintf (f, "%s:%s", p->pw_name, p->pw_passwd) == EOF; +#ifdef ATT_AGE + if (p->pw_age && p->pw_age[0]) + status |= fprintf (f, ",%s", p->pw_age) == EOF; +#endif + status |= fprintf (f, ":%d:%d:%s", p->pw_uid, p->pw_gid, + p->pw_gecos) == EOF; +#ifdef ATT_COMMENT + if (p->pw_comment && p->pw_comment[0]) + status |= fprintf (f, ",%s", p->pw_comment) == EOF; +#endif + status |= fprintf (f, ":%s:%s\n", p->pw_dir, p->pw_shell) == EOF; +#endif + return status; +} diff --git a/lib/putspent.c b/lib/putspent.c new file mode 100644 index 00000000..941d76bc --- /dev/null +++ b/lib/putspent.c @@ -0,0 +1,103 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifdef SHADOWPWD /*{*/ +#ifndef HAVE_PUTSPENT + +#include "rcsid.h" +RCSID("$Id: putspent.c,v 1.3 1997/12/07 23:26:54 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include + +int +putspent(const struct spwd *sp, FILE *fp) +{ + int errors = 0; + + if (! fp || ! sp) + return -1; + + if (fprintf (fp, "%s:%s:", sp->sp_namp, sp->sp_pwdp) < 0) + errors++; + + if (sp->sp_lstchg != -1) { + if (fprintf (fp, "%ld:", sp->sp_lstchg) < 0) + errors++; + } else if (putc (':', fp) == EOF) + errors++; + + if (sp->sp_min != -1) { + if (fprintf (fp, "%ld:", sp->sp_min) < 0) + errors++; + } else if (putc (':', fp) == EOF) + errors++; + + if (sp->sp_max != -1) { + if (fprintf (fp, "%ld:", sp->sp_max) < 0) + errors++; + } else if (putc (':', fp) == EOF) + errors++; + + if (sp->sp_warn != -1) { + if (fprintf (fp, "%ld:", sp->sp_warn) < 0) + errors++; + } else if (putc (':', fp) == EOF) + errors++; + + if (sp->sp_inact != -1) { + if (fprintf (fp, "%ld:", sp->sp_inact) < 0) + errors++; + } else if (putc (':', fp) == EOF) + errors++; + + if (sp->sp_expire != -1) { + if (fprintf (fp, "%ld:", sp->sp_expire) < 0) + errors++; + } else if (putc (':', fp) == EOF) + errors++; + + if (sp->sp_flag != -1) { + if (fprintf (fp, "%ld", sp->sp_flag) < 0) + errors++; + } + if (putc ('\n', fp) == EOF) + errors++; + + if (errors) + return -1; + else + return 0; +} +#endif +#endif /*}*/ diff --git a/lib/pwauth.c b/lib/pwauth.c new file mode 100644 index 00000000..2e8fea54 --- /dev/null +++ b/lib/pwauth.c @@ -0,0 +1,548 @@ +/* + * Copyright 1992 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: pwauth.c,v 1.9 1998/12/28 20:34:38 marekm Exp $") + +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" +#include "pwauth.h" +#include "getdef.h" + +#ifdef SKEY +#include +#endif + +#ifdef OPIE +#include +#endif + +#ifdef __linux__ /* standard password prompt by default */ +static const char *PROMPT = gettext_noop("Password: "); +#else +static const char *PROMPT = gettext_noop("%s's Password:"); +#endif + +extern char *getpass(); + +#ifdef AUTH_METHODS +/* + * Look-up table for bound-in methods. Put the name that the + * method is known by in the password field as "name" and a + * pointer to the function + */ + +struct method { + char *name; + int (*func) P_((const char *, int, const char *)); +}; + +#ifdef PAD_AUTH +int pad_auth(); +#endif +static struct method methods[] = { +#ifdef PAD_AUTH + { "pad", pad_auth }, +#endif + { "", 0 } +}; +#endif /* AUTH_METHODS */ + +int wipe_clear_pass = 1; +char *clear_pass = NULL; + +/* + * _old_auth - perform getpass/crypt authentication + * + * _old_auth gets the user's cleartext password and encrypts it + * using the salt in the encrypted password. The results are + * compared. + */ + +static int +_old_auth(const char *cipher, const char *user, int reason, const char *input) +{ + char prompt[1024]; + char *clear = NULL; + const char *cp; + int retval; +#ifdef SKEY + int use_skey = 0; + char challenge_info[40]; + struct skey skey; +#endif + +#ifdef OPIE + int use_opie = 0; + char o_challenge_info[OPIE_CHALLENGE_MAX + 1]; + struct opie opie; + /* + * This implementation is based almost entirely on the SKEY code + * above. Thus the opie struct is called skey, etc. I am unaware + * if the system works at the same time, but I cannot imagine why + * anyone would want to do this.... + * -- A.R. + * Mod: 5/14/98 A.R. + * Made the OPIE code separate from the S/Key code. Now + * (conceivably) both can be compiled in and function apart from + * one another (assuming a sysadmin really wants to maintain OPIE + * and an S/Key databases....). + * + * Also cleaned up the code a bit. Will be adding second-prompt + * support (the traditional Echo-on S/Key/OPIE-only prompts to let + * the users see the one-time passwords they are typing/pasting + * in.... + * -- A.R. + */ +#endif + + /* + * There are programs for adding and deleting authentication data. + */ + + if (reason == PW_ADD || reason == PW_DELETE) + return 0; + + /* + * There are even programs for changing the user name ... + */ + + if (reason == PW_CHANGE && input != (char *) 0) + return 0; + + /* + * WARNING: + * + * When we change a password and we are root, we don't prompt. + * This is so root can change any password without having to + * know it. This is a policy decision that might have to be + * revisited. + */ + + if (reason == PW_CHANGE && getuid () == 0) + return 0; + + /* + * WARNING: + * + * When we are logging in a user with no ciphertext password, + * we don't prompt for the password or anything. In reality + * the user could just hit , so it doesn't really + * matter. + */ + + if (cipher == (char *) 0 || *cipher == '\0') + return 0; + +#ifdef SKEY + /* + * If the user has an S/KEY entry show them the pertinent info + * and then we can try validating the created cyphertext and the SKEY. + * If there is no SKEY information we default to not using SKEY. + */ + + if (skeychallenge (&skey, user, challenge_info) == 0) + use_skey = 1; +#endif + +#ifdef OPIE + /* + * Ditto above, for OPIE passwords. + * -- AR + */ + + o_challenge_info[0] = '\0'; + if (opiechallenge(&opie, user, o_challenge_info) == 0) + use_opie = 1; + + if (use_opie == 0) + opieverify(&opie, (char *)NULL); + /* + * This call to opieverify is necessary within OPIE's interface: + * Every call to opiechallenge(), which checks to see if the user + * has an OPIE password, and if so get the challenge, must be + * accompanied by exactly one call to opieverify, which clears + * any outstanding locks, and otherwise cleans up. + * -- AR + */ +#endif + + /* + * Prompt for the password as required. FTPD and REXECD both + * get the cleartext password for us. + */ + + if (reason != PW_FTP && reason != PW_REXEC && !input) { + if (! (cp = getdef_str ("LOGIN_STRING"))) + cp = PROMPT; +#ifdef SKEY + if (use_skey) + printf ("[%s]\n", challenge_info); +#endif + +#ifdef OPIE + if (use_opie) + printf("[ %s ]\n", o_challenge_info); +#endif + + snprintf(prompt, sizeof prompt, cp, user); + clear = getpass(_(prompt)); + if (!clear) { + static char c[1]; + c[0] = '\0'; + clear = c; + } + input = clear; + } + + /* + * Convert the cleartext password into a ciphertext string. + * If the two match, the return value will be zero, which is + * SUCCESS. Otherwise we see if SKEY is being used and check + * the results there as well. + */ + + retval = strcmp(pw_encrypt(input, cipher), cipher); + +#ifdef OPIE + /* + * This is required because using OPIE, opieverify() MUST be called + * opiechallenge() above even if OPIE isn't being used in this case, + * so locks get released, etc. + * -- AR + */ + + if ((retval == 0) && use_opie) + opieverify(&opie, (char *)NULL); +#endif + +#ifdef SKEY + if (retval && use_skey) { + int passcheck = -1; + +#if 0 /* some skey libs don't have skey_passcheck. --marekm */ + passcheck = skey_passcheck(user, input); +#else + if (skeyverify(&skey, input) == 0) + passcheck = skey.n; +#endif /* if 0 */ + if (passcheck > 0) + retval = 0; + } +#endif + +#ifdef OPIE + if (retval && use_opie) { + if (opieverify(&opie, input) == 0) + retval = 0; + } +#endif /* OPIE */ + + /* + * Things like RADIUS authentication may need the password - + * if the external variable wipe_clear_pass is zero, we will + * not wipe it (the caller should wipe clear_pass when it is + * no longer needed). --marekm + */ + + clear_pass = clear; + if (wipe_clear_pass && clear && *clear) + strzero(clear); + return retval; +} + +#ifdef AUTH_METHODS +/* + * _pw_auth - perform alternate password authentication + * + * pw_auth executes the alternate password authentication method + * described in the user's password entry. _pw_auth does the real + * work, pw_auth splits the authentication string into individual + * command names. + */ + +static int +_pw_auth(const char *command, const char *user, int reason, const char *input) +{ + RETSIGTYPE (*sigint)(); + RETSIGTYPE (*sigquit)(); +#ifdef SIGTSTP + RETSIGTYPE (*sigtstp)(); +#endif + int pid; + int status; + int i; + char * const argv[5]; + int argc = 0; + int pipes[2]; + char *empty_env = NULL; + int use_pipe; + + /* + * Start with a quick sanity check. ALL command names must + * be fully-qualified path names. + */ + + if (command[0] != '/') + return -1; + + /* + * Set the keyboard signals to be ignored. When the user kills + * the child we don't want the parent dying as well. + */ + + sigint = signal (SIGINT, SIG_IGN); + sigquit = signal (SIGQUIT, SIG_IGN); +#ifdef SIGTSTP + sigtstp = signal (SIGTSTP, SIG_IGN); +#endif + + /* + * FTP and REXEC reasons don't give the program direct access + * to the user. This means that the program can only get input + * from this function. So we set up a pipe for that purpose. + */ + + use_pipe = (reason == PW_FTP || reason == PW_REXEC); + if (use_pipe) + if (pipe (pipes)) + return -1; + + /* + * The program will be forked off with the parent process waiting + * on the child to tell it how successful it was. + */ + + switch (pid = fork ()) { + + /* + * The fork() failed completely. Clean up as needed and + * return to the caller. + */ + case -1: + if (use_pipe) { + close (pipes[0]); + close (pipes[1]); + } + return -1; + case 0: + + /* + * Let the child catch the SIGINT and SIGQUIT + * signals. The parent, however, will continue + * to ignore them. + */ + signal (SIGINT, SIG_DFL); + signal (SIGQUIT, SIG_DFL); + + /* + * Set up the command line. The first argument is + * the name of the command being executed. The + * second is the command line option for the reason, + * and the third is the user name. + */ + argv[argc++] = command; + switch (reason) { + case PW_SU: argv[argc++] = "-s"; break; + case PW_LOGIN: argv[argc++] = "-l"; break; + case PW_ADD: argv[argc++] = "-a"; break; + case PW_CHANGE: argv[argc++] = "-c"; break; + case PW_DELETE: argv[argc++] = "-d"; break; + case PW_TELNET: argv[argc++] = "-t"; break; + case PW_RLOGIN: argv[argc++] = "-r"; break; + case PW_FTP: argv[argc++] = "-f"; break; + case PW_REXEC: argv[argc++] = "-x"; break; + } + if (reason == PW_CHANGE && input) + argv[argc++] = input; + + argv[argc++] = user; + argv[argc] = (char *) 0; + + /* + * The FTP and REXEC reasons use a pipe to communicate + * with the parent. The other standard I/O descriptors + * are closed and re-opened as /dev/null. + */ + if (use_pipe) { + close (0); + close (1); + close (2); + + if (dup (pipes[0]) != 0) + exit (1); + + close (pipes[0]); + close (pipes[1]); + + if (open ("/dev/null", O_WRONLY) != 1) + exit (1); + + if (open ("/dev/null", O_WRONLY) != 2) + exit (1); + } + + /* + * Now we execute the command directly. + * Do it with empty environment for safety. --marekm + */ + execve(command, argv, &empty_env); + _exit((errno == ENOENT) ? 127 : 126); + /*NOTREACHED*/ + default: + /* + * FTP and REXEC cause a single line of text to be + * sent to the child over a pipe that was set up + * earlier. + */ + if (use_pipe) { + close (pipes[0]); + + if (input) + write (pipes[1], input, strlen (input)); + + write (pipes[1], "\n", 1); + close (pipes[1]); + } + + /* + * Wait on the child to die. When it does you will + * get the exit status and use that to determine if + * the authentication program was successful. + */ + while ((i = wait (&status)) != pid && i != -1) + ; + + /* + * Re-set the signals to their earlier values. + */ + signal (SIGINT, sigint); + signal (SIGQUIT, sigquit); +#ifdef SIGTSTP + signal (SIGTSTP, sigtstp); +#endif + + /* + * Make sure we found the right process! + */ + if (i == -1) + return -1; + + if (status == 0) + return 0; + else + return -1; + } + /*NOTREACHED*/ +} + +/* + * _builtin_auth - lookup routine in table and execute + */ + +static int +_builtin_auth(const char *command, const char *user, int reason, const char *input) +{ + int i; + + /* + * Scan the table, looking for a match. If we fall off + * the end, it must mean that this method isn't supported, + * so we fail the authentication. + */ + + for (i = 0;methods[i].name[0];i++) { + if (! strcmp (command, methods[i].name)) + break; + } + if (methods[i].name[0] == '\0') + return -1; + + /* + * Call the pointed to function with the other three + * arguments. + */ + + return (methods[i].func) (user, reason, input); +} +#endif /* AUTH_METHODS */ + +/* + * This function does the real work. It splits the list of program names + * up into individual programs and executes them one at a time. + */ + +int +pw_auth(const char *command, const char *user, int reason, const char *input) +{ +#ifdef AUTH_METHODS + char buf[256]; + char *cmd, *end; + int rc; + + /* + * Quick little sanity check ... + */ + + if (strlen (command) >= sizeof buf) + return -1; + + strcpy (buf, command); /* safe (because of the above check) --marekm */ + + /* + * Find each command and make sure it is NUL-terminated. Then + * invoke _pw_auth to actually run the program. The first + * failing program ends the whole mess. + */ + + for (cmd = buf;cmd;cmd = end) { + if ((end = strchr (cmd, ';'))) + *end++ = '\0'; + + if (cmd[0] != '@') + rc = _old_auth (cmd, user, reason, input); + else if (cmd[1] == '/') + rc = _pw_auth (cmd + 1, user, reason, input); + else + rc = _builtin_auth (cmd + 1, user, reason, input); + if (rc) + return -1; + } + return 0; +#else + return _old_auth(command, user, reason, input); +#endif +} diff --git a/lib/pwauth.h b/lib/pwauth.h new file mode 100644 index 00000000..ab6017b4 --- /dev/null +++ b/lib/pwauth.h @@ -0,0 +1,60 @@ +/* + * Copyright 1992 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: pwauth.h,v 1.2 1997/05/01 23:14:44 marekm Exp $ + */ + +#if __STDC__ +int pw_auth(const char *program,const char *user,int flag,const char *input); +#else +int pw_auth (); +#endif + +/* + * Local access + */ + +#define PW_SU 1 +#define PW_LOGIN 2 + +/* + * Administrative functions + */ + +#define PW_ADD 101 +#define PW_CHANGE 102 +#define PW_DELETE 103 + +/* + * Network access + */ + +#define PW_TELNET 201 +#define PW_RLOGIN 202 +#define PW_FTP 203 +#define PW_REXEC 204 diff --git a/lib/pwdbm.c b/lib/pwdbm.c new file mode 100644 index 00000000..c0de8460 --- /dev/null +++ b/lib/pwdbm.c @@ -0,0 +1,143 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifdef NDBM /*{*/ + +#include "rcsid.h" +RCSID("$Id: pwdbm.c,v 1.4 1997/12/14 20:07:19 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +#include +extern DBM *pw_dbm; + +/* + * pw_dbm_update + * + * Updates the DBM password files, if they exist. + */ + +int +pw_dbm_update(const struct passwd *pw) +{ + datum key; + datum content; + char data[BUFSIZ]; + int len; + static int once; + + if (! once) { + if (! pw_dbm) + setpwent (); + once++; + } + if (! pw_dbm) + return 0; + + len = pw_pack (pw, data); + content.dsize = len; + content.dptr = data; + + key.dsize = strlen (pw->pw_name); + key.dptr = pw->pw_name; + + if (dbm_store(pw_dbm, key, content, DBM_REPLACE)) + return 0; + + /* + * XXX - on systems with 16-bit UIDs (such as Linux/x86) + * name "aa" and UID 24929 will give the same key. This + * happens only rarely, but code which only "works most + * of the time" is not good enough... + * + * This needs to be fixed in several places (pwdbm.c, + * grdbm.c, pwent.c, grent.c). Fixing it will cause + * incompatibility with existing dbm files. + * + * Summary: don't use this stuff for now. --marekm + */ + + key.dsize = sizeof pw->pw_uid; + key.dptr = (char *) &pw->pw_uid; + + if (dbm_store(pw_dbm, key, content, DBM_REPLACE)) + return 0; + + return 1; +} + +/* + * pw_dbm_remove + * + * Removes the DBM password entry, if it exists. + */ + +int +pw_dbm_remove(const struct passwd *pw) +{ + datum key; + static int once; + char data[BUFSIZ]; + + if (! once) { + if (! pw_dbm) + setpwent (); + once++; + } + if (! pw_dbm) + return 0; + + key.dsize = strlen (pw->pw_name); + key.dptr = pw->pw_name; + + if (dbm_delete (pw_dbm, key)) + return 0; + + key.dsize = sizeof pw->pw_uid; + key.dptr = (char *) &pw->pw_uid; + + if (dbm_delete (pw_dbm, key)) + return 0; + + return 1; +} + + +int +pw_dbm_present(void) +{ + return (access(PASSWD_PAG_FILE, F_OK) == 0); +} +#endif /* NDBM */ diff --git a/lib/pwio.c b/lib/pwio.c new file mode 100644 index 00000000..7dc7e9ad --- /dev/null +++ b/lib/pwio.c @@ -0,0 +1,187 @@ + +#include + +#include "rcsid.h" +RCSID("$Id: pwio.c,v 1.9 1998/01/29 23:22:31 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include +#include + +#include "commonio.h" +#include "pwio.h" + +extern struct passwd *sgetpwent P_((const char *)); +extern int putpwent P_((const struct passwd *, FILE *)); + +struct passwd * +__pw_dup(const struct passwd *pwent) +{ + struct passwd *pw; + + if (!(pw = (struct passwd *) malloc(sizeof *pw))) + return NULL; + *pw = *pwent; + if (!(pw->pw_name = strdup(pwent->pw_name))) + return NULL; + if (!(pw->pw_passwd = strdup(pwent->pw_passwd))) + return NULL; +#ifdef ATT_AGE + if (!(pw->pw_age = strdup(pwent->pw_age))) + return NULL; +#endif +#ifdef ATT_COMMENT + if (!(pw->pw_comment = strdup(pwent->pw_comment))) + return NULL; +#endif + if (!(pw->pw_gecos = strdup(pwent->pw_gecos))) + return NULL; + if (!(pw->pw_dir = strdup(pwent->pw_dir))) + return NULL; + if (!(pw->pw_shell = strdup(pwent->pw_shell))) + return NULL; + return pw; +} + +static void * +passwd_dup(const void *ent) +{ + const struct passwd *pw = ent; + return __pw_dup(pw); +} + +static void +passwd_free(void *ent) +{ + struct passwd *pw = ent; + + free(pw->pw_name); + free(pw->pw_passwd); +#ifdef ATT_AGE + free(pw->pw_age); +#endif +#ifdef ATT_COMMENT + free(pw->pw_comment); +#endif + free(pw->pw_gecos); + free(pw->pw_dir); + free(pw->pw_shell); + free(pw); +} + +static const char * +passwd_getname(const void *ent) +{ + const struct passwd *pw = ent; + return pw->pw_name; +} + +static void * +passwd_parse(const char *line) +{ + return (void *) sgetpwent(line); +} + +static int +passwd_put(const void *ent, FILE *file) +{ + const struct passwd *pw = ent; + return (putpwent(pw, file) == -1) ? -1 : 0; +} + +static struct commonio_ops passwd_ops = { + passwd_dup, + passwd_free, + passwd_getname, + passwd_parse, + passwd_put, + fgets, + fputs +}; + +static struct commonio_db passwd_db = { + PASSWD_FILE, /* filename */ + &passwd_ops, /* ops */ + NULL, /* fp */ + NULL, /* head */ + NULL, /* tail */ + NULL, /* cursor */ + 0, /* changed */ + 0, /* isopen */ + 0, /* locked */ + 0, /* readonly */ + 1 /* use_lckpwdf */ +}; + +int +pw_name(const char *filename) +{ + return commonio_setname(&passwd_db, filename); +} + +int +pw_lock(void) +{ + return commonio_lock(&passwd_db); +} + +int +pw_open(int mode) +{ + return commonio_open(&passwd_db, mode); +} + +const struct passwd * +pw_locate(const char *name) +{ + return commonio_locate(&passwd_db, name); +} + +int +pw_update(const struct passwd *pw) +{ + return commonio_update(&passwd_db, (const void *) pw); +} + +int +pw_remove(const char *name) +{ + return commonio_remove(&passwd_db, name); +} + +int +pw_rewind(void) +{ + return commonio_rewind(&passwd_db); +} + +const struct passwd * +pw_next(void) +{ + return commonio_next(&passwd_db); +} + +int +pw_close(void) +{ + return commonio_close(&passwd_db); +} + +int +pw_unlock(void) +{ + return commonio_unlock(&passwd_db); +} + +struct commonio_entry * +__pw_get_head(void) +{ + return passwd_db.head; +} + +void +__pw_del_entry(const struct commonio_entry *ent) +{ + commonio_del_entry(&passwd_db, ent); +} diff --git a/lib/pwio.h b/lib/pwio.h new file mode 100644 index 00000000..88bace77 --- /dev/null +++ b/lib/pwio.h @@ -0,0 +1,12 @@ +extern struct passwd *__pw_dup P_((const struct passwd *)); +extern void __pw_set_changed P_((void)); +extern int pw_close P_((void)); +extern const struct passwd *pw_locate P_((const char *)); +extern int pw_lock P_((void)); +extern int pw_name P_((const char *)); +extern const struct passwd *pw_next P_((void)); +extern int pw_open P_((int)); +extern int pw_remove P_((const char *)); +extern int pw_rewind P_((void)); +extern int pw_unlock P_((void)); +extern int pw_update P_((const struct passwd *)); diff --git a/lib/pwpack.c b/lib/pwpack.c new file mode 100644 index 00000000..67053baf --- /dev/null +++ b/lib/pwpack.c @@ -0,0 +1,163 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: pwpack.c,v 1.4 1998/04/16 19:57:42 marekm Exp $") + +#include +#include "defines.h" +#include +#include + + +/* + * pw_pack - convert a (struct pwd) to a packed record + * WARNING: buf must be large enough, no check for overrun! + */ + +int +pw_pack(const struct passwd *passwd, char *buf) +{ + char *cp; + + cp = buf; + strcpy (cp, passwd->pw_name); + cp += strlen (cp) + 1; + + strcpy (cp, passwd->pw_passwd); +#ifdef ATT_AGE + if (passwd->pw_age[0]) { + *cp++ = ','; + strcat (cp, passwd->pw_age); + } +#endif + cp += strlen (cp) + 1; + + memcpy (cp, (const char *) &passwd->pw_uid, sizeof passwd->pw_uid); + cp += sizeof passwd->pw_uid; + + memcpy (cp, (const char *) &passwd->pw_gid, sizeof passwd->pw_gid); + cp += sizeof passwd->pw_gid; +#ifdef BSD_QUOTA + memcpy (cp, (const char *) &passwd->pw_quota, sizeof passwd->pw_quota); + cp += sizeof passwd->pw_quota; +#endif +#ifdef ATT_COMMENT + if (passwd->pw_comment) { + strcpy (cp, passwd->pw_comment); + cp += strlen (cp) + 1; + } else + *cp++ = '\0'; +#endif + strcpy (cp, passwd->pw_gecos); + cp += strlen (cp) + 1; + + strcpy (cp, passwd->pw_dir); + cp += strlen (cp) + 1; + + strcpy (cp, passwd->pw_shell); + cp += strlen (cp) + 1; + + return cp - buf; +} + +/* + * pw_unpack - convert a packed (struct pwd) record to a (struct pwd) + */ + +int +pw_unpack(char *buf, int len, struct passwd *passwd) +{ + char *org = buf; +#ifdef ATT_AGE + char *cp; +#endif + + memzero(passwd, sizeof *passwd); + + passwd->pw_name = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + passwd->pw_passwd = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + +#ifdef ATT_AGE + if (cp = strchr (passwd->pw_passwd, ',')) { + *cp++ = '\0'; + passwd->pw_age = cp; + } else + passwd->pw_age = ""; +#endif + + memcpy ((void *) &passwd->pw_uid, (void *) buf, sizeof passwd->pw_uid); + buf += sizeof passwd->pw_uid; + if (buf - org > len) + return -1; + + memcpy ((void *) &passwd->pw_gid, (void *) buf, sizeof passwd->pw_gid); + buf += sizeof passwd->pw_gid; + if (buf - org > len) + return -1; + +#ifdef BSD_QUOTA + memcpy ((void *) &passwd->pw_quota, (void *) buf, + sizeof passwd->pw_quota); + buf += sizeof passwd->pw_quota; + if (buf - org > len) + return -1; +#endif +#ifdef ATT_COMMENT + passwd->pw_comment = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; +#endif + passwd->pw_gecos = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + passwd->pw_dir = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + passwd->pw_shell = buf; + buf += strlen (buf) + 1; + if (buf - org > len) + return -1; + + return 0; +} diff --git a/lib/rad64.c b/lib/rad64.c new file mode 100644 index 00000000..5b22e96e --- /dev/null +++ b/lib/rad64.c @@ -0,0 +1,126 @@ +/* + * Copyright 1989 - 1992, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: rad64.c,v 1.4 1997/12/07 23:26:56 marekm Exp $") + +/* + * c64i - convert a radix 64 character to an integer + */ + +int +c64i(char c) +{ + if (c == '.') + return (0); + + if (c == '/') + return (1); + + if (c >= '0' && c <= '9') + return (c - '0' + 2); + + if (c >= 'A' && c <= 'Z') + return (c - 'A' + 12); + + if (c >= 'a' && c <= 'z') + return (c - 'a' + 38); + else + return (-1); +} + +/* + * i64c - convert an integer to a radix 64 character + */ + +int +i64c(int i) +{ + if (i <= 0) + return ('.'); + + if (i == 1) + return ('/'); + + if (i >= 2 && i < 12) + return ('0' - 2 + i); + + if (i >= 12 && i < 38) + return ('A' - 12 + i); + + if (i >= 38 && i < 63) + return ('a' - 38 + i); + + return ('z'); +} + +#ifndef HAVE_A64L + +/* + * l64a - convert a long to a string of radix 64 characters + */ + +char * +l64a(long l) +{ + static char buf[8]; + int i = 0; + + if (l < 0L) + return ((char *) 0); + + do { + buf[i++] = i64c ((int) (l % 64)); + buf[i] = '\0'; + } while (l /= 64L, l > 0 && i < 6); + + return (buf); +} + +/* + * a64l - convert a radix 64 string to a long integer + */ + +long +a64l(const char *s) +{ + int i; + long value; + long shift = 0; + + for (i = 0, value = 0L;i < 6 && *s;s++) { + value += (c64i (*s) << shift); + shift += 6; + } + return (value); +} + +#endif /* !HAVE_A64L */ diff --git a/lib/rcsid.h b/lib/rcsid.h new file mode 100644 index 00000000..3869afc1 --- /dev/null +++ b/lib/rcsid.h @@ -0,0 +1,22 @@ +/* + * $Id: rcsid.h,v 1.2 1999/06/07 16:40:44 marekm Exp $ + */ +#define PKG_VER " $Package: " PACKAGE " $ $Version: " VERSION " $ " +#if defined(NO_RCSID) || defined(lint) +#define RCSID(x) /* empty */ +#else +#if __STDC__ +/* + * This function is never called from anywhere, but it calls itself + * recursively only to fool gcc to not generate warnings :-). + */ +static const char *rcsid(const char *); +#define RCSID(x) \ + static const char *rcsid(const char *s) { \ + return rcsid(x); } +#else /* ! __STDC__ */ +#define RCSID(x) \ + static char *rcsid(s) char *s; { \ + return rcsid(x); } +#endif /* ! __STDC__ */ +#endif diff --git a/lib/rename.c b/lib/rename.c new file mode 100644 index 00000000..d693d794 --- /dev/null +++ b/lib/rename.c @@ -0,0 +1,91 @@ +/* + * Copyright 1993 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: rename.c,v 1.3 1997/12/07 23:26:57 marekm Exp $") + +#include "defines.h" +#include +#include + +/* + * rename - rename a file to another name + * + * rename is provided for systems which do not include the rename() + * system call. + */ + +int +rename(const char *begin, const char *end) +{ + struct stat s1, s2; + extern int errno; + int orig_err = errno; + + if (stat (begin, &s1)) + return -1; + + if (stat (end, &s2)) { + errno = orig_err; + } else { + + /* + * See if this is a cross-device link. We do this to + * insure that the link below has a chance of working. + */ + + if (s1.st_dev != s2.st_dev) { + errno = EXDEV; + return -1; + } + + /* + * See if we can unlink the existing destination + * file. If the unlink works the directory is writable, + * so there is no need here to figure that out. + */ + + if (unlink (end)) + return -1; + } + + /* + * Now just link the original name to the final name. If there + * was no file previously, this link will fail if the target + * directory isn't writable. The unlink will fail if the source + * directory isn't writable, but life stinks ... + */ + + if (link (begin, end) || unlink (begin)) + return -1; + + return 0; +} diff --git a/lib/rmdir.c b/lib/rmdir.c new file mode 100644 index 00000000..d6a57508 --- /dev/null +++ b/lib/rmdir.c @@ -0,0 +1,59 @@ +/* + * Copyright 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include "rcsid.h" +RCSID("$Id: rmdir.c,v 1.4 1998/01/29 23:22:31 marekm Exp $") + +/* + * rmdir - remove a directory + * + * rmdir is provided for systems which do not include the rmdir() + * system call. + */ + +int +rmdir(const char *dir) +{ + int status; + + if (fork()) { + while (wait(&status) != -1) + ; + + return status >> 8; + } + close(2); + open("/dev/null", O_WRONLY); + execl("/bin/rmdir", "rmdir", dir, 0); + _exit(127); + /*NOTREACHED*/ +} diff --git a/lib/sgetgrent.c b/lib/sgetgrent.c new file mode 100644 index 00000000..daa5fbe2 --- /dev/null +++ b/lib/sgetgrent.c @@ -0,0 +1,140 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: sgetgrent.c,v 1.4 1998/04/02 21:51:45 marekm Exp $") + +#include +#include +#include "defines.h" + +#define NFIELDS 4 + +/* + * list - turn a comma-separated string into an array of (char *)'s + * + * list() converts the comma-separated list of member names into + * an array of character pointers. + * + * WARNING: I profiled this once with and without strchr() calls + * and found that using a register variable and an explicit loop + * works best. For large /etc/group files, this is a major win. + * + * FINALLY added dynamic allocation. Still need to fix sgetsgent(). + * --marekm + */ + +static char ** +list(char *s) +{ + static char **members = 0; + static int size = 0; /* max members + 1 */ + int i; + char **rbuf; + + i = 0; + for (;;) { + /* check if there is room for another pointer (to a group + member name, or terminating NULL). */ + if (i >= size) { + size = i + 100; /* at least: i + 1 */ + if (members) { + rbuf = realloc(members, size * sizeof(char *)); + } else { + /* for old (before ANSI C) implementations of + realloc() that don't handle NULL properly */ + rbuf = malloc(size * sizeof(char *)); + } + if (!rbuf) { + if (members) + free(members); + members = 0; + size = 0; + return (char **) 0; + } + members = rbuf; + } + if (!s || s[0] == '\0') + break; + members[i++] = s; + while (*s && *s != ',') + s++; + if (*s) + *s++ = '\0'; + } + members[i] = (char *) 0; + return members; +} + + +struct group * +sgetgrent(const char *buf) +{ + static char *grpbuf = 0; + static size_t size = 0; + static char *grpfields[NFIELDS]; + static struct group grent; + int i; + char *cp; + + if (strlen(buf) + 1 > size) { + /* no need to use realloc() here - just free it and + allocate a larger block */ + if (grpbuf) + free(grpbuf); + size = strlen(buf) + 1000; /* at least: strlen(buf) + 1 */ + grpbuf = malloc(size); + if (!grpbuf) { + size = 0; + return 0; + } + } + strcpy(grpbuf, buf); + + if ((cp = strrchr(grpbuf, '\n'))) + *cp = '\0'; + + for (cp = grpbuf, i = 0; i < NFIELDS && cp; i++) { + grpfields[i] = cp; + if ((cp = strchr(cp, ':'))) + *cp++ = 0; + } + if (i < (NFIELDS-1) || *grpfields[2] == '\0') + return 0; + grent.gr_name = grpfields[0]; + grent.gr_passwd = grpfields[1]; + grent.gr_gid = atoi(grpfields[2]); + grent.gr_mem = list(grpfields[3]); + if (!grent.gr_mem) + return (struct group *) 0; /* out of memory */ + + return &grent; +} diff --git a/lib/sgetpwent.c b/lib/sgetpwent.c new file mode 100644 index 00000000..993f3c97 --- /dev/null +++ b/lib/sgetpwent.c @@ -0,0 +1,136 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: sgetpwent.c,v 1.5 1998/04/02 21:51:46 marekm Exp $") + +#include +#include "defines.h" +#include +#include + +#define NFIELDS 7 + +/* + * sgetpwent - convert a string to a (struct passwd) + * + * sgetpwent() parses a string into the parts required for a password + * structure. Strict checking is made for the UID and GID fields and + * presence of the correct number of colons. Any failing tests result + * in a NULL pointer being returned. + * + * NOTE: This function uses hard-coded string scanning functions for + * performance reasons. I am going to come up with some conditional + * compilation glarp to improve on this in the future. + */ + +struct passwd * +sgetpwent(const char *buf) +{ + static struct passwd pwent; + static char pwdbuf[1024]; + register int i; + register char *cp; + char *ep; + char *fields[NFIELDS]; + + /* + * Copy the string to a static buffer so the pointers into + * the password structure remain valid. + */ + + if (strlen(buf) >= sizeof pwdbuf) + return 0; /* fail if too long */ + strcpy(pwdbuf, buf); + + /* + * Save a pointer to the start of each colon separated + * field. The fields are converted into NUL terminated strings. + */ + + for (cp = pwdbuf, i = 0;i < NFIELDS && cp;i++) { + fields[i] = cp; + while (*cp && *cp != ':') + ++cp; + + if (*cp) + *cp++ = '\0'; + else + cp = 0; + } + + /* + * There must be exactly NFIELDS colon separated fields or + * the entry is invalid. Also, the UID and GID must be non-blank. + */ + + if (i != NFIELDS || *fields[2] == '\0' || *fields[3] == '\0') + return 0; + + /* + * Each of the fields is converted the appropriate data type + * and the result assigned to the password structure. If the + * UID or GID does not convert to an integer value, a NULL + * pointer is returned. + */ + + pwent.pw_name = fields[0]; + pwent.pw_passwd = fields[1]; + if (fields[2][0] == '\0' || + ((pwent.pw_uid = strtol (fields[2], &ep, 10)) == 0 && *ep)) { + return 0; + } + if (fields[3][0] == '\0' || + ((pwent.pw_gid = strtol (fields[3], &ep, 10)) == 0 && *ep)) { + return 0; + } +#ifdef ATT_AGE + cp = pwent.pw_passwd; + while (*cp && *cp != ',') + ++cp; + + if (*cp) { + *cp++ = '\0'; + pwent.pw_age = cp; + } else { + cp = 0; + pwent.pw_age = ""; + } +#endif + pwent.pw_gecos = fields[4]; +#ifdef ATT_COMMENT + pwent.pw_comment = ""; +#endif + pwent.pw_dir = fields[5]; + pwent.pw_shell = fields[6]; + + return &pwent; +} diff --git a/lib/sgetspent.c b/lib/sgetspent.c new file mode 100644 index 00000000..1860075f --- /dev/null +++ b/lib/sgetspent.c @@ -0,0 +1,198 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifdef SHADOWPWD /*{*/ + +#include "rcsid.h" +RCSID("$Id: sgetspent.c,v 1.5 1998/04/02 21:51:47 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include + +#define FIELDS 9 +#define OFIELDS 5 + +/* + * sgetspent - convert string in shadow file format to (struct spwd *) + */ + +struct spwd * +sgetspent(const char *string) +{ + static char spwbuf[1024]; + static struct spwd spwd; + char *fields[FIELDS]; + char *cp; + char *cpp; + int i; + + /* + * Copy string to local buffer. It has to be tokenized and we + * have to do that to our private copy. + */ + + if (strlen(string) >= sizeof spwbuf) + return 0; /* fail if too long */ + strcpy(spwbuf, string); + + if ((cp = strrchr (spwbuf, '\n'))) + *cp = '\0'; + + /* + * Tokenize the string into colon separated fields. Allow up to + * FIELDS different fields. + */ + + for (cp = spwbuf, i = 0;*cp && i < FIELDS;i++) { + fields[i] = cp; + while (*cp && *cp != ':') + cp++; + + if (*cp) + *cp++ = '\0'; + } + + /* + * It is acceptable for the last SVR4 field to be blank. This + * results in the loop being terminated early. In which case, + * we just make the last field be blank and be done with it. + */ + + if (i == (FIELDS-1)) + fields[i++] = cp; + + if ((cp && *cp) || (i != FIELDS && i != OFIELDS)) + return 0; + + /* + * Start populating the structure. The fields are all in + * static storage, as is the structure we pass back. + */ + + spwd.sp_namp = fields[0]; + spwd.sp_pwdp = fields[1]; + + /* + * Get the last changed date. For all of the integer fields, + * we check for proper format. It is an error to have an + * incorrectly formatted number. + */ + + if ((spwd.sp_lstchg = strtol (fields[2], &cpp, 10)) == 0 && *cpp) { + return 0; + } else if (fields[2][0] == '\0') + spwd.sp_lstchg = -1; + + /* + * Get the minimum period between password changes. + */ + + if ((spwd.sp_min = strtol (fields[3], &cpp, 10)) == 0 && *cpp) { + return 0; + } else if (fields[3][0] == '\0') + spwd.sp_min = -1; + + /* + * Get the maximum number of days a password is valid. + */ + + if ((spwd.sp_max = strtol (fields[4], &cpp, 10)) == 0 && *cpp) { + return 0; + } else if (fields[4][0] == '\0') + spwd.sp_max = -1; + + /* + * If there are only OFIELDS fields (this is a SVR3.2 /etc/shadow + * formatted file), initialize the other field members to -1. + */ + +#if 0 /* SVR4 */ + if (i == OFIELDS) + return 0; +#else + if (i == OFIELDS) { + spwd.sp_warn = spwd.sp_inact = spwd.sp_expire = + spwd.sp_flag = -1; + + return &spwd; + } +#endif + + /* + * The rest of the fields are mandatory for SVR4, but optional + * for anything else. However, if one is present the others + * must be as well. + */ + + /* + * Get the number of days of password expiry warning. + */ + + if ((spwd.sp_warn = strtol (fields[5], &cpp, 10)) == 0 && *cpp) { + return 0; + } else if (fields[5][0] == '\0') + spwd.sp_warn = -1; + + /* + * Get the number of days of inactivity before an account is + * disabled. + */ + + if ((spwd.sp_inact = strtol (fields[6], &cpp, 10)) == 0 && *cpp) { + return 0; + } else if (fields[6][0] == '\0') + spwd.sp_inact = -1; + + /* + * Get the number of days after the epoch before the account is + * set to expire. + */ + + if ((spwd.sp_expire = strtol (fields[7], &cpp, 10)) == 0 && *cpp) { + return 0; + } else if (fields[7][0] == '\0') + spwd.sp_expire = -1; + + /* + * This field is reserved for future use. But it isn't supposed + * to have anything other than a valid integer in it. + */ + + if ((spwd.sp_flag = strtol (fields[8], &cpp, 10)) == 0 && *cpp) { + return 0; + } else if (fields[8][0] == '\0') + spwd.sp_flag = -1; + + return (&spwd); +} +#endif /*}*/ diff --git a/lib/sgroupio.c b/lib/sgroupio.c new file mode 100644 index 00000000..a10e422e --- /dev/null +++ b/lib/sgroupio.c @@ -0,0 +1,213 @@ + +#include + +#ifdef SHADOWGRP + +#include "rcsid.h" +RCSID("$Id: sgroupio.c,v 1.9 1998/01/29 23:22:31 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" + +#include "commonio.h" +#include "sgroupio.h" + +extern int putsgent P_((const struct sgrp *, FILE *)); +extern struct sgrp *sgetsgent P_((const char *)); + +struct sgrp * +__sgr_dup(const struct sgrp *sgent) +{ + struct sgrp *sg; + int i; + + if (!(sg = (struct sgrp *) malloc(sizeof *sg))) + return NULL; + *sg = *sgent; + if (!(sg->sg_name = strdup(sgent->sg_name))) + return NULL; + if (!(sg->sg_passwd = strdup(sgent->sg_passwd))) + return NULL; + + for (i = 0; sgent->sg_adm[i]; i++) + ; + sg->sg_adm = (char **) malloc((i + 1) * sizeof(char *)); + if (!sg->sg_adm) + return NULL; + for (i = 0; sgent->sg_adm[i]; i++) { + sg->sg_adm[i] = strdup(sgent->sg_adm[i]); + if (!sg->sg_adm[i]) + return NULL; + } + sg->sg_adm[i] = NULL; + + for (i = 0; sgent->sg_mem[i]; i++) + ; + sg->sg_mem = (char **) malloc((i + 1) * sizeof(char *)); + if (!sg->sg_mem) + return NULL; + for (i = 0; sgent->sg_mem[i]; i++) { + sg->sg_mem[i] = strdup(sgent->sg_mem[i]); + if (!sg->sg_mem[i]) + return NULL; + } + sg->sg_mem[i] = NULL; + + return sg; +} + +static void * +gshadow_dup(const void *ent) +{ + const struct sgrp *sg = ent; + return __sgr_dup(sg); +} + +static void +gshadow_free(void *ent) +{ + struct sgrp *sg = ent; + + free(sg->sg_name); + free(sg->sg_passwd); + while(*(sg->sg_adm)) { + free(*(sg->sg_adm)); + sg->sg_adm++; + } + while(*(sg->sg_mem)) { + free(*(sg->sg_mem)); + sg->sg_mem++; + } + free(sg); +} + +static const char * +gshadow_getname(const void *ent) +{ + const struct sgrp *gr = ent; + return gr->sg_name; +} + +static void * +gshadow_parse(const char *line) +{ + return (void *) sgetsgent(line); +} + +static int +gshadow_put(const void *ent, FILE *file) +{ + const struct sgrp *sg = ent; + return (putsgent(sg, file) == -1) ? -1 : 0; +} + +static struct commonio_ops gshadow_ops = { + gshadow_dup, + gshadow_free, + gshadow_getname, + gshadow_parse, + gshadow_put, + fgetsx, + fputsx +}; + +static struct commonio_db gshadow_db = { + SGROUP_FILE, /* filename */ + &gshadow_ops, /* ops */ + NULL, /* fp */ + NULL, /* head */ + NULL, /* tail */ + NULL, /* cursor */ + 0, /* changed */ + 0, /* isopen */ + 0, /* locked */ + 0, /* readonly */ + 0 /* use_lckpwdf */ +}; + +int +sgr_name(const char *filename) +{ + return commonio_setname(&gshadow_db, filename); +} + +int +sgr_file_present(void) +{ + return commonio_present(&gshadow_db); +} + +int +sgr_lock(void) +{ + return commonio_lock(&gshadow_db); +} + +int +sgr_open(int mode) +{ + return commonio_open(&gshadow_db, mode); +} + +const struct sgrp * +sgr_locate(const char *name) +{ + return commonio_locate(&gshadow_db, name); +} + +int +sgr_update(const struct sgrp *sg) +{ + return commonio_update(&gshadow_db, (const void *) sg); +} + +int +sgr_remove(const char *name) +{ + return commonio_remove(&gshadow_db, name); +} + +int +sgr_rewind(void) +{ + return commonio_rewind(&gshadow_db); +} + +const struct sgrp * +sgr_next(void) +{ + return commonio_next(&gshadow_db); +} + +int +sgr_close(void) +{ + return commonio_close(&gshadow_db); +} + +int +sgr_unlock(void) +{ + return commonio_unlock(&gshadow_db); +} + +void +__sgr_set_changed(void) +{ + gshadow_db.changed = 1; +} + +struct commonio_entry * +__sgr_get_head(void) +{ + return gshadow_db.head; +} + +void +__sgr_del_entry(const struct commonio_entry *ent) +{ + commonio_del_entry(&gshadow_db, ent); +} +#else +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif diff --git a/lib/sgroupio.h b/lib/sgroupio.h new file mode 100644 index 00000000..7f41a8fa --- /dev/null +++ b/lib/sgroupio.h @@ -0,0 +1,13 @@ +extern struct sgrp *__sgr_dup P_((const struct sgrp *)); +extern void __sgr_set_changed P_((void)); +extern int sgr_close P_((void)); +extern int sgr_file_present P_((void)); +extern const struct sgrp *sgr_locate P_((const char *)); +extern int sgr_lock P_((void)); +extern int sgr_name P_((const char *)); +extern const struct sgrp *sgr_next P_((void)); +extern int sgr_open P_((int)); +extern int sgr_remove P_((const char *)); +extern int sgr_rewind P_((void)); +extern int sgr_unlock P_((void)); +extern int sgr_update P_((const struct sgrp *)); diff --git a/lib/shadow.c b/lib/shadow.c new file mode 100644 index 00000000..76179d3a --- /dev/null +++ b/lib/shadow.c @@ -0,0 +1,592 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +/* Newer versions of Linux libc already have shadow support. */ +#if defined(SHADOWPWD) && !defined(HAVE_GETSPNAM) /*{*/ + +#include "rcsid.h" +RCSID("$Id: shadow.c,v 1.6 1998/01/29 23:22:32 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include + +#ifdef NDBM +#include +#include +DBM *sp_dbm; +int sp_dbm_mode = -1; +static int dbmopened; +static int dbmerror; +#endif + +#ifdef USE_NIS +static int nis_used; +static int nis_ignore; +static enum { native, start, middle, native2 } nis_state; +static int nis_bound; +static char *nis_domain; +static char *nis_key; +static int nis_keylen; +static char *nis_val; +static int nis_vallen; +#define IS_NISCHAR(c) ((c)=='+') +#endif + +static FILE *shadow; +static char spwbuf[BUFSIZ]; +static struct spwd spwd; + +#define FIELDS 9 +#define OFIELDS 5 + +#ifdef USE_NIS + +/* + * __setspNIS - turn on or off NIS searches + */ + +void +__setspNIS(int flag) +{ + nis_ignore = ! flag; + + if (nis_ignore) + nis_used = 0; +} + +/* + * bind_nis - bind to NIS server + */ + +static int +bind_nis(void) +{ + if (yp_get_default_domain (&nis_domain)) + return -1; + + nis_bound = 1; + return 0; +} +#endif + +/* + * setspent - initialize access to shadow text and DBM files + */ + +void +setspent(void) +{ + if (shadow) + rewind(shadow); + else + shadow = fopen(SHADOW_FILE, "r"); + +#ifdef USE_NIS + nis_state = native; +#endif + + /* + * Attempt to open the DBM files if they have never been opened + * and an error has never been returned. + */ + +#ifdef NDBM + if (! dbmerror && ! dbmopened) { + int mode; + char dbmfiles[BUFSIZ]; + + strcpy (dbmfiles, SHADOW_PAG_FILE); + + if (sp_dbm_mode == -1) + mode = O_RDWR; + else + mode = (sp_dbm_mode == O_RDWR) ? O_RDWR:O_RDONLY; + + if (! (sp_dbm = dbm_open (SHADOW_FILE, mode, 0))) + dbmerror = 1; + else + dbmopened = 1; + } +#endif +} + +/* + * endspent - terminate access to shadow text and DBM files + */ + +void +endspent(void) +{ + if (shadow) + (void) fclose (shadow); + + shadow = (FILE *) 0; +#ifdef NDBM + if (dbmopened && sp_dbm) { + dbm_close (sp_dbm); + sp_dbm = 0; + } + dbmopened = 0; + dbmerror = 0; +#endif +} + +/* + * my_sgetspent - convert string in shadow file format to (struct spwd *) + */ + +static struct spwd * +my_sgetspent(const char *string) +{ + char *fields[FIELDS]; + char *cp; + char *cpp; + int i; + + /* + * Copy string to local buffer. It has to be tokenized and we + * have to do that to our private copy. + */ + + if (strlen(string) >= sizeof spwbuf) + return 0; + strcpy(spwbuf, string); + + if ((cp = strrchr (spwbuf, '\n'))) + *cp = '\0'; + + /* + * Tokenize the string into colon separated fields. Allow up to + * FIELDS different fields. + */ + + for (cp = spwbuf, i = 0;*cp && i < FIELDS;i++) { + fields[i] = cp; + while (*cp && *cp != ':') + cp++; + + if (*cp) + *cp++ = '\0'; + } + + /* + * It is acceptable for the last SVR4 field to be blank. This + * results in the loop being terminated early. In which case, + * we just make the last field be blank and be done with it. + */ + + if (i == (FIELDS-1)) + fields[i++] = cp; + + if ((cp && *cp) || (i != FIELDS && i != OFIELDS)) + return 0; + + /* + * Start populating the structure. The fields are all in + * static storage, as is the structure we pass back. If we + * ever see a name with '+' as the first character, we try + * to turn on NIS processing. + */ + + spwd.sp_namp = fields[0]; +#ifdef USE_NIS + if (IS_NISCHAR (fields[0][0])) + nis_used = 1; +#endif + spwd.sp_pwdp = fields[1]; + + /* + * Get the last changed date. For all of the integer fields, + * we check for proper format. It is an error to have an + * incorrectly formatted number, unless we are using NIS. + */ + + if ((spwd.sp_lstchg = strtol (fields[2], &cpp, 10)) == 0 && *cpp) { +#ifdef USE_NIS + if (! nis_used) + return 0; + else + spwd.sp_lstchg = -1; +#else + return 0; +#endif + } else if (fields[2][0] == '\0') + spwd.sp_lstchg = -1; + + /* + * Get the minimum period between password changes. + */ + + if ((spwd.sp_min = strtol (fields[3], &cpp, 10)) == 0 && *cpp) { +#ifdef USE_NIS + if (! nis_used) + return 0; + else + spwd.sp_min = -1; +#else + return 0; +#endif + } else if (fields[3][0] == '\0') + spwd.sp_min = -1; + + /* + * Get the maximum number of days a password is valid. + */ + + if ((spwd.sp_max = strtol (fields[4], &cpp, 10)) == 0 && *cpp) { +#ifdef USE_NIS + if (! nis_used) + return 0; + else + spwd.sp_max = -1; +#else + return 0; +#endif + } else if (fields[4][0] == '\0') + spwd.sp_max = -1; + + /* + * If there are only OFIELDS fields (this is a SVR3.2 /etc/shadow + * formatted file), initialize the other field members to -1. + */ + +#if 0 /* SVR4 */ + if (i == OFIELDS) + return 0; +#else + if (i == OFIELDS) { + spwd.sp_warn = spwd.sp_inact = spwd.sp_expire = + spwd.sp_flag = -1; + + return &spwd; + } +#endif + + /* + * The rest of the fields are mandatory for SVR4, but optional + * for anything else. However, if one is present the others + * must be as well. + */ + + /* + * Get the number of days of password expiry warning. + */ + + if ((spwd.sp_warn = strtol (fields[5], &cpp, 10)) == 0 && *cpp) { +#ifdef USE_NIS + if (! nis_used) + return 0; + else + spwd.sp_warn = -1; +#else + return 0; +#endif + } else if (fields[5][0] == '\0') + spwd.sp_warn = -1; + + /* + * Get the number of days of inactivity before an account is + * disabled. + */ + + if ((spwd.sp_inact = strtol (fields[6], &cpp, 10)) == 0 && *cpp) { +#ifdef USE_NIS + if (! nis_used) + return 0; + else + spwd.sp_inact = -1; +#else + return 0; +#endif + } else if (fields[6][0] == '\0') + spwd.sp_inact = -1; + + /* + * Get the number of days after the epoch before the account is + * set to expire. + */ + + if ((spwd.sp_expire = strtol (fields[7], &cpp, 10)) == 0 && *cpp) { +#ifdef USE_NIS + if (! nis_used) + return 0; + else + spwd.sp_expire = -1; +#else + return 0; +#endif + } else if (fields[7][0] == '\0') + spwd.sp_expire = -1; + + /* + * This field is reserved for future use. But it isn't supposed + * to have anything other than a valid integer in it. + */ + + if ((spwd.sp_flag = strtol (fields[8], &cpp, 10)) == 0 && *cpp) { +#ifdef USE_NIS + if (! nis_used) + return 0; + else + spwd.sp_flag = -1; +#else + return 0; +#endif + } else if (fields[8][0] == '\0') + spwd.sp_flag = -1; + + return (&spwd); +} + +/* + * fgetspent - get an entry from a /etc/shadow formatted stream + */ + +struct spwd * +fgetspent(FILE *fp) +{ + char buf[BUFSIZ]; + char *cp; + + if (! fp) + return (0); + +#ifdef USE_NIS + while (fgets (buf, sizeof buf, fp) != (char *) 0) +#else + if (fgets (buf, sizeof buf, fp) != (char *) 0) +#endif + { + if ((cp = strchr (buf, '\n'))) + *cp = '\0'; +#ifdef USE_NIS + if (nis_ignore && IS_NISCHAR (buf[0])) + continue; +#endif + return my_sgetspent(buf); + } + return 0; +} + +/* + * getspent - get a (struct spwd *) from the current shadow file + */ + +struct spwd * +getspent(void) +{ +#ifdef USE_NIS + int nis_1_user = 0; + struct spwd *val; + char buf[BUFSIZ]; +#endif + if (! shadow) + setspent (); + +#ifdef USE_NIS +again: + /* + * See if we are reading from the local file. + */ + + if (nis_state == native || nis_state == native2) { + + /* + * Get the next entry from the shadow file. Return NULL + * right away if there is none. + */ + + if (! (val = fgetspent (shadow))) + return 0; + + /* + * If this entry began with a NIS escape character, we have + * to see if this is just a single user, or if the entire + * map is being asked for. + */ + + if (IS_NISCHAR (val->sp_namp[0])) { + if (val->sp_namp[1]) + nis_1_user = 1; + else + nis_state = start; + } + + /* + * If this isn't a NIS user and this isn't an escape to go + * use a NIS map, it must be a regular local user. + */ + + if (nis_1_user == 0 && nis_state != start) + return val; + + /* + * If this is an escape to use an NIS map, switch over to + * that bunch of code. + */ + + if (nis_state == start) + goto again; + + /* + * NEEDSWORK. Here we substitute pieces-parts of this entry. + */ + + return 0; + } else { + if (nis_bound == 0) { + if (bind_nis ()) { + nis_state = native2; + goto again; + } + } + if (nis_state == start) { + if (yp_first (nis_domain, "shadow.bynam", &nis_key, + &nis_keylen, &nis_val, &nis_vallen)) { + nis_state = native2; + goto again; + } + nis_state = middle; + } else if (nis_state == middle) { + if (yp_next (nis_domain, "shadow.bynam", nis_key, + nis_keylen, &nis_key, &nis_keylen, + &nis_val, &nis_vallen)) { + nis_state = native2; + goto again; + } + } + return my_sgetspent(nis_val); + } +#else + return (fgetspent (shadow)); +#endif +} + +/* + * getspnam - get a shadow entry by name + */ + +struct spwd * +getspnam(const char *name) +{ + struct spwd *sp; +#ifdef NDBM + datum key; + datum content; +#endif +#ifdef USE_NIS + char buf[BUFSIZ]; + static char save_name[16]; + int nis_disabled = 0; +#endif + + setspent (); + +#ifdef NDBM + + /* + * If the DBM file are now open, create a key for this UID and + * try to fetch the entry from the database. A matching record + * will be unpacked into a static structure and returned to + * the user. + */ + + if (dbmopened) { + key.dsize = strlen (name); + key.dptr = (char *) name; + + content = dbm_fetch (sp_dbm, key); + if (content.dptr != 0) { + memcpy (spwbuf, content.dptr, content.dsize); + spw_unpack (spwbuf, content.dsize, &spwd); + endspent(); + return &spwd; + } + } +#endif +#ifdef USE_NIS + /* + * Search the shadow.byname map for this user. + */ + + if (! nis_ignore && ! nis_bound) + bind_nis (); + + if (! nis_ignore && nis_bound) { + char *cp; + + if (yp_match (nis_domain, "shadow.byname", name, + strlen (name), &nis_val, &nis_vallen) == 0) { + + if (cp = strchr (nis_val, '\n')) + *cp = '\0'; + + nis_state = middle; + if ((sp = my_sgetspent(nis_val))) { + strcpy (save_name, sp->sp_namp); + nis_key = save_name; + nis_keylen = strlen (save_name); + } + endspent(); + return sp; + } else + nis_state = native2; + } +#endif +#ifdef USE_NIS + /* + * NEEDSWORK -- this is a mess, and it is the same mess in the + * other three files. I can't just blindly turn off NIS because + * this might be the first pass through the local files. In + * that case, I never discover that NIS is present. + */ + + if (nis_used) { + nis_ignore++; + nis_disabled++; + } +#endif + while ((sp = getspent ()) != (struct spwd *) 0) { + if (strcmp (name, sp->sp_namp) == 0) + break; + } +#ifdef USE_NIS + if (nis_disabled) + nis_ignore--; +#endif + endspent(); + return (sp); +} +#else +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif /*}*/ diff --git a/lib/shadow_.h b/lib/shadow_.h new file mode 100644 index 00000000..ebb43802 --- /dev/null +++ b/lib/shadow_.h @@ -0,0 +1,89 @@ +/* + * Copyright 1988 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _H_SHADOW +#define _H_SHADOW + +/* + * This information is not derived from AT&T licensed sources. Posted + * to the USENET 11/88, and updated 11/90 with information from SVR4. + * + * $Id: shadow_.h,v 1.2 1997/05/01 23:14:48 marekm Exp $ + */ + +#ifdef ITI_AGING +typedef time_t sptime; +#else +typedef long sptime; +#endif + +/* + * Shadow password security file structure. + */ + +struct spwd { + char *sp_namp; /* login name */ + char *sp_pwdp; /* encrypted password */ + sptime sp_lstchg; /* date of last change */ + sptime sp_min; /* minimum number of days between changes */ + sptime sp_max; /* maximum number of days between changes */ + sptime sp_warn; /* number of days of warning before password + expires */ + sptime sp_inact; /* number of days after password expires + until the account becomes unusable. */ + sptime sp_expire; /* days since 1/1/70 until account expires */ + unsigned long sp_flag; /* reserved for future use */ +}; + +/* + * Shadow password security file functions. + */ + +#include /* for FILE */ + +#if defined(__STDC__) +struct spwd *getspent (void); +struct spwd *getspnam (const char *); +struct spwd *sgetspent (const char *); +struct spwd *fgetspent (FILE *); +void setspent (void); +void endspent (void); +int putspent (const struct spwd *, FILE *); +#else +struct spwd *getspent (); +struct spwd *getspnam (); +struct spwd *sgetspent (); +struct spwd *fgetspent (); +void setspent (); +void endspent (); +int putspent (); +#endif + +#define SHADOW "/etc/shadow" +#endif diff --git a/lib/shadowio.c b/lib/shadowio.c new file mode 100644 index 00000000..4575b2bb --- /dev/null +++ b/lib/shadowio.c @@ -0,0 +1,172 @@ + +#include + +#ifdef SHADOWPWD + +#include "rcsid.h" +RCSID("$Id: shadowio.c,v 1.11 1998/01/29 23:22:32 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#ifdef HAVE_SHADOW_H +# include +#endif +#include + +#include "commonio.h" +#include "shadowio.h" + +struct spwd * +__spw_dup(const struct spwd *spent) +{ + struct spwd *sp; + + if (!(sp = (struct spwd *) malloc(sizeof *sp))) + return NULL; + *sp = *spent; + if (!(sp->sp_namp = strdup(spent->sp_namp))) + return NULL; + if (!(sp->sp_pwdp = strdup(spent->sp_pwdp))) + return NULL; + return sp; +} + +static void * +shadow_dup(const void *ent) +{ + const struct spwd *sp = ent; + return __spw_dup(sp); +} + +static void +shadow_free(void *ent) +{ + struct spwd *sp = ent; + + free(sp->sp_namp); + free(sp->sp_pwdp); + free(sp); +} + +static const char * +shadow_getname(const void *ent) +{ + const struct spwd *sp = ent; + return sp->sp_namp; +} + +static void * +shadow_parse(const char *line) +{ + return (void *) sgetspent(line); +} + +static int +shadow_put(const void *ent, FILE *file) +{ + const struct spwd *sp = ent; + return (putspent(sp, file) == -1) ? -1 : 0; +} + +static struct commonio_ops shadow_ops = { + shadow_dup, + shadow_free, + shadow_getname, + shadow_parse, + shadow_put, + fgets, + fputs +}; + +static struct commonio_db shadow_db = { + SHADOW_FILE, /* filename */ + &shadow_ops, /* ops */ + NULL, /* fp */ + NULL, /* head */ + NULL, /* tail */ + NULL, /* cursor */ + 0, /* changed */ + 0, /* isopen */ + 0, /* locked */ + 0, /* readonly */ + 1 /* use_lckpwdf */ +}; + +int +spw_name(const char *filename) +{ + return commonio_setname(&shadow_db, filename); +} + +int +spw_file_present(void) +{ + return commonio_present(&shadow_db); +} + +int +spw_lock(void) +{ + return commonio_lock(&shadow_db); +} + +int +spw_open(int mode) +{ + return commonio_open(&shadow_db, mode); +} + +const struct spwd * +spw_locate(const char *name) +{ + return commonio_locate(&shadow_db, name); +} + +int +spw_update(const struct spwd *sp) +{ + return commonio_update(&shadow_db, (const void *) sp); +} + +int +spw_remove(const char *name) +{ + return commonio_remove(&shadow_db, name); +} + +int +spw_rewind(void) +{ + return commonio_rewind(&shadow_db); +} + +const struct spwd * +spw_next(void) +{ + return commonio_next(&shadow_db); +} + +int +spw_close(void) +{ + return commonio_close(&shadow_db); +} + +int +spw_unlock(void) +{ + return commonio_unlock(&shadow_db); +} + +struct commonio_entry * +__spw_get_head(void) +{ + return shadow_db.head; +} + +void +__spw_del_entry(const struct commonio_entry *ent) +{ + commonio_del_entry(&shadow_db, ent); +} +#endif diff --git a/lib/shadowio.h b/lib/shadowio.h new file mode 100644 index 00000000..5c8934f6 --- /dev/null +++ b/lib/shadowio.h @@ -0,0 +1,13 @@ +extern struct spwd *__spw_dup P_((const struct spwd *)); +extern void __spw_set_changed P_((void)); +extern int spw_close P_((void)); +extern int spw_file_present P_((void)); +extern const struct spwd *spw_locate P_((const char *)); +extern int spw_lock P_((void)); +extern int spw_name P_((const char *)); +extern const struct spwd *spw_next P_((void)); +extern int spw_open P_((int)); +extern int spw_remove P_((const char *)); +extern int spw_rewind P_((void)); +extern int spw_unlock P_((void)); +extern int spw_update P_((const struct spwd *)); diff --git a/lib/snprintf.c b/lib/snprintf.c new file mode 100644 index 00000000..c62366d9 --- /dev/null +++ b/lib/snprintf.c @@ -0,0 +1,320 @@ +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + **************************************************************/ + +/* $XFree86: xc/lib/misc/snprintf.c,v 3.0 1996/08/26 06:19:23 dawes Exp $ */ + +#include +#include "snprintf.h" + +static void dopr(); +static char *end; + +/* varargs declarations: */ + +#if defined(HAVE_STDARG_H) +# include +# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ +# define VA_LOCAL_DECL va_list ap; +# define VA_START(f) va_start(ap, f) +# define VA_SHIFT(v,t) ; /* no-op for ANSI */ +# define VA_END va_end(ap) +#else +# if defined(HAVE_VARARGS_H) +# include +# undef HAVE_STDARGS +# define VA_LOCAL_DECL va_list ap; +# define VA_START(f) va_start(ap) /* f is ignored! */ +# define VA_SHIFT(v,t) v = va_arg(ap,t) +# define VA_END va_end(ap) +# else +/*XX ** NO VARARGS ** XX*/ +# endif +#endif + +#ifdef HAVE_STDARGS +int snprintf (char *str, size_t count, const char *fmt, ...); +int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#else +int snprintf (); +int vsnprintf (); +#endif + +int +vsnprintf(str, count, fmt, args) + char *str; + size_t count; + const char *fmt; + va_list args; +{ + str[0] = 0; + end = str+count-1; + dopr( str, fmt, args ); + if( count>0 ){ + end[0] = 0; + } + return(strlen(str)); +} + +/* VARARGS3 */ +#ifdef HAVE_STDARGS +int +snprintf (char *str,size_t count,const char *fmt,...) +#else +int +snprintf (va_alist) va_dcl +#endif +{ +#ifndef HAVE_STDARGS + char *str; + size_t count; + char *fmt; +#endif + VA_LOCAL_DECL + + VA_START (fmt); + VA_SHIFT (str, char *); + VA_SHIFT (count, size_t ); + VA_SHIFT (fmt, char *); + (void) vsnprintf ( str, count, fmt, ap); + VA_END; + return( strlen( str ) ); +} + +/* + * dopr(): poor man's version of doprintf + */ + +static void fmtstr( +#if NeedFunctionPrototypes + char *value, int ljust, int len, int zpad +#endif +); + +static void fmtnum( +#if NeedFunctionPrototypes + long value, int base, int dosign, int ljust, int len, int zpad +#endif +); + +static void dostr( +#if NeedFunctionPrototypes + char * +#endif +); + +static char *output; + +static void dopr_outch( +#if NeedFunctionPrototypes + int c +#endif +); + +static void +dopr( buffer, format, args ) + char *buffer; + char *format; + va_list args; +{ + int ch; + long value; + int longflag = 0; + char *strvalue; + int ljust; + int len; + int zpad; + + output = buffer; + while( (ch = *format++) ){ + switch( ch ){ + case '%': + ljust = len = zpad = 0; + nextch: + ch = *format++; + switch( ch ){ + case 0: + dostr( "**end of format**" ); + return; + case '-': ljust = 1; goto nextch; + case '0': /* set zero padding if len not set */ + if(len==0) zpad = '0'; + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + len = len*10 + ch - '0'; + goto nextch; + case 'l': longflag = 1; goto nextch; + case 'u': case 'U': + /*fmtnum(value,base,dosign,ljust,len,zpad) */ + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 10,0, ljust, len, zpad ); break; + case 'o': case 'O': + /*fmtnum(value,base,dosign,ljust,len,zpad) */ + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 8,0, ljust, len, zpad ); break; + case 'd': case 'D': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 10,1, ljust, len, zpad ); break; + case 'x': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 16,0, ljust, len, zpad ); break; + case 'X': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value,-16,0, ljust, len, zpad ); break; + case 's': + strvalue = va_arg( args, char *); + fmtstr( strvalue,ljust,len,zpad ); break; + case 'c': + ch = va_arg( args, int ); + dopr_outch( ch ); break; + case '%': dopr_outch( ch ); continue; + default: + dostr( "???????" ); + } + longflag = 0; + break; + default: + dopr_outch( ch ); + break; + } + } + *output = 0; +} + +static void +fmtstr( value, ljust, len, zpad ) + char *value; + int ljust, len, zpad; +{ + int padlen, strlen; /* amount to pad */ + + if( value == 0 ){ + value = ""; + } + for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */ + padlen = len - strlen; + if( padlen < 0 ) padlen = 0; + if( ljust ) padlen = -padlen; + while( padlen > 0 ) { + dopr_outch( ' ' ); + --padlen; + } + dostr( value ); + while( padlen < 0 ) { + dopr_outch( ' ' ); + ++padlen; + } +} + +static void +fmtnum( value, base, dosign, ljust, len, zpad ) + long value; + int base, dosign, ljust, len, zpad; +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int padlen = 0; /* amount to pad */ + int caps = 0; + + /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", + value, base, dosign, ljust, len, zpad )); */ + uvalue = value; + if( dosign ){ + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } + } + if( base < 0 ){ + caps = 1; + base = -base; + } + do{ + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + }while(uvalue); + convert[place] = 0; + padlen = len - place; + if( padlen < 0 ) padlen = 0; + if( ljust ) padlen = -padlen; + /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n", + convert,place,signvalue,padlen)); */ + if( zpad && padlen > 0 ){ + if( signvalue ){ + dopr_outch( signvalue ); + --padlen; + signvalue = 0; + } + while( padlen > 0 ){ + dopr_outch( zpad ); + --padlen; + } + } + while( padlen > 0 ) { + dopr_outch( ' ' ); + --padlen; + } + if( signvalue ) dopr_outch( signvalue ); + while( place > 0 ) dopr_outch( convert[--place] ); + while( padlen < 0 ){ + dopr_outch( ' ' ); + ++padlen; + } +} + +static void +dostr( str ) + char *str; +{ + while(*str) dopr_outch(*str++); +} + +static void +dopr_outch( c ) + int c; +{ + if( iscntrl(c) && c != '\n' && c != '\t' ){ + c = '@' + (c & 0x1F); + if( end == 0 || output < end ){ + *output++ = '^'; + } + } + if( end == 0 || output < end ){ + *output++ = c; + } +} diff --git a/lib/snprintf.h b/lib/snprintf.h new file mode 100644 index 00000000..e900e31e --- /dev/null +++ b/lib/snprintf.h @@ -0,0 +1,51 @@ +/* $XFree86: xc/lib/misc/snprintf.h,v 3.1 1996/08/26 14:42:33 dawes Exp $ */ + +#ifndef SNPRINTF_H +#define SNPRINTF_H + +#ifdef HAS_SNPRINTF +#ifdef LIBXT +#define _XtSnprintf snprintf +#define _XtVsnprintf vsnprintf +#endif +#ifdef LIBX11 +#define _XSnprintf snprintf +#define _XVsnprintf vsnprintf +#endif +#else /* !HAS_SNPRINTF */ + +#ifdef LIBXT +#define snprintf _XtSnprintf +#define vsnprintf _XtVsnprintf +#endif +#ifdef LIBX11 +#define snprintf _XSnprintf +#define vsnprintf _XVsnprintf +#endif + +#if 1 /* the system might have no X11 headers. -MM */ +#include +#include +#else /* but we still need this... */ +#include +/* adjust the following defines if necessary (pre-ANSI) */ +#define NeedFunctionPrototypes 1 +#define NeedVarargsPrototypes 1 +#endif + +#if NeedVarargsPrototypes +#define HAVE_STDARG_H +#endif + +#ifdef HAVE_STDARG_H +#include +extern int snprintf (char *str, size_t count, const char *fmt, ...); +extern int vsnprintf (char *str, size_t count, const char *fmt, va_list arg); +#else +extern int snprintf (); +extern int vsnprintf (); +#endif + +#endif /* HAS_SNPRINTF */ + +#endif /* SNPRINTF_H */ diff --git a/lib/spdbm.c b/lib/spdbm.c new file mode 100644 index 00000000..317ea6b7 --- /dev/null +++ b/lib/spdbm.c @@ -0,0 +1,116 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#if defined(SHADOWPWD) && defined(NDBM) /*{*/ + +#include "rcsid.h" +RCSID("$Id: spdbm.c,v 1.3 1997/12/07 23:26:58 marekm Exp $") + +#include +#include +#include "prototypes.h" +#include "defines.h" + +#include +extern DBM *sp_dbm; + +/* + * sp_dbm_update + * + * Updates the DBM password files, if they exist. + */ + +int +sp_dbm_update(struct spwd *sp) +{ + datum key; + datum content; + char data[BUFSIZ]; + int len; + static int once; + + if (! once) { + if (! sp_dbm) + setspent (); + + once++; + } + if (! sp_dbm) + return 0; + + len = spw_pack (sp, data); + + content.dsize = len; + content.dptr = data; + + key.dsize = strlen (sp->sp_namp); + key.dptr = sp->sp_namp; + if (dbm_store (sp_dbm, key, content, DBM_REPLACE)) + return 0; + + return 1; +} + +/* + * sp_dbm_remove + * + * Updates the DBM password files, if they exist. + */ + +int +sp_dbm_remove(char *user) +{ + datum key; + static int once; + + if (! once) { + if (! sp_dbm) + setspent (); + + once++; + } + if (! sp_dbm) + return 0; + + key.dsize = strlen (user); + key.dptr = user; + if (dbm_delete (sp_dbm, key)) + return 0; + + return 1; +} + +int +sp_dbm_present(void) +{ + return (access(SHADOW_PAG_FILE, F_OK) == 0); +} +#endif /*} SHADOWPWD && NDBM */ diff --git a/lib/sppack.c b/lib/sppack.c new file mode 100644 index 00000000..463f633a --- /dev/null +++ b/lib/sppack.c @@ -0,0 +1,113 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifdef SHADOWPWD /*{*/ + +#include "rcsid.h" +RCSID("$Id: sppack.c,v 1.3 1997/12/07 23:26:58 marekm Exp $") + +#include +#include +#include "defines.h" + +int +spw_pack(const struct spwd *spwd, char *buf) +{ + char *cp; + + cp = buf; + strcpy (cp, spwd->sp_namp); + cp += strlen (cp) + 1; + + strcpy (cp, spwd->sp_pwdp); + cp += strlen (cp) + 1; + + memcpy (cp, &spwd->sp_min, sizeof spwd->sp_min); + cp += sizeof spwd->sp_min; + + memcpy (cp, &spwd->sp_max, sizeof spwd->sp_max); + cp += sizeof spwd->sp_max; + + memcpy (cp, &spwd->sp_lstchg, sizeof spwd->sp_lstchg); + cp += sizeof spwd->sp_lstchg; + + memcpy (cp, &spwd->sp_warn, sizeof spwd->sp_warn); + cp += sizeof spwd->sp_warn; + + memcpy (cp, &spwd->sp_inact, sizeof spwd->sp_inact); + cp += sizeof spwd->sp_inact; + + memcpy (cp, &spwd->sp_expire, sizeof spwd->sp_expire); + cp += sizeof spwd->sp_expire; + + memcpy (cp, &spwd->sp_flag, sizeof spwd->sp_flag); + cp += sizeof spwd->sp_flag; + + return cp - buf; +} + +int +spw_unpack(char *buf, int len, struct spwd *spwd) +{ + char *org = buf; + + spwd->sp_namp = buf; + buf += strlen (buf) + 1; + + spwd->sp_pwdp = buf; + buf += strlen (buf) + 1; + + memcpy (&spwd->sp_min, buf, sizeof spwd->sp_min); + buf += sizeof spwd->sp_min; + + memcpy (&spwd->sp_max, buf, sizeof spwd->sp_max); + buf += sizeof spwd->sp_max; + + memcpy (&spwd->sp_lstchg, buf, sizeof spwd->sp_lstchg); + buf += sizeof spwd->sp_lstchg; + + memcpy (&spwd->sp_warn, buf, sizeof spwd->sp_warn); + buf += sizeof spwd->sp_warn; + + memcpy (&spwd->sp_inact, buf, sizeof spwd->sp_inact); + buf += sizeof spwd->sp_inact; + + memcpy (&spwd->sp_expire, buf, sizeof spwd->sp_expire); + buf += sizeof spwd->sp_expire; + + memcpy (&spwd->sp_flag, buf, sizeof spwd->sp_flag); + buf += sizeof spwd->sp_flag; + + if (buf - org > len) + return -1; + + return 0; +} +#endif /*}*/ diff --git a/lib/strcasecmp.c b/lib/strcasecmp.c new file mode 100644 index 00000000..414a47aa --- /dev/null +++ b/lib/strcasecmp.c @@ -0,0 +1,25 @@ +#include +#include "defines.h" +#include + +#include "rcsid.h" +RCSID("$Id: strcasecmp.c,v 1.1 1999/07/09 18:02:43 marekm Exp $") + +/* + * strcasecmp - compare strings, ignoring case + */ + +char * +strcasecmp(const char *s1, const char *s2) +{ + int ret; + + for (;;) { + ret = tolower(*s1) - tolower(*s2); + if (ret || *s1 == '\0' || *s2 == '\0') + break; + s1++; + s2++; + } + return ret; +} diff --git a/lib/strdup.c b/lib/strdup.c new file mode 100644 index 00000000..fe522b45 --- /dev/null +++ b/lib/strdup.c @@ -0,0 +1,16 @@ +#include +#include "defines.h" +#include "rcsid.h" +RCSID("$Id: strdup.c,v 1.2 1997/12/07 23:26:59 marekm Exp $") + +extern char *malloc(); + +char * +strdup(const char *str) +{ + char *s = malloc(strlen(str) + 1); + + if (s) + strcpy(s, str); + return s; +} diff --git a/lib/strerror.c b/lib/strerror.c new file mode 100644 index 00000000..184b1a46 --- /dev/null +++ b/lib/strerror.c @@ -0,0 +1,23 @@ +#include +#include +#include "defines.h" +#include "rcsid.h" +RCSID("$Id: strerror.c,v 1.3 1998/12/28 20:34:39 marekm Exp $") + +#include + +extern int sys_nerr; +extern char *sys_errlist[]; + +char * +strerror(int err) +{ + static char unknown[80]; + + if (err >= 0 && err < sys_nerr) + return sys_errlist[err]; + + snprintf(unknown, sizeof unknown, _("Unknown error %d"), err); + errno = EINVAL; + return unknown; +} diff --git a/lib/strstr.c b/lib/strstr.c new file mode 100644 index 00000000..b4fca453 --- /dev/null +++ b/lib/strstr.c @@ -0,0 +1,55 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "defines.h" + +#include "rcsid.h" +RCSID("$Id: strstr.c,v 1.4 1998/01/29 23:22:32 marekm Exp $") + +/* + * strstr - find substring in string + */ + +char * +strstr(const char *string, const char *pattern) +{ + char *cp; + int len; + + len = strlen (pattern); + + for (cp = string;cp = strchr (cp, *pattern);) { + if (strncmp (cp, pattern, len) == 0) + return cp; + + cp++; + } + return 0; +} diff --git a/lib/tcfsio.c b/lib/tcfsio.c new file mode 100644 index 00000000..2649e0be --- /dev/null +++ b/lib/tcfsio.c @@ -0,0 +1,90 @@ + +#include + +#ifdef HAVE_TCFS + +#include "prototypes.h" +#include "defines.h" + +#ifdef TCFS_GDBM_SUPPORT +#undef GDBM_SUPPORT +#define GDBM_SUPPORT +#endif + +#include +#include + +#include "commonio.h" +#include "tcfsio.h" + +static struct commonio_db tcfs_db = { + TCFSPWDFILE, /* filename */ + NULL, /* ops */ + NULL, + NULL, + NULL, + NULL, + 0, + 0, + 0, + 0, + 1 +}; + +int +tcfs_file_present(void) +{ + return commonio_present(&tcfs_db); +} + +int +tcfs_lock(void) +{ + return commonio_lock(&tcfs_db); +} + +int +tcfs_open(int mode) +{ + return 1; +/* return tcfs_open(); */ +} + +tcfspwdb * +tcfs_locate(char *name) +{ + return tcfs_getpwnam(name, NULL); +} + +int +tcfs_update(char *user, struct tcfspwd *tcfspword) +{ + char *o, *p; + + o=(char*)calloc(128,sizeof(char)); + p=(char*)calloc(128,sizeof(char)); + strcpy (o, tcfspword->tcfsorig); + strcpy (p, tcfspword->tcfspass); + return tcfs_chgkey(user,o,p); +} + +int +tcfs_remove(char *name) +{ + return tcfs_putpwnam(name, NULL, U_DEL); +} + +int +tcfs_close(void) +{ + return 1; +/* return tcfs_close(&shadow_db); */ +} + +int +tcfs_unlock(void) +{ + return commonio_unlock(&tcfs_db); +} + +#endif diff --git a/lib/tcfsio.h b/lib/tcfsio.h new file mode 100644 index 00000000..3a8ff6c5 --- /dev/null +++ b/lib/tcfsio.h @@ -0,0 +1,14 @@ +struct tcfspwd { + char tcfspass[200]; /* new password */ + char tcfsorig[200]; /* old password */ +}; + +extern int tcfs_close P_((void)); +extern int tcfs_file_present P_((void)); +extern tcfspwdb *tcfs_locate P_((char *)); +extern int tcfs_lock P_((void)); +extern int tcfs_name P_((char *)); +extern int tcfs_open P_((int)); +extern int tcfs_remove P_((char *)); +extern int tcfs_unlock P_((void)); +extern int tcfs_update P_((char *, struct tcfspwd *)); diff --git a/lib/utent.c b/lib/utent.c new file mode 100644 index 00000000..0b14d14c --- /dev/null +++ b/lib/utent.c @@ -0,0 +1,114 @@ +/* + * Copyright 1993 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef HAVE_GETUTENT + +#include "defines.h" +#include +#include +#include + +#ifndef lint +static char rcsid[] = "$Id: utent.c,v 1.4 1998/01/29 23:22:32 marekm Exp $"; +#endif + +static int utmp_fd = -1; +static struct utmp utmp_buf; + +/* + * setutent - open or rewind the utmp file + */ + +void +setutent(void) +{ + if (utmp_fd == -1) + if ((utmp_fd = open (_UTMP_FILE, O_RDWR)) == -1) + utmp_fd = open (_UTMP_FILE, O_RDONLY); + + if (utmp_fd != -1) + lseek (utmp_fd, (off_t) 0L, SEEK_SET); +} + +/* + * endutent - close the utmp file + */ + +void +endutent(void) +{ + if (utmp_fd != -1) + close (utmp_fd); + + utmp_fd = -1; +} + +/* + * getutent - get the next record from the utmp file + */ + +struct utmp * +getutent(void) +{ + if (utmp_fd == -1) + setutent (); + + if (utmp_fd == -1) + return 0; + + if (read (utmp_fd, &utmp_buf, sizeof utmp_buf) != sizeof utmp_buf) + return 0; + + return &utmp_buf; +} + +/* + * getutline - get the utmp entry matching ut_line + */ + +struct utmp * +getutline(const struct utmp *utent) +{ + struct utmp save; + struct utmp *new; + + save = *utent; + while (new = getutent ()) + if (strncmp (new->ut_line, save.ut_line, sizeof new->ut_line)) + continue; + else + return new; + + return (struct utmp *) 0; +} +#else +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am new file mode 100644 index 00000000..21fe04cd --- /dev/null +++ b/libmisc/Makefile.am @@ -0,0 +1,20 @@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +noinst_HEADERS = chkname.h failure.h getdate.h + +noinst_LIBRARIES = libmisc.a + +libdir = $(prefix)/lib +localedir = $(datadir)/locale +INCLUDES = -I$(top_srcdir)/libmisc -I$(top_srcdir)/lib +DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@ + +libmisc_a_SOURCES = addgrps.c age.c basename.c chkname.c chkshell.c \ + chowndir.c chowntty.c console.c copydir.c entry.c env.c failure.c \ + fields.c getdate.y hushed.c isexpired.c limits.c list.c log.c \ + login_access.c login_desrpc.c login_krb.c loginprompt.c mail.c motd.c \ + myname.c obscure.c pam_pass.c pwd2spwd.c pwdcheck.c pwd_init.c rlogin.c \ + salt.c setugid.c setup.c setupenv.c shell.c strtoday.c suauth.c sub.c \ + sulog.c ttytype.c tz.c ulimit.c utmp.c valid.c xmalloc.c + diff --git a/libmisc/Makefile.in b/libmisc/Makefile.in new file mode 100644 index 00000000..edac7d4c --- /dev/null +++ b/libmisc/Makefile.in @@ -0,0 +1,418 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +noinst_HEADERS = chkname.h failure.h getdate.h + +noinst_LIBRARIES = libmisc.a + +libdir = $(prefix)/lib +localedir = $(datadir)/locale +INCLUDES = -I$(top_srcdir)/libmisc -I$(top_srcdir)/lib +DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@ + +libmisc_a_SOURCES = addgrps.c age.c basename.c chkname.c chkshell.c \ + chowndir.c chowntty.c console.c copydir.c entry.c env.c failure.c \ + fields.c getdate.y hushed.c isexpired.c limits.c list.c log.c \ + login_access.c login_desrpc.c login_krb.c loginprompt.c mail.c motd.c \ + myname.c obscure.c pam_pass.c pwd2spwd.c pwdcheck.c pwd_init.c rlogin.c \ + salt.c setugid.c setup.c setupenv.c shell.c strtoday.c suauth.c sub.c \ + sulog.c ttytype.c tz.c ulimit.c utmp.c valid.c xmalloc.c +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libmisc_a_LIBADD = +libmisc_a_OBJECTS = addgrps.o age.o basename.o chkname.o chkshell.o \ +chowndir.o chowntty.o console.o copydir.o entry.o env.o failure.o \ +fields.o getdate.o hushed.o isexpired.o limits.o list.o log.o \ +login_access.o login_desrpc.o login_krb.o loginprompt.o mail.o motd.o \ +myname.o obscure.o pam_pass.o pwd2spwd.o pwdcheck.o pwd_init.o rlogin.o \ +salt.o setugid.o setup.o setupenv.o shell.o strtoday.o suauth.o sub.o \ +sulog.o ttytype.o tz.o ulimit.o utmp.o valid.o xmalloc.o +AR = ar +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@ +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = Makefile.am Makefile.in getdate.c + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +SOURCES = $(libmisc_a_SOURCES) +OBJECTS = $(libmisc_a_OBJECTS) + +all: Makefile $(LIBRARIES) $(HEADERS) + +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s .y +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps libmisc/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES) + -rm -f libmisc.a + $(AR) cru libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD) + $(RANLIB) libmisc.a +.y.c: + $(YACC) $(YFLAGS) $< && mv y.tab.c $*.c + if test -f y.tab.h; then \ + if cmp -s y.tab.h $*.h; then rm -f y.tab.h; else mv y.tab.h $*.h; fi; \ + else :; fi +getdate.h: getdate.c + + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = libmisc + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +addgrps.o: addgrps.c ../config.h ../lib/prototypes.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/rcsid.h +age.o: age.c ../config.h ../lib/prototypes.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/rcsid.h +basename.o: basename.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/prototypes.h +chkname.o: chkname.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h chkname.h +chkshell.o: chkshell.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +chowndir.o: chowndir.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +chowntty.o: chowntty.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +console.o: console.c ../config.h ../lib/defines.h ../lib/gshadow_.h \ + ../lib/getdef.h ../lib/rcsid.h +copydir.o: copydir.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +entry.o: entry.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +env.o: env.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +failure.o: failure.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/faillog.h ../lib/getdef.h failure.h +fields.o: fields.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +getdate.o: getdate.c ../config.h getdate.h ../lib/defines.h \ + ../lib/gshadow_.h +hushed.o: hushed.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/prototypes.h ../lib/getdef.h +isexpired.o: isexpired.c ../config.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/rcsid.h +limits.o: limits.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +list.o: list.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +login_access.o: login_access.c ../config.h ../lib/rcsid.h \ + ../lib/prototypes.h ../lib/defines.h ../lib/gshadow_.h +login_desrpc.o: login_desrpc.c ../config.h +login_krb.o: login_krb.c ../config.h +loginprompt.o: loginprompt.c ../config.h ../lib/rcsid.h \ + ../lib/prototypes.h ../lib/defines.h ../lib/gshadow_.h \ + ../lib/getdef.h +log.o: log.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h +mail.o: mail.c ../config.h ../lib/prototypes.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/getdef.h ../lib/rcsid.h +motd.o: motd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +myname.o: myname.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/prototypes.h +obscure.o: obscure.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +pam_pass.o: pam_pass.c ../config.h +pwd2spwd.o: pwd2spwd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +pwdcheck.o: pwdcheck.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwauth.h +pwd_init.o: pwd_init.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h +rlogin.o: rlogin.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +salt.o: salt.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +setugid.o: setugid.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +setupenv.o: setupenv.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +setup.o: setup.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +shell.o: shell.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +strtoday.o: strtoday.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h getdate.h +suauth.o: suauth.c ../config.h ../lib/prototypes.h ../lib/defines.h \ + ../lib/gshadow_.h +sub.o: sub.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +sulog.o: sulog.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/getdef.h +ttytype.o: ttytype.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +tz.o: tz.c ../config.h ../lib/rcsid.h ../lib/defines.h ../lib/gshadow_.h \ + ../lib/getdef.h +ulimit.o: ulimit.c ../config.h ../lib/rcsid.h +utmp.o: utmp.c ../config.h ../lib/defines.h ../lib/gshadow_.h \ + ../lib/rcsid.h +valid.o: valid.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +xmalloc.o: xmalloc.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h + +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags \ + mostlyclean-generic + +clean: clean-noinstLIBRARIES clean-compile clean-libtool clean-tags \ + clean-generic mostlyclean + +distclean: distclean-noinstLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-generic \ + clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-generic \ + distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile mostlyclean-libtool distclean-libtool \ +clean-libtool maintainer-clean-libtool tags mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info dvi \ +installcheck install-exec install-data install uninstall all \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libmisc/addgrps.c b/libmisc/addgrps.c new file mode 100644 index 00000000..589d295f --- /dev/null +++ b/libmisc/addgrps.c @@ -0,0 +1,89 @@ +#include + +#ifdef HAVE_SETGROUPS + +#include "prototypes.h" +#include "defines.h" + +#include +#include +#include + +#include "rcsid.h" +RCSID("$Id: addgrps.c,v 1.4 1998/12/28 20:34:41 marekm Exp $") + +#define SEP ",:" + +/* + * Add groups with names from LIST (separated by commas or colons) + * to the supplementary group set. Silently ignore groups which are + * already there. Warning: uses strtok(). + */ + +int +add_groups(const char *list) +{ + GETGROUPS_T *grouplist, *tmp; + int i, ngroups, added; + struct group *grp; + char *token; + char buf[1024]; + + if (strlen(list) >= sizeof(buf)) { + errno = EINVAL; + return -1; + } + strcpy(buf, list); + + i = 16; + for (;;) { + grouplist = malloc(i * sizeof(GETGROUPS_T)); + if (!grouplist) + return -1; + ngroups = getgroups(i, grouplist); + if (i > ngroups) + break; + /* not enough room, so try allocating a larger buffer */ + free(grouplist); + i *= 2; + } + if (ngroups < 0) { + free(grouplist); + return -1; + } + + added = 0; + for (token = strtok(buf, SEP); token; token = strtok(NULL, SEP)) { + + grp = getgrnam(token); + if (!grp) { + fprintf(stderr, _("Warning: unknown group %s\n"), token); + continue; + } + + for (i = 0; i < ngroups && grouplist[i] != grp->gr_gid; i++) + ; + + if (i < ngroups) + continue; + + if (ngroups >= NGROUPS_MAX) { + fprintf(stderr, _("Warning: too many groups\n")); + break; + } + tmp = realloc(grouplist, (ngroups + 1) * sizeof(GETGROUPS_T)); + if (!tmp) { + free(grouplist); + return -1; + } + tmp[ngroups++] = grp->gr_gid; + grouplist = tmp; + added++; + } + + if (added) + return setgroups(ngroups, grouplist); + + return 0; +} +#endif diff --git a/libmisc/age.c b/libmisc/age.c new file mode 100644 index 00000000..7d3b355f --- /dev/null +++ b/libmisc/age.c @@ -0,0 +1,235 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" +#include +#include +#ifdef HAVE_USERSEC_H +#include +#include +#include +#endif + +#ifndef AGING +#if defined(SHADOWPWD) || defined(HAVE_USERSEC_H) +#define AGING 1 +#endif +#else +#if !defined(SHADOWPWD) && !defined(HAVE_USERSEC_H) && !defined(ATT_AGE) +#undef AGING +#endif +#endif + +#if defined(SHADOWPWD) || defined(AGING) /*{*/ + +#include "rcsid.h" +RCSID("$Id: age.c,v 1.6 1998/12/28 20:34:42 marekm Exp $") + +#ifndef PASSWD_PROGRAM +#define PASSWD_PROGRAM "/bin/passwd" +#endif + +/* + * expire - force password change if password expired + * + * expire() calls /bin/passwd to change the user's password + * if it has expired. + */ + +#ifdef SHADOWPWD +int +expire(const struct passwd *pw, const struct spwd *sp) +{ +#else +int +expire(const struct passwd *pw) +{ +#endif + int status; + int child; + int pid; + +#ifdef SHADOWPWD + if (! sp) + sp = pwd_to_spwd (pw); +#endif + + /* + * See if the user's password has expired, and if so + * force them to change their password. + */ + +#ifdef SHADOWPWD + switch (status = isexpired (pw, sp)) +#else + switch (status = isexpired (pw)) +#endif + { + case 0: + return 0; + case 1: + printf(_("Your password has expired.")); + break; + case 2: + printf(_("Your password is inactive.")); + break; + case 3: + printf(_("Your login has expired.")); + break; + } + + /* + * Setting the maximum valid period to less than the minimum + * valid period means that the minimum period will never + * occur while the password is valid, so the user can never + * change that password. + */ + +#ifdef SHADOWPWD + if (status > 1 || sp->sp_max < sp->sp_min) +#else + if (status > 1 || c64i (pw->pw_age[0]) < c64i (pw->pw_age[1])) +#endif + { + puts(_(" Contact the system administrator.\n")); + exit(1); + } + puts(_(" Choose a new password.\n")); + fflush (stdout); + + /* + * Close all the files so that unauthorized access won't + * occur. This needs to be done anyway because those files + * might become stale after "passwd" is executed. + */ + +#ifdef SHADOWPWD + endspent (); +#endif + endpwent (); +#ifdef SHADOWGRP + endsgent (); +#endif + endgrent (); + + /* + * Execute the /bin/passwd command. The exit status will be + * examined to see what the result is. If there are any + * errors the routine will exit. This forces the user to + * change their password before being able to use the account. + */ + + if ((pid = fork ()) == 0) { + int err; + + /* + * Set the UID to be that of the user. This causes + * passwd to work just like it would had they executed + * it from the command line while logged in. + */ + if (setup_uid_gid(pw, 0)) + _exit(126); + + execl(PASSWD_PROGRAM, PASSWD_PROGRAM, pw->pw_name, (char *)0); + err = errno; + perror("Can't execute " PASSWD_PROGRAM); + _exit((err == ENOENT) ? 127 : 126); + } else if (pid == -1) { + perror("fork"); + exit(1); + } + while ((child = wait (&status)) != pid && child != -1) + ; + + if (child == pid && status == 0) + return 1; + + exit (1); + /*NOTREACHED*/ +} + +/* + * agecheck - see if warning is needed for password expiration + * + * agecheck sees how many days until the user's password is going + * to expire and warns the user of the pending password expiration. + */ + +#ifdef SHADOWPWD +void +agecheck(const struct passwd *pw, const struct spwd *sp) +{ +#else +void +agecheck(const struct passwd *pw) +{ +#endif + long now = time ((long *) 0) / SCALE; + long remain; + +#ifdef SHADOWPWD + if (! sp) + sp = pwd_to_spwd (pw); + + /* + * The last, max, and warn fields must be supported or the + * warning period cannot be calculated. + */ + + if (sp->sp_lstchg == -1 || sp->sp_max == -1 || sp->sp_warn == -1) + return; +#else + if (pw->pw_age[0] == '\0') + return; +#endif + +#ifdef SHADOWPWD + if ((remain = (sp->sp_lstchg + sp->sp_max) - now) <= sp->sp_warn) +#else + if ((remain = (a64l (pw->pw_age + 2) + c64i (pw->pw_age[0])) * 7 + - now) <= getdef_num ("PASS_WARN_AGE", 7)) +#endif + { + remain /= DAY/SCALE; + if (remain > 1) + printf(_("Your password will expire in %ld days.\n"), remain); + else if (remain == 1) + printf(_("Your password will expire tomorrow.\n")); + else if (remain == 0) + printf(_("Your password will expire today.\n")); + } +} +#endif /*}*/ diff --git a/libmisc/basename.c b/libmisc/basename.c new file mode 100644 index 00000000..caf3ccdd --- /dev/null +++ b/libmisc/basename.c @@ -0,0 +1,22 @@ +/* + * basename.c - not worth copyrighting :-). Some versions of Linux libc + * already have basename(), other versions don't. To avoid confusion, + * we will not use the function from libc and use a different name here. + * --marekm + */ + +#include + +#include "rcsid.h" +RCSID("$Id: basename.c,v 1.2 1997/12/07 23:27:00 marekm Exp $") + +#include "defines.h" +#include "prototypes.h" + +char * +Basename(char *str) +{ + char *cp = strrchr(str, '/'); + + return cp ? cp+1 : str; +} diff --git a/libmisc/chkname.c b/libmisc/chkname.c new file mode 100644 index 00000000..8e71d69a --- /dev/null +++ b/libmisc/chkname.c @@ -0,0 +1,73 @@ +/* + * check_user_name(), check_group_name() - check the new user/group + * name for validity; return value: 1 - OK, 0 - bad name + */ + +#include + +#include "rcsid.h" +RCSID("$Id: chkname.c,v 1.4 1998/04/16 19:57:43 marekm Exp $") + +#include +#include "defines.h" +#include "chkname.h" + +#if HAVE_UTMPX_H +#include +#else +#include +#endif + +static int +good_name(const char *name) +{ + /* + * User/group names must start with a letter, and may not + * contain colons, commas, newlines (used in passwd/group + * files...) or any non-printable characters. + */ + if (!*name || !isalpha(*name)) + return 0; + + while (*name) { + if (*name == ':' || *name == ',' || + *name == '\n' || !isprint(*name)) + return 0; + + name++; + } + + return 1; +} + +int +check_user_name(const char *name) +{ +#if HAVE_UTMPX_H + struct utmpx ut; +#else + struct utmp ut; +#endif + + /* + * User names are limited by whatever utmp can + * handle (usually max 8 characters). + */ + if (strlen(name) > sizeof(ut.ut_user)) + return 0; + + return good_name(name); +} + +int +check_group_name(const char *name) +{ + /* + * Arbitrary limit for group names - max 16 + * characters (same as on HP-UX 10). + */ + if (strlen(name) > 16) + return 0; + + return good_name(name); +} diff --git a/libmisc/chkname.h b/libmisc/chkname.h new file mode 100644 index 00000000..c706f15d --- /dev/null +++ b/libmisc/chkname.h @@ -0,0 +1,15 @@ +/* $Id: chkname.h,v 1.1 1997/12/07 23:27:00 marekm Exp $ */ +#ifndef _CHKNAME_H_ +#define _CHKNAME_H_ + +/* + * check_user_name(), check_group_name() - check the new user/group + * name for validity; return value: 1 - OK, 0 - bad name + */ + +#include "defines.h" + +extern int check_user_name P_((const char *)); +extern int check_group_name P_((const char *name)); + +#endif diff --git a/libmisc/chkshell.c b/libmisc/chkshell.c new file mode 100644 index 00000000..d2a45d6f --- /dev/null +++ b/libmisc/chkshell.c @@ -0,0 +1,98 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: chkshell.c,v 1.1 1997/12/07 23:27:00 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +#ifndef SHELLS_FILE +#define SHELLS_FILE "/etc/shells" +#endif + +/* + * check_shell - see if the user's login shell is listed in /etc/shells + * + * The /etc/shells file is read for valid names of login shells. If the + * /etc/shells file does not exist the user cannot set any shell unless + * they are root. + * + * If getusershell() is available (Linux, *BSD, possibly others), use it + * instead of re-implementing it. + */ + +int +check_shell(const char *sh) +{ + char *cp; + int found = 0; +#ifndef HAVE_GETUSERSHELL + char buf[BUFSIZ]; + FILE *fp; +#endif + +#ifdef HAVE_GETUSERSHELL + setusershell(); + while ((cp = getusershell())) { + if (*cp == '#') + continue; + + if (strcmp(cp, sh) == 0) { + found = 1; + break; + } + } + endusershell(); +#else + if ((fp = fopen (SHELLS_FILE, "r")) == (FILE *) 0) + return 0; + + while (fgets (buf, sizeof(buf), fp)) { + if ((cp = strrchr(buf, '\n'))) + *cp = '\0'; + + if (buf[0] == '#') + continue; + + if (strcmp (buf, sh) == 0) { + found = 1; + break; + } + } + fclose (fp); +#endif + return found; +} + diff --git a/libmisc/chowndir.c b/libmisc/chowndir.c new file mode 100644 index 00000000..b8fe4c0d --- /dev/null +++ b/libmisc/chowndir.c @@ -0,0 +1,126 @@ +/* + * Copyright 1992, 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: chowndir.c,v 1.5 1998/04/16 19:57:43 marekm Exp $") + +#include +#include +#include "prototypes.h" +#include "defines.h" + +#include +#include + +/* + * chown_tree - change ownership of files in a directory tree + * + * chown_dir() walks a directory tree and changes the ownership + * of all files owned by the provided user ID. + */ + +int +chown_tree(const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid, gid_t new_gid) +{ + char new_name[1024]; + int rc = 0; + struct DIRECT *ent; + struct stat sb; + DIR *dir; + + /* + * Make certain the directory exists. This routine is called + * directory by the invoker, or recursively. + */ + + if (access(root, F_OK) != 0) + return -1; + + /* + * Open the directory and read each entry. Every entry is tested + * to see if it is a directory, and if so this routine is called + * recursively. If not, it is checked to see if it is owned by + * old user ID. + */ + + if (! (dir = opendir (root))) + return -1; + + while ((ent = readdir (dir))) { + + /* + * Skip the "." and ".." entries + */ + + if (strcmp (ent->d_name, ".") == 0 || + strcmp (ent->d_name, "..") == 0) + continue; + + /* + * Make the filename for both the source and the + * destination files. + */ + + if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name) + break; + + snprintf(new_name, sizeof new_name, "%s/%s", root, ent->d_name); + + if (stat (new_name, &sb) == -1) + continue; + + if (S_ISDIR(sb.st_mode)) { + + /* + * Do the entire subdirectory. + */ + + if ((rc = chown_tree (new_name, old_uid, new_uid, + old_gid, new_gid))) + break; + } + if (sb.st_uid == old_uid) + chown (new_name, new_uid, + sb.st_gid == old_gid ? new_gid:sb.st_gid); + } + closedir (dir); + + /* + * Now do the root of the tree + */ + + if (! stat (root, &sb)) { + if (sb.st_uid == old_uid) + chown (root, new_uid, + sb.st_gid == old_gid ? new_gid:sb.st_gid); + } + return rc; +} diff --git a/libmisc/chowntty.c b/libmisc/chowntty.c new file mode 100644 index 00000000..f52b5a4a --- /dev/null +++ b/libmisc/chowntty.c @@ -0,0 +1,127 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: chowntty.c,v 1.7 1998/12/28 20:34:43 marekm Exp $") + +#include +#include + +#include +#include + +#include "prototypes.h" +#include "defines.h" +#include +#include "getdef.h" + +/* + * is_my_tty -- determine if "tty" is the same as TTY stdin is using + */ + +static int +is_my_tty(const char *tty) +{ + struct stat by_name, by_fd; + + if (stat (tty, &by_name) || fstat (0, &by_fd)) + return 0; + + if (by_name.st_rdev != by_fd.st_rdev) + return 0; + else + return 1; +} + +/* + * chown_tty() sets the login tty to be owned by the new user ID + * with TTYPERM modes + */ + +void +chown_tty(const char *tty, const struct passwd *info) +{ + char buf[200], full_tty[200]; + char *group; /* TTY group name or number */ + struct group *grent; + gid_t gid; + + /* + * See if login.defs has some value configured for the port group + * ID. Otherwise, use the user's primary group ID. + */ + + if (! (group = getdef_str ("TTYGROUP"))) + gid = info->pw_gid; + else if (group[0] >= '0' && group[0] <= '9') + gid = atoi (group); + else if ((grent = getgrnam (group))) + gid = grent->gr_gid; + else + gid = info->pw_gid; + + /* + * Change the permissions on the TTY to be owned by the user with + * the group as determined above. + */ + + if (*tty != '/') { + snprintf(full_tty, sizeof full_tty, "/dev/%s", tty); + tty = full_tty; + } + + if (! is_my_tty (tty)) { + SYSLOG((LOG_WARN, "unable to determine TTY name, got %s\n", + tty)); + closelog(); + exit (1); + } + + if (chown(tty, info->pw_uid, gid) || + chmod(tty, getdef_num("TTYPERM", 0600))) { + snprintf(buf, sizeof buf, _("Unable to change tty %s"), tty); + SYSLOG((LOG_WARN, "unable to change tty `%s' for user `%s'\n", + tty, info->pw_name)); + closelog(); + perror (buf); + exit(1); + } + +#ifdef __linux__ + /* + * Please don't add code to chown /dev/vcs* to the user logging in - + * it's a potential security hole. I wouldn't like the previous user + * to hold the file descriptor open and watch my screen. We don't + * have the *BSD revoke() system call yet, and vhangup() only works + * for tty devices (which vcs* is not). --marekm + */ +#endif +} diff --git a/libmisc/console.c b/libmisc/console.c new file mode 100644 index 00000000..75e69074 --- /dev/null +++ b/libmisc/console.c @@ -0,0 +1,115 @@ +/* + * Copyright 1991, Julianne Frances Haugh and Chip Rosenthal + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "defines.h" +#include +#include "getdef.h" + +#include "rcsid.h" +RCSID("$Id: console.c,v 1.5 1998/12/28 20:34:44 marekm Exp $") + +/* + * This is now rather generic function which decides if "tty" is listed + * under "cfgin" in config (directly or indirectly). Fallback to default if + * something is bad. + */ +int +is_listed(const char *cfgin, const char *tty, int def) +{ + FILE *fp; + char buf[200], *cons, *s; + + /* + * If the CONSOLE configuration definition isn't given, + * fallback to default. + */ + + if ((cons = getdef_str(cfgin)) == NULL) + return def; + + /* + * If this isn't a filename, then it is a ":" delimited list of + * console devices upon which root logins are allowed. + */ + + if (*cons != '/') { + cons = strcpy(buf, cons); + while ((s = strtok(cons, ":")) != NULL) { + if (strcmp(s, tty) == 0) + return 1; + + cons = NULL; + } + return 0; + } + + /* + * If we can't open the console list, then call everything a + * console - otherwise root will never be allowed to login. + */ + + if ((fp = fopen(cons, "r")) == NULL) + return def; + + /* + * See if this tty is listed in the console file. + */ + + while (fgets(buf, sizeof(buf), fp) != NULL) { + buf[strlen(buf) - 1] = '\0'; + if (strcmp(buf, tty) == 0) { + (void) fclose(fp); + return 1; + } + } + + /* + * This tty isn't a console. + */ + + (void) fclose(fp); + return 0; +} + +/* + * console - return 1 if the "tty" is a console device, else 0. + * + * Note - we need to take extreme care here to avoid locking out root logins + * if something goes awry. That's why we do things like call everything a + * console if the consoles file can't be opened. Because of this, we must + * warn the user to protect against the remove of the consoles file since + * that would allow an unauthorized root login. + */ + +int +console(const char *tty) +{ + return is_listed("CONSOLE", tty, 1); +} diff --git a/libmisc/copydir.c b/libmisc/copydir.c new file mode 100644 index 00000000..cb1a470a --- /dev/null +++ b/libmisc/copydir.c @@ -0,0 +1,411 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: copydir.c,v 1.6 1998/06/25 22:10:42 marekm Exp $") + + +#include + +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" + +static const char *src_orig; +static const char *dst_orig; + +struct link_name { + dev_t ln_dev; + ino_t ln_ino; + int ln_count; + char *ln_name; + struct link_name *ln_next; +}; +static struct link_name *links; + +/* + * remove_link - delete a link from the link list + */ + +static void +remove_link(struct link_name *ln) +{ + struct link_name *lp; + + if (links == ln) { + links = ln->ln_next; + free (ln->ln_name); + free (ln); + return; + } + for (lp = links;lp;lp = lp->ln_next) + if (lp->ln_next == ln) + break; + + if (! lp) + return; + + lp->ln_next = lp->ln_next->ln_next; + free (ln->ln_name); + free (ln); +} + +/* + * check_link - see if a file is really a link + */ + +static struct link_name * +check_link(const char *name, const struct stat *sb) +{ + struct link_name *lp; + int src_len; + int dst_len; + int name_len; + int len; + + for (lp = links;lp;lp = lp->ln_next) + if (lp->ln_dev == sb->st_dev && lp->ln_ino == sb->st_ino) + return lp; + + if (sb->st_nlink == 1) + return 0; + + lp = (struct link_name *) xmalloc (sizeof *lp); + src_len = strlen (src_orig); + dst_len = strlen (dst_orig); + name_len = strlen (name); + lp->ln_dev = sb->st_dev; + lp->ln_ino = sb->st_ino; + lp->ln_count = sb->st_nlink; + len = name_len - src_len + dst_len + 1; + lp->ln_name = xmalloc(len); + snprintf(lp->ln_name, len, "%s%s", dst_orig, name + src_len); + lp->ln_next = links; + links = lp; + + return 0; +} + +/* + * copy_tree - copy files in a directory tree + * + * copy_tree() walks a directory tree and copies ordinary files + * as it goes. + */ + +int +copy_tree(const char *src_root, const char *dst_root, uid_t uid, gid_t gid) +{ + char src_name[1024]; + char dst_name[1024]; + char buf[1024]; + int ifd; + int ofd; + int err = 0; + int cnt; + int set_orig = 0; + struct DIRECT *ent; + struct stat sb; + struct link_name *lp; + DIR *dir; + + /* + * Make certain both directories exist. This routine is called + * after the home directory is created, or recursively after the + * target is created. It assumes the target directory exists. + */ + + if (access(src_root, F_OK) != 0 || access(dst_root, F_OK) != 0) + return -1; + + /* + * Open the source directory and read each entry. Every file + * entry in the directory is copied with the UID and GID set + * to the provided values. As an added security feature only + * regular files (and directories ...) are copied, and no file + * is made set-ID. + */ + + if (! (dir = opendir (src_root))) + return -1; + + if (src_orig == 0) { + src_orig = src_root; + dst_orig = dst_root; + set_orig++; + } + while ((ent = readdir (dir))) { + + /* + * Skip the "." and ".." entries + */ + + if (strcmp (ent->d_name, ".") == 0 || + strcmp (ent->d_name, "..") == 0) + continue; + + /* + * Make the filename for both the source and the + * destination files. + */ + + if (strlen (src_root) + strlen (ent->d_name) + 2 > sizeof src_name) { + err++; + break; + } + snprintf(src_name, sizeof src_name, "%s/%s", src_root, ent->d_name); + + if (strlen (dst_root) + strlen (ent->d_name) + 2 > sizeof dst_name) { + err++; + break; + } + snprintf(dst_name, sizeof dst_name, "%s/%s", dst_root, ent->d_name); + +#ifdef S_IFLNK + if (lstat (src_name, &sb) == -1) +#else + if (stat (src_name, &sb) == -1) +#endif + continue; + + if (S_ISDIR(sb.st_mode)) { + + /* + * Create a new target directory, make it owned by + * the user and then recursively copy that directory. + */ + + mkdir (dst_name, sb.st_mode & 0777); + chown (dst_name, uid == (uid_t) -1 ? sb.st_uid:uid, + gid == (gid_t) -1 ? sb.st_gid:gid); + + if (copy_tree (src_name, dst_name, uid, gid)) { + err++; + break; + } + continue; + } +#ifdef S_IFLNK + /* + * Copy any symbolic links + */ + + if (S_ISLNK(sb.st_mode)) { + char oldlink[1024]; + char dummy[1024]; + int len; + + /* + * Get the name of the file which the link points + * to. If that name begins with the original + * source directory name, that part of the link + * name will be replaced with the original + * destinateion directory name. + */ + + if ((len = readlink(src_name, oldlink, sizeof(oldlink) - 1)) < 0) { + err++; + break; + } + oldlink[len] = '\0'; /* readlink() does not NUL-terminate */ + if (!strncmp(oldlink, src_orig, strlen(src_orig))) { + snprintf(dummy, sizeof dummy, "%s%s", + dst_orig, oldlink + strlen(src_orig)); + strcpy(oldlink, dummy); + } + if (symlink(oldlink, dst_name)) { + err++; + break; + } + continue; + } +#endif + + /* + * See if this is a previously copied link + */ + + if ((lp = check_link (src_name, &sb))) { + if (link (lp->ln_name, dst_name)) { + err++; + break; + } + if (unlink (src_name)) { + err++; + break; + } + if (--lp->ln_count <= 0) + remove_link (lp); + + continue; + } + + /* + * Deal with FIFOs and special files. The user really + * shouldn't have any of these, but it seems like it + * would be nice to copy everything ... + */ + + if (!S_ISREG(sb.st_mode)) { + if (mknod (dst_name, sb.st_mode & ~07777, sb.st_rdev) || + chown (dst_name, uid == (uid_t) -1 ? sb.st_uid:uid, + gid == (gid_t) -1 ? sb.st_gid:gid) || + chmod (dst_name, sb.st_mode & 07777)) { + err++; + break; + } + continue; + } + + /* + * Create the new file and copy the contents. The new + * file will be owned by the provided UID and GID values. + */ + + if ((ifd = open (src_name, O_RDONLY)) < 0) { + err++; + break; + } + if ((ofd = open (dst_name, O_WRONLY|O_CREAT, 0)) < 0 || + chown (dst_name, uid == (uid_t) -1 ? sb.st_uid:uid, + gid == (gid_t) -1 ? sb.st_gid:gid) || + chmod (dst_name, sb.st_mode & 07777)) { + close (ifd); + err++; + break; + } + while ((cnt = read (ifd, buf, sizeof buf)) > 0) { + if (write (ofd, buf, cnt) != cnt) { + cnt = -1; + break; + } + } + close (ifd); + close (ofd); + + if (cnt == -1) { + err++; + break; + } + } + closedir (dir); + + if (set_orig) { + src_orig = 0; + dst_orig = 0; + } + return err ? -1:0; +} + +/* + * remove_tree - remove files in a directory tree + * + * remove_tree() walks a directory tree and deletes all the files + * and directories. + */ + +int +remove_tree(const char *root) +{ + char new_name[1024]; + int err = 0; + struct DIRECT *ent; + struct stat sb; + DIR *dir; + + /* + * Make certain the directory exists. + */ + + if (access(root, F_OK) != 0) + return -1; + + /* + * Open the source directory and read each entry. Every file + * entry in the directory is copied with the UID and GID set + * to the provided values. As an added security feature only + * regular files (and directories ...) are copied, and no file + * is made set-ID. + */ + + dir = opendir (root); + + while ((ent = readdir (dir))) { + + /* + * Skip the "." and ".." entries + */ + + if (strcmp (ent->d_name, ".") == 0 || + strcmp (ent->d_name, "..") == 0) + continue; + + /* + * Make the filename for the current entry. + */ + + if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name) { + err++; + break; + } + snprintf(new_name, sizeof new_name, "%s/%s", root, ent->d_name); +#ifdef S_IFLNK + if (lstat (new_name, &sb) == -1) +#else + if (stat (new_name, &sb) == -1) +#endif + continue; + + if (S_ISDIR(sb.st_mode)) { + + /* + * Recursively delete this directory. + */ + + if (remove_tree (new_name)) { + err++; + break; + } + if (rmdir (new_name)) { + err++; + break; + } + continue; + } + unlink (new_name); + } + closedir (dir); + + return err ? -1:0; +} diff --git a/libmisc/entry.c b/libmisc/entry.c new file mode 100644 index 00000000..5baa8ed6 --- /dev/null +++ b/libmisc/entry.c @@ -0,0 +1,99 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: entry.c,v 1.3 1997/12/07 23:27:03 marekm Exp $") + +#include +#include +#include "prototypes.h" +#include "defines.h" +#include + +struct passwd *fgetpwent (); + +void +entry(const char *name, struct passwd *pwent) +{ + struct passwd *passwd; +#ifdef SHADOWPWD + struct spwd *spwd; +#ifdef ATT_AGE + char *l64a (); + char *cp; +#endif +#endif + + if (! (passwd = getpwnam (name))) { + pwent->pw_name = (char *) 0; + return; + } else { + pwent->pw_name = xstrdup (passwd->pw_name); + pwent->pw_uid = passwd->pw_uid; + pwent->pw_gid = passwd->pw_gid; +#ifdef ATT_COMMENT + pwent->pw_comment = xstrdup (passwd->pw_comment); +#endif + pwent->pw_gecos = xstrdup (passwd->pw_gecos); + pwent->pw_dir = xstrdup (passwd->pw_dir); + pwent->pw_shell = xstrdup (passwd->pw_shell); +#if defined(SHADOWPWD) && !defined(AUTOSHADOW) + setspent (); + if ((spwd = getspnam (name))) { + pwent->pw_passwd = xstrdup (spwd->sp_pwdp); +#ifdef ATT_AGE + pwent->pw_age = (char *) xmalloc (5); + + if (spwd->sp_max > (63*7)) + spwd->sp_max = (63*7); + if (spwd->sp_min > (63*7)) + spwd->sp_min = (63*7); + + pwent->pw_age[0] = i64c (spwd->sp_max / 7); + pwent->pw_age[1] = i64c (spwd->sp_min / 7); + + cp = l64a (spwd->sp_lstchg / 7); + pwent->pw_age[2] = cp[0]; + pwent->pw_age[3] = cp[1]; + + pwent->pw_age[4] = '\0'; +#endif + endspent (); + return; + } + endspent (); +#endif + pwent->pw_passwd = xstrdup (passwd->pw_passwd); +#ifdef ATT_AGE + pwent->pw_age = xstrdup (passwd->pw_age); +#endif + } +} diff --git a/libmisc/env.c b/libmisc/env.c new file mode 100644 index 00000000..8d7b2a11 --- /dev/null +++ b/libmisc/env.c @@ -0,0 +1,250 @@ +/* + * Copyright 1989 - 1992, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: env.c,v 1.9 1999/03/07 19:14:38 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +/* + * NEWENVP_STEP must be a power of two. This is the number + * of (char *) pointers to allocate at a time, to avoid using + * realloc() too often. + */ +#define NEWENVP_STEP 16 + +size_t newenvc = 0; +char **newenvp = NULL; +extern char **environ; + +static const char *forbid[] = { + "_RLD_=", + "BASH_ENV=", /* GNU creeping featurism strikes again... */ + "ENV=", + "HOME=", + "IFS=", + "KRB_CONF=", + "LD_", /* anything with the LD_ prefix */ + "LIBPATH=", + "MAIL=", + "NLSPATH=", + "PATH=", + "SHELL=", + "SHLIB_PATH=", + (char *) 0 +}; + +/* these are allowed, but with no slashes inside + (to work around security problems in GNU gettext) */ +static const char *noslash[] = { + "LANG=", + "LANGUAGE=", + "LC_", /* anything with the LC_ prefix */ + (char *) 0 +}; + +/* + * initenv() must be called once before using addenv(). + */ +void +initenv(void) +{ + newenvp = (char **)xmalloc(NEWENVP_STEP * sizeof(char *)); + *newenvp = NULL; +} + + +void +addenv(const char *string, const char *value) +{ + char *cp, *newstring; + size_t i; + size_t n; + + if (value) { + newstring = xmalloc(strlen(string) + strlen(value) + 2); + sprintf(newstring, "%s=%s", string, value); + } else { + newstring = xstrdup(string); + } + + /* + * Search for a '=' character within the string and if none is found + * just ignore the whole string. + */ + + cp = strchr(newstring, '='); + if (!cp) { + free(newstring); + return; + } + + n = (size_t)(cp - newstring); + + for (i = 0; i < newenvc; i++) { + if (strncmp(newstring, newenvp[i], n) == 0 && + (newenvp[i][n] == '=' || newenvp[i][n] == '\0')) + break; + } + + if (i < newenvc) { + free(newenvp[i]); + newenvp[i] = newstring; + return; + } + + newenvp[newenvc++] = newstring; + + /* + * Check whether newenvc is a multiple of NEWENVP_STEP. + * If so we have to resize the vector. + * the expression (newenvc & (NEWENVP_STEP - 1)) == 0 + * is equal to (newenvc % NEWENVP_STEP) == 0 + * as long as NEWENVP_STEP is a power of 2. + */ + + if ((newenvc & (NEWENVP_STEP - 1)) == 0) { + char **__newenvp; + size_t newsize; + + /* + * If the resize operation succeds we can + * happily go on, else print a message. + */ + + newsize = (newenvc + NEWENVP_STEP) * sizeof(char *); + __newenvp = (char **)realloc(newenvp, newsize); + + if (__newenvp) { + /* + * If this is our current environment, update + * environ so that it doesn't point to some + * free memory area (realloc() could move it). + */ + if (environ == newenvp) + environ = __newenvp; + newenvp = __newenvp; + } else { + fprintf(stderr, _("Environment overflow\n")); + free(newenvp[--newenvc]); + } + } + + /* + * The last entry of newenvp must be NULL + */ + + newenvp[newenvc] = NULL; +} + + +/* + * set_env - copy command line arguments into the environment + */ +void +set_env(int argc, char * const *argv) +{ + int noname = 1; + char variable[1024]; + char *cp; + + for ( ; argc > 0; argc--, argv++) { + if (strlen(*argv) >= sizeof variable) + continue; /* ignore long entries */ + + if (! (cp = strchr (*argv, '='))) { + snprintf(variable, sizeof variable, "L%d", noname++); + addenv(variable, *argv); + } else { + const char **p; + + for (p = forbid; *p; p++) + if (strncmp(*argv, *p, strlen(*p)) == 0) + break; + + if (*p) { + strncpy(variable, *argv, cp - *argv); + variable[cp - *argv] = '\0'; + printf(_("You may not change $%s\n"), variable); + continue; + } + + addenv(*argv, NULL); + } + } +} + +/* + * sanitize_env - remove some nasty environment variables + * If you fall into a total paranoia, you should call this + * function for any root-setuid program or anything the user + * might change the environment with. 99% useless as almost + * all modern Unixes will handle setuid executables properly, + * but... I feel better with that silly precaution. -j. + */ + +void +sanitize_env(void) +{ + char **envp = environ; + const char **bad; + char **cur; + char **move; + + for (cur = envp; *cur; cur++) { + for (bad = forbid; *bad; bad++) { + if (strncmp(*cur, *bad, strlen(*bad)) == 0) { + for (move = cur; *move; move++) + *move = *(move + 1); + cur--; + break; + } + } + } + + for (cur = envp; *cur; cur++) { + for (bad = noslash; *bad; bad++) { + if (strncmp(*cur, *bad, strlen(*bad)) != 0) + continue; + if (!strchr(*cur, '/')) + continue; /* OK */ + for (move = cur; *move; move++) + *move = *(move + 1); + cur--; + break; + } + } +} + diff --git a/libmisc/failure.c b/libmisc/failure.c new file mode 100644 index 00000000..6f62ef1f --- /dev/null +++ b/libmisc/failure.c @@ -0,0 +1,278 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: failure.c,v 1.6 1998/12/28 20:34:46 marekm Exp $") + +#include +#include +#include "defines.h" +#include "faillog.h" +#include "getdef.h" +#include "failure.h" + +#include + +#define YEAR (365L*DAY) + +/* + * failure - make failure entry + * + * failure() creates a new (struct faillog) entry or updates an + * existing one with the current failed login information. + */ + +void +failure(uid_t uid, const char *tty, struct faillog *fl) +{ + int fd; + + /* + * Don't do anything if failure logging isn't set up. + */ + + if ((fd = open(FAILLOG_FILE, O_RDWR)) < 0) + return; + + /* + * The file is indexed by uid value meaning that shared UID's + * share failure log records. That's OK since they really + * share just about everything else ... + */ + + lseek(fd, (off_t) (sizeof *fl) * uid, SEEK_SET); + if (read(fd, (char *) fl, sizeof *fl) != sizeof *fl) + memzero(fl, sizeof *fl); + + /* + * Update the record. We increment the failure count to log the + * latest failure. The only concern here is overflow, and we'll + * check for that. The line name and time of day are both + * updated as well. + */ + + if (fl->fail_cnt + 1 > 0) + fl->fail_cnt++; + + strncpy(fl->fail_line, tty, sizeof fl->fail_line); + time(&fl->fail_time); + + /* + * Seek back to the correct position in the file and write the + * record out. Ideally we should lock the file in case the same + * account is being logged simultaneously. But the risk doesn't + * seem that great. + */ + + lseek(fd, (off_t) (sizeof *fl) * uid, SEEK_SET); + write(fd, (char *) fl, sizeof *fl); + close(fd); +} + +static int +too_many_failures(const struct faillog *fl) +{ + time_t now; + + if (fl->fail_max == 0 || fl->fail_cnt < fl->fail_max) + return 0; + + if (fl->fail_locktime == 0) + return 1; /* locked until reset manually */ + + time(&now); + if (fl->fail_time + fl->fail_locktime > now) + return 0; /* enough time since last failure */ + + return 1; +} + +/* + * failcheck - check for failures > allowable + * + * failcheck() is called AFTER the password has been validated. If the + * account has been "attacked" with too many login failures, failcheck() + * returns FALSE to indicate that the login should be denied even though + * the password is valid. + */ + +int +failcheck(uid_t uid, struct faillog *fl, int failed) +{ + int fd; + struct faillog fail; + + /* + * Suppress the check if the log file isn't there. + */ + + if ((fd = open(FAILLOG_FILE, O_RDWR)) < 0) + return 1; + + /* + * Get the record from the file and determine if the user has + * exceeded the failure limit. If "max" is zero, any number + * of failures are permitted. Only when "max" is non-zero and + * "cnt" is greater than or equal to "max" is the account + * considered to be locked. + * + * If read fails, there is no record for this user yet (the + * file is initially zero length and extended by writes), so + * no need to reset the count. + */ + + lseek (fd, (off_t) (sizeof *fl) * uid, SEEK_SET); + if (read(fd, (char *) fl, sizeof *fl) != sizeof *fl) { + close(fd); + return 1; + } + + if (too_many_failures(fl)) { + close(fd); + return 0; + } + + /* + * The record is updated if this is not a failure. The count will + * be reset to zero, but the rest of the information will be left + * in the record in case someone wants to see where the failed + * login originated. + */ + + if (!failed) { + fail = *fl; + fail.fail_cnt = 0; + + lseek (fd, (off_t) sizeof fail * uid, SEEK_SET); + write (fd, (char *) &fail, sizeof fail); + } + close (fd); + return 1; +} + +/* + * failprint - print line of failure information + * + * failprint takes a (struct faillog) entry and formats it into a + * message which is displayed at login time. + */ + +void +failprint(const struct faillog *fail) +{ + struct tm *tp; +#if HAVE_STRFTIME + char lasttimeb[256]; + char *lasttime = lasttimeb; + const char *fmt; +#else + char *lasttime; +#endif + time_t NOW; + + if (fail->fail_cnt == 0) + return; + + tp = localtime (&(fail->fail_time)); + time(&NOW); + +#if HAVE_STRFTIME + /* + * Only print as much date and time info as it needed to + * know when the failure was. + */ + + if (NOW - fail->fail_time >= YEAR) + fmt = "%Y"; + else if (NOW - fail->fail_time >= DAY) + fmt = "%A %T"; + else + fmt = "%T"; + strftime(lasttimeb, sizeof lasttimeb, fmt, tp); +#else + + /* + * Do the same thing, but don't use strftime since it + * probably doesn't exist on this system + */ + + lasttime = asctime (tp); + lasttime[24] = '\0'; + + if (NOW - fail->fail_time < YEAR) + lasttime[19] = '\0'; + if (NOW - fail->fail_time < DAY) + lasttime = lasttime + 11; + + if (*lasttime == ' ') + lasttime++; +#endif + printf (_("%d %s since last login. Last was %s on %s.\n"), + fail->fail_cnt, fail->fail_cnt > 1 ? _("failures"):_("failure"), + lasttime, fail->fail_line); +} + +/* + * failtmp - update the cummulative failure log + * + * failtmp updates the (struct utmp) formatted failure log which + * maintains a record of all login failures. + */ + +void +failtmp(const struct utmp *failent) +{ + char *ftmp; + int fd; + + /* + * Get the name of the failure file. If no file has been defined + * in login.defs, don't do this. + */ + + if (!(ftmp = getdef_str("FTMP_FILE"))) + return; + + /* + * Open the file for append. It must already exist for this + * feature to be used. + */ + + if ((fd = open(ftmp, O_WRONLY|O_APPEND)) == -1) + return; + + /* + * Output the new failure record and close the log file. + */ + + write(fd, (const char *) failent, sizeof *failent); + close(fd); +} diff --git a/libmisc/failure.h b/libmisc/failure.h new file mode 100644 index 00000000..7fbac2bf --- /dev/null +++ b/libmisc/failure.h @@ -0,0 +1,44 @@ +/* $Id: failure.h,v 1.1 1997/12/07 23:27:04 marekm Exp $ */ +#ifndef _FAILURE_H_ +#define _FAILURE_H_ + +#include "defines.h" +#include "faillog.h" +#include + +/* + * failure - make failure entry + * + * failure() creates a new (struct faillog) entry or updates an + * existing one with the current failed login information. + */ +extern void failure P_((uid_t, const char *, struct faillog *)); + +/* + * failcheck - check for failures > allowable + * + * failcheck() is called AFTER the password has been validated. If the + * account has been "attacked" with too many login failures, failcheck() + * returns FALSE to indicate that the login should be denied even though + * the password is valid. + */ +extern int failcheck P_((uid_t, struct faillog *, int)); + +/* + * failprint - print line of failure information + * + * failprint takes a (struct faillog) entry and formats it into a + * message which is displayed at login time. + */ +extern void failprint P_((const struct faillog *)); + +/* + * failtmp - update the cummulative failure log + * + * failtmp updates the (struct utmp) formatted failure log which + * maintains a record of all login failures. + */ +extern void failtmp P_((const struct utmp *)); + +#endif + diff --git a/libmisc/fields.c b/libmisc/fields.c new file mode 100644 index 00000000..a645ec59 --- /dev/null +++ b/libmisc/fields.c @@ -0,0 +1,104 @@ +/* + * Copyright 1990, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: fields.c,v 1.5 1997/12/07 23:27:04 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" + +/* + * valid_field - insure that a field contains all legal characters + * + * The supplied field is scanned for non-printing and other illegal + * characters. If any illegal characters are found, valid_field + * returns -1. Zero is returned for success. + */ + +int +valid_field(const char *field, const char *illegal) +{ + const char *cp; + + for (cp = field; *cp && isprint(*cp & 0x7F) && !strchr(illegal, *cp); cp++) + ; + + if (*cp) + return -1; + else + return 0; +} + +/* + * change_field - change a single field if a new value is given. + * + * prompt the user with the name of the field being changed and the + * current value. + */ + +void +change_field(char *buf, size_t maxsize, const char *prompt) +{ + char newf[200]; + char *cp; + + if (maxsize > sizeof(newf)) + maxsize = sizeof(newf); + + printf ("\t%s [%s]: ", prompt, buf); + if (fgets(newf, maxsize, stdin) != newf) + return; + + if (!(cp = strchr(newf, '\n'))) + return; + *cp = '\0'; + + if (newf[0]) { + /* + * Remove leading and trailing whitespace. This also + * makes it possible to change the field to empty, by + * entering a space. --marekm + */ + + while (--cp >= newf && isspace(*cp)) + ; + *++cp = '\0'; + + cp = newf; + while (*cp && isspace(*cp)) + cp++; + + strncpy(buf, cp, maxsize - 1); + buf[maxsize - 1] = '\0'; + } +} diff --git a/libmisc/getdate.c b/libmisc/getdate.c new file mode 100644 index 00000000..559add3a --- /dev/null +++ b/libmisc/getdate.c @@ -0,0 +1,2006 @@ + +/* A Bison parser, made from getdate.y + by GNU Bison version 1.25 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define tAGO 258 +#define tDAY 259 +#define tDAY_UNIT 260 +#define tDAYZONE 261 +#define tDST 262 +#define tHOUR_UNIT 263 +#define tID 264 +#define tMERIDIAN 265 +#define tMINUTE_UNIT 266 +#define tMONTH 267 +#define tMONTH_UNIT 268 +#define tSEC_UNIT 269 +#define tSNUMBER 270 +#define tUNUMBER 271 +#define tYEAR_UNIT 272 +#define tZONE 273 + +#line 1 "getdate.y" + +/* +** Originally written by Steven M. Bellovin while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** and Jim Berets in August, 1990; +** +** This grammar has 13 shift/reduce conflicts. +** +** This code is in the public domain and has no copyright. +*/ + +#ifdef HAVE_CONFIG_H +# include +# ifdef FORCE_ALLOCA_H +# include +# endif +#endif + +/* Since the code of getdate.y is not included in the Emacs executable + itself, there is no need to #define static in this file. Even if + the code were included in the Emacs executable, it probably + wouldn't do any harm to #undef it here; this will only cause + problems if we try to write to a static variable, which I don't + think this code needs to do. */ +#ifdef emacs +# undef static +#endif + +#include +#include + +#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii(c) +#endif + +#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) +#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) +#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) + +/* ISDIGIT differs from ISDIGIT_LOCALE, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char. + - It's guaranteed to evaluate its argument exactly once. + - It's typically faster. + Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that + only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless + it's important to use the locale's definition of `digit' even when the + host does not conform to Posix. */ +#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) + +#include "getdate.h" + +#if defined (STDC_HEADERS) || defined (USG) +# include +#endif + +/* Some old versions of bison generate parsers that use bcopy. + That loses on systems that don't provide the function, so we have + to redefine it here. */ +#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy) +# define bcopy(from, to, len) memcpy ((to), (from), (len)) +#endif + +extern struct tm *gmtime (); +extern struct tm *localtime (); +extern time_t mktime (); + +/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), + as well as gratuitiously global symbol names, so we can have multiple + yacc generated parsers in the same program. Note that these are only + the variables produced by yacc. If other parser generators (bison, + byacc, etc) produce additional global names that conflict at link time, + then those parser generators need to be fixed instead of adding those + names to this list. */ + +#define yymaxdepth gd_maxdepth +#define yyparse gd_parse +#define yylex gd_lex +#define yyerror gd_error +#define yylval gd_lval +#define yychar gd_char +#define yydebug gd_debug +#define yypact gd_pact +#define yyr1 gd_r1 +#define yyr2 gd_r2 +#define yydef gd_def +#define yychk gd_chk +#define yypgo gd_pgo +#define yyact gd_act +#define yyexca gd_exca +#define yyerrflag gd_errflag +#define yynerrs gd_nerrs +#define yyps gd_ps +#define yypv gd_pv +#define yys gd_s +#define yy_yys gd_yys +#define yystate gd_state +#define yytmp gd_tmp +#define yyv gd_v +#define yy_yyv gd_yyv +#define yyval gd_val +#define yylloc gd_lloc +#define yyreds gd_reds /* With YYDEBUG defined */ +#define yytoks gd_toks /* With YYDEBUG defined */ +#define yylhs gd_yylhs +#define yylen gd_yylen +#define yydefred gd_yydefred +#define yydgoto gd_yydgoto +#define yysindex gd_yysindex +#define yyrindex gd_yyrindex +#define yygindex gd_yygindex +#define yytable gd_yytable +#define yycheck gd_yycheck + +static int yylex (); +static int yyerror (); + +#define EPOCH 1970 +#define HOUR(x) ((x) * 60) + +#define MAX_BUFF_LEN 128 /* size of buffer to read the date into */ + +/* +** An entry in the lexical lookup table. +*/ +typedef struct _TABLE { + const char *name; + int type; + int value; +} TABLE; + + +/* +** Meridian: am, pm, or 24-hour style. +*/ +typedef enum _MERIDIAN { + MERam, MERpm, MER24 +} MERIDIAN; + + +/* +** Global variables. We could get rid of most of these by using a good +** union as the yacc stack. (This routine was originally written before +** yacc had the %union construct.) Maybe someday; right now we only use +** the %union very rarely. +*/ +static const char *yyInput; +static int yyDayOrdinal; +static int yyDayNumber; +static int yyHaveDate; +static int yyHaveDay; +static int yyHaveRel; +static int yyHaveTime; +static int yyHaveZone; +static int yyTimezone; +static int yyDay; +static int yyHour; +static int yyMinutes; +static int yyMonth; +static int yySeconds; +static int yyYear; +static MERIDIAN yyMeridian; +static int yyRelDay; +static int yyRelHour; +static int yyRelMinutes; +static int yyRelMonth; +static int yyRelSeconds; +static int yyRelYear; + + +#line 175 "getdate.y" +typedef union { + int Number; + enum _MERIDIAN Meridian; +} YYSTYPE; +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 61 +#define YYFLAG -32768 +#define YYNTBASE 22 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 273 ? yytranslate[x] : 32) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 20, 2, 2, 21, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 19, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 6, 8, 10, 12, 14, 16, 19, + 24, 29, 36, 43, 45, 47, 50, 52, 55, 58, + 62, 68, 72, 76, 79, 84, 87, 91, 94, 96, + 99, 102, 104, 107, 110, 112, 115, 118, 120, 123, + 126, 128, 131, 134, 136, 139, 142, 144, 146, 147 +}; + +static const short yyrhs[] = { -1, + 22, 23, 0, 24, 0, 25, 0, 27, 0, 26, + 0, 28, 0, 30, 0, 16, 10, 0, 16, 19, + 16, 31, 0, 16, 19, 16, 15, 0, 16, 19, + 16, 19, 16, 31, 0, 16, 19, 16, 19, 16, + 15, 0, 18, 0, 6, 0, 18, 7, 0, 4, + 0, 4, 20, 0, 16, 4, 0, 16, 21, 16, + 0, 16, 21, 16, 21, 16, 0, 16, 15, 15, + 0, 16, 12, 15, 0, 12, 16, 0, 12, 16, + 20, 16, 0, 16, 12, 0, 16, 12, 16, 0, + 29, 3, 0, 29, 0, 16, 17, 0, 15, 17, + 0, 17, 0, 16, 13, 0, 15, 13, 0, 13, + 0, 16, 5, 0, 15, 5, 0, 5, 0, 16, + 8, 0, 15, 8, 0, 8, 0, 16, 11, 0, + 15, 11, 0, 11, 0, 16, 14, 0, 15, 14, + 0, 14, 0, 16, 0, 0, 10, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 191, 192, 195, 198, 201, 204, 207, 210, 213, 219, + 225, 234, 240, 252, 255, 258, 264, 268, 272, 278, + 282, 300, 306, 312, 316, 321, 325, 332, 340, 343, + 346, 349, 352, 355, 358, 361, 364, 367, 370, 373, + 376, 379, 382, 385, 388, 391, 394, 399, 432, 436 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","tAGO","tDAY", +"tDAY_UNIT","tDAYZONE","tDST","tHOUR_UNIT","tID","tMERIDIAN","tMINUTE_UNIT", +"tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tYEAR_UNIT","tZONE", +"':'","','","'/'","spec","item","time","zone","day","date","rel","relunit","number", +"o_merid", NULL +}; +#endif + +static const short yyr1[] = { 0, + 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, + 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, + 27, 27, 27, 27, 27, 27, 27, 28, 28, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 30, 31, 31 +}; + +static const short yyr2[] = { 0, + 0, 2, 1, 1, 1, 1, 1, 1, 2, 4, + 4, 6, 6, 1, 1, 2, 1, 2, 2, 3, + 5, 3, 3, 2, 4, 2, 3, 2, 1, 2, + 2, 1, 2, 2, 1, 2, 2, 1, 2, 2, + 1, 2, 2, 1, 2, 2, 1, 1, 0, 1 +}; + +static const short yydefact[] = { 1, + 0, 17, 38, 15, 41, 44, 0, 35, 47, 0, + 48, 32, 14, 2, 3, 4, 6, 5, 7, 29, + 8, 18, 24, 37, 40, 43, 34, 46, 31, 19, + 36, 39, 9, 42, 26, 33, 45, 0, 30, 0, + 0, 16, 28, 0, 23, 27, 22, 49, 20, 25, + 50, 11, 0, 10, 0, 49, 21, 13, 12, 0, + 0 +}; + +static const short yydefgoto[] = { 1, + 14, 15, 16, 17, 18, 19, 20, 21, 54 +}; + +static const short yypact[] = {-32768, + 0, -19,-32768,-32768,-32768,-32768, -13,-32768,-32768, 30, + 15,-32768, 14,-32768,-32768,-32768,-32768,-32768,-32768, 19, +-32768,-32768, 4,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768, -6,-32768,-32768, 16,-32768, 17, + 23,-32768,-32768, 24,-32768,-32768,-32768, 27, 28,-32768, +-32768,-32768, 29,-32768, 32, -8,-32768,-32768,-32768, 50, +-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, -5 +}; + + +#define YYLAST 51 + + +static const short yytable[] = { 60, + 22, 51, 23, 2, 3, 4, 58, 5, 45, 46, + 6, 7, 8, 9, 10, 11, 12, 13, 30, 31, + 42, 43, 32, 44, 33, 34, 35, 36, 37, 38, + 47, 39, 48, 40, 24, 41, 51, 25, 49, 50, + 26, 52, 27, 28, 56, 53, 29, 57, 55, 61, + 59 +}; + +static const short yycheck[] = { 0, + 20, 10, 16, 4, 5, 6, 15, 8, 15, 16, + 11, 12, 13, 14, 15, 16, 17, 18, 4, 5, + 7, 3, 8, 20, 10, 11, 12, 13, 14, 15, + 15, 17, 16, 19, 5, 21, 10, 8, 16, 16, + 11, 15, 13, 14, 16, 19, 17, 16, 21, 0, + 56 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 196 "/usr/share/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 3: +#line 195 "getdate.y" +{ + yyHaveTime++; + ; + break;} +case 4: +#line 198 "getdate.y" +{ + yyHaveZone++; + ; + break;} +case 5: +#line 201 "getdate.y" +{ + yyHaveDate++; + ; + break;} +case 6: +#line 204 "getdate.y" +{ + yyHaveDay++; + ; + break;} +case 7: +#line 207 "getdate.y" +{ + yyHaveRel++; + ; + break;} +case 9: +#line 213 "getdate.y" +{ + yyHour = yyvsp[-1].Number; + yyMinutes = 0; + yySeconds = 0; + yyMeridian = yyvsp[0].Meridian; + ; + break;} +case 10: +#line 219 "getdate.y" +{ + yyHour = yyvsp[-3].Number; + yyMinutes = yyvsp[-1].Number; + yySeconds = 0; + yyMeridian = yyvsp[0].Meridian; + ; + break;} +case 11: +#line 225 "getdate.y" +{ + yyHour = yyvsp[-3].Number; + yyMinutes = yyvsp[-1].Number; + yyMeridian = MER24; + yyHaveZone++; + yyTimezone = (yyvsp[0].Number < 0 + ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 + : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); + ; + break;} +case 12: +#line 234 "getdate.y" +{ + yyHour = yyvsp[-5].Number; + yyMinutes = yyvsp[-3].Number; + yySeconds = yyvsp[-1].Number; + yyMeridian = yyvsp[0].Meridian; + ; + break;} +case 13: +#line 240 "getdate.y" +{ + yyHour = yyvsp[-5].Number; + yyMinutes = yyvsp[-3].Number; + yySeconds = yyvsp[-1].Number; + yyMeridian = MER24; + yyHaveZone++; + yyTimezone = (yyvsp[0].Number < 0 + ? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60 + : - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60)); + ; + break;} +case 14: +#line 252 "getdate.y" +{ + yyTimezone = yyvsp[0].Number; + ; + break;} +case 15: +#line 255 "getdate.y" +{ + yyTimezone = yyvsp[0].Number - 60; + ; + break;} +case 16: +#line 259 "getdate.y" +{ + yyTimezone = yyvsp[-1].Number - 60; + ; + break;} +case 17: +#line 264 "getdate.y" +{ + yyDayOrdinal = 1; + yyDayNumber = yyvsp[0].Number; + ; + break;} +case 18: +#line 268 "getdate.y" +{ + yyDayOrdinal = 1; + yyDayNumber = yyvsp[-1].Number; + ; + break;} +case 19: +#line 272 "getdate.y" +{ + yyDayOrdinal = yyvsp[-1].Number; + yyDayNumber = yyvsp[0].Number; + ; + break;} +case 20: +#line 278 "getdate.y" +{ + yyMonth = yyvsp[-2].Number; + yyDay = yyvsp[0].Number; + ; + break;} +case 21: +#line 282 "getdate.y" +{ + /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. + The goal in recognizing YYYY/MM/DD is solely to support legacy + machine-generated dates like those in an RCS log listing. If + you want portability, use the ISO 8601 format. */ + if (yyvsp[-4].Number >= 1000) + { + yyYear = yyvsp[-4].Number; + yyMonth = yyvsp[-2].Number; + yyDay = yyvsp[0].Number; + } + else + { + yyMonth = yyvsp[-4].Number; + yyDay = yyvsp[-2].Number; + yyYear = yyvsp[0].Number; + } + ; + break;} +case 22: +#line 300 "getdate.y" +{ + /* ISO 8601 format. yyyy-mm-dd. */ + yyYear = yyvsp[-2].Number; + yyMonth = -yyvsp[-1].Number; + yyDay = -yyvsp[0].Number; + ; + break;} +case 23: +#line 306 "getdate.y" +{ + /* e.g. 17-JUN-1992. */ + yyDay = yyvsp[-2].Number; + yyMonth = yyvsp[-1].Number; + yyYear = -yyvsp[0].Number; + ; + break;} +case 24: +#line 312 "getdate.y" +{ + yyMonth = yyvsp[-1].Number; + yyDay = yyvsp[0].Number; + ; + break;} +case 25: +#line 316 "getdate.y" +{ + yyMonth = yyvsp[-3].Number; + yyDay = yyvsp[-2].Number; + yyYear = yyvsp[0].Number; + ; + break;} +case 26: +#line 321 "getdate.y" +{ + yyMonth = yyvsp[0].Number; + yyDay = yyvsp[-1].Number; + ; + break;} +case 27: +#line 325 "getdate.y" +{ + yyMonth = yyvsp[-1].Number; + yyDay = yyvsp[-2].Number; + yyYear = yyvsp[0].Number; + ; + break;} +case 28: +#line 332 "getdate.y" +{ + yyRelSeconds = -yyRelSeconds; + yyRelMinutes = -yyRelMinutes; + yyRelHour = -yyRelHour; + yyRelDay = -yyRelDay; + yyRelMonth = -yyRelMonth; + yyRelYear = -yyRelYear; + ; + break;} +case 30: +#line 343 "getdate.y" +{ + yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 31: +#line 346 "getdate.y" +{ + yyRelYear += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 32: +#line 349 "getdate.y" +{ + yyRelYear++; + ; + break;} +case 33: +#line 352 "getdate.y" +{ + yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 34: +#line 355 "getdate.y" +{ + yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 35: +#line 358 "getdate.y" +{ + yyRelMonth++; + ; + break;} +case 36: +#line 361 "getdate.y" +{ + yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 37: +#line 364 "getdate.y" +{ + yyRelDay += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 38: +#line 367 "getdate.y" +{ + yyRelDay++; + ; + break;} +case 39: +#line 370 "getdate.y" +{ + yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 40: +#line 373 "getdate.y" +{ + yyRelHour += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 41: +#line 376 "getdate.y" +{ + yyRelHour++; + ; + break;} +case 42: +#line 379 "getdate.y" +{ + yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 43: +#line 382 "getdate.y" +{ + yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 44: +#line 385 "getdate.y" +{ + yyRelMinutes++; + ; + break;} +case 45: +#line 388 "getdate.y" +{ + yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 46: +#line 391 "getdate.y" +{ + yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number; + ; + break;} +case 47: +#line 394 "getdate.y" +{ + yyRelSeconds++; + ; + break;} +case 48: +#line 400 "getdate.y" +{ + if (yyHaveTime && yyHaveDate && !yyHaveRel) + yyYear = yyvsp[0].Number; + else + { + if (yyvsp[0].Number>10000) + { + yyHaveDate++; + yyDay= (yyvsp[0].Number)%100; + yyMonth= (yyvsp[0].Number/100)%100; + yyYear = yyvsp[0].Number/10000; + } + else + { + yyHaveTime++; + if (yyvsp[0].Number < 100) + { + yyHour = yyvsp[0].Number; + yyMinutes = 0; + } + else + { + yyHour = yyvsp[0].Number / 100; + yyMinutes = yyvsp[0].Number % 100; + } + yySeconds = 0; + yyMeridian = MER24; + } + } + ; + break;} +case 49: +#line 433 "getdate.y" +{ + yyval.Meridian = MER24; + ; + break;} +case 50: +#line 437 "getdate.y" +{ + yyval.Meridian = yyvsp[0].Meridian; + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 498 "/usr/share/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 442 "getdate.y" + + +/* Month and day table. */ +static TABLE const MonthDayTable[] = { + { "january", tMONTH, 1 }, + { "february", tMONTH, 2 }, + { "march", tMONTH, 3 }, + { "april", tMONTH, 4 }, + { "may", tMONTH, 5 }, + { "june", tMONTH, 6 }, + { "july", tMONTH, 7 }, + { "august", tMONTH, 8 }, + { "september", tMONTH, 9 }, + { "sept", tMONTH, 9 }, + { "october", tMONTH, 10 }, + { "november", tMONTH, 11 }, + { "december", tMONTH, 12 }, + { "sunday", tDAY, 0 }, + { "monday", tDAY, 1 }, + { "tuesday", tDAY, 2 }, + { "tues", tDAY, 2 }, + { "wednesday", tDAY, 3 }, + { "wednes", tDAY, 3 }, + { "thursday", tDAY, 4 }, + { "thur", tDAY, 4 }, + { "thurs", tDAY, 4 }, + { "friday", tDAY, 5 }, + { "saturday", tDAY, 6 }, + { NULL } +}; + +/* Time units table. */ +static TABLE const UnitsTable[] = { + { "year", tYEAR_UNIT, 1 }, + { "month", tMONTH_UNIT, 1 }, + { "fortnight", tDAY_UNIT, 14 }, + { "week", tDAY_UNIT, 7 }, + { "day", tDAY_UNIT, 1 }, + { "hour", tHOUR_UNIT, 1 }, + { "minute", tMINUTE_UNIT, 1 }, + { "min", tMINUTE_UNIT, 1 }, + { "second", tSEC_UNIT, 1 }, + { "sec", tSEC_UNIT, 1 }, + { NULL } +}; + +/* Assorted relative-time words. */ +static TABLE const OtherTable[] = { + { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 }, + { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 }, + { "today", tMINUTE_UNIT, 0 }, + { "now", tMINUTE_UNIT, 0 }, + { "last", tUNUMBER, -1 }, + { "this", tMINUTE_UNIT, 0 }, + { "next", tUNUMBER, 2 }, + { "first", tUNUMBER, 1 }, +/* { "second", tUNUMBER, 2 }, */ + { "third", tUNUMBER, 3 }, + { "fourth", tUNUMBER, 4 }, + { "fifth", tUNUMBER, 5 }, + { "sixth", tUNUMBER, 6 }, + { "seventh", tUNUMBER, 7 }, + { "eighth", tUNUMBER, 8 }, + { "ninth", tUNUMBER, 9 }, + { "tenth", tUNUMBER, 10 }, + { "eleventh", tUNUMBER, 11 }, + { "twelfth", tUNUMBER, 12 }, + { "ago", tAGO, 1 }, + { NULL } +}; + +/* The timezone table. */ +static TABLE const TimezoneTable[] = { + { "gmt", tZONE, HOUR ( 0) }, /* Greenwich Mean */ + { "ut", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ + { "utc", tZONE, HOUR ( 0) }, + { "wet", tZONE, HOUR ( 0) }, /* Western European */ + { "bst", tDAYZONE, HOUR ( 0) }, /* British Summer */ + { "wat", tZONE, HOUR ( 1) }, /* West Africa */ + { "at", tZONE, HOUR ( 2) }, /* Azores */ +#if 0 + /* For completeness. BST is also British Summer, and GST is + * also Guam Standard. */ + { "bst", tZONE, HOUR ( 3) }, /* Brazil Standard */ + { "gst", tZONE, HOUR ( 3) }, /* Greenland Standard */ +#endif +#if 0 + { "nft", tZONE, HOUR (3.5) }, /* Newfoundland */ + { "nst", tZONE, HOUR (3.5) }, /* Newfoundland Standard */ + { "ndt", tDAYZONE, HOUR (3.5) }, /* Newfoundland Daylight */ +#endif + { "ast", tZONE, HOUR ( 4) }, /* Atlantic Standard */ + { "adt", tDAYZONE, HOUR ( 4) }, /* Atlantic Daylight */ + { "est", tZONE, HOUR ( 5) }, /* Eastern Standard */ + { "edt", tDAYZONE, HOUR ( 5) }, /* Eastern Daylight */ + { "cst", tZONE, HOUR ( 6) }, /* Central Standard */ + { "cdt", tDAYZONE, HOUR ( 6) }, /* Central Daylight */ + { "mst", tZONE, HOUR ( 7) }, /* Mountain Standard */ + { "mdt", tDAYZONE, HOUR ( 7) }, /* Mountain Daylight */ + { "pst", tZONE, HOUR ( 8) }, /* Pacific Standard */ + { "pdt", tDAYZONE, HOUR ( 8) }, /* Pacific Daylight */ + { "yst", tZONE, HOUR ( 9) }, /* Yukon Standard */ + { "ydt", tDAYZONE, HOUR ( 9) }, /* Yukon Daylight */ + { "hst", tZONE, HOUR (10) }, /* Hawaii Standard */ + { "hdt", tDAYZONE, HOUR (10) }, /* Hawaii Daylight */ + { "cat", tZONE, HOUR (10) }, /* Central Alaska */ + { "ahst", tZONE, HOUR (10) }, /* Alaska-Hawaii Standard */ + { "nt", tZONE, HOUR (11) }, /* Nome */ + { "idlw", tZONE, HOUR (12) }, /* International Date Line West */ + { "cet", tZONE, -HOUR (1) }, /* Central European */ + { "met", tZONE, -HOUR (1) }, /* Middle European */ + { "mewt", tZONE, -HOUR (1) }, /* Middle European Winter */ + { "mest", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ + { "mesz", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ + { "swt", tZONE, -HOUR (1) }, /* Swedish Winter */ + { "sst", tDAYZONE, -HOUR (1) }, /* Swedish Summer */ + { "fwt", tZONE, -HOUR (1) }, /* French Winter */ + { "fst", tDAYZONE, -HOUR (1) }, /* French Summer */ + { "eet", tZONE, -HOUR (2) }, /* Eastern Europe, USSR Zone 1 */ + { "bt", tZONE, -HOUR (3) }, /* Baghdad, USSR Zone 2 */ +#if 0 + { "it", tZONE, -HOUR (3.5) },/* Iran */ +#endif + { "zp4", tZONE, -HOUR (4) }, /* USSR Zone 3 */ + { "zp5", tZONE, -HOUR (5) }, /* USSR Zone 4 */ +#if 0 + { "ist", tZONE, -HOUR (5.5) },/* Indian Standard */ +#endif + { "zp6", tZONE, -HOUR (6) }, /* USSR Zone 5 */ +#if 0 + /* For completeness. NST is also Newfoundland Standard, and SST is + * also Swedish Summer. */ + { "nst", tZONE, -HOUR (6.5) },/* North Sumatra */ + { "sst", tZONE, -HOUR (7) }, /* South Sumatra, USSR Zone 6 */ +#endif /* 0 */ + { "wast", tZONE, -HOUR (7) }, /* West Australian Standard */ + { "wadt", tDAYZONE, -HOUR (7) }, /* West Australian Daylight */ +#if 0 + { "jt", tZONE, -HOUR (7.5) },/* Java (3pm in Cronusland!) */ +#endif + { "cct", tZONE, -HOUR (8) }, /* China Coast, USSR Zone 7 */ + { "jst", tZONE, -HOUR (9) }, /* Japan Standard, USSR Zone 8 */ +#if 0 + { "cast", tZONE, -HOUR (9.5) },/* Central Australian Standard */ + { "cadt", tDAYZONE, -HOUR (9.5) },/* Central Australian Daylight */ +#endif + { "east", tZONE, -HOUR (10) }, /* Eastern Australian Standard */ + { "eadt", tDAYZONE, -HOUR (10) }, /* Eastern Australian Daylight */ + { "gst", tZONE, -HOUR (10) }, /* Guam Standard, USSR Zone 9 */ + { "nzt", tZONE, -HOUR (12) }, /* New Zealand */ + { "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */ + { "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */ + { "idle", tZONE, -HOUR (12) }, /* International Date Line East */ + { NULL } +}; + +/* Military timezone table. */ +static TABLE const MilitaryTable[] = { + { "a", tZONE, HOUR ( 1) }, + { "b", tZONE, HOUR ( 2) }, + { "c", tZONE, HOUR ( 3) }, + { "d", tZONE, HOUR ( 4) }, + { "e", tZONE, HOUR ( 5) }, + { "f", tZONE, HOUR ( 6) }, + { "g", tZONE, HOUR ( 7) }, + { "h", tZONE, HOUR ( 8) }, + { "i", tZONE, HOUR ( 9) }, + { "k", tZONE, HOUR ( 10) }, + { "l", tZONE, HOUR ( 11) }, + { "m", tZONE, HOUR ( 12) }, + { "n", tZONE, HOUR (- 1) }, + { "o", tZONE, HOUR (- 2) }, + { "p", tZONE, HOUR (- 3) }, + { "q", tZONE, HOUR (- 4) }, + { "r", tZONE, HOUR (- 5) }, + { "s", tZONE, HOUR (- 6) }, + { "t", tZONE, HOUR (- 7) }, + { "u", tZONE, HOUR (- 8) }, + { "v", tZONE, HOUR (- 9) }, + { "w", tZONE, HOUR (-10) }, + { "x", tZONE, HOUR (-11) }, + { "y", tZONE, HOUR (-12) }, + { "z", tZONE, HOUR ( 0) }, + { NULL } +}; + + + + +/* ARGSUSED */ +static int +yyerror (s) + char *s; +{ + return 0; +} + +static int +ToHour (Hours, Meridian) + int Hours; + MERIDIAN Meridian; +{ + switch (Meridian) + { + case MER24: + if (Hours < 0 || Hours > 23) + return -1; + return Hours; + case MERam: + if (Hours < 1 || Hours > 12) + return -1; + if (Hours == 12) + Hours = 0; + return Hours; + case MERpm: + if (Hours < 1 || Hours > 12) + return -1; + if (Hours == 12) + Hours = 0; + return Hours + 12; + default: + abort (); + } + /* NOTREACHED */ +} + +static int +ToYear (Year) + int Year; +{ + if (Year < 0) + Year = -Year; + + /* XPG4 suggests that years 00-68 map to 2000-2068, and + years 69-99 map to 1969-1999. */ + if (Year < 69) + Year += 2000; + else if (Year < 100) + Year += 1900; + + return Year; +} + +static int +LookupWord (buff) + char *buff; +{ + register char *p; + register char *q; + register const TABLE *tp; + int i; + int abbrev; + + /* Make it lowercase. */ + for (p = buff; *p; p++) + if (ISUPPER (*p)) + *p = tolower (*p); + + if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) + { + yylval.Meridian = MERam; + return tMERIDIAN; + } + if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) + { + yylval.Meridian = MERpm; + return tMERIDIAN; + } + + /* See if we have an abbreviation for a month. */ + if (strlen (buff) == 3) + abbrev = 1; + else if (strlen (buff) == 4 && buff[3] == '.') + { + abbrev = 1; + buff[3] = '\0'; + } + else + abbrev = 0; + + for (tp = MonthDayTable; tp->name; tp++) + { + if (abbrev) + { + if (strncmp (buff, tp->name, 3) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + } + else if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + } + + for (tp = TimezoneTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + if (strcmp (buff, "dst") == 0) + return tDST; + + for (tp = UnitsTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + /* Strip off any plural and try the units table again. */ + i = strlen (buff) - 1; + if (buff[i] == 's') + { + buff[i] = '\0'; + for (tp = UnitsTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + buff[i] = 's'; /* Put back for "this" in OtherTable. */ + } + + for (tp = OtherTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + /* Military timezones. */ + if (buff[1] == '\0' && ISALPHA (*buff)) + { + for (tp = MilitaryTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + } + + /* Drop out any periods and try the timezone table again. */ + for (i = 0, p = q = buff; *q; q++) + if (*q != '.') + *p++ = *q; + else + i++; + *p = '\0'; + if (i) + for (tp = TimezoneTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + return tID; +} + +static int +yylex () +{ + register char c; + register char *p; + char buff[20]; + int Count; + int sign; + + for (;;) + { + while (ISSPACE (*yyInput)) + yyInput++; + + if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') + { + if (c == '-' || c == '+') + { + sign = c == '-' ? -1 : 1; + if (!ISDIGIT (*++yyInput)) + /* skip the '-' sign */ + continue; + } + else + sign = 0; + for (yylval.Number = 0; ISDIGIT (c = *yyInput++);) + yylval.Number = 10 * yylval.Number + c - '0'; + yyInput--; + if (sign < 0) + yylval.Number = -yylval.Number; + return sign ? tSNUMBER : tUNUMBER; + } + if (ISALPHA (c)) + { + for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';) + if (p < &buff[sizeof buff - 1]) + *p++ = c; + *p = '\0'; + yyInput--; + return LookupWord (buff); + } + if (c != '(') + return *yyInput++; + Count = 0; + do + { + c = *yyInput++; + if (c == '\0') + return c; + if (c == '(') + Count++; + else if (c == ')') + Count--; + } + while (Count > 0); + } +} + +#define TM_YEAR_ORIGIN 1900 + +/* Yield A - B, measured in seconds. */ +static long +difftm (a, b) + struct tm *a, *b; +{ + int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); + int by = b->tm_year + (TM_YEAR_ORIGIN - 1); + long days = ( + /* difference in day of year */ + a->tm_yday - b->tm_yday + /* + intervening leap days */ + + ((ay >> 2) - (by >> 2)) + - (ay / 100 - by / 100) + + ((ay / 100 >> 2) - (by / 100 >> 2)) + /* + difference in years * 365 */ + + (long) (ay - by) * 365 + ); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} + +time_t +get_date (p, now) + const char *p; + const time_t *now; +{ + struct tm tm, tm0, *tmp; + time_t Start; + + yyInput = p; + Start = now ? *now : time ((time_t *) NULL); + tmp = localtime (&Start); + yyYear = tmp->tm_year + TM_YEAR_ORIGIN; + yyMonth = tmp->tm_mon + 1; + yyDay = tmp->tm_mday; + yyHour = tmp->tm_hour; + yyMinutes = tmp->tm_min; + yySeconds = tmp->tm_sec; + yyMeridian = MER24; + yyRelSeconds = 0; + yyRelMinutes = 0; + yyRelHour = 0; + yyRelDay = 0; + yyRelMonth = 0; + yyRelYear = 0; + yyHaveDate = 0; + yyHaveDay = 0; + yyHaveRel = 0; + yyHaveTime = 0; + yyHaveZone = 0; + + if (yyparse () + || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) + return -1; + + tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear; + tm.tm_mon = yyMonth - 1 + yyRelMonth; + tm.tm_mday = yyDay + yyRelDay; + if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) + { + tm.tm_hour = ToHour (yyHour, yyMeridian); + if (tm.tm_hour < 0) + return -1; + tm.tm_min = yyMinutes; + tm.tm_sec = yySeconds; + } + else + { + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + } + tm.tm_hour += yyRelHour; + tm.tm_min += yyRelMinutes; + tm.tm_sec += yyRelSeconds; + tm.tm_isdst = -1; + tm0 = tm; + + Start = mktime (&tm); + + if (Start == (time_t) -1) + { + + /* Guard against falsely reporting errors near the time_t boundaries + when parsing times in other time zones. For example, if the min + time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead + of UTC, then the min localtime value is 1970-01-01 08:00:00; if + we apply mktime to 1970-01-01 00:00:00 we will get an error, so + we apply mktime to 1970-01-02 08:00:00 instead and adjust the time + zone by 24 hours to compensate. This algorithm assumes that + there is no DST transition within a day of the time_t boundaries. */ + if (yyHaveZone) + { + tm = tm0; + if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) + { + tm.tm_mday++; + yyTimezone -= 24 * 60; + } + else + { + tm.tm_mday--; + yyTimezone += 24 * 60; + } + Start = mktime (&tm); + } + + if (Start == (time_t) -1) + return Start; + } + + if (yyHaveDay && !yyHaveDate) + { + tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7 + + 7 * (yyDayOrdinal - (0 < yyDayOrdinal))); + Start = mktime (&tm); + if (Start == (time_t) -1) + return Start; + } + + if (yyHaveZone) + { + long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start)); + if ((Start + delta < Start) != (delta < 0)) + return -1; /* time_t overflow */ + Start += delta; + } + + return Start; +} + +#if defined (TEST) + +/* ARGSUSED */ +int +main (ac, av) + int ac; + char *av[]; +{ + char buff[MAX_BUFF_LEN + 1]; + time_t d; + + (void) printf ("Enter date, or blank line to exit.\n\t> "); + (void) fflush (stdout); + + buff[MAX_BUFF_LEN] = 0; + while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) + { + d = get_date (buff, (time_t *) NULL); + if (d == -1) + (void) printf ("Bad format - couldn't convert.\n"); + else + (void) printf ("%s", ctime (&d)); + (void) printf ("\t> "); + (void) fflush (stdout); + } + exit (0); + /* NOTREACHED */ +} +#endif /* defined (TEST) */ diff --git a/libmisc/getdate.h b/libmisc/getdate.h new file mode 100644 index 00000000..c866afce --- /dev/null +++ b/libmisc/getdate.h @@ -0,0 +1,8 @@ +#ifndef _GETDATE_H_ +#define _GETDATE_H_ + +#include +#include "defines.h" + +time_t get_date P_((const char *p, const time_t *now)); +#endif diff --git a/libmisc/getdate.y b/libmisc/getdate.y new file mode 100644 index 00000000..d33fa063 --- /dev/null +++ b/libmisc/getdate.y @@ -0,0 +1,1024 @@ +%{ +/* +** Originally written by Steven M. Bellovin while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** and Jim Berets in August, 1990; +** +** This grammar has 13 shift/reduce conflicts. +** +** This code is in the public domain and has no copyright. +*/ + +#ifdef HAVE_CONFIG_H +# include +# ifdef FORCE_ALLOCA_H +# include +# endif +#endif + +/* Since the code of getdate.y is not included in the Emacs executable + itself, there is no need to #define static in this file. Even if + the code were included in the Emacs executable, it probably + wouldn't do any harm to #undef it here; this will only cause + problems if we try to write to a static variable, which I don't + think this code needs to do. */ +#ifdef emacs +# undef static +#endif + +#include +#include + +#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII)) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii(c) +#endif + +#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) +#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) +#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) + +/* ISDIGIT differs from ISDIGIT_LOCALE, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char. + - It's guaranteed to evaluate its argument exactly once. + - It's typically faster. + Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that + only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless + it's important to use the locale's definition of `digit' even when the + host does not conform to Posix. */ +#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) + +#include "getdate.h" + +#if defined (STDC_HEADERS) || defined (USG) +# include +#endif + +/* Some old versions of bison generate parsers that use bcopy. + That loses on systems that don't provide the function, so we have + to redefine it here. */ +#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy) +# define bcopy(from, to, len) memcpy ((to), (from), (len)) +#endif + +extern struct tm *gmtime (); +extern struct tm *localtime (); +extern time_t mktime (); + +/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc), + as well as gratuitiously global symbol names, so we can have multiple + yacc generated parsers in the same program. Note that these are only + the variables produced by yacc. If other parser generators (bison, + byacc, etc) produce additional global names that conflict at link time, + then those parser generators need to be fixed instead of adding those + names to this list. */ + +#define yymaxdepth gd_maxdepth +#define yyparse gd_parse +#define yylex gd_lex +#define yyerror gd_error +#define yylval gd_lval +#define yychar gd_char +#define yydebug gd_debug +#define yypact gd_pact +#define yyr1 gd_r1 +#define yyr2 gd_r2 +#define yydef gd_def +#define yychk gd_chk +#define yypgo gd_pgo +#define yyact gd_act +#define yyexca gd_exca +#define yyerrflag gd_errflag +#define yynerrs gd_nerrs +#define yyps gd_ps +#define yypv gd_pv +#define yys gd_s +#define yy_yys gd_yys +#define yystate gd_state +#define yytmp gd_tmp +#define yyv gd_v +#define yy_yyv gd_yyv +#define yyval gd_val +#define yylloc gd_lloc +#define yyreds gd_reds /* With YYDEBUG defined */ +#define yytoks gd_toks /* With YYDEBUG defined */ +#define yylhs gd_yylhs +#define yylen gd_yylen +#define yydefred gd_yydefred +#define yydgoto gd_yydgoto +#define yysindex gd_yysindex +#define yyrindex gd_yyrindex +#define yygindex gd_yygindex +#define yytable gd_yytable +#define yycheck gd_yycheck + +static int yylex (); +static int yyerror (); + +#define EPOCH 1970 +#define HOUR(x) ((x) * 60) + +#define MAX_BUFF_LEN 128 /* size of buffer to read the date into */ + +/* +** An entry in the lexical lookup table. +*/ +typedef struct _TABLE { + const char *name; + int type; + int value; +} TABLE; + + +/* +** Meridian: am, pm, or 24-hour style. +*/ +typedef enum _MERIDIAN { + MERam, MERpm, MER24 +} MERIDIAN; + + +/* +** Global variables. We could get rid of most of these by using a good +** union as the yacc stack. (This routine was originally written before +** yacc had the %union construct.) Maybe someday; right now we only use +** the %union very rarely. +*/ +static const char *yyInput; +static int yyDayOrdinal; +static int yyDayNumber; +static int yyHaveDate; +static int yyHaveDay; +static int yyHaveRel; +static int yyHaveTime; +static int yyHaveZone; +static int yyTimezone; +static int yyDay; +static int yyHour; +static int yyMinutes; +static int yyMonth; +static int yySeconds; +static int yyYear; +static MERIDIAN yyMeridian; +static int yyRelDay; +static int yyRelHour; +static int yyRelMinutes; +static int yyRelMonth; +static int yyRelSeconds; +static int yyRelYear; + +%} + +%union { + int Number; + enum _MERIDIAN Meridian; +} + +%token tAGO tDAY tDAY_UNIT tDAYZONE tDST tHOUR_UNIT tID +%token tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT +%token tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE + +%type tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tMINUTE_UNIT +%type tMONTH tMONTH_UNIT +%type tSEC_UNIT tSNUMBER tUNUMBER tYEAR_UNIT tZONE +%type tMERIDIAN o_merid + +%% + +spec : /* NULL */ + | spec item + ; + +item : time { + yyHaveTime++; + } + | zone { + yyHaveZone++; + } + | date { + yyHaveDate++; + } + | day { + yyHaveDay++; + } + | rel { + yyHaveRel++; + } + | number + ; + +time : tUNUMBER tMERIDIAN { + yyHour = $1; + yyMinutes = 0; + yySeconds = 0; + yyMeridian = $2; + } + | tUNUMBER ':' tUNUMBER o_merid { + yyHour = $1; + yyMinutes = $3; + yySeconds = 0; + yyMeridian = $4; + } + | tUNUMBER ':' tUNUMBER tSNUMBER { + yyHour = $1; + yyMinutes = $3; + yyMeridian = MER24; + yyHaveZone++; + yyTimezone = ($4 < 0 + ? -$4 % 100 + (-$4 / 100) * 60 + : - ($4 % 100 + ($4 / 100) * 60)); + } + | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { + yyHour = $1; + yyMinutes = $3; + yySeconds = $5; + yyMeridian = $6; + } + | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER { + yyHour = $1; + yyMinutes = $3; + yySeconds = $5; + yyMeridian = MER24; + yyHaveZone++; + yyTimezone = ($6 < 0 + ? -$6 % 100 + (-$6 / 100) * 60 + : - ($6 % 100 + ($6 / 100) * 60)); + } + ; + +zone : tZONE { + yyTimezone = $1; + } + | tDAYZONE { + yyTimezone = $1 - 60; + } + | + tZONE tDST { + yyTimezone = $1 - 60; + } + ; + +day : tDAY { + yyDayOrdinal = 1; + yyDayNumber = $1; + } + | tDAY ',' { + yyDayOrdinal = 1; + yyDayNumber = $1; + } + | tUNUMBER tDAY { + yyDayOrdinal = $1; + yyDayNumber = $2; + } + ; + +date : tUNUMBER '/' tUNUMBER { + yyMonth = $1; + yyDay = $3; + } + | tUNUMBER '/' tUNUMBER '/' tUNUMBER { + /* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY. + The goal in recognizing YYYY/MM/DD is solely to support legacy + machine-generated dates like those in an RCS log listing. If + you want portability, use the ISO 8601 format. */ + if ($1 >= 1000) + { + yyYear = $1; + yyMonth = $3; + yyDay = $5; + } + else + { + yyMonth = $1; + yyDay = $3; + yyYear = $5; + } + } + | tUNUMBER tSNUMBER tSNUMBER { + /* ISO 8601 format. yyyy-mm-dd. */ + yyYear = $1; + yyMonth = -$2; + yyDay = -$3; + } + | tUNUMBER tMONTH tSNUMBER { + /* e.g. 17-JUN-1992. */ + yyDay = $1; + yyMonth = $2; + yyYear = -$3; + } + | tMONTH tUNUMBER { + yyMonth = $1; + yyDay = $2; + } + | tMONTH tUNUMBER ',' tUNUMBER { + yyMonth = $1; + yyDay = $2; + yyYear = $4; + } + | tUNUMBER tMONTH { + yyMonth = $2; + yyDay = $1; + } + | tUNUMBER tMONTH tUNUMBER { + yyMonth = $2; + yyDay = $1; + yyYear = $3; + } + ; + +rel : relunit tAGO { + yyRelSeconds = -yyRelSeconds; + yyRelMinutes = -yyRelMinutes; + yyRelHour = -yyRelHour; + yyRelDay = -yyRelDay; + yyRelMonth = -yyRelMonth; + yyRelYear = -yyRelYear; + } + | relunit + ; + +relunit : tUNUMBER tYEAR_UNIT { + yyRelYear += $1 * $2; + } + | tSNUMBER tYEAR_UNIT { + yyRelYear += $1 * $2; + } + | tYEAR_UNIT { + yyRelYear++; + } + | tUNUMBER tMONTH_UNIT { + yyRelMonth += $1 * $2; + } + | tSNUMBER tMONTH_UNIT { + yyRelMonth += $1 * $2; + } + | tMONTH_UNIT { + yyRelMonth++; + } + | tUNUMBER tDAY_UNIT { + yyRelDay += $1 * $2; + } + | tSNUMBER tDAY_UNIT { + yyRelDay += $1 * $2; + } + | tDAY_UNIT { + yyRelDay++; + } + | tUNUMBER tHOUR_UNIT { + yyRelHour += $1 * $2; + } + | tSNUMBER tHOUR_UNIT { + yyRelHour += $1 * $2; + } + | tHOUR_UNIT { + yyRelHour++; + } + | tUNUMBER tMINUTE_UNIT { + yyRelMinutes += $1 * $2; + } + | tSNUMBER tMINUTE_UNIT { + yyRelMinutes += $1 * $2; + } + | tMINUTE_UNIT { + yyRelMinutes++; + } + | tUNUMBER tSEC_UNIT { + yyRelSeconds += $1 * $2; + } + | tSNUMBER tSEC_UNIT { + yyRelSeconds += $1 * $2; + } + | tSEC_UNIT { + yyRelSeconds++; + } + ; + +number : tUNUMBER + { + if (yyHaveTime && yyHaveDate && !yyHaveRel) + yyYear = $1; + else + { + if ($1>10000) + { + yyHaveDate++; + yyDay= ($1)%100; + yyMonth= ($1/100)%100; + yyYear = $1/10000; + } + else + { + yyHaveTime++; + if ($1 < 100) + { + yyHour = $1; + yyMinutes = 0; + } + else + { + yyHour = $1 / 100; + yyMinutes = $1 % 100; + } + yySeconds = 0; + yyMeridian = MER24; + } + } + } + ; + +o_merid : /* NULL */ + { + $$ = MER24; + } + | tMERIDIAN + { + $$ = $1; + } + ; + +%% + +/* Month and day table. */ +static TABLE const MonthDayTable[] = { + { "january", tMONTH, 1 }, + { "february", tMONTH, 2 }, + { "march", tMONTH, 3 }, + { "april", tMONTH, 4 }, + { "may", tMONTH, 5 }, + { "june", tMONTH, 6 }, + { "july", tMONTH, 7 }, + { "august", tMONTH, 8 }, + { "september", tMONTH, 9 }, + { "sept", tMONTH, 9 }, + { "october", tMONTH, 10 }, + { "november", tMONTH, 11 }, + { "december", tMONTH, 12 }, + { "sunday", tDAY, 0 }, + { "monday", tDAY, 1 }, + { "tuesday", tDAY, 2 }, + { "tues", tDAY, 2 }, + { "wednesday", tDAY, 3 }, + { "wednes", tDAY, 3 }, + { "thursday", tDAY, 4 }, + { "thur", tDAY, 4 }, + { "thurs", tDAY, 4 }, + { "friday", tDAY, 5 }, + { "saturday", tDAY, 6 }, + { NULL } +}; + +/* Time units table. */ +static TABLE const UnitsTable[] = { + { "year", tYEAR_UNIT, 1 }, + { "month", tMONTH_UNIT, 1 }, + { "fortnight", tDAY_UNIT, 14 }, + { "week", tDAY_UNIT, 7 }, + { "day", tDAY_UNIT, 1 }, + { "hour", tHOUR_UNIT, 1 }, + { "minute", tMINUTE_UNIT, 1 }, + { "min", tMINUTE_UNIT, 1 }, + { "second", tSEC_UNIT, 1 }, + { "sec", tSEC_UNIT, 1 }, + { NULL } +}; + +/* Assorted relative-time words. */ +static TABLE const OtherTable[] = { + { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 }, + { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 }, + { "today", tMINUTE_UNIT, 0 }, + { "now", tMINUTE_UNIT, 0 }, + { "last", tUNUMBER, -1 }, + { "this", tMINUTE_UNIT, 0 }, + { "next", tUNUMBER, 2 }, + { "first", tUNUMBER, 1 }, +/* { "second", tUNUMBER, 2 }, */ + { "third", tUNUMBER, 3 }, + { "fourth", tUNUMBER, 4 }, + { "fifth", tUNUMBER, 5 }, + { "sixth", tUNUMBER, 6 }, + { "seventh", tUNUMBER, 7 }, + { "eighth", tUNUMBER, 8 }, + { "ninth", tUNUMBER, 9 }, + { "tenth", tUNUMBER, 10 }, + { "eleventh", tUNUMBER, 11 }, + { "twelfth", tUNUMBER, 12 }, + { "ago", tAGO, 1 }, + { NULL } +}; + +/* The timezone table. */ +static TABLE const TimezoneTable[] = { + { "gmt", tZONE, HOUR ( 0) }, /* Greenwich Mean */ + { "ut", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ + { "utc", tZONE, HOUR ( 0) }, + { "wet", tZONE, HOUR ( 0) }, /* Western European */ + { "bst", tDAYZONE, HOUR ( 0) }, /* British Summer */ + { "wat", tZONE, HOUR ( 1) }, /* West Africa */ + { "at", tZONE, HOUR ( 2) }, /* Azores */ +#if 0 + /* For completeness. BST is also British Summer, and GST is + * also Guam Standard. */ + { "bst", tZONE, HOUR ( 3) }, /* Brazil Standard */ + { "gst", tZONE, HOUR ( 3) }, /* Greenland Standard */ +#endif +#if 0 + { "nft", tZONE, HOUR (3.5) }, /* Newfoundland */ + { "nst", tZONE, HOUR (3.5) }, /* Newfoundland Standard */ + { "ndt", tDAYZONE, HOUR (3.5) }, /* Newfoundland Daylight */ +#endif + { "ast", tZONE, HOUR ( 4) }, /* Atlantic Standard */ + { "adt", tDAYZONE, HOUR ( 4) }, /* Atlantic Daylight */ + { "est", tZONE, HOUR ( 5) }, /* Eastern Standard */ + { "edt", tDAYZONE, HOUR ( 5) }, /* Eastern Daylight */ + { "cst", tZONE, HOUR ( 6) }, /* Central Standard */ + { "cdt", tDAYZONE, HOUR ( 6) }, /* Central Daylight */ + { "mst", tZONE, HOUR ( 7) }, /* Mountain Standard */ + { "mdt", tDAYZONE, HOUR ( 7) }, /* Mountain Daylight */ + { "pst", tZONE, HOUR ( 8) }, /* Pacific Standard */ + { "pdt", tDAYZONE, HOUR ( 8) }, /* Pacific Daylight */ + { "yst", tZONE, HOUR ( 9) }, /* Yukon Standard */ + { "ydt", tDAYZONE, HOUR ( 9) }, /* Yukon Daylight */ + { "hst", tZONE, HOUR (10) }, /* Hawaii Standard */ + { "hdt", tDAYZONE, HOUR (10) }, /* Hawaii Daylight */ + { "cat", tZONE, HOUR (10) }, /* Central Alaska */ + { "ahst", tZONE, HOUR (10) }, /* Alaska-Hawaii Standard */ + { "nt", tZONE, HOUR (11) }, /* Nome */ + { "idlw", tZONE, HOUR (12) }, /* International Date Line West */ + { "cet", tZONE, -HOUR (1) }, /* Central European */ + { "met", tZONE, -HOUR (1) }, /* Middle European */ + { "mewt", tZONE, -HOUR (1) }, /* Middle European Winter */ + { "mest", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ + { "mesz", tDAYZONE, -HOUR (1) }, /* Middle European Summer */ + { "swt", tZONE, -HOUR (1) }, /* Swedish Winter */ + { "sst", tDAYZONE, -HOUR (1) }, /* Swedish Summer */ + { "fwt", tZONE, -HOUR (1) }, /* French Winter */ + { "fst", tDAYZONE, -HOUR (1) }, /* French Summer */ + { "eet", tZONE, -HOUR (2) }, /* Eastern Europe, USSR Zone 1 */ + { "bt", tZONE, -HOUR (3) }, /* Baghdad, USSR Zone 2 */ +#if 0 + { "it", tZONE, -HOUR (3.5) },/* Iran */ +#endif + { "zp4", tZONE, -HOUR (4) }, /* USSR Zone 3 */ + { "zp5", tZONE, -HOUR (5) }, /* USSR Zone 4 */ +#if 0 + { "ist", tZONE, -HOUR (5.5) },/* Indian Standard */ +#endif + { "zp6", tZONE, -HOUR (6) }, /* USSR Zone 5 */ +#if 0 + /* For completeness. NST is also Newfoundland Standard, and SST is + * also Swedish Summer. */ + { "nst", tZONE, -HOUR (6.5) },/* North Sumatra */ + { "sst", tZONE, -HOUR (7) }, /* South Sumatra, USSR Zone 6 */ +#endif /* 0 */ + { "wast", tZONE, -HOUR (7) }, /* West Australian Standard */ + { "wadt", tDAYZONE, -HOUR (7) }, /* West Australian Daylight */ +#if 0 + { "jt", tZONE, -HOUR (7.5) },/* Java (3pm in Cronusland!) */ +#endif + { "cct", tZONE, -HOUR (8) }, /* China Coast, USSR Zone 7 */ + { "jst", tZONE, -HOUR (9) }, /* Japan Standard, USSR Zone 8 */ +#if 0 + { "cast", tZONE, -HOUR (9.5) },/* Central Australian Standard */ + { "cadt", tDAYZONE, -HOUR (9.5) },/* Central Australian Daylight */ +#endif + { "east", tZONE, -HOUR (10) }, /* Eastern Australian Standard */ + { "eadt", tDAYZONE, -HOUR (10) }, /* Eastern Australian Daylight */ + { "gst", tZONE, -HOUR (10) }, /* Guam Standard, USSR Zone 9 */ + { "nzt", tZONE, -HOUR (12) }, /* New Zealand */ + { "nzst", tZONE, -HOUR (12) }, /* New Zealand Standard */ + { "nzdt", tDAYZONE, -HOUR (12) }, /* New Zealand Daylight */ + { "idle", tZONE, -HOUR (12) }, /* International Date Line East */ + { NULL } +}; + +/* Military timezone table. */ +static TABLE const MilitaryTable[] = { + { "a", tZONE, HOUR ( 1) }, + { "b", tZONE, HOUR ( 2) }, + { "c", tZONE, HOUR ( 3) }, + { "d", tZONE, HOUR ( 4) }, + { "e", tZONE, HOUR ( 5) }, + { "f", tZONE, HOUR ( 6) }, + { "g", tZONE, HOUR ( 7) }, + { "h", tZONE, HOUR ( 8) }, + { "i", tZONE, HOUR ( 9) }, + { "k", tZONE, HOUR ( 10) }, + { "l", tZONE, HOUR ( 11) }, + { "m", tZONE, HOUR ( 12) }, + { "n", tZONE, HOUR (- 1) }, + { "o", tZONE, HOUR (- 2) }, + { "p", tZONE, HOUR (- 3) }, + { "q", tZONE, HOUR (- 4) }, + { "r", tZONE, HOUR (- 5) }, + { "s", tZONE, HOUR (- 6) }, + { "t", tZONE, HOUR (- 7) }, + { "u", tZONE, HOUR (- 8) }, + { "v", tZONE, HOUR (- 9) }, + { "w", tZONE, HOUR (-10) }, + { "x", tZONE, HOUR (-11) }, + { "y", tZONE, HOUR (-12) }, + { "z", tZONE, HOUR ( 0) }, + { NULL } +}; + + + + +/* ARGSUSED */ +static int +yyerror (s) + char *s; +{ + return 0; +} + +static int +ToHour (Hours, Meridian) + int Hours; + MERIDIAN Meridian; +{ + switch (Meridian) + { + case MER24: + if (Hours < 0 || Hours > 23) + return -1; + return Hours; + case MERam: + if (Hours < 1 || Hours > 12) + return -1; + if (Hours == 12) + Hours = 0; + return Hours; + case MERpm: + if (Hours < 1 || Hours > 12) + return -1; + if (Hours == 12) + Hours = 0; + return Hours + 12; + default: + abort (); + } + /* NOTREACHED */ +} + +static int +ToYear (Year) + int Year; +{ + if (Year < 0) + Year = -Year; + + /* XPG4 suggests that years 00-68 map to 2000-2068, and + years 69-99 map to 1969-1999. */ + if (Year < 69) + Year += 2000; + else if (Year < 100) + Year += 1900; + + return Year; +} + +static int +LookupWord (buff) + char *buff; +{ + register char *p; + register char *q; + register const TABLE *tp; + int i; + int abbrev; + + /* Make it lowercase. */ + for (p = buff; *p; p++) + if (ISUPPER (*p)) + *p = tolower (*p); + + if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) + { + yylval.Meridian = MERam; + return tMERIDIAN; + } + if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) + { + yylval.Meridian = MERpm; + return tMERIDIAN; + } + + /* See if we have an abbreviation for a month. */ + if (strlen (buff) == 3) + abbrev = 1; + else if (strlen (buff) == 4 && buff[3] == '.') + { + abbrev = 1; + buff[3] = '\0'; + } + else + abbrev = 0; + + for (tp = MonthDayTable; tp->name; tp++) + { + if (abbrev) + { + if (strncmp (buff, tp->name, 3) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + } + else if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + } + + for (tp = TimezoneTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + if (strcmp (buff, "dst") == 0) + return tDST; + + for (tp = UnitsTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + /* Strip off any plural and try the units table again. */ + i = strlen (buff) - 1; + if (buff[i] == 's') + { + buff[i] = '\0'; + for (tp = UnitsTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + buff[i] = 's'; /* Put back for "this" in OtherTable. */ + } + + for (tp = OtherTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + /* Military timezones. */ + if (buff[1] == '\0' && ISALPHA (*buff)) + { + for (tp = MilitaryTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + } + + /* Drop out any periods and try the timezone table again. */ + for (i = 0, p = q = buff; *q; q++) + if (*q != '.') + *p++ = *q; + else + i++; + *p = '\0'; + if (i) + for (tp = TimezoneTable; tp->name; tp++) + if (strcmp (buff, tp->name) == 0) + { + yylval.Number = tp->value; + return tp->type; + } + + return tID; +} + +static int +yylex () +{ + register char c; + register char *p; + char buff[20]; + int Count; + int sign; + + for (;;) + { + while (ISSPACE (*yyInput)) + yyInput++; + + if (ISDIGIT (c = *yyInput) || c == '-' || c == '+') + { + if (c == '-' || c == '+') + { + sign = c == '-' ? -1 : 1; + if (!ISDIGIT (*++yyInput)) + /* skip the '-' sign */ + continue; + } + else + sign = 0; + for (yylval.Number = 0; ISDIGIT (c = *yyInput++);) + yylval.Number = 10 * yylval.Number + c - '0'; + yyInput--; + if (sign < 0) + yylval.Number = -yylval.Number; + return sign ? tSNUMBER : tUNUMBER; + } + if (ISALPHA (c)) + { + for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';) + if (p < &buff[sizeof buff - 1]) + *p++ = c; + *p = '\0'; + yyInput--; + return LookupWord (buff); + } + if (c != '(') + return *yyInput++; + Count = 0; + do + { + c = *yyInput++; + if (c == '\0') + return c; + if (c == '(') + Count++; + else if (c == ')') + Count--; + } + while (Count > 0); + } +} + +#define TM_YEAR_ORIGIN 1900 + +/* Yield A - B, measured in seconds. */ +static long +difftm (a, b) + struct tm *a, *b; +{ + int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); + int by = b->tm_year + (TM_YEAR_ORIGIN - 1); + long days = ( + /* difference in day of year */ + a->tm_yday - b->tm_yday + /* + intervening leap days */ + + ((ay >> 2) - (by >> 2)) + - (ay / 100 - by / 100) + + ((ay / 100 >> 2) - (by / 100 >> 2)) + /* + difference in years * 365 */ + + (long) (ay - by) * 365 + ); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} + +time_t +get_date (p, now) + const char *p; + const time_t *now; +{ + struct tm tm, tm0, *tmp; + time_t Start; + + yyInput = p; + Start = now ? *now : time ((time_t *) NULL); + tmp = localtime (&Start); + yyYear = tmp->tm_year + TM_YEAR_ORIGIN; + yyMonth = tmp->tm_mon + 1; + yyDay = tmp->tm_mday; + yyHour = tmp->tm_hour; + yyMinutes = tmp->tm_min; + yySeconds = tmp->tm_sec; + yyMeridian = MER24; + yyRelSeconds = 0; + yyRelMinutes = 0; + yyRelHour = 0; + yyRelDay = 0; + yyRelMonth = 0; + yyRelYear = 0; + yyHaveDate = 0; + yyHaveDay = 0; + yyHaveRel = 0; + yyHaveTime = 0; + yyHaveZone = 0; + + if (yyparse () + || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) + return -1; + + tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear; + tm.tm_mon = yyMonth - 1 + yyRelMonth; + tm.tm_mday = yyDay + yyRelDay; + if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay)) + { + tm.tm_hour = ToHour (yyHour, yyMeridian); + if (tm.tm_hour < 0) + return -1; + tm.tm_min = yyMinutes; + tm.tm_sec = yySeconds; + } + else + { + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + } + tm.tm_hour += yyRelHour; + tm.tm_min += yyRelMinutes; + tm.tm_sec += yyRelSeconds; + tm.tm_isdst = -1; + tm0 = tm; + + Start = mktime (&tm); + + if (Start == (time_t) -1) + { + + /* Guard against falsely reporting errors near the time_t boundaries + when parsing times in other time zones. For example, if the min + time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead + of UTC, then the min localtime value is 1970-01-01 08:00:00; if + we apply mktime to 1970-01-01 00:00:00 we will get an error, so + we apply mktime to 1970-01-02 08:00:00 instead and adjust the time + zone by 24 hours to compensate. This algorithm assumes that + there is no DST transition within a day of the time_t boundaries. */ + if (yyHaveZone) + { + tm = tm0; + if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) + { + tm.tm_mday++; + yyTimezone -= 24 * 60; + } + else + { + tm.tm_mday--; + yyTimezone += 24 * 60; + } + Start = mktime (&tm); + } + + if (Start == (time_t) -1) + return Start; + } + + if (yyHaveDay && !yyHaveDate) + { + tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7 + + 7 * (yyDayOrdinal - (0 < yyDayOrdinal))); + Start = mktime (&tm); + if (Start == (time_t) -1) + return Start; + } + + if (yyHaveZone) + { + long delta = yyTimezone * 60L + difftm (&tm, gmtime (&Start)); + if ((Start + delta < Start) != (delta < 0)) + return -1; /* time_t overflow */ + Start += delta; + } + + return Start; +} + +#if defined (TEST) + +/* ARGSUSED */ +int +main (ac, av) + int ac; + char *av[]; +{ + char buff[MAX_BUFF_LEN + 1]; + time_t d; + + (void) printf ("Enter date, or blank line to exit.\n\t> "); + (void) fflush (stdout); + + buff[MAX_BUFF_LEN] = 0; + while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) + { + d = get_date (buff, (time_t *) NULL); + if (d == -1) + (void) printf ("Bad format - couldn't convert.\n"); + else + (void) printf ("%s", ctime (&d)); + (void) printf ("\t> "); + (void) fflush (stdout); + } + exit (0); + /* NOTREACHED */ +} +#endif /* defined (TEST) */ diff --git a/libmisc/hushed.c b/libmisc/hushed.c new file mode 100644 index 00000000..c9990d16 --- /dev/null +++ b/libmisc/hushed.c @@ -0,0 +1,90 @@ +/* + * Copyright 1991, 1993, Julianne Frances Haugh and Chip Rosenthal + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: hushed.c,v 1.3 1997/12/07 23:27:05 marekm Exp $") + +#include +#include +#include "defines.h" +#include "prototypes.h" +#include "getdef.h" +#include + +/* + * hushed - determine if a user receives login messages + * + * Look in the hushed-logins file (or user's home directory) to see + * if the user is to receive the login-time messages. + */ + +int +hushed(const struct passwd *pw) +{ + char *hushfile; + char buf[BUFSIZ]; + int found; + FILE *fp; + + /* + * Get the name of the file to use. If this option is not + * defined, default to a noisy login. + */ + + if ( (hushfile=getdef_str("HUSHLOGIN_FILE")) == NULL ) + return 0; + + /* + * If this is not a fully rooted path then see if the + * file exists in the user's home directory. + */ + + if (hushfile[0] != '/') { + strcat(strcat(strcpy(buf, pw->pw_dir), "/"), hushfile); + return (access(buf, F_OK) == 0); + } + + /* + * If this is a fully rooted path then go through the file + * and see if this user is in there. + */ + + if ((fp = fopen(hushfile, "r")) == NULL) + return 0; + + for (found = 0;! found && fgets (buf, sizeof buf, fp);) { + buf[strlen (buf) - 1] = '\0'; + found = ! strcmp (buf, + buf[0] == '/' ? pw->pw_shell:pw->pw_name); + } + (void) fclose(fp); + return found; +} diff --git a/libmisc/isexpired.c b/libmisc/isexpired.c new file mode 100644 index 00000000..d70b2a79 --- /dev/null +++ b/libmisc/isexpired.c @@ -0,0 +1,173 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Extracted from age.c and made part of libshadow.a - may be useful + * in other shadow-aware programs. --marekm + */ + +#include + +#include +#include "prototypes.h" +#include "defines.h" +#include +#include + +#ifdef HAVE_USERSEC_H +#include +#include +#include +#endif + +#ifndef AGING +#if defined(SHADOWPWD) || defined(HAVE_USERSEC_H) +#define AGING 1 +#endif +#else +#if !defined(SHADOWPWD) && !defined(HAVE_USERSEC_H) && !defined(ATT_AGE) +#undef AGING +#endif +#endif + +#if defined(SHADOWPWD) || defined(AGING) /*{*/ + +#include "rcsid.h" +RCSID("$Id: isexpired.c,v 1.7 1997/12/07 23:27:05 marekm Exp $") + +/* + * isexpired - determine if account is expired yet + * + * isexpired calculates the expiration date based on the + * password expiration criteria. + */ + +/*ARGSUSED*/ + +#ifdef SHADOWPWD +int +isexpired(const struct passwd *pw, const struct spwd *sp) +{ +#else +int +isexpired(const struct passwd *pw) +{ +#endif + long now; +#ifdef HAVE_USERSEC_H + int minage = 0; + int maxage = 10000; + int curage = 0; + struct userpw *pu; +#endif + + now = time ((time_t *) 0) / SCALE; + +#ifdef SHADOWPWD + + if (!sp) + sp = pwd_to_spwd(pw); + + /* + * Quick and easy - there is an expired account field + * along with an inactive account field. Do the expired + * one first since it is worse. + */ + + if (sp->sp_expire > 0 && now >= sp->sp_expire) + return 3; + + /* + * Last changed date 1970-01-01 (not very likely) means that + * the password must be changed on next login (passwd -e). + * + * The check for "x" is a workaround for RedHat NYS libc bug - + * if /etc/shadow doesn't exist, getspnam() still succeeds and + * returns sp_lstchg==0 (must change password) instead of -1! + */ + if (sp->sp_lstchg == 0 && !strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING)) + return 1; + + if (sp->sp_lstchg > 0 && sp->sp_max >= 0 && sp->sp_inact >= 0 && + now >= sp->sp_lstchg + sp->sp_max + sp->sp_inact) + return 2; +#endif +#ifdef HAVE_USERSEC_H /*{*/ + /* + * The aging information lives someplace else. Get it from the + * login.cfg file + */ + + if (getconfattr (SC_SYS_PASSWD, SC_MINAGE, &minage, SEC_INT)) + minage = -1; + + if (getconfattr (SC_SYS_PASSWD, SC_MAXAGE, &maxage, SEC_INT)) + maxage = -1; + + pu = getuserpw (pw->pw_name); + curage = (time (0) - pu->upw_lastupdate) / (7*86400L); + + if (maxage != -1 && curage > maxage) + return 1; +#else /*} !HAVE_USERSEC_H */ + + /* + * The last and max fields must be present for an account + * to have an expired password. A maximum of >10000 days + * is considered to be infinite. + */ + +#ifdef SHADOWPWD + if (sp->sp_lstchg == -1 || + sp->sp_max == -1 || sp->sp_max >= (10000L*DAY/SCALE)) + return 0; +#endif +#ifdef ATT_AGE + if (pw->pw_age[0] == '\0' || pw->pw_age[0] == '/') + return 0; +#endif + + /* + * Calculate today's day and the day on which the password + * is going to expire. If that date has already passed, + * the password has expired. + */ + +#ifdef SHADOWPWD + if (now >= sp->sp_lstchg + sp->sp_max) + return 1; +#endif +#ifdef ATT_AGE + if (a64l (pw->pw_age + 2) + c64i (pw->pw_age[1]) < now / 7) + return 1; +#endif +#endif /*} HAVE_USERSEC_H */ + return 0; +} +#endif /*}*/ diff --git a/libmisc/limits.c b/libmisc/limits.c new file mode 100644 index 00000000..0769b1d9 --- /dev/null +++ b/libmisc/limits.c @@ -0,0 +1,394 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Separated from setup.c. --marekm + * Resource limits thanks to Cristian Gafton. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: limits.c,v 1.9 1999/03/07 19:14:39 marekm Exp $") + +#include +#include + +#include + +#include "prototypes.h" +#include "defines.h" +#include +#include "getdef.h" + +#ifdef HAVE_SYS_RESOURCE_H +#include +#define LIMITS +#endif + +#ifdef LIMITS + +#ifndef LIMITS_FILE +#define LIMITS_FILE "/etc/limits" +#endif + +#define LOGIN_ERROR_RLIMIT 1 +#define LOGIN_ERROR_LOGIN 2 + +/* Set a limit on a resource */ +/* + * rlimit - RLIMIT_XXXX + * value - string value to be read + * multiplier - value*multiplier is the actual limit + */ +static int +setrlimit_value(unsigned int rlimit, const char *value, unsigned int multiplier) +{ + struct rlimit rlim; + long limit; + char **endptr = (char **) &value; + const char *value_orig = value; + + limit = strtol(value, endptr, 10); + if (limit == 0 && value_orig == *endptr) /* no chars read */ + return 0; + limit *= multiplier; + rlim.rlim_cur = limit; + rlim.rlim_max = limit; + if (setrlimit(rlimit, &rlim)) + return LOGIN_ERROR_RLIMIT; + return 0; +} + + +static int +set_prio(const char *value) +{ + int prio; + char **endptr = (char **) &value; + + prio = strtol(value, endptr, 10); + if ((prio == 0) && (value == *endptr)) + return 0; + if (setpriority(PRIO_PROCESS, 0, prio)) + return LOGIN_ERROR_RLIMIT; + return 0; +} + + +/* Counts the number of user logins and check against the limit */ +static int +check_logins(const char *name, const char *maxlogins) +{ + struct utmp *ut; + unsigned int limit, count; + char **endptr = (char **) &maxlogins; + const char *ml_orig = maxlogins; + + limit = strtol(maxlogins, endptr, 10); + if (limit == 0 && ml_orig == *endptr) /* no chars read */ + return 0; + + if (limit == 0) /* maximum 0 logins ? */ { + SYSLOG((LOG_WARN, "No logins allowed for `%s'\n", name)); + return LOGIN_ERROR_LOGIN; + } + + setutent(); + count = 0; + while ((ut = getutent())) { +#ifdef USER_PROCESS + if (ut->ut_type != USER_PROCESS) + continue; +#endif + if (ut->ut_user[0] == '\0') + continue; + if (strncmp(name, ut->ut_user, sizeof(ut->ut_user)) != 0) + continue; + if (++count > limit) + break; + } + endutent(); + /* + * This is called after setutmp(), so the number of logins counted + * includes the user who is currently trying to log in. + */ + if (count > limit) { + SYSLOG((LOG_WARN, "Too many logins (max %d) for %s\n", + limit, name)); + return LOGIN_ERROR_LOGIN; + } + return 0; +} + +/* Function setup_user_limits - checks/set limits for the curent login + * Original idea from Joel Katz's lshell. Ported to shadow-login + * by Cristian Gafton - gafton@sorosis.ro + * + * We are passed a string of the form ('BASH' constants for ulimit) + * [Aa][Cc][Dd][Ff][Mm][Nn][Rr][Ss][Tt][Uu][Ll][Pp] + * (eg. 'C2F256D2048N5' or 'C2 F256 D2048 N5') + * where: + * [Aa]: a = RLIMIT_AS max address space (KB) + * [Cc]: c = RLIMIT_CORE max core file size (KB) + * [Dd]: d = RLIMIT_DATA max data size (KB) + * [Ff]: f = RLIMIT_FSIZE Maximum filesize (KB) + * [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB) + * [Nn]: n = RLIMIT_NOFILE max number of open files + * [Rr]: r = RLIMIT_RSS max resident set size (KB) + * [Ss]: s = RLIMIT_STACK max stack size (KB) + * [Tt]: t = RLIMIT_CPU max CPU time (MIN) + * [Uu]: u = RLIMIT_NPROC max number of processes + * [Ll]: l = max number of logins for this user + * [Pp]: p = process priority -20..20 (negative = high priority) + * + * Return value: + * 0 = okay, of course + * LOGIN_ERROR_RLIMIT = error setting some RLIMIT + * LOGIN_ERROR_LOGIN = error - too many logins for this user + * + * buf - the limits string + * name - the username + */ +static int +do_user_limits(const char *buf, const char *name) +{ + const char *pp; + int retval = 0; + + pp = buf; + + while (*pp != '\0') switch(*pp++) { +#ifdef RLIMIT_AS + case 'a': + case 'A': + /* RLIMIT_AS - max address space (KB) */ + retval |= setrlimit_value(RLIMIT_AS, pp, 1024); +#endif +#ifdef RLIMIT_CPU + case 't': + case 'T': + /* RLIMIT_CPU - max CPU time (MIN) */ + retval |= setrlimit_value(RLIMIT_CPU, pp, 60); + break; +#endif +#ifdef RLIMIT_DATA + case 'd': + case 'D': + /* RLIMIT_DATA - max data size (KB) */ + retval |= setrlimit_value(RLIMIT_DATA, pp, 1024); + break; +#endif +#ifdef RLIMIT_FSIZE + case 'f': + case 'F': + /* RLIMIT_FSIZE - Maximum filesize (KB) */ + retval |= setrlimit_value(RLIMIT_FSIZE, pp, 1024); + break; +#endif +#ifdef RLIMIT_NPROC + case 'u': + case 'U': + /* RLIMIT_NPROC - max number of processes */ + retval |= setrlimit_value(RLIMIT_NPROC, pp, 1); + break; +#endif +#ifdef RLIMIT_CORE + case 'c': + case 'C': + /* RLIMIT_CORE - max core file size (KB) */ + retval |= setrlimit_value(RLIMIT_CORE, pp, 1024); + break; +#endif +#ifdef RLIMIT_MEMLOCK + case 'm': + case 'M': + /* RLIMIT_MEMLOCK - max locked-in-memory address space (KB) */ + retval |= setrlimit_value(RLIMIT_MEMLOCK, pp, 1024); + break; +#endif +#ifdef RLIMIT_NOFILE + case 'n': + case 'N': + /* RLIMIT_NOFILE - max number of open files */ + retval |= setrlimit_value(RLIMIT_NOFILE, pp, 1); + break; +#endif +#ifdef RLIMIT_RSS + case 'r': + case 'R': + /* RLIMIT_RSS - max resident set size (KB) */ + retval |= setrlimit_value(RLIMIT_RSS, pp, 1024); + break; +#endif +#ifdef RLIMIT_STACK + case 's': + case 'S': + /* RLIMIT_STACK - max stack size (KB) */ + retval |= setrlimit_value(RLIMIT_STACK, pp, 1024); + break; +#endif + case 'l': + case 'L': + /* LIMIT the number of concurent logins */ + retval |= check_logins(name, pp); + break; + case 'p': + case 'P': + retval |= set_prio(pp); + break; + } + return retval; +} + +static int +setup_user_limits(const char *uname) +{ + /* TODO: allow and use @group syntax --cristiang */ + FILE *fil; + char buf[1024]; + char name[1024]; + char limits[1024]; + char deflimits[1024]; + char tempbuf[1024]; + + /* init things */ + memzero(buf, sizeof(buf)); + memzero(name, sizeof(name)); + memzero(limits, sizeof(limits)); + memzero(deflimits, sizeof(deflimits)); + memzero(tempbuf, sizeof(tempbuf)); + + /* start the checks */ + fil = fopen(LIMITS_FILE, "r"); + if (fil == NULL) { +#if 0 /* no limits file is ok, not everyone is a BOFH :-). --marekm */ + SYSLOG((LOG_WARN, NO_LIMITS, uname, LIMITS_FILE)); +#endif + return 0; + } + /* The limits file have the following format: + * - '#' (comment) chars only as first chars on a line; + * - username must start on first column + * A better (smarter) checking should be done --cristiang */ + while (fgets(buf, 1024, fil) != NULL) { + if (buf[0]=='#' || buf[0]=='\n') + continue; + memzero(tempbuf, sizeof(tempbuf)); + /* a valid line should have a username, then spaces, + * then limits + * we allow the format: + * username L2 D2048 R4096 + * where spaces={' ',\t}. Also, we reject invalid limits. + * Imposing a limit should be done with care, so a wrong + * entry means no care anyway :-). A '-' as a limits + * strings means no limits --cristiang */ + if (sscanf(buf, "%s%[ACDFMNRSTULPacdfmnrstulp0-9 \t-]", + name, tempbuf) == 2) { + if (strcmp(name, uname) == 0) { + strcpy(limits, tempbuf); + break; + } else if (strcmp(name, "*") == 0) { + strcpy(deflimits, tempbuf); + } + } + } + fclose(fil); + if (limits[0] == '\0') { + /* no user specific limits */ + if (deflimits[0] == '\0') /* no default limits */ + return 0; + strcpy(limits, deflimits); /* use the default limits */ + } + return do_user_limits(limits, uname); +} +#endif /* LIMITS */ + +/* + * set the process nice, ulimit, and umask from the password file entry + */ + +void +setup_limits(const struct passwd *info) +{ + char *cp; + int i; + long l; + +#ifdef USERGROUPS + if (info->pw_uid != 0 && info->pw_uid == info->pw_gid) { + const struct group *grp; + + grp = getgrgid(info->pw_gid); + if (grp && !strcmp(info->pw_name, grp->gr_name)) { + umask(umask(0) & ~070); + } + } +#endif + + /* + * See if the GECOS field contains values for NICE, UMASK or ULIMIT. + * If this feature is enabled in /etc/login.defs, we make those + * values the defaults for this login session. + */ + + if ( getdef_bool("QUOTAS_ENAB") ) { +#ifdef LIMITS + if (info->pw_uid) + if (setup_user_limits(info->pw_name) & LOGIN_ERROR_LOGIN) { + fprintf(stderr, _("Too many logins.\n")); + sleep(2); + exit(1); + } +#endif + for (cp = info->pw_gecos ; cp != NULL ; cp = strchr (cp, ',')) { + if (*cp == ',') + cp++; + + if (strncmp (cp, "pri=", 4) == 0) { + i = atoi (cp + 4); + if (i >= -20 && i <= 20) + (void) nice (i); + + continue; + } + if (strncmp (cp, "ulimit=", 7) == 0) { + l = strtol (cp + 7, (char **) 0, 10); + set_filesize_limit(l); + continue; + } + if (strncmp (cp, "umask=", 6) == 0) { + i = strtol (cp + 6, (char **) 0, 8) & 0777; + (void) umask (i); + + continue; + } + } + } +} diff --git a/libmisc/list.c b/libmisc/list.c new file mode 100644 index 00000000..db63c8dc --- /dev/null +++ b/libmisc/list.c @@ -0,0 +1,234 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Removed duplicated code from gpmain.c, useradd.c, userdel.c and + usermod.c. --marekm */ + +#include + +#include "rcsid.h" +RCSID("$Id: list.c,v 1.3 1997/12/07 23:27:05 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" + +/* + * add_list - add a member to a list of group members + * + * the array of member names is searched for the new member + * name, and if not present it is added to a freshly allocated + * list of users. + */ + +char ** +add_list(char **list, const char *member) +{ + int i; + char **tmp; + + /* + * Scan the list for the new name. Return the original list + * pointer if it is present. + */ + + for (i = 0;list[i] != (char *) 0;i++) + if (strcmp (list[i], member) == 0) + return list; + + /* + * Allocate a new list pointer large enough to hold all the + * old entries, and the new entries as well. + */ + + tmp = (char **) xmalloc ((i + 2) * sizeof member); + + /* + * Copy the original list to the new list, then append the + * new member and NULL terminate the result. This new list + * is returned to the invoker. + */ + + for (i = 0;list[i] != (char *) 0;i++) + tmp[i] = list[i]; + + tmp[i++] = xstrdup (member); + tmp[i] = (char *) 0; + + return tmp; +} + +/* + * del_list - delete a member from a list of group members + * + * the array of member names is searched for the old member + * name, and if present it is deleted from a freshly allocated + * list of users. + */ + +char ** +del_list(char **list, const char *member) +{ + int i, j; + char **tmp; + + /* + * Scan the list for the old name. Return the original list + * pointer if it is not present. + */ + + for (i = j = 0;list[i] != (char *) 0;i++) + if (strcmp (list[i], member)) + j++; + + if (j == i) + return list; + + /* + * Allocate a new list pointer large enough to hold all the + * old entries. + */ + + tmp = (char **) xmalloc ((j + 1) * sizeof member); + + /* + * Copy the original list except the deleted members to the + * new list, then NULL terminate the result. This new list + * is returned to the invoker. + */ + + for (i = j = 0;list[i] != (char *) 0;i++) + if (strcmp (list[i], member)) + tmp[j++] = list[i]; + + tmp[j] = (char *) 0; + + return tmp; +} + +char ** +dup_list(char * const *list) +{ + int i; + char **tmp; + + for (i = 0; list[i]; i++) + ; + + tmp = (char **) xmalloc((i + 1) * sizeof(char *)); + + i = 0; + while (*list) + tmp[i++] = xstrdup(*list++); + + tmp[i] = (char *) 0; + return tmp; +} + +int +is_on_list(char * const *list, const char *member) +{ + while (*list) { + if (strcmp(*list, member) == 0) + return 1; + list++; + } + return 0; +} + +/* + * comma_to_list - convert comma-separated list to (char *) array + */ + +char ** +comma_to_list(const char *comma) +{ + char *members; + char **array; + int i; + char *cp, *cp2; + + /* + * Make a copy since we are going to be modifying the list + */ + + members = xstrdup (comma); + + /* + * Count the number of commas in the list + */ + + for (cp = members, i = 0;;i++) + if ((cp2 = strchr (cp, ','))) + cp = cp2 + 1; + else + break; + + /* + * Add 2 - one for the ending NULL, the other for the last item + */ + + i += 2; + + /* + * Allocate the array we're going to store the pointers into. + */ + + array = (char **) xmalloc (sizeof (char *) * i); + + /* + * Empty list is special - 0 members, not 1 empty member. --marekm + */ + + if (!*members) { + *array = (char *) 0; + return array; + } + + /* + * Now go walk that list all over again, this time building the + * array of pointers. + */ + + for (cp = members, i = 0;;i++) { + array[i] = cp; + if ((cp2 = strchr (cp, ','))) { + *cp2++ = '\0'; + cp = cp2; + } else { + array[i + 1] = (char *) 0; + break; + } + } + + /* + * Return the new array of pointers + */ + + return array; +} diff --git a/libmisc/log.c b/libmisc/log.c new file mode 100644 index 00000000..a0ee0e1b --- /dev/null +++ b/libmisc/log.c @@ -0,0 +1,100 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: log.c,v 1.5 1998/04/16 19:57:44 marekm Exp $") + +#include +#include +#include +#include +#include "defines.h" +#if HAVE_LASTLOG_H +#include +#else +#include "lastlog_.h" +#endif + +/* + * dolastlog - create lastlog entry + * + * A "last login" entry is created for the user being logged in. The + * UID is extracted from the global (struct passwd) entry and the + * TTY information is gotten from the (struct utmp). + */ + +void +dolastlog(struct lastlog *ll, const struct passwd *pw, const char *line, const char *host) +{ + int fd; + off_t offset; + struct lastlog newlog; + + /* + * If the file does not exist, don't create it. + */ + + if ((fd = open(LASTLOG_FILE, O_RDWR)) == -1) + return; + + /* + * The file is indexed by UID number. Seek to the record + * for this UID. Negative UID's will create problems, but ... + */ + + offset = (unsigned long) pw->pw_uid * sizeof newlog; + + if (lseek(fd, offset, SEEK_SET) != offset) { + close(fd); + return; + } + + /* + * Read the old entry so we can tell the user when they last + * logged in. Then construct the new entry and write it out + * the way we read the old one in. + */ + + if (read(fd, (char *) &newlog, sizeof newlog) != sizeof newlog) + memzero(&newlog, sizeof newlog); + if (ll) + *ll = newlog; + + time(&newlog.ll_time); + strncpy(newlog.ll_line, line, sizeof newlog.ll_line); +#if HAVE_LL_HOST + strncpy(newlog.ll_host, host, sizeof newlog.ll_host); +#endif + if (lseek(fd, offset, SEEK_SET) == offset) + write(fd, (char *) &newlog, sizeof newlog); + close(fd); +} + diff --git a/libmisc/login_access.c b/libmisc/login_access.c new file mode 100644 index 00000000..1d06d3e7 --- /dev/null +++ b/libmisc/login_access.c @@ -0,0 +1,340 @@ +/* Taken from logdaemon-5.0, only minimal changes. --marekm */ + +/************************************************************************ +* Copyright 1995 by Wietse Venema. All rights reserved. Individual files +* may be covered by other copyrights (as noted in the file itself.) +* +* This material was originally written and compiled by Wietse Venema at +* Eindhoven University of Technology, The Netherlands, in 1990, 1991, +* 1992, 1993, 1994 and 1995. +* +* Redistribution and use in source and binary forms are permitted +* provided that this entire copyright notice is duplicated in all such +* copies. +* +* This software is provided "as is" and without any expressed or implied +* warranties, including, without limitation, the implied warranties of +* merchantibility and fitness for any particular purpose. +************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef LOGIN_ACCESS +#include "rcsid.h" +RCSID("$Id: login_access.c,v 1.6 1998/01/29 23:22:34 marekm Exp $") +#include "prototypes.h" + + /* + * This module implements a simple but effective form of login access + * control based on login names and on host (or domain) names, internet + * addresses (or network numbers), or on terminal line names in case of + * non-networked logins. Diagnostics are reported through syslog(3). + * + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + */ + +#include +#include +#include +#include +#include +#include +#ifdef PRIMARY_GROUP_MATCH +#include +#endif +#include +#include +#include +#include +#include +#include +#include /* for inet_ntoa() */ + +extern struct group *getgrnam(); +extern int innetgr(); +#if 0 /* should be defined by */ +extern int errno; +#endif + +#if !defined(MAXHOSTNAMELEN) || (MAXHOSTNAMELEN < 64) +#undef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + + /* Path name of the access control file. */ + +#ifndef TABLE +#define TABLE "/etc/login.access" +#endif + + /* Delimiters for fields and for lists of users, ttys or hosts. */ + +static char fs[] = ":"; /* field separator */ +static char sep[] = ", \t"; /* list-element separator */ + + /* Constants to be used in assignments only, not in comparisons... */ + +#define YES 1 +#define NO 0 + +static int list_match(); +static int user_match(); +static int from_match(); +static int string_match(); + +/* login_access - match username/group and host/tty with access control file */ + +int +login_access(const char *user, const char *from) +{ + FILE *fp; + char line[BUFSIZ]; + char *perm; /* becomes permission field */ + char *users; /* becomes list of login names */ + char *froms; /* becomes list of terminals or hosts */ + int match = NO; + int end; + int lineno = 0; /* for diagnostics */ + + /* + * Process the table one line at a time and stop at the first match. + * Blank lines and lines that begin with a '#' character are ignored. + * Non-comment lines are broken at the ':' character. All fields are + * mandatory. The first field should be a "+" or "-" character. A + * non-existing table means no access control. + */ + + if ((fp = fopen(TABLE, "r"))) { + while (!match && fgets(line, sizeof(line), fp)) { + lineno++; + if (line[end = strlen(line) - 1] != '\n') { + syslog(LOG_ERR, "%s: line %d: missing newline or line too long", + TABLE, lineno); + continue; + } + if (line[0] == '#') + continue; /* comment line */ + while (end > 0 && isspace(line[end - 1])) + end--; + line[end] = 0; /* strip trailing whitespace */ + if (line[0] == 0) /* skip blank lines */ + continue; + if (!(perm = strtok(line, fs)) + || !(users = strtok((char *) 0, fs)) + || !(froms = strtok((char *) 0, fs)) + || strtok((char *) 0, fs)) { + syslog(LOG_ERR, "%s: line %d: bad field count", TABLE, lineno); + continue; + } + if (perm[0] != '+' && perm[0] != '-') { + syslog(LOG_ERR, "%s: line %d: bad first field", TABLE, lineno); + continue; + } + match = (list_match(froms, from, from_match) + && list_match(users, user, user_match)); + } + (void) fclose(fp); + } else if (errno != ENOENT) { + syslog(LOG_ERR, "cannot open %s: %m", TABLE); + } + return (match == 0 || (line[0] == '+')); +} + +/* list_match - match an item against a list of tokens with exceptions */ + +static int +list_match(char *list, const char *item, int (*match_fn)()) +{ + char *tok; + int match = NO; + + /* + * Process tokens one at a time. We have exhausted all possible matches + * when we reach an "EXCEPT" token or the end of the list. If we do find + * a match, look for an "EXCEPT" list and recurse to determine whether + * the match is affected by any exceptions. + */ + + for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) { + if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */ + break; + if ((match = (*match_fn) (tok, item))) /* YES */ + break; + } + /* Process exceptions to matches. */ + + if (match != NO) { + while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT")) + /* VOID */ ; + if (tok == 0 || list_match((char *) 0, item, match_fn) == NO) + return (match); + } + return (NO); +} + +/* myhostname - figure out local machine name */ + +static char * +myhostname(void) +{ + static char name[MAXHOSTNAMELEN + 1] = ""; + + if (name[0] == 0) { + gethostname(name, sizeof(name)); + name[MAXHOSTNAMELEN] = 0; + } + return (name); +} + +/* netgroup_match - match group against machine or user */ + +static int +netgroup_match(const char *group, const char *machine, const char *user) +{ +#if 0 /* original code */ +#ifdef NIS + static char *mydomain = 0; + + if (mydomain == 0) + yp_get_default_domain(&mydomain); + return (innetgr(group, machine, user, mydomain)); +#else + syslog(LOG_ERR, "NIS netgroup support not configured"); + return (NO); +#endif +#else /* works better with glibc? */ + static char *mydomain = 0; + + if (mydomain == 0) { + static char domain[MAXHOSTNAMELEN+1]; + + getdomainname(domain, MAXHOSTNAMELEN); + mydomain = domain; + } + + return innetgr(group, machine, user, mydomain); +#endif +} + +/* user_match - match a username against one token */ + +static int +user_match(const char *tok, const char *string) +{ + struct group *group; +#ifdef PRIMARY_GROUP_MATCH + struct passwd *userinf; +#endif + int i; + char *at; + + /* + * If a token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the username, or if + * the token is a group that contains the username. + */ + + if ((at = strchr(tok + 1, '@')) != 0) { /* split user@host pattern */ + *at = 0; + return (user_match(tok, string) && from_match(at + 1, myhostname())); + } else if (tok[0] == '@') { /* netgroup */ + return (netgroup_match(tok + 1, (char *) 0, string)); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if ((group = getgrnam(tok))) { /* try group membership */ + for (i = 0; group->gr_mem[i]; i++) + if (strcasecmp(string, group->gr_mem[i]) == 0) + return (YES); +#ifdef PRIMARY_GROUP_MATCH + /* + * If the sting is an user whose initial GID matches the token, + * accept it. May avoid excessively long lines in /etc/group. + * Radu-Adrian Feurdean + * + * XXX - disabled by default for now. Need to verify that + * getpwnam() doesn't have some nasty side effects. --marekm + */ + if ((userinf = getpwnam(string))) + if (userinf->pw_gid == group->gr_gid) + return (YES); +#endif + } + return (NO); +} + +static char * +resolve_hostname(string) + char *string; +{ +#if 1 + /* + * Resolve hostname to numeric IP address, as suggested + * by Dave Hagewood . --marekm + */ + struct hostent *hp; + + hp = gethostbyname(string); + if (hp) + return inet_ntoa(*((struct in_addr *) *(hp->h_addr_list))); + + syslog(LOG_ERR, "%s - unknown host", string); +#endif + return string; +} + +/* from_match - match a host or tty against a list of tokens */ + +static int +from_match(const char *tok, const char *string) +{ + int tok_len; + int str_len; + + /* + * If a token has the magic value "ALL" the match always succeeds. Return + * YES if the token fully matches the string. If the token is a domain + * name, return YES if it matches the last fields of the string. If the + * token has the magic value "LOCAL", return YES if the string does not + * contain a "." character. If the token is a network number, return YES + * if it matches the head of the string. + */ + + if (tok[0] == '@') { /* netgroup */ + return (netgroup_match(tok + 1, string, (char *) 0)); + } else if (string_match(tok, string)) { /* ALL or exact match */ + return (YES); + } else if (tok[0] == '.') { /* domain: match last fields */ + if ((str_len = strlen(string)) > (tok_len = strlen(tok)) + && strcasecmp(tok, string + str_len - tok_len) == 0) + return (YES); + } else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */ + if (strchr(string, '.') == 0) + return (YES); + } else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */ + && strncmp(tok, resolve_hostname(string), tok_len) == 0) { + return (YES); + } + return (NO); +} + +/* string_match - match a string against one token */ + +static int +string_match(const char *tok, const char *string) +{ + + /* + * If the token has the magic value "ALL" the match always succeeds. + * Otherwise, return YES if the token fully matches the string. + */ + + if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */ + return (YES); + } else if (strcasecmp(tok, string) == 0) { /* try exact match */ + return (YES); + } + return (NO); +} +#endif /* LOGIN_ACCESS */ diff --git a/libmisc/login_desrpc.c b/libmisc/login_desrpc.c new file mode 100644 index 00000000..9767b406 --- /dev/null +++ b/libmisc/login_desrpc.c @@ -0,0 +1,77 @@ +/* Taken from logdaemon-5.0, only minimal changes. --marekm */ + +/************************************************************************ +* Copyright 1995 by Wietse Venema. All rights reserved. Individual files +* may be covered by other copyrights (as noted in the file itself.) +* +* This material was originally written and compiled by Wietse Venema at +* Eindhoven University of Technology, The Netherlands, in 1990, 1991, +* 1992, 1993, 1994 and 1995. +* +* Redistribution and use in source and binary forms are permitted +* provided that this entire copyright notice is duplicated in all such +* copies. +* +* This software is provided "as is" and without any expressed or implied +* warranties, including, without limitation, the implied warranties of +* merchantibility and fitness for any particular purpose. +************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef DES_RPC +#include "rcsid.h" +RCSID("$Id: login_desrpc.c,v 1.7 1999/06/07 16:40:44 marekm Exp $") + +#include "defines.h" + + /* + * Decrypt the user's secret secure RPC key and stores it into the + * keyserver. Returns 0 if successful, -1 on failure. + * + * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. + */ + +#include +#include +#include + +#if !(defined __GLIBC__ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0))) +/* these don't seem to be in any header file (libc-5.4.33) */ +/* but will be in glibc 2.1 and */ +extern int getnetname(char *); +extern int getsecretkey(const char *, char *, const char *); +extern int key_setsecret(const char *); +#endif + +int +login_desrpc(const char *passwd) +{ + char netname[MAXNETNAMELEN + 1]; + char secretkey[HEXKEYBYTES + 1]; + + if (getnetname(netname) == 0) + return -1; + + if (getsecretkey(netname, secretkey, passwd) == 0) + return -1; + + if (secretkey[0] == 0) { + fprintf(stderr, + _("Password does not decrypt secret key for %s.\n"), + netname); + return -1; + } + if (key_setsecret(secretkey) < 0) { + fprintf(stderr, + _("Could not set %s's secret key: is the keyserv daemon running?\n"), + netname); + return -1; + } + return 0; +} +#else +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif diff --git a/libmisc/login_krb.c b/libmisc/login_krb.c new file mode 100644 index 00000000..001a2163 --- /dev/null +++ b/libmisc/login_krb.c @@ -0,0 +1,61 @@ +/* Taken from logdaemon-5.0, only minimal changes. --marekm */ + +/************************************************************************ +* Copyright 1995 by Wietse Venema. All rights reserved. Individual files +* may be covered by other copyrights (as noted in the file itself.) +* +* This material was originally written and compiled by Wietse Venema at +* Eindhoven University of Technology, The Netherlands, in 1990, 1991, +* 1992, 1993, 1994 and 1995. +* +* Redistribution and use in source and binary forms are permitted +* provided that this entire copyright notice is duplicated in all such +* copies. +* +* This software is provided "as is" and without any expressed or implied +* warranties, including, without limitation, the implied warranties of +* merchantibility and fitness for any particular purpose. +************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef KERBEROS +#include "rcsid.h" +RCSID("$Id: login_krb.c,v 1.3 1998/01/29 23:22:34 marekm Exp $") + +#include + + /* + * Do an equivalent to kinit here. We need to do the kinit before trying to + * cd to the home directory, because it might be on a remote filesystem that + * uses Kerberos authentication. We also need to do this after we've + * setuid() to the user, or krb_get_pw_in_tkt() won't know where to put the + * ticket. + * + * We don't really care about whether or not it succeeds; if it fails, we'll + * just carry on bravely. + * + * NB: we assume: local realm, same username and password as supplied to login. + * + * Security note: if pp is NULL, login doesn't have the password. This is + * common when it's called by rlogind. Since this is almost always a remote + * connection, we don't want to risk asking for the password by supplying a + * NULL pp to krb_get_pw_in_tkt(), because somebody could be listening. So + * we'll just forget the whole thing. -jdd + */ + +int +login_kerberos(const char *username, const char *password) +{ + char realm[REALM_SZ]; + + (void) krb_get_lrealm(realm, 1); + if (password != 0) + (void) krb_get_pw_in_tkt(username, "", realm, "krbtgt", + realm, DEFAULT_TKT_LIFE, password); +} +#else +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif /* KERBEROS */ diff --git a/libmisc/loginprompt.c b/libmisc/loginprompt.c new file mode 100644 index 00000000..eb0958f1 --- /dev/null +++ b/libmisc/loginprompt.c @@ -0,0 +1,165 @@ +/* + * Copyright 1989 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: loginprompt.c,v 1.5 1998/04/16 19:57:44 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" +#include "defines.h" +#include "getdef.h" + +static void +login_exit(int sig) +{ + exit(1); +} + +/* + * login_prompt - prompt the user for their login name + * + * login_prompt() displays the standard login prompt. If ISSUE_FILE + * is set in login.defs, this file is displayed before the prompt. + */ + +void +login_prompt(const char *prompt, char *name, int namesize) +{ + char buf[1024]; +#define MAX_ENV 32 + char *envp[MAX_ENV]; + int envc; + char *cp; + int i; + FILE *fp; + RETSIGTYPE (*sigquit) P_((int)); +#ifdef SIGTSTP + RETSIGTYPE (*sigtstp) P_((int)); +#endif + + /* + * There is a small chance that a QUIT character will be part of + * some random noise during a prompt. Deal with this by exiting + * instead of core dumping. If SIGTSTP is defined, do the same + * thing for that signal. + */ + + sigquit = signal(SIGQUIT, login_exit); +#ifdef SIGTSTP + sigtstp = signal(SIGTSTP, login_exit); +#endif + + /* + * See if the user has configured the issue file to + * be displayed and display it before the prompt. + */ + + if (prompt) { + cp = getdef_str("ISSUE_FILE"); + if (cp && (fp = fopen(cp, "r"))) { + while ((i = getc(fp)) != EOF) + putc(i, stdout); + + fclose(fp); + } + gethostname(buf, sizeof buf); + printf(prompt, buf); + fflush(stdout); + } + + /* + * Read the user's response. The trailing newline will be + * removed. + */ + + memzero(buf, sizeof buf); + if (fgets(buf, sizeof buf, stdin) != buf) + exit(1); + + cp = strchr(buf, '\n'); + if (!cp) + exit(1); + *cp = '\0'; /* remove \n [ must be there ] */ + + /* + * Skip leading whitespace. This makes " username" work right. + * Then copy the rest (up to the end or the first "non-graphic" + * character into the username. + */ + + for (cp = buf;*cp == ' ' || *cp == '\t';cp++) + ; + + for (i = 0; i < namesize - 1 && isgraph(*cp); name[i++] = *cp++) + ; + while (isgraph(*cp)) + cp++; + + if (*cp) + cp++; + + name[i] = '\0'; + + /* + * This is a disaster, at best. The user may have entered extra + * environmental variables at the prompt. There are several ways + * to do this, and I just take the easy way out. + */ + + if (*cp != '\0') { /* process new variables */ + char *nvar; + int count = 1; + + for (envc = 0; envc < MAX_ENV; envc++) { + nvar = strtok(envc ? (char *)0 : cp, " \t,"); + if (!nvar) + break; + if (strchr(nvar, '=')) { + envp[envc] = nvar; + } else { + envp[envc] = xmalloc(strlen(nvar) + 32); + sprintf(envp[envc], "L%d=%s", count++, nvar); + } + } + set_env(envc, envp); + } + + /* + * Set the SIGQUIT handler back to its original value + */ + + signal(SIGQUIT, sigquit); +#ifdef SIGTSTP + signal(SIGTSTP, sigtstp); +#endif +} diff --git a/libmisc/mail.c b/libmisc/mail.c new file mode 100644 index 00000000..7b24e974 --- /dev/null +++ b/libmisc/mail.c @@ -0,0 +1,79 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "prototypes.h" +#include "defines.h" +#include +#include +#include + +#include "getdef.h" + +#include "rcsid.h" +RCSID("$Id: mail.c,v 1.7 1998/12/28 20:34:49 marekm Exp $") + +void +mailcheck(void) +{ + struct stat statbuf; + char *mailbox; + + if (!getdef_bool("MAIL_CHECK_ENAB")) + return; + + /* + * Check incoming mail in Maildir format - J. + */ + if ((mailbox = getenv("MAILDIR"))) { + char *newmail; + + newmail = xmalloc(strlen(mailbox) + 5); + sprintf(newmail, "%s/new", mailbox); + if (stat(newmail, &statbuf) != -1 && statbuf.st_size != 0) { + if (statbuf.st_mtime > statbuf.st_atime) { + free(newmail); + puts(_("You have new mail.")); + return; + } + } + free(newmail); + } + + if (!(mailbox = getenv("MAIL"))) + return; + + if (stat(mailbox, &statbuf) == -1 || statbuf.st_size == 0) + puts(_("No mail.")); + else if (statbuf.st_atime > statbuf.st_mtime) + puts(_("You have mail.")); + else + puts(_("You have new mail.")); +} + diff --git a/libmisc/motd.c b/libmisc/motd.c new file mode 100644 index 00000000..0ff6973e --- /dev/null +++ b/libmisc/motd.c @@ -0,0 +1,69 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: motd.c,v 1.3 1997/12/07 23:27:07 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include "getdef.h" + +/* + * motd -- output the /etc/motd file + * + * motd() determines the name of a login announcement file and outputs + * it to the user's terminal at login time. The MOTD_FILE configuration + * option is a colon-delimited list of filenames. + */ + +void +motd(void) +{ + FILE *fp; + char motdlist[BUFSIZ], *motdfile, *mb; + register int c; + + if ((mb = getdef_str("MOTD_FILE")) == NULL) + return; + + strncpy(motdlist, mb, sizeof(motdlist)); + motdlist[sizeof(motdlist)-1] = '\0'; + + for (mb = motdlist ; (motdfile = strtok(mb,":")) != NULL ; mb = NULL) { + if ((fp = fopen(motdfile, "r")) != NULL) { + while ((c = getc (fp)) != EOF) + putchar (c); + fclose (fp); + } + } + fflush (stdout); +} diff --git a/libmisc/myname.c b/libmisc/myname.c new file mode 100644 index 00000000..66e80e56 --- /dev/null +++ b/libmisc/myname.c @@ -0,0 +1,41 @@ +/* + * myname.c - determine the current username and get the passwd entry + * + * Copyright (C) 1996 Marek Michalkiewicz + * + * This code may be freely used, modified and distributed for any purpose. + * There is no warranty, if it breaks you have to keep both pieces, etc. + * If you improve it, please send me your changes. Thanks! + */ + +#include + +#include "rcsid.h" +RCSID("$Id: myname.c,v 1.2 1997/12/07 23:27:07 marekm Exp $") + +#include "defines.h" +#include +#include "prototypes.h" + +struct passwd * +get_my_pwent(void) +{ + struct passwd *pw; + const char *cp = getlogin(); + uid_t ruid = getuid(); + + /* + * Try getlogin() first - if it fails or returns a non-existent + * username, or a username which doesn't match the real UID, fall + * back to getpwuid(getuid()). This should work reasonably with + * usernames longer than the utmp limit (8 characters), as well as + * shared UIDs - but not both at the same time... + * + * XXX - when running from su, will return the current user (not + * the original user, like getlogin() does). Does this matter? + */ + if (cp && *cp && (pw = getpwnam(cp)) && pw->pw_uid == ruid) + return pw; + + return getpwuid(ruid); +} diff --git a/libmisc/obscure.c b/libmisc/obscure.c new file mode 100644 index 00000000..845bd264 --- /dev/null +++ b/libmisc/obscure.c @@ -0,0 +1,286 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: obscure.c,v 1.9 1999/03/07 19:14:40 marekm Exp $") + +/* + * This version of obscure.c contains modifications to support "cracklib" + * by Alec Muffet (alec.muffett@uk.sun.com). You must obtain the Cracklib + * library source code for this function to operate. + */ + +#include +#include +#include "prototypes.h" +#include "defines.h" + +#include "getdef.h" + +/* + * can't be a palindrome - like `R A D A R' or `M A D A M' + */ + +/*ARGSUSED*/ +static int +palindrome(const char *old, const char *new) +{ + int i, j; + + i = strlen (new); + + for (j = 0;j < i;j++) + if (new[i - j - 1] != new[j]) + return 0; + + return 1; +} + +/* + * more than half of the characters are different ones. + */ + +/*ARGSUSED*/ +static int +similar(const char *old, const char *new) +{ + int i, j; + + /* + * XXX - sometimes this fails when changing from a simple password + * to a really long one (MD5). For now, I just return success if + * the new password is long enough. Please feel free to suggest + * something better... --marekm + */ + if (strlen(new) >= 8) + return 0; + + for (i = j = 0; new[i] && old[i]; i++) + if (strchr(new, old[i])) + j++; + + if (i >= j * 2) + return 0; + + return 1; +} + +/* + * a nice mix of characters. + */ + +/*ARGSUSED*/ +static int +simple(const char *old, const char *new) +{ + int digits = 0; + int uppers = 0; + int lowers = 0; + int others = 0; + int size; + int i; + + for (i = 0;new[i];i++) { + if (isdigit (new[i])) + digits++; + else if (isupper (new[i])) + uppers++; + else if (islower (new[i])) + lowers++; + else + others++; + } + + /* + * The scam is this - a password of only one character type + * must be 8 letters long. Two types, 7, and so on. + */ + + size = 9; + if (digits) size--; + if (uppers) size--; + if (lowers) size--; + if (others) size--; + + if (size <= i) + return 0; + + return 1; +} + +static char * +str_lower(char *string) +{ + char *cp; + + for (cp = string; *cp; cp++) + *cp = tolower(*cp); + return string; +} + +static const char * +password_check(const char *old, const char *new, const struct passwd *pwdp) +{ + const char *msg = NULL; + char *oldmono, *newmono, *wrapped; +#ifdef HAVE_LIBCRACK + char *dictpath; +#ifdef HAVE_LIBCRACK_PW + char *FascistCheckPw(); +#else + char *FascistCheck(); +#endif +#endif + + if (strcmp(new, old) == 0) + return "no change"; + + newmono = str_lower(xstrdup(new)); + oldmono = str_lower(xstrdup(old)); + wrapped = xmalloc(strlen(oldmono) * 2 + 1); + strcpy (wrapped, oldmono); + strcat (wrapped, oldmono); + + if (palindrome(oldmono, newmono)) + msg = "a palindrome"; + + if (!msg && strcmp(oldmono, newmono) == 0) + msg = "case changes only"; + + if (!msg && similar(oldmono, newmono)) + msg = "too similar"; + + if (!msg && simple(old, new)) + msg = "too simple"; + + if (!msg && strstr(wrapped, newmono)) + msg = "rotated"; + +#ifdef HAVE_LIBCRACK + /* + * Invoke Alec Muffett's cracklib routines. + */ + + if (!msg && (dictpath = getdef_str("CRACKLIB_DICTPATH"))) +#ifdef HAVE_LIBCRACK_PW + msg = FascistCheckPw(new, dictpath, pwdp); +#else + msg = FascistCheck(new, dictpath); +#endif +#endif + strzero(newmono); + strzero(oldmono); + strzero(wrapped); + free(newmono); + free(oldmono); + free(wrapped); + + return msg; +} + +/*ARGSUSED*/ +static const char * +obscure_msg(const char *old, const char *new, const struct passwd *pwdp) +{ + int maxlen, oldlen, newlen; + char *new1, *old1; + const char *msg; + + oldlen = strlen(old); + newlen = strlen(new); + +#if 0 /* why not check the password when set for the first time? --marekm */ + if (old[0] == '\0') + return NULL; +#endif + + if ( newlen < getdef_num("PASS_MIN_LEN", 0) ) + return "too short"; + + /* + * Remaining checks are optional. + */ + if (!getdef_bool("OBSCURE_CHECKS_ENAB")) + return NULL; + + msg = password_check(old, new, pwdp); + if (msg) + return msg; + + /* The traditional crypt() truncates passwords to 8 chars. It is + possible to circumvent the above checks by choosing an easy + 8-char password and adding some random characters to it... + Example: "password$%^&*123". So check it again, this time + truncated to the maximum length. Idea from npasswd. --marekm */ + + if (getdef_bool("MD5_CRYPT_ENAB")) + return NULL; /* unlimited password length */ + + maxlen = getdef_num("PASS_MAX_LEN", 8); + if (oldlen <= maxlen && newlen <= maxlen) + return NULL; + + new1 = xstrdup(new); + old1 = xstrdup(old); + if (newlen > maxlen) + new1[maxlen] = '\0'; + if (oldlen > maxlen) + old1[maxlen] = '\0'; + + msg = password_check(old1, new1, pwdp); + + memzero(new1, newlen); + memzero(old1, oldlen); + free(new1); + free(old1); + + return msg; +} + +/* + * Obscure - see if password is obscure enough. + * + * The programmer is encouraged to add as much complexity to this + * routine as desired. Included are some of my favorite ways to + * check passwords. + */ + +int +obscure(const char *old, const char *new, const struct passwd *pwdp) +{ + const char *msg = obscure_msg(old, new, pwdp); + if (msg) { + printf(_("Bad password: %s. "), msg); + return 0; + } + return 1; +} + diff --git a/libmisc/pam_pass.c b/libmisc/pam_pass.c new file mode 100644 index 00000000..b3e7ac75 --- /dev/null +++ b/libmisc/pam_pass.c @@ -0,0 +1,58 @@ +#include + +#ifdef USE_PAM + +#include "rcsid.h" +RCSID("$Id: pam_pass.c,v 1.6 1999/06/07 16:40:44 marekm Exp $") + +/* + * Change the user's password using PAM. Requires libpam and libpam_misc + * (for misc_conv). Note: libpam_misc is probably Linux-PAM specific, + * so you may have to port it if you want to use this code on non-Linux + * systems with PAM (such as Solaris 2.6). --marekm + */ + +#include +#include +#include +#include + +#include "defines.h" + +#include "pam_defs.h" + +static const struct pam_conv conv = { + misc_conv, + NULL +}; + +void +do_pam_passwd(const char *user, int silent, int change_expired) +{ + pam_handle_t *pamh = NULL; + int flags = 0, ret; + + if (silent) + flags |= PAM_SILENT; + if (change_expired) + flags |= PAM_CHANGE_EXPIRED_AUTHTOK; + + ret = pam_start("passwd", user, &conv, &pamh); + if (ret != PAM_SUCCESS) { + fprintf(stderr, _("passwd: pam_start() failed, error %d\n"), + ret); + exit(10); /* XXX */ + } + + ret = pam_chauthtok(pamh, flags); + if (ret != PAM_SUCCESS) { + fprintf(stderr, _("passwd: %s\n"), PAM_STRERROR(pamh, ret)); + pam_end(pamh, ret); + exit(10); /* XXX */ + } + + pam_end(pamh, PAM_SUCCESS); +} +#else /* !USE_PAM */ +extern int errno; /* warning: ANSI C forbids an empty source file */ +#endif /* !USE_PAM */ diff --git a/libmisc/pwd2spwd.c b/libmisc/pwd2spwd.c new file mode 100644 index 00000000..e53d96ab --- /dev/null +++ b/libmisc/pwd2spwd.c @@ -0,0 +1,103 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifdef SHADOWPWD + +#include "rcsid.h" +RCSID("$Id: pwd2spwd.c,v 1.3 1997/12/07 23:27:07 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include + +extern time_t time (); + +/* + * pwd_to_spwd - create entries for new spwd structure + * + * pwd_to_spwd() creates a new (struct spwd) containing the + * information in the pointed-to (struct passwd). + */ + +struct spwd * +pwd_to_spwd(const struct passwd *pw) +{ + static struct spwd sp; + + /* + * Nice, easy parts first. The name and passwd map directly + * from the old password structure to the new one. + */ + sp.sp_namp = pw->pw_name; + sp.sp_pwdp = pw->pw_passwd; + +#ifdef ATT_AGE + /* + * AT&T-style password aging maps the sp_min, sp_max, and + * sp_lstchg information from the pw_age field, which appears + * after the encrypted password. + */ + if (pw->pw_age[0]) { + sp.sp_max = (c64i(pw->pw_age[0]) * WEEK) / SCALE; + + if (pw->pw_age[1]) + sp.sp_min = (c64i(pw->pw_age[1]) * WEEK) / SCALE; + else + sp.sp_min = (10000L * DAY) / SCALE; + + if (pw->pw_age[1] && pw->pw_age[2]) + sp.sp_lstchg = (a64l(pw->pw_age + 2) * WEEK) / SCALE; + else + sp.sp_lstchg = time((time_t *) 0) / SCALE; + } else +#endif + { + /* + * Defaults used if there is no pw_age information. + */ + sp.sp_min = 0; + sp.sp_max = (10000L * DAY) / SCALE; + sp.sp_lstchg = time((time_t *) 0) / SCALE; + } + + /* + * These fields have no corresponding information in the password + * file. They are set to uninitialized values. + */ + sp.sp_warn = -1; + sp.sp_expire = -1; + sp.sp_inact = -1; + sp.sp_flag = -1; + + return &sp; +} +#endif /* SHADOWPWD */ diff --git a/libmisc/pwd_init.c b/libmisc/pwd_init.c new file mode 100644 index 00000000..e09f02bd --- /dev/null +++ b/libmisc/pwd_init.c @@ -0,0 +1,73 @@ + +#include + +#include "rcsid.h" +RCSID("$Id: pwd_init.c,v 1.1 1997/12/07 23:27:07 marekm Exp $") + +#include "defines.h" +#include +#include +#include + +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +/* + * pwd_init - ignore signals, and set resource limits to safe + * values. Call this before modifying password files, so that + * it is less likely to fail in the middle of operation. + */ +void +pwd_init(void) +{ +#ifdef HAVE_SYS_RESOURCE_H + struct rlimit rlim; + +#ifdef RLIMIT_CORE + rlim.rlim_cur = rlim.rlim_max = 0; + setrlimit(RLIMIT_CORE, &rlim); +#endif + rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; +#ifdef RLIMIT_AS + setrlimit(RLIMIT_AS, &rlim); +#endif +#ifdef RLIMIT_CPU + setrlimit(RLIMIT_CPU, &rlim); +#endif +#ifdef RLIMIT_DATA + setrlimit(RLIMIT_DATA, &rlim); +#endif +#ifdef RLIMIT_FSIZE + setrlimit(RLIMIT_FSIZE, &rlim); +#endif +#ifdef RLIMIT_NOFILE + setrlimit(RLIMIT_NOFILE, &rlim); +#endif +#ifdef RLIMIT_RSS + setrlimit(RLIMIT_RSS, &rlim); +#endif +#ifdef RLIMIT_STACK + setrlimit(RLIMIT_STACK, &rlim); +#endif +#else /* !HAVE_SYS_RESOURCE_H */ + set_filesize_limit(30000); + /* don't know how to set the other limits... */ +#endif /* !HAVE_SYS_RESOURCE_H */ + + signal(SIGALRM, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGTERM, SIG_IGN); +#ifdef SIGTSTP + signal(SIGTSTP, SIG_IGN); +#endif +#ifdef SIGTTOU + signal(SIGTTOU, SIG_IGN); +#endif + + umask(077); +} + diff --git a/libmisc/pwdcheck.c b/libmisc/pwdcheck.c new file mode 100644 index 00000000..1b3cea74 --- /dev/null +++ b/libmisc/pwdcheck.c @@ -0,0 +1,69 @@ +#include + +#include "rcsid.h" +RCSID("$Id$") + +#include "prototypes.h" +#include "defines.h" + +#include +#include "pwauth.h" + +#ifdef HAVE_SHADOW_H +#include +#endif + +#ifdef USE_PAM +#include "pam_defs.h" +#endif + +#define WRONGPWD2 "incorrect password for `%s'" + +void +passwd_check(const char *user, const char *passwd, const char *progname) +{ +#ifdef USE_PAM + pam_handle_t *pamh = NULL; + int retcode; + struct pam_conv conv = { misc_conv, NULL }; + + if (pam_start(progname, user, &conv, &pamh)) { +bailout: + SYSLOG((LOG_WARN, WRONGPWD2, user)); + sleep(1); + fprintf(stderr, _("Incorrect password for %s.\n"), user); + exit(1); + } + if (pam_authenticate(pamh, 0)) + goto bailout; + + retcode = pam_acct_mgmt(pamh, 0); + if (retcode == PAM_NEW_AUTHTOK_REQD) { + retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + } else if (retcode) + goto bailout; + + if (pam_setcred(pamh, 0)) + goto bailout; + + /* no need to establish a session; this isn't a session-oriented + * activity... */ + +#else /* !USE_PAM */ + +#ifdef SHADOWPWD + struct spwd *sp; + + if ((sp = getspnam(user))) + passwd = sp->sp_pwdp; + endspent(); +#endif + if (pw_auth(passwd, user, PW_LOGIN, (char *) 0) != 0) { + SYSLOG((LOG_WARN, WRONGPWD2, user)); + sleep(1); + fprintf(stderr, _("Incorrect password for %s.\n"), user); + exit(1); + } +#endif /* !USE_PAM */ +} + diff --git a/libmisc/rlogin.c b/libmisc/rlogin.c new file mode 100644 index 00000000..b44a86aa --- /dev/null +++ b/libmisc/rlogin.c @@ -0,0 +1,170 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifdef RLOGIN + +#include "rcsid.h" +RCSID("$Id: rlogin.c,v 1.4 1997/12/14 20:07:20 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" + +#include +#include + +extern int ruserok(); + +static struct { + int spd_name; + int spd_baud; +} speed_table [] = { +#ifdef B50 + { B50, 50 }, +#endif +#ifdef B75 + { B75, 75 }, +#endif +#ifdef B110 + { B110, 110 }, +#endif +#ifdef B134 + { B134, 134 }, +#endif +#ifdef B150 + { B150, 150 }, +#endif +#ifdef B200 + { B200, 200 }, +#endif +#ifdef B300 + { B300, 300 }, +#endif +#ifdef B600 + { B600, 600 }, +#endif +#ifdef B1200 + { B1200, 1200 }, +#endif +#ifdef B1800 + { B1800, 1800 }, +#endif +#ifdef B2400 + { B2400, 2400 }, +#endif +#ifdef B4800 + { B4800, 4800 }, +#endif +#ifdef B9600 + { B9600, 9600 }, +#endif +#ifdef B19200 + { B19200, 19200 }, +#endif +#ifdef B38400 + { B38400, 38400 }, +#endif + { -1, -1 } +}; + +static void +get_remote_string(char *buf, int size) +{ + for (;;) { + if (read (0, buf, 1) != 1) + exit (1); + if (*buf == '\0') + return; + if (--size > 0) + ++buf; + } + /*NOTREACHED*/ +} + +int +do_rlogin(const char *remote_host, char *name, int namelen, char *term, int termlen) +{ + struct passwd *pwd; + char remote_name[32]; + char *cp; + int remote_speed = 9600; + int speed_name = B9600; + int i; + TERMIO termio; + + get_remote_string (remote_name, sizeof remote_name); + get_remote_string (name, namelen); + get_remote_string (term, termlen); + + if ((cp = strchr (term, '/'))) { + *cp++ = '\0'; + + if (! (remote_speed = atoi (cp))) + remote_speed = 9600; + } + for (i = 0;speed_table[i].spd_baud != remote_speed && + speed_table[i].spd_name != -1;i++) + ; + + if (speed_table[i].spd_name != -1) + speed_name = speed_table[i].spd_name; + + /* + * Put the terminal in cooked mode with echo turned on. + */ + + GTTY (0, &termio); +#ifndef USE_SGTTY + termio.c_iflag |= ICRNL|IXON; + termio.c_oflag |= OPOST|ONLCR; + termio.c_lflag |= ICANON|ECHO|ECHOE; + termio.c_cflag = (termio.c_cflag & ~CBAUD) | speed_name; +#else +#endif + STTY (0, &termio); + + if (! (pwd = getpwnam (name))) + return 0; + + /* + * ruserok() returns 0 for success on modern systems, and 1 on + * older ones. If you are having trouble with people logging + * in without giving a required password, THIS is the culprit - + * go fix the #define in config.h. + */ + +#ifndef RUSEROK + return 0; +#else + return ruserok (remote_host, pwd->pw_uid == 0, + remote_name, name) == RUSEROK; +#endif +} +#endif /* RLOGIN */ diff --git a/libmisc/salt.c b/libmisc/salt.c new file mode 100644 index 00000000..b5478e45 --- /dev/null +++ b/libmisc/salt.c @@ -0,0 +1,70 @@ +/* + * salt.c - generate a random salt string for crypt() + * + * Written by Marek Michalkiewicz , + * public domain. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: salt.c,v 1.5 1997/12/07 23:27:09 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include + +#if 1 +#include "getdef.h" + +extern char *l64a(); + +/* + * Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB + * in /etc/login.defs is "yes", the salt string will be prefixed by "$1$" + * (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible + * version of crypt() instead of the standard one. + */ +char * +crypt_make_salt(void) +{ + struct timeval tv; + static char result[40]; + + result[0] = '\0'; + if (getdef_bool("MD5_CRYPT_ENAB")) { + strcpy(result, "$1$"); /* magic for the new MD5 crypt() */ + } + + /* + * Generate 8 chars of salt, the old crypt() will use only first 2. + */ + gettimeofday(&tv, (struct timezone *) 0); + strcat(result, l64a(tv.tv_usec)); + strcat(result, l64a(tv.tv_sec + getpid() + clock())); + + if (strlen(result) > 3 + 8) /* magic+salt */ + result[11] = '\0'; + + return result; +} +#else + +/* + * This is the old style random salt generator... + */ +char * +crypt_make_salt(void) +{ + time_t now; + static unsigned long x; + static char result[3]; + + time(&now); + x += now + getpid() + clock(); + result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077); + result[1] = i64c(((x >> 12) ^ x) & 077); + result[2] = '\0'; + return result; +} +#endif diff --git a/libmisc/setugid.c b/libmisc/setugid.c new file mode 100644 index 00000000..5dae7659 --- /dev/null +++ b/libmisc/setugid.c @@ -0,0 +1,134 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Separated from setup.c. --marekm + */ + +#include + +#include "rcsid.h" +RCSID("$Id: setugid.c,v 1.6 1998/07/23 22:13:16 marekm Exp $") + +#include +#include + +#include "prototypes.h" +#include "defines.h" +#include + +#include "getdef.h" + +/* + * setup_uid_gid() split in two functions for PAM support - + * pam_setcred() needs to be called after initgroups(), but + * before setuid(). + */ + +int +setup_groups(const struct passwd *info) +{ + /* + * Set the real group ID to the primary group ID in the password + * file. + */ + if (setgid (info->pw_gid) == -1) { + perror("setgid"); + SYSLOG((LOG_ERR, "bad group ID `%d' for user `%s': %m\n", + info->pw_gid, info->pw_name)); + closelog(); + return -1; + } +#ifdef HAVE_INITGROUPS + /* + * For systems which support multiple concurrent groups, go get + * the group set from the /etc/group file. + */ + if (initgroups(info->pw_name, info->pw_gid) == -1) { + perror("initgroups"); + SYSLOG((LOG_ERR, "initgroups failed for user `%s': %m\n", + info->pw_name)); + closelog(); + return -1; + } +#endif + return 0; +} + +int +change_uid(const struct passwd *info) +{ + /* + * Set the real UID to the UID value in the password file. + */ +#ifndef BSD + if (setuid(info->pw_uid)) +#else + if (setreuid(info->pw_uid, info->pw_uid)) +#endif + { + perror("setuid"); + SYSLOG((LOG_ERR, "bad user ID `%d' for user `%s': %m\n", + (int) info->pw_uid, info->pw_name)); + closelog(); + return -1; + } + return 0; +} + +/* + * setup_uid_gid() performs the following steps - + * + * set the group ID to the value from the password file entry + * set the supplementary group IDs + * optionally call specified function which may add more groups + * set the user ID to the value from the password file entry + * + * Returns 0 on success, or -1 on failure. + */ + +int +setup_uid_gid(const struct passwd *info, int is_console) +{ + if (setup_groups(info) < 0) + return -1; + +#ifdef HAVE_INITGROUPS + if (is_console) { + char *cp = getdef_str("CONSOLE_GROUPS"); + if (cp && add_groups(cp)) + perror("Warning: add_groups"); + } +#endif /* HAVE_INITGROUPS */ + + if (change_uid(info) < 0) + return -1; + + return 0; +} diff --git a/libmisc/setup.c b/libmisc/setup.c new file mode 100644 index 00000000..7b8df91b --- /dev/null +++ b/libmisc/setup.c @@ -0,0 +1,72 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: setup.c,v 1.3 1997/12/07 23:27:09 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include + +/* + * setup - initialize login environment + * + * setup() performs the following steps - + * + * set the process nice, ulimit, and umask from the password file entry + * set the group ID to the value from the password file entry + * set the supplementary group IDs + * set the user ID to the value from the password file entry + * change to the user's home directory + * set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental + * variables. + */ + +void +setup(struct passwd *info) +{ + /* + * Set resource limits. + */ + setup_limits(info); + + /* + * Set the real group ID, do initgroups, and set the real user ID + * to the value in the password file. + */ + if (setup_uid_gid(info, 0)) + exit(1); + + /* + * Change to the home directory, and set up environment. + */ + setup_env(info); +} diff --git a/libmisc/setupenv.c b/libmisc/setupenv.c new file mode 100644 index 00000000..90e5b179 --- /dev/null +++ b/libmisc/setupenv.c @@ -0,0 +1,277 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Separated from setup.c. --marekm + */ + +#include + +#include "rcsid.h" +RCSID("$Id: setupenv.c,v 1.9 1999/03/07 19:14:41 marekm Exp $") + +#include +#include + +#include +#include + +#include "prototypes.h" +#include "defines.h" +#include +#include "getdef.h" + +static void +addenv_path(const char *varname, const char *dirname, const char *filename) +{ + char *buf; + + buf = xmalloc(strlen(dirname) + strlen(filename) + 2); + sprintf(buf, "%s/%s", dirname, filename); + addenv(varname, buf); + free(buf); +} + + +static void +read_env_file(const char *filename) +{ + FILE *fp; + char buf[1024]; + char *cp, *name, *val; + + fp = fopen(filename, "r"); + if (!fp) + return; + while (fgets(buf, sizeof buf, fp) == buf) { + cp = strrchr(buf, '\n'); + if (!cp) + break; + *cp = '\0'; + + cp = buf; + /* ignore whitespace and comments */ + while (*cp && isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + continue; + /* + * ignore lines which don't follow the name=value format + * (for example, the "export NAME" shell commands) + */ + name = cp; + while (*cp && !isspace(*cp) && *cp != '=') + cp++; + if (*cp != '=') + continue; + /* NUL-terminate the name */ + *cp++ = '\0'; + val = cp; +#if 0 /* XXX untested, and needs rewrite with fewer goto's :-) */ +/* + (state, char_type) -> (state, action) + + state: unquoted, single_quoted, double_quoted, escaped, double_quoted_escaped + char_type: normal, white, backslash, single, double + action: remove_curr, remove_curr_skip_next, remove_prev, finish XXX +*/ +no_quote: + if (*cp == '\\') { + /* remove the backslash */ + remove_char(cp); + /* skip over the next character */ + if (*cp) + cp++; + goto no_quote; + } else if (*cp == '\'') { + /* remove the quote */ + remove_char(cp); + /* now within single quotes */ + goto s_quote; + } else if (*cp == '"') { + /* remove the quote */ + remove_char(cp); + /* now within double quotes */ + goto d_quote; + } else if (*cp == '\0') { + /* end of string */ + goto finished; + } else if (isspace(*cp)) { + /* unescaped whitespace - end of string */ + *cp = '\0'; + goto finished; + } else { + cp++; + goto no_quote; + } +s_quote: + if (*cp == '\'') { + /* remove the quote */ + remove_char(cp); + /* unquoted again */ + goto no_quote; + } else if (*cp == '\0') { + /* end of string */ + goto finished; + } else { + /* preserve everything within single quotes */ + cp++; + goto s_quote; + } +d_quote: + if (*cp == '\"') { + /* remove the quote */ + remove_char(cp); + /* unquoted again */ + goto no_quote; + } else if (*cp == '\\') { + cp++; + /* if backslash followed by double quote, remove backslash + else skip over the backslash and following char */ + if (*cp == '"') + remove_char(cp - 1); + else if (*cp) + cp++; + goto d_quote; + } eise if (*cp == '\0') { + /* end of string */ + goto finished; + } else { + /* preserve everything within double quotes */ + goto d_quote; + } +finished: +#endif /* 0 */ + /* + * XXX - should handle quotes, backslash escapes, etc. + * like the shell does. + */ + addenv(name, val); + } + fclose(fp); +} + +/* + * change to the user's home directory + * set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental + * variables. + */ + +void +setup_env(struct passwd *info) +{ + char *cp, *envf; + + /* + * Change the current working directory to be the home directory + * of the user. It is a fatal error for this process to be unable + * to change to that directory. There is no "default" home + * directory. + * + * We no longer do it as root - should work better on NFS-mounted + * home directories. Some systems default to HOME=/, so we make + * this a configurable option. --marekm + */ + + if (chdir(info->pw_dir) == -1) { + static char temp_pw_dir[] = "/"; + if (!getdef_bool("DEFAULT_HOME") || chdir("/") == -1) { + fprintf(stderr, _("Unable to cd to \"%s\"\n"), + info->pw_dir); + SYSLOG((LOG_WARN, + "unable to cd to `%s' for user `%s'\n", + info->pw_dir, info->pw_name)); + closelog(); + exit (1); + } + puts(_("No directory, logging in with HOME=/")); + info->pw_dir = temp_pw_dir; + } + + /* + * Create the HOME environmental variable and export it. + */ + + addenv("HOME", info->pw_dir); + + /* + * Create the SHELL environmental variable and export it. + */ + + if (info->pw_shell == (char *) 0 || ! *info->pw_shell) { + static char temp_pw_shell[] = "/bin/sh"; + info->pw_shell = temp_pw_shell; + } + + addenv("SHELL", info->pw_shell); + + /* + * Create the PATH environmental variable and export it. + */ + + cp = getdef_str( info->pw_uid == 0 ? "ENV_SUPATH" : "ENV_PATH" ); + addenv(cp ? cp : "PATH=/bin:/usr/bin", NULL); + + /* + * Export the user name. For BSD derived systems, it's "USER", for + * all others it's "LOGNAME". We set both of them. + */ + + addenv("USER", info->pw_name); + addenv("LOGNAME", info->pw_name); + + /* + * MAILDIR environment variable for Qmail + */ + if ((cp=getdef_str("QMAIL_DIR"))) + addenv_path("MAILDIR", info->pw_dir, cp); + + /* + * Create the MAIL environmental variable and export it. login.defs + * knows the prefix. + */ + + if ((cp=getdef_str("MAIL_DIR"))) + addenv_path("MAIL", cp, info->pw_name); + else if ((cp=getdef_str("MAIL_FILE"))) + addenv_path("MAIL", info->pw_dir, cp); + else { +#if defined(MAIL_SPOOL_FILE) + addenv_path("MAIL", info->pw_dir, MAIL_SPOOL_FILE); +#elif defined(MAIL_SPOOL_DIR) + addenv_path("MAIL", MAIL_SPOOL_DIR, info->pw_name); +#endif + } + + /* + * Read environment from optional config file. --marekm + */ + if ((envf = getdef_str("ENVIRON_FILE"))) + read_env_file(envf); +} diff --git a/libmisc/shell.c b/libmisc/shell.c new file mode 100644 index 00000000..23058f37 --- /dev/null +++ b/libmisc/shell.c @@ -0,0 +1,126 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: shell.c,v 1.7 1998/12/28 20:34:53 marekm Exp $") + +#include +#include +#include "prototypes.h" +#include "defines.h" + + +extern char **newenvp; +extern size_t newenvc; + +/* + * shell - execute the named program + * + * shell begins by trying to figure out what argv[0] is going to + * be for the named process. The user may pass in that argument, + * or it will be the last pathname component of the file with a + * '-' prepended. The first attempt is to just execute the named + * file. If the errno comes back "ENOEXEC", the file is assumed + * at first glance to be a shell script. The first two characters + * must be "#!", in which case "/bin/sh" is executed to process + * the file. If all that fails, give up in disgust ... + */ + +void +shell(const char *file, const char *arg) +{ + char arg0[1024]; + int err; + + if (file == (char *) 0) + exit (1); + + /* + * The argv[0]'th entry is usually the path name, but + * for various reasons the invoker may want to override + * that. So, we determine the 0'th entry only if they + * don't want to tell us what it is themselves. + */ + + if (arg == (char *) 0) { + snprintf(arg0, sizeof arg0, "-%s", Basename((char *) file)); + arg = arg0; + } +#ifdef DEBUG + printf (_("Executing shell %s\n"), file); +#endif + + /* + * First we try the direct approach. The system should be + * able to figure out what we are up to without too much + * grief. + */ + + execle (file, arg, (char *) 0, newenvp); + err = errno; + + /* Linux handles #! in the kernel, and bash doesn't make + sense of "#!" so it wouldn't work anyway... --marekm */ +#ifndef __linux__ + /* + * It is perfectly OK to have a shell script for a login + * shell, and this code attempts to support that. It + * relies on the standard shell being able to make sense + * of the "#!" magic number. + */ + + if (err == ENOEXEC) { + FILE *fp; + + if ((fp = fopen (file, "r"))) { + if (getc (fp) == '#' && getc (fp) == '!') { + fclose (fp); + execle ("/bin/sh", "sh", + file, (char *) 0, newenvp); + err = errno; + } else { + fclose (fp); + } + } + } +#endif + + /* + * Obviously something is really wrong - I can't figure out + * how to execute this stupid shell, so I might as well give + * up in disgust ... + */ + + snprintf(arg0, sizeof arg0, _("Cannot execute %s"), file); + errno = err; + perror(arg0); + exit(1); +} diff --git a/libmisc/strtoday.c b/libmisc/strtoday.c new file mode 100644 index 00000000..4870f9df --- /dev/null +++ b/libmisc/strtoday.c @@ -0,0 +1,207 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if !defined(__GLIBC__) +#define _XOPEN_SOURCE 500 +#endif + +#include + +#include "rcsid.h" +RCSID("$Id: strtoday.c,v 1.8 1999/03/07 19:14:42 marekm Exp $") + +#include "defines.h" + +#ifndef USE_GETDATE +#define USE_GETDATE 1 +#endif + +#if USE_GETDATE + +#include "getdate.h" + +/* + * strtoday() now uses get_date() (borrowed from GNU shellutils) + * which can handle many date formats, for example: + * 1970-09-17 # ISO 8601. + * 70-9-17 # This century assumed by default. + * 70-09-17 # Leading zeros are ignored. + * 9/17/72 # Common U.S. writing. + * 24 September 1972 + * 24 Sept 72 # September has a special abbreviation. + * 24 Sep 72 # Three-letter abbreviations always allowed. + * Sep 24, 1972 + * 24-sep-72 + * 24sep72 + */ +long +strtoday(const char *str) +{ + time_t t; + + /* + * get_date() interprets an empty string as the current date, + * which is not what we expect, unless you're a BOFH :-). + * (useradd sets sp_expire = current date for new lusers) + */ + if (!str || *str == '\0') + return -1; + + t = get_date(str, (time_t *) 0); + if (t == (time_t) -1) + return -1; + /* convert seconds to days since 1970-01-01 */ + return (t + DAY/2)/DAY; +} + +#else /* !USE_GETDATE */ +/* + * Old code, just in case get_date() doesn't work as expected... + */ + +#include + +#ifdef HAVE_STRPTIME +/* + * for now we allow just one format, but we can define more later + * (we try them all until one succeeds). --marekm + */ +static char *date_formats[] = { + "%Y-%m-%d", + (char *) 0 +}; +#else +/* + * days and juldays are used to compute the number of days in the + * current month, and the cummulative number of days in the preceding + * months. they are declared so that january is 1, not 0. + */ + +static short days[13] = { 0, + 31, 28, 31, 30, 31, 30, /* JAN - JUN */ + 31, 31, 30, 31, 30, 31 }; /* JUL - DEC */ + +static short juldays[13] = { 0, + 0, 31, 59, 90, 120, 151, /* JAN - JUN */ + 181, 212, 243, 273, 304, 334 }; /* JUL - DEC */ +#endif + +/* + * strtoday - compute the number of days since 1970. + * + * the total number of days prior to the current date is + * computed. january 1, 1970 is used as the origin with + * it having a day number of 0. + */ + +long +strtoday(const char *str) +{ +#ifdef HAVE_STRPTIME + struct tm tp; + char * const *fmt; + char *cp; + time_t result; + + memzero(&tp, sizeof tp); + for (fmt = date_formats; *fmt; fmt++) { + cp = strptime((char *) str, *fmt, &tp); + if (!cp || *cp != '\0') + continue; + + result = mktime(&tp); + if (result == (time_t) -1) + continue; + + return result / DAY; /* success */ + } + return -1; +#else + char slop[2]; + int month; + int day; + int year; + long total; + + /* + * start by separating the month, day and year. the order + * is compiled in ... + */ + + if (sscanf (str, "%d/%d/%d%c", &year, &month, &day, slop) != 3) + return -1; + + /* + * the month, day of the month, and year are checked for + * correctness and the year adjusted so it falls between + * 1970 and 2069. + */ + + if (month < 1 || month > 12) + return -1; + + if (day < 1) + return -1; + + if ((month != 2 || (year % 4) != 0) && day > days[month]) + return -1; + else if ((month == 2 && (year % 4) == 0) && day > 29) + return -1; + + if (year < 0) + return -1; + else if (year <= 69) + year += 2000; + else if (year <= 99) + year += 1900; + + /* + * On systems with 32-bit signed time_t, time wraps around in 2038 + * - for now we just limit the year to 2037 (instead of 2069). + * This limit can be removed once no one is using 32-bit systems + * anymore :-). --marekm + */ + if (year < 1970 || year > 2037) + return -1; + + /* + * the total number of days is the total number of days in all + * the whole years, plus the number of leap days, plus the + * number of days in the whole months preceding, plus the number + * of days so far in the month. + */ + + total = (long) ((year - 1970) * 365L) + (((year + 1) - 1970) / 4); + total += (long) juldays[month] + (month > 2 && (year % 4) == 0 ? 1:0); + total += (long) day - 1; + + return total; +#endif /* HAVE_STRPTIME */ +} +#endif /* !USE_GETDATE */ diff --git a/libmisc/suauth.c b/libmisc/suauth.c new file mode 100644 index 00000000..313a6ec6 --- /dev/null +++ b/libmisc/suauth.c @@ -0,0 +1,201 @@ +#include + +#ifdef SU_ACCESS + +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +#ifndef SUAUTHFILE +#define SUAUTHFILE "/etc/suauth" +#endif + +#define NOACTION 0 +#define NOPWORD 1 +#define DENY -1 +#define OWNPWORD 2 + +/* Really, I could do with a few const char's here defining all the + * strings output to the user or the syslog. -- chris + */ + +static int applies P_((const char *, char *)); + +int check_su_auth P_((const char *, const char *)); +int isgrp P_((const char *, const char *)); + +static int lines = 0; + +extern struct passwd pwent; + +int +check_su_auth(const char *actual_id, const char *wanted_id) +{ + int posn, endline; + const char field[] = ":"; + FILE *authfile_fd; + char temp[1024]; + char *to_users; + char *from_users; + char *action; + + if (!(authfile_fd = fopen(SUAUTHFILE, "r"))) { + /* + * If the file doesn't exist - default to the standard su + * behaviour (no access control). If open fails for some + * other reason - maybe someone is trying to fool us with + * file descriptors limit etc., so deny access. --marekm + */ + if (errno == ENOENT) + return NOACTION; + SYSLOG((LOG_ERR, "could not open/read config file '%s': %m\n", + SUAUTHFILE)); + return DENY; + } + + while (fgets(temp, sizeof(temp), authfile_fd) != NULL) { + lines++; + + if (temp[endline = strlen(temp) - 1] != '\n') { + SYSLOG((LOG_ERR, + "%s, line %d: line too long or missing newline", + SUAUTHFILE, lines)); + continue; + } + + while (endline > 0 && (temp[endline-1] == ' ' + || temp[endline-1] == '\t' || temp[endline-1] == '\n')) + endline--; + temp[endline] = '\0'; + + posn = 0; + while (temp[posn] == ' ' || temp[posn] == '\t') + posn++; + + if (temp[posn] == '\n' || temp[posn] == '#' || temp[posn] == '\0') { + continue; + } + if (!(to_users = strtok(temp + posn, field)) + || !(from_users = strtok((char *)NULL, field)) + || !(action = strtok((char *)NULL, field)) + || strtok((char *)NULL, field)) { + SYSLOG((LOG_ERR, "%s, line %d. Bad number of fields.\n", + SUAUTHFILE, lines)); + continue; + } + + if (!applies(wanted_id, to_users)) + continue; + if (!applies(actual_id, from_users)) + continue; + if (!strcmp(action, "DENY")) { + SYSLOG((pwent.pw_uid ? LOG_NOTICE : LOG_WARN, + "DENIED su from `%s' to `%s' (%s)\n", + actual_id, wanted_id, SUAUTHFILE)); + fprintf(stderr, _("Access to su to that account DENIED.\n")); + fclose(authfile_fd); + return DENY; + } else if (!strcmp(action, "NOPASS")) { + SYSLOG((pwent.pw_uid ? LOG_INFO : LOG_NOTICE, + "NO password asked for su from `%s' to `%s' (%s)\n", + actual_id, wanted_id, SUAUTHFILE)); + fprintf(stderr, _("Password authentication bypassed.\n")); + fclose(authfile_fd); + return NOPWORD; + } else if (!strcmp(action, "OWNPASS")) { + SYSLOG((pwent.pw_uid ? LOG_INFO : LOG_NOTICE, + "su from `%s' to `%s': asking for user's own password (%s)\n", + actual_id, wanted_id, SUAUTHFILE)); + fprintf(stderr, _("Please enter your OWN password as authentication.\n")); + fclose(authfile_fd); + return OWNPWORD; + } else { + SYSLOG((LOG_ERR, "%s, line %d: unrecognised action!\n", + SUAUTHFILE, lines)); + } + } + fclose(authfile_fd); + return NOACTION; +} + +static int +applies(const char *single, char *list) +{ + const char split[] = ", "; + char *tok; + + int state = 0; + + for (tok = strtok(list, split); tok != NULL; tok = strtok(NULL, split)) { + + if (!strcmp(tok, "ALL")) { + if (state != 0) { + SYSLOG((LOG_ERR, + "%s, line %d: ALL in bad place\n", + SUAUTHFILE, lines)); + return 0; + } + state = 1; + } else if (!strcmp(tok, "EXCEPT")) { + if (state != 1) { + SYSLOG((LOG_ERR, + "%s, line %d: EXCEPT in bas place\n", + SUAUTHFILE, lines)); + return 0; + } + state = 2; + } else if (!strcmp(tok, "GROUP")) { + if ((state != 0) && (state != 2)) { + SYSLOG((LOG_ERR, + "%s, line %d: GROUP in bad place\n", + SUAUTHFILE, lines)); + return 0; + } + state = (state == 0) ? 3 : 4; + } else { + switch (state) { + case 0: /* No control words yet */ + if (!strcmp(tok, single)) + return 1; + break; + case 1: /* An all */ + SYSLOG((LOG_ERR, "%s, line %d: expect another token after ALL\n", + SUAUTHFILE, lines)); + return 0; + case 2: /* All except */ + if (!strcmp(tok, single)) + return 0; + break; + case 3: /* Group */ + if (isgrp(single, tok)) + return 1; + break; + case 4: /* All except group */ + if (isgrp(single, tok)) + return 0; + /* FALL THRU */ + } + } + } + if ((state != 0) && (state != 3)) + return 1; + return 0; +} + +int +isgrp(const char *name, const char *group) +{ + struct group *grp; + + grp = getgrnam(group); + + if (!grp || !grp->gr_mem) + return 0; + + return is_on_list(grp->gr_mem, name); +} +#endif /* SU_ACCESS */ diff --git a/libmisc/sub.c b/libmisc/sub.c new file mode 100644 index 00000000..88f2df03 --- /dev/null +++ b/libmisc/sub.c @@ -0,0 +1,78 @@ +/* + * Copyright 1989 - 1991, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: sub.c,v 1.6 1999/03/07 19:14:43 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" + +#include + +#define BAD_SUBROOT2 "invalid root `%s' for user `%s'\n" +#define NO_SUBROOT2 "no subsystem root `%s' for user `%s'\n" + +/* + * subsystem - change to subsystem root + * + * A subsystem login is indicated by the presense of a "*" as + * the first character of the login shell. The given home + * directory will be used as the root of a new filesystem which + * the user is actually logged into. + */ + +void +subsystem(const struct passwd *pw) +{ + /* + * The new root directory must begin with a "/" character. + */ + + if (pw->pw_dir[0] != '/') { + printf(_("Invalid root directory \"%s\"\n"), pw->pw_dir); + SYSLOG((LOG_WARN, BAD_SUBROOT2, pw->pw_dir, pw->pw_name)); + closelog(); + exit (1); + } + + /* + * The directory must be accessible and the current process + * must be able to change into it. + */ + + if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) { + printf(_("Can't change root directory to \"%s\"\n"), pw->pw_dir); + SYSLOG((LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name)); + closelog(); + exit (1); + } +} diff --git a/libmisc/sulog.c b/libmisc/sulog.c new file mode 100644 index 00000000..f20152e7 --- /dev/null +++ b/libmisc/sulog.c @@ -0,0 +1,77 @@ +/* + * Copyright 1989 - 1992, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: sulog.c,v 1.4 1998/04/02 21:51:51 marekm Exp $") + +#include +#include +#include +#include +#include "defines.h" +#include "getdef.h" + +extern char name[]; +extern char oldname[]; +extern struct tm *localtime (); + +/* + * sulog - log a SU command execution result + */ + +void +sulog(const char *tty, int success) +{ + char *sulog_file; + time_t now; + struct tm *tm; + FILE *fp; + mode_t oldmask; + + if ((sulog_file = getdef_str("SULOG_FILE")) == (char *) 0) + return; + + oldmask = umask(077); + fp = fopen(sulog_file, "a+"); + umask(oldmask); + if (fp == (FILE *) 0) + return; /* can't open or create logfile */ + + time(&now); + tm = localtime(&now); + + fprintf(fp, "SU %.02d/%.02d %.02d:%.02d %c %.6s %s-%s\n", + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, + success ? '+':'-', tty, oldname, name); + + fflush(fp); + fclose(fp); +} diff --git a/libmisc/ttytype.c b/libmisc/ttytype.c new file mode 100644 index 00000000..965dc7f1 --- /dev/null +++ b/libmisc/ttytype.c @@ -0,0 +1,89 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: ttytype.c,v 1.5 1997/12/07 23:27:10 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include "getdef.h" + +extern char *getenv(); + +/* + * ttytype - set ttytype from port to terminal type mapping database + */ + +void +ttytype(const char *line) +{ + FILE *fp; + char buf[BUFSIZ]; + char *typefile; + char *cp; + char type[BUFSIZ]; + char port[BUFSIZ]; + + if (getenv ("TERM")) + return; + if ((typefile=getdef_str("TTYTYPE_FILE")) == NULL ) + return; + if (access(typefile, F_OK)) + return; + + if (! (fp = fopen (typefile, "r"))) { + perror (typefile); + return; + } + while (fgets(buf, sizeof buf, fp)) { + if (buf[0] == '#') + continue; + + if ((cp = strchr (buf, '\n'))) + *cp = '\0'; + +#if defined(SUN) || defined(BSD) || defined(SUN4) + if ((sscanf (buf, "%s \"%*[^\"]\" %s", port, type) == 2 || + sscanf (buf, "%s %*s %s", port, type) == 2) && + strcmp (line, port) == 0) + break; +#else /* USG */ + if (sscanf (buf, "%s %s", type, port) == 2 && + strcmp (line, port) == 0) + break; +#endif + } + if (! feof (fp) && ! ferror (fp)) + addenv("TERM", type); + + fclose (fp); +} diff --git a/libmisc/tz.c b/libmisc/tz.c new file mode 100644 index 00000000..9449f6d8 --- /dev/null +++ b/libmisc/tz.c @@ -0,0 +1,67 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh and Chip Rosenthal + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: tz.c,v 1.4 1998/01/29 23:22:36 marekm Exp $") + +#include +#include +#include "defines.h" +#include "getdef.h" + +/* + * tz - return local timezone name + * + * tz() determines the name of the local timezone by reading the + * contents of the file named by ``fname''. + */ + +char * +tz(const char *fname) +{ + FILE *fp = 0; + static char tzbuf[BUFSIZ]; + const char *def_tz; + + if ((fp = fopen(fname,"r")) == NULL || + fgets (tzbuf, sizeof (tzbuf), fp) == NULL) { + if (! (def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/') + def_tz = "TZ=CST6CDT"; + + strcpy (tzbuf, def_tz); + } else + tzbuf[strlen(tzbuf) - 1] = '\0'; + + if (fp) + (void) fclose(fp); + + return tzbuf; +} diff --git a/libmisc/ulimit.c b/libmisc/ulimit.c new file mode 100644 index 00000000..e99dab22 --- /dev/null +++ b/libmisc/ulimit.c @@ -0,0 +1,34 @@ +#include + +#include "rcsid.h" +RCSID("$Id: ulimit.c,v 1.2 1997/12/07 23:27:11 marekm Exp $") + +#if HAVE_ULIMIT_H +#include + +#ifndef UL_SETFSIZE +#ifdef UL_SFILLIM +#define UL_SETFSIZE UL_SFILLIM +#else +#define UL_SETFSIZE 2 +#endif +#endif + +#elif HAVE_SYS_RESOURCE_H +#include /* for struct timeval on sunos4 */ +/* XXX - is the above ok or should it be on ultrix? */ +#include +#endif + +void +set_filesize_limit(int blocks) +{ +#if HAVE_ULIMIT_H + ulimit(UL_SETFSIZE, blocks); +#elif defined(RLIMIT_FSIZE) + struct rlimit rlimit_fsize; + + rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks; + setrlimit(RLIMIT_FSIZE, &rlimit_fsize); +#endif +} diff --git a/libmisc/utmp.c b/libmisc/utmp.c new file mode 100644 index 00000000..bc020a2a --- /dev/null +++ b/libmisc/utmp.c @@ -0,0 +1,478 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "defines.h" + +#include + +#if HAVE_UTMPX_H +#include +#endif + +#include +#include + +#include "rcsid.h" +RCSID("$Id: utmp.c,v 1.8 1999/06/07 16:40:44 marekm Exp $") + +#if HAVE_UTMPX_H +extern struct utmpx utxent; +#endif +extern struct utmp utent; + +extern struct utmp *getutent(); +extern struct utmp *getutline(); +extern void setutent(); +extern void endutent(); +extern time_t time(); +extern char *ttyname(); +extern long lseek(); + +#define NO_UTENT \ + "No utmp entry. You must exec \"login\" from the lowest level \"sh\"" +#define NO_TTY \ + "Unable to determine your tty name." + +/* + * checkutmp - see if utmp file is correct for this process + * + * System V is very picky about the contents of the utmp file + * and requires that a slot for the current process exist. + * The utmp file is scanned for an entry with the same process + * ID. If no entry exists the process exits with a message. + * + * The "picky" flag is for network and other logins that may + * use special flags. It allows the pid checks to be overridden. + * This means that getty should never invoke login with any + * command line flags. + */ + +#if defined(__linux__) /* XXX */ + +void +checkutmp(int picky) +{ + char *line; + struct utmp *ut; + pid_t pid = getpid(); + + setutent(); + + /* First, try to find a valid utmp entry for this process. */ + while ((ut = getutent())) + if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] && + (ut->ut_type==LOGIN_PROCESS || ut->ut_type==USER_PROCESS)) + break; + + /* If there is one, just use it, otherwise create a new one. */ + if (ut) { + utent = *ut; + } else { + if (picky) { + puts(NO_UTENT); + exit(1); + } + line = ttyname(0); + if (!line) { + puts(NO_TTY); + exit(1); + } + if (strncmp(line, "/dev/", 5) == 0) + line += 5; + memset((void *) &utent, 0, sizeof utent); + utent.ut_type = LOGIN_PROCESS; + utent.ut_pid = pid; + strncpy(utent.ut_line, line, sizeof utent.ut_line); + /* XXX - assumes /dev/tty?? */ + strncpy(utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id); + strcpy(utent.ut_user, "LOGIN"); + time(&utent.ut_time); + } +} + +#elif defined(LOGIN_PROCESS) + +void +checkutmp(int picky) +{ + char *line; + struct utmp *ut; +#if HAVE_UTMPX_H + struct utmpx *utx; +#endif + pid_t pid = getpid(); + +#if HAVE_UTMPX_H + setutxent(); +#endif + setutent(); + + if (picky) { +#if HAVE_UTMPX_H + while ((utx = getutxent())) + if (utx->ut_pid == pid) + break; + + if (utx) + utxent = *utx; +#endif + while ((ut = getutent())) + if (ut->ut_pid == pid) + break; + + if (ut) + utent = *ut; + +#if HAVE_UTMPX_H + endutxent(); +#endif + endutent(); + + if (!ut) { + puts(NO_UTENT); + exit(1); + } +#ifndef UNIXPC + + /* + * If there is no ut_line value in this record, fill + * it in by getting the TTY name and stuffing it in + * the structure. The UNIX/PC is broken in this regard + * and needs help ... + */ + + if (utent.ut_line[0] == '\0') +#endif /* !UNIXPC */ + { + if (!(line = ttyname(0))) { + puts(NO_TTY); + exit(1); + } + if (strncmp(line, "/dev/", 5) == 0) + line += 5; + strncpy(utent.ut_line, line, sizeof utent.ut_line); +#if HAVE_UTMPX_H + strncpy(utxent.ut_line, line, sizeof utxent.ut_line); +#endif + } + } else { + if (!(line = ttyname(0))) { + puts(NO_TTY); + exit(1); + } + if (strncmp(line, "/dev/", 5) == 0) + line += 5; + + strncpy (utent.ut_line, line, sizeof utent.ut_line); + if ((ut = getutline(&utent))) + strncpy(utent.ut_id, ut->ut_id, sizeof ut->ut_id); + + strcpy(utent.ut_user, "LOGIN"); + utent.ut_pid = getpid(); + utent.ut_type = LOGIN_PROCESS; + time(&utent.ut_time); +#if HAVE_UTMPX_H + strncpy(utxent.ut_line, line, sizeof utxent.ut_line); + if ((utx = getutxline(&utxent))) + strncpy(utxent.ut_id, utx->ut_id, sizeof utxent.ut_id); + + strcpy(utxent.ut_user, "LOGIN"); + utxent.ut_pid = utent.ut_pid; + utxent.ut_type = utent.ut_type; + gettimeofday((struct timeval *) &utxent.ut_tv, NULL); + utent.ut_time = utxent.ut_tv.tv_sec; +#endif + } +} + +#else /* !USG */ + +void +checkutmp(int picky) +{ + char *line; + + /* + * Hand-craft a new utmp entry. + */ + + memzero(&utent, sizeof utent); + if (! (line = ttyname (0))) { + puts (NO_TTY); + exit (1); + } + if (strncmp (line, "/dev/", 5) == 0) + line += 5; + + (void) strncpy (utent.ut_line, line, sizeof utent.ut_line); + (void) time (&utent.ut_time); +} + +#endif /* !USG */ + + +/* + * Some systems already have updwtmp() and possibly updwtmpx(). Others + * don't, so we re-implement these functions if necessary. --marekm + */ + +#ifndef HAVE_UPDWTMP +static void +updwtmp(const char *filename, const struct utmp *ut) +{ + int fd; + + fd = open(filename, O_APPEND | O_WRONLY, 0); + if (fd >= 0) { + write(fd, (const char *) ut, sizeof(*ut)); + close(fd); + } +} +#endif /* ! HAVE_UPDWTMP */ + +#ifdef HAVE_UTMPX_H +#ifndef HAVE_UPDWTMPX +static void +updwtmpx(const char *filename, const struct utmpx *utx) +{ + int fd; + + fd = open(filename, O_APPEND | O_WRONLY, 0); + if (fd >= 0) { + write(fd, (const char *) utx, sizeof(*utx)); + close(fd); + } +} +#endif /* ! HAVE_UPDWTMPX */ +#endif /* ! HAVE_UTMPX_H */ + + +/* + * setutmp - put a USER_PROCESS entry in the utmp file + * + * setutmp changes the type of the current utmp entry to + * USER_PROCESS. the wtmp file will be updated as well. + */ + +#if defined(__linux__) /* XXX */ + +void +setutmp(const char *name, const char *line, const char *host) +{ + utent.ut_type = USER_PROCESS; + strncpy(utent.ut_user, name, sizeof utent.ut_user); + time(&utent.ut_time); + /* other fields already filled in by checkutmp above */ + setutent(); + pututline(&utent); + endutent(); + updwtmp(_WTMP_FILE, &utent); +} + +#elif HAVE_UTMPX_H + +void +setutmp(const char *name, const char *line, const char *host) +{ + struct utmp *utmp, utline; + struct utmpx *utmpx, utxline; + pid_t pid = getpid (); + int found_utmpx = 0, found_utmp = 0; + + /* + * The canonical device name doesn't include "/dev/"; skip it + * if it is already there. + */ + + if (strncmp (line, "/dev/", 5) == 0) + line += 5; + + /* + * Update utmpx. We create an empty entry in case there is + * no matching entry in the utmpx file. + */ + + setutxent (); + setutent (); + + while (utmpx = getutxent ()) { + if (utmpx->ut_pid == pid) { + found_utmpx = 1; + break; + } + } + while (utmp = getutent ()) { + if (utmp->ut_pid == pid) { + found_utmp = 1; + break; + } + } + + /* + * If the entry matching `pid' cannot be found, create a new + * entry with the device name in it. + */ + + if (! found_utmpx) { + memset ((void *) &utxline, 0, sizeof utxline); + strncpy (utxline.ut_line, line, sizeof utxline.ut_line); + utxline.ut_pid = getpid (); + } else { + utxline = *utmpx; + if (strncmp (utxline.ut_line, "/dev/", 5) == 0) { + memmove (utxline.ut_line, utxline.ut_line + 5, + sizeof utxline.ut_line - 5); + utxline.ut_line[sizeof utxline.ut_line - 5] = '\0'; + } + } + if (! found_utmp) { + memset ((void *) &utline, 0, sizeof utline); + strncpy (utline.ut_line, utxline.ut_line, + sizeof utline.ut_line); + utline.ut_pid = utxline.ut_pid; + } else { + utline = *utmp; + if (strncmp (utline.ut_line, "/dev/", 5) == 0) { + memmove (utline.ut_line, utline.ut_line + 5, + sizeof utline.ut_line - 5); + utline.ut_line[sizeof utline.ut_line - 5] = '\0'; + } + } + + /* + * Fill in the fields in the utmpx entry and write it out. Do + * the utmp entry at the same time to make sure things don't + * get messed up. + */ + + strncpy (utxline.ut_user, name, sizeof utxline.ut_user); + strncpy (utline.ut_user, name, sizeof utline.ut_user); + + utline.ut_type = utxline.ut_type = USER_PROCESS; + + gettimeofday(&utxline.ut_tv, NULL); + utline.ut_time = utxline.ut_tv.tv_sec; + + strncpy(utxline.ut_host, host ? host : "", sizeof utxline.ut_host); + + pututxline (&utxline); + pututline (&utline); + + updwtmpx(_WTMP_FILE "x", &utxline); + updwtmp(_WTMP_FILE, &utline); + + utxent = utxline; + utent = utline; +} + +#else /* !SVR4 */ + +void +setutmp(const char *name, const char *line) +{ + struct utmp utmp; + int fd; + int found = 0; + + if ((fd = open(_UTMP_FILE, O_RDWR)) < 0) + return; + +#if !defined(SUN) && !defined(BSD) && !defined(SUN4) /* XXX */ + while (!found && read(fd, (char *)&utmp, sizeof utmp) == sizeof utmp) { + if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line)) + found++; + } +#endif + + if (! found) { + + /* + * This is a brand-new entry. Clear it out and fill it in + * later. + */ + + memzero(&utmp, sizeof utmp); + strncpy(utmp.ut_line, line, (int) sizeof utmp.ut_line); + } + + /* + * Fill in the parts of the UTMP entry. BSD has just the name, + * while System V has the name, PID and a type. + */ + + strncpy(utmp.ut_user, name, sizeof utent.ut_user); +#ifdef USER_PROCESS + utmp.ut_type = USER_PROCESS; + utmp.ut_pid = getpid (); +#endif + + /* + * Put in the current time (common to everyone) + */ + + (void) time (&utmp.ut_time); + +#ifdef UT_HOST + /* + * Update the host name field for systems with networking support + */ + + (void) strncpy (utmp.ut_host, utent.ut_host, (int) sizeof utmp.ut_host); +#endif + + /* + * Locate the correct position in the UTMP file for this + * entry. + */ + +#ifdef HAVE_TTYSLOT + (void) lseek (fd, (off_t) (sizeof utmp) * ttyslot (), SEEK_SET); +#else + if (found) /* Back up a splot */ + lseek (fd, (off_t) - sizeof utmp, SEEK_CUR); + else /* Otherwise, go to the end of the file */ + lseek (fd, (off_t) 0, SEEK_END); +#endif + + /* + * Scribble out the new entry and close the file. We're done + * with UTMP, next we do WTMP (which is real easy, put it on + * the end of the file. + */ + + (void) write (fd, (char *) &utmp, sizeof utmp); + (void) close (fd); + + updwtmp(_WTMP_FILE, &utmp); + utent = utmp; +} + +#endif /* SVR4 */ diff --git a/libmisc/valid.c b/libmisc/valid.c new file mode 100644 index 00000000..8559638e --- /dev/null +++ b/libmisc/valid.c @@ -0,0 +1,101 @@ +/* + * Copyright 1989 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: valid.c,v 1.4 1999/03/07 19:14:44 marekm Exp $") + +#include +#include +#include "prototypes.h" +#include "defines.h" +#include + +/* + * valid - compare encrypted passwords + * + * Valid() compares the DES encrypted password from the password file + * against the password which the user has entered after it has been + * encrypted using the same salt as the original. Entries which do + * not have a password file entry have a NULL pw_name field and this + * is used to indicate that a dummy salt must be used to encrypt the + * password anyway. + */ + +int +valid(const char *password, const struct passwd *ent) +{ + const char *encrypted; + const char *salt; + + /* + * Start with blank or empty password entries. Always encrypt + * a password if no such user exists. Only if the ID exists and + * the password is really empty do you return quickly. This + * routine is meant to waste CPU time. + */ + + if (ent->pw_name && ! ent->pw_passwd[0]) { + if (! password[0]) + return (1); /* user entered nothing */ + else + return (0); /* user entered something! */ + } + + /* + * If there is no entry then we need a salt to use. + */ + + if (ent->pw_name == (char *) 0 || ent->pw_passwd[0] == '\0') { + salt = "xx"; + } else { + salt = ent->pw_passwd; + } + + /* + * Now, perform the encryption using the salt from before on + * the users input. Since we always encrypt the string, it + * should be very difficult to determine if the user exists by + * looking at execution time. + */ + + encrypted = pw_encrypt(password, salt); + + /* + * One last time we must deal with there being no password file + * entry for the user. We use the pw_name == NULL idiom to + * cause non-existent users to not be validated. + */ + + if (ent->pw_name && strcmp(encrypted, ent->pw_passwd) == 0) + return (1); + else + return (0); +} diff --git a/libmisc/xmalloc.c b/libmisc/xmalloc.c new file mode 100644 index 00000000..e85ae26c --- /dev/null +++ b/libmisc/xmalloc.c @@ -0,0 +1,38 @@ +/* Replacements for malloc and strdup with error checking. Too trivial + to be worth copyrighting :-). I did that because a lot of code used + malloc and strdup without checking for NULL pointer, and I like some + message better than a core dump... --marekm + + Yeh, but. Remember that bailing out might leave the system in some + bizarre state. You really want to put in error checking, then add + some back-out failure recovery code. -- jfh */ + +#include + +#include "rcsid.h" +RCSID("$Id: xmalloc.c,v 1.3 1998/12/28 20:34:56 marekm Exp $") + +#include + +#include "defines.h" + +extern char *malloc(); + +char * +xmalloc(size_t size) +{ + char *ptr; + + ptr = malloc(size); + if (!ptr && size) { + fprintf(stderr, _("malloc(%d) failed\n"), (int) size); + exit(13); + } + return ptr; +} + +char * +xstrdup(const char *str) +{ + return strcpy(xmalloc(strlen(str) + 1), str); +} diff --git a/ltconfig b/ltconfig new file mode 100755 index 00000000..60637ccd --- /dev/null +++ b/ltconfig @@ -0,0 +1,1519 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# This file 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A lot of this script is taken from autoconf-2.10. + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +echo=echo +if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : +else + # The Solaris and AIX default echo program unquotes backslashes. + # This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # So, we emulate echo with printf '%s\n' + echo="printf %s\\n" + if test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then : + else + # Oops. We have no working printf. Try to find a not-so-buggy echo. + echo=echo + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH /usr/ucb; do + if test -f $dir/echo && test "X`$dir/echo '\t'`" = 'X\t'; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.2 +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.c 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.c $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking. +enable_static=yes +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +verify_host=yes +with_gcc=no +with_gnu_ld=no + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_NM="$NM" +old_RANLIB="$RANLIB" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test -f "$ltmain"; then : +else + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to ltmain.sh. + srcdir=`$echo "$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds;\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib;$old_postinstall_cmds" +fi + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + for dir in $PATH; do + IFS="$save_ifs" + test -z "$dir" && dir=. + if test -f $dir/gcc; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:424: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + no_builtin_flag=' -fno-builtin' + + case "$host_os" in + aix3* | aix4* | irix5* | irix6* | osf3* | osf4*) + # PIC is the default for these OSes. + ;; + os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4.2uw2*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:547: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:548: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:591: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftestdata + if ln -s X conftestdata 2>/dev/null; then + $rm conftestdata + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:624: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + /* | [A-Za-z]:\\*) + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:642: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:645: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 &5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +archive_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= + +case "$host_os" in +amigaos* | sunos4*) + # On these operating systems, we should treat GNU ld like the system ld. + gnu_ld_acts_native=yes + ;; +*) + gnu_ld_acts_native=no + ;; +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes && test "$gnu_ld_acts_native" != yes; then + + # See if GNU ld supports shared libraries. + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + case "$host_os" in + linux-gnu*) + archive_cmds='$CC -shared ${wl}-soname $wl$soname -o $lib$libobjs $deplibs' + ;; + *) + archive_cmds='$CC -shared ${wl}-soname $wl$soname -o $lib$libobjs' + ;; + esac + runpath_var=LD_RUN_PATH + ld_shlibs=yes + else + ld_shlibs=no + fi + + if test "$ld_shlibs" = yes; then + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$LD -o $objdir/$soname$libobjs -bE:$lib.exp -T512 -H512 -bM:SRE;$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + allow_undefined_flag=unsupported + archive_cmds='$NM$libobjs | $global_symbol_pipe | sed '\''s/.* //'\'' > $lib.exp;$CC -o $objdir/$soname$libobjs ${wl}-bE:$lib.exp ${wl}-bM:SRE ${wl}-bnoentry;$AR cru $lib $objdir/$soname' + hardcode_direct=yes + hardcode_minus_L=yes + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data;$echo "#define NAME $libname" > $objdir/a2ixlibrary.data;$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data;$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data;$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data;$AR cru $lib$libobjs;$RANLIB $lib;(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3, at last, uses gcc -shared to do shared libraries. + freebsd3*) + archive_cmds='$CC -shared -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + archive_cmds='$rm $objdir/$soname;$LD -b +s +b $install_libdir -o $objdir/$soname$libobjs;mv $objdir/$soname $lib' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + archive_cmds='$LD -b +h $soname +s +b $install_libdir -o $lib$libobjs' + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + archive_cmds='$LD -shared -o $lib -soname $soname -set_version $verstring$libobjs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + ;; + + netbsd*) + # Tested with NetBSD 1.2 ld + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def;$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def;$echo DATA >> $objdir/$libname.def;$echo " SINGLE NONSHARED" >> $objdir/$libname.def;$echo EXPORTS >> $objdir/$libname.def;emxexp$libobjs >> $objdir/$libname.def;$CC -Zdll -Zcrtdll -o $lib$libobjs $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3* | osf4*) + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} -o $lib -soname $soname -set_version $verstring$libobjs$deplibs' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -o $lib$libobjs' + hardcode_direct=yes + ;; + + solaris2*) + no_undefined_flag=' -z text' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + + # Solaris 2 before 2.5 hardcodes -L paths. + case "$host_os" in + solaris2.[0-4]*) + hardcode_minus_L=yes + ;; + esac + ;; + + sunos4*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared -o $lib$libobjs' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib$libobjs' + fi + + if test "$with_gnu_ld" = yes; then + export_dynamic_flag_spec='${wl}-export-dynamic' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib$libobjs' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + can_build_shared=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + /* | [A-Za-z]:\\*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in /usr/ucb /usr/ccs/bin $PATH /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + else + NM="$ac_dir/nm" + fi + break + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRSTU]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \1' + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDTU]' + ;; +irix*) + # Cannot use undefined symbols on IRIX because inlined functions mess us up. + symcode='[BCDEGRST]' + ;; +solaris2*) + symcode='[BDTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTUW]' +fi + +# Write the raw and C identifiers. +global_symbol_pipe="sed -n -e 's/^.* $symcode $sympat$/$symxfrm/p'" + +# Check to see that the pipe works correctly. +pipe_works=no +$rm conftest* +cat > conftest.c <&5 +if { (eval echo $progname:979: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:982: eval \"$NM conftest.o | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.o | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`$echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + rm -f "$nlist"T + count=-1 + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + sed 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> conftest.c + + cat <> conftest.c +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{ +EOF + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.o conftestm.o + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS='conftestm.o' + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1040: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi +else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* + +# Do not use the global_symbol_pipe unless it works. +echo "$ac_t$pipe_works" 1>&6 +test "$pipe_works" = yes || global_symbol_pipe= + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && \ + test "$hardcode_minus_L" != no && \ + test "$hardcode_shlibpath_var" != no; then + + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +elif test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" != yes; then + # We cannot hardcode anything. + hardcode_action=unsupported +else + # We can only hardcode existing directories. + hardcode_action=relink +fi +echo "$ac_t$hardcode_action" 1>&6 +test "$hardcode_action" = unsupported && can_build_shared=no + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 +# PORTME Some linker may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" 1>&6 +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +version_type=none +dynamic_linker="$host_os ld.so" + +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3* | aix4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so.$major' + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +freebsd2* | freebsd3*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +gnu*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + shlibpath_var=SHLIB_PATH + library_names_spec='${libname}${release}.sl.$versuffix ${libname}${release}.sl.$major $libname.sl' + soname_spec='${libname}${release}.sl.$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + finish_cmds='PATH="$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd* | openbsd*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4*) + version_type=osf + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so.$versuffix $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so.$versuffix' + finish_cmds='PATH="$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4.2uw2*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major $libname.so' + soname_spec='${libname}${release}.so.$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" 1>&6 +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds;\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" + +# Now quote all the things that may contain metacharacters. +for var in ltecho old_CC old_CFLAGS old_CPPFLAGS old_LD old_NM old_RANLIB \ + old_LN_S AR CC LD LN_S NM reload_flag reload_cmds wl pic_flag \ + link_static_flag no_builtin_flag export_dynamic_flag_spec \ + libname_spec library_names_spec soname_spec RANLIB \ + old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds postinstall_cmds postuninstall_cmds \ + allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe \ + hardcode_libdir_flag_spec hardcode_libdir_separator; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | archive_cmds | \ + postinstall_cmds | postuninstall_cmds | finish_cmds) + # Double-quote double-evaled strings. + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\"\`" + ;; + *) + eval "$var=\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`" + ;; + esac +done + +ofile=libtool +trap "$rm $ofile; exit 1" 1 2 15 +echo creating $ofile +$rm $ofile +cat < $ofile +#! /bin/sh + +# libtool - Provide generalized library-building support services. +# Generated automatically by $PROGRAM - GNU $PACKAGE $VERSION +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This program was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC="$old_CC" CFLAGS="$old_CFLAGS" CPPFLAGS="$old_CPPFLAGS" \\ +# LD="$old_LD" NM="$old_NM" RANLIB="$old_RANLIB" LN_S="$old_LN_S" \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "\${CDPATH+set}" = set; then CDPATH=; export CDPATH; fi + +# An echo program that does not interpret backslashes. +echo="$ltecho" + +# The version of $progname that generated this script. +LTCONFIG_VERSION="$VERSION" + +# Shell to use when invoking shell scripts. +SHELL=${CONFIG_SHELL-/bin/sh} + +# Whether or not to build libtool libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build old-style libraries. +build_old_libs=$enable_static + +# The host system. +host_alias="$host_alias" +host="$host" + +# The archiver. +AR="$AR" + +# The default C compiler. +CC="$CC" + +# The linker used to build libraries. +LD="$LD" + +# Whether we need hard or soft links. +LN_S="$LN_S" + +# A BSD-compatible nm program. +NM="$NM" + +# The name of the directory that contains temporary libtool files. +objdir="$objdir" + +# How to create reloadable object files. +reload_flag="$reload_flag" +reload_cmds="$reload_cmds" + +# How to pass a linker flag through the compiler. +wl="$wl" + +# Additional compiler flags for building library objects. +pic_flag="$pic_flag" + +# Compiler flag to prevent dynamic linking. +link_static_flag="$link_static_flag" + +# Compiler flag to turn off builtin functions. +no_builtin_flag="$no_builtin_flag" + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec="$export_dynamic_flag_spec" + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec="$libname_spec" + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec="$library_names_spec" + +# The coded name of the library, if different from the real name. +soname_spec="$soname_spec" + +# Commands used to build and install an old-style archive. +RANLIB="$RANLIB" +old_archive_cmds="$old_archive_cmds" +old_postinstall_cmds="$old_postinstall_cmds" +old_postuninstall_cmds="$old_postuninstall_cmds" + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds="$old_archive_from_new_cmds" + +# Commands used to build and install a shared archive. +archive_cmds="$archive_cmds" +postinstall_cmds="$postinstall_cmds" +postuninstall_cmds="$postuninstall_cmds" + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag="$allow_undefined_flag" + +# Flag that forces no undefined symbols. +no_undefined_flag="$no_undefined_flag" + +# Commands used to finish a libtool library installation in a directory. +finish_cmds="$finish_cmds" + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval="$finish_eval" + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe="$global_symbol_pipe" + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec="$hardcode_libdir_flag_spec" + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator="$hardcode_libdir_separator" + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +EOF + +case "$host_os" in +aix3*) + cat <<\EOF >> $ofile +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "${COLLECT_NAMES+set}" != set; then + COLLECT_NAMES= + export COLLECT_NAMES +fi + +EOF + ;; +esac + +# Append the ltmain.sh script. +cat "$ltmain" >> $ofile || (rm -f $ofile; exit 1) + +chmod +x $ofile +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/ltmain.sh b/ltmain.sh new file mode 100644 index 00000000..e9350b3f --- /dev/null +++ b/ltmain.sh @@ -0,0 +1,2453 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun ltconfig. +# +# Copyright (C) 1996-1998 Free Software Foundation, Inc. +# Gordon Matzigkeit , 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# The name of this program. +progname=`$echo "$0" | sed 's%^.*/%%'` +modename="$progname" + +# Constants. +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.2 + +default_mode= +help="Try \`$progname --help' for more information." +magic="%%%MAGIC variable%%%" +mkdir="mkdir" +mv="mv -f" +rm="rm -f" + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi + +if test "$LTCONFIG_VERSION" != "$VERSION"; then + echo "$modename: ltconfig version \`$LTCONFIG_VERSION' does not match $PROGRAM version \`$VERSION'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case "$arg" in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + execute_dlfiles) + eval "$prev=\"\$$prev \$arg\"" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case "$arg" in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION" + exit 0 + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case "$nonopt" in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case "$arg" in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case "$mode" in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + lastarg= + srcfile="$nonopt" + suppress_output= + + for arg + do + # Accept any command-line options. + case "$arg" in + -o) + $echo "$modename: you cannot specify the output filename with \`-o'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly in scan + # sets, so we specify it separately. + case "$lastarg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + + # Recognize several different file suffixes. + xform='[cCFSfms]' + case "$libobj" in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case "$libobj" in + *.lo) obj=`$echo "X$libobj" | $Xsed -e 's/\.lo$/.o/'` ;; + *) + $echo "$modename: cannot determine name of library object from \`$srcfile'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + $run $rm $obj $libobj + trap "$run $rm $obj $libobj; exit 1" 1 2 15 + else + $run $rm $libobj + trap "$run $rm $libobj; exit 1" 1 2 15 + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + # All platforms use -DPIC, to notify preprocessed assembler code. + $show "$base_compile$pic_flag -DPIC $srcfile" + if $run eval "$base_compile\$pic_flag -DPIC \$srcfile"; then : + else + test -n "$obj" && $run $rm $obj + exit 1 + fi + + # If we have no pic_flag, then copy the object into place and finish. + if test -z "$pic_flag"; then + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj + exit $? + fi + + # Just move the object, then go on to compile the next one + $show "$mv $obj $libobj" + $run $mv $obj $libobj || exit 1 + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + # Suppress compiler output if we already did a PIC compilation. + $show "$base_compile $srcfile$suppress_output" + if $run eval "$base_compile \$srcfile$suppress_output"; then : + else + $run $rm $obj $libobj + exit 1 + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + fi + + exit 0 + ;; + + # libtool link mode + link) + modename="$modename: link" + CC="$nonopt" + allow_undefined=yes + compile_command="$CC" + finalize_command="$CC" + + compile_shlibpath= + finalize_shlibpath= + deplibs= + dlfiles= + dlprefiles= + export_dynamic=no + hardcode_libdirs= + libobjs= + link_against_libtool_libs= + ltlibs= + objs= + prev= + prevarg= + release= + rpath= + perm_rpath= + temp_rpath= + vinfo= + + # We need to know -static, to get the right output filenames. + for arg + do + case "$arg" in + -all-static | -static) + if test "X$arg" = "X-all-static" && test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + for arg + do + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case "$prev" in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case "$prev" in + dlfiles|dlprefiles) + case "$arg" in + *.la | *.lo) ;; # We handle these cases below. + *) + dlprefiles="$dlprefiles $arg" + test "$prev" = dlfiles && dlfiles="$dlfiles $arg" + prev= + ;; + esac + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath) + rpath="$rpath $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi + + prevarg="$arg" + + case "$arg" in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + if test "$export_dynamic" != yes; then + export_dynamic=yes + if test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + else + arg= + fi + + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + fi + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's%^-L\(.*\)$%\1%'` + case "$dir" in + /* | [A-Za-z]:\\*) + # Add the corresponding hardcode_libdir_flag, if it is not identical. + ;; + *) + $echo "$modename: \`-L$dir' cannot specify a relative directory" 1>&2 + exit 1 + ;; + esac + deplibs="$deplibs $arg" + ;; + + -l*) deplibs="$deplibs $arg" ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -static) + # If we have no pic_flag, then this is the same as -all-static. + if test -z "$pic_flag" && test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + + *.o | *.a) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A library object. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test "$build_libtool_libs" = yes; then + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e 's/\.lo$/\.o/'` + prev= + fi + libobjs="$libobjs $arg" + ;; + + *.la) + # A libtool-controlled library. + + dlname= + libdir= + library_names= + old_library= + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $arg | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$arg' is not a valid libtool archive" 1>&2 + exit 1 + fi + + # If there is no directory component, then add one. + case "$arg" in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$libdir"; then + $echo "$modename: \`$arg' contains no -rpath information" 1>&2 + exit 1 + fi + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$arg'" 1>&2 + exit 1 + fi + + # Find the relevant object directory and library name. + name=`$echo "X$arg" | $Xsed -e 's%^.*/%%' -e 's/\.la$//' -e 's/^lib//'` + dir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$arg"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + + # This library was specified with -dlopen. + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + if test -z "$dlname"; then + # If there is no dlname, we need to preload. + prev=dlprefiles + else + # We should not create a dependency on this library, but we + # may need any libraries it requires. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + prev= + continue + fi + fi + + # The library was specified with -dlpreopen. + if test "$prev" = dlprefiles; then + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + dlprefiles="$dlprefiles $dir/$old_library" + else + dlprefiles="$dlprefiles $dir/$linklib" + fi + prev= + fi + + if test "$build_libtool_libs" = yes && test -n "$library_names"; then + link_against_libtool_libs="$link_against_libtool_libs $arg" + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + + # This is the magic to use -rpath. + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + # Do the same for the permanent run path. + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + + + case "$hardcode_action" in + immediate) + if test "$hardcode_direct" = no; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = no; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = no; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + relink) + # We need an absolute path. + case "$dir" in + /* | [A-Za-z]:\\*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit 1 + fi + dir="$absdir" + ;; + esac + + if test "$hardcode_direct" = yes; then + compile_command="$compile_command $dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + compile_command="$compile_command -L$dir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + compile_shlibpath="$compile_shlibpath$dir:" + compile_command="$compile_command -l$name" + fi + ;; + + *) + $echo "$modename: \`$hardcode_action' is an unknown hardcode action" 1>&2 + exit 1 + ;; + esac + + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + finalize_command="$finalize_command $libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + finalize_command="$finalize_command -L$libdir -l$name" + elif test "$hardcode_shlibpath_var" = yes; then + finalize_shlibpath="$finalize_shlibpath$libdir:" + finalize_command="$finalize_command -l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + finalize_command="$finalize_command -L$libdir -l$name" + fi + else + # Transform directly to old archives if we don't build new libraries. + if test -n "$pic_flag" && test -z "$old_library"; then + $echo "$modename: cannot find static library for \`$arg'" 1>&2 + exit 1 + fi + + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_command="$compile_command $dir/$linklib" + finalize_command="$finalize_command $dir/$linklib" + else + compile_command="$compile_command -L$dir -l$name" + finalize_command="$finalize_command -L$dir -l$name" + fi + fi + + # Add in any libraries that this one depends upon. + compile_command="$compile_command$dependency_libs" + finalize_command="$finalize_command$dependency_libs" + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + ;; + esac + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$vinfo" && test -n "$release"; then + $echo "$modename: you cannot specify both \`-version-info' and \`-release'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + oldlib= + oldobjs= + case "$output" in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + */* | *\\*) + $echo "$modename: output file \`$output' must have no directory components" 1>&2 + exit 1 + ;; + + *.a) + # Now set the variables for building old libraries. + build_libtool_libs=no + build_old_libs=yes + oldlib="$output" + $show "$rm $oldlib" + $run $rm $oldlib + ;; + + *.la) + # Make sure we only generate libraries of the form `libNAME.la'. + case "$output" in + lib*) ;; + *) + $echo "$modename: libtool library \`$arg' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + name=`$echo "X$output" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + current=0 + revision=0 + age=0 + + if test -n "$objs"; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects:$objs" 2>&1 + exit 1 + fi + + # How the heck are we supposed to write a wrapper for a shared library? + if test -n "$link_against_libtool_libs"; then + $echo "$modename: libtool library \`$output' may not depend on uninstalled libraries:$link_against_libtool_libs" 1>&2 + exit 1 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating libtool libraries" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$rpath"; then + $echo "$modename: you must specify an installation directory with \`-rpath'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + set dummy $rpath + if test $# -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + # Parse the version information argument. + IFS="${IFS= }"; save_ifs="$IFS"; IFS=':' + set dummy $vinfo + IFS="$save_ifs" + + if test -n "$5"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + test -n "$2" && current="$2" + test -n "$3" && revision="$3" + test -n "$4" && age="$4" + + # Check that each of the things are valid numbers. + case "$current" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$revision" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case "$age" in + 0 | [1-9] | [1-9][0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test $age -gt $current; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + version_vars="version_type current age revision" + case "$version_type" in + none) ;; + + linux) + version_vars="$version_vars major versuffix" + major=`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + version_vars="$version_vars versuffix verstring" + major=`expr $current - $age` + versuffix="$current.$age.$revision" + verstring="$versuffix" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test $loop != 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + version_vars="$version_vars major versuffix" + major="$current" + versuffix="$current.$revision" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Create the output directory, or remove our outputs if we need to. + if test -d $objdir; then + $show "$rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.*" + $run $rm $objdir/$output $objdir/$libname.* $objdir/${libname}${release}.* + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + # Add libc to deplibs on all systems. + dependency_libs="$deplibs" + deplibs="$deplibs -lc" + + if test "$build_libtool_libs" = yes; then + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + lib="$objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are PIC. + test -z "$pic_flag" && libobjs=`$echo "X$libobjs " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//g'` + + # Do each of the archive commands. + eval cmds=\"$archive_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Create links to the real library. + for linkname in $linknames; do + $show "(cd $objdir && $LN_S $realname $linkname)" + $run eval '(cd $objdir && $LN_S $realname $linkname)' || exit $? + done + + # If -export-dynamic was specified, set the dlname. + if test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + + # Now set the variables for building old libraries. + oldlib="$objdir/$libname.a" + ;; + + *.lo | *.o) + if test -n "$link_against_libtool_libs"; then + $echo "$modename: error: cannot link libtool libraries into reloadable objects" 1>&2 + exit 1 + fi + + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored while creating objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles"; then + $echo "$modename: warning: \`-dlopen' is ignored while creating objects" 1>&2 + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored while creating objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while creating objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + case "$output" in + *.lo) + if test -n "$objs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e 's/\.lo$/.o/'` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Create the old-style object. + reload_objs="$objs"`$echo "X$libobjs " | $Xsed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'` + + output="$obj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + test -z "$libobj" && exit 0 + + if test "$build_libtool_libs" != yes; then + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag"; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs" + output="$libobj" + eval cmds=\"$reload_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show "$LN_S $obj $libobj" + $run $LN_S $obj $libobj || exit 1 + fi + + exit 0 + ;; + + *) + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored while linking programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored while creating objects" 1>&2 + fi + + if test -n "$rpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + # Put the magic libdir with the hardcode flag. + hardcode_libdirs="$libdir" + libdir="@HARDCODE_LIBDIRS@" + else + # Just accumulate the unique libdirs. + case "$hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator" in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + libdir= + fi + fi + + if test -n "$libdir"; then + eval flag=\"$hardcode_libdir_flag_spec\" + + compile_command="$compile_command $flag" + finalize_command="$finalize_command $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + fi + + # Substitute the hardcoded libdirs into the compile commands. + if test -n "$hardcode_libdir_separator"; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@HARDCODE_LIBDIRS@%$hardcode_libdirs%g"` + fi + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + finalize_command=`$echo "X$finalize_command " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + fi + + if test "$export_dynamic" = yes && test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${output}S.c" + else + dlsyms= + fi + + if test -n "$dlsyms"; then + # Add our own program objects to the preloaded list. + dlprefiles=`$echo "X$objs$dlprefiles " | $Xsed -e 's/\.lo /.o /g' -e 's/ $//'` + + # Discover the nlist of each of the dlfiles. + nlist="$objdir/${output}.nm" + + if test -d $objdir; then + $show "$rm $nlist ${nlist}T" + $run $rm "$nlist" "${nlist}T" + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + # Parse the name list into a source file. + $show "creating $objdir/$dlsyms" + if test -z "$run"; then + # Make sure we at least have an empty file. + test -f "$nlist" || : > "$nlist" + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + wcout=`wc "$nlist" 2>/dev/null` + count=`echo "X$wcout" | $Xsed -e 's/^[ ]*\([0-9][0-9]*\).*$/\1/'` + (test "$count" -ge 0) 2>/dev/null || count=-1 + else + $rm "$nlist"T + count=-1 + fi + + case "$dlsyms" in + "") ;; + *.c) + $echo > "$objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$output' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define dld_preloaded_symbol_count some_other_symbol +#define dld_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test -f "$nlist"; then + sed -e 's/^.* \(.*\)$/extern char \1;/' < "$nlist" >> "$objdir/$dlsyms" + else + echo '/* NONE */' >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + +#undef dld_preloaded_symbol_count +#undef dld_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define __ptr_t void * +#else +# define __ptr_t char * +#endif + +/* The number of symbols in dld_preloaded_symbols, -1 if unsorted. */ +int dld_preloaded_symbol_count = $count; + +/* The mapping between symbol names and symbols. */ +struct { + char *name; + __ptr_t address; +} +dld_preloaded_symbols[] = +{\ +" + + if test -f "$nlist"; then + sed 's/^\(.*\) \(.*\)$/ {"\1", (__ptr_t) \&\2},/' < "$nlist" >> "$objdir/$dlsyms" + fi + + $echo >> "$objdir/$dlsyms" "\ + {0, (__ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif\ +" + ;; + + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + fi + + # Now compile the dynamic symbol file. + $show "(cd $objdir && $CC -c$no_builtin_flag \"$dlsyms\")" + $run eval '(cd $objdir && $CC -c$no_builtin_flag "$dlsyms")' || exit $? + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$objdir/${output}S.o%"` + elif test "$export_dynamic" != yes; then + test -n "$dlfiles$dlprefiles" && $echo "$modename: warning: \`-dlopen' and \`-dlpreopen' are ignored without \`-export-dynamic'" 1>&2 + else + # We keep going just in case the user didn't refer to + # dld_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test -z "$link_against_libtool_libs" || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + + # We have no uninstalled library dependencies, so finalize right now. + $show "$compile_command" + $run eval "$compile_command" + exit $? + fi + + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'%g'` + finalize_command=`$echo "X$finalize_command" | $Xsed -e 's%@OUTPUT@%'"$objdir/$output"'T%g'` + + # Create the binary in the object directory, then wrap it. + if test -d $objdir; then : + else + $show "$mkdir $objdir" + $run $mkdir $objdir + status=$? + if test $status -eq 0 || test -d $objdir; then : + else + exit $status + fi + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case "$dir" in + /* | [A-Za-z]:\\*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + # Delete the old output file. + $run $rm $output + + if test -n "$compile_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_command="$runpath_var=\"$rpath\$$runpath_var\" $compile_command" + finalize_command="$runpath_var=\"$rpath\$$runpath_var\" $finalize_command" + fi + + case "$hardcode_action" in + relink) + # AGH! Flame the AIX and HP-UX people for me, will ya? + $echo "$modename: warning: using a buggy system linker" 1>&2 + $echo "$modename: relinking will be required before \`$output' can be installed" 1>&2 + ;; + esac + + $show "$compile_command" + $run eval "$compile_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the finalize command for shipping. + finalize_command=`$echo "X$finalize_command" | $Xsed -e "$sed_quote_subst"` + + # Quote $echo for shipping. + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! /bin/sh + +# $output - temporary wrapper script for $objdir/$output +# Generated by ltmain.sh - GNU $PACKAGE $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of \``pwd`'. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=; export CDPATH; fi + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + link_against_libtool_libs='$link_against_libtool_libs' + finalize_command=\"$finalize_command\" +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" = \"$magic\"; then : + else + echo=\"$qecho\" + file=\"\$0\" + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + /* | [A-Za-z]:\\*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" + + progdir=\"\$thisdir/$objdir\" + program='$output' + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/:*\$//'\` + + export $shlibpath_var +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} + + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + if test "$build_old_libs" = "yes"; then + # Transform .lo files to .o files. + oldobjs="$objs"`$echo "X$libobjs " | $Xsed -e 's/[^ ]*\.a //g' -e 's/\.lo /.o /g' -e 's/ $//g'` + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + eval cmds=\"$old_archive_cmds\" + fi + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Now create the libtool archive. + case "$output" in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.a" + + $show "creating $output" + + # Only create the output if not a dry run. + if test -z "$run"; then + $echo > $output "\ +# $output - a libtool library file +# Generated by ltmain.sh - GNU $PACKAGE $VERSION + +# The name that we can dlopen(3). +dlname='$dlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Directory that this library needs to be installed in: +libdir='$install_libdir'\ +" + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $objdir && $LN_S ../$output $output)" + $run eval "(cd $objdir && $LN_S ../$output $output)" || exit 1 + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional /bin/sh argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL"; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir= + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case "$arg" in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case "$arg" in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test -n "$isdir"; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test $# -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case "$destdir" in + /* | [A-Za-z]:\\*) ;; + *) + for file in $files; do + case "$file" in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case "$file" in + *.a) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir="`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/" + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$realname $destdir/$realname" + $run eval "$install_prog $dir/$realname $destdir/$realname" || exit $? + test "X$dlname" = "X$realname" && dlname= + + if test $# -gt 0; then + # Delete the old symlinks. + rmcmd="$rm" + for linkname + do + rmcmd="$rmcmd $destdir/$linkname" + done + $show "$rmcmd" + $run $rmcmd + + # ... and create new ones. + for linkname + do + test "X$dlname" = "X$linkname" && dlname= + $show "(cd $destdir && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $LN_S $realname $linkname)" + done + fi + + if test -n "$dlname"; then + # Install the dynamically-loadable library. + $show "$install_prog $dir/$dlname $destdir/$dlname" + $run eval "$install_prog $dir/$dlname $destdir/$dlname" || exit $? + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + $show "$install_prog $file $destdir/$name" + $run eval "$install_prog $file $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case "$destfile" in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e 's/\.lo$/\.o/'` + ;; + *.o) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e 's/\.lo$/\.o/'` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + link_against_libtool_libs= + finalize_command= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$link_against_libtool_libs" || test -z "$finalize_command"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $link_against_libtool_libs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case "$lib" in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/`$echo "X$lib" | $Xsed -e 's%^.*/%%g'`" + if test -z "$libdir"; then + $echo "$modename: warning: \`$lib' contains no -rpath information" 1>&2 + elif test -f "$libfile"; then : + else + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + if test "$hardcode_action" = relink; then + if test "$finalize" = yes; then + $echo "$modename: warning: relinking \`$file' on behalf of your buggy system linker" 1>&2 + $show "$finalize_command" + if $run eval "$finalize_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + continue + fi + file="$objdir/$file"T + else + $echo "$modename: warning: cannot relink \`$file' on behalf of your buggy system linker" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + $show "$install_prog$stripme $file $dest" + $run eval "$install_prog\$stripme \$file \$dest" || exit $? + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec $SHELL $0 --finish$current_libdirs + exit 1 + fi + + exit 0 + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" + fi + done + fi + + echo "------------------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "To link against installed libraries in a given directory, LIBDIR," + echo "you must use the \`-LLIBDIR' flag during linking." + echo + echo " You will also need to do one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "------------------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test -f "$file"; then : + else + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case "$file" in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case "$file" in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + # If there is no directory component, then add one. + case "$file" in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + + # Now actually exec the command. + eval "exec \$cmd$args" + + $echo "$modename: cannot exec \$cmd$args" + exit 1 + else + # Display what would be done. + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool uninstall mode + uninstall) + modename="$modename: uninstall" + rm="$nonopt" + files= + + for arg + do + case "$arg" in + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + rmfiles="$file" + + case "$name" in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep '^# Generated by ltmain\.sh') >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $dir/$n" + test "X$n" = "X$dlname" && dlname= + done + test -n "$dlname" && rmfiles="$rmfiles $dir/$dlname" + test -n "$old_library" && rmfiles="$rmfiles $dir/$old_library" + + $show "$rm $rmfiles" + $run $rm $rmfiles + + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + IFS="${IFS= }"; save_ifs="$IFS"; IFS=';' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + done + IFS="$save_ifs" + fi + + # FIXME: should reinstall the best remaining shared library. + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e 's/\.lo$/\.o/'` + rmfiles="$rmfiles $dir/$oldobj" + fi + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + + *) + $show "$rm $rmfiles" + $run $rm $rmfiles + ;; + esac + done + exit 0 + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 +fi # test -z "$show_help" + +# We need to display help for each of the modes. +case "$mode" in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + +-n, --dry-run display commands without modifying any files + --features display configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to dld_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only +library objects (\`.lo' files) may be specified, and \`-rpath' is required. + +If OUTPUT-FILE ends in \`.a', then a standard library is created using \`ar' +and \`ranlib'. + +If OUTPUT-FILE ends in \`.lo' or \`.o', then a reloadable object file is +created, otherwise an executable program is created." + ;; + +uninstall) + $echo +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/man/Makefile.am b/man/Makefile.am new file mode 100644 index 00000000..22aacad9 --- /dev/null +++ b/man/Makefile.am @@ -0,0 +1,32 @@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +man_MANS = chage.1 chfn.1 chsh.1 gpasswd.1 \ + login.1 newgrp.1 passwd.1 su.1 \ + shadow.3 \ + faillog.5 limits.5 login.access.5 login.defs.5 \ + passwd.5 porttime.5 shadow.5 suauth.5 \ + chpasswd.8 dpasswd.8 faillog.8 \ + groupadd.8 groupdel.8 groupmod.8 \ + grpck.8 lastlog.8 logoutd.8 mkpasswd.8 newusers.8 \ + pwck.8 pwconv.8 shadowconfig.8 \ + useradd.8 userdel.8 usermod.8 vipw.8 + +# XXX - for some reason "make dist" no longer distributes man_MANS +# automatically after upgrade to automake-1.2 (it worked with 1.0). +# So they are now all listed in EXTRA_DIST. --marekm +# +#EXTRA_DIST = groups.1 id.1 pw_auth.3 pwauth.8 sulogin.8 + +EXTRA_DIST = groups.1 id.1 pw_auth.3 pwauth.8 sulogin.8 \ + chage.1 chfn.1 chsh.1 gpasswd.1 \ + login.1 newgrp.1 passwd.1 su.1 \ + shadow.3 \ + faillog.5 limits.5 login.access.5 login.defs.5 \ + passwd.5 porttime.5 shadow.5 suauth.5 \ + chpasswd.8 dpasswd.8 faillog.8 \ + groupadd.8 groupdel.8 groupmod.8 \ + grpck.8 lastlog.8 logoutd.8 mkpasswd.8 newusers.8 \ + pwck.8 pwconv.8 shadowconfig.8 \ + useradd.8 userdel.8 usermod.8 vipw.8 + diff --git a/man/Makefile.in b/man/Makefile.in new file mode 100644 index 00000000..6360c7ea --- /dev/null +++ b/man/Makefile.in @@ -0,0 +1,370 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +man_MANS = chage.1 chfn.1 chsh.1 gpasswd.1 \ + login.1 newgrp.1 passwd.1 su.1 \ + shadow.3 \ + faillog.5 limits.5 login.access.5 login.defs.5 \ + passwd.5 porttime.5 shadow.5 suauth.5 \ + chpasswd.8 dpasswd.8 faillog.8 \ + groupadd.8 groupdel.8 groupmod.8 \ + grpck.8 lastlog.8 logoutd.8 mkpasswd.8 newusers.8 \ + pwck.8 pwconv.8 shadowconfig.8 \ + useradd.8 userdel.8 usermod.8 vipw.8 + +# XXX - for some reason "make dist" no longer distributes man_MANS +# automatically after upgrade to automake-1.2 (it worked with 1.0). +# So they are now all listed in EXTRA_DIST. --marekm +# +#EXTRA_DIST = groups.1 id.1 pw_auth.3 pwauth.8 sulogin.8 + +EXTRA_DIST = groups.1 id.1 pw_auth.3 pwauth.8 sulogin.8 \ + chage.1 chfn.1 chsh.1 gpasswd.1 \ + login.1 newgrp.1 passwd.1 su.1 \ + shadow.3 \ + faillog.5 limits.5 login.access.5 login.defs.5 \ + passwd.5 porttime.5 shadow.5 suauth.5 \ + chpasswd.8 dpasswd.8 faillog.8 \ + groupadd.8 groupdel.8 groupmod.8 \ + grpck.8 lastlog.8 logoutd.8 mkpasswd.8 newusers.8 \ + pwck.8 pwconv.8 shadowconfig.8 \ + useradd.8 userdel.8 usermod.8 vipw.8 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +man1dir = $(mandir)/man1 +man3dir = $(mandir)/man3 +man5dir = $(mandir)/man5 +man8dir = $(mandir)/man8 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile $(MANS) + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps man/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +install-man1: + $(mkinstalldirs) $(DESTDIR)$(man1dir) + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \ + done + +uninstall-man1: + @list='$(man1_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.1*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \ + rm -f $(DESTDIR)$(man1dir)/$$inst; \ + done + +install-man3: + $(mkinstalldirs) $(DESTDIR)$(man3dir) + @list='$(man3_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.3*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man3dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man3dir)/$$inst; \ + done + +uninstall-man3: + @list='$(man3_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.3*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man3dir)/$$inst"; \ + rm -f $(DESTDIR)$(man3dir)/$$inst; \ + done + +install-man5: + $(mkinstalldirs) $(DESTDIR)$(man5dir) + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \ + done + +uninstall-man5: + @list='$(man5_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.5*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \ + rm -f $(DESTDIR)$(man5dir)/$$inst; \ + done + +install-man8: + $(mkinstalldirs) $(DESTDIR)$(man8dir) + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ + done + +uninstall-man8: + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ + rm -f $(DESTDIR)$(man8dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) install-man1 install-man3 install-man5 install-man8 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) uninstall-man1 uninstall-man3 uninstall-man5 uninstall-man8 +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = man + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: install-man + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: uninstall-man + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(mandir)/man1 $(DESTDIR)$(mandir)/man3 \ + $(DESTDIR)$(mandir)/man5 $(DESTDIR)$(mandir)/man8 + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: install-man1 uninstall-man1 install-man3 uninstall-man3 \ +install-man5 uninstall-man5 install-man8 uninstall-man8 install-man \ +uninstall-man tags distdir info dvi installcheck install-exec \ +install-data install uninstall all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/man/chage.1 b/man/chage.1 new file mode 100644 index 00000000..86d0c1fa --- /dev/null +++ b/man/chage.1 @@ -0,0 +1,109 @@ +.\" Copyright 1990 - 1994 Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: chage.1,v 1.5 1999/03/07 19:14:45 marekm Exp $ +.\" +.TH CHAGE 1 +.SH NAME +chage \- change user password expiry information +.SH SYNOPSIS +.TP 6 +\fBchage\fR +[\fB-m \fImindays\fR] [\fB-M \fImaxdays\fR] +[\fB-d \fIlastday\fR] [\fB-I \fIinactive\fR] +.br +[\fB-E \fIexpiredate\fR] [\fB-W \fIwarndays\fR] \fIuser\fR +.TP 6 +\fBchage\fR +\fB-l\fR \fIuser\fR +.SH DESCRIPTION +\fBchage\fR changes the number of days between password changes and the +date of the last password change. +This information is used by the system to determine when a user must +change her password. +The \fBchage\fR command is restricted to the root user, except for the +\fB-l\fR option, which may be used by an unprivileged user to determine +when her password or account is due to expire. +.PP +With the \fB-m\fR option, the value of \fImindays\fR is the minimum number +of days between password changes. +A value of zero for this field indicates that the user may change +her password at any time. +.PP +With the \fB-M\fR option, the value of \fImaxdays\fR is the maximum number +of days during which a password is valid. +When \fImaxdays\fR plus \fIlastday\fR is less than the current day, +the user will be required to change her password before being +able to use her account. +This occurance can be planned for in advance by use of the \fB-W\fR option, +which provides the user with advance warning. +.PP +With the \fB-d\fR option, the value of \fIlastday\fR is the number of days +since January 1st, 1970 when the password was last changed. +The date may also be expressed in the format YYYY-MM-DD (or the format more +commonly used in your area). +.PP +The \fB-E\fR option is used to set a date on which the user's account will +no longer be accessible. +The \fIexpiredate\fR option is the number of days since January 1, 1970 on +which the accounted is locked. +The date may also be expressed in the format YYYY-MM-DD (or the format more +commonly used in your area). +A user whose account is locked must contact the system administrator before +being able to use the system again. +.PP +The \fB-I\fR option is used to set the number of days of inactivity after +a password has expired before the account is locked. +A user whose account is locked must contact the system administrator before +being able to use the system again. +The \fIinactive\fR option is the number of days of inactivity. A value of +0 disables this feature. +.PP +The \fB-W\fR option is used to set the number of days of warning before a +password change is required. +The \fIwarndays\fR option is the number of days prior to the password +expiring that a user will be warned her password is about to expire. +.PP +All of the above values are stored exactly as days when the shadow +password file is used, but are converted to and from weeks when the +standard password file is used. +Because of this conversion, rounding errors may result. +.PP +If none of the options are selected, \fBchage\fR operates in an interactive +fashion, prompting the user with the current values for all of the fields. +Enter the new value to change the field, or leave the line blank to use +the current value. +The current value is displayed between a pair of \fB[ ]\fR marks. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- shadow user account information +.SH SEE ALSO +.BR passwd (5), +.BR shadow (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/chfn.1 b/man/chfn.1 new file mode 100644 index 00000000..6f62023b --- /dev/null +++ b/man/chfn.1 @@ -0,0 +1,66 @@ +.\" Copyright 1990 - 1994 Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: chfn.1,v 1.4 1998/12/28 20:34:58 marekm Exp $ +.\" +.TH CHFN 1 +.SH NAME +chfn \- change user name and information +.SH SYNOPSIS +.TP 5 +\fBchfn\fR +[\fB-f \fIfull_name\fR] [\fB-r \fIroom_no\fR] +.br +[\fB-w \fIwork_ph\fR] [\fB-h \fIhome_ph\fR] [\fB-o \fIother\fR] +[\fIuser\fR] +.SH DESCRIPTION +\fBchfn\fR changes user fullname, office number, office extension, and home +phone number information for a user's account. +This information is typically printed by \fBfinger\fR(1) and similiar +programs. +A normal user may only change the fields for their own account, +the super user may change the fields for any account. +Also, only the super user may use the \fB-o\fR option to change the +undefined portions of the GCOS field. +.PP +The only restrictions placed on the contents of the fields is that no +control characters may be present, nor any of comma, colon, or equal sign. +The \fIother\fR field does not have this restriction, and is used to +store accounting information used by other applications. +.PP +If none of the options are selected, \fBchfn\fR operates in an interactive +fashion, prompting the user with the current values for all of the fields. +Enter the new value to change the field, or leave the line blank to use +the current value. +The current value is displayed between a pair of \fB[ ]\fR marks. +Without options, chfn prompts for the current user account. +.SH FILES +/etc/passwd \- user account information +.SH SEE ALSO +.BR passwd (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/chpasswd.8 b/man/chpasswd.8 new file mode 100644 index 00000000..33aabd74 --- /dev/null +++ b/man/chpasswd.8 @@ -0,0 +1,62 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: chpasswd.8,v 1.5 1998/12/28 20:34:59 marekm Exp $ +.\" +.TH CHPASSWD 8 +.SH NAME +\fBchpasswd\fR - update password file in batch +.SH SYNOPSIS +\fBchpasswd [-e]\fR +.SH DESCRIPTION +\fBchpasswd\fR reads a file of user name and password pairs +from standard input and uses this information +to update a group of existing users. Without the -e switch, the +passwords are expected to be cleartext. With the -e switch, the +passwords are expected to be in encrypted form. +Each line is of the format +.sp 1 + \fIuser_name\fR:\fIpassword\fR +.sp 1 +The named user must exist. +The supplied password will be encrypted as necessary, and the password age +updated, if present. +.PP +This command is intended to be used in a large system environment where +many accounts are created at a single time. +.SH CAVEATS +.\" The \fBmkpasswd\fR command must be executed afterwards to update the +.\" DBM password files. +The input file must be protected if it contains unencrypted passwords. +.\" This command may be discarded in favor of the newusers(8) command. +.SH SEE ALSO +.\" mkpasswd(8), passwd(1), useradd(1) +.BR passwd (1), +.BR useradd (8), +.BR newusers (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/chsh.1 b/man/chsh.1 new file mode 100644 index 00000000..6b9ac9cc --- /dev/null +++ b/man/chsh.1 @@ -0,0 +1,66 @@ +.\" Copyright 1990, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: chsh.1,v 1.4 1998/12/28 20:35:01 marekm Exp $ +.\" +.TH CHSH 1 +.SH NAME +chsh \- change login shell +.SH SYNOPSIS +.TP 5 +\fBchsh\fR +[\fB-s \fIlogin_shell\fR] [\fIuser\fR] +.SH DESCRIPTION +\fBchsh\fR changes the user login shell. +This determines the name of the user's initial login command. +A normal user may only change the login shell for their own account, +the super user may change the login shell for any account. +.PP +The only restrictions placed on the login shell is that the +command name must be listed in \fI/etc/shells\fR, unless the +invoker is the super-user, and then any value may be added. +An account with a restricted login shell may not change +their login shell. +For this reason, placing \fB/bin/rsh\fR in \fI/etc/shells\fR +is discouraged since accidentally changing to a restricted +shell would prevent the user from every changing their login +shell back to its original value. +.PP +If the \fB-s\fR option is not selected, \fBchsh\fR operates in an interactive +fashion, prompting the user with the current login shell. +Enter the new value to change the field, or leave the line blank to use +the current value. +The current value is displayed between a pair of \fB[ ]\fR marks. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shells \- list of valid login shells +.SH SEE ALSO +.BR chfn (1), +.BR passwd (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/dpasswd.8 b/man/dpasswd.8 new file mode 100644 index 00000000..00d54105 --- /dev/null +++ b/man/dpasswd.8 @@ -0,0 +1,55 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: dpasswd.8,v 1.4 1998/12/28 20:35:02 marekm Exp $ +.\" +.TH DPASSWD 8 +.SH NAME +\fBdpasswd\fR - change dialup password +.SH SYNOPSIS +\fBdpasswd\fR +.RB [ - ( a | d )] +\fIshell\fR +.SH DESCRIPTION +\fBdpasswd\fR adds, deletes, and updates dialup passwords for user +login shells. +The dialup password is prompted for after a user's password has been +authenticated whenever the user logs in over a dialup line. +\fBdpasswd\fR will prompt for the new password twice to insure it +has been entered correctly. +.PP +The \fIshell\fR argument must be the complete pathname of the login +program. +.SH FILES +.br +/etc/d_passwd +.br +/etc/dialups +.SH SEE ALSO +.BR login (1) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/faillog.5 b/man/faillog.5 new file mode 100644 index 00000000..b1f39f3a --- /dev/null +++ b/man/faillog.5 @@ -0,0 +1,59 @@ +.\" Copyright 1989 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: faillog.5,v 1.4 1998/12/28 20:35:03 marekm Exp $ +.\" +.TH FAILLOG 5 +.SH NAME +faillog \- Login failure logging file +.SH DESCRIPTION +.I faillog +maintains a count of login failures and the limits for each account. +The file is fixed length record, indexed by numerical UID. +Each record contains the count of login failures since the last +successful login; +the maximum number of failures before the account is disabled; +the line the last login failure occured on; +and the date the last login failure occured. +.PP +The structure of the file is +.DS + + struct faillog { + short fail_cnt; + short fail_max; + char fail_line[12]; + time_t fail_time; + }; + +.DE +.SH FILES +/var/log/faillog \- login failure log +.SH SEE ALSO +.BR faillog (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/faillog.8 b/man/faillog.8 new file mode 100644 index 00000000..d0a0d871 --- /dev/null +++ b/man/faillog.8 @@ -0,0 +1,100 @@ +.\" Copyright 1989 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: faillog.8,v 1.6 1999/07/09 18:02:43 marekm Exp $ +.\" +.TH FAILLOG 8 +.SH NAME +faillog \- examine faillog and set login failure limits +.SH SYNOPSIS +.TP 8 +.B faillog +.RB [ -u +.IR login-name ] +.RB [ -a ] +.RB [ -t +.IR days ] +.RB [ -m +.IR max ] +.RB [ -pr ] +.SH DESCRIPTION +\fBfaillog\fR formats the contents of the failure log, +\fI/var/log/faillog\fR, and maintains failure counts and +limits. +The order of the arguments to \fBfaillog\fR is significant. +Each argument is processed immediately in the order given. +.PP +The \fB-p\fR flag causes failure entries to be printed in UID +order. +Entering \fB-u \fIlogin-name\fR flag will +cause the failure record for \fIlogin-name\fR only to be printed. +Entering \fB-t \fIdays\fR will cause only the +failures more recent than \fIdays\fR to be printed. +The \fB-t\fR flag overrides the use of \fB-u\fR. +The \fB-a\fR flag causes all users to be selected. +When used with the \fB-p\fR flag, this option selects all users +who have ever had a login failure. +It is meaningless with the \fB-r\fR flag. +.PP +The \fB-r\fR flag is used to reset the count of login failures. +Write access to \fI/var/log/faillog\fR is required for +this option. +Entering \fB-u \fIlogin-name\fR will cause only the failure count +for \fIlogin-name\fR to be reset. +.PP +The \fB-m\fR flag is used to set the maximum number of login +failures before the account is disabled. +Write access to \fI/var/log/faillog\fR is required for this +option. +Entering \fB-m \fImax\fR will cause all accounts to be disabled +after \fImax\fR failed logins occur. +This may be modified with \fB-u \fIlogin-name\fR to limit this +function to \fIlogin-name\fR only. +Selecting a \fImax\fR value of 0 has the effect of not placing +a limit on the number of failed logins. +The maximum failure count +should always be 0 for \fBroot\fR to prevent +a denial of services attack against the system. +.PP +Options may be combined in virtually any fashion. +Each \fB-p\fR, \fB-r\fR, and \fB-m\fR option will cause +immediate execution using any \fB-u\fR or \fB-t\fR modifier. +.SH CAVEATS +\fBfaillog\fR only prints out users with no successful login since +the last failure. +To print out a user who has had a successful login since their last +failure, you must explicitly request the user with the \fB-u\fR flag, +or print out all users with the \fB-a\fR flag. +.PP +Some systems may replace /var/log with /var/adm or /usr/adm. +.SH FILES +/var/log/faillog \- failure logging file +.SH SEE ALSO +.BR login (1), +.BR faillog (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/gpasswd.1 b/man/gpasswd.1 new file mode 100644 index 00000000..2b9c3dfa --- /dev/null +++ b/man/gpasswd.1 @@ -0,0 +1,73 @@ +.\" Copyright 1996, Rafal Maszkowski, rzm@pdi.net +.\" All rights reserved. You can redistribute this man page 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. +.\" +.\" $Id: gpasswd.1,v 1.2 1996/09/10 02:45:18 marekm Exp $ +.\" +.TH GPASSWD 1 +.SH NAME +gpasswd \- administer the /etc/group file +.br +.SH SYNOPSIS +.B gpasswd \fIgroup\fR +.br +.B gpasswd +.B -a +\fIuser\fR \fIgroup\fR +.br +.B gpasswd +.B -d +\fIuser\fR \fIgroup\fR +.br +.B gpasswd +.B -R +\fIgroup\fR +.br +.B gpasswd +.B -r +\fIgroup\fR +.br +.B gpasswd +.RB [ -A +\fIuser\fR,...] +.RB [ -M +\fIuser\fR,...] +\fIgroup\fR +.br +.SH DESCRIPTION +.B gpasswd +is used to administer the /etc/group file (and /etc/gshadow +file if compiled with SHADOWGRP defined). Every group can +have administrators, members and a password. System +administrator can use \fB-A\fR option to define group +administrator(s) and \fB-M\fR option to define members and +has all rights of group administrators and members. +.PP +Group administrator can add and delete users using \fB-a\fR +and \fB-d\fR options respectively. Administrators can use +\fB-r\fR option to remove group password. When no password +is set only group members can use +.BR newgrp (1) +to join the group. Option \fB-R\fR disables +access to the group through +.BR newgrp (1) +command. +.PP +.B gpasswd +called by a group administrator with group name only prompts +for the group password. If password is set the members can still +.BR newgrp (1) +without a password, non-members must supply the password. + +.SH FILES +/etc/group \- group information +.br +/etc/gshadow \- shadow group information +.SH SEE ALSO +.BR newgrp (1), +.BR groupadd (8), +.BR groupdel (8), +.BR groupmod (8), +.BR grpck (8) diff --git a/man/groupadd.8 b/man/groupadd.8 new file mode 100644 index 00000000..5a50351d --- /dev/null +++ b/man/groupadd.8 @@ -0,0 +1,64 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: groupadd.8,v 1.4 1998/12/28 20:35:05 marekm Exp $ +.\" +.TH GROUPADD 8 +.SH NAME +groupadd \- Create a new group +.SH SYNOPSIS +.B groupadd +[\fB-g\fI gid \fR[\fB-o\fR]] +.I group +.SH DESCRIPTION +The \fBgroupadd\fR command +creates a new group account using the values specified on the +command line and the default values from the system. +The new group will be entered into the system files as needed. +The options which apply to the \fBgroupadd\fR command are +.IP "\fB-g \fIgid\fR" +The numerical value of the group's ID. +This value must be unique, unless the \fB-o\fR option is used. +The value must be non-negative. +The default is to use the smallest ID value greater than 99 and +greater than every other group. +Values between 0 and 99 are typically reserved for system accounts. +.SH FILES +/etc/group \- group account information +.br +/etc/gshadow \- secure group account information +.SH SEE ALSO +.BR chfn (1), +.BR chsh (1), +.BR useradd (8), +.BR userdel (8), +.BR usermod (8), +.BR passwd (1), +.BR groupdel (8), +.BR groupmod (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/groupdel.8 b/man/groupdel.8 new file mode 100644 index 00000000..375b889d --- /dev/null +++ b/man/groupdel.8 @@ -0,0 +1,60 @@ +.\" Copyright 1991 - 1993, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: groupdel.8,v 1.4 1998/12/28 20:35:06 marekm Exp $ +.\" +.TH GROUPDEL 8 +.SH NAME +groupdel \- Delete a group +.SH SYNOPSIS +.B groupdel +.I group +.SH DESCRIPTION +The \fBgroupdel\fR command modifies the system account files, deleting +all entries that refer to \fIgroup\fR. +The named group must exist. +.PP +You must manually check all filesystems to insure that no files remain +with the named group as the file group ID. +.SH CAVEATS +You may not remove the primary group of any existing user. +You must remove the user before you remove the group. +.SH FILES +/etc/group \- group information +.br +/etc/gshadow \- secure group information +.SH SEE ALSO +.BR chfn (1), +.BR chsh (1), +.BR useradd (8), +.BR userdel (8), +.BR usermod (8), +.BR passwd (1), +.BR groupadd (8), +.BR groupmod (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/groupmod.8 b/man/groupmod.8 new file mode 100644 index 00000000..ff3a537a --- /dev/null +++ b/man/groupmod.8 @@ -0,0 +1,66 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: groupmod.8,v 1.4 1998/12/28 20:35:07 marekm Exp $ +.\" +.TH GROUPMOD 8 +.SH NAME +groupmod \- Modify a group +.SH SYNOPSIS +.B groupmod +[\fB-g\fI gid \fR[\fB-o\fR]] +[\fB-n\fI group_name \fR] +.I group +.SH DESCRIPTION +The \fBgroupmod\fR command modifies the system account files to reflect +the changes that are specified on the command line. +The options which apply to the \fIgroupmod\fR command are +.IP "\fB-g \fIgid\fR" +The numerical value of the group's ID. +This value must be unique, unless the \fB-o\fR option is used. +The value must be non-negative. +Values between 0 and 99 are typically reserved for system groups. +Any files which the old group ID is the file group ID +must have the file group ID changed manually. +.IP "\fB-n \fIgroup_name\fR" +The name of the group will be changed from \fIgroup\fR to +\fIgroup_name\fR. +.SH FILES +/etc/group \- group information +.br +/etc/gshadow \- secure group information +.SH SEE ALSO +.BR chfn (1), +.BR chsh (1), +.BR useradd (8), +.BR userdel (8), +.BR usermod (8), +.BR passwd (1), +.BR groupadd (8), +.BR groupdel (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/groups.1 b/man/groups.1 new file mode 100644 index 00000000..075a87b5 --- /dev/null +++ b/man/groups.1 @@ -0,0 +1,57 @@ +.\" Copyright 1991 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: groups.1,v 1.4 1998/12/28 20:35:08 marekm Exp $ +.\" +.TH GROUPS 1 +.SH NAME +groups \- Display current group ID names +.SH SYNOPSIS +.B groups +.RI [ user ] +.SH DESCRIPTION +.B groups +displays the current group ID names +or values. +If the value does not have a corresponding entry in +\fI/etc/group\fR, the value will be displayed as the numerical group value. +The optional \fIuser\fR parameter will display the groups for the named +\fIuser\fR. +.SH NOTE +Systems which do not support concurrent group sets will have the information +from \fI/etc/group\fR reported. +The user must use \fBnewgrp\fR or \fBsg\fR to change their current real and +effective group ID. +.SH FILES +/etc/group \- group information +.SH SEE ALSO +.BR newgrp (1), +.BR getuid (2), +.BR getgid (2), +.BR getgroups (2) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/grpck.8 b/man/grpck.8 new file mode 100644 index 00000000..50109f37 --- /dev/null +++ b/man/grpck.8 @@ -0,0 +1,101 @@ +.\" Copyright 1992 - 1993, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: grpck.8,v 1.4 1998/12/28 20:35:09 marekm Exp $ +.\" +.TH GRPCK 1 +.SH NAME +grpck \- verify integrity of group files +.SH SYNOPSIS +\fBgrpck\fR [\fB-r\fR] [\fIgroup\fR \fIshadow\fR] +.SH DESCRIPTION +\fBgrpck\fR verifies the integrity of the system authentication information. +All entries in the \fI/etc/group\fR and \fI/etc/gshadow\fR are checked to +see that the entry has the proper format and valid data in each field. +The user is prompted to delete entries that are improperly formatted or +which have other incorrectable errors. +.P +Checks are made to verify that each entry has +.sp +.in +.5i +- the correct number of fields +.br +- a unique group name +.br +- a valid list of members and administrators +.in -.5i +.sp +.P +The checks for correct number of fields and unique group name are fatal. +If the entry has the wrong number of fields, the user will be prompted to +delete the entire line. +If the user does not answer affirmatively, all further checks are bypassed. +An entry with a duplicated group name is prompted for deletion, but the +remaining checks will still be made. +All other errors are warnings and the user is encouraged to run the +\fBgroupmod\fR command to correct the error. +.P +The commands which operate on the \fI/etc/group\fR file are not able to +alter corrupted or duplicated entries. +\fBgrpck\fR should be used in those circumstances to remove the offending +entry. +.SH OPTIONS +By default, \fBgrpck\fR operates on the files \fI/etc/group\fR and +\fI/etc/gshadow\fR. +The user may select alternate files with the \fIgroup\fR and \fIshadow\fR +parameters. +Additionally, the user may execute the command in read-only mode by +specifying the \fB-r\fR flag. +This causes all questions regarding changes to be answered \fBno\fR +without user intervention. +.SH FILES +/etc/group \- group account information +.br +/etc/gshadow \- encrypted passwords and group administrator information +.br +/etc/passwd \- user information +.SH SEE ALSO +.BR groupmod (8), +.BR group (5), +.BR passwd (5), +.BR shadow (5) +.SH DIAGNOSTICS +The \fBgrpck\fR command exits with the following values: +.IP 0 5 +Success +.IP 1 5 +Syntax Error +.IP 2 5 +One or more bad group entries +.IP 3 5 +Cannot open group files +.IP 4 5 +Cannot lock group files +.IP 5 5 +Cannot update group files +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/id.1 b/man/id.1 new file mode 100644 index 00000000..40cfdeac --- /dev/null +++ b/man/id.1 @@ -0,0 +1,54 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: id.1,v 1.4 1998/12/28 20:35:10 marekm Exp $ +.\" +.TH ID 1 +.SH NAME +id \- Display current user and group ID names +.SH SYNOPSIS +.B id +.RB [ -a ] +.SH DESCRIPTION +.B id +displays the current real and effective user and group ID names +or values. +If the value does not have a corresponding entry in \fI/etc/passwd\fR +or \fI/etc/group\fR, the value will be displayed without the corresponding +name. +The optional \fB-a\fR flag will display the group set on systems which +support multiple concurrent group membership. +.SH FILES +/etc/passwd \- user account information +.br +/etc/group \- group information +.SH SEE ALSO +.BR getuid (2), +.BR getgid (2), +.BR getgroups (2) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/lastlog.8 b/man/lastlog.8 new file mode 100644 index 00000000..2c268479 --- /dev/null +++ b/man/lastlog.8 @@ -0,0 +1,63 @@ +.\" Copyright 1992, Phillip Street and Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lastlog.8 3.3 08:24:58 29 Sep 1993 (National Guard Release) +.\" $Id: lastlog.8,v 1.5 1998/12/28 20:35:11 marekm Exp $ +.\" +.TH LASTLOG 8 +.SH NAME +lastlog \- examine lastlog file +.SH SYNOPSIS +.B lastlog +.RB [ -u +.IR uid ] +.RB [ -t +.IR days ] +.SH DESCRIPTION +\fBlastlog\fR formats and prints the contents of the last login log, +\fI/var/log/lastlog\fR. The \fBlogin-name\fR, \fBport\fR, and \fBlast login +time\fR will be printed. +The default (no flags) causes lastlog entries to be printed in UID +order. +Entering \fB-u \fIlogin-name\fR flag will +cause the lastlog record for \fIlogin-name\fR only to be printed. +Entering \fB-t \fIdays\fR will cause only the +lastlogins more recent than \fIdays\fR to be printed. +The \fB-t\fR flag overrides the use of \fB-u\fR. +.PP +If the user has never logged in the message \fB"**Never logged in**"\fR will +be displayed instead of the port and time. +.SH FILES +/var/log/lastlog \- lastlog logging file +.SH CAVEATS +Large gaps in uid numbers will cause the lastlog program to run longer with +no output to the screen (i.e. if mmdf=800 and last uid=170, program will +appear to hang as it processes uid 171-799). +.SH AUTHORS +Julianne Frances Haugh (jfh@bga.com) +.br +Phillip Street diff --git a/man/limits.5 b/man/limits.5 new file mode 100644 index 00000000..57fced5e --- /dev/null +++ b/man/limits.5 @@ -0,0 +1,74 @@ +.TH LIMITS 5 +.SH NAME +limits \- Resource limits definition +.SH DESCRIPTION +The +.I limits +file (/etc/limits by default or LIMITS_FILE defined config.h) +describes the resource limits you wish to impose. +It should be owned by root and readable by root account only. +.PP +By default no quotas are imposed on 'root'. In fact, there is no way to impose +limits via this procedure to root-equiv accounts (accounts with UID 0). +.PP +Each line describes a limit for a user in the form: +.sp +.I user LIMITS_STRING +.PP +The \fBLIMITS_STRING\fP is a string of a concatenated list of resource limits. +Each limit consists of a letter identifier followed by a numerical limit. +.PP +The valid identifiers are: +.sp +A: max address space (KB) +.br +C: max core file size (KB) +.br +D: max data size (KB) +.br +F: maximum filesize (KB) +.br +M: max locked-in-memory address space (KB) +.br +N: max number of open files +.br +R: max resident set size (KB) +.br +S: max stack size (KB) +.br +T: max CPU time (MIN) +.br +U: max number of processes +.br +L: max number of logins for this user +.br +P: process priority, set by \fBsetpriority\fR(2). +.PP +For example, \fIL2D2048N5\fP is a valid \fBLIMITS_STRING\fP. For reading convenience, +the following entries are equivalent: +.sp +username L2D2048N5 +.br +username L2 D2048 N5 +.PP +Be aware that after \fIusername\fP the rest of the line is considered a limit +string, thus comments are not allowed. A invalid limits string will be +rejected (not considered) by the login program. +.PP +The default entry is denoted by username "\fB*\fP". If you have multiple \fIdefault\fP +entries in your \fBLIMITS_FILE\fP, then the last one will be used as the default +entry. +.PP +To completely disable limits for a user, a single dash "\fB-\fP" will do. +.PP +Also, please note that all limit settings are set PER LOGIN. They are +not global, nor are they permanent. Perhaps global limits will come, but +for now this will have to do ;) +.SH FILES +/etc/limits +.SH SEE ALSO +.BR login (1), +.BR setpriority (2), +.BR setrlimit (2) +.SH AUTHOR +Cristian Gafton (gafton@sorosis.ro) diff --git a/man/login.1 b/man/login.1 new file mode 100644 index 00000000..8735ad80 --- /dev/null +++ b/man/login.1 @@ -0,0 +1,134 @@ +.\" Copyright 1989 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: login.1,v 1.6 1999/06/07 16:40:44 marekm Exp $ +.\" +.TH LOGIN 1 +.SH NAME +login \- Begin session on the system +.SH SYNOPSIS +.B login +.RI [ username " [" environmental-variables ]] +.\" XXX - document -f -h -p -r options +.SH DESCRIPTION +.B login +is used to establish a new session with the system. +It is normally invoked automatically by responding to the +.I login: +prompt on the user\'s terminal. +.B login +may be special to the shell and may not be invoked as a sub-process. +Typically, +.B login +is treated by the shell as \fBexec login\fR which causes the user +to exit from the current shell. +Attempting to execute \fBlogin\fR from any shell but the login shell +will produce an error message. +.PP +When invoked from the \fIlogin:\fR prompt, the user may enter +environmental variables after the username. +These variables are entered in the form \fBNAME=VALUE\fR. +Not all variables may be set in the fashion, notably \fBPATH\fR, +\fBHOME\fR and \fBSHELL\fR. +Additionally, \fBIFS\fR may be inhibited if the user\'s login +shell is \fB/bin/sh\fR. +.PP +The user is then prompted for a password, where appropriate. +Echoing is disabled to prevent revealing the password. +Only a small number of password failures are permitted before +\fBlogin\fR exits and the communications link is severed. +.PP +If password aging has been enabled for your account, you may be +prompted for a new password before proceeding. +You will be forced to provide your old password and the new +password before continuing. +Please refer to \fBpasswd \fR(1) for more information. +.PP +After a successful login, +you will be informed of any system messages and the presence +of mail. +You may turn off the printing of the system message file, +\fI/etc/motd\fR, by creating a zero-length file \fI.hushlogin\fR +in your login directory. +The mail message will be one of "\fBYou have new mail.\fR", +"\fBYou have mail.\fR", or "\fBNo Mail.\fR" according to +the condition of your mailbox. +.PP +Your user and group ID will be set according to their values in +the \fI/etc/passwd\fR file. +The value for \fB$HOME\fR, \fB$SHELL\fR, \fB$PATH\fR, \fB$LOGNAME\fR, +and \fB$MAIL\fR are set according to the appropriate fields in the +password entry. +Ulimit, umask and nice values may also be set according to +entries in the GECOS field. +.PP +On some installations, the environmental variable \fB$TERM\fR will be +initialize to the terminal type on your tty line, as specified in +\fI/etc/ttytype\fR. +.PP +An initialization script for your command interpreter may also be +executed. +Please see the appropriate manual section for more information on +this function. +.SH CAVEATS +.PP +This version of \fBlogin\fR has many compilation options, only some of which +may be in use at any particular site. +.PP +The location of files is subject to differences in system configuration. +.SH FILES +/etc/utmp \- list of current login sessions +.br +/etc/wtmp \- list of previous login sessions +.br +/etc/passwd \- user account information +.br +/etc/shadow \- encrypted passwords and age information +.br +/etc/motd \- system message file +.br +/etc/nologin \- prevent non-root users from logging in +.br +/etc/ttytype \- list of terminal types +.br +$HOME/.profile \- initialization script for default shell +.br +$HOME/.hushlogin \- suppress printing of system messages +.br +.SH SEE ALSO +.PP +.BR getty (8), +.BR mail (1), +.BR passwd (1), +.BR sh (1), +.BR su (1), +.BR login.defs (5), +.\" .BR d_passwd (5), +.BR passwd (5), +.BR nologin (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/login.access.5 b/man/login.access.5 new file mode 100644 index 00000000..01f06beb --- /dev/null +++ b/man/login.access.5 @@ -0,0 +1,52 @@ +.\" this is comment +.TH LOGIN.ACCESS 5 +.\" .Dt SKEY.ACCESS 5 +.\" .Os FreeBSD 1.2 +.SH NAME +login.access \- Login access control table +.SH DESCRIPTION +The +.I login.access +file specifies (user, host) combinations and/or (user, tty) +combinations for which a login will be either accepted or refused. +.PP +When someone logs in, the +.I login.access +is scanned for the first entry that +matches the (user, host) combination, or, in case of non-networked +logins, the first entry that matches the (user, tty) combination. The +permissions field of that table entry determines whether the login will +be accepted or refused. +.PP +Each line of the login access control table has three fields separated by a +":" character: +.sp 1 +.IR permission : users : origins +.sp 1 +The first field should be a "\fB+\fR" (access granted) or "\fB-\fR" +(access denied) character. The second field should be a list of one or +more login names, group names, or +.B ALL +(always matches). The third field should be a list +of one or more tty names (for non-networked logins), host names, domain +names (begin with "\fB.\fR"), host addresses, internet network numbers +(end with "\fB.\fR"), +.B ALL +(always matches) or +.B LOCAL +(matches any string that does not contain a "\fB.\fR" character). +If you run NIS you can use @netgroupname in host or user patterns. +.PP +The +.B EXCEPT +operator makes it possible to write very compact rules. +.PP +The group file is searched only when a name does not match that of the +logged-in user. Only groups are matched in which users are explicitly +listed: the program does not look at a user's primary group id value. +.SH FILES +/etc/login.access +.SH SEE ALSO +.BR login (1) +.SH AUTHOR +Guido van Rooij diff --git a/man/login.defs.5 b/man/login.defs.5 new file mode 100644 index 00000000..69414238 --- /dev/null +++ b/man/login.defs.5 @@ -0,0 +1,563 @@ +.\" Copyright 1991 - 1993, Julianne Frances Haugh and Chip Rosenthal +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: login.defs.5,v 1.6 1998/12/28 20:35:13 marekm Exp $ +.\" +.TH LOGIN 5 +.SH NAME +/etc/login.defs \- Login configuration +.SH DESCRIPTION +The +.I /etc/login.defs +file defines the site-specific configuration for the shadow login +suite. This file is required. Absence of this file will not prevent +system operation, but will probably result in undesirable operation. +.PP +This file is a readable text file, each line of the file describing +one configuration parameter. The lines consist of a configuration +name and value, seperated by whitespace. Blank lines and comment +lines are ignored. Comments are introduced with a `#' pound sign and +the pound sign must be the first non-white character of the line. +.PP +Parameter values may be of four types: strings, booleans, numbers, +and long numbers. A string is comprised of any printable characters. +A boolean should be either the value ``yes'' or ``no''. An undefined +boolean parameter or one with a value other than these will be given +a ``no'' value. Numbers (both regular and long) may be either decimal +values, octal values (precede the value with ``0'') or hexadecimal +values (precede the value with ``0x''). The maximum value of the +regular and long numeric parameters is machine-dependant. +.PP +The following configuration items are provided: +.\" +.IP "CHFN_AUTH (boolean)" +If +.IR yes , +the +.B chfn +and +.B chsh +programs will ask for password before making any changes, unless +run by the superuser. +.\" +.IP "CHFN_RESTRICT (string)" +This parameter specifies which values in the +.I gecos +field of the +.I passwd +file may be changed by regular users using the +.B chfn +program. It can be any combination of letters +.IR f , +.IR r , +.IR w , +.IR h , +for Full name, Room number, Work phone, and Home phone, respectively. +If not specified, only the superuser can make any changes. +.\" +.IP "CONSOLE (string)" +If specified, this definition provides for a restricted set of lines +on which root logins will be allowed. An attempted root login which +does not meet the criteria established here will be rejected. The +value of this field may be one of two forms, either a fully-rooted +pathname such as +.sp +.ft I + CONSOLE /etc/consoles +.ft R +.sp +or a colon-delimited list of terminal lines such as: +.sp +.ft I + CONSOLE console:tty01:tty02:tty03:tty04 +.ft R +.sp +If a pathname is given, each line of the file should specify one +terminal line. If this parameter is not defined or the specified file +does not exist, then root logins will be allowed from any terminal +line. Because the removal of this file, or its truncation, could +result in unauthorized root logins, this file must be protected. +Where security is critical, the colon-separated form should be used +to prevent this potential method of attack. +.\" +.IP "CONSOLE_GROUPS (string)" +XXX needs to be documented. +.\" +.IP "CRACKLIB_DICTPATH (string)" +XXX needs to be documented. +.\" +.IP "DEFAULT_HOME (boolean)" +XXX needs to be documented. +.\" +.IP "DIALUPS_CHECK_ENAB (boolean)" +If +.I yes +and an +.I /etc/dialups +file exists, then secondary passwords are enabled upon the dialup +lines specified in this file. This file should contain a list of +dialups, one per line, for example: +.nf +.sp +.ft I + ttyfm01 + ttyfm02 + \0\0. + \0\0. + \0\0. +.ft R +.sp +.fi +.\" +.IP "ENVIRON_FILE (string)" +XXX needs to be documented. +.\" +.IP "ENV_HZ (string)" +This parameter specifies a value for an HZ environment parameter. +Example usage is: +.sp + \fIENV_HZ HZ=50\fR +.sp +If this parameter is not defined then no HZ value will be established. +.\" +.IP "ENV_PATH (string)" +This parameter must be defined as the search path for regular users. +When a login with UID other than zero occurs, the PATH environment +parameter is initialized to this value. This parameter is required; +if undefined a possibly incorrect default value will be provided. +.\" +.IP "ENV_SUPATH (string)" +This parameter must be defined as the search path for the superuser. +When a login with UID zero occurs, the PATH environment parameter is +initialized to this value. This parameter is required; if undefined +a possibly incorrect default value will be provided. +.\" +.IP "ENV_TZ (string)" +This parameter specifies information for generating a TZ environment +parameter. The value must either be the desired contents of TZ, or +the full pathname of a file which contains this information. Example +usage is: +.sp + \fIENV_TZ\0\0\0\0TZ=CST6CDT\fP +.sp +or +.sp + \fIENV_TZ\0\0\0\0/etc/tzname\fP +.sp +If a nonexistent file is named, then TZ will be initialized to some +default value. If this parameter is not defined then no TZ value will +be established. +.\" +.IP "ERASECHAR (number)" +The terminal +.I erase +character is initialized to this value. This is supported only on +systems with the +.I termio +interface, e.g. System V. If not specified, the erase character will +be initialized to a backspace. See KILLCHAR for related information. +.\" +.IP "FAILLOG_ENAB (boolean)" +If +.I yes +then login failures will be accumulated in +.I /var/log/faillog +in a +.BR faillog (8) +format. +.\" +.IP "FAIL_DELAY (number)" +Delay time in seconds after each failed login attempt. +.\" +.IP "FAKE_SHELL (string)" +Instead of the real user shell, the program specified by this +parameter will be launched, although its visible name (argv[0]) will +be the shell's. The program may do whatever it wants (logging, +additional authentification, banner, ...) before running the actual +shell. +.\" +.IP "FTMP_FILE (string)" +This parameter specifies the full pathname to a file to which login +failures are recorded. When a login failure occurs, a +.I utmp +format record will be appended to this file. Note that this differs +from the +.I /var/log/faillog +failure logging in that this facility logs every failure whereas the +``faillog'' facility accumulates failure information per user. If +this parameter is not specified then logging will be inhibited. See +FAILLOG_ENAB and LOG_UNKFAIL_ENAB for related information. +.\" +.IP "GID_MAX (number)" +.IP "GID_MIN (number)" +Range of group IDs to choose from for the +.B groupadd +program. +.\" +.IP "HUSHLOGIN_FILE (string)" +This parameter is used to establish ``hushlogin'' conditions. There +are two possible ways to establish these conditions. First, if the +value of this parameter is a filename and that file exists in the +user's home directory then ``hushlogin'' conditions will be in effect. +The contents of this file are ignored; its mere presence triggers +``hushlogin'' conditions. Second, if the value of this parameter is +a full pathname and either the user's login name or the user's shell +is found in this file, then ``hushlogin'' conditions will be in effect. +In this case, the file should be in a format similar to: +.nf +.sp +.ft I + demo + /usr/lib/uucp/uucico + \0\0. + \0\0. + \0\0. +.ft R +.sp +.fi +If this parameter is not defined, then ``hushlogin'' conditions will +never occur. When ``hushlogin'' conditions are established, the +message of the day, last successful and unsuccessful login display, +mail status display, and password aging checks are suppressed. Note +that allowing hushlogin files in user home directories allows the user +to disable password aging checks. See MOTD_FILE, FAILLOG_ENAB, +LASTLOG_ENAB, and MAIL_CHECK_ENAB for related information. +.\" +.IP "ISSUE_FILE (string)" +Full pathname of the file to display before each login prompt. +.\" +.IP "KILLCHAR (number)" +The terminal +.I kill +character is initialized to this value. This is supported only on +systems with the +.I termio +interface, e.g. System V. If not specified, the kill character will +be initialized to a \s-2CTRL/U\s0. +See ERASECHAR for related information. +.\" +.IP "LASTLOG_ENAB (boolean)" +If +.IR yes , +and if the +.I /var/log/lastlog +file exists, then a successful user login will be recorded to this +file. Furthermore, if this option is enabled then the times of the +most recent successful and unsuccessful logins will be displayed to +the user upon login. The unsuccessful login display will be suppressed +if FAILLOG_ENAB is not enabled. If ``hushlogin'' conditions are in +effect, then both the successful and unsuccessful login information +will be suppressed. +.\" +.IP "LOGIN_RETRIES (number)" +Number of login attempts allowed before the +.B login +program exits. +.\" +.IP "LOGIN_STRING (string)" +XXX needs to be documented. +.IP "LOGIN_TIMEOUT (number)" +XXX needs to be documented. +.IP "LOG_OK_LOGINS (boolean)" +XXX needs to be documented. +.IP "LOG_UNKFAIL_ENAB (boolean)" +If +.I yes +then unknown usernames will be included when a login failure is +recorded. Note that this is a potential security risk; a common login +failure mode is transposition of the user name and password, thus this +mode will often cause passwords to accumulate in the failure logs. +If this option is disabled then unknown usernames will be suppressed +in login failure messages. +.\" +.IP "MAIL_CHECK_ENAB (boolean)" +If +.IR yes , +the user will be notified of his or her mailbox status upon login. +See MAIL_DIR for related information. +.\" +.IP "MAIL_DIR (string)" +This parameter specifies the full pathname to the directory which +contains the user mailbox files. The user's login name is appended +to this path to form the MAIL environment parameter \- the path to +the user's mailbox. Either this parameter or MAIL_FILE must be defined; +if undefined some possibly incorrect default value will be assumed. +See MAIL_CHECK_ENAB for related information. +.\" +.IP "MAIL_FILE (string)" +This parameter specifies the name of the user's mailbox file. This +name is appended to the name of the user's home directory to form the +MAIL environment parameter \- the path to the user's mailbox. Either +this parameter or MAIL_DIR must be defined; if undefined some possibly +incorrect default value will be assumed. See MAIL_CHECK_ENAB for +related information. +.\" +.IP "MD5_CRYPT_ENAB (boolean)" +If +.IR yes , +the +.B passwd +program will encrypt newly changed passwords using a new MD5-based +.BR crypt (3) +password hashing algorithm, which originally appeared in FreeBSD, and +is also supported by libc-5.4.38 and glibc-2.0 (or higher) on Linux. +This algorithm allows passwords longer than 8 characters (limited by +.BR getpass (3) +to 127 characters), but is incompatible with traditional +.BR crypt (3) +implementations. +.\" +.IP "MOTD_FILE (string)" +This parameter specifies a colon-delimited list of pathnames to ``message +of the day'' files. +If a specified file exists, then its contents are displayed to the user +upon login. +If this parameter is not defined or ``hushlogin'' login conditions are +in effect, this information will be suppressed. +.\" +.IP "NOLOGINS_FILE (string)" +This parameter specifies the full pathname to a file which inhibits +non-root logins. If this file exists and a user other than root +attempts to log in, the contents of the file will be displayed and +the user will be disconnected. If this parameter is not specified +then this feature will be inhibited. +.\" +.IP "NOLOGIN_STR (string)" +XXX needs to be documented. +.\" +.IP "OBSCURE_CHECKS_ENAB (boolean)" +If +.IR yes , +the +.B passwd +program will perform additional checks before accepting a password change. +The checks performed are fairly simple, and their use is recommended. +These obscurity checks are bypassed if +.B passwd +is run by +.IR root . +See PASS_MIN_LEN for related information. +.\" +.IP "PASS_ALWAYS_WARN (boolean)" +XXX needs to be documented. +.\" +.IP "PASS_CHANGE_TRIES (number)" +XXX needs to be documented. +.\" +.IP "PASS_MIN_DAYS (number)" +The minimum number of days allowed between password changes. Any password +changes attempted sooner than this will be rejected. If not specified, a +zero value will be assumed. +.\" +.IP "PASS_MIN_LEN (number)" +The minimum number of characters in an acceptable password. An attempt to +assign a password with fewer characters will be rejected. A zero value +suppresses this check. If not specified, a zero value will be assumed. +.\" +.IP "PASS_MAX_DAYS (number)" +The maximum number of days a password may be used. If the password is +older than this, then the account will be locked. If not specified, +a large value will be assumed. +.\" +.IP "PASS_MAX_LEN (number)" +XXX needs to be documented. +.\" +.IP "PASS_WARN_AGE (number)" +The number of days warning given before a password expires. A zero means +warning is given only upon the day of expiration, a negative value means +no warning is given. If not specified, no warning will be provided. +.\" +.IP "PORTTIME_CHECKS_ENAB (boolean)" +If +.I yes +and an +.I /etc/porttime +file exists, that file will be consulted to ensure the user may login +at this time on the given line. +c.f. +.BR porttime (5) +.\" +.IP "QMAIL_DIR (string)" +For Qmail users, this parameter specifies a directory where a Maildir +hierarchy is stored. +See MAIL_CHECK_ENAB for related information. +.\" +.IP "QUOTAS_ENAB (boolean)" +If +.I yes , +then the user's ``ulimit,'' ``umask,'' and ``niceness'' will be +initialized to the values if specified in the +.I gecos +field of the +.I passwd +file. +c.f. +.BR passwd (5). +.\" +.IP "SU_NAME (string)" +This parameter assigns a command name when ``su -'' is run. For +example, if the parameter is defined as ``su'', then a +.BR ps (1) +listing would show the command running as ``-su''. If this parameter +is undefined, then a +.BR ps (1) +listing would show the name of the actual shell being run, e.g. +something like ``-sh''. +.\" +.IP "SULOG_FILE (string)" +This parameter specifies a full pathname of a file in which +.B su +activity is logged. +If this parameter is not specified, the logging is suppressed. +Because the +.B su +command may be used when attempting to authenticate a password, +either this option, or +.I syslog +should be used to note +.B su +activity. See the SYSLOG_SU_ENAB option for related information. +.\" +.IP "SU_WHEEL_ONLY (boolean)" +XXX needs to be documented. +.\" +.IP "SYSLOG_SG_ENAB (boolean)" +XXX needs to be documented. +.\" +.IP "SYSLOG_SU_ENAB (boolean)" +If +.I yes +and +.B login +was compiled with +.I syslog +support, then all +.B su +activity will be noted through the +.I syslog +facility. +See SULOG_FILE for related information. +.\" +.IP "TTYGROUP (string or number)" +The group ownership of the terminal is initialized to this group +name or number. One well-known security attack involves forcing terminal +control sequences upon another user's terminal line. This problem +can be averted by disabling permissions which allow other users to +access the terminal line, but this unfortunately prevents programs +such as +.B write +from operating. Another solution is to use a version of the +.B write +program which filters out potentially dangerous character sequences, +make this program ``setgid'' to a special group, assign group ownership +of the terminal line to this special group, and assign permissions of +\fI0620\fR to the terminal line. The TTYGROUP definition has been +provided for just this situation. If this item is not defined, then +the group ownership of the terminal is initialized to the user's group +number. See TTYPERMS for related information. +.\" +.IP "TTYPERM (number)" +The login terminal permissions are initialized to this value. Typical +values will be \fI0622\fR to permit others write access to the line +or \fI0600\fR to secure the line from other users. If not specified, +the terminal permissions will be initialized to \fI0622\fR. See +TTYGROUP for related information. +.\" +.IP "TTYTYPE_FILE (string)" +This parameter specifies the full pathname to a file which maps terminal +lines to terminal types. Each line of the file contains a terminal +type and a terminal line, seperated by whitespace, for example: +.nf +.sp +.ft I + vt100\0 tty01 + wyse60 tty02 + \0\0.\0\0\0 \0\0. + \0\0.\0\0\0 \0\0. + \0\0.\0\0\0 \0\0. +.ft R +.sp +.fi +This information is used to initialize the TERM environment parameter. +A line starting with a ``#'' pound sign will be treated as a comment. +If this paramter is not specified, the file does not exist, or the terminal +line is not found in the file, then the TERM environment parameter will not +be set. +.\" +.IP "UID_MAX (number)" +XXX needs to be documented. +.IP "UID_MIN (number)" +XXX needs to be documented. +.\" +.IP "ULIMIT (long number)" +The file size limit is initialized to this value. This is supported +only on systems with a +.IR ulimit , +e.g. System V. If not specified, the file size limit will be initialized +to some large value. +.\" +.IP "UMASK (number)" +The permission mask is initialized to this value. If not specified, +the permission mask will be initialized to zero. +.\" +.IP "USERDEL_CMD (string)" +XXX needs to be documented. +.\" +.SH CROSS REFERENCE +The following cross reference shows which programs in the shadow login +suite use which parameters. +.na +.IP login 12 +CONSOLE DIALUPS_CHECK_ENAB ENV_HZ ENV_SUPATH ENV_TZ ERASECHAR FAILLOG_ENAB +FTMP_FILE HUSHLOGIN_FILE KILLCHAR LASTLOG_ENAB LOG_UNKFAIL_ENAB +MAIL_CHECK_ENAB MAIL_DIR MOTD_FILE NOLOGINS_FILE PORTTIME_CHECKS_ENAB +QUOTAS_ENAB TTYPERM TTYTYPE_FILE ULIMIT UMASK +.IP newusers 12 +PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE UMASK +.IP passwd 12 +OBSCURE_CHECKS_ENAB PASS_MIN_LEN +.IP pwconv 12 +PASS_MAX_DAYS PASS_MIN_DAYS PASS_WARN_AGE +.IP su 12 +ENV_HZ ENV_SUPATH ENV_TZ HUSHLOGIN_FILE MAIL_CHECK_ENAB MAIL_DIR +MOTD_FILE NOLOGIN_STR QUOTAS_ENAB SULOG_FILE SYSLOG_SU_ENAB +.IP sulogin 12 +ENV_HZ ENV_SUPATH ENV_TZ MAIL_DIR QUOTAS_ENAB TTYPERM +.ad +.SH BUGS +Some of the supported configuration parameters are not documented in this +manual page. +.SH SEE ALSO +.BR login (1), +.BR passwd (5), +.BR faillog (5), +.BR porttime (5), +.BR faillog (8) +.SH AUTHORS +Julianne Frances Haugh (jfh@bga.com) +.br +Chip Rosenthal (chip@unicom.com) diff --git a/man/logoutd.8 b/man/logoutd.8 new file mode 100644 index 00000000..9acf4c31 --- /dev/null +++ b/man/logoutd.8 @@ -0,0 +1,51 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: logoutd.8,v 1.4 1998/12/28 20:35:14 marekm Exp $ +.\" +.TH LOGOUTD 8 +.SH NAME +logoutd \- Enforce login time restrictions +.SH SYNOPSIS +.B logoutd +.SH DESCRIPTION +.B logoutd +enforces the login time and port restrictions specified in +.IR /etc/porttime . +.B logoutd +should be started from \fI/etc/rc\fR. +The \fI/etc/utmp\fR file is scanned periodically and each user name +is checked to see if the named user is permitted on the named port +at the current time. +Any login session which is violating the restrictions in \fI/etc/porttime\fR +is terminated. +.SH FILES +/etc/porttime \- login and port permissions +.br +/etc/utmp \- current login sessions +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/mkpasswd.8 b/man/mkpasswd.8 new file mode 100644 index 00000000..13be2c43 --- /dev/null +++ b/man/mkpasswd.8 @@ -0,0 +1,81 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: mkpasswd.8,v 1.4 1998/12/28 20:35:15 marekm Exp $ +.\" +.TH MKPASSWD 1 +.SH NAME +mkpasswd \- Update passwd and group database files +.SH SYNOPSIS +\fBmkpasswd\fR [\fB-fvgps\fR] \fIfile\fR +.SH DESCRIPTION +.B mkpasswd +reads the file in the format given by the flags and converts it to the +corresponding database file format. +These database files are used to improve access performance on systems +with large numbers of users. +The output files will be named \fIfile\fR.dir and \fIfile\fR.pag. +.PP +The \fB-f\fR option causes \fBmkpasswd\fR to ignore any existing output +files and overwrite them. +Normally \fBmkpasswd\fR complains about existing output files and quits. +.PP +The \fB-v\fR option causes \fBmkpasswd\fR to output information about +each record as it is converted, with a final message at the very end. +.PP +The \fB-g\fR option treats the input file as though it were in +\fI/etc/group\fR file format. +When combined with the \fB-s\fR option, the \fI/etc/gshadow\fR file +format is used instead. +.PP +The \fB-p\fR option treats the input file as though it were in +\fI/etc/passwd\fR file format. +This is the default. +When combined with the \fB-s\fR option, the \fI/etc/shadow\fR file +format is used instead. +.SH CAVEATS +The use of more than one database file is limited to systems which +include the NDBM database library and therefore may not be available +on every system. +.SH NOTE +Since most commands are capable of updating the database files as +changes are made, this command need only be used when re-creating a +deleted or corrupted database file. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- shadow user information +.br +/etc/group \- group information +.br +/etc/gshadow \- shadow group information +.SH SEE ALSO +.BR passwd (5), +.BR group (5), +.BR shadow (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/newgrp.1 b/man/newgrp.1 new file mode 100644 index 00000000..db71e3ac --- /dev/null +++ b/man/newgrp.1 @@ -0,0 +1,80 @@ +.\" Copyright 1991, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: newgrp.1,v 1.4 1998/12/28 20:35:16 marekm Exp $ +.\" +.TH NEWGRP 1 +.SH NAME +newgrp \- Change group ID +.br +sg \- Execute command as different group ID +.SH SYNOPSIS +.BR newgrp " [" - ] +[\fIgroup\fR] +.br +.BR sg " [" - ] +[\fIgroup\fR [\fB-c\fR \fIcommand\fR]] +.SH DESCRIPTION +.B newgrp +is used to change the current group ID during a login session. +If the optional \fB\-\fR flag is given, the user's environment +will be reinitialized as though the user had logged in, otherwise +the current environment, including current working directory, +remains unchanged. +.PP +.B newgrp +changes the current real group ID to the named group, or to +the default group listed in \fI/etc/passwd\fR if no group name +is given. +The user will be prompted for a password if they do not have a +password and the group does, or if the user is not listed as a +member and the group has a password. +The user will be denied access if the group password is empty +and the user is not listed as a member. +.PP +The +.B sg +command works similiar to \fBnewgrp\fR but does not replace the +user's shell, so upon exit from a \fBsg\fR command, you are +returned to your previous group ID. +.B sg +also accepts a command. +The command will be executed with the Bourne shell and must be +enclosed in quotes. +.SH CAVEATS +This version of \fBnewgrp\fR has many compilation options, +only some of which may be in use at any particular site. +.SH FILES +/etc/passwd \- user account information +.br +/etc/group \- group information +.SH SEE ALSO +.BR login (1), +.BR id (1), +.BR su (1) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/newusers.8 b/man/newusers.8 new file mode 100644 index 00000000..02c4c584 --- /dev/null +++ b/man/newusers.8 @@ -0,0 +1,68 @@ +.\" Copyright 1991 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: newusers.8,v 1.4 1998/12/28 20:35:17 marekm Exp $ +.\" +.TH NEWUSERS 8 +.SH NAME +\fBnewusers\fR - update and create new users in batch +.SH SYNOPSIS +\fBnewusers\fR [\fI new_users \fR] +.SH DESCRIPTION +\fBnewusers\fR reads a file of user name and cleartext password pairs +and uses this information to update a group of existing users or to +create new users. +Each line is in the same format as the standard password file (see +\fBpasswd\fR(5)) with the following exceptions. +.IP "\fIpw_passwd\fR" 10 +This field will be encrypted and used as the new value +of the encrpted password. +.IP "\fIpw_age\fR" +This field will be ignored for shadow passwords if the user already +exists. +.IP "\fIpw_gid\fR" +This field may be the name of an existing group, in which case the +named user will be added as a member. If a non-existent numerical +group is given, a new group will be created having this number. +.IP "\fIpw_dir\fR" +This field will be checked for existence as a directory and a new +directory with the same name will be created if it does not already exist. +The ownership of the directory will be set to be that of the user +being created or updated. +.PP +This command is intended to be used in a large system environment where +many accounts are updated at a single time. +.SH CAVEATS +.\" The \fImkpasswd\fR command must be executed afterwards to update the +.\" DBM password files. +The input file must be protected since it contains unencrypted passwords. +.SH SEE ALSO +.\" mkpasswd(8), passwd(1), useradd(1) +.BR passwd (1), +.BR useradd (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/passwd.1 b/man/passwd.1 new file mode 100644 index 00000000..20c6b1ff --- /dev/null +++ b/man/passwd.1 @@ -0,0 +1,190 @@ +.\" Copyright 1989 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: passwd.1,v 1.4 1998/12/28 20:35:18 marekm Exp $ +.\" +.TH PASSWD 1 +.SH NAME +passwd \- change user password +.SH SYNOPSIS +\fBpasswd\fR [\fB-f\fR|\fB-s\fR] [\fIname\fR] +.br +\fBpasswd\fR [\fB-g\fR] [\fB-r\fR|\fBR\fR] \fIgroup\fR +.br +\fBpasswd\fR [\fB-x\fR \fImax\fR] [\fB-n\fR \fImin\fR] +[\fB-w\fR \fIwarn\fR] [\fB-i\fR \fIinact\fR] \fIname\fR +.br +\fBpasswd\fR {\fB-l\fR|\fB-u\fR|\fB-d\fR|\fB-S\fR} \fIname\fR +.SH DESCRIPTION +\fBpasswd\fR changes passwords for user and group accounts. +A normal user may only change the password for their own account, +the super user may change the password for any account. +The administrator of a group may change the password for the group. +\fBpasswd\fR also changes account information, such as the full name +of the user, their login shell, or password expiry dates and intervals. +.SS Password Changes +The user is first prompted for their old password, +if one is present. +This password is then encrypted and compared against the +stored password. +The user has only one chance to enter the correct password. +The super user is permitted to bypass this step so that forgotten +passwords may be changed. +.PP +After the password has been entered, password aging information +is checked to see if the user is permitted to change their password +at this time. +If not, \fBpasswd\fR refuses to change the password and exits. +.PP +The user is then prompted for a replacement password. +This password is tested for complexity. +As a general guideline, +passwords should consist of 6 to 8 characters including +one or more from each of following sets: +.IP "" .5i +Lower case alphabetics +.IP "" .5i +Upper case alphabetics +.IP "" .5i +Digits 0 thru 9 +.IP "" .5i +Punctuation marks +.PP +Care must be taken not to include the system default erase +or kill characters. +\fBpasswd\fR will reject any password which is not suitably +complex. +.PP +If the password is accepted, +\fBpasswd\fR will prompt again and compare the second entry +against the first. +Both entries are require to match in order for the password +to be changed. +.SS Group passwords +When the \fB-g\fR option is used, the password for the named +group is changed. +The user must either be the super user, or a group administrator +for the named group. +The current group password is not prompted for. +The \fB-r\fR option is used with the \fB-g\fR option to remove +the current password from the named group. +This allows group access to all members. +The \fB-R\fR option is used with the \fB-g\fR option to restrict +the named group for all users. +.SS Password expiry information +The password aging information may be changed by the super +user with the \fB-x\fR, \fB-n\fR, \fB-w\fR, and \fB-i\fR options. +The \fB-x\fR option is used to set the maximum number of days +a password remains valid. +After \fImax\fR days, the password is required to be changed. +The \fB-n\fR option is used to set the minimum number of days +before a password may be changed. +The user will not be permitted to change the password until +\fImin\fR days have elapsed. +The \fB-w\fR option is used to set the number of days of warning +the user will receive before their password will expire. +The warning occurs \fIwarn\fR days before the expiration, telling +the user how many days until the password is set to expire. +The \fB-i\fR option is used to disable an account after the +password has been expired for a number of days. +After a user account has had an expired password for \fIinact\fR +days, the user may no longer sign on to the account. +.SS Account maintenance +User accounts may be locked and unlocked with the \fB-l\fR and +\fB-u\fR flags. +The \fB-l\fR option disables an account by changing the password to a +value which matches no possible encrypted value. +The \fB-u\fR option re-enables an account by changing the password +back to its previous value. +.PP +The account status may be given with the \fB-S\fR option. +The status information consists of 6 parts. +The first part indicates if the user account is locked (L), has no +password (NP), or has a usable password (P). +The second part gives the date of the last password change. +The next four parts are the minimum age, maximum age, warning period, +and inactivity period for the password. +.SS Hints for user passwords +The security of a password depends upon the strength of the +encryption algorithm and the size of the key space. +The \fB\s-2UNIX\s+2\fR System encryption method is based on +the NBS DES algorithm and is very secure. +The size of the key space depends upon the randomness of the +password which is selected. +.PP +Compromises in password security normally result from careless +password selection or handling. +For this reason, you should select a password which does not +appear in a dictionary or which must be written down. +The password should also not be a proper name, your license +number, birth date, or street address. +Any of these may be used as guesses to violate system security. +.PP +Your password must easily remembered so that you will not +be forced to write it on a piece of paper. +This can be accomplished by appending two small words together +and separating each with a special character or digit. +For example, Pass%word. +.PP +Other methods of construction involve selecting an easily +remembered phrase from literature and selecting the first +or last letter from each. +An example of this is +.IP "" .5i +Ask not for whom the bell tolls. +.PP +which produces +.IP "" .5i +An4wtbt. +.PP +You may be reasonably sure few crackers will have +included this in their dictionary. +You should, however, select your own methods for constructing +passwords and not rely exclusively on the methods given here. +.SS Notes about group passwords +Group passwords are an inherent security problem since more +than one person is permitted to know the password. +However, groups are a useful tool for permitting co-operation +between different users. +.SH CAVEATS +Not all options may be supported. +Password complexity checking may vary from site to site. +The user is urged to select as complex a password as they +feel comfortable with. +User's may not be able to change their password on a system if NIS +is enabled and they are not logged into the NIS server. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- encrypted user passwords +.SH SEE ALSO +.BR passwd (3), +.BR shadow (3), +.BR group (5), +.BR passwd (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/passwd.5 b/man/passwd.5 new file mode 100644 index 00000000..d93758b1 --- /dev/null +++ b/man/passwd.5 @@ -0,0 +1,111 @@ +.\" Copyright 1989 - 1990, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: passwd.5,v 1.4 1998/12/28 20:35:19 marekm Exp $ +.\" +.TH PASSWD 5 +.SH NAME +passwd \- The password file +.SH DESCRIPTION +.I passwd +contains various pieces of information for each user account. +Included is +.IP "" .5i +Login name +.IP "" .5i +Optional encrypted password +.IP "" .5i +Numerical user ID +.IP "" .5i +Numerical group ID +.IP "" .5i +User name or comment field +.IP "" .5i +User home directory +.IP "" .5i +User command interpreter +.PP +The password field may not be filled if shadow passwords +have been enabled. +If shadow passwords are being used, the encrypted password will +be found in \fI/etc/shadow\fR. +The encryped password consists of 13 characters from the +64 character alphabet +a thru z, A thru Z, 0 thru 9, \. and /. +Refer to \fBcrypt\fR(3) for details on how this string is +interpreted. +.PP +An optional password age string may follow the encrypted +password, separated by a comma, from the same alphabet +as the password itself. +The first character gives the number of weeks during which the +password is valid. +The second character gives the number of weeks which must pass +before the user is permitted to change the password. +The last two characters give the week since Jan 1970 when the +password was last changed. +When the number of weeks during which the password is valid +have passed, the user will be required to provide a new +password. +.PP +The comment field is used by various system utilities, such as +\fBfinger\fR(1). +Three additional values may be present in the comment field. +They are +.IP "" .5i +pri= \- set initial value of nice +.IP "" .5i +umask= \- set initial value of umask +.IP "" .5i +ulimit= \- set initial value of ulimit +.PP +These fields are separated from each other and from any other +comment field by a comma. +.PP +The home directory field provides the name of the initial +working directory. +\fBLogin\fR uses this information to set the value of +the \fBHOME\fR environmental variable. +.PP +The command interpreter field provides the name of the user's +command language interpreter, or the name of the initial program +to execute. +\fBLogin\fR uses this information to set the value of the +\fBSHELL\fR environmental variable. +If this field is empty, it defaults to the value \fB/bin/sh\fR. +.SH FILES +/etc/passwd \- user account information +.SH SEE ALSO +.BR login (1), +.BR passwd (1), +.BR su (1), +.BR sulogin (8), +.BR shadow (5), +.BR pwconv (8), +.BR pwunconv (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/porttime.5 b/man/porttime.5 new file mode 100644 index 00000000..04497e90 --- /dev/null +++ b/man/porttime.5 @@ -0,0 +1,84 @@ +.\" Copyright 1989 - 1990, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: porttime.5,v 1.4 1998/12/28 20:35:20 marekm Exp $ +.\" +.TH PORTTIME 5 +.SH NAME +porttime \- port access time file +.SH DESCRIPTION +.I porttime +contains a list of tty devices, user names, and permitted login times. +.PP +Each entry consists of three colon separated fields. +The first field is a comma separated list of tty devices, +or an asterisk to indicate that all tty devices are matched by this entry. +The second field is a comma separated list of user names, or an +asterisk to indicated that all user names are matched by this entry. +The third field is a comma separated list of permitted access times. +.PP +Each access time entry consists of zero or more days of the week, +abbreviated \fBSu\fR, \fBMo\fR, \fBTu\fR, \fBWe\fR, \fBTh\fR, +\fBFr\fR, and \fBSa\fR, followed by a pair of times separated by +a hyphen. +The abbreviation \fBWk\fR may be used to represent Monday thru Friday, +and \fBAl\fR may be used to indicate every day. +If no days are given, \fBAl\fR is assumed. +.SH EXAMPLES +The following entry allows access to user \fBjfh\fR on every port +during weekdays from 9am to 5pm. +.br +.sp 1 + *:jfh:Wk0900-1700 +.br +.sp 1 +The following entries allow access only to the users \fBroot\fR and +\fBoper\fR on /dev/console at any time. +This illustrates how the +\fI/etc/porttime\fR file is an ordered list of access times. +Any other user would match the second entry which does not permit +access at any time. +.br +.sp 1 + console:root,oper:Al0000-2400 +.br + console:*: +.br +.sp 1 +The following entry allows access for the user \fBgames\fR on any +port during non-working hours. +.br +.sp 1 + *:games:Wk1700-0900,SaSu0000-2400 +.br +.sp 1 +.SH FILES +/etc/porttime \- file containing port access times +.SH SEE ALSO +.BR login (1) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/pw_auth.3 b/man/pw_auth.3 new file mode 100644 index 00000000..830529c4 --- /dev/null +++ b/man/pw_auth.3 @@ -0,0 +1,159 @@ +.\" Copyright 1992 - 1993, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pw_auth.3,v 1.4 1998/12/28 20:35:21 marekm Exp $ +.\" +.TH PWAUTH 3 +.SH NAME +pwauth \- administrator defined password authentication routines +.SH SYNTAX +.B #include +.PP +.B int pw_auth (char +.I *command, +.B char +.I *user, +.B int +.I reason, +.B char +.IB *input) ; +.SH DESCRIPTION +.B pw_auth +invokes the administrator defined functions for a given user. +.PP +\fIcommand\fR is the name of the authentication program. +It is retrieved from the user's password file information. +The string contains one or more executable file names, delimited by +semi-colons. +Each program will be executed in the order given. +The command line arguments are given for each of the reasons listed +below. +.PP +\fIuser\fR is the name of the user to be authenticated, as given +in the \fI/etc/passwd\fR file. +User entries are indexed by username. +This allows non-unique user IDs to be present and for each different +username associated with that user ID to have a different +authentication program and information. +.PP +Each of the permissible authentication reasons is handled in a +potentially differenent manner. +Unless otherwise mentioned, the standard file descriptors 0, 1, and +2 are available for communicating with the user. +The real user ID may be used to determine the identity of the user +making the authentication request. +\fIreason\fR is one of +.IP \fBPW_SU\fR 1i +Perform authentication for the current real user ID attempting to +switch real user ID to the named user. +The authentication program will be invoked with a \fB-s\fR option, followed +by the username. +.IP \fBPW_LOGIN\fR 1i +Perform authentication for the named user creating a new login session. +The authentication program will be invoked with a \fB-l\fR option, followed +by the username. +.IP \fBPW_ADD\fR 1i +Create a new entry for the named user. +This allows an authentication program to initialize storage for a new +user. +The authentication program will be invoked with a \fB-a\fR option, followed +by the username. +.IP \fBPW_CHANGE\fR 1i +Alter an existing entry for the named user. +This allows an authentication program to alter the authentication +information for an existing user. +The authentication program will be invoked with a \fB-c\fR option, followed +by the username. +.IP \fBPW_DELETE\fR 1i +Delete authentication information for the named user. +This allows an authentication program to reclaim storage for a user which +is no longer authenticated using the authentication program. +The authentication program will be invoked with a \fB-d\fR option, followed +by the username. +.IP \fBPW_TELNET\fR 1i +Authenticate a user who is connecting to the system using the +fBtelnet\fR command. +The authentication program will be invoked with a \fB-t\fR option, followed +by the username. +.IP \fBPW_RLOGIN\fR 1i +Authenticate a user who is connecting to the system using the \fBrlogin\fR +command. +The authentication program will be invoked with a \fB-r\fR option, followed +by the username. +.IP \fBPW_FTP\fR 1i +Authenticate a user who is connecting to the system using the \fBftp\fR +command. +The authentication program will be invoked with a \fR-f\fR option, followed +by the username. +The standard file descriptors are not available for communicating with the +user. +The standard input file descriptor will be connected to the parent process, +while the other two output file descriptors will be connected to +\fI/dev/null\fR. +The \fBpw_auth\fR function will pipe a single line of data to the +authentication program using file descriptor 0. +.IP \fBPW_REXEC\fR 1i +Authenticate a user who is connecting to the system using the \fIrexec\fR +command. +The authentication program will be invoked with a \fB-x\fR option, followed +by the username. +The standard file descriptors are not available for communicating with the +remote user. +The standard input file descriptor will be connected to the parent process, +while the other two output file descriptors will be connected to +\fI/dev/null\fR. +The \fBpw_auth\fR function will pipe a single line of data to the +authentication program using file descriptor 0. +.PP +The last argument is the authentication data which is used by the +.B PW_FTP +and +.B PW_REXEC +reasons. +It is treated as a single line of text which is piped to the authentication +program. +When the reason is +.BR PW_CHANGE, +the value of \fIinput\fR is the value of +previous user name if the user name is being changed. +.SH CAVEATS +This function does not create the actual session. +It only indicates if the user should be allowed to create the session. +.PP +The network options are untested at this time. +.SH DIAGNOSTICS +The \fBpw_auth\fR function returns 0 if the authentication program exited +with a 0 exit code, and a non-zero value otherwise. +.SH SEE ALSO +.BR login (1), +.BR passwd (1), +.BR su (1), +.BR useradd (8), +.BR userdel (8), +usermod(8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/pwauth.8 b/man/pwauth.8 new file mode 100644 index 00000000..8f0da284 --- /dev/null +++ b/man/pwauth.8 @@ -0,0 +1,67 @@ +.\" Copyright 1992, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pwauth.8,v 1.4 1998/12/28 20:35:22 marekm Exp $ +.\" +.TH PWAUTH 8 +.SH NAME +pwauth \- administrator defined password authentication +.SH DESCRIPTION +The system administrator is able to define a list of programs which +are used to validate a user's identity. +These programs are given in place of the encrypted password +information which is present in either the \fI/etc/passwd\fR or +\fI/etc/shadow\fR files. +The utilities which administer user accounts examine the encrypted +password field and determine if the user has an administrator defined +authentication program. +The \fBpw_auth\fR function will be invoked whenever one of these +administration programs determines that a user which is being altered +has authentication programs defined. +.PP +The initial entry is created with the \fBuseradd\fR command. +Alterations, such as changing authentication information or deleting +the user account, will cause the \fBpw_auth\fR function to be invoked. +This keeps the authentication information up to date for each user +account. +.PP +The authentication programs do not create the actual login or network +sessions. +The exit code from the authentication program is taken as an +indication that the action is to be permitted. +The calling process must have the appropriate priviledges to create +the login or network session itself. +.SH SEE ALSO +.BR login (1), +.BR passwd (1), +.BR su (1), +.BR useradd (8), +.BR userdel (8), +.BR usermod (8), +.BR pw_auth (3) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/pwck.8 b/man/pwck.8 new file mode 100644 index 00000000..d0d38ea5 --- /dev/null +++ b/man/pwck.8 @@ -0,0 +1,107 @@ +.\" Copyright 1992, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pwck.8,v 1.4 1998/12/28 20:35:23 marekm Exp $ +.\" +.TH PWCK 1 +.SH NAME +pwck \- verify integrity of password files +.SH SYNOPSIS +\fBpwck\fR [\fB-r\fR] [\fIpasswd\fR \fIshadow\fR] +.SH DESCRIPTION +\fBpwck\fR verifies the integrity of the system authentication information. +All entries in the \fI/etc/passwd\fR and \fI/etc/shadow\fR are checked to +see that the entry has the proper format and valid data in each field. +The user is prompted to delete entries that are improperly formatted or +which have other incorrectable errors. +.P +Checks are made to verify that each entry has +.sp +.in +.5i +- the correct number of fields +.br +- a unique user name +.br +- a valid user and group identifier +.br +- a valid primary group +.br +- a valid home directory +.br +- a valid login shell +.in -.5i +.sp +.P +The checks for correct number of fields and unique user name are fatal. +If the entry has the wrong number of fields, the user will be prompted to +delete the entire line. +If the user does not answer affirmatively, all further checks are bypassed. +An entry with a duplicated user name is prompted for deletion, but the +remaining checks will still be made. +All other errors are warning and the user is encouraged to run the +\fBusermod\fR command to correct the error. +.P +The commands which operate on the \fI/etc/passwd\fR file are not able to +alter corrupted or duplicated entries. +\fBpwck\fR should be used in those circumstances to remove the offending +entry. +.SH OPTIONS +By default, \fBpwck\fR operates on the files \fI/etc/passwd\fR and +\fI/etc/shadow\fR. +The user may select alternate files with the \fIpasswd\fR and \fIshadow\fR +parameters. +Additionally, the user may execute the command in read-only mode by +specifying the \fB-r\fR flag. +This causes all questions regarding changes to be answered \fBno\fR +without user intervention. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- encrypted password information +.br +/etc/group \- group information +.SH SEE ALSO +.BR usermod (8), +.BR group (5), +.BR passwd (5), +.BR shadow (5) +.SH DIAGNOSTICS +The \fBpwck\fR command exits with the following values: +.IP 0 5 +Success +.IP 1 5 +Syntax Error +.IP 2 5 +One or more bad password entries +.IP 3 5 +Cannot open password files +.IP 4 5 +Cannot lock password files +.IP 5 5 +Cannot update password files +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/pwconv.8 b/man/pwconv.8 new file mode 100644 index 00000000..f7bafba5 --- /dev/null +++ b/man/pwconv.8 @@ -0,0 +1,63 @@ +.\" $Id: pwconv.8,v 1.8 1998/06/25 22:10:43 marekm Exp $ +.TH PWCONV 8 "26 Sep 1997" +.SH NAME +pwconv, pwunconv, grpconv, grpunconv \- convert to and from shadow passwords and groups. +.SH SYNOPSIS +.B pwconv +.br +.B pwunconv +.br +.B grpconv +.br +.B grpunconv +.SH DESCRIPTION +These four programs all operate on the normal and shadow password and +group files: +.IR /etc/passwd ", " /etc/group ", " /etc/shadow ", and " /etc/gshadow . + +.B pwconv +.RI "creates " shadow " from " passwd " and an optionally existing " shadow . +.B pwunconv +.RI "creates " passwd " from " passwd " and " shadow " and then removes " shadow . +.B grpconv +.RI "creates " gshadow " from " group " and an optionally existing " gshadow . +.B grpunconv +.RI "creates " group " from " group " and " gshadow " and then removes " gshadow . + +Each program acquires the necessary locks before conversion. + +.BR pwconv " and " grpconv +are similiar. First, entries in the shadowed file which don't exist +in the main file are removed. Then, shadowed entries which don't have +`x' as the password in the main file are updated. Any missing +shadowed entries are added. Finally, passwords in the main file are +replaced with `x'. These programs can be used for initial conversion +as well to update the shadowed file if the main file is edited by +hand. + +.B pwconv +will use the values of +.BR PASS_MIN_DAYS ", " PASS_MAX_DAYS ", and " PASS_WARN_AGE +from +.I /etc/login.defs +when adding new entries to +.IR /etc/shadow . + +.RB "Likewise, " pwunconv " and " grpunconv +are similiar. Passwords in the main file are updated from the +shadowed file. Entries which exist in the main file but not in the +shadowed file are left alone. Finally, the shadowed file is removed. + +Some password aging information is lost by +.BR pwunconv . +It will convert what it can. +.SH "BUGS" +Errors in the password or group files (such as invalid or duplicate +entries) may cause these programs to loop forever or fail in other +strange ways. Please run \fBpwck\fR and \fBgrpck\fR to correct any +such errors before converting to or from shadow passwords or groups. +.SH "SEE ALSO" +.BR login.defs (5), +.BR pwck (8), +.BR grpck (8), +.BR shadowconfig (8) diff --git a/man/shadow.3 b/man/shadow.3 new file mode 100644 index 00000000..74d2b2c2 --- /dev/null +++ b/man/shadow.3 @@ -0,0 +1,148 @@ +.\" Copyright 1989 - 1993, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: shadow.3,v 1.4 1998/12/28 20:35:24 marekm Exp $ +.\" +.TH SHADOW 3 +.SH NAME +shadow \- encrypted password file routines +.SH SYNTAX +.B #include +.PP +.B struct spwd *getspent(); +.PP +.B struct spwd *getspnam(char +.IB *name ); +.PP +.B void setspent(); +.PP +.B void endspent(); +.PP +.B struct spwd *fgetspent(FILE +.IB *fp ); +.PP +.B struct spwd *sgetspent(char +.IB *cp ); +.PP +.B int putspent(struct spwd +.I *p, +.B FILE +.IB *fp ); +.PP +.B int lckpwdf(); +.PP +.B int ulckpwdf(); +.SH DESCRIPTION +.I shadow +manipulates the contents of the shadow password file, +\fI/etc/shadow\fR. +The structure in the \fI#include\fR file is +.sp +struct spwd { +.in +.5i +.br + char *sp_namp; /* user login name */ +.br + char *sp_pwdp; /* encrypted password */ +.br + long sp_lstchg; /* last password change */ +.br + int sp_min; /* days until change allowed. */ +.br + int sp_max; /* days before change required */ +.br + int sp_warn; /* days warning for expiration */ +.br + int sp_inact; /* days before account inactive */ +.br + int sp_expire; /* date when account expires */ +.br + int sp_flag; /* reserved for future use */ +.br +.in -.5i +} +.PP +The meanings of each field are +.sp +sp_namp \- pointer to null-terminated user name. +.br +sp_pwdp \- pointer to null-terminated password. +.br +sp_lstchg \- days since Jan 1, 1970 password was last changed. +.br +sp_min \- days before which password may not be changed. +.br +sp_max \- days after which password must be changed. +.br +sp_warn \- days before password is to expire that user is warned +of pending password expiration. +.br +sp_inact \- days after password expires that account is considered +inactive and disabled. +.br +sp_expire \- days since Jan 1, 1970 when account will be disabled. +.br +sp_flag \- reserved for future use. +.SH DESCRIPTION +\fBgetspent\fR, \fBgetspname\fR, \fBfgetspent\fR, and \fBsgetspent\fR +each return a pointer to a \fBstruct spwd\fR. +\fBgetspent\fR returns the +next entry from the file, and \fBfgetspent\fR returns the next +entry from the given stream, which is assumed to be a file of +the proper format. +\fBsgetspent\fR returns a pointer to a \fBstruct spwd\fR using the +provided string as input. +\fBgetspnam\fR searches from the current position in the file for +an entry matching \fBname\fR. +.PP +\fBsetspent\fR and \fBendspent\fR may be used to begin and end, +respectively, access to the shadow password file. +.PP +The \fBlckpwdf\fR and \fBulckpwdf\fR routines should be used to +insure exclusive access to the \fI/etc/shadow\fR file. +\fBlckpwdf\fR attempts to acquire a lock using \fBpw_lock\fR for +up to 15 seconds. +It continues by attempting to acquire a second lock using \fBspw_lock\fR +for the remainder of the initial 15 seconds. +Should either attempt fail after a total of 15 seconds, \fBlckpwdf\fR +returns -1. +When both locks are acquired 0 is returned. +.SH DIAGNOSTICS +Routines return NULL if no more entries are available or if an +error occurs during processing. +Routines which have \fBint\fR as the return value return 0 for +success and -1 for failure. +.SH CAVEATS +These routines may only be used by the super user as access to +the shadow password file is restricted. +.SH FILES +/etc/shadow \- encrypted user passwords +.SH SEE ALSO +.BR getpwent (3), +.BR shadow (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/shadow.5 b/man/shadow.5 new file mode 100644 index 00000000..b39f2402 --- /dev/null +++ b/man/shadow.5 @@ -0,0 +1,99 @@ +.\" Copyright 1989 - 1990, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: shadow.5,v 1.4 1998/12/28 20:35:25 marekm Exp $ +.\" +.TH SHADOW 5 +.SH NAME +shadow \- encrypted password file +.SH DESCRIPTION +.I shadow +contains the encrypted password information for user's accounts +and optional the password aging information. +Included is +.IP "" .5i +Login name +.IP "" .5i +Encrypted password +.IP "" .5i +Days since Jan 1, 1970 that password was last changed +.IP "" .5i +Days before password may be changed +.IP "" .5i +Days after which password must be changed +.IP "" .5i +Days before password is to expire that user is warned +.IP "" .5i +Days after password expires that account is disabled +.IP "" .5i +Days since Jan 1, 1970 that account is disabled +.IP "" .5i +A reserved field +.PP +The password field must be filled. +The encryped password consists of 13 to 24 characters from the +64 character alphabet +a thru z, A thru Z, 0 thru 9, \. and /. +Refer to \fBcrypt\fR(3) for details on how this string is +interpreted. +.PP +The date of the last password change is given as the number +of days since Jan 1, 1970. +The password may not be changed again until the proper number +of days have passed, and must be changed after the maximum +number of days. +If the minimum number of days required is greater than the +maximum number of day allowed, this password may not be +changed by the user. +.PP +An account is considered to be inactive and is disabled if +the password is not changed within the specified number of +days after the password expires. +An account will also be disabled on the specified day +regardless of other password expiration information. +.PP +This information supercedes any password or password age +information present in \fI/etc/passwd\fR. +.PP +This file must not be readable by regular users if password +security is to be maintained. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- encrypted user passwords +.SH SEE ALSO +.BR chage (1), +.BR login (1), +.BR passwd (1), +.BR su (1), +.BR sulogin (8), +.BR shadow (3), +.BR passwd (5), +.BR pwconv (8), +.BR pwunconv (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/shadowconfig.8 b/man/shadowconfig.8 new file mode 100644 index 00000000..ac6af945 --- /dev/null +++ b/man/shadowconfig.8 @@ -0,0 +1,24 @@ +.\" $Id: shadowconfig.8,v 1.2 1997/12/14 20:07:22 marekm Exp $ +.TH SHADOWCONFIG 8 "19 Apr 1997" "Debian GNU/Linux" +.SH NAME +shadowconfig \- toggle shadow passwords on and off +.SH SYNOPSIS +.B "shadowconfig" +.IR on " | " off +.SH DESCRIPTION +.PP +.B shadowconfig on +will turn shadow passwords on; +.B shadowconfig off +will turn shadow passwords off. +.B shadowconfig +will print an error message and exit with a nonzero code if it finds +anything awry. If that happens, you should correct the error and run +it again. + +Turning shadow passwords on when they are already on, or off when they +are already off, is harmless. + +Read +.I /usr/doc/passwd/README.debian.gz +for a brief introduction to shadow passwords and related features. diff --git a/man/su.1 b/man/su.1 new file mode 100644 index 00000000..15dc64a2 --- /dev/null +++ b/man/su.1 @@ -0,0 +1,83 @@ +.\" Copyright 1989 - 1990, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: su.1,v 1.5 1998/12/28 20:35:26 marekm Exp $ +.\" +.TH SU 1 +.SH NAME +su \- Change user ID or become super-user +.SH SYNOPSIS +.BR su " [" - ] +.RI [ username " [" args ]] +.SH DESCRIPTION +.B su +is used to become another user during a login session. +Invoked without a username, \fBsu\fR defaults to becoming +the super user. +The optional argument \fB\-\fR may be used to provide an +environment similiar to what the user would expect had +the user logged in directly. +.PP +Additional arguments may be provided after the username, +in which case they are supplied to the user\'s login shell. +In particular, an argument of \fB-c\fR will cause the +next argument to be treated as a command by most command +interpreters. +.\" The command will be executed under the shell specified by +.\" \fB$SHELL\fR, or if undefined, by the one specified in +.\" \fI/etc/passwd\fR. +.\" XXX - the above was not quite correct. --marekm +The command will be executed by the shell specified in +\fI/etc/passwd\fR for the target user. +.PP +The user will be prompted for a password, if appropriate. +Invalid passwords will produce an error message. +All attempts, both valid and invalid, are logged to detect +abuses of the system. +.PP +The current environment is passed to the new shell. The value of +\fB$PATH\fR is reset to \fB/bin:/usr/bin\fR for normal users, or +\fB/sbin:/bin:/usr/sbin:/usr/bin\fR for the super user. This may be +changed with the \fBENV_PATH\fR and \fBENV_SUPATH\fR definitions in +\fI/etc/login.defs\fR. +.SH CAVEATS +.PP +This version of \fBsu\fR has many compilation options, only some of which +may be in use at any particular site. +.SH Files +/etc/passwd \- user account information +.br +/etc/shadow \- encrypted passwords and age information +.br +$HOME/.profile \- initialization script for default shell +.SH SEE ALSO +.BR login (1), +.BR sh (1), +.BR suauth (5), +.BR login.defs (5) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/suauth.5 b/man/suauth.5 new file mode 100644 index 00000000..a3aa1581 --- /dev/null +++ b/man/suauth.5 @@ -0,0 +1,112 @@ +.TH SUAUTH 5 "Feb 14, 1996" +.UC 5 +.SH NAME +suauth \- Detailed su control file +.SH SYNOPSIS +.B /etc/suauth +.SH DESCRIPTION +The file +.I /etc/suauth +is referenced whenever the su command is called. It can change the +behaviour of the su command, based upon +.PP +.RS +.nf +1) the user su is targetting +.fi +2) the user executing the su command (or any groups he might be +a member of) +.RE +.PP +The file is formatted like this, with lines starting with a # +being treated as comment lines and ignored; +.PP +.RS +to-id:from-id:ACTION +.RE +.PP +Where to-id is either the word +.BR ALL , +a list of usernames +delimited by "," or the words +.B ALL EXCEPT +followed by a list +of usernames delimted by "," +.PP +from-id is formatted the same as to-id except the extra word +.B GROUP +is recognised. +.B ALL EXCEPT GROUP +is perfectly valid too. +Following +.B GROUP +appears one or more group names, delimited by +",". It is not sufficient to have primary group id of the +relevant group, an entry in +.BR /etc/group (5) +is neccessary. +.PP +Action can be one only of the following currently supported +options. +.TP 20 +.B DENY +The attempt to su is stopped before a password is even asked for. +.TP 20 +.B NOPASS +The attempt to su is automatically successful; no password is +asked for. +.TP 20 +.B OWNPASS +For the su command to be successful, the user must enter +his or her own password. They are told this. +.PP +Note there are three separate fields delimted by a colon. No +whitespace must surround this colon. Also note that the file +is examined sequentially line by line, and the first applicable +rule is used without examining the file further. This makes it +possible for a system administrator to exercise as fine control +as he or she wishes. +.SH EXAMPLE +.PP +.nf +# sample /etc/suauth file +# +# A couple of privileged usernames may +# su to root with their own password. +# +root:chris,birddog:OWNPASS +# +# Anyone else may not su to root unless in +# group wheel. This is how BSD does things. +# +root:ALL EXCEPT GROUP wheel:DENY +# +# Perhaps terry and birddog are accounts +# owned by the same person. +# Access can be arranged between them +# with no password. +# +terry:birddog:NOPASS +birddog:terry:NOPASS +# +.fi +.SH FILES +/etc/suauth +.SH BUGS +There could be plenty lurking. The file parser is particularly +unforgiving about syntax errors, expecting no spurious whitespace +(apart from beginning and end of lines), and a specific token +delimiting different things. +.SH DIAGNOSTICS +An error parsing the file is reported using +.BR syslogd (8) +as level ERR on +facility AUTH. +.SH SEE ALSO +.BR su (1) +.SH AUTHOR +.nf +Chris Evans (lady0110@sable.ox.ac.uk) +Lady Margaret Hall +Oxford University +England diff --git a/man/sulogin.8 b/man/sulogin.8 new file mode 100644 index 00000000..2de82795 --- /dev/null +++ b/man/sulogin.8 @@ -0,0 +1,88 @@ +.\" Copyright 1989 - 1992, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: sulogin.8,v 1.4 1998/12/28 20:35:27 marekm Exp $ +.\" +.TH SULOGIN 8 +.SH NAME +sulogin \- Single-user login +.SH SYNTAX +\fBsulogin\fR [\fItty-device\fR] +.SH DESCRIPTION +.B sulogin +is invoked by \fBinit\fR prior to allowing the user +access to the system when in single user mode. +This feature may only be available on certain systems where +\fBinit\fR has been modified accordingly, or where the +\fB/etc/inittab\fR has an entry for a single user login. +.PP +The user is prompted +.IP "" .5i +Type control-d to proceed with normal startup, +.br +(or give root password for system maintenance): +.PP +Input and output will be performed with the standard file +descriptors unless the optional device name argument is provided. +.PP +If the user enters the correct root password, a login session +is initiated. +When \fBEOF\fR is pressed instead, the system enters multi-user +mode. +.PP +After the user exits the single-user shell, or presses \fBEOF\fR, +the system begins the initialization process required to enter +multi-user mode. +.SH CAVEATS +.PP +This command can only be used if \fBinit\fR has been modified to call +\fBsulogin\fR instead of \fB/bin/sh\fR, +or if the user has set the \fIinittab\fR to support a single user +login. +For example, the line +.br +.sp 1 +co:s:respawn:/etc/sulogin /dev/console +.br +.sp 1 +should execute the sulogin command in single user mode. +.PP +As complete an environment as possible is created. +However, various devices may be unmounted or uninitialized and many +of the user commands may be unavailable or nonfunctional as a result. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- encrypted passwords and age information +.br +/.profile \- initialization script for single user shell +.SH SEE ALSO +.BR login (1), +.BR init (8), +.BR sh (1) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/useradd.8 b/man/useradd.8 new file mode 100644 index 00000000..68f7a5bf --- /dev/null +++ b/man/useradd.8 @@ -0,0 +1,197 @@ +.\" Copyright 1991 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: useradd.8,v 1.6 1999/03/07 19:14:47 marekm Exp $ +.\" +.TH USERADD 8 +.SH NAME +useradd \- Create a new user or update default new user information +.SH SYNOPSIS +.TP 8 +.B useradd +.\" .RB [ -A +.\" .RI { method | \fBDEFAULT\fR "},... ]" +.RB [ -c +.IR comment ] +.RB [ -d +.IR home_dir ] +.br +.RB [ -e +.IR expire_date ] +.RB [ -f +.IR inactive_time ] +.br +.RB [ -g +.IR initial_group ] +.RB [ -G +.IR group [,...]] +.br +.RB [ -m " [" -k +.IR skeleton_dir ]] +.RB [ -p +.IR passwd ] +.br +.RB [ -s +.IR shell ] +.RB [ -u +.IR uid " [" +.BR -o ]] +.I login +.TP 8 +.B useradd +\fB-D\fR +[\fB-g\fI default_group\fR] +[\fB-b\fI default_home\fR] +.br +[\fB-f\fI default_inactive\fR] +[\fB-e\fI default_expire_date\fR] +.br +[\fB-s\fI default_shell\fR] +.SH DESCRIPTION +.SS Creating New Users +When invoked without the \fB-D\fR option, the \fBuseradd\fR command +creates a new user account using the values specified on the +command line and the default values from the system. +The new user account will be entered into the system files as needed, +the home directory will be created, and initial files copied, depending +on the command line options. +The options which apply to the \fBuseradd\fR command are +.\" .IP "\fB-A {\fImethod\fR|\fBDEFAULT\fR},..." +.\" The value of the user's authentication method. +.\" The authentication method is the name of a program which is responsible +.\" for validating the user's identity. +.\" The string \fBDEFAULT\fR may be used to change the user's authentication +.\" method to the standard system password method. +.\" This is a comma-separated list of program names. +.\" It may include \fBDEFAULT\fR exactly once. +.IP "\fB-c \fIcomment\fR" +The new user's password file comment field. +.IP "\fB-d \fIhome_dir\fR" +The new user will be created using \fIhome_dir\fR as the value for +the user's login directory. +The default is to append the \fIlogin\fR name to \fIdefault_home\fR +and use that as the login directory name. +.IP "\fB-e \fIexpire_date\fR" +The date on which the user account will be disabled. +The date is specified in the format \fIYYYY-MM-DD\fR. +.IP "\fB-f \fIinactive_days\fR" +The number of days after a password expires until the account +is permanently disabled. +A value of 0 disables the account as soon as the password has +expired, and a value of -1 disables the feature. +The default value is -1. +.IP "\fB-g \fIinitial_group\fR" +The group name or number of the user's initial login group. +The group name must exist. A group number must refer to an +already existing group. +The default group number is 1. +.IP "\fB-G \fIgroup,[...]\fR" +A list of supplementary groups which the user is also a member +of. +Each group is separated from the next by a comma, with no +intervening whitespace. +The groups are subject to the same restrictions as the group +given with the \fB-g\fR option. +The default is for the user to belong only to the initial group. +.IP \fB-m\fR +The user's home directory will be created if it does not exist. +The files contained in \fIskeleton_dir\fR will be copied to the +home directory if the \fB-k\fR option is used, otherwise the +files contained in \fI/etc/skel\fR will be used instead. +Any directories contained in \fIskeleton_dir\fR or \fI/etc/skel\fR +will be created in the user's home directory as well. +The \fB-k\fR option is only valid in conjunction with the \fB-m\fR +option. +The default is to not create the directory and to not copy any +files. +.IP "\fB-p \fIpasswd\fR" +The encrypted password, as returned by \fBcrypt\fR(3). +The default is to disable the account. +.IP "\fB-s \fIshell\fR" +The name of the user's login shell. +The default is to leave this field blank, which causes the system +to select the default login shell. +.IP "\fB-u \fIuid\fR" +The numerical value of the user's ID. +This value must be unique, unless the \fI-o\fR option is used. +The value must be non-negative. +The default is to use the smallest ID value greater than 99 and +greater than every other user. +Values between 0 and 99 are typically reserved for system accounts. +.SS Changing the default values +When invoked with the \fB-D\fR option, \fBuseradd\fR will either +display the current default values, or update the default values +from the command line. +The valid options are +.IP "\fB-b \fIdefault_home\fR" +The initial path prefix for a new user's home directory. +The user's name will be affixed to the end of \fIdefault_home\fR +to create the new directory name if the \fB-d\fI option is not +used when creating a new account. +.IP "\fB-e \fIdefault_expire_date\fR" +The date on which the user account is disabled. +.IP "\fB-f \fIdefault_inactive\fR" +The number of days after a password has expired before the +account will be disabled. +.IP "\fB-g \fIdefault_group\fR" +The group name or ID for a new user's initial group. +The named group must exist, and a numerical group ID must have +an existing entry . +.IP "\fB-s \fIdefault_shell\fR" +The name of the new user's login shell. +The named program will be used for all future new user accounts. +.PP +If no options are specified, \fBuseradd\fR displays the current +default values. +.SH NOTES +The system administrator is responsible for placing the default +user files in the \fI/etc/skel\fR directory. +.SH CAVEATS +You may not add a user to an NIS group. +This must be performed on the NIS server. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- secure user account information +.br +/etc/group \- group information +.br +/etc/default/useradd \- default information +.br +/etc/skel \- directory containing default files +.SH SEE ALSO +.BR chfn (1), +.BR chsh (1), +.BR crypt (3), +.BR groupadd (8), +.BR groupdel (8), +.BR groupmod (8), +.BR passwd (1), +.BR userdel (8), +.BR usermod (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/userdel.8 b/man/userdel.8 new file mode 100644 index 00000000..eb9e5b89 --- /dev/null +++ b/man/userdel.8 @@ -0,0 +1,69 @@ +.\" Copyright 1991 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: userdel.8,v 1.4 1998/12/28 20:35:29 marekm Exp $ +.\" +.TH USERDEL 8 +.SH NAME +userdel \- Delete a user account and related files +.SH SYNOPSIS +.B userdel +[\fB-r\fR] +.I login +.SH DESCRIPTION +The \fBuserdel\fR command modifies the system account files, deleting +all entries that refer to \fIlogin\fR. +The named user must exist. +.IP \fB-r\fR +Files in the user's home directory will be removed along with the +home directory itself. +Files located in other file system will have to be searched for +and deleted manually. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- secure user account information +.br +/etc/group \- group information +.SH CAVEATS +\fBuserdel\fR will not allow you to remove an account if the user +is currently logged in. +You must kill any running processes which belong to an account that +you are deleting. +You may not remove any NIS attributes on an NIS client. +This must be performed on the NIS server. +.SH SEE ALSO +.BR chfn (1), +.BR chsh (1), +.BR groupadd (8), +.BR groupdel (8), +.BR groupmod (8), +.BR passwd (1), +.BR useradd (8), +.BR usermod (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/usermod.8 b/man/usermod.8 new file mode 100644 index 00000000..8aecfd36 --- /dev/null +++ b/man/usermod.8 @@ -0,0 +1,153 @@ +.\" Copyright 1991 - 1994, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: usermod.8,v 1.6 1999/03/07 19:14:48 marekm Exp $ +.\" +.TH USERMOD 8 +.SH NAME +usermod \- Modify a user account +.SH SYNOPSIS +.TP 8 +.B usermod +.\" .RB [ -A +.\" .RI { method | \fBDEFAULT\fR "},... ]" +.RB [ -c +.IR comment ] +.RB [ -d +.IR home_dir " [" +.BR -m ]] +.br +.RB [ -e +.IR expire_date ] +.RB [ -f +.IR inactive_time ] +.br +.RB [ -g +.IR initial_group ] +.RB [ -G +.IR group [,...]] +.br +.RB [ -l +.IR login_name ] +.RB [ -p +.IR passwd ] +.br +.RB [ -s +.IR shell ] +.RB [ -u +.IR uid " [" +.BR -o ]] +.I login +.SH DESCRIPTION +The \fBusermod\fR command modifies the system account files to reflect +the changes that are specified on the command line. +The options which apply to the \fBusermod\fR command are +.\" .IP "\fB-A \fImethod\fR|\fBDEFAULT\fR" +.\" The new value of the user's authentication method. +.\" The authentication method is the name of a program which is responsible +.\" for validating the user's identity. +.\" The string \fBDEFAULT\fR may be used to change the user's authentication +.\" method to the standard system password method. +.IP "\fB-c \fIcomment\fR" +The new value of the user's password file comment field. +It is normally modified using the \fBchfn\fR(1) utility. +.IP "\fB-d \fIhome_dir\fR" +The user's new login directory. +If the \fB-m\fR option is given the contents of the current home directory +will be moved to the new home directory, which is created if it does not +already exist. +.IP "\fB-e \fIexpire_date\fR" +The date on which the user account will be disabled. +The date is specified in the format \fIYYYY-MM-DD\fR. +.IP "\fB-f \fIinactive_days\fR" +The number of days after a password expires until the account +is permanently disabled. +A value of 0 disables the account as soon as the password has +expired, and a value of -1 disables the feature. +The default value is -1. +.IP "\fB-g \fIinitial_group\fR" +The group name or number of the user's new initial login group. +The group name must exist. A group number must refer to an +already existing group. +The default group number is 1. +.IP "\fB-G \fIgroup,[...]\fR" +A list of supplementary groups which the user is also a member +of. +Each group is separated from the next by a comma, with no +intervening whitespace. +The groups are subject to the same restrictions as the group +given with the \fB-g\fR option. +If the user is currently a member of a group which is not listed, +the user will be removed from the group +.IP "\fB-l \fIlogin_name\fR" +The name of the user will be changed from \fIlogin\fR to +\fIlogin_name\fR. +Nothing else is changed. +In particular, the user's home directory name should probably +be changed to reflect the new login name. +.IP "\fB-p \fIpasswd\fR" +The encrypted password, as returned by \fBcrypt\fR(3). +.IP "\fB-s \fIshell\fR" +The name of the user's new login shell. +Setting this field to blank causes the system +to select the default login shell. +.IP "\fB-u \fIuid\fR" +The numerical value of the user's ID. +This value must be unique, unless the \fI-o\fR option is used. +The value must be non-negative. +Values between 0 and 99 are typically reserved for system accounts. +Any files which the user owns and which are located in the directory +tree rooted at the user's home directory will have the file user ID +changed automatically. +Files outside of the user's home directory must be altered manually. +.SH CAVEATS +\fBusermod\fR will not allow you to change the name of a user who is +logged in. +You must make certain that the named user is not executing any processes +when this command is being executed if the user's numerical user ID is +being changed. +You must change the owner of any crontab files manually. +You must change the owner of any at jobs manually. +You must make any changes involving NIS on the NIS server. +.SH FILES +/etc/passwd \- user account information +.br +/etc/shadow \- secure user account information +.br +/etc/group \- group information +.SH SEE ALSO +.BR chfn (1), +.BR chsh (1), +.BR crypt (3), +.BR groupadd (8), +.BR groupdel (8), +.BR groupmod (8), +.BR passwd (1), +.BR useradd (8), +.BR userdel (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@bga.com) diff --git a/man/vipw.8 b/man/vipw.8 new file mode 100644 index 00000000..c8d3b3d4 --- /dev/null +++ b/man/vipw.8 @@ -0,0 +1,29 @@ +.\" $Id: vipw.8,v 1.2 1997/12/14 20:07:22 marekm Exp $ +.TH VIPW 8 "26 Sep 1997" +.SH NAME +vipw, vigr \- edit the password, group, shadow-password, or shadow-group file. +.SH SYNOPSIS +.BR vipw " [-s]" +.br +.BR vigr " [-s]" +.SH DESCRIPTION +.BR vipw " and " vigr +will edit the files +.IR /etc/passwd " and " /etc/group ", respectively." +With the +.B -s +flag, they will edit the shadow versions of those files, +.IR /etc/shadow " and " /etc/gshadow ", respectively. +The programs will set the appropriate locks to prevent file corruption. + +When looking for an editor, the programs will first try the +environment variable +.BR VISUAL , +then the environment variable +.BR EDITOR , +and finally the default editor, +.BR vi . +.SH "SEE ALSO" +.BR passwd (5), +.BR group (5), +.BR shadow (5) diff --git a/missing b/missing new file mode 100755 index 00000000..cbe2b0ef --- /dev/null +++ b/missing @@ -0,0 +1,188 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997 Free Software Foundation, Inc. +# Franc,ois Pinard , 1996. + +# 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, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing - GNU libit 0.0" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`configure.in'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`configure.in'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`configure.in'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER([^):]*:\([^)]*\)).*/\1/p' configure.in` + if test -z "$files"; then + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^):]*\)).*/\1/p' configure.in` + test -z "$files" || files="$files.in" + else + files=`echo "$files" | sed -e 's/:/ /g'` + fi + test -z "$files" && files="config.h.in" + touch $files + ;; + + automake) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print \ + | sed 's/^\(.*\).am$/touch \1.in/' \ + | sh + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 00000000..61cd1d95 --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.3 1998/01/29 23:22:23 marekm Exp $ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/old/Makefile.am b/old/Makefile.am new file mode 100644 index 00000000..7c0fe142 --- /dev/null +++ b/old/Makefile.am @@ -0,0 +1,7 @@ +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + +EXTRA_DIST = Makefile.linux Makefile.sun4 Makefile.svr4 Makefile.xenix \ + config.h.linux config.h.sun4 config.h.svr4 config.h.xenix \ + orig-config.h pwconv.8 pwconv-old.8 pwconv-old.c pwd.h.m4 \ + pwunconv.8 pwunconv-old.8 pwunconv-old.c scologin.c vipw.8 diff --git a/old/Makefile.in b/old/Makefile.in new file mode 100644 index 00000000..61c95e27 --- /dev/null +++ b/old/Makefile.in @@ -0,0 +1,198 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +EXTRA_DIST = Makefile.linux Makefile.sun4 Makefile.svr4 Makefile.xenix \ + config.h.linux config.h.sun4 config.h.svr4 config.h.xenix \ + orig-config.h pwconv.8 pwconv-old.8 pwconv-old.c pwd.h.m4 \ + pwunconv.8 pwunconv-old.8 pwunconv-old.c scologin.c vipw.8 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps old/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = old + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir info dvi installcheck install-exec install-data \ +install uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/old/Makefile.linux b/old/Makefile.linux new file mode 100644 index 00000000..a2bbaf8d --- /dev/null +++ b/old/Makefile.linux @@ -0,0 +1,751 @@ +# +# Copyright 1988 - 1994, Julianne Frances Haugh +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of Julianne F. Haugh nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# %W% %U% - Shadow password system (Linux) +# +# $Id: Makefile.linux,v 1.2 1997/05/01 23:11:54 marekm Exp $ +# +SHELL = /bin/sh + +# +# Set this flag to decide what level of code "get" returns. +# The base USENET release was release 1. It is no longer supported. +# The version with the utilities added was release 2. It is now unsupported. +# The version with database-like file access is release 3. +RELEASE = 3 +VERSION = ver3.3.2 +GFLAGS = -n $(VERSION) +GET = get_file + +# Define the directory login is copied to. Linux uses /bin. +LOGINDIR = /bin + +# Define any special libraries required to access the directory routines. +# Linux does not use any special libraries. +NDIR = + +# Define some stuff for Cracklib. This assumes that libcracklib.a is +# in a system directory. +# Add -DPWC_HIST to check password history using TS&SzS cracklib +# CRACKDEF='-DUSE_CRACKLIB' +# CRACKLIB=-lcrack + +# Pick your favorite C compiler and tags command +CC = gcc +TAGS = ctags + +# OS. This is Linux. +OS = -DUSG -DLINUX + +# Do you have to do ranlib (probably SUN, BSD and XENIX)? +RANLIB = ranlib +# RANLIB = echo + +# Configuration Flags +# +# DEST_INCLUDE_DIR - local include files +# LIBS - system libraries +# -lsocket - needed for TCP/IP and possibly SYSLOG +# -ldbm or -lndbm - needed for DBM support +# -lcrypt - needed for SCO crypt() functions +# CFLAGS - C compiler flags +# -DLAI_TCP - needed for SCO Xenix Lachman TCP/IP + +prefix=/ +exec_prefix=$(prefix) +bindir=$(exec_prefix)/bin +sbindir=$(exec_prefix)/sbin +usrbindir=$(exec_prefix)/usr/bin +usrsbindir=$(exec_prefix)/usr/sbin +includedir=$(prefix)/usr/include +libdir=$(prefix)/usr/lib +mandir=$(prefix)/usr/man +man1dir=$(mandir)/man1 +man3dir=$(mandir)/man3 +man4dir=$(mandir)/man4 +man5dir=$(mandir)/man5 +man8dir=$(mandir)/man8 + +login_perms=-m755 +# If you need "exec login", comment out the above line and uncomment below +#login_perms=-m4755 + +#DEST_INCLUDE_DIR = /usr/local/include +DEST_INCLUDE_DIR = $(includedir) + +# Dirty hack to avoid name collisions (programs linked with libshadow +# could have their own xmalloc/xstrdup, these names are quite common). +# Don't look. --marekm +#HACK = -Dxmalloc=libshadow_xmalloc -Dxstrdup=libshadow_xstrdup +# Flags for Linux +CFLAGS = -O2 -fomit-frame-pointer -Wall $(CRACKDEF) $(OS) $(HACK) +LIBS = #-ldbm #-lskey +#LIBSHADOW = libshadow.a +LIBSHADOW = shlib/libshadow.so +STATIC = -static +LDFLAGS = -s +LTFLAGS = + +# Where the login.defs file will be copied. Must agree with config.h +DEST_LOGIN_DEFS = /etc/login.defs + +# Rules for .L (lint) files. +.SUFFIXES: .L +LINT = lint +LINTFLAGS = $(OS) -Dlint + +.c.L: + $(LINT) -pxu $(LINTFLAGS) $*.c > $*.L + +LOBJS = lmain.o login.o env.o valid.o setup.o shell.o age.o \ + utmp.o sub.o mail.o motd.o log.o ttytype.o failure.o \ + tz.o console.o hushed.o login_access.o setugid.o \ + chowntty.o ulimit.o + +LSRCS = lmain.c login.c env.c valid.c setup.c shell.c age.c \ + utmp.c sub.c mail.c motd.c log.c ttytype.c failure.c \ + tz.c console.c hushed.c login_access.c setugid.c \ + chowntty.c ulimit.c + +SOBJS = smain.o env.o entry.o setup.o shell.o \ + sub.o mail.o motd.o sulog.o age.o tz.o hushed.o setugid.o \ + suauth.o console.o ulimit.o + +SSRCS = smain.c env.c entry.c setup.c shell.c \ + pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \ + tz.c hushed.c setugid.c suauth.c console.c ulimit.c + +POBJS = passwd.o obscure.o ulimit.o +PSRCS = passwd.c obscure.c ulimit.c + +GPSRCS = gpmain.c + +GPOBJS = gpmain.o + +PWOBJS = pwconv.o + +PWSRCS = pwconv.c pwent.c shadow.c pwpack.c rad64.c + +PWUNOBJS = pwunconv.o + +PWUNSRCS = pwunconv.c pwent.c shadow.c pwpack.c rad64.c + +SULOGOBJS = sulogin.o entry.o env.o age.o setup.o \ + valid.o shell.o tz.o setugid.o ulimit.o + +SULOGSRCS = sulogin.c entry.c env.c age.c pwent.c setup.c \ + shadow.c shell.c valid.c pwpack.c tz.c setugid.c ulimit.c + +MKPWDOBJS = mkpasswd.o + +MKPWDSRCS = mkpasswd.c + +NGSRCS = newgrp.c env.c shell.c + +NGOBJS = newgrp.o env.o shell.o + +CHFNSRCS = chfn.c fields.c ulimit.c +CHFNOBJS = chfn.o fields.o ulimit.o +CHSHSRCS = chsh.c fields.c ulimit.c +CHSHOBJS = chsh.o fields.o ulimit.o +CHAGEOBJS = chage.o fields.o +CHAGESRCS = chage.c fields.c +CHPASSOBJS = chpasswd.o +CHPASSSRCS = chpasswd.c +DPSRCS = dpmain.c +DPOBJS = dpmain.o + +ALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \ + motd.c obscure.c passwd.c pwconv.c pwent.c pwunconv.c getpass.c \ + setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \ + utmp.c valid.c port.c newgrp.c gpmain.c grent.c mkpasswd.c pwpack.c \ + chfn.c chsh.c chage.c rad64.c encrypt.c chpasswd.c shadowio.c pwio.c \ + newusers.c groupio.c fields.c pwdbm.c grpack.c grdbm.c sppack.c \ + spdbm.c dpmain.c gshadow.c gsdbm.c gspack.c sgroupio.c useradd.c \ + userdel.c patchlevel.h usermod.c copydir.c mkrmdir.c groupadd.c \ + groupdel.c groupmod.c tz.c console.c hushed.c getdef.c scologin.c \ + logoutd.c groups.c pwauth.c lockpw.c chowndir.c rename.c + +FILES1 = LICENSE README patchlevel.h newgrp.c Makefile config.h pwunconv.c obscure.c \ + age.c id.c + +FILES2 = passwd.c port.c lmain.c sulogin.c pwpack.c dialup.c expiry.c \ + gshadow.h + +FILES3 = chfn.c chsh.c smain.c faillog.c pwconv.c shadow.c pwck.c utent.c + +FILES4 = gpmain.c chage.c pwent.c valid.c setup.c entry.c ttytype.c port.h + +FILES5 = pwio.c encrypt.c chpasswd.c newusers.c rad64.c dialchk.c faillog.h \ + pwdbm.c grdbm.c gshadow.c sppack.c grpck.c + +FILES6 = gspack.c spdbm.c lastlog.h shell.c login.c sub.c dpmain.c mail.c \ + env.c pwd.h.m4 grpack.c shadow.h log.c grent.c motd.c dialup.h \ + fields.c gsdbm.c utmp.c failure.c + +FILES7 = groupio.c shadowio.c sgroupio.c groups.c copydir.c mkrmdir.c \ + mkpasswd.c pwauth.c pwauth.h lastlog.c + +FILES8 = useradd.c usermod.c login.defs rename.c + +FILES9 = groupadd.c groupdel.c groupmod.c tz.c console.c hushed.c getdef.c \ + scologin.c logoutd.c sulog.c getpass.c userdel.c lockpw.c chowndir.c + +FILES_SUN4 = Makefile.sun4 README.sun4 config.h.sun4 +FILES_SVR4 = Makefile.svr4 config.h.svr4 +FILES_LINUX = Makefile.linux config.h.linux + +MAN_1 = chage.1 chfn.1 chsh.1 id.1 login.1 newgrp.1 passwd.1 su.1 \ + useradd.1 userdel.1 usermod.1 groupadd.1 groupdel.1 groupmod.1 \ + groups.1 pwck.1 grpck.1 +MAN_3 = shadow.3 pwauth.3 +MAN_4 = # faillog.4 passwd.4 porttime.4 shadow.4 +MAN_5 = login.5 faillog.5 passwd.5 porttime.5 shadow.5 +MAN_8 = chpasswd.8 dpasswd.8 faillog.8 newusers.8 pwconv.8 pwunconv.8 \ + sulogin.8 mkpasswd.8 logoutd.8 pwauth.8 lastlog.8 + +DOCS1 = $(MAN_1) $(MAN_3) $(MAN_4) +DOCS2 = $(MAN_5) $(MAN_8) +DOCS = $(DOCS1) $(DOCS2) + +BINS = su login login-static pwconv pwunconv passwd sulogin faillog newgrp \ + sg gpasswd mkpasswd chfn chsh chage chpasswd newusers dpasswd id \ + useradd userdel usermod groupadd groupdel groupmod $(SCOLOGIN) \ + logoutd groups pwck grpck lastlog expiry + +all: Linux $(BINS) $(DOCS) + +# +# Linux has its own /usr/include/shadow.h. Use it instead. +# +SHADOW = /usr/include/shadow.h +PWD = /usr/include/pwd.h +Linux: + -mv shadow.h oldshadow.h + touch Linux + +$(BINS): Linux + +.PRECIOUS: libshadow.a + +LIBOBJS = dialchk.o dialup.o encrypt.o salt.o md5crypt.o md5.o getdef.o \ + getpass.o commonio.o grdbm.o grent.o groupio.o grpack.o gshadow.o \ + gsdbm.o gspack.o sgroupio.o port.o pwdbm.o pwent.o pwio.o pwpack.o \ + pwauth.o rad64.o spdbm.o shadow.o shadowio.o sppack.o lockpw.o \ + rename.o utent.o list.o strtoday.o basename.o isexpired.o xmalloc.o + +libshadow.a: $(LIBOBJS) + $(AR) rc libshadow.a $^ + $(RANLIB) libshadow.a + +shlib/libshadow.so: $(LIBOBJS) + cd shlib && \ + $(MAKE) CC=$(CC) CFLAGS="$(CFLAGS)" LIBOBJS="$(LIBOBJS)" libshadow.so + +old-libshadow.a: \ + libshadow.a(dialchk.o) \ + libshadow.a(dialup.o) \ + libshadow.a(encrypt.o) \ + libshadow.a(salt.o) \ + libshadow.a(md5crypt.o) \ + libshadow.a(md5.o) \ + libshadow.a(getdef.o) \ + libshadow.a(getpass.o) \ + libshadow.a(commonio.o) \ + libshadow.a(grdbm.o) \ + libshadow.a(grent.o) \ + libshadow.a(groupio.o) \ + libshadow.a(grpack.o) \ + libshadow.a(gshadow.o) \ + libshadow.a(gsdbm.o) \ + libshadow.a(gspack.o) \ + libshadow.a(sgroupio.o) \ + libshadow.a(port.o) \ + libshadow.a(pwdbm.o) \ + libshadow.a(pwent.o) \ + libshadow.a(pwio.o) \ + libshadow.a(pwpack.o) \ + libshadow.a(pwauth.o) \ + libshadow.a(rad64.o) \ + libshadow.a(spdbm.o) \ + libshadow.a(shadow.o) \ + libshadow.a(shadowio.o) \ + libshadow.a(sppack.o) \ + libshadow.a(lockpw.o) \ + libshadow.a(rename.o) \ + libshadow.a(utent.o) \ + libshadow.a(list.o) \ + libshadow.a(strtoday.o) \ + libshadow.a(basename.o) \ + libshadow.a(isexpired.o) \ + libshadow.a(xmalloc.o) + $(RANLIB) libshadow.a + +# these two (from the original Makefile) don't work on Linux, see below +# +#save: +# [ ! -d save ] && mkdir save +# -cp $(LOGINDIR)/login save +# -cp /etc/mkpasswd /etc/pwconv /etc/pwunconv /etc/sulogin /etc/chpasswd \ +# /etc/newusers /etc/useradd /etc/userdel /etc/usermod \ +# /etc/groupadd /etc/groupdel /etc/groupmod /etc/logoutd \ +# /etc/login.defs /etc/pwck /etc/grpck /bin/expiry save +# -cp /bin/su /bin/passwd /bin/gpasswd /bin/dpasswd /bin/faillog \ +# /bin/newgrp /bin/chfn /bin/chsh /bin/chage /bin/id \ +# /bin/scologin save +# -cp $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/gshadow.h save +# +#restore: +# [ -d save ] +# -(cd save ; cp login $(LOGINDIR) ) +# -(cd save ; -cp mkpasswd pwconv pwunconv sulogin chpasswd \ +# newusers useradd userdel usermod groupadd groupdel groupmod \ +# logoutd login.defs pwck grpck /etc) +# -(cd save ; cp su passwd gpasswd dpasswd faillog newgrp chfn chsh \ +# chage id scologin expiry /bin) +# -(cd save ; cp gshadow.h dialup.h $(DEST_INCLUDE_DIR) ) + +# automatic pathnames detection, thanks to Rafal Maszkowski +# (not tested by me; it is best to have a good backup anyway... --marekm) + +save: + -( [ ! -d save ] && mkdir save ) + -( whereis -b id groups chfn chsh chage login login-static sulogin \ + newusers useradd userdel usermod groupadd groupdel \ + groupmod pwck grpck lastlog faillog dpasswd chpasswd \ + logoutd mkpasswd pwconv pwunconv su passwd gpasswd \ + newgrp expiry | awk '{if ($$2!="") print $$2}' > save/list ) + -( cat save/list | awk '{print "cp -p", $$1, "save"}' | sh ) + -cp -p /etc/login.defs save + -cp -p $(includedir)/dialup.h $(includedir)/gshadow.h save + -cp -p $(libdir)/libshadow.a save + +restore: + [ -d save ] + -( cd save ; cp -p login.defs /etc ; \ + cp -p dialup.h gshadow.h $(includedir) ; \ + cp -p libshadow.a $(libdir) ) + -( cat save/list | awk '{ last=split($$1,comp,"/"); print "cp -p", comp[last], $$1}' | sh) + + +install: all + test -f /etc/login.defs || cp login.defs.linux $(DEST_LOGIN_DEFS) + install -d $(man1dir) + install -d $(man3dir) +# install -d $(man4dir) + install -d $(man5dir) + install -d $(man8dir) + install -d $(usrbindir) + install -d $(usrsbindir) + install -d $(LOGINDIR) + install -d $(bindir) + install -d $(includedir) + install -d $(libdir) + install -m 644 $(MAN_1) $(man1dir)/ + install -m 644 $(MAN_3) $(man3dir)/ +# install -m 644 $(MAN_4) $(man4dir)/ + install -m 644 $(MAN_5) $(man5dir)/ + install -m 644 $(MAN_8) $(man8dir)/ +# install -m 755 id groups $(usrbindir)/ + install -m 4755 chfn chsh chage $(usrbindir)/ + install $(login_perms) login $(LOGINDIR)/login +# install $(login_perms) login-static $(LOGINDIR)/login-static + install -m 755 sulogin $(sbindir)/sulogin + install -m 755 newusers \ + useradd userdel usermod groupadd groupdel groupmod \ + pwck grpck lastlog faillog dpasswd \ + chpasswd logoutd mkpasswd pwconv pwunconv $(usrsbindir)/ + install -m 4755 su $(bindir)/ + install -m 4755 passwd gpasswd newgrp expiry $(usrbindir)/ + ln -sf $(usrbindir)/newgrp $(bindir)/sg + install -m 644 gshadow.h dialup.h $(includedir)/ + install -m 644 libshadow.a $(libdir)/ + $(RANLIB) $(libdir)/libshadow.a + +lint: su.lint login.lint pwconv.lint pwunconv.lint passwd.lint sulogin.lint \ + faillog.lint newgrp.lint gpasswd.lint mkpasswd.lint chfn.lint \ + chsh.lint chage.lint dpasswd.lint id.lint useradd.lint userdel.lint \ + usermod.lint groupadd.lint groupdel.lint groupmod.lint logoutd.lint \ + pwck.lint grpck.lint expiry.lint \ + $(ALLSRCS:.c=.L) + +tags: $(ALLSRCS) + $(TAGS) $(ALLSRCS) + +README: + [ -f s.README ] && $(GET) $(GFLAGS) s.README + +$(DOCS): + [ -f s.$@ ] && $(GET) $(GFLAGS) s.$@ + +login.defs: + [ -f s.login.defs ] && $(GET) $(GFLAGS) s.login.defs + +Makefile.sun4: + [ -f s.Makefile.sun4 ] && $(GET) $(GFLAGS) s.Makefile.sun4 + +Makefile.svr4: + [ -f s.Makefile.svr4 ] && $(GET) $(GFLAGS) s.Makefile.svr4 + +README.sun4: + [ -f s.README.sun4 ] && $(GET) $(GFLAGS) s.README.sun4 + +config.h.sun4: + [ -f s.config.h.sun4 ] && $(GET) $(GFLAGS) s.config.h.sun4 + +config.h.svr4: + [ -f s.config.h.svr4 ] && $(GET) $(GFLAGS) s.config.h.svr4 + +login: $(LOBJS) $(LIBSHADOW) + $(CC) -o login $(LDFLAGS) $(LOBJS) $(LIBSHADOW) $(LIBS) + +login-static: $(LOBJS) libshadow.a + $(CC) -o login-static $(STATIC) $(LDFLAGS) $(LOBJS) $(LIBSHADOW) $(LIBS) + +login.lint: $(LSRCS) + $(LINT) $(LINTFLAGS) $(LSRCS) > login.lint + +su: $(SOBJS) $(LIBSHADOW) + $(CC) -o su $(LDFLAGS) $(SOBJS) $(LIBSHADOW) $(LIBS) + +su.lint: $(SSRCS) + $(LINT) $(LINTFLAGS) -DSU $(SSRCS) > su.lint + +passwd: $(POBJS) $(LIBSHADOW) + $(CC) -o passwd $(LDFLAGS) $(POBJS) $(LIBSHADOW) $(LIBS) $(CRACKLIB) + +passwd.lint: $(PSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PSRCS) > passwd.lint + +gpasswd: $(GPOBJS) $(LIBSHADOW) + $(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) $(LIBSHADOW) $(LIBS) + +gpasswd.lint: $(GPSRCS) + $(LINT) $(LINTFLAGS) $(GPSRCS) > gpasswd.lint + +dpasswd: $(DPOBJS) $(LIBSHADOW) + $(CC) -o dpasswd $(LDFLAGS) $(DPOBJS) $(LIBSHADOW) $(LIBS) + +dpasswd.lint: $(DPSRCS) + $(LINT) $(LINTFLAGS) $(DPSRCS) > dpasswd.lint + +pwconv: $(PWOBJS) $(LIBSHADOW) config.h + $(CC) -o pwconv $(LDFLAGS) $(PWOBJS) $(LIBSHADOW) $(LIBS) + +pwconv.lint: $(PWSRCS) config.h + $(LINT) $(LINTFLAGS) -DPASSWD $(PWSRCS) > pwconv.lint + +pwunconv: $(PWUNOBJS) $(LIBSHADOW) config.h + $(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) $(LIBSHADOW) $(LIBS) + +pwunconv.lint: $(PWUNSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PWUNSRCS) > pwunconv.lint + +sulogin: $(SULOGOBJS) $(LIBSHADOW) + $(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) $(LIBSHADOW) $(LIBS) + +sulogin.lint: $(SULOGSRCS) + $(LINT) $(LINTFLAGS) $(SULOGSRCS) > sulogin.lint + +faillog: faillog.o + $(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS) + +faillog.lint: faillog.c faillog.h config.h + $(LINT) $(LINTFLAGS) faillog.c > faillog.lint + +lastlog: lastlog.o + $(CC) -o lastlog $(LDFLAGS) lastlog.o $(LIBS) + +lastlog.lint: lastlog.c config.h lastlog.h + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > lastlog.lint + +mkpasswd: $(MKPWDOBJS) $(LIBSHADOW) + $(CC) -o mkpasswd $(LDFLAGS) $(MKPWDOBJS) $(LIBSHADOW) $(LIBS) + +mkpasswd.lint: $(MKPWDSRCS) + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > mkpasswd.lint + +newgrp: $(NGOBJS) $(LIBSHADOW) + $(CC) -o newgrp $(LDFLAGS) $(NGOBJS) $(LIBSHADOW) $(LIBS) + +newgrp.lint: $(NGSRCS) + $(LINT) $(LINTFLAGS) $(NGSRCS) > newgrp.lint + +sg: newgrp + rm -f sg + ln newgrp sg + +sg.lint: newgrp.lint + ln newgrp.lint sg.lint + +chfn: $(CHFNOBJS) $(LIBSHADOW) + $(CC) -o chfn $(LDFLAGS) $(CHFNOBJS) $(LIBSHADOW) $(LIBS) + +chfn.lint: $(CHFNSRCS) + $(LINT) $(LINTFLAGS) $(CHFNSRCS) > chfn.lint + +chsh: $(CHSHOBJS) $(LIBSHADOW) + $(CC) -o chsh $(LDFLAGS) $(CHSHOBJS) $(LIBSHADOW) $(LIBS) + +chsh.lint: $(CHSHSRCS) + $(LINT) $(LINTFLAGS) $(CHSHSRCS) > chsh.lint + +chage: $(CHAGEOBJS) $(LIBSHADOW) + $(CC) -o chage $(LDFLAGS) $(CHAGEOBJS) $(LIBSHADOW) $(LIBS) + +chage.lint: $(CHAGESRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(CHAGESRCS) > chage.lint + +chpasswd: $(CHPASSOBJS) $(LIBSHADOW) + $(CC) -o chpasswd $(LDFLAGS) $(CHPASSOBJS) $(LIBSHADOW) $(LIBS) + +chpasswd.lint: $(CHPASSSRCS) + $(LINT) $(LINTFLAGS) $(CHPASSSRCS) > chpasswd.lint + +newusers: newusers.o $(LIBSHADOW) + $(CC) -o newusers $(LDFLAGS) newusers.o $(LIBSHADOW) $(LIBS) + +newusers.lint: newusers.c + $(LINT) $(LINTFLAGS) newusers.c > newusers.lint + +id: id.o $(LIBSHADOW) + $(CC) -o id $(LDFLAGS) id.o $(LIBSHADOW) $(LIBS) + +id.lint: id.c + $(LINT) $(LINTFLAGS) id.c > id.lint + +groups: groups.o $(LIBSHADOW) + $(CC) -o groups $(LDFLAGS) groups.o $(LIBSHADOW) $(LIBS) + +groups.lint: groups.c + $(LINT) $(LINTFLAGS) groups.c > groups.lint + +useradd: useradd.o copydir.o mkrmdir.o $(LIBSHADOW) + $(CC) -o useradd $(LDFLAGS) useradd.o copydir.o mkrmdir.o \ + $(LIBSHADOW) $(LIBS) $(NDIR) + +useradd.lint: useradd.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) useradd.c copydir.c mkrmdir.c > useradd.lint + +userdel: userdel.o copydir.o mkrmdir.o $(LIBSHADOW) + $(CC) -o userdel $(LDFLAGS) userdel.o copydir.o mkrmdir.o \ + $(LIBSHADOW) $(LIBS) $(NDIR) + +userdel.lint: userdel.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) userdel.c copydir.c mkrmdir.c > userdel.lint + +usermod: usermod.o copydir.o mkrmdir.o chowndir.o $(LIBSHADOW) + $(CC) -o usermod $(LDFLAGS) usermod.o copydir.o mkrmdir.o \ + chowndir.o $(LIBSHADOW) $(LIBS) $(NDIR) + +usermod.lint: usermod.c copydir.c mkrmdir.c chowndir.c + $(LINT) $(LINTFLAGS) usermod.c copydir.c mkrmdir.c \ + chowndir.c > usermod.lint + +groupadd: groupadd.o chkgname.o $(LIBSHADOW) + $(CC) -o groupadd $(LDFLAGS) groupadd.o chkgname.o $(LIBSHADOW) $(LIBS) + +groupadd.lint: groupadd.c + $(LINT) $(LINTFLAGS) groupadd.c > groupadd.lint + +groupdel: groupdel.o $(LIBSHADOW) + $(CC) -o groupdel $(LDFLAGS) groupdel.o $(LIBSHADOW) $(LIBS) + +groupdel.lint: groupdel.c + $(LINT) $(LINTFLAGS) groupdel.c > groupdel.lint + +groupmod: groupmod.o chkgname.o $(LIBSHADOW) + $(CC) -o groupmod $(LDFLAGS) groupmod.o chkgname.o $(LIBSHADOW) $(LIBS) + +groupmod.lint: groupmod.c + $(LINT) $(LINTFLAGS) groupmod.c > groupmod.lint + +logoutd: logoutd.o $(LIBSHADOW) + $(CC) -o logoutd $(LDFLAGS) logoutd.o $(LIBSHADOW) + +logoutd.lint: logoutd.c + $(LINT) $(LINTFLAGS) logoutd.c > logoutd.lint + +pwck: pwck.o $(LIBSHADOW) + $(CC) -o pwck $(LDFLAGS) pwck.o $(LIBSHADOW) $(LIBS) + +pwck.lint: pwck.c + $(LINT) $(LINTFLAGS) pwck.c > pwck.lint + +grpck: grpck.o $(LIBSHADOW) + $(CC) -o grpck $(LDFLAGS) grpck.o $(LIBSHADOW) $(LIBS) + +grpck.lint: grpck.c + $(LINT) $(LINTFLAGS) grpck.c > grpck.lint + +expiry: expiry.o age.o setugid.o $(LIBSHADOW) + $(CC) -o expiry $(LDFLAGS) expiry.o age.o setugid.o $(LIBSHADOW) $(LIBS) + +expiry.lint: expiry.c + $(LINT) $(LINTFLAGS) expiry.c > expiry.lint + +sulog.o: config.h + +scologin: scologin.o + $(CC) -o scologin $(LDFLAGS) scologin.o -lsocket + +passwd.o: config.h $(SHADOW) $(PWD) pwauth.h +lmain.o: config.h lastlog.h faillog.h $(PWD) pwauth.h +smain.o: config.h lastlog.h $(PWD) $(SHADOW) pwauth.h +sub.o: $(PWD) +setup.o: config.h $(PWD) +mkrmdir.o: config.h +utmp.o: config.h +mail.o: config.h +motd.o: config.h +age.o: config.h gshadow.h $(PWD) +log.o: config.h lastlog.h $(PWD) +lastlog.o: lastlog.h +shell.o: config.h +entry.o: config.h $(SHADOW) $(PWD) +hushed.o: config.h $(PWD) +valid.o: config.h $(PWD) +failure.o: faillog.h config.h +faillog.o: faillog.h config.h $(PWD) +newgrp.o: config.h gshadow.h $(SHADOW) $(PWD) +mkpasswd.o: config.h gshadow.h $(SHADOW) $(PWD) +gpmain.o: config.h gshadow.h $(PWD) +chfn.o: config.h $(PWD) +chsh.o: config.h $(PWD) +chage.o: config.h $(SHADOW) $(PWD) +pwconv.o: config.h $(SHADOW) +pwunconv.o: config.h $(SHADOW) $(PWD) +chpasswd.o: config.h $(SHADOW) $(PWD) +id.o: $(PWD) +newusers.o: config.h $(SHADOW) $(PWD) +dpmain.o: config.h dialup.h +useradd.o: config.h gshadow.h $(SHADOW) $(PWD) pwauth.h +userdel.o: config.h gshadow.h $(SHADOW) $(PWD) pwauth.h +usermod.o: config.h gshadow.h $(SHADOW) $(PWD) pwauth.h +groupadd.o: config.h gshadow.h +groupdel.o: config.h gshadow.h +groupmod.o: config.h gshadow.h +logoutd.o: config.h +sulogin.o: config.h pwauth.h +copydir.o: config.h +chowndir.o: config.h +pwck.o: config.h $(SHADOW) $(PWD) +grpck.o: config.h gshadow.h $(PWD) + +$(LIBSHADOW)(shadow.o): $(SHADOW) config.h +$(LIBSHADOW)(shadowio.o): $(SHADOW) config.h +$(LIBSHADOW)(grent.o): config.h gshadow.h +$(LIBSHADOW)(groupio.o): config.h +$(LIBSHADOW)(sgroupio.o): config.h gshadow.h +$(LIBSHADOW)(dialup.o): dialup.h +$(LIBSHADOW)(dialchk.o): dialup.h config.h +$(LIBSHADOW)(getdef.o): config.h +$(LIBSHADOW)(pwdbm.o): config.h $(PWD) +$(LIBSHADOW)(spdbm.o): config.h $(SHADOW) +$(LIBSHADOW)(grdbm.o): config.h +$(LIBSHADOW)(gshadow.o): config.h +$(LIBSHADOW)(gsdbm.o): config.h gshadow.h +$(LIBSHADOW)(pwauth.o): config.h pwauth.h +$(LIBSHADOW)(pwpack.o): config.h $(PWD) +$(LIBSHADOW)(pwent.o): config.h $(PWD) +$(LIBSHADOW)(pwio.o): $(PWD) config.h +$(LIBSHADOW)(getpass.o): config.h +$(LIBSHADOW)(encrypt.o): config.h +$(LIBSHADOW)(salt.o): config.h +$(LIBSHADOW)(md5crypt.o): config.h +$(LIBSHADOW)(md5.o): config.h +$(LIBSHADOW)(port.o): port.h +$(LIBSHADOW)(rad64.o): config.h +$(LIBSHADOW)(lockpw.o): +$(LIBSHADOW)(rename.o): config.h +$(LIBSHADOW)(gspack.o): config.h gshadow.h +$(LIBSHADOW)(list.o): +$(LIBSHADOW)(strtoday.o): config.h +$(LIBSHADOW)(xmalloc.o): +$(LIBSHADOW)(basename.o): +$(LIBSHADOW)(isexpired.o): config.h $(SHADOW) +$(LIBSHADOW)(commonio.o): + +shadow.h: + -rm -f Linux + -mv oldshadow.h shadow.h + +clean: shadow.h + -rm -f *.o a.out core npasswd nshadow *.pag *.dir + +clobber: clean + -rm -f $(BINS) *.lint *.L libshadow.a + +nuke: clobber + -for file in * ; do \ + if [ -f s.$$file -a ! -f p.$$file ] ; then \ + rm -f $$file ;\ + fi ;\ + done + +# File lists for this are out of sync with reality... --marekm +# +#shar: login.sh.01 login.sh.02 login.sh.03 login.sh.04 login.sh.05 \ +# login.sh.06 login.sh.07 login.sh.08 login.sh.09 login.sh.10 \ +# login.sh.11 login.sh.12 +# +#login.sh.01: $(FILES1) Makefile +# shar -Dc $(FILES1) > login.sh.01 +# +#login.sh.02: $(FILES2) Makefile +# shar -Dc $(FILES2) > login.sh.02 +# +#login.sh.03: $(FILES3) Makefile +# shar -Dc $(FILES3) > login.sh.03 +# +#login.sh.04: $(FILES4) Makefile +# shar -Dc $(FILES4) > login.sh.04 +# +#login.sh.05: $(FILES5) Makefile +# shar -Dc $(FILES5) > login.sh.05 +# +#login.sh.06: $(FILES6) Makefile +# shar -Dc $(FILES6) > login.sh.06 +# +#login.sh.07: $(FILES7) Makefile +# shar -Dc $(FILES7) > login.sh.07 +# +#login.sh.08: $(FILES8) Makefile +# shar -Dc $(FILES8) > login.sh.08 +# +#login.sh.09: $(FILES9) Makefile +# shar -Dc $(FILES9) > login.sh.09 +# +#login.sh.10: $(DOCS1) Makefile +# shar -Dc $(DOCS1) > login.sh.10 +# +#login.sh.11: $(DOCS2) Makefile +# shar -Dc $(DOCS2) > login.sh.11 +# +#login.sh.12: $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) Makefile +# shar -Dc $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) > login.sh.12 diff --git a/old/Makefile.sun4 b/old/Makefile.sun4 new file mode 100644 index 00000000..0b9e94a6 --- /dev/null +++ b/old/Makefile.sun4 @@ -0,0 +1,685 @@ +# +# Copyright 1988 - 1994, Julianne Frances Haugh +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of Julianne F. Haugh nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# %W% %U% - Shadow password system (SunOS 4.1.1 version) +# +# $Id: Makefile.sun4,v 1.2 1997/05/01 23:11:55 marekm Exp $ +# +SHELL = /bin/sh + +# +# Set this flag to decide what level of code "get" returns. +# The base USENET release was release 1. It is no longer supported. +# The version with the utilities added was release 2. +# The version with database-like file access is release 3. +RELEASE = 3 +GFLAGS = -t -r$(RELEASE) + +# SunOS 4.1.1 uses /usr/bin +LOGINDIR = /usr/bin + +# SunOS 4.1.1 requires no extra libraries +NDIR = + +# Define some stuff for Cracklib. This assumes that libcracklib.a is +# in a system directory. +# CRACKDEF='-DUSE_CRACKLIB' +# CRACKLIB=-lcrack + +# Pick your favorite C compiler and tags command +CC = /usr/bin/cc +TAGS = ctags + +# SunOS 4.1.1 is SUN4 +OS = -DSUN4 + +# SunOS 4.1.1 uses ranlib +RANLIB = ranlib + +# Configuration Flags +# +# DEST_INCLUDE_DIR - local include files +# LIBS - system libraries +# -lsocket - needed for TCP/IP and possibly SYSLOG +# -ldbm or -lndbm - needed for DBM support +# -lcrypt - needed for SCO crypt() functions +# CFLAGS - C compiler flags +# -DLAI_TCP - needed for SCO Xenix Lachman TCP/IP + +DEST_INCLUDE_DIR = /usr/5include + +# Flags for SunOS 4.1.1 +CFLAGS = -O2 $(OS) -I$(DEST_INCLUDE_DIR) $(CRACKDEF) +LIBS = +LDFLAGS = + +# Library for SunOS 4.1.1 +LIBSEC = libsec.a + +# Names for root user and group, and bin user and group. See your +# /etc/passwd and /etc/group files. This is for SunOS 4.1.1 +RUID = root +RGID = wheel +BUID = bin +BGID = bin + +# Where the login.defs file will be copied. Must agree with config.h +DEST_LOGIN_DEFS = /etc/login.defs + +# SunOS has its own pwd.h, use that one. +PWD = /usr/include/pwd.h + +# Rules for .L (lint) files. +.SUFFIXES: .L +LINT = lint +LINTFLAGS = $(OS) -Dlint + +.c.L: + $(LINT) -pxu $(LINTFLAGS) $*.c > $*.L + +LOBJS = lmain.o login.o env.o valid.o setup.o shell.o age.o \ + utmp.o sub.o mail.o motd.o log.o ttytype.o failure.o \ + tz.o console.o hushed.o + +LSRCS = lmain.c login.c env.c valid.c setup.c shell.c age.c \ + utmp.c sub.c mail.c motd.c log.c ttytype.c failure.c \ + tz.c console.c hushed.c + +SOBJS = smain.o env.o entry.o susetup.o shell.o \ + sub.o mail.o motd.o sulog.o age.o tz.o hushed.o + +SSRCS = smain.c env.c entry.c setup.c shell.c \ + pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \ + tz.c hushed.c + +POBJS = passwd.o obscure.o +PSRCS = passwd.c obscure.c + +GPSRCS = gpmain.c + +GPOBJS = gpmain.o + +PWOBJS = pwconv.o + +PWSRCS = pwconv.c pwent.c shadow.c pwpack.c rad64.c + +PWUNOBJS = pwunconv.o + +PWUNSRCS = pwunconv.c pwent.c shadow.c pwpack.c rad64.c + +SULOGOBJS = sulogin.o entry.o env.o age.o setup.o \ + valid.o shell.o tz.o + +SULOGSRCS = sulogin.c entry.c env.c age.c pwent.c setup.c \ + shadow.c shell.c valid.c pwpack.c tz.c + +MKPWDOBJS = mkpasswd.o + +MKPWDSRCS = mkpasswd.c + +NGSRCS = newgrp.c env.c shell.c + +NGOBJS = newgrp.o env.o shell.o + +CHFNSRCS = chfn.c fields.c +CHFNOBJS = chfn.o fields.o +CHSHSRCS = chsh.c fields.c +CHSHOBJS = chsh.o fields.o +CHAGEOBJS = chage.o fields.o +CHAGESRCS = chage.c fields.c +CHPASSOBJS = chpasswd.o +CHPASSSRCS = chpasswd.c +DPSRCS = dpmain.c +DPOBJS = dpmain.o + +ALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \ + motd.c obscure.c passwd.c pwconv.c pwent.c pwunconv.c getpass.c \ + setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \ + utmp.c valid.c port.c newgrp.c gpmain.c grent.c mkpasswd.c pwpack.c \ + chfn.c chsh.c chage.c rad64.c encrypt.c chpasswd.c shadowio.c pwio.c \ + newusers.c groupio.c fields.c pwdbm.c grpack.c grdbm.c sppack.c \ + spdbm.c dpmain.c gshadow.c gsdbm.c gspack.c sgroupio.c useradd.c \ + userdel.c patchlevel.h usermod.c copydir.c mkrmdir.c groupadd.c \ + groupdel.c groupmod.c tz.c console.c hushed.c getdef.c scologin.c \ + logoutd.c groups.c pwauth.c lockpw.c chowndir.c utent.c + +FILES1 = LICENSE README patchlevel.h newgrp.c Makefile config.h pwunconv.c obscure.c \ + age.c id.c + +FILES2 = passwd.c port.c lmain.c sulogin.c pwpack.c dialup.c expiry.c \ + gshadow.h + +FILES3 = chfn.c chsh.c smain.c faillog.c pwconv.c shadow.c pwck.c utent.c + +FILES4 = gpmain.c chage.c pwent.c valid.c setup.c entry.c ttytype.c port.h + +FILES5 = pwio.c encrypt.c chpasswd.c newusers.c rad64.c dialchk.c faillog.h \ + pwdbm.c grdbm.c gshadow.c sppack.c grpck.c + +FILES6 = gspack.c spdbm.c lastlog.h shell.c login.c sub.c dpmain.c mail.c \ + env.c pwd.h.m4 grpack.c shadow.h log.c grent.c motd.c dialup.h \ + fields.c gsdbm.c utmp.c failure.c + +FILES7 = groupio.c shadowio.c sgroupio.c groups.c copydir.c mkrmdir.c \ + mkpasswd.c pwauth.c pwauth.h lastlog.c + +FILES8 = useradd.c usermod.c login.defs + +FILES9 = groupadd.c groupdel.c groupmod.c tz.c console.c hushed.c getdef.c \ + scologin.c logoutd.c sulog.c getpass.c userdel.c lockpw.c chowndir.c + +FILES_SUN4 = Makefile.sun4 README.sun4 config.h.sun4 +FILES_SVR4 = Makefile.svr4 config.h.svr4 +FILES_LINUX = Makefile.linux config.h.linux + +MAN_1 = chage.1 chfn.1 chsh.1 id.1 login.1 newgrp.1 passwd.1 su.1 \ + useradd.1 userdel.1 usermod.1 groupadd.1 groupdel.1 groupmod.1 \ + groups.1 pwck.1 grpck.1 +MAN_3 = shadow.3 pwauth.3 +MAN_4 = faillog.4 passwd.4 porttime.4 shadow.4 +MAN_5 = login.5 +MAN_8 = chpasswd.8 dpasswd.8 faillog.8 newusers.8 pwconv.8 pwunconv.8 \ + sulogin.8 mkpasswd.8 logoutd.8 pwauth.8 lastlog.8 + +DOCS1 = $(MAN_1) $(MAN_3) $(MAN_4) +DOCS2 = $(MAN_5) $(MAN_8) +DOCS = $(DOCS1) $(DOCS2) + +BINS = su login pwconv pwunconv passwd sulogin faillog newgrp gpasswd \ + mkpasswd chfn chsh chage chpasswd newusers dpasswd id useradd \ + userdel usermod groupadd groupdel groupmod logoutd groups \ + pwck grpck lastlog expiry + +all: $(BINS) $(DOCS) + +.PRECIOUS: libshadow.a + +libshadow.a: \ + libshadow.a(dialchk.o) \ + libshadow.a(dialup.o) \ + libshadow.a(encrypt.o) \ + libshadow.a(getdef.o) \ + libshadow.a(getpass.o) \ + libshadow.a(grdbm.o) \ + libshadow.a(grent.o) \ + libshadow.a(groupio.o) \ + libshadow.a(grpack.o) \ + libshadow.a(gshadow.o) \ + libshadow.a(gsdbm.o) \ + libshadow.a(gspack.o) \ + libshadow.a(sgroupio.o) \ + libshadow.a(port.o) \ + libshadow.a(pwdbm.o) \ + libshadow.a(pwent.o) \ + libshadow.a(pwio.o) \ + libshadow.a(pwpack.o) \ + libshadow.a(pwauth.o) \ + libshadow.a(rad64.o) \ + libshadow.a(spdbm.o) \ + libshadow.a(shadow.o) \ + libshadow.a(shadowio.o) \ + libshadow.a(sppack.o) \ + libshadow.a(lockpw.o) \ + libshadow.a(utent.o) \ + libshadow.a(list.o) \ + libshadow.a(strtoday.o) \ + libshadow.a(basename.o) \ + libshadow.a(isexpired.o) \ + libshadow.a(xmalloc.o) + $(RANLIB) libshadow.a + +libsec: $(LIBSEC)(shadow.o) + $(RANLIB) $(LIBSEC) + +save: + [ ! -d save ] && mkdir save + -cp $(LOGINDIR)/login save + -cp /etc/mkpasswd /etc/pwconv /etc/pwunconv /etc/sulogin /etc/chpasswd \ + /etc/newusers /etc/useradd /etc/userdel /etc/usermod \ + /etc/groupadd /etc/groupdel /etc/groupmod /etc/logoutd \ + /etc/login.defs /etc/pwck /etc/grpck /bin/expiry save + -cp /bin/su /bin/passwd /bin/gpasswd /bin/dpasswd /bin/faillog \ + /bin/newgrp /bin/chfn /bin/chsh /bin/chage /bin/id \ + /bin/scologin save + -cp $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/shadow.h \ + save + +restore: + [ -d save ] + -(cd save ; cp login $(LOGINDIR) ) + -(cd save ; -cp mkpasswd pwconv pwunconv sulogin chpasswd \ + newusers useradd userdel usermod groupadd groupdel groupmod \ + logoutd login.defs pwck grpck /etc) + -(cd save ; cp su passwd gpasswd dpasswd faillog newgrp chfn chsh \ + chage id scologin expiry /bin) + -(cd save ; cp dialup.h shadow.h gshadow.h $(DEST_INCLUDE_DIR) ) + +install: all + strip $(BINS) + cp login $(LOGINDIR)/login + cp mkpasswd /etc + cp pwconv /etc + cp pwunconv /etc + cp sulogin /etc + cp chpasswd /etc + cp newusers /etc + cp useradd /etc + cp userdel /etc + cp usermod /etc + cp groupadd /etc + cp groupdel /etc + cp groupmod /etc + cp logoutd /etc + cp pwck /etc + cp grpck /etc + cp su /bin + cp passwd /bin + cp gpasswd /bin + cp dpasswd /bin + cp faillog /bin + cp newgrp /bin + cp chfn /bin + cp chsh /bin + cp chage /bin + cp id /bin + cp expiry /bin + cp dialup.h shadow.h gshadow.h $(DEST_INCLUDE_DIR) + chown $(RUID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \ + /bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \ + /bin/dpasswd /bin/chsh /bin/chfn /bin/chage /etc/useradd \ + /etc/userdel /etc/usermod /etc/groupadd /etc/groupdel \ + /etc/groupmod /etc/logoutd /etc/pwck /etc/grpck /bin/expiry + chgrp $(RGID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \ + /bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \ + /bin/dpasswd /bin/chsh /bin/chfn /bin/chage /etc/useradd \ + /etc/userdel /etc/usermod /etc/groupadd /etc/groupdel \ + /etc/groupmod /etc/logoutd /etc/pwck /etc/grpck /bin/expiry + chown $(BUID) /bin/faillog /bin/id $(DEST_INCLUDE_DIR)/shadow.h \ + $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/gshadow.h + chgrp $(BGID) /bin/faillog /bin/id $(DEST_INCLUDE_DIR)/shadow.h \ + $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/gshadow.h + chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd \ + /etc/chpasswd /etc/newusers /bin/dpasswd /bin/chage \ + /etc/useradd /etc/userdel /etc/usermod /etc/groupadd \ + /etc/groupdel /etc/groupmod /etc/logoutd /etc/pwck \ + /etc/grpck + chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \ + /bin/newgrp /bin/chfn /bin/chsh /bin/expiry + chmod 711 /bin/faillog /bin/id + chmod 444 $(DEST_INCLUDE_DIR)/shadow.h $(DEST_INCLUDE_DIR)/dialup.h \ + $(DEST_INCLUDE_DIR)/gshadow.h + [ -f $(DEST_LOGIN_DEFS) ] || (cp login.defs $(DEST_LOGIN_DEFS) ; \ + chown $(RUID) $(DEST_LOGIN_DEFS) ; \ + chgrp $(RGID) $(DEST_LOGIN_DEFS) ; \ + chmod 600 $(DEST_LOGIN_DEFS) ) + +lint: su.lint login.lint pwconv.lint pwunconv.lint passwd.lint sulogin.lint \ + faillog.lint newgrp.lint gpasswd.lint mkpasswd.lint chfn.lint \ + chsh.lint chage.lint dpasswd.lint id.lint useradd.lint userdel.lint \ + usermod.lint groupadd.lint groupdel.lint groupmod.lint logoutd.lint \ + pwck.lint grpck.lint expiry.lint \ + $(ALLSRCS:.c=.L) + +tags: $(ALLSRCS) + $(TAGS) $(ALLSRCS) + +README: + [ -f s.README ] && get -t -r$(RELEASE) s.README + +$(DOCS): + [ -f s.$@ ] && get -t -r$(RELEASE) s.$@ + +login.defs: + [ -f s.login.defs ] && get -t -r$(RELEASE) s.login.defs + +Makefile.sun4: + [ -f s.Makefile.sun4 ] && get -t -r$(RELEASE) s.Makefile.sun4 + +README.sun4: + [ -f s.README.sun4 ] && get -t -r$(RELEASE) s.README.sun4 + +config.h.sun4: + [ -f s.config.h.sun4 ] && get -t -r$(RELEASE) s.config.h.sun4 + +login: $(LOBJS) libshadow.a + $(CC) -o login $(LDFLAGS) $(LOBJS) libshadow.a $(LIBS) + +login.lint: $(LSRCS) + $(LINT) $(LINTFLAGS) $(LSRCS) > login.lint + +su: $(SOBJS) libshadow.a + $(CC) -o su $(LDFLAGS) $(SOBJS) libshadow.a $(LIBS) + +su.lint: $(SSRCS) + $(LINT) $(LINTFLAGS) -DSU $(SSRCS) > su.lint + +passwd: $(POBJS) libshadow.a + $(CC) -o passwd $(LDFLAGS) $(POBJS) libshadow.a $(LIBS) $(CRACKLIB) + +passwd.lint: $(PSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PSRCS) > passwd.lint + +gpasswd: $(GPOBJS) libshadow.a + $(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) libshadow.a $(LIBS) + +gpasswd.lint: $(GPSRCS) + $(LINT) $(LINTFLAGS) $(GPSRCS) > gpasswd.lint + +dpasswd: $(DPOBJS) libshadow.a + $(CC) -o dpasswd $(LDFLAGS) $(DPOBJS) libshadow.a $(LIBS) + +dpasswd.lint: $(DPSRCS) + $(LINT) $(LINTFLAGS) $(DPSRCS) > dpasswd.lint + +pwconv: $(PWOBJS) libshadow.a config.h + $(CC) -o pwconv $(LDFLAGS) $(PWOBJS) libshadow.a $(LIBS) + +pwconv.lint: $(PWSRCS) config.h + $(LINT) $(LINTFLAGS) -DPASSWD $(PWSRCS) > pwconv.lint + +pwunconv: $(PWUNOBJS) libshadow.a config.h + $(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) libshadow.a $(LIBS) + +pwunconv.lint: $(PWUNSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PWUNSRCS) > pwunconv.lint + +sulogin: $(SULOGOBJS) libshadow.a + $(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) libshadow.a $(LIBS) + +sulogin.lint: $(SULOGSRCS) + $(LINT) $(LINTFLAGS) $(SULOGSRCS) > sulogin.lint + +faillog: faillog.o + $(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS) + +faillog.lint: faillog.c faillog.h config.h + $(LINT) $(LINTFLAGS) faillog.c > faillog.lint + +lastlog: lastlog.o + $(CC) -o lastlog $(LDFLAGS) lastlog.o $(LIBS) + +lastlog.lint: lastlog.c config.h lastlog.h + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > lastlog.lint + +mkpasswd: $(MKPWDOBJS) libshadow.a + $(CC) -o mkpasswd $(LDFLAGS) $(MKPWDOBJS) libshadow.a $(LIBS) + +mkpasswd.lint: $(MKPWDSRCS) + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > mkpasswd.lint + +newgrp: $(NGOBJS) libshadow.a + $(CC) -o newgrp $(LDFLAGS) $(NGOBJS) libshadow.a $(LIBS) + +newgrp.lint: $(NGSRCS) + $(LINT) $(LINTFLAGS) $(NGSRCS) > newgrp.lint + +sg: newgrp + rm -f sg + ln newgrp sg + +chfn: $(CHFNOBJS) libshadow.a + $(CC) -o chfn $(LDFLAGS) $(CHFNOBJS) libshadow.a $(LIBS) + +chfn.lint: $(CHFNSRCS) + $(LINT) $(LINTFLAGS) $(CHFNSRCS) > chfn.lint + +chsh: $(CHSHOBJS) libshadow.a + $(CC) -o chsh $(LDFLAGS) $(CHSHOBJS) libshadow.a $(LIBS) + +chsh.lint: $(CHSHSRCS) + $(LINT) $(LINTFLAGS) $(CHSHSRCS) > chsh.lint + +chage: $(CHAGEOBJS) libshadow.a + $(CC) -o chage $(LDFLAGS) $(CHAGEOBJS) libshadow.a $(LIBS) + +chage.lint: $(CHAGESRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(CHAGESRCS) > chage.lint + +chpasswd: $(CHPASSOBJS) libshadow.a + $(CC) -o chpasswd $(LDFLAGS) $(CHPASSOBJS) libshadow.a $(LIBS) + +chpasswd.lint: $(CHPASSSRCS) + $(LINT) $(LINTFLAGS) $(CHPASSSRCS) > chpasswd.lint + +newusers: newusers.o libshadow.a + $(CC) -o newusers $(LDFLAGS) newusers.o libshadow.a $(LIBS) + +newusers.lint: newusers.c + $(LINT) $(LINTFLAGS) newusers.c > newusers.lint + +id: id.o libshadow.a + $(CC) -o id $(LDFLAGS) id.o libshadow.a $(LIBS) + +id.lint: id.c + $(LINT) $(LINTFLAGS) id.c > id.lint + +groups: groups.o libshadow.a + $(CC) -o groups $(LDFLAGS) groups.o libshadow.a $(LIBS) + +groups.lint: groups.c + $(LINT) $(LINTFLAGS) groups.c > groups.lint + +useradd: useradd.o copydir.o mkrmdir.o libshadow.a + $(CC) -o useradd $(LDFLAGS) useradd.o copydir.o mkrmdir.o \ + libshadow.a $(LIBS) $(NDIR) + +useradd.lint: useradd.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) useradd.c copydir.c mkrmdir.c > useradd.lint + +userdel: userdel.o copydir.o mkrmdir.o libshadow.a + $(CC) -o userdel $(LDFLAGS) userdel.o copydir.o mkrmdir.o \ + libshadow.a $(LIBS) $(NDIR) + +userdel.lint: userdel.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) userdel.c copydir.c mkrmdir.c > userdel.lint + +usermod: usermod.o copydir.o mkrmdir.o chowndir.o libshadow.a + $(CC) -o usermod $(LDFLAGS) usermod.o copydir.o mkrmdir.o \ + chowndir.o libshadow.a $(LIBS) $(NDIR) + +usermod.lint: usermod.c copydir.c mkrmdir.c chowndir.c + $(LINT) $(LINTFLAGS) usermod.c copydir.c mkrmdir.c \ + chowndir.c > usermod.lint + +groupadd: groupadd.o libshadow.a + $(CC) -o groupadd $(LDFLAGS) groupadd.o libshadow.a $(LIBS) + +groupadd.lint: groupadd.c + $(LINT) $(LINTFLAGS) groupadd.c > groupadd.lint + +groupdel: groupdel.o libshadow.a + $(CC) -o groupdel $(LDFLAGS) groupdel.o libshadow.a $(LIBS) + +groupdel.lint: groupdel.c + $(LINT) $(LINTFLAGS) groupdel.c > groupdel.lint + +groupmod: groupmod.o libshadow.a + $(CC) -o groupmod $(LDFLAGS) groupmod.o libshadow.a $(LIBS) + +groupmod.lint: groupmod.c + $(LINT) $(LINTFLAGS) groupmod.c > groupmod.lint + +logoutd: logoutd.o libshadow.a + $(CC) -o logoutd $(LDFLAGS) logoutd.o libshadow.a + +logoutd.lint: logoutd.c + $(LINT) $(LINTFLAGS) logoutd.c > logoutd.lint + +pwck: pwck.o libshadow.a + $(CC) -o pwck $(LDFLAGS) pwck.o libshadow.a $(LIBS) + +pwck.lint: pwck.c + $(LINT) $(LINTFLAGS) pwck.c > pwck.lint + +grpck: grpck.o libshadow.a + $(CC) -o grpck $(LDFLAGS) grpck.o libshadow.a $(LIBS) + +grpck.lint: grpck.c + $(LINT) $(LINTFLAGS) grpck.c > grpck.lint + +expiry: expiry.o age.o libshadow.a + $(CC) -o expiry $(LDFLAGS) expiry.o age.o libshadow.a $(LIBS) + +expiry.lint: expiry.c + $(LINT) $(LINTFLAGS) expiry.c > expiry.lint + +sulog.o: config.h + +susetup.c: setup.c + cp setup.c susetup.c + +susetup.o: config.h susetup.c $(PWD) + $(CC) -c $(CFLAGS) -DSU susetup.c + +scologin: scologin.o + $(CC) -o scologin $(LDFLAGS) scologin.o -lsocket + +passwd.o: config.h shadow.h pwauth.h $(PWD) +lmain.o: config.h lastlog.h faillog.h pwauth.h $(PWD) +smain.o: config.h lastlog.h shadow.h pwauth.h $(PWD) +sub.o: $(PWD) +setup.o: config.h $(PWD) +mkrmdir.o: config.h +utmp.o: config.h +mail.o: config.h +motd.o: config.h +age.o: config.h gshadow.h $(PWD) +log.o: config.h lastlog.h $(PWD) +lastlog.o: lastlog.h +shell.o: config.h +entry.o: config.h shadow.h $(PWD) +hushed.o: config.h $(PWD) +valid.o: config.h $(PWD) +failure.o: faillog.h config.h +faillog.o: faillog.h config.h $(PWD) +newgrp.o: config.h shadow.h gshadow.h $(PWD) +mkpasswd.o: config.h shadow.h gshadow.h $(PWD) +gpmain.o: config.h gshadow.h $(PWD) +chfn.o: config.h $(PWD) +chsh.o: config.h $(PWD) +chage.o: config.h shadow.h $(PWD) +pwconv.o: config.h shadow.h +pwunconv.o: config.h shadow.h $(PWD) +chpasswd.o: config.h shadow.h $(PWD) +id.o: $(PWD) +newusers.o: config.h shadow.h $(PWD) +dpmain.o: config.h dialup.h +useradd.o: config.h shadow.h gshadow.h pwauth.h $(PWD) +userdel.o: config.h shadow.h gshadow.h pwauth.h $(PWD) +usermod.o: config.h shadow.h gshadow.h pwauth.h $(PWD) +groupadd.o: config.h gshadow.h +groupdel.o: config.h gshadow.h +groupmod.o: config.h gshadow.h +logoutd.o: config.h +sulogin.o: config.h pwauth.h +copydir.o: config.h +chowndir.o: config.h +pwck.o: config.h shadow.h $(PWD) +grpck.o: config.h gshadow.h $(PWD) + +libshadow.a(shadow.o): shadow.h config.h +libshadow.a(shadowio.o): shadow.h +libshadow.a(grent.o): config.h gshadow.h +libshadow.a(sgroupio.o): config.h gshadow.h +libshadow.a(dialup.o): dialup.h +libshadow.a(dialchk.o): dialup.h config.h +libshadow.a(getdef.o): config.h +libshadow.a(pwdbm.o): config.h $(PWD) +libshadow.a(spdbm.o): config.h shadow.h +libshadow.a(grdbm.o): config.h +libshadow.a(gshadow.o): config.h +libshadow.a(gsdbm.o): config.h gshadow.h +libshadow.a(pwauth.o): config.h pwauth.h +libshadow.a(pwpack.o): config.h $(PWD) +libshadow.a(pwent.o): config.h $(PWD) +libshadow.a(pwio.o): config.h $(PWD) +libshadow.a(getpass.o): config.h +libshadow.a(encrypt.o): config.h +libshadow.a(port.o): port.h +libshadow.a(rad64.o): config.h +libshadow.a(lockpw.o): +libshadow.a(gspack.o): config.h gshadow.h +libshadow.a(utent.o): config.h +libshadow.a(list.o): +libshadow.a(strtoday.o): config.h +libshadow.a(xmalloc.o): +libshadow.a(basename.o): +libshadow.a(isexpired.o): config.h shadow.h + +clean: + -rm -f susetup.c *.o a.out core npasswd nshadow *.pag *.dir + +clobber: clean + -rm -f $(BINS) *.lint *.L libshadow.a + +nuke: clobber + -for file in * ; do \ + if [ -f s.$$file -a ! -f p.$$file ] ; then \ + rm -f $$file ;\ + fi ;\ + done + +shar: login.sh.01 login.sh.02 login.sh.03 login.sh.04 login.sh.05 \ + login.sh.06 login.sh.07 login.sh.08 login.sh.09 login.sh.10 \ + login.sh.11 login.sh.12 + +login.sh.01: $(FILES1) Makefile + shar -a $(FILES1) > login.sh.01 + +login.sh.02: $(FILES2) Makefile + shar -a $(FILES2) > login.sh.02 + +login.sh.03: $(FILES3) Makefile + shar -a $(FILES3) > login.sh.03 + +login.sh.04: $(FILES4) Makefile + shar -a $(FILES4) > login.sh.04 + +login.sh.05: $(FILES5) Makefile + shar -a $(FILES5) > login.sh.05 + +login.sh.06: $(FILES6) Makefile + shar -a $(FILES6) > login.sh.06 + +login.sh.07: $(FILES7) Makefile + shar -a $(FILES7) > login.sh.07 + +login.sh.08: $(FILES8) Makefile + shar -a $(FILES8) > login.sh.08 + +login.sh.09: $(FILES9) Makefile + shar -a $(FILES9) > login.sh.09 + +login.sh.10: $(DOCS1) Makefile + shar -a $(DOCS1) > login.sh.10 + +login.sh.11: $(DOCS2) Makefile + shar -a $(DOCS2) > login.sh.11 + +login.sh.12: $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) Makefile + shar -a $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) > login.sh.12 diff --git a/old/Makefile.svr4 b/old/Makefile.svr4 new file mode 100644 index 00000000..846e46c9 --- /dev/null +++ b/old/Makefile.svr4 @@ -0,0 +1,681 @@ +# +# Copyright 1988 - 1994, Julianne Frances Haugh +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of Julianne F. Haugh nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# %W% %U% - Shadow password system (SVR4) +# +# $Id: Makefile.svr4,v 1.2 1997/05/01 23:11:55 marekm Exp $ +# +SHELL = /sbin/sh + +# +# Set this flag to decide what level of code "get" returns. +# The base USENET release was release 1. It is no longer supported. +# The version with the utilities added was release 2. +# The version with database-like file access is release 3. +RELEASE = 3 +VERSION = ver3.3.2 +GFLAGS = -n $(VERSION) +GET = get_file + +# Define the directory login is copied to. SVr4 uses /usr/bin. +LOGINDIR = /usr/bin +SBIN=/usr/sbin +# system (admin) commands +UBIN=/usr/bin +# user commands + +# SVr4 doesn't need extra libraries +NDIR = + +# Define some stuff for Cracklib. This assumes that libcracklib.a is +# in a system directory. +CRACKDEF='-DUSE_CRACKLIB' +CRACKLIB=-lcrack + +# Pick your favorite C compiler and tags command +CC = cc +TAGS = ctags + +# OS. This is SVr4 +OS = -DUSG -DSVR4 -DUSE_NIS + +# SVr4 doesn't use ranlib +RANLIB = echo + +# Configuration Flags +# +# DEST_INCLUDE_DIR - local include files +# LIBS - system libraries +# -lsocket - needed for TCP/IP and possibly SYSLOG +# -ldbm or -lndbm - needed for DBM support +# -lcrypt - needed for SCO crypt() functions +# -lucb if -ldbm is defined +# -lsocket and -lnsl if RLOGIN is defined +# CFLAGS - C compiler flags +# -DLAI_TCP - needed for SCO Xenix Lachman TCP/IP + +DEST_INCLUDE_DIR = /usr/include + +# Flags for SVr4 +CFLAGS = -O -g $(OS) -I$(DEST_INCLUDE_DIR) $(CRACKDEF) +LIBS = -lsocket -lnsl -ldbm -lucb +LDFLAGS = -g + +# Library is libsec.a +LIBSEC = libsec.a + +# Names for root user and group, and bin user and group. +RUID = root +RGID = root +BUID = bin +BGID = bin + +# Where the login.defs file will be copied. Must agree with config.h +DEST_LOGIN_DEFS = /etc/login.defs + +# Macros for files in SVR4 that aren't to be changed +PWD = /usr/include/pwd.h +SHADOW = /usr/include/shadow.h + +# Rules for .L (lint) files. +.SUFFIXES: .L +LINT = lint +LINTFLAGS = $(OS) -Dlint + +.c.L: + $(LINT) -pxu $(LINTFLAGS) $*.c > $*.L + +LOBJS = lmain.o login.o env.o valid.o setup.o shell.o age.o \ + utmp.o sub.o mail.o motd.o log.o ttytype.o failure.o \ + tz.o console.o hushed.o + +LSRCS = lmain.c login.c env.c valid.c setup.c shell.c age.c \ + utmp.c sub.c mail.c motd.c log.c ttytype.c failure.c \ + tz.c console.c hushed.c + +SOBJS = smain.o env.o entry.o susetup.o shell.o \ + sub.o mail.o motd.o sulog.o age.o tz.o hushed.o + +SSRCS = smain.c env.c entry.c setup.c shell.c \ + pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \ + tz.c hushed.c + +POBJS = passwd.o obscure.o +PSRCS = passwd.c obscure.c + +GPSRCS = gpmain.c + +GPOBJS = gpmain.o + +PWOBJS = pwconv.o + +PWSRCS = pwconv.c pwent.c shadow.c pwpack.c rad64.c + +PWUNOBJS = pwunconv.o + +PWUNSRCS = pwunconv.c pwent.c shadow.c pwpack.c rad64.c + +SULOGOBJS = sulogin.o entry.o env.o age.o setup.o \ + valid.o shell.o tz.o + +SULOGSRCS = sulogin.c entry.c env.c age.c pwent.c setup.c \ + shadow.c shell.c valid.c pwpack.c tz.c + +MKPWDOBJS = mkpasswd.o + +MKPWDSRCS = mkpasswd.c + +NGSRCS = newgrp.c env.c shell.c + +NGOBJS = newgrp.o env.o shell.o + +CHFNSRCS = chfn.c fields.c +CHFNOBJS = chfn.o fields.o +CHSHSRCS = chsh.c fields.c +CHSHOBJS = chsh.o fields.o +CHAGEOBJS = chage.o fields.o +CHAGESRCS = chage.c fields.c +CHPASSOBJS = chpasswd.o +CHPASSSRCS = chpasswd.c +DPSRCS = dpmain.c +DPOBJS = dpmain.o + +ALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \ + motd.c obscure.c passwd.c pwconv.c pwent.c pwunconv.c getpass.c \ + setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \ + utmp.c valid.c port.c newgrp.c gpmain.c grent.c mkpasswd.c pwpack.c \ + chfn.c chsh.c chage.c rad64.c encrypt.c chpasswd.c shadowio.c pwio.c \ + newusers.c groupio.c fields.c pwdbm.c grpack.c grdbm.c sppack.c \ + spdbm.c dpmain.c gshadow.c gsdbm.c gspack.c sgroupio.c useradd.c \ + userdel.c patchlevel.h usermod.c copydir.c mkrmdir.c groupadd.c \ + groupdel.c groupmod.c tz.c console.c hushed.c getdef.c \ + logoutd.c groups.c pwauth.c lockpw.c chowndir.c + +FILES1 = LICENSE README patchlevel.h newgrp.c Makefile config.h pwunconv.c obscure.c \ + age.c id.c + +FILES2 = passwd.c port.c lmain.c sulogin.c pwpack.c dialup.c expiry.c \ + gshadow.h + +FILES3 = chfn.c chsh.c smain.c faillog.c pwconv.c shadow.c pwck.c + +FILES4 = gpmain.c chage.c pwent.c valid.c setup.c entry.c ttytype.c port.h + +FILES5 = pwio.c encrypt.c chpasswd.c newusers.c rad64.c dialchk.c faillog.h \ + pwdbm.c grdbm.c gshadow.c sppack.c grpck.c + +FILES6 = gspack.c spdbm.c lastlog.h shell.c login.c sub.c dpmain.c mail.c \ + env.c pwd.h.m4 grpack.c shadow.h log.c grent.c motd.c dialup.h \ + fields.c gsdbm.c utmp.c failure.c + +FILES7 = groupio.c shadowio.c sgroupio.c groups.c copydir.c mkrmdir.c \ + mkpasswd.c pwauth.c pwauth.h lastlog.c + +FILES8 = useradd.c usermod.c login.defs + +FILES9 = groupadd.c groupdel.c groupmod.c tz.c console.c hushed.c getdef.c \ + scologin.c logoutd.c sulog.c getpass.c userdel.c lockpw.c chowndir.c + +FILES_SUN4 = Makefile.sun4 README.sun4 config.h.sun4 +FILES_SVR4 = Makefile.svr4 config.h.svr4 +FILES_LINUX = Makefile.linux config.h.linux + +MAN_1 = chage.1 chfn.1 chsh.1 id.1 login.1 newgrp.1 passwd.1 su.1 \ + useradd.1 userdel.1 usermod.1 groupadd.1 groupdel.1 groupmod.1 \ + groups.1 pwck.1 grpck.1 +MAN_3 = shadow.3 pwauth.3 +MAN_4 = faillog.4 passwd.4 porttime.4 shadow.4 +MAN_5 = login.5 +MAN_8 = chpasswd.8 dpasswd.8 faillog.8 newusers.8 pwconv.8 pwunconv.8 \ + sulogin.8 mkpasswd.8 logoutd.8 pwauth.8 lastlog.8 + +DOCS1 = $(MAN_1) $(MAN_3) $(MAN_4) +DOCS2 = $(MAN_5) $(MAN_8) +DOCS = $(DOCS1) $(DOCS2) + +BINS = su login pwconv pwunconv passwd sulogin faillog newgrp sg gpasswd \ + mkpasswd chfn chsh chage chpasswd newusers dpasswd id useradd \ + userdel usermod groupadd groupdel groupmod $(SCOLOGIN) logoutd \ + groups pwck grpck lastlog expiry + +all: $(BINS) $(DOCS) + +.PRECIOUS: libshadow.a + +libshadow.a: \ + libshadow.a(dialchk.o) \ + libshadow.a(dialup.o) \ + libshadow.a(encrypt.o) \ + libshadow.a(getdef.o) \ + libshadow.a(getpass.o) \ + libshadow.a(grdbm.o) \ + libshadow.a(grent.o) \ + libshadow.a(groupio.o) \ + libshadow.a(grpack.o) \ + libshadow.a(gshadow.o) \ + libshadow.a(gsdbm.o) \ + libshadow.a(gspack.o) \ + libshadow.a(sgroupio.o) \ + libshadow.a(port.o) \ + libshadow.a(pwdbm.o) \ + libshadow.a(pwent.o) \ + libshadow.a(pwio.o) \ + libshadow.a(pwpack.o) \ + libshadow.a(pwauth.o) \ + libshadow.a(rad64.o) \ + libshadow.a(spdbm.o) \ + libshadow.a(shadow.o) \ + libshadow.a(shadowio.o) \ + libshadow.a(sppack.o) \ + libshadow.a(lockpw.o) \ + libshadow.a(utent.o) \ + libshadow.a(list.o) \ + libshadow.a(strtoday.o) \ + libshadow.a(basename.o) \ + libshadow.a(isexpired.o) \ + libshadow.a(xmalloc.o) + $(RANLIB) libshadow.a + +libsec: $(LIBSEC)(shadow.o) + $(RANLIB) $(LIBSEC) + +save: + [ ! -d save ] && mkdir save + -cp $(LOGINDIR)/login save + -cp $(SBIN)/mkpasswd $(SBIN)/pwconv $(SBIN)/pwunconv $(SBIN)/sulogin \ + $(SBIN)/chpasswd $(SBIN)/newusers $(SBIN)/useradd \ + $(SBIN)/userdel $(SBIN)/usermod $(SBIN)/groupadd \ + $(SBIN)/groupdel $(SBIN)/groupmod $(SBIN)/logoutd \ + $(SBIN)/login.defs $(SBIN)/pwck $(SBIN)/grpck save + -cp $(UBIN)/su $(UBIN)/passwd $(UBIN)/gpasswd $(UBIN)/dpasswd \ + $(UBIN)/faillog $(UBIN)/newgrp $(UBIN)/chfn \ + $(UBIN)/chsh $(UBIN)/chage $(UBIN)/id $(UBIN)/expiry save + -cp $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/gshadow.h save + +restore: + [ -d save ] + -(cd save ; cp login $(LOGINDIR) ) + -(cd save ; -cp mkpasswd pwconv pwunconv sulogin chpasswd \ + newusers useradd userdel usermod groupadd groupdel groupmod \ + logoutd login.defs pwck grpck $(SBIN) ) + -(cd save ; cp su passwd gpasswd dpasswd faillog newgrp chfn chsh \ + chage id expiry $(UBIN) ) + -(cd save ; cp dialup.h gshadow.h $(DEST_INCLUDE_DIR) ) + +install: all + strip $(BINS) + mcs -da '@(#)shadow 3.3.3' $(BINS) + cp login $(LOGINDIR)/login + cp mkpasswd pwconv pwunconv sulogin chpasswd newusers \ + useradd userdel usermod groupadd groupdel groupmod logoutd \ + pwck grpck lastlog $(SBIN) + cp su passwd gpasswd dpasswd faillog newgrp chfn chsh chage id $(UBIN) + cp dialup.h gshadow.h /usr/include + chown $(RUID) $(LOGINDIR)/login $(SBIN)/pwconv $(SBIN)/pwunconv \ + $(SBIN)/sulogin $(UBIN)/su $(UBIN)/passwd $(UBIN)/gpasswd \ + $(UBIN)/newgrp $(SBIN)/mkpasswd $(UBIN)/dpasswd $(UBIN)/chsh \ + $(UBIN)/chfn $(UBIN)/chage $(SBIN)/useradd $(SBIN)/userdel \ + $(SBIN)/usermod $(SBIN)/groupadd $(SBIN)/groupdel \ + $(SBIN)/groupmod $(SBIN)/logoutd $(SBIN)/pwck $(SBIN)/grpck \ + $(UBIN)/expiry + chgrp $(RGID) $(LOGINDIR)/login $(SBIN)/pwconv $(SBIN)/pwunconv \ + $(SBIN)/sulogin $(UBIN)/su $(UBIN)/passwd $(UBIN)/gpasswd \ + $(UBIN)/newgrp $(SBIN)/mkpasswd $(UBIN)/dpasswd $(UBIN)/chsh \ + $(UBIN)/chfn $(UBIN)/chage $(SBIN)/useradd $(SBIN)/userdel \ + $(SBIN)/usermod $(SBIN)/groupadd $(SBIN)/groupdel \ + $(SBIN)/groupmod $(SBIN)/logoutd $(SBIN)/pwck $(SBIN)/grpck \ + $(UBIN)/expiry + chown $(BUID) $(UBIN)/faillog $(UBIN)/id /usr/include/gshadow.h \ + /usr/include/dialup.h + chgrp $(BGID) $(UBIN)/faillog $(UBIN)/id /usr/include/gshadow.h \ + /usr/include/dialup.h + chmod 700 $(SBIN)/pwconv $(SBIN)/pwunconv $(SBIN)/sulogin \ + $(SBIN)/mkpasswd $(SBIN)/chpasswd $(SBIN)/newusers \ + $(UBIN)/dpasswd $(UBIN)/chage $(SBIN)/useradd $(SBIN)/userdel \ + $(SBIN)/usermod $(SBIN)/groupadd $(SBIN)/groupdel \ + $(SBIN)/groupmod $(SBIN)/logoutd $(SBIN)/pwck $(SBIN)/grpck + chmod 4711 $(LOGINDIR)/login $(UBIN)/su $(UBIN)/passwd $(UBIN)/gpasswd \ + $(UBIN)/newgrp $(UBIN)/chfn $(UBIN)/chsh $(UBIN)/expiry + chmod 711 $(UBIN)/faillog $(UBIN)/id + chmod 444 /usr/include/gshadow.h /usr/include/dialup.h + rm -f $(UBIN)/sg + ln $(UBIN)/newgrp $(UBIN)/sg + [ -f /etc/login.defs ] || (cp login.defs /etc ; \ + chown $(RUID) /etc/login.defs ; \ + chgrp $(RGID) /etc/login.defs ; \ + chmod 600 /etc/login.defs ) + +lint: su.lint login.lint pwconv.lint pwunconv.lint passwd.lint sulogin.lint \ + faillog.lint newgrp.lint gpasswd.lint mkpasswd.lint chfn.lint \ + chsh.lint chage.lint dpasswd.lint id.lint useradd.lint userdel.lint \ + usermod.lint groupadd.lint groupdel.lint groupmod.lint logoutd.lint \ + pwck.lint grpck.lint expiry.lint \ + $(ALLSRCS:.c=.L) + +tags: $(ALLSRCS) + $(TAGS) $(ALLSRCS) + +README: + [ -f s.README ] && get -t -r$(RELEASE) s.README + +$(DOCS): + [ -f s.$@ ] && get -t -r$(RELEASE) s.$@ + +login.defs: + [ -f s.login.defs ] && get -t -r$(RELEASE) s.login.defs + +Makefile.sun4: + [ -f s.Makefile.sun4 ] && get -t -r$(RELEASE) s.Makefile.sun4 + +Makefile.svr4: + [ -f s.Makefile.svr4 ] && get -t -r$(RELEASE) s.Makefile.svr4 + +README.sun4: + [ -f s.README.sun4 ] && get -t -r$(RELEASE) s.README.sun4 + +config.h.sun4: + [ -f s.config.h.sun4 ] && get -t -r$(RELEASE) s.config.h.sun4 + +config.h.svr4: + [ -f s.config.h.svr4 ] && get -t -r$(RELEASE) s.config.h.svr4 + +login: $(LOBJS) libshadow.a + $(CC) -o login $(LDFLAGS) $(LOBJS) libshadow.a $(LIBS) + +login.lint: $(LSRCS) + $(LINT) $(LINTFLAGS) $(LSRCS) > login.lint + +su: $(SOBJS) libshadow.a + $(CC) -o su $(LDFLAGS) $(SOBJS) libshadow.a $(LIBS) + +su.lint: $(SSRCS) + $(LINT) $(LINTFLAGS) -DSU $(SSRCS) > su.lint + +passwd: $(POBJS) libshadow.a + $(CC) -o passwd $(LDFLAGS) $(POBJS) libshadow.a $(LIBS) $(CRACKLIB) + +passwd.lint: $(PSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PSRCS) > passwd.lint + +gpasswd: $(GPOBJS) libshadow.a + $(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) libshadow.a $(LIBS) + +gpasswd.lint: $(GPSRCS) + $(LINT) $(LINTFLAGS) $(GPSRCS) > gpasswd.lint + +dpasswd: $(DPOBJS) libshadow.a + $(CC) -o dpasswd $(LDFLAGS) $(DPOBJS) libshadow.a $(LIBS) + +dpasswd.lint: $(DPSRCS) + $(LINT) $(LINTFLAGS) $(DPSRCS) > dpasswd.lint + +pwconv: $(PWOBJS) libshadow.a config.h + $(CC) -o pwconv $(LDFLAGS) $(PWOBJS) libshadow.a $(LIBS) + +pwconv.lint: $(PWSRCS) config.h + $(LINT) $(LINTFLAGS) -DPASSWD $(PWSRCS) > pwconv.lint + +pwunconv: $(PWUNOBJS) libshadow.a config.h + $(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) libshadow.a $(LIBS) + +pwunconv.lint: $(PWUNSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PWUNSRCS) > pwunconv.lint + +sulogin: $(SULOGOBJS) libshadow.a + $(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) libshadow.a $(LIBS) + +sulogin.lint: $(SULOGSRCS) + $(LINT) $(LINTFLAGS) $(SULOGSRCS) > sulogin.lint + +faillog: faillog.o + $(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS) + +faillog.lint: faillog.c faillog.h config.h + $(LINT) $(LINTFLAGS) faillog.c > faillog.lint + +lastlog: lastlog.o + $(CC) -o lastlog $(LDFLAGS) lastlog.o $(LIBS) + +lastlog.lint: lastlog.c config.h lastlog.h + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > lastlog.lint + +mkpasswd: $(MKPWDOBJS) libshadow.a + $(CC) -o mkpasswd $(LDFLAGS) $(MKPWDOBJS) libshadow.a $(LIBS) + +mkpasswd.lint: $(MKPWDSRCS) + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > mkpasswd.lint + +newgrp: $(NGOBJS) libshadow.a + $(CC) -o newgrp $(LDFLAGS) $(NGOBJS) libshadow.a $(LIBS) + +newgrp.lint: $(NGSRCS) + $(LINT) $(LINTFLAGS) $(NGSRCS) > newgrp.lint + +sg: newgrp + /bin/rm -f sg + ln newgrp sg + +sg.lint: newgrp.lint + ln newgrp.lint sg.lint + +chfn: $(CHFNOBJS) libshadow.a + $(CC) -o chfn $(LDFLAGS) $(CHFNOBJS) libshadow.a $(LIBS) + +chfn.lint: $(CHFNSRCS) + $(LINT) $(LINTFLAGS) $(CHFNSRCS) > chfn.lint + +chsh: $(CHSHOBJS) libshadow.a + $(CC) -o chsh $(LDFLAGS) $(CHSHOBJS) libshadow.a $(LIBS) + +chsh.lint: $(CHSHSRCS) + $(LINT) $(LINTFLAGS) $(CHSHSRCS) > chsh.lint + +chage: $(CHAGEOBJS) libshadow.a + $(CC) -o chage $(LDFLAGS) $(CHAGEOBJS) libshadow.a $(LIBS) + +chage.lint: $(CHAGESRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(CHAGESRCS) > chage.lint + +chpasswd: $(CHPASSOBJS) libshadow.a + $(CC) -o chpasswd $(LDFLAGS) $(CHPASSOBJS) libshadow.a $(LIBS) + +chpasswd.lint: $(CHPASSSRCS) + $(LINT) $(LINTFLAGS) $(CHPASSSRCS) > chpasswd.lint + +newusers: newusers.o libshadow.a + $(CC) -o newusers $(LDFLAGS) newusers.o libshadow.a $(LIBS) + +newusers.lint: newusers.c + $(LINT) $(LINTFLAGS) newusers.c > newusers.lint + +id: id.o libshadow.a + $(CC) -o id $(LDFLAGS) id.o libshadow.a $(LIBS) + +id.lint: id.c + $(LINT) $(LINTFLAGS) id.c > id.lint + +groups: groups.o libshadow.a + $(CC) -o groups $(LDFLAGS) groups.o libshadow.a $(LIBS) + +groups.lint: groups.c + $(LINT) $(LINTFLAGS) groups.c > groups.lint + +useradd: useradd.o copydir.o mkrmdir.o libshadow.a + $(CC) -o useradd $(LDFLAGS) useradd.o copydir.o mkrmdir.o \ + libshadow.a $(LIBS) $(NDIR) + +useradd.lint: useradd.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) useradd.c copydir.c mkrmdir.c > useradd.lint + +userdel: userdel.o copydir.o mkrmdir.o libshadow.a + $(CC) -o userdel $(LDFLAGS) userdel.o copydir.o mkrmdir.o \ + libshadow.a $(LIBS) $(NDIR) + +userdel.lint: userdel.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) userdel.c copydir.c mkrmdir.c > userdel.lint + +usermod: usermod.o copydir.o mkrmdir.o chowndir.o libshadow.a + $(CC) -o usermod $(LDFLAGS) usermod.o copydir.o mkrmdir.o \ + chowndir.o libshadow.a $(LIBS) $(NDIR) + +usermod.lint: usermod.c copydir.c mkrmdir.c chowndir.c + $(LINT) $(LINTFLAGS) usermod.c copydir.c mkrmdir.c \ + chowndir.c > usermod.lint + +groupadd: groupadd.o libshadow.a + $(CC) -o groupadd $(LDFLAGS) groupadd.o libshadow.a $(LIBS) + +groupadd.lint: groupadd.c + $(LINT) $(LINTFLAGS) groupadd.c > groupadd.lint + +groupdel: groupdel.o libshadow.a + $(CC) -o groupdel $(LDFLAGS) groupdel.o libshadow.a $(LIBS) + +groupdel.lint: groupdel.c + $(LINT) $(LINTFLAGS) groupdel.c > groupdel.lint + +groupmod: groupmod.o libshadow.a + $(CC) -o groupmod $(LDFLAGS) groupmod.o libshadow.a $(LIBS) + +groupmod.lint: groupmod.c + $(LINT) $(LINTFLAGS) groupmod.c > groupmod.lint + +logoutd: logoutd.o libshadow.a + $(CC) -o logoutd $(LDFLAGS) logoutd.o libshadow.a + +logoutd.lint: logoutd.c + $(LINT) $(LINTFLAGS) logoutd.c > logoutd.lint + +pwck: pwck.o libshadow.a + $(CC) -o pwck $(LDFLAGS) pwck.o libshadow.a $(LIBS) + +pwck.lint: pwck.c + $(LINT) $(LINTFLAGS) pwck.c > pwck.lint + +grpck: grpck.o libshadow.a + $(CC) -o grpck $(LDFLAGS) grpck.o libshadow.a $(LIBS) + +grpck.lint: grpck.c + $(LINT) $(LINTFLAGS) grpck.c > grpck.lint + +expiry: expiry.o age.o libshadow.a + $(CC) -o expiry $(LDFLAGS) expiry.o age.o libshadow.a $(LIBS) + +expiry.lint: expiry.c + $(LINT) $(LINTFLAGS) expiry.c > expiry.lint + +sulog.o: config.h + +susetup.c: setup.c + cp setup.c susetup.c + +susetup.o: config.h susetup.c $(PWD) + $(CC) -c $(CFLAGS) -DSU susetup.c + +passwd.o: config.h $(SHADOW) $(PWD) pwauth.h +lmain.o: config.h lastlog.h faillog.h $(PWD) pwauth.h +smain.o: config.h lastlog.h $(PWD) $(SHADOW) pwauth.h +sub.o: $(PWD) +setup.o: config.h $(PWD) +mkrmdir.o: config.h +utmp.o: config.h +mail.o: config.h +motd.o: config.h +age.o: config.h gshadow.h $(PWD) +log.o: config.h lastlog.h $(PWD) +lastlog.o: lastlog.h +shell.o: config.h +entry.o: config.h $(SHADOW) $(PWD) +hushed.o: config.h $(PWD) +valid.o: config.h $(PWD) +failure.o: faillog.h config.h +faillog.o: faillog.h config.h $(PWD) +newgrp.o: config.h $(SHADOW) $(PWD) +mkpasswd.o: config.h $(SHADOW) $(PWD) +gpmain.o: config.h $(PWD) +chfn.o: config.h $(PWD) +chsh.o: config.h $(PWD) +chage.o: config.h $(SHADOW) $(PWD) +pwconv.o: config.h $(SHADOW) +pwunconv.o: config.h $(SHADOW) $(PWD) +chpasswd.o: config.h $(SHADOW) $(PWD) +id.o: $(PWD) +newusers.o: config.h $(SHADOW) $(PWD) +dpmain.o: config.h dialup.h +useradd.o: config.h $(SHADOW) $(PWD) pwauth.h gshadow.h +userdel.o: config.h $(SHADOW) $(PWD) pwauth.h gshadow.h +usermod.o: config.h $(SHADOW) $(PWD) pwauth.h gshadow.h +groupadd.o: config.h gshadow.h +groupdel.o: config.h gshadow.h +groupmod.o: config.h gshadow.h +logoutd.o: config.h +sulogin.o: config.h pwauth.h +copydir.o: config.h +chowndir.o: config.h +pwck.o: config.h $(SHADOW) $(PWD) +grpck.o: config.h gshadow.h $(PWD) + +libshadow.a(shadow.o): $(SHADOW) config.h +libshadow.a(shadowio.o): $(SHADOW) config.h +libshadow.a(grent.o): config.h gshadow.h +libshadow.a(sgroupio.o): config.h gshadow.h +libshadow.a(dialup.o): dialup.h +libshadow.a(dialchk.o): dialup.h config.h +libshadow.a(getdef.o): config.h +libshadow.a(pwdbm.o): config.h $(PWD) +libshadow.a(spdbm.o): config.h $(SHADOW) +libshadow.a(grdbm.o): config.h +libshadow.a(gsdbm.o): config.h gshadow.h +libshadow.a(pwauth.o): config.h pwauth.h +libshadow.a(pwpack.o): config.h $(PWD) +libshadow.a(pwent.o): config.h $(PWD) +libshadow.a(pwio.o): $(PWD) +libshadow.a(getpass.o): config.h +libshadow.a(encrypt.o): config.h +libshadow.a(port.o): port.h +libshadow.a(rad64.o): config.h +libshadow.a(lockpw.o): +libshadow.a(gspack.o): config.h gshadow.h +libshadow.a(list.o): +libshadow.a(strtoday.o): config.h +libshadow.a(xmalloc.o): +libshadow.a(basename.o): +libshadow.a(isexpired.o): config.h $(SHADOW) + +clean: + -rm -f susetup.c *.o a.out core npasswd nshadow *.pag *.dir + +clobber: clean + -rm -f $(BINS) *.lint *.L libshadow.a + +nuke: clobber + -for file in * ; do \ + if [ -f s.$$file -a ! -f p.$$file ] ; then \ + rm -f $$file ;\ + fi ;\ + done + +shar: login.sh.01 login.sh.02 login.sh.03 login.sh.04 login.sh.05 \ + login.sh.06 login.sh.07 login.sh.08 login.sh.09 login.sh.10 \ + login.sh.11 login.sh.12 + +login.sh.01: $(FILES1) Makefile + shar -a $(FILES1) > login.sh.01 + +login.sh.02: $(FILES2) Makefile + shar -a $(FILES2) > login.sh.02 + +login.sh.03: $(FILES3) Makefile + shar -a $(FILES3) > login.sh.03 + +login.sh.04: $(FILES4) Makefile + shar -a $(FILES4) > login.sh.04 + +login.sh.05: $(FILES5) Makefile + shar -a $(FILES5) > login.sh.05 + +login.sh.06: $(FILES6) Makefile + shar -a $(FILES6) > login.sh.06 + +login.sh.07: $(FILES7) Makefile + shar -a $(FILES7) > login.sh.07 + +login.sh.08: $(FILES8) Makefile + shar -a $(FILES8) > login.sh.08 + +login.sh.09: $(FILES9) Makefile + shar -a $(FILES9) > login.sh.09 + +login.sh.10: $(DOCS1) Makefile + shar -a $(DOCS1) > login.sh.10 + +login.sh.11: $(DOCS2) Makefile + shar -a $(DOCS2) > login.sh.11 + +login.sh.12: $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) Makefile + shar -a $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) > login.sh.12 diff --git a/old/Makefile.xenix b/old/Makefile.xenix new file mode 100644 index 00000000..43689199 --- /dev/null +++ b/old/Makefile.xenix @@ -0,0 +1,723 @@ +# +# Copyright 1988 - 1994, Julianne Frances Haugh +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of Julianne F. Haugh nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# %W% %U% - Shadow password system +# +# $Id: Makefile.xenix,v 1.2 1997/05/01 23:11:55 marekm Exp $ +# +SHELL = /bin/sh + +# +# Set this flag to decide what level of code "get" returns. +# The base USENET release was release 1. It is no longer supported. +# The version with the utilities added was release 2. It is now unsupported. +# The version with database-like file access is release 3. +RELEASE = 3 +VERSION = ver3.3.2 +GFLAGS = -n $(VERSION) +GET = get_file + +# Define the directory login is copied to. BE VERY CAREFUL!!! BSD old SunOS +# seems to use /bin, USG seems to use /etc, SunOS 4.1.1 seems to use /usr/bin. +# If you define SCOLOGIN, you MUST use /etc as LOGINDIR. +# LOGINDIR = /bin +LOGINDIR = /etc +# LOGINDIR = /usr/bin + +# Define any special libraries required to access the directory routines. +# Some systems require -lndir for the directory routines. SCO Xenix uses +# -lx for that. Your system might need nothing. +# NDIR = -lndir +NDIR = -lx +# NDIR = + +# Define some stuff for Cracklib. This assumes that libcracklib.a is +# in a system directory. +# CRACKDEF='-DUSE_CRACKLIB' +# CRACKLIB=-lcrack + +# Pick your favorite C compiler and tags command +CC = cc +TAGS = ctags + +# OS. Pick one of USG (AT&T, SYSV, SYS3), BSD, SUN (SunOS 2 and 3), +# SUN4 (SunOS 4.1.1.), UNIXPC (AT&T PC/7300, 3B1), or AIX (AIX v3) +# OS = -DUSG -DSYS3 +OS = -DUSG +# OS = -DBSD +# OS = -DSUN +# OS = -DSUN4 +# OS = -DUSG -DUNIXPC +# OS = -DAIX + +# Do you have to do ranlib (probably SUN, BSD and XENIX)? +RANLIB = ranlib +# RANLIB = echo + +# Enable the following if you are running SCO TCP/IP. It is a /bin/login +# which understands the *ahem* novel way they do rlogin/telnet. +# SCOLOGIN = scologin + +# Configuration Flags +# +# DEST_INCLUDE_DIR - local include files +# LIBS - system libraries +# -lsocket - needed for TCP/IP and possibly SYSLOG +# -ldbm or -lndbm - needed for DBM support +# -lcrypt - needed for SCO crypt() functions +# CFLAGS - C compiler flags +# -DLAI_TCP - needed for SCO Xenix Lachman TCP/IP + +DEST_INCLUDE_DIR = /usr/include + +# Flags for SCO Xenix/386 +CFLAGS = -O -M3 -g $(OS) -I$(DEST_INCLUDE_DIR) $(CRACKDEF) +LIBS = -lcrypt -lndbm +# LIBS = -lcrypt -ldbm +LDFLAGS = -M3 -g +LTFLAGS = + +# Flags for normal machines +# CFLAGS = -O -g $(OS) -I$(DEST_INCLUDE_DIR) $(CRACKDEF) +# LIBS = +# LDFLAGS = -g + +# Flags for SunOS 4.1.1 +# CFLAGS = -O2 $(OS) -I$(DEST_INCLUDE_DIR) $(CRACKDEF) +# LIBS = +# LDFLAGS = + +# This should be Slibsec.a for small model, or Llibsec.a for +# large model or whatever. MUST AGREE WITH CFLAGS!!! For non-Intel +# machines, just use libsec.a +LIBSEC = Slibsec.a +# LIBSEC = libsec.a + +# Names for root user and group, and bin user and group. See your +# /etc/passwd and /etc/group files. BSD and SUN use "wheel", most +# others use "root" for RGID. +RUID = root +RGID = root +# RGID = wheel +BUID = bin +BGID = bin + +# Where the login.defs file will be copied. Must agree with config.h +DEST_LOGIN_DEFS = /etc/login.defs + +# Rules for .L (lint) files. +.SUFFIXES: .L +LINT = lint +LINTFLAGS = $(OS) -Dlint + +.c.L: + $(LINT) -pxu $(LINTFLAGS) $*.c > $*.L + +LOBJS = lmain.o login.o env.o valid.o setup.o shell.o age.o \ + utmp.o sub.o mail.o motd.o log.o ttytype.o failure.o \ + tz.o console.o hushed.o + +LSRCS = lmain.c login.c env.c valid.c setup.c shell.c age.c \ + utmp.c sub.c mail.c motd.c log.c ttytype.c failure.c \ + tz.c console.c hushed.c + +SOBJS = smain.o env.o entry.o susetup.o shell.o \ + sub.o mail.o motd.o sulog.o age.o tz.o hushed.o + +SSRCS = smain.c env.c entry.c setup.c shell.c \ + pwent.c sub.c mail.c motd.c sulog.c shadow.c age.c pwpack.c rad64.c \ + tz.c hushed.c + +POBJS = passwd.o obscure.o +PSRCS = passwd.c obscure.c + +GPSRCS = gpmain.c + +GPOBJS = gpmain.o + +PWOBJS = pwconv.o + +PWSRCS = pwconv.c pwent.c shadow.c pwpack.c rad64.c + +PWUNOBJS = pwunconv.o + +PWUNSRCS = pwunconv.c pwent.c shadow.c pwpack.c rad64.c + +SULOGOBJS = sulogin.o entry.o env.o age.o setup.o \ + valid.o shell.o tz.o + +SULOGSRCS = sulogin.c entry.c env.c age.c pwent.c setup.c \ + shadow.c shell.c valid.c pwpack.c tz.c + +MKPWDOBJS = mkpasswd.o + +MKPWDSRCS = mkpasswd.c + +NGSRCS = newgrp.c env.c shell.c + +NGOBJS = newgrp.o env.o shell.o + +CHFNSRCS = chfn.c fields.c +CHFNOBJS = chfn.o fields.o +CHSHSRCS = chsh.c fields.c +CHSHOBJS = chsh.o fields.o +CHAGEOBJS = chage.o fields.o +CHAGESRCS = chage.c fields.c +CHPASSOBJS = chpasswd.o +CHPASSSRCS = chpasswd.c +DPSRCS = dpmain.c +DPOBJS = dpmain.o + +ALLSRCS = age.c dialchk.c dialup.c entry.c env.c lmain.c log.c login.c mail.c \ + motd.c obscure.c passwd.c pwconv.c pwent.c pwunconv.c getpass.c \ + setup.c shadow.c shell.c smain.c sub.c sulog.c sulogin.c ttytype.c \ + utmp.c valid.c port.c newgrp.c gpmain.c grent.c mkpasswd.c pwpack.c \ + chfn.c chsh.c chage.c rad64.c encrypt.c chpasswd.c shadowio.c pwio.c \ + newusers.c groupio.c fields.c pwdbm.c grpack.c grdbm.c sppack.c \ + spdbm.c dpmain.c gshadow.c gsdbm.c gspack.c sgroupio.c useradd.c \ + userdel.c patchlevel.h usermod.c copydir.c mkrmdir.c groupadd.c \ + groupdel.c groupmod.c tz.c console.c hushed.c getdef.c scologin.c \ + logoutd.c groups.c pwauth.c lockpw.c chowndir.c rename.c + +FILES1 = LICENSE README patchlevel.h newgrp.c Makefile config.h pwunconv.c obscure.c \ + age.c id.c + +FILES2 = passwd.c port.c lmain.c sulogin.c pwpack.c dialup.c expiry.c \ + gshadow.h + +FILES3 = chfn.c chsh.c smain.c faillog.c pwconv.c shadow.c pwck.c utent.c + +FILES4 = gpmain.c chage.c pwent.c valid.c setup.c entry.c ttytype.c port.h + +FILES5 = pwio.c encrypt.c chpasswd.c newusers.c rad64.c dialchk.c faillog.h \ + pwdbm.c grdbm.c gshadow.c sppack.c grpck.c + +FILES6 = gspack.c spdbm.c lastlog.h shell.c login.c sub.c dpmain.c mail.c \ + env.c pwd.h.m4 grpack.c shadow.h log.c grent.c motd.c dialup.h \ + fields.c gsdbm.c utmp.c failure.c + +FILES7 = groupio.c shadowio.c sgroupio.c groups.c copydir.c mkrmdir.c \ + mkpasswd.c pwauth.c pwauth.h lastlog.c + +FILES8 = useradd.c usermod.c login.defs rename.c + +FILES9 = groupadd.c groupdel.c groupmod.c tz.c console.c hushed.c getdef.c \ + scologin.c logoutd.c sulog.c getpass.c userdel.c lockpw.c chowndir.c + +FILES_SUN4 = Makefile.sun4 README.sun4 config.h.sun4 +FILES_SVR4 = Makefile.svr4 config.h.svr4 +FILES_LINUX = Makefile.linux config.h.linux + +MAN_1 = chage.1 chfn.1 chsh.1 id.1 login.1 newgrp.1 passwd.1 su.1 \ + useradd.1 userdel.1 usermod.1 groupadd.1 groupdel.1 groupmod.1 \ + groups.1 pwck.1 grpck.1 +MAN_3 = shadow.3 pwauth.3 +MAN_4 = faillog.4 passwd.4 porttime.4 shadow.4 +MAN_5 = login.5 +MAN_8 = chpasswd.8 dpasswd.8 faillog.8 newusers.8 pwconv.8 pwunconv.8 \ + sulogin.8 mkpasswd.8 logoutd.8 pwauth.8 lastlog.8 + +DOCS1 = $(MAN_1) $(MAN_3) $(MAN_4) +DOCS2 = $(MAN_5) $(MAN_8) +DOCS = $(DOCS1) $(DOCS2) + +BINS = su login pwconv pwunconv passwd sulogin faillog newgrp sg gpasswd \ + mkpasswd chfn chsh chage chpasswd newusers dpasswd id useradd \ + userdel usermod groupadd groupdel groupmod $(SCOLOGIN) logoutd \ + groups pwck grpck lastlog expiry + +all: $(BINS) $(DOCS) + +.PRECIOUS: libshadow.a + +libshadow.a: \ + libshadow.a(dialchk.o) \ + libshadow.a(dialup.o) \ + libshadow.a(encrypt.o) \ + libshadow.a(getdef.o) \ + libshadow.a(getpass.o) \ + libshadow.a(grdbm.o) \ + libshadow.a(grent.o) \ + libshadow.a(groupio.o) \ + libshadow.a(grpack.o) \ + libshadow.a(gshadow.o) \ + libshadow.a(gsdbm.o) \ + libshadow.a(gspack.o) \ + libshadow.a(sgroupio.o) \ + libshadow.a(port.o) \ + libshadow.a(pwdbm.o) \ + libshadow.a(pwent.o) \ + libshadow.a(pwio.o) \ + libshadow.a(pwpack.o) \ + libshadow.a(pwauth.o) \ + libshadow.a(rad64.o) \ + libshadow.a(spdbm.o) \ + libshadow.a(shadow.o) \ + libshadow.a(shadowio.o) \ + libshadow.a(sppack.o) \ + libshadow.a(lockpw.o) \ + libshadow.a(rename.o) \ + libshadow.a(utent.o) \ + libshadow.a(list.o) \ + libshadow.a(strtoday.o) \ + libshadow.a(basename.o) \ + libshadow.a(isexpired.o) \ + libshadow.a(xmalloc.o) + $(RANLIB) libshadow.a + +libsec: $(LIBSEC)(shadow.o) + $(RANLIB) $(LIBSEC) + +save: + [ ! -d save ] && mkdir save + -cp $(LOGINDIR)/login save + -cp /etc/mkpasswd /etc/pwconv /etc/pwunconv /etc/sulogin /etc/chpasswd \ + /etc/newusers /etc/useradd /etc/userdel /etc/usermod \ + /etc/groupadd /etc/groupdel /etc/groupmod /etc/logoutd \ + /etc/login.defs /etc/pwck /etc/grpck /bin/expiry save + -cp /bin/su /bin/passwd /bin/gpasswd /bin/dpasswd /bin/faillog \ + /bin/newgrp /bin/chfn /bin/chsh /bin/chage /bin/id \ + /bin/scologin save + -cp $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/shadow.h \ + $(DEST_INCLUDE_DIR)/pwd.h $(DEST_INCLUDE_DIR)/gshadow.h save + +restore: + [ -d save ] + -(cd save ; cp login $(LOGINDIR) ) + -(cd save ; -cp mkpasswd pwconv pwunconv sulogin chpasswd \ + newusers useradd userdel usermod groupadd groupdel groupmod \ + logoutd login.defs pwck grpck /etc) + -(cd save ; cp su passwd gpasswd dpasswd faillog newgrp chfn chsh \ + chage id scologin expiry /bin) + -(cd save ; cp dialup.h shadow.h pwd.h gshadow.h $(DEST_INCLUDE_DIR) ) + +install: all + strip $(BINS) + cp login $(LOGINDIR)/login + cp mkpasswd pwconv pwunconv sulogin chpasswd newusers \ + useradd userdel usermod groupadd groupdel groupmod logoutd \ + pwck grpck /etc + cp su passwd gpasswd dpasswd faillog newgrp chfn chsh chage id /bin + rm -f /bin/sg + ln /bin/newgrp /bin/sg + cp dialup.h shadow.h pwd.h gshadow.h $(DEST_INCLUDE_DIR) + chown $(RUID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \ + /bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \ + /bin/dpasswd /bin/chsh /bin/chfn /bin/chage /etc/useradd \ + /etc/userdel /etc/usermod /etc/groupadd /etc/groupdel \ + /etc/groupmod /etc/logoutd /etc/pwck /etc/grpck /bin/expiry + chgrp $(RGID) $(LOGINDIR)/login /etc/pwconv /etc/pwunconv /etc/sulogin \ + /bin/su /bin/passwd /bin/gpasswd /bin/newgrp /etc/mkpasswd \ + /bin/dpasswd /bin/chsh /bin/chfn /bin/chage /etc/useradd \ + /etc/userdel /etc/usermod /etc/groupadd /etc/groupdel \ + /etc/groupmod /etc/logoutd /etc/pwck /etc/grpck /bin/expiry + chown $(BUID) /bin/faillog /bin/id $(DEST_INCLUDE_DIR)/shadow.h \ + $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/pwd.h \ + $(DEST_INCLUDE_DIR)/gshadow.h + chgrp $(BGID) /bin/faillog /bin/id $(DEST_INCLUDE_DIR)/shadow.h \ + $(DEST_INCLUDE_DIR)/dialup.h $(DEST_INCLUDE_DIR)/pwd.h \ + $(DEST_INCLUDE_DIR)/gshadow.h + chmod 700 /etc/pwconv /etc/pwunconv /etc/sulogin /etc/mkpasswd \ + /etc/chpasswd /etc/newusers /bin/dpasswd /etc/logoutd \ + /etc/useradd /etc/userdel /etc/usermod /etc/groupadd \ + /etc/groupdel /etc/groupmod /etc/pwck /etc/grpck + chmod 4711 $(LOGINDIR)/login /bin/su /bin/passwd /bin/gpasswd \ + /bin/newgrp /bin/chfn /bin/chsh /bin/chage /bin/expiry + chmod 711 /bin/faillog /bin/id + chmod 444 $(DEST_INCLUDE_DIR)/shadow.h $(DEST_INCLUDE_DIR)/dialup.h \ + $(DEST_INCLUDE_DIR)/pwd.h $(DEST_INCLUDE_DIR)/gshadow.h + [ -f $(DEST_LOGIN_DEFS) ] || (cp login.defs $(DEST_LOGIN_DEFS) ; \ + chown $(RUID) $(DEST_LOGIN_DEFS) ; \ + chgrp $(RGID) $(DEST_LOGIN_DEFS) ; \ + chmod 600 $(DEST_LOGIN_DEFS) ) + [ -z "$(SCOLOGIN)" ] || (cp scologin /bin/login ; \ + chown $(RUID) /bin/login ; \ + chgrp $(RGID) /bin/login ; \ + chmod 755 /bin/login ) + +lint: su.lint login.lint pwconv.lint pwunconv.lint passwd.lint sulogin.lint \ + faillog.lint newgrp.lint gpasswd.lint mkpasswd.lint chfn.lint \ + chsh.lint chage.lint dpasswd.lint id.lint useradd.lint userdel.lint \ + usermod.lint groupadd.lint groupdel.lint groupmod.lint logoutd.lint \ + pwck.lint grpck.lint expiry.lint \ + $(ALLSRCS:.c=.L) + +tags: $(ALLSRCS) + $(TAGS) $(ALLSRCS) + +README: + [ -f s.README ] && $(GET) $(GFLAGS) s.README + +$(DOCS): + [ -f s.$@ ] && $(GET) $(GFLAGS) s.$@ + +login.defs: + [ -f s.login.defs ] && $(GET) $(GFLAGS) s.login.defs + +Makefile.sun4: + [ -f s.Makefile.sun4 ] && $(GET) $(GFLAGS) s.Makefile.sun4 + +Makefile.svr4: + [ -f s.Makefile.svr4 ] && $(GET) $(GFLAGS) s.Makefile.svr4 + +README.sun4: + [ -f s.README.sun4 ] && $(GET) $(GFLAGS) s.README.sun4 + +config.h.sun4: + [ -f s.config.h.sun4 ] && $(GET) $(GFLAGS) s.config.h.sun4 + +config.h.svr4: + [ -f s.config.h.svr4 ] && $(GET) $(GFLAGS) s.config.h.svr4 + +login: $(LOBJS) libshadow.a + $(CC) -o login $(LDFLAGS) $(LOBJS) libshadow.a $(LIBS) + +login.lint: $(LSRCS) + $(LINT) $(LINTFLAGS) $(LSRCS) > login.lint + +su: $(SOBJS) libshadow.a + $(CC) -o su $(LDFLAGS) $(SOBJS) libshadow.a $(LIBS) + +su.lint: $(SSRCS) + $(LINT) $(LINTFLAGS) -DSU $(SSRCS) > su.lint + +passwd: $(POBJS) libshadow.a + $(CC) -o passwd $(LDFLAGS) $(POBJS) libshadow.a $(LIBS) $(CRACKLIB) + +passwd.lint: $(PSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PSRCS) > passwd.lint + +gpasswd: $(GPOBJS) libshadow.a + $(CC) -o gpasswd $(LDFLAGS) $(GPOBJS) libshadow.a $(LIBS) + +gpasswd.lint: $(GPSRCS) + $(LINT) $(LINTFLAGS) $(GPSRCS) > gpasswd.lint + +dpasswd: $(DPOBJS) libshadow.a + $(CC) -o dpasswd $(LDFLAGS) $(DPOBJS) libshadow.a $(LIBS) + +dpasswd.lint: $(DPSRCS) + $(LINT) $(LINTFLAGS) $(DPSRCS) > dpasswd.lint + +pwconv: $(PWOBJS) libshadow.a config.h + $(CC) -o pwconv $(LDFLAGS) $(PWOBJS) libshadow.a $(LIBS) + +pwconv.lint: $(PWSRCS) config.h + $(LINT) $(LINTFLAGS) -DPASSWD $(PWSRCS) > pwconv.lint + +pwunconv: $(PWUNOBJS) libshadow.a config.h + $(CC) -o pwunconv $(LDFLAGS) $(PWUNOBJS) libshadow.a $(LIBS) + +pwunconv.lint: $(PWUNSRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(PWUNSRCS) > pwunconv.lint + +sulogin: $(SULOGOBJS) libshadow.a + $(CC) -o sulogin $(LDFLAGS) $(SULOGOBJS) libshadow.a $(LIBS) + +sulogin.lint: $(SULOGSRCS) + $(LINT) $(LINTFLAGS) $(SULOGSRCS) > sulogin.lint + +faillog: faillog.o + $(CC) -o faillog $(LDFLAGS) faillog.o $(LIBS) + +faillog.lint: faillog.c faillog.h config.h + $(LINT) $(LINTFLAGS) faillog.c > faillog.lint + +lastlog: lastlog.o + $(CC) -o lastlog $(LDFLAGS) lastlog.o $(LIBS) + +lastlog.lint: lastlog.c config.h lastlog.h + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > lastlog.lint + +mkpasswd: $(MKPWDOBJS) libshadow.a + $(CC) -o mkpasswd $(LDFLAGS) $(MKPWDOBJS) libshadow.a $(LIBS) + +mkpasswd.lint: $(MKPWDSRCS) + $(LINT) $(LINTFLAGS) $(MKPWDSRCS) > mkpasswd.lint + +newgrp: $(NGOBJS) libshadow.a + $(CC) -o newgrp $(LDFLAGS) $(NGOBJS) libshadow.a $(LIBS) + +newgrp.lint: $(NGSRCS) + $(LINT) $(LINTFLAGS) $(NGSRCS) > newgrp.lint + +sg: newgrp + rm -f sg + ln newgrp sg + +sg.lint: newgrp.lint + ln newgrp.lint sg.lint + +chfn: $(CHFNOBJS) libshadow.a + $(CC) -o chfn $(LDFLAGS) $(CHFNOBJS) libshadow.a $(LIBS) + +chfn.lint: $(CHFNSRCS) + $(LINT) $(LINTFLAGS) $(CHFNSRCS) > chfn.lint + +chsh: $(CHSHOBJS) libshadow.a + $(CC) -o chsh $(LDFLAGS) $(CHSHOBJS) libshadow.a $(LIBS) + +chsh.lint: $(CHSHSRCS) + $(LINT) $(LINTFLAGS) $(CHSHSRCS) > chsh.lint + +chage: $(CHAGEOBJS) libshadow.a + $(CC) -o chage $(LDFLAGS) $(CHAGEOBJS) libshadow.a $(LIBS) + +chage.lint: $(CHAGESRCS) + $(LINT) $(LINTFLAGS) -DPASSWD $(CHAGESRCS) > chage.lint + +chpasswd: $(CHPASSOBJS) libshadow.a + $(CC) -o chpasswd $(LDFLAGS) $(CHPASSOBJS) libshadow.a $(LIBS) + +chpasswd.lint: $(CHPASSSRCS) + $(LINT) $(LINTFLAGS) $(CHPASSSRCS) > chpasswd.lint + +newusers: newusers.o libshadow.a + $(CC) -o newusers $(LDFLAGS) newusers.o libshadow.a $(LIBS) + +newusers.lint: newusers.c + $(LINT) $(LINTFLAGS) newusers.c > newusers.lint + +id: id.o libshadow.a + $(CC) -o id $(LDFLAGS) id.o libshadow.a $(LIBS) + +id.lint: id.c + $(LINT) $(LINTFLAGS) id.c > id.lint + +groups: groups.o libshadow.a + $(CC) -o groups $(LDFLAGS) groups.o libshadow.a $(LIBS) + +groups.lint: groups.c + $(LINT) $(LINTFLAGS) groups.c > groups.lint + +useradd: useradd.o copydir.o mkrmdir.o libshadow.a + $(CC) -o useradd $(LDFLAGS) useradd.o copydir.o mkrmdir.o \ + libshadow.a $(LIBS) $(NDIR) + +useradd.lint: useradd.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) useradd.c copydir.c mkrmdir.c > useradd.lint + +userdel: userdel.o copydir.o mkrmdir.o libshadow.a + $(CC) -o userdel $(LDFLAGS) userdel.o copydir.o mkrmdir.o \ + libshadow.a $(LIBS) $(NDIR) + +userdel.lint: userdel.c copydir.c mkrmdir.c + $(LINT) $(LINTFLAGS) userdel.c copydir.c mkrmdir.c > userdel.lint + +usermod: usermod.o copydir.o mkrmdir.o chowndir.o libshadow.a + $(CC) -o usermod $(LDFLAGS) usermod.o copydir.o mkrmdir.o \ + chowndir.o libshadow.a $(LIBS) $(NDIR) + +usermod.lint: usermod.c copydir.c mkrmdir.c chowndir.c + $(LINT) $(LINTFLAGS) usermod.c copydir.c mkrmdir.c \ + chowndir.c > usermod.lint + +groupadd: groupadd.o libshadow.a + $(CC) -o groupadd $(LDFLAGS) groupadd.o libshadow.a $(LIBS) + +groupadd.lint: groupadd.c + $(LINT) $(LINTFLAGS) groupadd.c > groupadd.lint + +groupdel: groupdel.o libshadow.a + $(CC) -o groupdel $(LDFLAGS) groupdel.o libshadow.a $(LIBS) + +groupdel.lint: groupdel.c + $(LINT) $(LINTFLAGS) groupdel.c > groupdel.lint + +groupmod: groupmod.o libshadow.a + $(CC) -o groupmod $(LDFLAGS) groupmod.o libshadow.a $(LIBS) + +groupmod.lint: groupmod.c + $(LINT) $(LINTFLAGS) groupmod.c > groupmod.lint + +pwd.h.m4: + [ -f s.pwd.h.m4 ] && $(GET) $(GFLAGS) s.pwd.h.m4 + +pwd.h: pwd.h.m4 Makefile + m4 $(OS) < pwd.h.m4 > pwd.h + +logoutd: logoutd.o libshadow.a + $(CC) -o logoutd $(LDFLAGS) logoutd.o libshadow.a + +logoutd.lint: logoutd.c + $(LINT) $(LINTFLAGS) logoutd.c > logoutd.lint + +pwck: pwck.o libshadow.a + $(CC) -o pwck $(LDFLAGS) pwck.o libshadow.a $(LIBS) + +pwck.lint: pwck.c + $(LINT) $(LINTFLAGS) pwck.c > pwck.lint + +grpck: grpck.o libshadow.a + $(CC) -o grpck $(LDFLAGS) grpck.o libshadow.a $(LIBS) + +grpck.lint: grpck.c + $(LINT) $(LINTFLAGS) grpck.c > grpck.lint + +expiry: expiry.o age.o libshadow.a + $(CC) -o expiry $(LDFLAGS) age.o expiry.o libshadow.a $(LIBS) + +expiry.lint: expiry.c + $(LINT) $(LINTFLAGS) expiry.c > expiry.lint + +sulog.o: config.h + +susetup.c: setup.c + cp setup.c susetup.c + +susetup.o: config.h susetup.c pwd.h + $(CC) -c $(CFLAGS) -DSU susetup.c + +scologin: scologin.o + $(CC) -o scologin $(LDFLAGS) scologin.o -lsocket + +passwd.o: config.h shadow.h pwd.h pwauth.h +lmain.o: config.h lastlog.h faillog.h pwd.h pwauth.h +smain.o: config.h lastlog.h pwd.h shadow.h pwauth.h +sub.o: pwd.h +setup.o: config.h pwd.h +mkrmdir.o: config.h +utmp.o: config.h +mail.o: config.h +motd.o: config.h +age.o: config.h pwd.h gshadow.h +log.o: config.h lastlog.h pwd.h +lastlog.o: lastlog.h +shell.o: config.h +entry.o: config.h shadow.h pwd.h +hushed.o: config.h pwd.h +valid.o: config.h pwd.h +failure.o: faillog.h config.h +faillog.o: faillog.h config.h pwd.h +newgrp.o: config.h shadow.h gshadow.h pwd.h +mkpasswd.o: config.h shadow.h gshadow.h pwd.h +gpmain.o: config.h pwd.h gshadow.h +chfn.o: config.h pwd.h +chsh.o: config.h pwd.h +chage.o: config.h shadow.h pwd.h +pwconv.o: config.h shadow.h +pwunconv.o: config.h shadow.h pwd.h +chpasswd.o: config.h shadow.h pwd.h +id.o: pwd.h +newusers.o: config.h shadow.h pwd.h +dpmain.o: config.h dialup.h +useradd.o: config.h shadow.h pwd.h pwauth.h gshadow.h +userdel.o: config.h shadow.h pwd.h pwauth.h gshadow.h +usermod.o: config.h shadow.h pwd.h pwauth.h gshadow.h +groupadd.o: config.h gshadow.h +groupdel.o: config.h gshadow.h +groupmod.o: config.h gshadow.h +logoutd.o: config.h +sulogin.o: config.h pwauth.h +copydir.o: config.h +chowndir.o: config.h +pwck.o: config.h shadow.h pwd.h +grpck.o: config.h pwd.h gshadow.h + +libshadow.a(shadow.o): shadow.h config.h +libshadow.a(shadowio.o): shadow.h config.h +libshadow.a(grent.o): config.h gshadow.h +libshadow.a(groupio.o): config.h +libshadow.a(sgroupio.o): config.h gshadow.h +libshadow.a(dialup.o): dialup.h +libshadow.a(dialchk.o): dialup.h config.h +libshadow.a(getdef.o): config.h +libshadow.a(pwdbm.o): config.h pwd.h +libshadow.a(spdbm.o): config.h shadow.h +libshadow.a(grdbm.o): config.h +libshadow.a(gshadow.o): config.h +libshadow.a(gsdbm.o): config.h gshadow.h +libshadow.a(pwauth.o): config.h pwauth.h +libshadow.a(pwpack.o): config.h pwd.h +libshadow.a(pwent.o): config.h pwd.h +libshadow.a(pwio.o): pwd.h config.h +libshadow.a(getpass.o): config.h +libshadow.a(encrypt.o): config.h +libshadow.a(port.o): port.h +libshadow.a(rad64.o): config.h +libshadow.a(lockpw.o): +libshadow.a(rename.o): config.h +libshadow.a(gspack.o): config.h gshadow.h +libshadow.a(list.o): +libshadow.a(strtoday.o): config.h +libshadow.a(xmalloc.o): +libshadow.a(basename.o): +libshadow.a(isexpired.o): config.h shadow.h + +clean: + -rm -f susetup.c *.o a.out core npasswd nshadow *.pag *.dir pwd.h + +clobber: clean + -rm -f $(BINS) *.lint *.L libshadow.a + +nuke: clobber + -for file in * ; do \ + if [ -f s.$$file -a ! -f p.$$file ] ; then \ + rm -f $$file ;\ + fi ;\ + done + +shar: login.sh.01 login.sh.02 login.sh.03 login.sh.04 login.sh.05 \ + login.sh.06 login.sh.07 login.sh.08 login.sh.09 login.sh.10 \ + login.sh.11 login.sh.12 + +login.sh.01: $(FILES1) Makefile + shar -Dc $(FILES1) > login.sh.01 + +login.sh.02: $(FILES2) Makefile + shar -Dc $(FILES2) > login.sh.02 + +login.sh.03: $(FILES3) Makefile + shar -Dc $(FILES3) > login.sh.03 + +login.sh.04: $(FILES4) Makefile + shar -Dc $(FILES4) > login.sh.04 + +login.sh.05: $(FILES5) Makefile + shar -Dc $(FILES5) > login.sh.05 + +login.sh.06: $(FILES6) Makefile + shar -Dc $(FILES6) > login.sh.06 + +login.sh.07: $(FILES7) Makefile + shar -Dc $(FILES7) > login.sh.07 + +login.sh.08: $(FILES8) Makefile + shar -Dc $(FILES8) > login.sh.08 + +login.sh.09: $(FILES9) Makefile + shar -Dc $(FILES9) > login.sh.09 + +login.sh.10: $(DOCS1) Makefile + shar -Dc $(DOCS1) > login.sh.10 + +login.sh.11: $(DOCS2) Makefile + shar -Dc $(DOCS2) > login.sh.11 + +login.sh.12: $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) Makefile + shar -Dc $(FILES_SUN4) $(FILES_SVR4) $(FILES_LINUX) > login.sh.12 diff --git a/old/config.h.linux b/old/config.h.linux new file mode 100644 index 00000000..cdab702d --- /dev/null +++ b/old/config.h.linux @@ -0,0 +1,454 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Configuration file for login. + * + * $Id: config.h.linux,v 1.2 1997/05/01 23:11:57 marekm Exp $ + */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +#ifdef __linux__ +#include +#include +#include +#endif + +/* + * Pathname to the run-time configuration definitions file. + */ + +#define LOGINDEFS "/etc/login.defs" + +/* + * Define SHADOWPWD to use shadow [ unreadable ] password file. + * Release 3 has a requirement that SHADOWPWD always be defined. + */ + +#define SHADOWPWD + +/* + * Define AUTOSHADOW to have root always copy sp_pwdp to pw_passwd + * for getpwuid() and getpwnam(). This provides compatibility for + * privileged applications which are shadow-ignorant. YOU ARE + * ENCOURAGED TO NOT USE THIS OPTION UNLESS ABSOLUTELY NECESSARY. + */ +/* + * Yes, don't do it (and don't build libc with the SHADOW_COMPAT=true + * option) unless you REALLY know what you're doing. It might work, + * but can lead to unshadowing your passwords. This is not the right + * way to support shadow passwords! You have been warned. --marekm + */ + +#undef AUTOSHADOW + +/* + * Define SHADOWGRP to user shadowed group files. This feature adds + * the concept of a group administrator. You MUST NOT define this + * if you disable SHADOWPWD. + */ + +#define SHADOWGRP /**/ + +/* + * Define these if you have shadow password/group support functions in + * your version of libc. This removes these functions from libshadow.a + * (the ones from libc will be used instead). + * + * Finally upgraded to ELF, so... + */ +#define HAVE_SHADOWPWD +#define HAVE_SHADOWGRP + +/* + * Define MD5_CRYPT to support the MD5-based password hashing algorithm + * compatible with FreeBSD. All programs using pw_encrypt() instead of + * crypt() will understand both styles: old (standard, DES-based), and + * new (MD5-based). + * + * This means that it is possible to copy encrypted passwords from FreeBSD. + * Programs to change passwords (like passwd) will still use the old style + * crypt() for compatibility. + * + * To enable the use of the new crypt() for new passwords (if you don't + * need to copy them to other systems, except FreeBSD and Linux), set the + * MD5_CRYPT option in /etc/login.defs to "yes". + * + * This algorithm supports passwords of any length (the getpass() limit + * is 127 on Linux) and salt strings up to 8 (instead of 2) characters. + * + * This is experimental, and currently requires that all programs use + * pw_encrypt() from libshadow.a instead of crypt() from libc. This is + * problematic especially on ELF systems (libc5 has getspnam() so there + * is otherwise no need to link with the static libshadow.a). On most + * a.out systems you have to link with libshadow.a anyway, no problem. + */ + +#define MD5_CRYPT + +/* + * Define DOUBLESIZE to use 16 character passwords. Define SW_CRYPT + * to use 80 character passwords with SecureWare[tm]'s method of + * generating ciphertext. + * Not recommended because of some potential weaknesses. --marekm + */ + +#undef DOUBLESIZE +#undef SW_CRYPT + +/* + * Define SKEY to allow dual-mode SKEY/normal logins + */ + +#undef SKEY + +/* + * Define AGING if you want the password aging checks made. + * Release 3 has a requirement that AGING always be defined. + */ + +#define AGING + +/* + * Pick your version of DBM. If you define either DBM or NDBM, you must + * define GETPWENT. If you define NDBM you must define GETGRENT as well. + */ + +/* + * DBM support is untested, not recommended yet. It might make more + * sense if someone could add it to getpwnam() etc. in libc so that all + * programs (such as ls) can benefit from it. Any volunteers? + * + * The old DBM (as opposed to NDBM) support may be removed in a future + * release if no one complains. It's too braindamaged for the number + * of #ifdefs it adds (only one database per process at a time). + * + * On Linux, NDBM is actually implemented using GDBM, which is licensed + * under the GPL (not LGPL!) - I'm not sure if it is legal to link it + * with non-GPL code (such as the shadow suite). Consult your lawyers, + * or just modify the code to use db instead. Welcome to the wonderful + * world of copyrights. Yuck! + * + * The current DBM support code has a subtle design flaw. See my + * comment in pwdbm.c for details... + * + * Unless you have 2000 users or so, DBM probably doesn't make things + * much faster, and it does make things more complicated (= possibly + * more buggy). Do it only if you know what you're doing! --marekm + */ + +#undef DBM +#undef NDBM + +/* + * Define USE_SYSLOG if you want to have SYSLOG functions included in your code. + */ + +#define USE_SYSLOG + +/* + * Enable RLOGIN to support the "-r" and "-h" options. + * Also enable UT_HOST if your /etc/utmp provides for a host name. + */ + +#define RLOGIN +#define UT_HOST + +/* + * Define NO_RFLG to remove support for login -r flag if your system has + * a new-style rlogind which doesn't need it. --marekm + */ + +#define NO_RFLG + +/* + * Define the "success" code from ruserok(). Most modern systems use 0 + * for success and -1 for failure, while certain older versions use 1 + * for success and 0 for failure. Please check your manpage to be sure. + */ + +#define RUSEROK 0 + +/* + * Select one of the following + */ + +#undef DIR_XENIX /* include , use (struct direct) */ +#undef DIR_BSD /* include , use (struct direct) */ +#define DIR_SYSV /* include , use (struct dirent) */ + +/* + * Various system environment definitions. + */ + +/* + * Define if you have sgetgrent() in libc, to remove this function from + * libshadow.a (some versions of libc5 reportedly have it, most reports + * so far are from Red Hat 2.1 users, more information is welcome). + */ +#undef HAVE_SGETGRENT + +/* + * Only important if you compile with GETGRENT defined (use my getgr*() + * but still use fgetgrent() from libc if HAVE_FGETGRENT defined). + */ +#undef HAVE_FGETGRENT + +#define HAVE_SIGACTION +#define HAVE_GETUSERSHELL /* Define if your UNIX supports getusershell() */ +#define HAVE_LL_HOST /* Define if "struct lastlog" contains ll_host */ +#define HAVE_ULIMIT /* Define if your UNIX supports ulimit() */ +#define HAVE_RLIMIT /* Define if your UNIX supports setrlimit() */ +#undef GETPWENT /* Define if you want my GETPWENT(3) routines */ +#undef GETGRENT /* Define if you want my GETGRENT(3) routines */ +#define NEED_AL64 /* Define if library does not include a64l() */ +#undef NEED_MKDIR /* Define if system does not have mkdir() */ +#undef NEED_RMDIR /* Define if system does not have rmdir() */ +#undef NEED_RENAME /* Define if system does not have rename() */ +#undef NEED_STRSTR /* Define if library does not include strstr() */ +#undef NEED_PUTPWENT /* Define if library does not include putpwent()*/ +#define SIGTYPE void /* Type returned by signal() */ + +/* + * These definitions MUST agree with the values defined in . + */ + +#undef BSD_QUOTA /* the pw_quota field exists */ +#undef ATT_AGE /* the pw_age field exists */ +#undef ATT_COMMENT /* the pw_comment field exists */ + +#define UID_T uid_t /* set to be the type of UID's */ +#define GID_T gid_t /* set to be the type of GID's */ + +#ifndef UID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define UID_T uid_t +#else +#define UID_T int +#endif +#endif + +#ifndef GID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define GID_T gid_t +#else +#define GID_T int +#endif +#endif + +/* + * Define NDEBUG for production versions + */ + +#define NDEBUG + +/* + * Define PWDFILE and GRPFILE to the names of the password and + * group files. //jiivee + */ + +#define PASSWD_FILE "/etc/passwd" +#define PASSWD_PAG_FILE "/etc/passwd.pag" +#define GROUP_FILE "/etc/group" +#define GROUP_PAG_FILE "/etc/group.pag" + +#ifdef SHADOWPWD +#define SHADOW_FILE "/etc/shadow" +#define SHADOW_PAG_FILE "/etc/shadow.pag" +#ifdef SHADOWGRP +#define SGROUP_FILE "/etc/gshadow" +#define SGROUP_PAG_FILE "/etc/gshadow.pag" +#endif +#endif + +/* + * The structure of the utmp file. There are two kinds of UTMP files, + * "BSD" and "USG". "BSD" has no PID or type information, "USG" does. + * If you define neither of these, the type will be defaulted by using + * BSD, SUN, SYS3 and USG defines. + */ + +#define _UTMP_FILE "/var/run/utmp" +#define _WTMP_FILE "/var/log/wtmp" + +#define USG_UTMP /**/ +/* #define BSD_UTMP */ + +#if !defined(USG_UTMP) && !defined(BSD_UTMP) +#if defined(BSD) || defined(SYS3) || defined(SUN) +#define BSD_UTMP +#else +#define USG_UTMP +#endif /* BSD || SYS3 || SUN */ +#endif /* !USG_UTMP || !BSD_UTMP */ + +/* + * From where to look for legal user shells + */ + +#ifndef SHELLS_FILE +#define SHELLS_FILE "/etc/shells" +#endif + +/* + * Default issue file location + */ + +#ifndef ISSUE_FILE +#define ISSUE_FILE "/etc/issue" +#endif + +/* + * Logoutd message file + */ + +#define HUP_MESG_FILE "/etc/logoutd.mesg" + +/* + * Mail spool directory. This is used if mailspool cannot be located otherwise + */ + +#ifndef MAIL_SPOOL_DIR +#define MAIL_SPOOL_DIR "/var/spool/mail" +#endif + +/* + * Where are new user default setup files kept + */ + +#define SKEL_DIR "/etc/skel" + +/* + * New user defaults. The NEW_USER_FILE must have 6 X's in the end of name + */ + +#define USER_DEFAULTS_FILE "/etc/default/useradd" +#define NEW_USER_FILE "/etc/default/nuaddXXXXXX" + +/* + * Telinit program. If your system uses /etc/telinit to change run + * level, define TELINIT and then define the RUNLEVEL macro to be the + * run-level to switch INIT to. This is used by sulogin to change + * from single user to multi-user mode. + * + * From bluca@www.polimi.it: instead, set up /etc/inittab properly + * ~0:S:wait:/sbin/sulogin + * ~9:S:wait:/sbin/telinit -t0 2 + */ + +#undef TELINIT +#undef PATH_TELINIT "/sbin/telinit" +#undef RUNLEVEL "2" + +/* + * Crontab and atrm. Used in userdel.c - see user_cancel(). Verify + * that these are correct for your distribution. --marekm + */ + +#if 0 /* old Slackware */ +#define CRONTAB_COMMAND "/usr/bin/crontab -d -u %s" +#define CRONTAB_FILE "/var/cron/tabs/%s" +#else +/* Debian 0.93R6 (marekm): */ +#define CRONTAB_COMMAND "/usr/bin/crontab -r -u %s" +#define CRONTAB_FILE "/var/spool/cron/crontabs/%s" +/* Red Hat 2.1 (jiivee@iki.fi): */ +/* #define CRONTAB_FILE "/var/spool/cron/%s" */ +#endif + +/* + * Hmmm, had to #undef this since at-2.8a on Linux doesn't have an option + * to remove all jobs owned by some user. + * + * Fortunately, atrun will not run any at jobs for users not listed in + * /etc/passwd. Unfortunately, if you remove a user and add a new user + * with the same UID before it is time to run the old at job, atrun will + * not notice this and run the old job. Not good. The best fix right + * now is to remove any at jobs left over by hand, and not reuse any + * previously used UID values. + * + * We probably should discuss this with the at maintainer... It might + * be better to store at jobs by user names, not UIDs. --marekm + */ + +#undef ATRM_COMMAND + +/* + * Login times log file location. + */ + +#define LASTLOG_FILE "/var/log/lastlog" + +/* + * Linux FSSTND recommends that the chfn, chsh, gpasswd, passwd commands + * are in /usr/bin, not /bin (not needed before mounting /usr). --marekm + */ + +#define CHFN_PROGRAM "/usr/bin/chfn" +#define CHSH_PROGRAM "/usr/bin/chsh" +#define GPASSWD_PROGRAM "/usr/bin/gpasswd" +#define PASSWD_PROGRAM "/usr/bin/passwd" + +/* + * On most Linux systems, the login prompt is "hostname login: ". Some + * automatic login scripts depend on it. If not defined, the default is + * just "login: ". %s is replaced by the hostname. --marekm + */ + +#define LOGIN_PROMPT "%s login: " + +/* + * Define to enable (warning: completely unsupported by me) administrator + * defined authentication methods. Most programs are not aware of them, + * so we can remove some code and possibly some bugs :-). PAM (when done) + * will replace much of this anyway... --marekm + */ + +/* #define AUTH_METHODS */ + +/* + * Define to enable detailed login access control (a la logdaemon/FreeBSD) + * and su access control (much more powerful/fascist than the traditional + * BSD-style "wheel group" feature). Any volunteers to convince the GNU + * folks that they should add access control to their version of su? + * Call me a fascist, but then I'll have to call you a communist :-). + */ + +#define LOGIN_ACCESS +#define SU_ACCESS + +/* see faillog.h for more info what it is */ +#define FAILLOG_LOCKTIME + +/* see lmain.c and login.defs.linux */ +#define CONSOLE_GROUPS + +#endif /* _CONFIG_H */ diff --git a/old/config.h.sun4 b/old/config.h.sun4 new file mode 100644 index 00000000..95527c05 --- /dev/null +++ b/old/config.h.sun4 @@ -0,0 +1,189 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Configuration file for login. + * + * $Id: config.h.sun4,v 1.2 1997/05/01 23:11:58 marekm Exp $ + * (SunOS 4.1.1) + */ + + +/* + * Pathname to the run-time configuration definitions file. + */ + +#define LOGINDEFS "/etc/login.defs" + +/* + * Define SHADOWPWD to use shadow [ unreadable ] password file. + * Release 3 has a requirement that SHADOWPWD always be defined. + */ + +#define SHADOWPWD + +/* + * Define AUTOSHADOW to have root always copy sp_pwdp to pw_passwd + * for getpwuid() and getpwnam(). This provides compatibility for + * privileged applications which are shadow-ignorant. YOU ARE + * ENCOURAGED TO NOT USE THIS OPTION UNLESS ABSOLUTELY NECESSARY. + */ + +#undef AUTOSHADOW + +/* + * Define SHADOWGRP to user shadowed group files. This feature adds + * the concept of a group administrator. + */ + +#define SHADOWGRP /**/ + +/* + * Define DOUBLESIZE to use 16 character passwords. Define SW_CRYPT + * to use 80 character passwords with SecureWare[tm]'s method of + * generating ciphertext. + */ + +#define DOUBLESIZE +#undef SW_CRYPT + +/* + * Define SKEY to allow dual-mode SKEY/normal logins + */ + +#undef SKEY + +/* + * Define AGING if you want the password aging checks made. + * Release 3 has a requirement that AGING always be defined. + */ + +#define AGING + +/* + * Pick your version of DBM. If you define either DBM or NDBM, you must + * define GETPWENT. If you define NDBM you must define GETGRENT as well. + */ + +/* #define DBM /**/ +#define NDBM /**/ + +/* + * Define USE_SYSLOG if you want to have SYSLOG functions included in your code. + */ + +#define USE_SYSLOG + +/* + * Enable RLOGIN to support the "-r" and "-h" options. + * Also enable UT_HOST if your /etc/utmp provides for a host name. + */ + +#define RLOGIN +#define UT_HOST + +/* + * Define the "success" code from ruserok(). Most modern systems use 0 + * for success and -1 for failure, while certain older versions use 1 + * for success and 0 for failure. Please check your manpage to be sure. + */ + +#define RUSEROK 0 + +/* + * Select one of the following + */ + +/* #define DIR_XENIX /* include , use (struct direct) */ +/* #define DIR_BSD /* include , use (struct direct) */ +#define DIR_SYSV /* include , use (struct dirent) */ + +/* + * Various system environment definitions. + */ + +#define HAVE_LL_HOST /* Define if "struct lastlog" contains ll_host */ +#define HAVE_ULIMIT /* Define if your UNIX supports ulimit() */ +#define GETPWENT /* Define if you want my GETPWENT(3) routines */ +#define GETGRENT /* Define if you want my GETGRENT(3) routines */ +#undef NEED_AL64 /* Define if library does not include a64l() */ +#undef NEED_MKDIR /* Define if system does not have mkdir() */ +#undef NEED_RMDIR /* Define if system does not have rmdir() */ +#undef NEED_RENAME /* Define if system does not have rename() */ +#define NEED_STRSTR /* Define if library does not include strstr() */ +#undef NEED_PUTPWENT /* Define if library does not include putpwent()*/ +#define NEED_UTENT /* Define if library does not include utent fncs*/ +#define SIGTYPE void /* Type returned by signal() */ + +/* + * These definitions MUST agree with the values defined in . + */ + +#undef BSD_QUOTA /* the pw_quota field exists */ +#define ATT_AGE /* the pw_age field exists */ +#define ATT_COMMENT /* the pw_comment field exists */ + +#define UID_T uid_t /* set to be the type of UID's */ +#define GID_T gid_t /* set to be the type of GID's */ + +#ifndef UID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define UID_T uid_t +#else +#define UID_T int +#endif +#endif + +#ifndef GID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define GID_T gid_t +#else +#define GID_T int +#endif +#endif + +/* + * Define NDEBUG for production versions + */ + +#define NDEBUG + +/* + * Define PWDFILE and GRPFILE to the names of the password and + * group files. + */ + +#define PWDFILE "/etc/passwd" +#define GRPFILE "/etc/group" + +/* + * Login times log file. + */ + +#define LASTFILE "/var/adm/lastlog" diff --git a/old/config.h.svr4 b/old/config.h.svr4 new file mode 100644 index 00000000..40c3d1ca --- /dev/null +++ b/old/config.h.svr4 @@ -0,0 +1,217 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Configuration file for login. + * + * $Id: config.h.svr4,v 1.2 1997/05/01 23:11:58 marekm Exp $ (SVR4) + */ + + +/* + * Pathname to the run-time configuration definitions file. + */ + +#define LOGINDEFS "/etc/login.defs" + +/* + * Define SHADOWPWD to use shadow [ unreadable ] password file. + * Release 3 has a requirement that SHADOWPWD always be defined. + */ + +#define SHADOWPWD + +/* + * Define AUTOSHADOW to have root always copy sp_pwdp to pw_passwd + * for getpwuid() and getpwnam(). This provides compatibility for + * privileged applications which are shadow-ignorant. YOU ARE + * ENCOURAGED TO NOT USE THIS OPTION UNLESS ABSOLUTELY NECESSARY. + * + * SVR4 has always had /etc/shadow + */ + +#undef AUTOSHADOW + +/* + * Define SHADOWGRP to user shadowed group files. This feature adds + * the concept of a group administrator. + */ + +/* #define SHADOWGRP /**/ + +/* + * Define DOUBLESIZE to use 16 character passwords. Define SW_CRYPT + * to use 80 character passwords with SecureWare[tm]'s method of + * generating ciphertext. + */ + +#define DOUBLESIZE +#undef SW_CRYPT + +/* + * Define SKEY to allow dual-mode SKEY/normal logins + */ + +#undef SKEY + +/* + * Define AGING if you want the password aging checks made. + * Release 3 has a requirement that AGING always be defined. + */ + +#define AGING + +/* + * Pick your version of DBM. If you define either DBM or NDBM, you must + * define GETPWENT. If you define NDBM you must define GETGRENT as well. + * + * SVR4 doesn't come with mkpasswd. + */ + +/* #define DBM /**/ +/* #define NDBM /**/ + +/* + * Define USE_SYSLOG if you want to have SYSLOG functions included in your code. + * + * SVR4 includes syslog() + */ + +#define USE_SYSLOG + +/* + * Enable RLOGIN to support the "-r" and "-h" options. + * Don't define UT_HOST, it's in utmpx. + */ + +#define RLOGIN +#undef UT_HOST + +/* + * Define the "success" code from ruserok(). Most modern systems use 0 + * for success and -1 for failure, while certain older versions use 1 + * for success and 0 for failure. Please check your manpage to be sure. + */ + +#define RUSEROK 0 + +/* + * Use SVR4 directory functions. + */ + +#define DIR_SYSV /* include , use (struct dirent) */ + +/* + * Various system environment definitions. + */ + +#undef HAVE_ULIMIT /* Define if your UNIX supports ulimit() */ +#define HAVE_RLIMIT /* Define if your UNIX supports setrlimit() */ +#define GETPWENT /* Define if you want my GETPWENT(3) routines */ +#undef GETGRENT /* Define if you want my GETGRENT(3) routines */ +#undef NEED_AL64 /* Define if library does not include a64l() */ +#undef NEED_MKDIR /* Define if system does not have mkdir() */ +#undef NEED_RMDIR /* Define if system does not have rmdir() */ +#undef NEED_RENAME /* Define if system does not have rename() */ +#undef NEED_STRSTR /* Define if library does not include strstr() */ +#undef NEED_PUTPWENT /* Define if library does not include putpwent()*/ +#define SIGTYPE void /* Type returned by signal() */ + +/* + * These definitions MUST agree with the values defined in . + */ + +#undef BSD_QUOTA /* the pw_quota field exists */ +#define ATT_AGE /* the pw_age field exists */ +#define ATT_COMMENT /* the pw_comment field exists */ + +#define UID_T uid_t /* set to be the type of UID's */ +#define GID_T gid_t /* set to be the type of GID's */ + +#ifndef UID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define UID_T uid_t +#else +#define UID_T int +#endif +#endif + +#ifndef GID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define GID_T gid_t +#else +#define GID_T int +#endif +#endif + +/* + * Define NDEBUG for production versions + */ + +#define NDEBUG + +/* + * Define PWDFILE and GRPFILE to the names of the password and + * group files. + */ + +#define PWDFILE "/etc/passwd" +#define GRPFILE "/etc/group" + +/* + * This is SVR4. + */ + +#define USG_UTMP + +/* + * Telinit program. If your system uses /etc/telinit to change run + * level, define TELINIT and then define the RUNLEVEL macro to be the + * run-level to switch INIT to. This is used by sulogin to change + * from single user to multi-user mode. + */ + +#define TELINIT /**/ +#define RUNLEVEL "2" /**/ + +/* + * Crontab and atrm. If your system can "crontab -r -u ", define + * HAS_CRONTAB. If your system can "atrm ", define HAS_ATRM. + * + * SVR4 has both of these. + */ + +#define HAS_CRONTAB +#define HAS_ATRM + +/* + * Login times log file. + */ + +#define LASTFILE "/var/adm/lastlog" diff --git a/old/config.h.xenix b/old/config.h.xenix new file mode 100644 index 00000000..4ee3d5bf --- /dev/null +++ b/old/config.h.xenix @@ -0,0 +1,224 @@ +/* + * Copyright 1989 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Configuration file for login. + * + * $Id: config.h.xenix,v 1.2 1997/05/01 23:11:58 marekm Exp $ + */ + + +/* + * Pathname to the run-time configuration definitions file. + */ + +#define LOGINDEFS "/etc/login.defs" + +/* + * Define SHADOWPWD to use shadow [ unreadable ] password file. + * Release 3 has a requirement that SHADOWPWD always be defined. + */ + +#define SHADOWPWD + +/* + * Define AUTOSHADOW to have root always copy sp_pwdp to pw_passwd + * for getpwuid() and getpwnam(). This provides compatibility for + * privileged applications which are shadow-ignorant. YOU ARE + * ENCOURAGED TO NOT USE THIS OPTION UNLESS ABSOLUTELY NECESSARY. + */ + +#undef AUTOSHADOW + +/* + * Define SHADOWGRP to user shadowed group files. This feature adds + * the concept of a group administrator. You MUST NOT define this + * if you disable SHADOWPWD. + */ + +/* #define SHADOWGRP /**/ + +/* + * Define DOUBLESIZE to use 16 character passwords. Define SW_CRYPT + * to use 80 character passwords with SecureWare[tm]'s method of + * generating ciphertext. + */ + +#define DOUBLESIZE +#undef SW_CRYPT + +/* + * Define SKEY to allow dual-mode SKEY/normal logins + */ + +#undef SKEY + +/* + * Define AGING if you want the password aging checks made. + * Release 3 has a requirement that AGING always be defined. + */ + +#define AGING + +/* + * Pick your version of DBM. If you define either DBM or NDBM, you must + * define GETPWENT. If you define NDBM you must define GETGRENT as well. + */ + +/* #define DBM /**/ +/* #define NDBM /**/ + +/* + * Define USE_SYSLOG if you want to have SYSLOG functions included in your code. + */ + +#define USE_SYSLOG + +/* + * Enable RLOGIN to support the "-r" and "-h" options. + * Also enable UT_HOST if your /etc/utmp provides for a host name. + */ + +#define RLOGIN +#undef UT_HOST + +/* + * Define the "success" code from ruserok(). Most modern systems use 0 + * for success and -1 for failure, while certain older versions use 1 + * for success and 0 for failure. Please check your manpage to be sure. + */ + +#define RUSEROK 0 + +/* + * Select one of the following + */ + +#define DIR_XENIX /* include , use (struct direct) */ +/* #define DIR_BSD /* include , use (struct direct) */ +/* #define DIR_SYSV /* include , use (struct dirent) */ + +/* + * Various system environment definitions. + */ + +#define HAVE_ULIMIT /* Define if your UNIX supports ulimit() */ +#undef HAVE_RLIMIT /* Define if your UNIX supports setrlimit() */ +#define GETPWENT /* Define if you want my GETPWENT(3) routines */ +#define GETGRENT /* Define if you want my GETGRENT(3) routines */ +#define NEED_AL64 /* Define if library does not include a64l() */ +#define NEED_MKDIR /* Define if system does not have mkdir() */ +#define NEED_RMDIR /* Define if system does not have rmdir() */ +#define NEED_RENAME /* Define if system does not have rename() */ +#define NEED_STRSTR /* Define if library does not include strstr() */ +#undef NEED_PUTPWENT /* Define if library does not include putpwent()*/ +#define SIGTYPE int /* Type returned by signal() */ + +/* + * These definitions MUST agree with the values defined in . + */ + +#undef BSD_QUOTA /* the pw_quota field exists */ +#define ATT_AGE /* the pw_age field exists */ +#define ATT_COMMENT /* the pw_comment field exists */ + +#define UID_T uid_t /* set to be the type of UID's */ +#define GID_T gid_t /* set to be the type of GID's */ + +#ifndef UID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define UID_T uid_t +#else +#define UID_T int +#endif +#endif + +#ifndef GID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define GID_T gid_t +#else +#define GID_T int +#endif +#endif + +/* + * Define NDEBUG for production versions + */ + +#define NDEBUG + +/* + * Define PWDFILE and GRPFILE to the names of the password and + * group files. + */ + +#define PWDFILE "/etc/passwd" +#define GRPFILE "/etc/group" + +/* + * The structure of the utmp file. There are two kinds of UTMP files, + * "BSD" and "USG". "BSD" has no PID or type information, "USG" does. + * If you define neither of these, the type will be defaulted by using + * BSD, SUN, SYS3 and USG defines. + */ + +#define USG_UTMP /**/ +/* #define BSD_UTMP /**/ + +#if !defined(USG_UTMP) && !defined(BSD_UTMP) +#if defined(BSD) || defined(SYS3) || defined(SUN) +#define BSD_UTMP +#else +#define USG_UTMP +#endif /* BSD || SYS3 || SUN */ +#endif /* !USG_UTMP || !BSD_UTMP */ + +/* + * Telinit program. If your system uses /etc/telinit to change run + * level, define TELINIT and then define the RUNLEVEL macro to be the + * run-level to switch INIT to. This is used by sulogin to change + * from single user to multi-user mode. + */ + +#define TELINIT /**/ +#define RUNLEVEL "2" /**/ + +/* + * Crontab and atrm. If your system can "crontab -r -u ", define + * HAS_CRONTAB. If your system can "atrm ", define HAS_ATRM. + */ + +#undef HAS_CRONTAB +#undef HAS_ATRM + +/* + * Login times log file. + */ + +#define LASTFILE "/var/adm/lastlog" diff --git a/old/orig-config.h b/old/orig-config.h new file mode 100644 index 00000000..790db8eb --- /dev/null +++ b/old/orig-config.h @@ -0,0 +1,454 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Configuration file for login. + * + * $Id: orig-config.h,v 1.2 1997/05/01 23:11:59 marekm Exp $ + */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +#ifdef __linux__ +#include +#include +#include +#endif + +/* + * Pathname to the run-time configuration definitions file. + */ + +#define LOGINDEFS "/etc/login.defs" + +/* + * Define SHADOWPWD to use shadow [ unreadable ] password file. + * Release 3 has a requirement that SHADOWPWD always be defined. + */ + +#define SHADOWPWD + +/* + * Define AUTOSHADOW to have root always copy sp_pwdp to pw_passwd + * for getpwuid() and getpwnam(). This provides compatibility for + * privileged applications which are shadow-ignorant. YOU ARE + * ENCOURAGED TO NOT USE THIS OPTION UNLESS ABSOLUTELY NECESSARY. + */ +/* + * Yes, don't do it (and don't build libc with the SHADOW_COMPAT=true + * option) unless you REALLY know what you're doing. It might work, + * but can lead to unshadowing your passwords. This is not the right + * way to support shadow passwords! You have been warned. --marekm + */ + +#undef AUTOSHADOW + +/* + * Define SHADOWGRP to user shadowed group files. This feature adds + * the concept of a group administrator. You MUST NOT define this + * if you disable SHADOWPWD. + */ + +#define SHADOWGRP /**/ + +/* + * Define these if you have shadow password/group support functions in + * your version of libc. This removes these functions from libshadow.a + * (the ones from libc will be used instead). + * + * Finally upgraded to ELF, so... + */ +#define HAVE_SHADOWPWD +#define HAVE_SHADOWGRP + +/* + * Define MD5_CRYPT to support the MD5-based password hashing algorithm + * compatible with FreeBSD. All programs using pw_encrypt() instead of + * crypt() will understand both styles: old (standard, DES-based), and + * new (MD5-based). + * + * This means that it is possible to copy encrypted passwords from FreeBSD. + * Programs to change passwords (like passwd) will still use the old style + * crypt() for compatibility. + * + * To enable the use of the new crypt() for new passwords (if you don't + * need to copy them to other systems, except FreeBSD and Linux), set the + * MD5_CRYPT option in /etc/login.defs to "yes". + * + * This algorithm supports passwords of any length (the getpass() limit + * is 127 on Linux) and salt strings up to 8 (instead of 2) characters. + * + * This is experimental, and currently requires that all programs use + * pw_encrypt() from libshadow.a instead of crypt() from libc. This is + * problematic especially on ELF systems (libc5 has getspnam() so there + * is otherwise no need to link with the static libshadow.a). On most + * a.out systems you have to link with libshadow.a anyway, no problem. + */ + +#define MD5_CRYPT + +/* + * Define DOUBLESIZE to use 16 character passwords. Define SW_CRYPT + * to use 80 character passwords with SecureWare[tm]'s method of + * generating ciphertext. + * Not recommended because of some potential weaknesses. --marekm + */ + +#undef DOUBLESIZE +#undef SW_CRYPT + +/* + * Define SKEY to allow dual-mode SKEY/normal logins + */ + +#undef SKEY + +/* + * Define AGING if you want the password aging checks made. + * Release 3 has a requirement that AGING always be defined. + */ + +#define AGING + +/* + * Pick your version of DBM. If you define either DBM or NDBM, you must + * define GETPWENT. If you define NDBM you must define GETGRENT as well. + */ + +/* + * DBM support is untested, not recommended yet. It might make more + * sense if someone could add it to getpwnam() etc. in libc so that all + * programs (such as ls) can benefit from it. Any volunteers? + * + * The old DBM (as opposed to NDBM) support may be removed in a future + * release if no one complains. It's too braindamaged for the number + * of #ifdefs it adds (only one database per process at a time). + * + * On Linux, NDBM is actually implemented using GDBM, which is licensed + * under the GPL (not LGPL!) - I'm not sure if it is legal to link it + * with non-GPL code (such as the shadow suite). Consult your lawyers, + * or just modify the code to use db instead. Welcome to the wonderful + * world of copyrights. Yuck! + * + * The current DBM support code has a subtle design flaw. See my + * comment in pwdbm.c for details... + * + * Unless you have 2000 users or so, DBM probably doesn't make things + * much faster, and it does make things more complicated (= possibly + * more buggy). Do it only if you know what you're doing! --marekm + */ + +#undef DBM +#undef NDBM + +/* + * Define USE_SYSLOG if you want to have SYSLOG functions included in your code. + */ + +#define USE_SYSLOG + +/* + * Enable RLOGIN to support the "-r" and "-h" options. + * Also enable UT_HOST if your /etc/utmp provides for a host name. + */ + +#define RLOGIN +#define UT_HOST + +/* + * Define NO_RFLG to remove support for login -r flag if your system has + * a new-style rlogind which doesn't need it. --marekm + */ + +#define NO_RFLG + +/* + * Define the "success" code from ruserok(). Most modern systems use 0 + * for success and -1 for failure, while certain older versions use 1 + * for success and 0 for failure. Please check your manpage to be sure. + */ + +#define RUSEROK 0 + +/* + * Select one of the following + */ + +#undef DIR_XENIX /* include , use (struct direct) */ +#undef DIR_BSD /* include , use (struct direct) */ +#define DIR_SYSV /* include , use (struct dirent) */ + +/* + * Various system environment definitions. + */ + +/* + * Define if you have sgetgrent() in libc, to remove this function from + * libshadow.a (some versions of libc5 reportedly have it, most reports + * so far are from Red Hat 2.1 users, more information is welcome). + */ +#undef HAVE_SGETGRENT + +/* + * Only important if you compile with GETGRENT defined (use my getgr*() + * but still use fgetgrent() from libc if HAVE_FGETGRENT defined). + */ +#undef HAVE_FGETGRENT + +#define HAVE_SIGACTION +#define HAVE_GETUSERSHELL /* Define if your UNIX supports getusershell() */ +#define HAVE_LL_HOST /* Define if "struct lastlog" contains ll_host */ +#define HAVE_ULIMIT /* Define if your UNIX supports ulimit() */ +#define HAVE_RLIMIT /* Define if your UNIX supports setrlimit() */ +#undef GETPWENT /* Define if you want my GETPWENT(3) routines */ +#undef GETGRENT /* Define if you want my GETGRENT(3) routines */ +#define NEED_AL64 /* Define if library does not include a64l() */ +#undef NEED_MKDIR /* Define if system does not have mkdir() */ +#undef NEED_RMDIR /* Define if system does not have rmdir() */ +#undef NEED_RENAME /* Define if system does not have rename() */ +#undef NEED_STRSTR /* Define if library does not include strstr() */ +#undef NEED_PUTPWENT /* Define if library does not include putpwent()*/ +#define SIGTYPE void /* Type returned by signal() */ + +/* + * These definitions MUST agree with the values defined in . + */ + +#undef BSD_QUOTA /* the pw_quota field exists */ +#undef ATT_AGE /* the pw_age field exists */ +#undef ATT_COMMENT /* the pw_comment field exists */ + +#define UID_T uid_t /* set to be the type of UID's */ +#define GID_T gid_t /* set to be the type of GID's */ + +#ifndef UID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define UID_T uid_t +#else +#define UID_T int +#endif +#endif + +#ifndef GID_T +#if defined(SVR4) || defined(_POSIX_SOURCE) +#define GID_T gid_t +#else +#define GID_T int +#endif +#endif + +/* + * Define NDEBUG for production versions + */ + +#define NDEBUG + +/* + * Define PWDFILE and GRPFILE to the names of the password and + * group files. //jiivee + */ + +#define PASSWD_FILE "/etc/passwd" +#define PASSWD_PAG_FILE "/etc/passwd.pag" +#define GROUP_FILE "/etc/group" +#define GROUP_PAG_FILE "/etc/group.pag" + +#ifdef SHADOWPWD +#define SHADOW_FILE "/etc/shadow" +#define SHADOW_PAG_FILE "/etc/shadow.pag" +#ifdef SHADOWGRP +#define SGROUP_FILE "/etc/gshadow" +#define SGROUP_PAG_FILE "/etc/gshadow.pag" +#endif +#endif + +/* + * The structure of the utmp file. There are two kinds of UTMP files, + * "BSD" and "USG". "BSD" has no PID or type information, "USG" does. + * If you define neither of these, the type will be defaulted by using + * BSD, SUN, SYS3 and USG defines. + */ + +#define _UTMP_FILE "/var/run/utmp" +#define _WTMP_FILE "/var/log/wtmp" + +#define USG_UTMP /**/ +/* #define BSD_UTMP */ + +#if !defined(USG_UTMP) && !defined(BSD_UTMP) +#if defined(BSD) || defined(SYS3) || defined(SUN) +#define BSD_UTMP +#else +#define USG_UTMP +#endif /* BSD || SYS3 || SUN */ +#endif /* !USG_UTMP || !BSD_UTMP */ + +/* + * From where to look for legal user shells + */ + +#ifndef SHELLS_FILE +#define SHELLS_FILE "/etc/shells" +#endif + +/* + * Default issue file location + */ + +#ifndef ISSUE_FILE +#define ISSUE_FILE "/etc/issue" +#endif + +/* + * Logoutd message file + */ + +#define HUP_MESG_FILE "/etc/logoutd.mesg" + +/* + * Mail spool directory. This is used if mailspool cannot be located otherwise + */ + +#ifndef MAIL_SPOOL_DIR +#define MAIL_SPOOL_DIR "/var/spool/mail" +#endif + +/* + * Where are new user default setup files kept + */ + +#define SKEL_DIR "/etc/skel" + +/* + * New user defaults. The NEW_USER_FILE must have 6 X's in the end of name + */ + +#define USER_DEFAULTS_FILE "/etc/default/useradd" +#define NEW_USER_FILE "/etc/default/nuaddXXXXXX" + +/* + * Telinit program. If your system uses /etc/telinit to change run + * level, define TELINIT and then define the RUNLEVEL macro to be the + * run-level to switch INIT to. This is used by sulogin to change + * from single user to multi-user mode. + * + * From bluca@www.polimi.it: instead, set up /etc/inittab properly + * ~0:S:wait:/sbin/sulogin + * ~9:S:wait:/sbin/telinit -t0 2 + */ + +#undef TELINIT +#undef PATH_TELINIT "/sbin/telinit" +#undef RUNLEVEL "2" + +/* + * Crontab and atrm. Used in userdel.c - see user_cancel(). Verify + * that these are correct for your distribution. --marekm + */ + +#if 0 /* old Slackware */ +#define CRONTAB_COMMAND "/usr/bin/crontab -d -u %s" +#define CRONTAB_FILE "/var/cron/tabs/%s" +#else +/* Debian 0.93R6 (marekm): */ +#define CRONTAB_COMMAND "/usr/bin/crontab -r -u %s" +#define CRONTAB_FILE "/var/spool/cron/crontabs/%s" +/* Red Hat 2.1 (jiivee@iki.fi): */ +/* #define CRONTAB_FILE "/var/spool/cron/%s" */ +#endif + +/* + * Hmmm, had to #undef this since at-2.8a on Linux doesn't have an option + * to remove all jobs owned by some user. + * + * Fortunately, atrun will not run any at jobs for users not listed in + * /etc/passwd. Unfortunately, if you remove a user and add a new user + * with the same UID before it is time to run the old at job, atrun will + * not notice this and run the old job. Not good. The best fix right + * now is to remove any at jobs left over by hand, and not reuse any + * previously used UID values. + * + * We probably should discuss this with the at maintainer... It might + * be better to store at jobs by user names, not UIDs. --marekm + */ + +#undef ATRM_COMMAND + +/* + * Login times log file location. + */ + +#define LASTLOG_FILE "/var/log/lastlog" + +/* + * Linux FSSTND recommends that the chfn, chsh, gpasswd, passwd commands + * are in /usr/bin, not /bin (not needed before mounting /usr). --marekm + */ + +#define CHFN_PROGRAM "/usr/bin/chfn" +#define CHSH_PROGRAM "/usr/bin/chsh" +#define GPASSWD_PROGRAM "/usr/bin/gpasswd" +#define PASSWD_PROGRAM "/usr/bin/passwd" + +/* + * On most Linux systems, the login prompt is "hostname login: ". Some + * automatic login scripts depend on it. If not defined, the default is + * just "login: ". %s is replaced by the hostname. --marekm + */ + +#define LOGIN_PROMPT "%s login: " + +/* + * Define to enable (warning: completely unsupported by me) administrator + * defined authentication methods. Most programs are not aware of them, + * so we can remove some code and possibly some bugs :-). PAM (when done) + * will replace much of this anyway... --marekm + */ + +/* #define AUTH_METHODS */ + +/* + * Define to enable detailed login access control (a la logdaemon/FreeBSD) + * and su access control (much more powerful/fascist than the traditional + * BSD-style "wheel group" feature). Any volunteers to convince the GNU + * folks that they should add access control to their version of su? + * Call me a fascist, but then I'll have to call you a communist :-). + */ + +#define LOGIN_ACCESS +#define SU_ACCESS + +/* see faillog.h for more info what it is */ +#define FAILLOG_LOCKTIME + +/* see lmain.c and login.defs.linux */ +#define CONSOLE_GROUPS + +#endif /* _CONFIG_H */ diff --git a/old/pwconv-old.8 b/old/pwconv-old.8 new file mode 100644 index 00000000..a8ad7bbb --- /dev/null +++ b/old/pwconv-old.8 @@ -0,0 +1,66 @@ +.\" Copyright 1989 - 1993, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pwconv-old.8,v 1.1 1997/09/29 22:01:31 marekm Exp $ +.\" +.TH PWCONV 8 +.SH NAME +pwconv \- convert and update shadow password files +.SH SYNOPSIS +.B pwconv +.SH DESCRIPTION +\fBPwconv\fR copies the old password file information to a new shadow +password file, +merging entries from an optional existing shadow file. +The new password file is left in \fInpasswd\fR, +the new shadow file is left in \fInshadow\fR. +Both of these are files are created with modes which only permit +read access to the owner. +Existing shadow entries are copied as is. +Shadow entries in the System V Release 3.2 format will be silently +converted to the new System V Release 4 format on output. +Any entries which are missing fields will have those fields +filled in with default values where appropriate. +New entries are created with passwords which expire in 10000 days, +with a last changed date of today, +unless password aging information was already present. +Entries with blank passwords are not copied to the shadow file at all. +.SH FILES +/etc/passwd \- old encrypted passwords and password aging +.br +/etc/shadow \- previously converted shadow password file +.br +./npasswd \- new password file +.br +./nshadow \- new shadow password file +.SH SEE ALSO +.BR passwd (1), +.BR passwd (5), +.BR shadow (5), +.BR pwunconv (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@tab.com) diff --git a/old/pwconv-old.c b/old/pwconv-old.c new file mode 100644 index 00000000..e8531fdb --- /dev/null +++ b/old/pwconv-old.c @@ -0,0 +1,217 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * pwconv - convert and update shadow password files + * + * Pwconv copies the old password file information to a new shadow + * password file, merging entries from an optional existing shadow + * file. + * + * The new password file is left in npasswd, the new shadow file is + * left in nshadow. Existing shadow entries are copied as is. + * New entries are created with passwords which expire in MAXDAYS days, + * with a last changed date of today, unless password aging + * information was already present. Likewise, the minimum number of + * days before which the password may be changed is controlled by + * MINDAYS. The number of warning days is set to WARNAGE if that + * macro exists. Entries with blank passwordsare not copied to the + * shadow file at all. + */ + +#include +#ifndef SHADOWPWD + +main() +{ + fprintf (stderr, "Shadow passwords are not configured.\n"); + exit (1); +} + +#else /*{*/ + +#include "rcsid.h" +RCSID("$Id: pwconv-old.c,v 1.1 1997/05/01 23:11:59 marekm Exp $") + +#include +#include +#include +#include +#include "defines.h" + +#include "getdef.h" + +static char buf[BUFSIZ]; + +long a64l (); + +int +main() +{ + long today; + struct passwd *pw; + struct passwd *sgetpwent (); + FILE *pwd; + FILE *npwd; + FILE *shadow; + struct spwd *spwd; + struct spwd tspwd; + int fd; + char *cp; + + if (! (pwd = fopen (PASSWD_FILE, "r"))) { + perror (PASSWD_FILE); + exit (1); + } + unlink ("npasswd"); + if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0 || + ! (npwd = fdopen (fd, "w"))) { + perror ("npasswd"); + exit (1); + } + unlink ("nshadow"); + if ((fd = open ("nshadow", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 || + ! (shadow = fdopen (fd, "w"))) { + perror ("nshadow"); + (void) unlink ("npasswd"); + (void) unlink ("nshadow"); + exit (1); + } + + (void) time (&today); + today /= (24L * 60L * 60L); + + while (fgets (buf, sizeof buf, pwd) == buf) { + if ((cp = strrchr (buf, '\n'))) + *cp = '\0'; + + if (buf[0] == '#') { /* comment line */ + (void) fprintf (npwd, "%s\n", buf); + continue; + } + if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */ + (void) fprintf (npwd, "%s\n", buf); + continue; + } +#if 0 /* convert all entries, even if no passwd. --marekm */ + if (pw->pw_passwd[0] == '\0') { /* no password, skip */ + (void) fprintf (npwd, "%s\n", buf); + continue; + } +#endif + setspent (); /* rewind old shadow file */ + +#if 0 + if ((spwd = getspnam(pw->pw_name))) { +#else + /* + * If the user exists, getspnam() in NYS libc (at least + * on Red Hat 3.0.3) always succeeds if the user exists, + * even if there is no /etc/shadow file. As a result, + * passwords are left in /etc/passwd after pwconv! + * + * Copy existing shadow entries only if the encrypted + * password field in /etc/passwd is "x" - this indicates + * that the shadow password is really there. --marekm + */ + spwd = getspnam(pw->pw_name); + if (spwd && strcmp(pw->pw_passwd, "x") == 0) { +#endif + if (putspent (spwd, shadow)) { /* copy old entry */ + perror ("nshadow"); + goto error; + } + } else { /* need a new entry. */ + tspwd.sp_namp = pw->pw_name; + tspwd.sp_pwdp = pw->pw_passwd; + pw->pw_passwd = "x"; +#ifdef ATT_AGE + if (pw->pw_age) { /* copy old password age stuff */ + if ((int) strlen (pw->pw_age) >= 2) { + tspwd.sp_min = c64i (pw->pw_age[1]); + tspwd.sp_max = c64i (pw->pw_age[0]); + } else { + tspwd.sp_min = tspwd.sp_max = -1; + } + if (strlen (pw->pw_age) == 4) + tspwd.sp_lstchg = a64l (&pw->pw_age[2]); + else + tspwd.sp_lstchg = -1; + + /* + * Convert weeks to days + */ + + if (tspwd.sp_min != -1) + tspwd.sp_min *= 7; + + if (tspwd.sp_max != -1) + tspwd.sp_max *= 7; + + if (tspwd.sp_lstchg != -1) + tspwd.sp_lstchg *= 7; + } else +#endif /* ATT_AGE */ + { /* fake up new password age stuff */ + tspwd.sp_max = getdef_num("PASS_MAX_DAYS", -1); + tspwd.sp_min = getdef_num("PASS_MIN_DAYS", 0); + tspwd.sp_lstchg = today; + } + tspwd.sp_warn = getdef_num("PASS_WARN_AGE", -1); + tspwd.sp_inact = tspwd.sp_expire = tspwd.sp_flag = -1; + if (putspent (&tspwd, shadow)) { /* output entry */ + perror ("nshadow"); + goto error; + } + } + (void) fprintf (npwd, "%s:%s:%d:%d:%s:%s:", + pw->pw_name, pw->pw_passwd, + pw->pw_uid, pw->pw_gid, + pw->pw_gecos, pw->pw_dir); + + if (fprintf (npwd, "%s\n", + pw->pw_shell ? pw->pw_shell:"") == EOF) { + perror ("npasswd"); + goto error; + } + } + endspent (); + + if (ferror (npwd) || ferror (shadow)) { + perror ("pwconv"); +error: + (void) unlink ("npasswd"); + (void) unlink ("nshadow"); + exit (1); + } + (void) fclose (pwd); + (void) fclose (npwd); + (void) fclose (shadow); + + exit (0); +} +#endif /*}*/ diff --git a/old/pwconv.8 b/old/pwconv.8 new file mode 100644 index 00000000..c13bdba4 --- /dev/null +++ b/old/pwconv.8 @@ -0,0 +1,59 @@ +.\" Copyright 1989 - 1993, Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pwconv.8,v 1.1 1997/12/07 23:27:13 marekm Exp $ +.\" +.TH PWCONV 8 +.SH NAME +pwconv \- convert and update shadow password files +.SH SYNOPSIS +.B pwconv +.SH DESCRIPTION +\fBPwconv\fR copies the password file information from \fI/etc/passwd\fR +to the shadow password file, \fI/etc/shadow\fR. +If the \fI/etc/shadow\fR file does not exist, it is created with +modes which only permit read access to the owner. +Shadow entries in the System V Release 3.2 format will be silently +converted to the new System V Release 4 format. +Any entries which are missing fields will have those fields +filled in with default values where appropriate. +New entries are created with passwords which expire in 10000 days, +with a last changed date of today, +unless password aging information was already present. +Shadow entries without corresponding entries in \fI/etc/passwd\fR +are removed. +.SH FILES +/etc/passwd +.br +/etc/shadow +.SH SEE ALSO +.BR passwd (1), +.BR passwd (5), +.BR shadow (5), +.BR pwunconv (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@tab.com) diff --git a/old/pwd.h.m4 b/old/pwd.h.m4 new file mode 100644 index 00000000..313f4a59 --- /dev/null +++ b/old/pwd.h.m4 @@ -0,0 +1,138 @@ +/* + * Copyright 1990, 1991, 1992, Julianne Frances Haugh and Steve Simmons + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Standard definitions for password files. This is an independant + * reimplementation of the definitions used by AT&T, BSD, and POSIX. + * It is not derived from any of those sources. Note that it can be + * site-defined to have non-POSIX features as well. Ideally this file + * is simply replaced by the standard system supplied /usr/include/pwd.h + * file. + * + * @(#)pwd.h.m4 3.4.1.3 12:55:53 05 Feb 1994 + * $Id: pwd.h.m4,v 1.2 1997/05/01 23:11:59 marekm Exp $ + */ + +#ifndef PWD_H +#define PWD_H + +#ifdef M_XENIX +typedef int uid_t; +typedef int gid_t; +#endif + +#if defined(SUN) || defined(SUN4) +#include +#endif + +#ifdef SVR4 +#include +#ifndef _POSIX_SOURCE +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#else /* _POSIX_SOURCE */ +#include +#endif /* !_POSIX_SOURCE */ +#define NGROUPS NGROUPS_MAX +#endif /* SVR4 */ + +ifdef(`SUN4', `#define ATT_AGE') +ifdef(`SUN4', `#define ATT_COMMENT') +ifdef(`SUN', `#define BSD_QUOTA') +ifdef(`BSD', `#define BSD_QUOTA') +ifdef(`AIX', `', `ifdef(`USG', `#define ATT_AGE')') +ifdef(`AIX', `', `ifdef(`USG', `#define ATT_COMMENT')') + +/* + * This is the data structure returned by the getpw* functions. The + * names of the elements and the structure are taken from traditional + * usage. + */ + +struct passwd { + char *pw_name ; /* User login name */ + char *pw_passwd ; /* Encrypted passwd or dummy field */ + uid_t pw_uid ; /* User uid number */ + gid_t pw_gid ; /* User group id number */ +#ifdef BSD_QUOTA + /* Most BSD systems have quotas, most USG ones don't */ + int pw_quota ; /* The BSD magic doodah */ +#endif +#ifdef ATT_AGE + /* Use ATT-style password aging */ + char *pw_age ; /* ATT radix-64 encoded data */ +#endif +#ifdef ATT_COMMENT + /* Provide the unused comment field */ + char *pw_comment; /* Unused comment field */ +#endif + char *pw_gecos ; /* ASCII user name, other data */ + char *pw_dir ; /* User home directory */ + char *pw_shell ; /* User startup shell */ +} ; + +#ifdef ATT_COMMENT +/* Provide the unused comment structure */ +struct comment { + char *c_dept; + char *c_name; + char *c_acct; + char *c_bin; +}; +#endif + +#if __STDC__ + +extern struct passwd *getpwent( void ) ; +extern struct passwd *getpwuid( uid_t user_uid ) ; +extern struct passwd *getpwnam( char *name ) ; +#ifdef SVR4 +void setpwent( void ); +void endpwent( void ); +#else +int setpwent( void ); +int endpwent( void ); +#endif + +#else + +extern struct passwd *getpwent(); +extern struct passwd *getpwuid(); +extern struct passwd *getpwnam(); +#ifdef SVR4 +void setpwent(); +void endpwent(); +#else +int setpwent(); +int endpwent(); +#endif +#endif /* of if __STDC__ */ + +#endif /* of ifdef PWD_H */ diff --git a/old/pwunconv-old.8 b/old/pwunconv-old.8 new file mode 100644 index 00000000..381dc808 --- /dev/null +++ b/old/pwunconv-old.8 @@ -0,0 +1,57 @@ +.\" Copyright 1989 - 1993 Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pwunconv-old.8,v 1.1 1997/09/29 22:01:31 marekm Exp $ +.\" +.TH PWUNCONV 8 +.SH NAME +pwunconv \- restore old password file from shadow password file +.SH SYNOPSIS +.B pwunconv +.SH DESCRIPTION +\fBPwunconv\fR copies the password file information from the shadow +password file, +merging entries from an optional existing shadow file. +The new password file is left in \fInpasswd\fR. +This file is created with modes which allow read access for +the owner only. +There is no new shadow file. +Password aging information is translated where possible. +There is some loss of resolution in the password aging information. +.SH FILES +/etc/passwd \- old encrypted passwords and password aging +.br +/etc/shadow \- previously converted shadow password file +.br +./npasswd \- new password file +.SH SEE ALSO +.BR passwd (1), +.BR passwd (5), +.BR shadow (5), +.BR pwconv (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@tab.com) diff --git a/old/pwunconv-old.c b/old/pwunconv-old.c new file mode 100644 index 00000000..e54d83ef --- /dev/null +++ b/old/pwunconv-old.c @@ -0,0 +1,150 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * pwunconv - restore old password file from shadow password file. + * + * Pwunconv copies the password file information from the shadow + * password file, merging entries from an optional existing shadow + * file. + * + * The new password file is left in npasswd. There is no new + * shadow file. Password aging information is translated where + * possible. + */ + +#include + +#include "rcsid.h" +RCSID("$Id: pwunconv-old.c,v 1.1 1997/05/01 23:11:59 marekm Exp $") + +#include "defines.h" +#include +#include +#include +#include + +#ifndef SHADOWPWD +int +main() +{ + fprintf (stderr, "Shadow passwords are not configured.\n"); + exit (1); +} + +#else /*{*/ + +char buf[BUFSIZ]; +char *l64a (); + +int +main() +{ + struct passwd *pw; + struct passwd *sgetpwent (); + FILE *pwd; + FILE *npwd; + struct spwd *spwd; + int fd; +#ifdef ATT_AGE + char newage[5]; +#endif + + if (! (pwd = fopen (PASSWD_FILE, "r"))) { + perror (PASSWD_FILE); + return (1); + } + unlink ("npasswd"); + if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 || + ! (npwd = fdopen (fd, "w"))) { + perror ("npasswd"); + return (1); + } + while (fgets (buf, sizeof buf, pwd) == buf) { + buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */ + + if (buf[0] == '#') { /* comment line */ + (void) fprintf (npwd, "%s\n", buf); + continue; + } + if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */ + (void) fprintf (npwd, "%s\n", buf); + continue; + } + setspent (); /* rewind shadow file */ + + if (! (spwd = getspnam (pw->pw_name))) { + (void) fprintf (npwd, "%s\n", buf); + continue; + } + pw->pw_passwd = spwd->sp_pwdp; + + /* + * Password aging works differently in the two different systems. + * With shadow password files you apparently must have some aging + * information. The maxweeks or minweeks may not map exactly. + * In pwconv we set max == 10000, which is about 30 years. Here + * we have to undo that kludge. So, if maxdays == 10000, no aging + * information is put into the new file. Otherwise, the days are + * converted to weeks and so on. + */ + +#ifdef ATT_AGE + if (spwd->sp_max > (63*WEEK/SCALE) && spwd->sp_max < 10000) + spwd->sp_max = (63*WEEK/SCALE); /* 10000 is infinity */ + + if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 && + spwd->sp_max >= 0 && spwd->sp_max <= 63*7) { + if (spwd->sp_lstchg == -1) + spwd->sp_lstchg = 0; + + spwd->sp_max /= WEEK/SCALE; /* turn it into weeks */ + spwd->sp_min /= WEEK/SCALE; + spwd->sp_lstchg /= WEEK/SCALE; + + strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) + + spwd->sp_min * (64L) + spwd->sp_max), 5); + pw->pw_age = newage; + } else + pw->pw_age = ""; +#endif /* ATT_AGE */ + if (putpwent (pw, npwd)) { + perror ("pwunconv: write error"); + exit (1); + } + } + endspent (); + + if (ferror (npwd)) { + perror ("pwunconv"); + (void) unlink ("npasswd"); + } + (void) fclose (npwd); + (void) fclose (pwd); + return (0); +} +#endif diff --git a/old/pwunconv.8 b/old/pwunconv.8 new file mode 100644 index 00000000..7f6520db --- /dev/null +++ b/old/pwunconv.8 @@ -0,0 +1,51 @@ +.\" Copyright 1989 - 1993 Julianne Frances Haugh +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of Julianne F. Haugh nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: pwunconv.8,v 1.1 1997/12/14 20:07:22 marekm Exp $ +.\" +.TH PWUNCONV 8 +.SH NAME +pwunconv \- restore old password file from shadow password file +.SH SYNOPSIS +.B pwunconv +.SH DESCRIPTION +\fBPwunconv\fR copies the password file information from the shadow +password file \fI/etc/shadow\fR, to the password file \fI/etc/passwd\fR. +The \fI/etc/shadow\fR file is then removed. +Password aging information is translated where possible. +There is some loss of resolution in the password aging information. +.SH FILES +/etc/passwd +.br +/etc/shadow +.SH SEE ALSO +.BR passwd (1), +.BR passwd (5), +.BR shadow (5), +.BR pwconv (8) +.SH AUTHOR +Julianne Frances Haugh (jfh@tab.com) diff --git a/old/scologin.c b/old/scologin.c new file mode 100644 index 00000000..0efe5a33 --- /dev/null +++ b/old/scologin.c @@ -0,0 +1,107 @@ +/* + * Copyright 1991, Julianne Frances Haugh and Chip Rosenthal + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$Id: scologin.c,v 1.1 1997/05/01 23:12:00 marekm Exp $"; +#endif + +#include +#include + +#define USAGE "usage: %s [ -r remote_host remote_user local_user [ term_type ] ]\n" +#define LOGIN "/etc/login" + +extern int errno; +extern char *sys_errlist[]; +extern char **environ; + +int +main(argc, argv) +int argc; +char *argv[]; +{ + char *rhost, *ruser, *luser; + char term[1024], *nargv[8], *nenvp[2]; + int root_user, i; + struct passwd *pw; + + if (argc == 1) { + + /* + * Called from telnetd. + */ + nargv[0] = "login"; + nargv[1] = "-p"; + nargv[2] = NULL; + + } else if (strcmp(argv[1], "-r") == 0 && argc >= 6) { + + /* + * Called from rlogind. + */ + + rhost = argv[2]; + ruser = argv[3]; + luser = argv[4]; + root_user = ((pw = getpwnam(luser)) != NULL && pw->pw_uid == 0); + + i = 0; + if ( argc == 6 ) { + strcpy(term, "TERM="); + strncat(term+sizeof("TERM=")-1, + argv[5], sizeof(term)-sizeof("TERM=")); + term[sizeof(term)-1] = '\0'; + nenvp[i++] = term; + } + nenvp[i++] = NULL; + environ = nenvp; + + i = 0; + nargv[i++] = "login"; + nargv[i++] = "-p"; + nargv[i++] = "-h"; + nargv[i++] = rhost; + if (ruserok(rhost, root_user, ruser, luser) == 0) + nargv[i++] = "-f"; + nargv[i++] = luser; + nargv[i++] = NULL; + + } else { + + fprintf(stderr, USAGE, argv[0]); + exit(1); + + } + + (void) execv(LOGIN, nargv); + fprintf(stderr, "%s: could not exec '%s' [%s]\n", + argv[0], LOGIN, sys_errlist[errno]); + exit(1); + /*NOTREACHED*/ +} diff --git a/old/vipw.8 b/old/vipw.8 new file mode 100644 index 00000000..b8503c9c --- /dev/null +++ b/old/vipw.8 @@ -0,0 +1,69 @@ +.\" Copyright (c) 1983, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)vipw.8 6.7 (Berkeley) 3/16/91 +.\" $Id: vipw.8,v 1.1 1997/12/07 23:27:13 marekm Exp $ +.\" +.Dd March 13, 1997 +.Dt VIPW 8 +.Os BSD 4 +.Sh NAME +.Nm vipw, vigr +.Nd edit the password, group, shadow, or sgroup file +.Sh SYNOPSIS +.Nm vipw [-s] +.Nm vigr [-s] +.Sh DESCRIPTION +.Nm Vipw +and +.Nm vigr +edit the password and group files, respectively, after setting the +appropriate locks. With the -s option, they will edit the shadow and +sgroup files. They do any necessary processing after +the files are unlocked. If the password or group file is already +locked for editing by another user, you will be asked to try again +later. +The default editor under Debian GNU/Linux is +.Xr ae 1 . +.Sh ENVIRONMENT +vipw and vigr will try the environment variables VISUAL and EDITOR +before defaulting to +.Xr ae 1 . +.Sh SEE ALSO +.Xr passwd 5 , +.Xr group 5 , +.Xr shadow 5 , +.Xr sgroup 5 +.Sh HISTORY +The +.Nm vipw +command appeared in +.Bx 4.0 . diff --git a/po/ChangeLog b/po/ChangeLog new file mode 100644 index 00000000..e69de29b diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 00000000..111b40fc --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,248 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. + +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = $(prefix)/@DATADIRNAME@ +localedir = $(datadir)/locale +gnulocaledir = $(prefix)/share/locale +gettextsrcdir = $(prefix)/share/gettext/po +subdir = po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@ + +CC = @CC@ +GENCAT = @GENCAT@ +GMSGFMT = PATH=../src:$$PATH @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = PATH=../src:$$PATH @XGETTEXT@ +MSGMERGE = PATH=../src:$$PATH msgmerge + +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ + +INCLUDES = -I.. -I$(top_srcdir)/intl + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +SOURCES = cat-id-tbl.c +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(PACKAGE).pot \ +stamp-cat-id $(POFILES) $(GMOFILES) $(SOURCES) + +POTFILES = \ + +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +INSTOBJEXT = @INSTOBJEXT@ + +.SUFFIXES: +.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat + +.c.o: + $(COMPILE) $< + +.po.pox: + $(MAKE) $(PACKAGE).pot + $(MSGMERGE) $< $(srcdir)/$(PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && $(GENCAT) $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: cat-id-tbl.c $(CATALOGS) +all-no: + +$(srcdir)/$(PACKAGE).pot: $(POTFILES) + $(XGETTEXT) --default-domain=$(PACKAGE) --directory=$(top_srcdir) \ + --add-comments --keyword=_ --keyword=N_ \ + --files-from=$(srcdir)/POTFILES.in \ + && test ! -f $(PACKAGE).po \ + || ( rm -f $(srcdir)/$(PACKAGE).pot \ + && mv $(PACKAGE).po $(srcdir)/$(PACKAGE).pot ) + +$(srcdir)/cat-id-tbl.c: stamp-cat-id; @: +$(srcdir)/stamp-cat-id: $(PACKAGE).pot + rm -f cat-id-tbl.tmp + sed -f ../intl/po2tbl.sed $(srcdir)/$(PACKAGE).pot \ + | sed -e "s/@PACKAGE NAME@/$(PACKAGE)/" > cat-id-tbl.tmp + if cmp -s cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; then \ + rm cat-id-tbl.tmp; \ + else \ + echo cat-id-tbl.c changed; \ + rm -f $(srcdir)/cat-id-tbl.c; \ + mv cat-id-tbl.tmp $(srcdir)/cat-id-tbl.c; \ + fi + cd $(srcdir) && rm -f stamp-cat-id && echo timestamp > stamp-cat-id + + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(datadir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(datadir); \ + fi + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + case "$$cat" in \ + *.gmo) destdir=$(gnulocaledir);; \ + *) destdir=$(localedir);; \ + esac; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + dir=$$destdir/$$lang/LC_MESSAGES; \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $$dir; \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \ + fi; \ + if test -r $$cat; then \ + $(INSTALL_DATA) $$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \ + echo "installing $$cat as $$dir/$(PACKAGE)$(INSTOBJEXT)"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(PACKAGE)$(INSTOBJEXT); \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(PACKAGE)$(INSTOBJEXT)"; \ + fi; \ + if test -r $$cat.m; then \ + $(INSTALL_DATA) $$cat.m $$dir/$(PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $$cat.m as $$dir/$(PACKAGE)$(INSTOBJEXT).m"; \ + else \ + if test -r $(srcdir)/$$cat.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$cat.m \ + $$dir/$(PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(PACKAGE)$(INSTOBJEXT).m"; \ + else \ + true; \ + fi; \ + fi; \ + done + if test "$(PACKAGE)" = "gettext"; then \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(gettextsrcdir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(gettextsrcdir); \ + fi; \ + $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ + $(gettextsrcdir)/Makefile.in.in; \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \ + rm -f $(localedir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \ + rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT); \ + rm -f $(gnulocaledir)/$$lang/LC_MESSAGES/$(PACKAGE)$(INSTOBJEXT).m; \ + done + rm -f $(gettextsrcdir)/po-Makefile.in.in + +check: all + +cat-id-tbl.o: ../intl/libgettext.h + +dvi info tags TAGS ID: + +mostlyclean: + rm -f core core.* *.pox $(PACKAGE).po *.old.po cat-id-tbl.tmp + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f $(GMOFILES) + +distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) +dist distdir: update-po $(DISTFILES) + dists="$(DISTFILES)"; \ + for file in $$dists; do \ + ln $(srcdir)/$$file $(distdir) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(PACKAGE).pot + PATH=`pwd`/../src:$$PATH; \ + cd $(srcdir); \ + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + mv $$lang.po $$lang.old.po; \ + echo "$$lang:"; \ + if $(MSGMERGE) $$lang.old.po $(PACKAGE).pot -o $$lang.po; then \ + rm -f $$lang.old.po; \ + else \ + echo "msgmerge for $$cat failed!"; \ + rm -f $$lang.po; \ + mv $$lang.old.po $$lang.po; \ + fi; \ + done + +POTFILES: POTFILES.in + ( if test 'x$(srcdir)' != 'x.'; then \ + posrcprefix='$(top_srcdir)/'; \ + else \ + posrcprefix="../"; \ + fi; \ + rm -f $@-t $@ \ + && (sed -e '/^#/d' -e '/^[ ]*$$/d' \ + -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \ + | sed -e '$$s/\\$$//') > $@-t \ + && chmod a-w $@-t \ + && mv $@-t $@ ) + +Makefile: Makefile.in.in ../config.status POTFILES + cd .. \ + && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 00000000..b04db505 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,123 @@ +# List of files which contain translatable strings. + +libmisc/addgrps.c +libmisc/age.c +libmisc/basename.c +libmisc/chkname.c +libmisc/chkshell.c +libmisc/chowndir.c +libmisc/chowntty.c +libmisc/console.c +libmisc/copydir.c +libmisc/entry.c +libmisc/env.c +libmisc/failure.c +libmisc/fields.c +libmisc/hushed.c +libmisc/isexpired.c +libmisc/limits.c +libmisc/list.c +libmisc/log.c +libmisc/login_access.c +libmisc/login_desrpc.c +libmisc/login_krb.c +libmisc/loginprompt.c +libmisc/mail.c +libmisc/motd.c +libmisc/myname.c +libmisc/obscure.c +libmisc/pam_pass.c +libmisc/pwd2spwd.c +libmisc/pwd_init.c +libmisc/rlogin.c +libmisc/salt.c +libmisc/setugid.c +libmisc/setup.c +libmisc/setupenv.c +libmisc/shell.c +libmisc/strtoday.c +libmisc/suauth.c +libmisc/sub.c +libmisc/sulog.c +libmisc/ttytype.c +libmisc/tz.c +libmisc/ulimit.c +libmisc/utmp.c +libmisc/valid.c +libmisc/xmalloc.c +lib/commonio.c +lib/dialchk.c +lib/dialup.c +lib/encrypt.c +lib/fputsx.c +lib/getdef.c +lib/getpass.c +lib/grdbm.c +lib/groupio.c +lib/grpack.c +lib/gsdbm.c +lib/gshadow.c +lib/gspack.c +lib/lockpw.c +lib/md5.c +lib/md5crypt.c +lib/mkdir.c +lib/port.c +lib/putgrent.c +lib/putpwent.c +lib/putspent.c +lib/pwauth.c +lib/pwdbm.c +lib/pwio.c +lib/pwpack.c +lib/rad64.c +lib/rename.c +lib/rmdir.c +lib/sgetgrent.c +lib/sgetpwent.c +lib/sgetspent.c +lib/sgroupio.c +lib/shadow.c +lib/shadowio.c +lib/snprintf.c +lib/spdbm.c +lib/sppack.c +lib/strcasecmp.c +lib/strdup.c +lib/strerror.c +lib/strstr.c +lib/tcfsio.c +lib/utent.c +src/chage.c +src/chfn.c +src/chpasswd.c +src/chsh.c +src/dpasswd.c +src/expiry.c +src/faillog.c +src/gpasswd.c +src/groupadd.c +src/groupdel.c +src/groupmod.c +src/groups.c +src/grpck.c +src/grpconv.c +src/grpunconv.c +src/id.c +src/lastlog.c +src/login.c +src/logoutd.c +src/mkpasswd.c +src/newgrp.c +src/newusers.c +src/passwd.c +src/pwck.c +src/pwconv.c +src/pwunconv.c +src/su.c +src/sulogin.c +src/useradd.c +src/userdel.c +src/usermod.c +src/vipw.c + diff --git a/po/cat-id-tbl.c b/po/cat-id-tbl.c new file mode 100644 index 00000000..743fffcd --- /dev/null +++ b/po/cat-id-tbl.c @@ -0,0 +1,500 @@ +/* Automatically generated by po2tbl.sed from shadow.pot. */ + +#if HAVE_CONFIG_H +# include +#endif + +#include "libgettext.h" + +const struct _msg_ent _msg_tbl[] = { + {"", 1}, + {"Warning: unknown group %s\n", 2}, + {"Warning: too many groups\n", 3}, + {"Your password has expired.", 4}, + {"Your password is inactive.", 5}, + {"Your login has expired.", 6}, + {" Contact the system administrator.\n", 7}, + {" Choose a new password.\n", 8}, + {"Your password will expire in %ld days.\n", 9}, + {"Your password will expire tomorrow.\n", 10}, + {"Your password will expire today.\n", 11}, + {"Unable to change tty %s", 12}, + {"Environment overflow\n", 13}, + {"You may not change $%s\n", 14}, + {"%d %s since last login. Last was %s on %s.\n", 15}, + {"failures", 16}, + {"failure", 17}, + {"Too many logins.\n", 18}, + {"Password does not decrypt secret key for %s.\n", 19}, + {"Could not set %s's secret key: is the keyserv daemon running?\n", 20}, + {"You have new mail.", 21}, + {"No mail.", 22}, + {"You have mail.", 23}, + {"Bad password: %s. ", 24}, + {"passwd: pam_start() failed, error %d\n", 25}, + {"passwd: %s\n", 26}, + {"Unable to cd to \"%s\"\n", 27}, + {"No directory, logging in with HOME=/", 28}, + {"Executing shell %s\n", 29}, + {"Cannot execute %s", 30}, + {"Access to su to that account DENIED.\n", 31}, + {"Password authentication bypassed.\n", 32}, + {"Please enter your OWN password as authentication.\n", 33}, + {"Invalid root directory \"%s\"\n", 34}, + {"Can't change root directory to \"%s\"\n", 35}, + {"malloc(%d) failed\n", 36}, + {"Dialup Password:", 37}, + {"Could not allocate space for config info.\n", 38}, + {"configuration error - unknown item '%s' (notify administrator)\n", 39}, + {"error - lookup '%s' failed\n", 40}, + {"%s not found\n", 41}, + {"Password: ", 42}, + {"%s's Password:", 43}, + {"Unknown error %d", 44}, + {"\ +Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -W warn ]\n\ + [ -I inactive ] [ -E expire ] [ -d last_day ] user\n", 45}, + {"Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -d last_day ] user\n", 46}, + {"\ +Enter the new value, or press return for the default\n\ +\n", 47}, + {"Minimum Password Age", 48}, + {"Maximum Password Age", 49}, + {"Last Password Change (YYYY-MM-DD)", 50}, + {"Password Expiration Warning", 51}, + {"Password Inactive", 52}, + {"Account Expiration Date (YYYY-MM-DD)", 53}, + {"Minimum:\t%ld\n", 54}, + {"Maximum:\t%ld\n", 55}, + {"Warning:\t%ld\n", 56}, + {"Inactive:\t%ld\n", 57}, + {"Last Change:\t\t", 58}, + {"Never\n", 59}, + {"Password Expires:\t", 60}, + {"%s: do not include \"l\" with other flags\n", 61}, + {"%s: permission denied\n", 62}, + {"%s: can't lock password file\n", 63}, + {"%s: can't open password file\n", 64}, + {"%s: unknown user: %s\n", 65}, + {"%s: can't lock shadow password file\n", 66}, + {"%s: can't open shadow password file\n", 67}, + {"Changing the aging information for %s\n", 68}, + {"%s: error changing fields\n", 69}, + {"%s: can't update password file\n", 70}, + {"%s: can't update shadow password file\n", 71}, + {"Error updating the DBM password entry.\n", 72}, + {"%s: can't rewrite shadow password file\n", 73}, + {"%s: can't rewrite password file\n", 74}, + {"%s: no aging information present\n", 75}, + {"\ +Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ]\n\ +\t[ -h home_ph ] [ -o other ] [ user ]\n", 76}, + {"\ +Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ] [ -h home_ph ]\n", 77}, + {"Enter the new value, or press return for the default\n", 78}, + {"Full Name", 79}, + {"\tFull Name: %s\n", 80}, + {"Room Number", 81}, + {"\tRoom Number: %s\n", 82}, + {"Work Phone", 83}, + {"\tWork Phone: %s\n", 84}, + {"Home Phone", 85}, + {"\tHome Phone: %s\n", 86}, + {"Other", 87}, + {"%s: Permission denied.\n", 88}, + {"%s: Unknown user %s\n", 89}, + {"%s: Cannot determine your user name.\n", 90}, + {"%s: cannot change user `%s' on NIS client.\n", 91}, + {"%s: `%s' is the NIS master for this client.\n", 92}, + {"Changing the user information for %s\n", 93}, + {"%s: invalid name: \"%s\"\n", 94}, + {"%s: invalid room number: \"%s\"\n", 95}, + {"%s: invalid work phone: \"%s\"\n", 96}, + {"%s: invalid home phone: \"%s\"\n", 97}, + {"%s: \"%s\" contains illegal characters\n", 98}, + {"%s: fields too long\n", 99}, + {"Cannot change ID to root.\n", 100}, + {"Cannot lock the password file; try again later.\n", 101}, + {"Cannot open the password file.\n", 102}, + {"%s: %s not found in /etc/passwd\n", 103}, + {"Error updating the password entry.\n", 104}, + {"Cannot commit password file changes.\n", 105}, + {"Cannot unlock the password file.\n", 106}, + {"usage: %s [-e]\n", 107}, + {"%s: can't lock shadow file\n", 108}, + {"%s: can't open shadow file\n", 109}, + {"%s: line %d: line too long\n", 110}, + {"%s: line %d: missing new password\n", 111}, + {"%s: line %d: unknown user %s\n", 112}, + {"%s: line %d: cannot update password entry\n", 113}, + {"%s: error detected, changes ignored\n", 114}, + {"%s: error updating shadow file\n", 115}, + {"%s: error updating password file\n", 116}, + {"Usage: %s [ -s shell ] [ name ]\n", 117}, + {"Login Shell", 118}, + {"You may not change the shell for %s.\n", 119}, + {"Changing the login shell for %s\n", 120}, + {"%s: Invalid entry: %s\n", 121}, + {"%s is an invalid shell.\n", 122}, + {"Usage: %s [ -(a|d) ] shell\n", 123}, + {"Shell password:", 124}, + {"re-enter Shell password:", 125}, + {"%s: Passwords do not match, try again.\n", 126}, + {"%s: can't create %s", 127}, + {"%s: can't open %s", 128}, + {"%s: Shell %s not found.\n", 129}, + {"Usage: expiry { -f | -c }\n", 130}, + {"%s: WARNING! Must be set-UID root!\n", 131}, + {"%s: unknown user\n", 132}, + {"usage: %s [-a|-u user] [-m max] [-r] [-t days] [-l locksecs]\n", 133}, + {"Unknown User: %s\n", 134}, + {"Username Failures Maximum Latest\n", 135}, + {" %s on %s", 136}, + {" [%lds left]", 137}, + {" [%lds lock]", 138}, + {"usage: %s [-r|-R] group\n", 139}, + {" %s [-a user] group\n", 140}, + {" %s [-d user] group\n", 141}, + {" %s [-A user,...] [-M user,...] group\n", 142}, + {" %s [-M user,...] group\n", 143}, + {"%s: unknown user %s\n", 144}, + {"Permission denied.\n", 145}, + {"%s: shadow group passwords required for -A\n", 146}, + {"Who are you?\n", 147}, + {"unknown group: %s\n", 148}, + {"Adding user %s to group %s\n", 149}, + {"Removing user %s from group %s\n", 150}, + {"%s: unknown member %s\n", 151}, + {"%s: Not a tty\n", 152}, + {"Changing the password for group %s\n", 153}, + {"New Password:", 154}, + {"Re-enter new password:", 155}, + {"They don't match; try again", 156}, + {"%s: Try again later\n", 157}, + {"%s: can't get lock\n", 158}, + {"%s: can't get shadow lock\n", 159}, + {"%s: can't open file\n", 160}, + {"%s: can't update entry\n", 161}, + {"%s: can't update shadow entry\n", 162}, + {"%s: can't re-write file\n", 163}, + {"%s: can't re-write shadow file\n", 164}, + {"%s: can't unlock file\n", 165}, + {"%s: can't update DBM files\n", 166}, + {"%s: can't update DBM shadow files\n", 167}, + {"usage: groupadd [-g gid [-o]] group\n", 168}, + {"%s: error adding new group entry\n", 169}, + {"%s: cannot add new dbm group entry\n", 170}, + {"%s: name %s is not unique\n", 171}, + {"%s: gid %ld is not unique\n", 172}, + {"%s: can't get unique gid\n", 173}, + {"%s: %s is a not a valid group name\n", 174}, + {"%s: invalid group %s\n", 175}, + {"%s: -O requires NAME=VALUE\n", 176}, + {"%s: cannot rewrite group file\n", 177}, + {"%s: cannot rewrite shadow group file\n", 178}, + {"%s: unable to lock group file\n", 179}, + {"%s: unable to open group file\n", 180}, + {"%s: unable to lock shadow group file\n", 181}, + {"%s: unable to open shadow group file\n", 182}, + {"%s: group %s exists\n", 183}, + {"usage: groupdel group\n", 184}, + {"%s: error removing group entry\n", 185}, + {"%s: error removing group dbm entry\n", 186}, + {"%s: error removing shadow group entry\n", 187}, + {"%s: error removing shadow group dbm entry\n", 188}, + {"%s: cannot remove user's primary group.\n", 189}, + {"%s: group %s does not exist\n", 190}, + {"%s: group %s is a NIS group\n", 191}, + {"%s: %s is the NIS master\n", 192}, + {"usage: groupmod [-g gid [-o]] [-n name] group\n", 193}, + {"%s: %s not found in /etc/group\n", 194}, + {"%s: cannot add new dbm shadow group entry\n", 195}, + {"%s: %ld is not a unique gid\n", 196}, + {"%s: %s is not a unique name\n", 197}, + {"unknown user %s\n", 198}, + {"Usage: %s [ -r ] [ group [ gshadow ] ]\n", 199}, + {"Usage: %s [ -r ] [ group ]\n", 200}, + {"No", 201}, + {"%s: cannot lock file %s\n", 202}, + {"%s: cannot open file %s\n", 203}, + {"invalid group file entry\n", 204}, + {"delete line `%s'? ", 205}, + {"duplicate group entry\n", 206}, + {"invalid group name `%s'\n", 207}, + {"group %s: bad GID (%d)\n", 208}, + {"group %s: no user %s\n", 209}, + {"delete member `%s'? ", 210}, + {"invalid shadow group file entry\n", 211}, + {"duplicate shadow group entry\n", 212}, + {"no matching group file entry\n", 213}, + {"shadow group %s: no administrative user %s\n", 214}, + {"delete administrative member `%s'? ", 215}, + {"shadow group %s: no user %s\n", 216}, + {"%s: cannot update file %s\n", 217}, + {"%s: the files have been updated; run mkpasswd\n", 218}, + {"%s: no changes\n", 219}, + {"%s: the files have been updated\n", 220}, + {"%s: can't lock group file\n", 221}, + {"%s: can't open group file\n", 222}, + {"%s: can't lock shadow group file\n", 223}, + {"%s: can't open shadow group file\n", 224}, + {"%s: can't remove shadow group %s\n", 225}, + {"%s: can't update shadow entry for %s\n", 226}, + {"%s: can't update entry for group %s\n", 227}, + {"%s: can't update shadow group file\n", 228}, + {"%s: can't update group file\n", 229}, + {"%s: not configured for shadow group support.\n", 230}, + {"%s: can't delete shadow group file\n", 231}, + {"usage: id [ -a ]\n", 232}, + {"usage: id\n", 233}, + {"uid=%d(%s)", 234}, + {"uid=%d", 235}, + {" gid=%d(%s)", 236}, + {" gid=%d", 237}, + {" euid=%d(%s)", 238}, + {" euid=%d", 239}, + {" egid=%d(%s)", 240}, + {" egid=%d", 241}, + {" groups=", 242}, + {"Username Port From Latest\n", 243}, + {"Username Port Latest\n", 244}, + {"**Never logged in**", 245}, + {"usage: %s [-p] [name]\n", 246}, + {" %s [-p] [-h host] [-f name]\n", 247}, + {" %s [-p] -r host\n", 248}, + {"Invalid login time\n", 249}, + {"\ +\n\ +System closed for routine maintenance\n", 250}, + {"\ +\n\ +[Disconnect bypassed -- root login allowed.]\n", 251}, + {"\ +\n\ +Login timed out after %d seconds.\n", 252}, + {" on `%.100s' from `%.200s'", 253}, + {" on `%.100s'", 254}, + {"\ +\n\ +%s login: ", 255}, + {"login: ", 256}, + {"Login incorrect", 257}, + {"Warning: login re-enabled after temporary lockout.\n", 258}, + {"Last login: %s on %s", 259}, + {"Last login: %.19s on %s", 260}, + {" from %.*s", 261}, + {"Starting rad_login\n", 262}, + {"%s: no DBM database on system - no action performed\n", 263}, + {"%s: cannot overwrite file %s\n", 264}, + {"%s: cannot open DBM files for %s\n", 265}, + {"%s: the beginning with ", 266}, + {"%s: error parsing line \"%s\"\n", 267}, + {"adding record for name ", 268}, + {"%s: error adding record for ", 269}, + {"added %d entries, longest was %d\n", 270}, + {"Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n", 271}, + {"Usage: %s [ -vf ] [ -p|g|sp ] file\n", 272}, + {"Usage: %s [ -vf ] [ -p|g ] file\n", 273}, + {"usage: newgrp [ - ] [ group ]\n", 274}, + {"usage: sg group [ command ]\n", 275}, + {"unknown uid: %d\n", 276}, + {"unknown gid: %ld\n", 277}, + {"unknown gid: %d\n", 278}, + {"Password:", 279}, + {"Sorry.\n", 280}, + {"too many groups\n", 281}, + {"Usage: %s [ input ]\n", 282}, + {"%s: can't lock /etc/passwd.\n", 283}, + {"%s: can't lock files, try again later\n", 284}, + {"%s: can't open files\n", 285}, + {"%s: line %d: invalid line\n", 286}, + {"%s: line %d: can't create GID\n", 287}, + {"%s: line %d: can't create UID\n", 288}, + {"%s: line %d: cannot find user %s\n", 289}, + {"%s: line %d: can't update password\n", 290}, + {"%s: line %d: mkdir failed\n", 291}, + {"%s: line %d: chown failed\n", 292}, + {"%s: line %d: can't update entry\n", 293}, + {"%s: error updating files\n", 294}, + {"usage: %s [ -f | -s ] [ name ]\n", 295}, + {" %s [ -x max ] [ -n min ] [ -w warn ] [ -i inact ] name\n", 296}, + {" %s { -l | -u | -d | -S | -e } name\n", 297}, + {"User %s has a TCFS key, his old password is required.\n", 298}, + {"You can use -t option to force the change.\n", 299}, + {"Old password:", 300}, + {"Incorrect password for `%s'\n", 301}, + {"Warning: user %s has a TCFS key.\n", 302}, + {"\ +Enter the new password (minimum of %d, maximum of %d characters)\n\ +Please use a combination of upper and lower case letters and numbers.\n", 303}, + {"New password:", 304}, + {"Try again.\n", 305}, + {"\ +\n\ +Warning: weak password (enter it again to use it anyway).\n", 306}, + {"They don't match; try again.\n", 307}, + {"The password for %s cannot be changed.\n", 308}, + {"Sorry, the password for %s cannot be changed yet.\n", 309}, + {"%s: out of memory\n", 310}, + {"Cannot lock the TCFS key database; try again later\n", 311}, + {"Cannot open the TCFS key database.\n", 312}, + {"Error updating the TCFS key database.\n", 313}, + {"Cannot commit TCFS changes.\n", 314}, + {"%s: Cannot execute %s", 315}, + {"%s: repository %s not supported\n", 316}, + {"%s: Permission denied\n", 317}, + {"You may not change the password for %s.\n", 318}, + {"Changing password for %s\n", 319}, + {"The password for %s is unchanged.\n", 320}, + {"Password changed.\n", 321}, + {"Usage: %s [ -qr ] [ passwd [ shadow ] ]\n", 322}, + {"Usage: %s [ -qr ] [ passwd ]\n", 323}, + {"invalid password file entry\n", 324}, + {"duplicate password entry\n", 325}, + {"invalid user name `%s'\n", 326}, + {"user %s: bad UID (%d)\n", 327}, + {"user %s: no group %d\n", 328}, + {"user %s: directory %s does not exist\n", 329}, + {"user %s: program %s does not exist\n", 330}, + {"invalid shadow password file entry\n", 331}, + {"duplicate shadow password entry\n", 332}, + {"no matching password file entry\n", 333}, + {"user %s: last password change in the future\n", 334}, + {"%s: can't lock passwd file\n", 335}, + {"%s: can't open passwd file\n", 336}, + {"%s: can't remove shadow entry for %s\n", 337}, + {"%s: can't update passwd entry for %s\n", 338}, + {"%s: can't update shadow file\n", 339}, + {"%s: can't update passwd file\n", 340}, + {"%s: Shadow passwords are not configured.\n", 341}, + {"%s: can't update entry for user %s\n", 342}, + {"%s: can't delete shadow password file\n", 343}, + {"Sorry.", 344}, + {"%s: must be run from a terminal\n", 345}, + {"%s: pam_start: error %d\n", 346}, + {"Unknown id: %s\n", 347}, + {"You are not authorized to su %s\n", 348}, + {"(Enter your own password.)", 349}, + {"%s: permission denied (shell).\n", 350}, + {"\ +%s: %s\n\ +(Ignored)\n", 351}, + {"No shell\n", 352}, + {"No password file\n", 353}, + {"No password entry for 'root'\n", 354}, + {"\ +\n\ +Type control-d to proceed with normal startup,\n\ +(or give root password for system maintenance):", 355}, + {"Entering System Maintenance Mode\n", 356}, + {"%s: rebuild the group database\n", 357}, + {"%s: rebuild the shadow group database\n", 358}, + {"%s: invalid numeric argument `%s'\n", 359}, + {"%s: unknown gid %s\n", 360}, + {"%s: unknown group %s\n", 361}, + {"group=%s,%ld basedir=%s skel=%s\n", 362}, + {"shell=%s ", 363}, + {"inactive=%ld expire=%s", 364}, + {"GROUP=%ld\n", 365}, + {"HOME=%s\n", 366}, + {"INACTIVE=%ld\n", 367}, + {"EXPIRE=%s\n", 368}, + {"SHELL=%s\n", 369}, + {"SKEL=%s\n", 370}, + {"%s: cannot create new defaults file\n", 371}, + {"%s: rename: %s", 372}, + {"%s: group `%s' is a NIS group.\n", 373}, + {"%s: too many groups specified (max %d).\n", 374}, + {"usage: %s\t[-u uid [-o]] [-g group] [-G group,...] \n", 375}, + {"\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n", 376}, + {"[-f inactive] [-e expire ] ", 377}, + {"[-A program] ", 378}, + {"[-p passwd] name\n", 379}, + {" %s\t-D [-g group] [-b base] [-s shell]\n", 380}, + {"\t\t[-f inactive] [-e expire ]\n", 381}, + {"%s: error locking group file\n", 382}, + {"%s: error opening group file\n", 383}, + {"%s: error locking shadow group file\n", 384}, + {"%s: error opening shadow group file\n", 385}, + {"%s: uid %d is not unique\n", 386}, + {"%s: can't get unique uid\n", 387}, + {"%s: invalid field `%s'\n", 388}, + {"%s: invalid base directory `%s'\n", 389}, + {"%s: invalid comment `%s'\n", 390}, + {"%s: invalid home directory `%s'\n", 391}, + {"%s: invalid date `%s'\n", 392}, + {"%s: shadow passwords required for -e\n", 393}, + {"%s: shadow passwords required for -f\n", 394}, + {"%s: invalid shell `%s'\n", 395}, + {"%s: invalid user name `%s'\n", 396}, + {"%s: cannot rewrite password file\n", 397}, + {"%s: cannot rewrite shadow password file\n", 398}, + {"%s: unable to lock password file\n", 399}, + {"%s: unable to open password file\n", 400}, + {"%s: cannot lock shadow password file\n", 401}, + {"%s: cannot open shadow password file\n", 402}, + {"%s: error adding authentication method\n", 403}, + {"%s: error adding new password entry\n", 404}, + {"%s: error updating password dbm entry\n", 405}, + {"%s: error adding new shadow password entry\n", 406}, + {"%s: error updating shadow passwd dbm entry\n", 407}, + {"%s: cannot create directory %s\n", 408}, + {"%s: user %s exists\n", 409}, + {"%s: warning: CREATE_HOME not supported, please use -m instead.\n", 410}, + {"usage: %s [-r] name\n", 411}, + {"%s: error updating group entry\n", 412}, + {"%s: cannot update dbm group entry\n", 413}, + {"%s: cannot rewrite TCFS key file\n", 414}, + {"%s: cannot lock TCFS key file\n", 415}, + {"%s: cannot open TCFS key file\n", 416}, + {"%s: cannot open group file\n", 417}, + {"%s: cannot open shadow group file\n", 418}, + {"%s: error deleting authentication\n", 419}, + {"%s: error deleting password entry\n", 420}, + {"%s: error deleting shadow password entry\n", 421}, + {"%s: error deleting TCFS entry\n", 422}, + {"%s: error deleting password dbm entry\n", 423}, + {"%s: error deleting shadow passwd dbm entry\n", 424}, + {"%s: user %s is currently logged in\n", 425}, + {"%s: warning: %s not owned by %s, not removing\n", 426}, + {"%s: warning: can't remove ", 427}, + {"%s: user %s does not exist\n", 428}, + {"%s: user %s is a NIS user\n", 429}, + {"%s: %s not owned by %s, not removing\n", 430}, + {"%s: not removing directory %s (would remove home of user %s)\n", 431}, + {"%s: error removing directory %s\n", 432}, + {"\t\t[-d home [-m]] [-s shell] [-c comment] [-l new_name]\n", 433}, + {"[-A {DEFAULT|program},... ] ", 434}, + {"%s: out of memory in update_group\n", 435}, + {"%s: out of memory in update_gshadow\n", 436}, + {"%s: no flags given\n", 437}, + {"%s: shadow passwords required for -e and -f\n", 438}, + {"%s: uid %ld is not unique\n", 439}, + {"%s: error deleting authentication method\n", 440}, + {"%s: error changing authentication method\n", 441}, + {"%s: error changing password entry\n", 442}, + {"%s: error removing password entry\n", 443}, + {"%s: error adding password dbm entry\n", 444}, + {"%s: error removing passwd dbm entry\n", 445}, + {"%s: error removing shadow password entry\n", 446}, + {"%s: error removing shadow passwd dbm entry\n", 447}, + {"%s: directory %s exists\n", 448}, + {"%s: can't create %s\n", 449}, + {"%s: can't chown %s\n", 450}, + {"%s: cannot rename directory %s to %s\n", 451}, + {"%s: warning: %s not owned by %s\n", 452}, + {"failed to change mailbox owner", 453}, + {"failed to rename mailbox", 454}, + {"\ +\n\ +%s: %s is unchanged\n", 455}, + {"Couldn't lock file", 456}, + {"Couldn't make backup", 457}, + {"%s: can't restore %s: %s (your changes are in %s)\n", 458}, + {"\ +Usage:\n\ +`vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n\ +`vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n", 459}, +}; + +int _msg_tbl_length = 459; diff --git a/po/el.gmo b/po/el.gmo new file mode 100644 index 00000000..408dd24d Binary files /dev/null and b/po/el.gmo differ diff --git a/po/el.po b/po/el.po new file mode 100644 index 00000000..164bc650 --- /dev/null +++ b/po/el.po @@ -0,0 +1,2428 @@ +# Shadow Password Suite +# Greek Translation by Nikos Mavroyanopoulos +# Thanks to Simos Xenitelis (S.Xenitellis@rhbnc.ac.uk) for his +# comments about making this translation better. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Shadow 980726\n" +"POT-Creation-Date: 1999-07-09 20:02+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Nikos Mavroyanopoulos \n" +"Language-Team: Hellenic \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO8859-7\n" +"Content-Transfer-Encoding: 8-bit\n" + +#: libmisc/addgrps.c:60 +#, c-format +msgid "Warning: unknown group %s\n" +msgstr "Ðñïåéäïðïßçóç: Üãíùóôç ïìÜäá %s\n" + +#: libmisc/addgrps.c:71 +msgid "Warning: too many groups\n" +msgstr "Ðñïåéäïðïßçóç: ÐïëëÝò ïìÜäåò\n" + +#: libmisc/age.c:104 +msgid "Your password has expired." +msgstr "Ôï óõíèçìáôéêü óáò Ý÷åé ëÞîåé." + +#: libmisc/age.c:107 +msgid "Your password is inactive." +msgstr "Ôï óõíèçìáôéêü óáò åßíáé áíåíåñãü." + +#: libmisc/age.c:110 +msgid "Your login has expired." +msgstr "Ï êùäéêüò åéóüäïõ óáò Ý÷åé ëÞîåé." + +#: libmisc/age.c:127 +msgid " Contact the system administrator.\n" +msgstr " ÅðéêïéíùíÞóôå ìå ôïí äéá÷åéñéóôÞ ôïõ óõóôÞìáôïò.\n" + +#: libmisc/age.c:130 +msgid " Choose a new password.\n" +msgstr " ÅðéëÝîôå Ýíá íÝï óõíèçìáôéêü.\n" + +#: libmisc/age.c:228 +#, c-format +msgid "Your password will expire in %ld days.\n" +msgstr "Ôï óõíèçìáôéêü óáò èá ëÞîåé óå %ld ìÝñåò.\n" + +#: libmisc/age.c:230 +msgid "Your password will expire tomorrow.\n" +msgstr "Ôï óõíèçìáôéêü óáò èá ëÞîåé áýñéï.\n" + +#: libmisc/age.c:232 +msgid "Your password will expire today.\n" +msgstr "Ôï óõíèçìáôéêü óáò èá ëÞîåé óÞìåñá.\n" + +#: libmisc/chowntty.c:110 +#, c-format +msgid "Unable to change tty %s" +msgstr "Áäõíáìßá áëëáãÞò tty %s" + +#: libmisc/env.c:160 +msgid "Environment overflow\n" +msgstr "Õðåñ÷åßëéóç ðåñéâÜëëïíôïò\n" + +#: libmisc/env.c:200 +#, c-format +msgid "You may not change $%s\n" +msgstr "Äåí ìðïñåßôå íá áëëÜîåôå ôï $%s\n" + +#: libmisc/failure.c:238 +#, c-format +msgid "%d %s since last login. Last was %s on %s.\n" +msgstr "%d %s áðü ôçí ôåëåõôáßá åßóïäï. Ç ôåëåõôáßá Þôáí óôéò %s óôï %s.\n" + +#: libmisc/failure.c:239 +msgid "failures" +msgstr "áðïôõ÷ßåò" + +#: libmisc/failure.c:239 +msgid "failure" +msgstr "áðïôõ÷ßá" + +#: libmisc/limits.c:365 +msgid "Too many logins.\n" +msgstr "ÐïëëÝò åßóïäïé óôï óýóôçìá.\n" + +#: libmisc/login_desrpc.c:63 +#, c-format +msgid "Password does not decrypt secret key for %s.\n" +msgstr "Ôï óõíèçìáôéêü äåí áðïêùäéêïðïéåß ôï ìõóôéêü êëåéäß ãéá ôï(í) %s.\n" + +#: libmisc/login_desrpc.c:69 +#, c-format +msgid "Could not set %s's secret key: is the keyserv daemon running?\n" +msgstr "" +"Äåí åßíáé äõíáôüí íá ôåèåß ôï ìõóôéêü êëåéäß ôïõ %s: Åêôåëåßôáé ï\n" +"äéáêïìéóôÞò êëåéäéþí;\n" + +#: libmisc/mail.c:62 libmisc/mail.c:77 +msgid "You have new mail." +msgstr "¸÷åôå íÝá ãñÜììáôá." + +#: libmisc/mail.c:73 +msgid "No mail." +msgstr "ÊáíÝíá ãñÜììá." + +#: libmisc/mail.c:75 +msgid "You have mail." +msgstr "¸÷åôå ãñÜììáôá." + +#: libmisc/obscure.c:281 src/passwd.c:311 +#, c-format +msgid "Bad password: %s. " +msgstr "Êáêü óõíèçìáôéêü: %s. " + +#: libmisc/pam_pass.c:42 +#, c-format +msgid "passwd: pam_start() failed, error %d\n" +msgstr "óõíèçìáôéêü: pam_start() áðÝôõ÷å, óöÜëìá %d\n" + +#: libmisc/pam_pass.c:49 +#, c-format +msgid "passwd: %s\n" +msgstr "óõíèçìáôéêü: %s\n" + +#: libmisc/setupenv.c:205 +#, c-format +msgid "Unable to cd to \"%s\"\n" +msgstr "Áäõíáìßá áëëáãÞò êáôáëüãïõ óôïí \"%s\"\n" + +#: libmisc/setupenv.c:213 +msgid "No directory, logging in with HOME=/" +msgstr "×ùñßò êáôÜëïãï, åéóáãùãÞ ìå ÌÇÔÑÉÊÏ_ÊÁÔÁËÏÃÏ=/" + +#: libmisc/shell.c:78 +#, c-format +msgid "Executing shell %s\n" +msgstr "ÅêôÝëåóç öëïéïý %s\n" + +#. +#. * Obviously something is really wrong - I can't figure out +#. * how to execute this stupid shell, so I might as well give +#. * up in disgust ... +#. +#: libmisc/shell.c:122 +#, c-format +msgid "Cannot execute %s" +msgstr "Áäõíáìßá åêôÝëåóçò %s" + +#: libmisc/suauth.c:99 +msgid "Access to su to that account DENIED.\n" +msgstr "Ðñüóâáóç óôç su óå áõôüí ôïí ëïãáñéáóìü ÁÑÍÇÈÇÊÅ.\n" + +#: libmisc/suauth.c:106 +msgid "Password authentication bypassed.\n" +msgstr "ÐáñÜêáìøç åîáêñßâùóçò ìå óõíèçìáôéêü.\n" + +#: libmisc/suauth.c:113 +msgid "Please enter your OWN password as authentication.\n" +msgstr "Ðáñáêáëþ åéóÜãåôå ôï ÄÉÊÏ óáò óõíèçìáôéêü ãéá åîáêñßâùóç.\n" + +#: libmisc/sub.c:61 +#, c-format +msgid "Invalid root directory \"%s\"\n" +msgstr "Ìç Ýãêõñïò ðñùôáñ÷éêüò êáôÜëïãïò \"%s\"\n" + +#: libmisc/sub.c:73 +#, c-format +msgid "Can't change root directory to \"%s\"\n" +msgstr "Áäõíáìßá áëëáãÞò ôïõ ðñùôáñ÷éêïý êáôáëüãïõ óå \"%s\"\n" + +#: libmisc/xmalloc.c:28 +#, c-format +msgid "malloc(%d) failed\n" +msgstr "Ç êëÞóç malloc(%d) áðÝôõ÷å\n" + +#: lib/dialchk.c:71 +msgid "Dialup Password:" +msgstr "Óõíèçìáôéêü ôçëåöùíéêÞò óýíäåóçò:" + +#: lib/getdef.c:247 +msgid "Could not allocate space for config info.\n" +msgstr "Áäõíáìßá äÝóìåõóçò ÷þñïõ ãéá ðëçñïöïñßåò äéáìüñöùóçò.\n" + +#. +#. * Item was never found. +#. +#: lib/getdef.c:301 +#, c-format +msgid "configuration error - unknown item '%s' (notify administrator)\n" +msgstr "" +"óöÜëìá äéáìüñöùóçò - Üãíùóôï áíôéêåßìåíï '%s' (åéäïðïéåßóôå ôïí " +"äéá÷åéñéóôÞ)\n" + +#: lib/getdef.c:388 +#, c-format +msgid "error - lookup '%s' failed\n" +msgstr "óöÜëìá - ç áíáæÞôçóç '%s' áðÝôõ÷å\n" + +#: lib/getdef.c:396 +#, c-format +msgid "%s not found\n" +msgstr "%s äåí âñÝèçêå\n" + +#: lib/pwauth.c:54 +msgid "Password: " +msgstr "Óõíèçìáôéêü: " + +#: lib/pwauth.c:56 +#, c-format +msgid "%s's Password:" +msgstr "Ôïõ %s ôï Óõíèçìáôéêü:" + +#: lib/strerror.c:20 +#, c-format +msgid "Unknown error %d" +msgstr "Áãíùóôï óöÜëìá %d" + +#: src/chage.c:141 +#, c-format +msgid "" +"Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -W warn ]\n" +" [ -I inactive ] [ -E expire ] [ -d last_day ] user\n" +msgstr "" +"×ñÞóç: %s [ -l ] [ -m åëá÷_ìÝñåò ] [ -M ìåã_ìÝñåò ] [ -W ðñïåéä. ]\n" +"\t[ -I áíåíåñãü ] [ -E ëÞîç ] [ -d ôåëåõôáßá_ìÝñá ] ÷ñÞóôçò\n" + +#: src/chage.c:143 +#, c-format +msgid "Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -d last_day ] user\n" +msgstr "" +"×ñÞóç: %s [ -l ] [ -m åëÜ÷_ìÝñåò ] [ -M ìåã_ìÝñåò ]\n" +"[ -d ôåëåõôáßá_ìÝñá ] ÷ñÞóôçò\n" + +#: src/chage.c:178 +msgid "" +"Enter the new value, or press return for the default\n" +"\n" +msgstr "" +"ÅéóÜãåôå ôçí íÝá ôéìÞ, Þ ðéÝóôå `return' ãéá ôçí ðñïêáèïñéóìÝíç\n" +"\n" + +#: src/chage.c:181 +msgid "Minimum Password Age" +msgstr "Ìéêñüôåñç äéÜñêåéá óõíèçìáôéêïý" + +#: src/chage.c:186 +msgid "Maximum Password Age" +msgstr "ÌÝãéóôç äéÜñêåéá óõíèçìáôéêïý" + +#: src/chage.c:192 +msgid "Last Password Change (YYYY-MM-DD)" +msgstr "Ôåëåõôáßá áëëáãÞ óõíèçìáôéêïý (××××-ÌÌ-ÇÇ)" + +#: src/chage.c:201 +msgid "Password Expiration Warning" +msgstr "Ðñïåéäïðïßçóç ëÞîçò óõíèçìáôéêïý" + +#: src/chage.c:206 +msgid "Password Inactive" +msgstr "Áíåíåñãü óõíèçìáôéêü" + +#: src/chage.c:212 +msgid "Account Expiration Date (YYYY-MM-DD)" +msgstr "Çìåñïìçíßá ËÞîçò Ëïãáñéáóìïý (××××-ÌÌ-ÇÇ)" + +#. +#. * Start with the easy numbers - the number of days before the +#. * password can be changed, the number of days after which the +#. * password must be chaged, the number of days before the +#. * password expires that the user is told, and the number of +#. * days after the password expires that the account becomes +#. * unusable. +#. +#: src/chage.c:266 +#, c-format +msgid "Minimum:\t%ld\n" +msgstr "ÅëÜ÷éóôï:\t%ld\n" + +#: src/chage.c:267 +#, c-format +msgid "Maximum:\t%ld\n" +msgstr "ÌÝãéóôï:\t%ld\n" + +#: src/chage.c:269 +#, c-format +msgid "Warning:\t%ld\n" +msgstr "Ðñïåéäïðïßçóç:\t%ld\n" + +#: src/chage.c:270 +#, c-format +msgid "Inactive:\t%ld\n" +msgstr "Áíåíåñãüò:\t%ld\n" + +#. +#. * The "last change" date is either "Never" or the date the +#. * password was last modified. The date is the number of +#. * days since 1/1/1970. +#. +#: src/chage.c:279 +msgid "Last Change:\t\t" +msgstr "Ôåëåõôáßá áëëáãÞ:\t\t" + +#: src/chage.c:281 src/chage.c:295 +msgid "Never\n" +msgstr "ÐïôÝ\n" + +#. +#. * The password expiration date is determined from the last +#. * change date plus the number of days the password is valid +#. * for. +#. +#: src/chage.c:293 +msgid "Password Expires:\t" +msgstr "Ôï óõíèçìáôéêü ëÞãåé:\t" + +#: src/chage.c:468 +#, c-format +msgid "%s: do not include \"l\" with other flags\n" +msgstr "%s: Íá ìçí óõìðåñéëáìâÜíåôå ôï \"l\" ìå ôéò Üëëåò åíäåßîåéò\n" + +#: src/chage.c:480 src/chage.c:592 src/login.c:532 +#, c-format +msgid "%s: permission denied\n" +msgstr "%s: Üäåéá áðïññßöèçêå\n" + +#: src/chage.c:492 src/chpasswd.c:122 +#, c-format +msgid "%s: can't lock password file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/chage.c:498 src/chpasswd.c:126 +#, c-format +msgid "%s: can't open password file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/chage.c:505 +#, c-format +msgid "%s: unknown user: %s\n" +msgstr "%s: Üãíùóôïò ÷ñÞóôçò: %s\n" + +#: src/chage.c:524 +#, c-format +msgid "%s: can't lock shadow password file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/chage.c:531 +#, c-format +msgid "%s: can't open shadow password file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/chage.c:613 +#, c-format +msgid "Changing the aging information for %s\n" +msgstr "ÁëëáãÞ ðëçñïöïñéþí ÷ñüíïõ ãéá ôïí %s\n" + +#: src/chage.c:615 +#, c-format +msgid "%s: error changing fields\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí áëëáãÞ ðåäßùí\n" + +#: src/chage.c:642 src/chage.c:705 src/pwunconv.c:184 +#, c-format +msgid "%s: can't update password file\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/chage.c:672 src/pwunconv.c:179 +#, c-format +msgid "%s: can't update shadow password file\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/chage.c:721 src/chage.c:736 src/chfn.c:572 src/chsh.c:411 +#: src/passwd.c:827 src/passwd.c:928 +msgid "Error updating the DBM password entry.\n" +msgstr "" +"ÓöÜëìá êáôÜ ôçí áíáíÝùóç ôçò êáôá÷þñçóçò óôï dbm áñ÷åßï óõíèçìáôéêþí.\n" + +#: src/chage.c:753 +#, c-format +msgid "%s: can't rewrite shadow password file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/chage.c:767 +#, c-format +msgid "%s: can't rewrite password file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/chage.c:816 +#, c-format +msgid "%s: no aging information present\n" +msgstr "%s: Äåí õðÜñ÷ïõí ðëçñïöïñßåò ãÞñáíóçò\n" + +#: src/chfn.c:108 +#, c-format +msgid "" +"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ]\n" +"\t[ -h home_ph ] [ -o other ] [ user ]\n" +msgstr "" +"Usage: %s [ -f ðëÞñåò_üíïìá ] [ -r áñßèì_äùìáôßïõ ] [ -w ôçë_åñãáóßáò ]\n" +"\t[ -h ôçë_ïéêßáò ] [ -o Üëëï ] [ ÷ñÞóôçò ]\n" + +#: src/chfn.c:112 +#, c-format +msgid "" +"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ] [ -h home_ph ]\n" +msgstr "" +"×ñÞóç: %s [ -f ðëÞñåò_üíïìá ] [ -r áñéèì_äùìáôßïõ ] [ -w ôçë_äùìáôßïõ ]\n" +"[ -h ôçë_ïéêßáò ]\n" + +#: src/chfn.c:164 src/chsh.c:120 +msgid "Enter the new value, or press return for the default\n" +msgstr "ÅéóÜãåôå ôçí íÝá ôéìÞ, Þ ðéÝóôå `return' ãéá ôçí ðñïêáèïñéóìÝíç\n" + +#: src/chfn.c:167 +msgid "Full Name" +msgstr "ÐëÞñåò üíïìá" + +#: src/chfn.c:169 +#, c-format +msgid "\tFull Name: %s\n" +msgstr "\tÐëÞñåò ¼íïìá: %s\n" + +#: src/chfn.c:172 +msgid "Room Number" +msgstr "Áñéèìüò äùìáôßïõ" + +#: src/chfn.c:174 +#, c-format +msgid "\tRoom Number: %s\n" +msgstr "\tÁñéèìüò Äùìáôßïõ: %s\n" + +#: src/chfn.c:177 +msgid "Work Phone" +msgstr "ÔçëÝöùíï Åñãáóßáò" + +#: src/chfn.c:179 +#, c-format +msgid "\tWork Phone: %s\n" +msgstr "\tÔçëÝöùíï Åñãáóßáò: %s\n" + +#: src/chfn.c:182 +msgid "Home Phone" +msgstr "ÔçëÝöùíï Ïéêßáò" + +#: src/chfn.c:184 +#, c-format +msgid "\tHome Phone: %s\n" +msgstr "\tÔçëÝöùíï ïéêßáò: %s\n" + +#: src/chfn.c:187 +msgid "Other" +msgstr "Áëëï" + +#: src/chfn.c:300 src/chfn.c:308 src/chfn.c:316 src/chfn.c:324 src/chfn.c:332 +#: src/chfn.c:393 src/passwd.c:1228 +#, c-format +msgid "%s: Permission denied.\n" +msgstr "%s: ¶äåéá áðïññßöèçêå.\n" + +#: src/chfn.c:353 src/chsh.c:226 src/passwd.c:1279 +#, c-format +msgid "%s: Unknown user %s\n" +msgstr "%s: Áãíùóôïò ï ÷ñÞóôçò %s\n" + +#: src/chfn.c:359 src/chsh.c:234 src/passwd.c:1209 +#, c-format +msgid "%s: Cannot determine your user name.\n" +msgstr "%s: Äåí åßíáé äõíáôüí íá êáèïñéóôåß ôï üíïìá ÷ñÞóôç óáò.\n" + +#: src/chfn.c:375 src/chsh.c:252 +#, c-format +msgid "%s: cannot change user `%s' on NIS client.\n" +msgstr "%s: áäõíáìßá áëëáãÞò ÷ñÞóôç `%s' óôïí NIS åîõðçñåôïýìåíï.\n" + +#: src/chfn.c:380 src/chsh.c:259 +#, c-format +msgid "%s: `%s' is the NIS master for this client.\n" +msgstr "%s: `%s' åßíáé ï êýñéïò äéáêïìéóôÞò NIS ãé'áõôüí ôïí åîõðçñåôïýìåíï.\n" + +#: src/chfn.c:455 +#, c-format +msgid "Changing the user information for %s\n" +msgstr "ÁëëáãÞ ðëçñïöïñéþí ÷ñÞóôç ãéá ôïí %s\n" + +#: src/chfn.c:464 +#, c-format +msgid "%s: invalid name: \"%s\"\n" +msgstr "%s: Ìç Ýãêõñï üíïìá: `%s'\n" + +#: src/chfn.c:469 +#, c-format +msgid "%s: invalid room number: \"%s\"\n" +msgstr "%s: Ìç Ýãêõñïò áñéèìüò äùìáôßïõ: `%s'\n" + +#: src/chfn.c:474 +#, c-format +msgid "%s: invalid work phone: \"%s\"\n" +msgstr "%s: Ìç Ýãêõñï ôçëÝöùíï åñãáóßáò: `%s'\n" + +#: src/chfn.c:479 +#, c-format +msgid "%s: invalid home phone: \"%s\"\n" +msgstr "%s: Ìç Ýãêõñï ôçëÝöùíï ïéêßáò: `%s'\n" + +#: src/chfn.c:484 +#, c-format +msgid "%s: \"%s\" contains illegal characters\n" +msgstr "%s: \"%s\" ðåñéÝ÷åé ìç Ýãêõñïõò ÷áñáêôÞñåò\n" + +#: src/chfn.c:496 +#, c-format +msgid "%s: fields too long\n" +msgstr "%s: Ðïëý ìáêñéÜ ðåäßá\n" + +#: src/chfn.c:511 src/chsh.c:349 src/gpasswd.c:583 src/passwd.c:1390 +msgid "Cannot change ID to root.\n" +msgstr "Áäõíáìßá áëëáãÞò ôáõôüôçôáò ÷ñÞóôç óå root.\n" + +#: src/chfn.c:524 src/chsh.c:363 src/passwd.c:737 src/passwd.c:882 +msgid "Cannot lock the password file; try again later.\n" +msgstr "Áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí. ÄïêéìÜóôå áñãüôåñá.\n" + +#: src/chfn.c:530 src/chsh.c:369 src/passwd.c:742 src/passwd.c:887 +msgid "Cannot open the password file.\n" +msgstr "Áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí.\n" + +#: src/chfn.c:547 src/chsh.c:384 src/passwd.c:748 src/usermod.c:1272 +#, c-format +msgid "%s: %s not found in /etc/passwd\n" +msgstr "%s: Ï %s äåí âñÝèçêå óôï /etc/passwd\n" + +#: src/chfn.c:564 src/chsh.c:403 src/passwd.c:821 src/passwd.c:922 +#: src/passwd.c:962 +msgid "Error updating the password entry.\n" +msgstr "ÓöÜëìá êáôÜ ôçí áíáíÝùóç êáôá÷þñçóçò óôï áñ÷åßï óõíèçìáôéêþí.\n" + +#: src/chfn.c:587 src/chsh.c:426 src/passwd.c:834 src/passwd.c:935 +msgid "Cannot commit password file changes.\n" +msgstr "Áäõíáìßá åéóáãùãÞò ôùí áëëáãþí óôï áñ÷åßï óõíèçìáôéêþí.\n" + +#: src/chfn.c:594 src/chsh.c:433 +msgid "Cannot unlock the password file.\n" +msgstr "Áäõíáìßá îåêëåéäþìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/chpasswd.c:78 +#, c-format +msgid "usage: %s [-e]\n" +msgstr "÷ñÞóç: %s [-e]\n" + +#: src/chpasswd.c:134 src/pwconv.c:105 +#, c-format +msgid "%s: can't lock shadow file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/chpasswd.c:139 src/gpasswd.c:609 src/pwconv.c:110 src/pwunconv.c:119 +#: src/pwunconv.c:124 +#, c-format +msgid "%s: can't open shadow file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/chpasswd.c:161 src/newusers.c:418 +#, c-format +msgid "%s: line %d: line too long\n" +msgstr "%s: ãñáììÞ %d: ðïëý ìåãÜëç ãñáììÞ\n" + +#: src/chpasswd.c:181 +#, c-format +msgid "%s: line %d: missing new password\n" +msgstr "%s: ãñáììÞ %d: Ýëëåéøç íÝïõ óõíèçìáôéêïý\n" + +#: src/chpasswd.c:197 +#, c-format +msgid "%s: line %d: unknown user %s\n" +msgstr "%s: ãñáììÞ %d: Üãíùóôïò ÷ñÞóôçò %s\n" + +#: src/chpasswd.c:249 +#, c-format +msgid "%s: line %d: cannot update password entry\n" +msgstr "%s: ãñáììÞ %d: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò óõíèçìáôéêïý\n" + +#: src/chpasswd.c:265 src/newusers.c:538 +#, c-format +msgid "%s: error detected, changes ignored\n" +msgstr "%s: Áíé÷íÝõôçêå óöÜëìá, ïé áëëáãÝò áãíïÞèçêáí\n" + +#: src/chpasswd.c:276 +#, c-format +msgid "%s: error updating shadow file\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áíáíÝùóç êáôá÷ùñÞóåùí óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#: src/chpasswd.c:284 +#, c-format +msgid "%s: error updating password file\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí áíáíÝùóç êáôá÷ùñÞóåùí óôï áñ÷åßï óõíèçìáôéêþí\n" + +#: src/chsh.c:106 +#, c-format +msgid "Usage: %s [ -s shell ] [ name ]\n" +msgstr "×ñÞóç: %s [ -s öëïéüò ] [ üíïìá ]\n" + +#: src/chsh.c:121 +msgid "Login Shell" +msgstr "ÊÝëõöïò Åéóüäïõ" + +#: src/chsh.c:275 src/chsh.c:288 +#, c-format +msgid "You may not change the shell for %s.\n" +msgstr "Äåí ìðïñåßôå íá áëëÜîåôå ôï öëïéü ãéá ôï(í) %s.\n" + +#: src/chsh.c:317 +#, c-format +msgid "Changing the login shell for %s\n" +msgstr "ÁëëÜãÞ ôïõ öëïéïý ãéá ôïí %s\n" + +#: src/chsh.c:329 +#, c-format +msgid "%s: Invalid entry: %s\n" +msgstr "%s: Ìç Ýãêõñç êáôá÷þñçóç: %s\n" + +#: src/chsh.c:334 +#, c-format +msgid "%s is an invalid shell.\n" +msgstr "%s äåí åßíáé Ýãêõñïò öëïéüò.\n" + +#: src/dpasswd.c:71 +#, c-format +msgid "Usage: %s [ -(a|d) ] shell\n" +msgstr "×ñÞóç: %s [ -(ald) ] öëïéüò\n" + +#: src/dpasswd.c:136 +msgid "Shell password:" +msgstr "Óõíèçìáôéêü öëïéïý:" + +#: src/dpasswd.c:142 +msgid "re-enter Shell password:" +msgstr "ÅðáíåéóÜãåôå ôï óõíèçìáôéêü öëïéïý:" + +#: src/dpasswd.c:149 +#, c-format +msgid "%s: Passwords do not match, try again.\n" +msgstr "%s: Ôá óõíèçìáôéêÜ äåí ôáéñéÜæïõí, äïêéìÜóôå îáíÜ.\n" + +#: src/dpasswd.c:169 +#, c-format +msgid "%s: can't create %s" +msgstr "%s: áäõíáìßá äçìéïõñãßáò ôïõ %s" + +#: src/dpasswd.c:174 +#, c-format +msgid "%s: can't open %s" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ %s" + +#: src/dpasswd.c:202 +#, c-format +msgid "%s: Shell %s not found.\n" +msgstr "%s: Ï öëïéüò %s äåí âñÝèçêå.\n" + +#: src/expiry.c:85 +msgid "Usage: expiry { -f | -c }\n" +msgstr "×ñÞóç: expiry { -f | -c }\n" + +#: src/expiry.c:138 +#, c-format +msgid "%s: WARNING! Must be set-UID root!\n" +msgstr "" +"%s: ÐÑÏÓÏ×Ç! ÐñÝðåé íá Ý÷åé ôåèåß ôï bit ðáñá÷þñçóçò ôáõôüôçôáò root!\n" + +#: src/expiry.c:149 +#, c-format +msgid "%s: unknown user\n" +msgstr "%s: Üãíùóôïò ÷ñÞóôçò\n" + +#: src/faillog.c:80 +#, c-format +msgid "usage: %s [-a|-u user] [-m max] [-r] [-t days] [-l locksecs]\n" +msgstr "" +"÷ñÞóç: %s [-a|-u ÷ñÞóôçò] [-m ìåã] [-r] [-t ìÝñåò] [-l äåõôåñüëåðôá_êëåéä]\n" + +#: src/faillog.c:135 src/lastlog.c:95 +#, c-format +msgid "Unknown User: %s\n" +msgstr "Áãíùóôïò ÷ñÞóôçò: %s\n" + +#: src/faillog.c:216 +msgid "Username Failures Maximum Latest\n" +msgstr "¼íïìá_×ñÞóôç Áðïôõ÷ßåò ÌÝãéóôï Ôåëåõôáßá\n" + +#: src/faillog.c:233 +#, c-format +msgid " %s on %s" +msgstr " %s óôï %s" + +#: src/faillog.c:237 +#, c-format +msgid " [%lds left]" +msgstr " [%lds áðÝìåéíáí]" + +#: src/faillog.c:240 +#, c-format +msgid " [%lds lock]" +msgstr " [%lds êëåßäùìá]" + +#: src/gpasswd.c:91 +#, c-format +msgid "usage: %s [-r|-R] group\n" +msgstr "÷ñÞóç: %s [-r|-R] ïìÜäá\n" + +#: src/gpasswd.c:92 +#, c-format +msgid " %s [-a user] group\n" +msgstr " %s [-a ÷ñÞóôçò] ïìÜäá\n" + +#: src/gpasswd.c:93 +#, c-format +msgid " %s [-d user] group\n" +msgstr " %s [-d ÷ñÞóôçò] ïìÜäá\n" + +#: src/gpasswd.c:95 +#, c-format +msgid " %s [-A user,...] [-M user,...] group\n" +msgstr " %s [-A ÷ñÞóôçò,...] [-M ÷ñÞóôçò,...] ïìÜäá\n" + +#: src/gpasswd.c:98 +#, c-format +msgid " %s [-M user,...] group\n" +msgstr " %s [-M ÷ñÞóôçò,...] ïìÜäá\n" + +#: src/gpasswd.c:162 src/gpasswd.c:247 +#, c-format +msgid "%s: unknown user %s\n" +msgstr "%s: Üãíùóôïò ÷ñÞóôçò %s\n" + +#: src/gpasswd.c:174 +msgid "Permission denied.\n" +msgstr "¶äåéá áðïññßöèçêå.\n" + +#: src/gpasswd.c:259 +#, c-format +msgid "%s: shadow group passwords required for -A\n" +msgstr "%s: óêéþäç óõíèçìáôéêÜ ïìÜäùí áðáéôïýíôáé ãéá ôï -A\n" + +#: src/gpasswd.c:310 +msgid "Who are you?\n" +msgstr "Ðïéïò åßóáé;\n" + +#: src/gpasswd.c:330 src/newgrp.c:241 +#, c-format +msgid "unknown group: %s\n" +msgstr "Üãíùóôç ïìÜäá: %s\n" + +#: src/gpasswd.c:438 +#, c-format +msgid "Adding user %s to group %s\n" +msgstr "ÐñïóèÞêç ôïõ ÷ñÞóôç %s óôçí ïìÜäá %s\n" + +#: src/gpasswd.c:455 +#, c-format +msgid "Removing user %s from group %s\n" +msgstr "ÄéáãñÜöç ôïõ ÷ñÞóôç %s áðü ôçí ïìÜäá %s\n" + +#: src/gpasswd.c:468 +#, c-format +msgid "%s: unknown member %s\n" +msgstr "%s: Üãíùóôï ìÝëïò %s\n" + +#: src/gpasswd.c:515 +#, c-format +msgid "%s: Not a tty\n" +msgstr "%s: Äåí åßíáé tty\n" + +#. +#. * A new password is to be entered and it must be encrypted, +#. * etc. The password will be prompted for twice, and both +#. * entries must be identical. There is no need to validate +#. * the old password since the invoker is either the group +#. * owner, or root. +#. +#: src/gpasswd.c:537 +#, c-format +msgid "Changing the password for group %s\n" +msgstr "ÁëëáãÞ ôïõ óõíèÞìáôïò ãéá ôçí ïìÜäá %s\n" + +#: src/gpasswd.c:540 +msgid "New Password:" +msgstr "ÍÝï Óõíèçìáôéêü:" + +#: src/gpasswd.c:545 src/passwd.c:424 +msgid "Re-enter new password:" +msgstr "ÅðáíåéóÜãåôå ôï íÝï óõíèçìáôéêü:" + +#: src/gpasswd.c:557 +msgid "They don't match; try again" +msgstr "Äåí ôáéñéÜæïõí. ÄïêéìÜóôå îáíÜ" + +#: src/gpasswd.c:561 +#, c-format +msgid "%s: Try again later\n" +msgstr "%s: ÎáíáäïêéìÜóôå áñãüôåñá\n" + +#: src/gpasswd.c:591 +#, c-format +msgid "%s: can't get lock\n" +msgstr "%s: Áäõíáìßá äçìéïõñãßáò êëåéäþìáôïò\n" + +#: src/gpasswd.c:597 +#, c-format +msgid "%s: can't get shadow lock\n" +msgstr "" +"%s: Áäõíáìßá äçìéïõñãßáò êëåéäþìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/gpasswd.c:603 +#, c-format +msgid "%s: can't open file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ %s\n" + +#: src/gpasswd.c:615 +#, c-format +msgid "%s: can't update entry\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò\n" + +#: src/gpasswd.c:621 +#, c-format +msgid "%s: can't update shadow entry\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#: src/gpasswd.c:627 +#, c-format +msgid "%s: can't re-write file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò áñ÷åßïõ\n" + +#: src/gpasswd.c:633 +#, c-format +msgid "%s: can't re-write shadow file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/gpasswd.c:641 +#, c-format +msgid "%s: can't unlock file\n" +msgstr "%s: áäõíáìßá îåêëåéäþìáôïò áñ÷åßïõ\n" + +#: src/gpasswd.c:646 +#, c-format +msgid "%s: can't update DBM files\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò ôùí DBM áñ÷åßùí\n" + +#: src/gpasswd.c:653 +#, c-format +msgid "%s: can't update DBM shadow files\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò ôùí DBM áñ÷åßùí óêéùäþí óõíèçìáôéêþí\n" + +#: src/groupadd.c:106 +msgid "usage: groupadd [-g gid [-o]] group\n" +msgstr "÷ñÞóç: groupadd [-g gid [-o]] ïìÜäá\n" + +#: src/groupadd.c:174 src/groupadd.c:197 src/groupmod.c:184 src/groupmod.c:231 +#: src/useradd.c:932 src/usermod.c:513 src/usermod.c:649 +#, c-format +msgid "%s: error adding new group entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí ðñïóèÞêç íÝáò êáôá÷þñçóçò óôï áñ÷åßï ïìÜäùí\n" + +#: src/groupadd.c:184 src/groupadd.c:207 src/groupmod.c:200 src/useradd.c:943 +#: src/usermod.c:525 src/usermod.c:661 +#, c-format +msgid "%s: cannot add new dbm group entry\n" +msgstr "%s: áäõíáìßá ðñïóèÞêçò íÝáò dbm êáôá÷þñçóçò óôï áñ÷åßï ïìÜäùí\n" + +#: src/groupadd.c:259 src/useradd.c:997 +#, c-format +msgid "%s: name %s is not unique\n" +msgstr "%s: Ôï üíïìá %s äåí åßíáé ìïíáäéêü\n" + +#: src/groupadd.c:274 +#, c-format +msgid "%s: gid %ld is not unique\n" +msgstr "%s: Ôï gid %ld äåí åßíáé ìïíáäéêü\n" + +#: src/groupadd.c:298 +#, c-format +msgid "%s: can't get unique gid\n" +msgstr "%s: áäõíáìßá åýñåóçò ìïíáäéêïý gid\n" + +#. +#. * All invalid group names land here. +#. +#: src/groupadd.c:322 src/groupmod.c:342 +#, c-format +msgid "%s: %s is a not a valid group name\n" +msgstr "%s: Ôï %s äåí åßíáé Ýãêõñï üíïìá ïìÜäáò\n" + +#: src/groupadd.c:351 src/groupmod.c:368 +#, c-format +msgid "%s: invalid group %s\n" +msgstr "%s: Ìç Ýãêõñç ïìÜäá `%s'\n" + +#: src/groupadd.c:368 src/useradd.c:1273 +#, c-format +msgid "%s: -O requires NAME=VALUE\n" +msgstr "%s: -O áðáéôåß ¼ÍÏÌÁ=ÔÉÌÇ\n" + +#: src/groupadd.c:413 src/groupdel.c:168 src/groupmod.c:404 src/useradd.c:1382 +#: src/userdel.c:273 src/usermod.c:537 +#, c-format +msgid "%s: cannot rewrite group file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò ôïõ áñ÷åßïõ ïìÜäùí\n" + +#: src/groupadd.c:419 src/groupdel.c:174 src/groupmod.c:410 src/useradd.c:1390 +#: src/userdel.c:279 src/usermod.c:674 +#, c-format +msgid "%s: cannot rewrite shadow group file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/groupadd.c:438 src/groupdel.c:193 src/groupmod.c:429 src/userdel.c:359 +#, c-format +msgid "%s: unable to lock group file\n" +msgstr "%s: Áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ ïìÜäùí\n" + +#: src/groupadd.c:442 src/groupdel.c:197 src/groupmod.c:433 +#, c-format +msgid "%s: unable to open group file\n" +msgstr "%s: Áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ ïìÜäùí\n" + +#: src/groupadd.c:447 src/groupdel.c:202 src/groupmod.c:438 src/userdel.c:368 +#, c-format +msgid "%s: unable to lock shadow group file\n" +msgstr "%s: Áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/groupadd.c:452 src/groupdel.c:207 src/groupmod.c:443 +#, c-format +msgid "%s: unable to open shadow group file\n" +msgstr "%s: Áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/groupadd.c:519 +#, c-format +msgid "%s: group %s exists\n" +msgstr "%s: Ç ïìÜäá %s õðÜñ÷åé\n" + +#: src/groupdel.c:87 +msgid "usage: groupdel group\n" +msgstr "÷ñÞóç: groupdel ïìÜäá\n" + +#: src/groupdel.c:105 src/groupmod.c:188 src/groupmod.c:235 +#, c-format +msgid "%s: error removing group entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ êáôá÷þñçóçò ïìÜäáò\n" + +#: src/groupdel.c:117 src/groupmod.c:207 +#, c-format +msgid "%s: error removing group dbm entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ êáôá÷þñçóçò óôï dbm áñ÷åßï ïìÜäùí\n" + +#: src/groupdel.c:132 +#, c-format +msgid "%s: error removing shadow group entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áöáßñåóç êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí " +"ïìÜäùí\n" + +#: src/groupdel.c:145 src/groupmod.c:253 +#, c-format +msgid "%s: error removing shadow group dbm entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áöáßñåóç êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#. +#. * Can't remove the group. +#. +#: src/groupdel.c:249 +#, c-format +msgid "%s: cannot remove user's primary group.\n" +msgstr "%s: áäõíáìßá áöáßñåóçò ôçò ðñùôáñ÷éêÞò ïìÜäáò ôïõ ÷ñÞóôç.\n" + +#: src/groupdel.c:306 src/groupmod.c:502 +#, c-format +msgid "%s: group %s does not exist\n" +msgstr "%s: Ç ïìÜäá %s äåí õðÜñ÷åé\n" + +#: src/groupdel.c:320 src/groupmod.c:518 +#, c-format +msgid "%s: group %s is a NIS group\n" +msgstr "%s: Ç ïìÜäá %s åßíáé NIS ïìÜäá\n" + +#: src/groupdel.c:326 src/groupmod.c:524 src/userdel.c:731 src/usermod.c:990 +#, c-format +msgid "%s: %s is the NIS master\n" +msgstr "%s: Ï %s åßíáé ï êýñéïò äéáêïìéóôÞò NIS\n" + +#: src/groupmod.c:106 +msgid "usage: groupmod [-g gid [-o]] [-n name] group\n" +msgstr "÷ñÞóç: groupmod [-g gid [-o]] [-n üíïìá] ïìÜäá\n" + +#: src/groupmod.c:166 +#, fuzzy, c-format +msgid "%s: %s not found in /etc/group\n" +msgstr "%s: Ï %s äåí âñÝèçêå óôï /etc/passwd\n" + +#: src/groupmod.c:247 +#, c-format +msgid "%s: cannot add new dbm shadow group entry\n" +msgstr "" +"%s: áäõíáìßá ðñïóèÞêçò íÝáò dbm êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí " +"ïìÜäùí\n" + +#: src/groupmod.c:300 +#, c-format +msgid "%s: %ld is not a unique gid\n" +msgstr "%s: Ôï %ld äåí åßíáé ìïíáäéêü gid\n" + +#: src/groupmod.c:331 +#, c-format +msgid "%s: %s is not a unique name\n" +msgstr "%s: Ôï %s äåí åßíáé ìïíáäéêü üíïìá\n" + +#: src/groups.c:63 +#, c-format +msgid "unknown user %s\n" +msgstr "Üãíùóôïò ÷ñÞóôçò: %s\n" + +#: src/grpck.c:99 +#, c-format +msgid "Usage: %s [ -r ] [ group [ gshadow ] ]\n" +msgstr "×ñÞóç: %s [ -r ] [ group [ gshadow ] ]\n" + +#: src/grpck.c:101 +#, c-format +msgid "Usage: %s [ -r ] [ group ]\n" +msgstr "×ñÞóç: %s [ -r ] [ group ]\n" + +#: src/grpck.c:120 src/pwck.c:120 +msgid "No" +msgstr "Ï÷é" + +#: src/grpck.c:235 src/grpck.c:243 src/pwck.c:217 src/pwck.c:226 +#, c-format +msgid "%s: cannot lock file %s\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ %s\n" + +#: src/grpck.c:258 src/grpck.c:266 src/mkpasswd.c:217 src/pwck.c:242 +#: src/pwck.c:251 +#, c-format +msgid "%s: cannot open file %s\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò áñ÷åßïõ %s\n" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/grpck.c:299 +msgid "invalid group file entry\n" +msgstr "Ìç Ýãêõñç êáôá÷þñçóç óôï áñ÷åßï ïìÜäùí\n" + +#: src/grpck.c:300 src/grpck.c:363 src/grpck.c:455 src/grpck.c:518 +#: src/grpck.c:535 src/pwck.c:287 src/pwck.c:349 src/pwck.c:456 src/pwck.c:518 +#: src/pwck.c:542 +#, c-format +msgid "delete line `%s'? " +msgstr "äéáãñáöÞ ãñáììÞò `%s'; " + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/grpck.c:362 +msgid "duplicate group entry\n" +msgstr "áíôéãñáöÞ êáôá÷þñçóçò óôï áñ÷åßï ïìÜäùí\n" + +#: src/grpck.c:379 +#, c-format +msgid "invalid group name `%s'\n" +msgstr "Ìç Ýãêõñï üíïìá ïìÜäáò `%s'\n" + +#: src/grpck.c:389 +#, c-format +msgid "group %s: bad GID (%d)\n" +msgstr "ïìÜäá %s: ëÜèïò GID (%d)\n" + +#: src/grpck.c:415 +#, c-format +msgid "group %s: no user %s\n" +msgstr "ïìÜäá %s: äåí õðÜñ÷åé ÷ñÞóôçò %s\n" + +#: src/grpck.c:417 src/grpck.c:586 +#, c-format +msgid "delete member `%s'? " +msgstr "äéáãñáöÞ ìÝëïõò `%s'; " + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/grpck.c:454 +msgid "invalid shadow group file entry\n" +msgstr "Ìç Ýãêõñç êáôá÷þñçóç óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/grpck.c:517 +msgid "duplicate shadow group entry\n" +msgstr "áíôéãñáöÞ êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/grpck.c:534 +msgid "no matching group file entry\n" +msgstr "Äåí âñÝèçêå êáôá÷þñçóç óôï áñ÷åßï ïìÜäùí ðïõ íá ôáéñéÜæåé\n" + +#: src/grpck.c:554 +#, c-format +msgid "shadow group %s: no administrative user %s\n" +msgstr "óêéþäçò ïìÜäá %s: Äåí õðÜñ÷åé äéá÷åéñéóôÞò ÷ñÞóôçò %s\n" + +#: src/grpck.c:556 +#, c-format +msgid "delete administrative member `%s'? " +msgstr "äéáãñáöÞ äéá÷åéñéóôéêïý ìÝëïõò `%s'; " + +#: src/grpck.c:584 +#, c-format +msgid "shadow group %s: no user %s\n" +msgstr "óêéþäçò ïìÜäá %s: äåí õðÜñ÷åé ÷ñÞóôçò %s\n" + +#: src/grpck.c:611 src/grpck.c:617 src/pwck.c:573 src/pwck.c:581 +#, c-format +msgid "%s: cannot update file %s\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò áñ÷åßïõ %s\n" + +#: src/grpck.c:641 src/pwck.c:607 +#, c-format +msgid "%s: the files have been updated; run mkpasswd\n" +msgstr "%s: ôá áñ÷åßá áíáíåþèçêáí. ÅêôåëÝóôå mkpasswd\n" + +#: src/grpck.c:642 src/grpck.c:646 src/pwck.c:608 src/pwck.c:612 +#, c-format +msgid "%s: no changes\n" +msgstr "%s: êáìéÜ áëëáãÞ\n" + +#: src/grpck.c:645 src/pwck.c:611 +#, c-format +msgid "%s: the files have been updated\n" +msgstr "%s: ôá áñ÷åßá áíáíåþèçêáí\n" + +#: src/grpconv.c:63 src/grpunconv.c:64 +#, c-format +msgid "%s: can't lock group file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ ïìÜäùí\n" + +#: src/grpconv.c:68 src/grpunconv.c:69 +#, c-format +msgid "%s: can't open group file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ ïìÜäùí\n" + +#: src/grpconv.c:73 src/grpunconv.c:74 +#, c-format +msgid "%s: can't lock shadow group file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/grpconv.c:78 src/grpunconv.c:79 +#, c-format +msgid "%s: can't open shadow group file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#. +#. * This shouldn't happen (the entry exists) but... +#. +#: src/grpconv.c:94 +#, c-format +msgid "%s: can't remove shadow group %s\n" +msgstr "" +"%s: áäõíáìßá áöáßñåóçò ôçò ïìÜäáò %s, áðü ôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" +"ïìÜäùí\n" + +#: src/grpconv.c:135 src/pwconv.c:161 +#, c-format +msgid "%s: can't update shadow entry for %s\n" +msgstr "" +"%s: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí ãéá ôïí " +"%s\n" + +#: src/grpconv.c:144 src/grpunconv.c:95 +#, c-format +msgid "%s: can't update entry for group %s\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò ãéá ôçí ïìÜäá %s\n" + +#: src/grpconv.c:151 src/grpunconv.c:103 +#, c-format +msgid "%s: can't update shadow group file\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/grpconv.c:155 src/grpunconv.c:108 +#, c-format +msgid "%s: can't update group file\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò ãéá ôï áñ÷åßï ïìÜäùí\n" + +#: src/grpconv.c:170 src/grpunconv.c:129 +#, c-format +msgid "%s: not configured for shadow group support.\n" +msgstr "%s: Äåí åßíáé äéáìïñöùìÝíï ãéá óêéþäç óõíèçìáôéêÜ ïìÜäùí.\n" + +#: src/grpunconv.c:113 +#, c-format +msgid "%s: can't delete shadow group file\n" +msgstr "" +"%s: Äåí åßíáé äõíáôüí íá äéáãñáöåß ôï áñ÷åßï óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/id.c:57 +msgid "usage: id [ -a ]\n" +msgstr "÷ñÞóç: id [ -a ]\n" + +#: src/id.c:59 +msgid "usage: id\n" +msgstr "÷ñÞóç: id\n" + +#: src/id.c:119 +#, c-format +msgid "uid=%d(%s)" +msgstr "" + +#: src/id.c:121 +#, c-format +msgid "uid=%d" +msgstr "" + +#: src/id.c:125 +#, c-format +msgid " gid=%d(%s)" +msgstr "" + +#: src/id.c:127 +#, c-format +msgid " gid=%d" +msgstr "" + +#: src/id.c:137 +#, c-format +msgid " euid=%d(%s)" +msgstr "" + +#: src/id.c:139 +#, c-format +msgid " euid=%d" +msgstr "" + +#: src/id.c:144 +#, c-format +msgid " egid=%d(%s)" +msgstr "" + +#: src/id.c:146 +#, c-format +msgid " egid=%d" +msgstr "" + +#. +#. * Start off the group message. It will be of the format +#. * +#. * groups=###(aaa),###(aaa),###(aaa) +#. * +#. * where "###" is a numerical value and "aaa" is the +#. * corresponding name for each respective numerical value. +#. +#: src/id.c:167 +msgid " groups=" +msgstr " ïìÜäåò=" + +#: src/lastlog.c:168 +msgid "Username Port From Latest\n" +msgstr "¼íïìá_×ñÞóôç Èýñá Áðü Ôåëåõôáßá\n" + +#: src/lastlog.c:170 +msgid "Username Port Latest\n" +msgstr "¼íïìá_×ñÞóôç Èýñá Ôåëåõôáßá\n" + +#: src/lastlog.c:184 +msgid "**Never logged in**" +msgstr "**ÊáìéÜ åßóïäïò óôï óýóôçìá**" + +#: src/login.c:199 +#, c-format +msgid "usage: %s [-p] [name]\n" +msgstr "÷ñÞóç: %s [-p] [üíïìá]\n" + +#: src/login.c:202 +#, c-format +msgid " %s [-p] [-h host] [-f name]\n" +msgstr " %s [-p] [-h óýóôçìá] [-f üíïìá]\n" + +#: src/login.c:204 +#, c-format +msgid " %s [-p] -r host\n" +msgstr " %s [-p] -r óýóôçìá\n" + +#: src/login.c:290 +msgid "Invalid login time\n" +msgstr "ÅóöáëìÝíç þñá åéóüäïõ\n" + +#: src/login.c:345 +msgid "" +"\n" +"System closed for routine maintenance\n" +msgstr "" +"\n" +"Ôï óýóôçìá Ýêëåéóå ãéá óõíôÞñçóç ñïõôßíáò\n" + +#: src/login.c:355 +msgid "" +"\n" +"[Disconnect bypassed -- root login allowed.]\n" +msgstr "" +"\n" +"[ÐáñÜêáìøç áðïóýíäåóçò -- Ç åßóïäïò ôïõ root åðåôñÜðç.]\n" + +#: src/login.c:394 +#, c-format +msgid "" +"\n" +"Login timed out after %d seconds.\n" +msgstr "" +"\n" +"Ç äéáäéêáóßá åéóüäïõ ôåñìáôßóôçêå ìåôÜ áðü %d äåõôåñüëåðôá.\n" + +#: src/login.c:695 +#, c-format +msgid " on `%.100s' from `%.200s'" +msgstr " óôï `%.100s' áðü `%.200s'" + +#: src/login.c:697 +#, c-format +msgid " on `%.100s'" +msgstr " óôï `%.100s'" + +#: src/login.c:810 +#, c-format +msgid "" +"\n" +"%s login: " +msgstr "" +"\n" +"%s login: " + +#: src/login.c:812 +msgid "login: " +msgstr "login: " + +#: src/login.c:994 src/sulogin.c:239 +msgid "Login incorrect" +msgstr "Äéáäéêáóßá åéóüäïõ áðÝôõ÷å" + +#: src/login.c:1166 +msgid "Warning: login re-enabled after temporary lockout.\n" +msgstr "" +"Ðñïåéäïðïßçóç: Ç åßóïäïò åðáíåíåñãïðïéÞèçêå ìåôÜ áðü ðñïóùñéíü áðïêëåéóìü.\n" + +#: src/login.c:1176 +#, c-format +msgid "Last login: %s on %s" +msgstr "Ôåëåõôáßá åßóïäïò: %s óôï %s" + +#: src/login.c:1179 +#, c-format +msgid "Last login: %.19s on %s" +msgstr "Ôåëåõôáßá åßóïäïò: %.19s óôï %s" + +#: src/login.c:1184 +#, c-format +msgid " from %.*s" +msgstr " áðü %.*s" + +#: src/login.c:1249 +msgid "Starting rad_login\n" +msgstr "¸íáñîç rad_login\n" + +#: src/mkpasswd.c:49 +#, c-format +msgid "%s: no DBM database on system - no action performed\n" +msgstr "" +"%s: Äåí õðÜñ÷åé DBM âÜóç äåäïìÝíùí óôï óýóôçìá - êáìéÜ åíÝñãåéá äåí " +"åêôåëåßôáé\n" + +#: src/mkpasswd.c:246 src/mkpasswd.c:250 +#, c-format +msgid "%s: cannot overwrite file %s\n" +msgstr "%s: áäõíáìßá åããñáöÞò ðÜíù áðü ôï áñ÷åßï %s\n" + +#: src/mkpasswd.c:264 +#, c-format +msgid "%s: cannot open DBM files for %s\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò DBM áñ÷åßùí ãéá ôï %s\n" + +#: src/mkpasswd.c:297 +#, c-format +msgid "%s: the beginning with " +msgstr "%s: ç áñ÷Þ ìå " + +#: src/mkpasswd.c:322 +#, c-format +msgid "%s: error parsing line \"%s\"\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí åðåîåñãáóßá ôçò ãñáììÞò \"%s\"\n" + +#: src/mkpasswd.c:327 src/mkpasswd.c:329 src/mkpasswd.c:331 src/mkpasswd.c:333 +msgid "adding record for name " +msgstr "ðñïóèÞêç êáôá÷þñçóçò ãéá üíïìá " + +#: src/mkpasswd.c:337 src/mkpasswd.c:342 src/mkpasswd.c:346 src/mkpasswd.c:350 +#, c-format +msgid "%s: error adding record for " +msgstr "%s: ÓöÜëìá êáôÜ ôçí ðñïóèÞêç êáôá÷þñçóçò ãéá " + +#: src/mkpasswd.c:368 +#, c-format +msgid "added %d entries, longest was %d\n" +msgstr "ðñïóôÝèçêáí %d êáôá÷ùñÞóåéò, ç ìåãáëýôåñç Þôáí %d\n" + +#: src/mkpasswd.c:383 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n" +msgstr "×ñÞóç: %s [ -vf ] [ -p|g|sp|sg ] áñ÷åßï\n" + +#: src/mkpasswd.c:385 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g|sp ] file\n" +msgstr "×ñÞóç: %s [ -vf ] [ -p|g|sp ] áñ÷åßï\n" + +#: src/mkpasswd.c:388 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g ] file\n" +msgstr "×ñÞóç: %s [ -vf ] [ -p|g ] áñ÷åßï\n" + +#: src/newgrp.c:67 +msgid "usage: newgrp [ - ] [ group ]\n" +msgstr "÷ñÞóç: newgrp [ - ] [ ïìÜäá ]\n" + +#: src/newgrp.c:69 +msgid "usage: sg group [ command ]\n" +msgstr "÷ñÞóç: sg ïìÜäá [ åíôïëÞ ]\n" + +#: src/newgrp.c:122 +#, c-format +msgid "unknown uid: %d\n" +msgstr "Üãíùóôï uid: %d\n" + +#: src/newgrp.c:190 +#, c-format +msgid "unknown gid: %ld\n" +msgstr "Üãíùóôï gid: %ld\n" + +#: src/newgrp.c:236 +#, c-format +msgid "unknown gid: %d\n" +msgstr "Üãíùóôï gid: %d\n" + +#. +#. * get the password from her, and set the salt for +#. * the decryption from the group file. +#. +#: src/newgrp.c:291 +msgid "Password:" +msgstr "Óõíèçìáôéêü:" + +#: src/newgrp.c:309 src/newgrp.c:318 +msgid "Sorry.\n" +msgstr "ËõðÜìáé.\n" + +#: src/newgrp.c:350 +msgid "too many groups\n" +msgstr "ðÜñá ðïëëÝò ïìÜäåò\n" + +#: src/newusers.c:79 +#, c-format +msgid "Usage: %s [ input ]\n" +msgstr "×ñÞóç: %s [ åßóïäïò ]\n" + +#: src/newusers.c:367 +#, c-format +msgid "%s: can't lock /etc/passwd.\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ /etc/passwd.\n" + +#: src/newusers.c:378 +#, c-format +msgid "%s: can't lock files, try again later\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò áñ÷åßùí, îáíáäïêéìÜóôå áñãüôåñá\n" + +#: src/newusers.c:393 +#, c-format +msgid "%s: can't open files\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôùí áñ÷åßùí\n" + +#: src/newusers.c:438 +#, c-format +msgid "%s: line %d: invalid line\n" +msgstr "%s: ãñáììÞ %d: ìç Ýãêõñç ãñáììÞ\n" + +#: src/newusers.c:456 +#, c-format +msgid "%s: line %d: can't create GID\n" +msgstr "%s: ãñáììÞ %d: áäõíáìßá äçìéïõñãßáò GID\n" + +#: src/newusers.c:472 +#, c-format +msgid "%s: line %d: can't create UID\n" +msgstr "%s: ãñáììÞ %d: áäõíáìßá äçìéïõñãßáò UID\n" + +#: src/newusers.c:484 +#, c-format +msgid "%s: line %d: cannot find user %s\n" +msgstr "%s: ãñáììÞ %d: áäõíáìßá åýñåóçò ÷ñÞóôç %s\n" + +#: src/newusers.c:492 +#, c-format +msgid "%s: line %d: can't update password\n" +msgstr "%s: ãñáììÞ %d: áäõíáìßá áíáíÝùóç óõíèçìáôéêïý\n" + +#: src/newusers.c:509 +#, c-format +msgid "%s: line %d: mkdir failed\n" +msgstr "%s: ãñáììÞ %d: áðïôõ÷ßá äçìéïõñãßáò êáôáëüãïõ(mkdir)\n" + +#: src/newusers.c:513 +#, c-format +msgid "%s: line %d: chown failed\n" +msgstr "%s: ãñáììÞ %d: áðïôõ÷ßá áëëáãÞò éäéïêôÞôç(chown)\n" + +#: src/newusers.c:522 +#, c-format +msgid "%s: line %d: can't update entry\n" +msgstr "%s: ãñáììÞ %d: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò\n" + +#: src/newusers.c:553 +#, c-format +msgid "%s: error updating files\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí åíçìÝñùóç áñ÷åßùí\n" + +#: src/passwd.c:241 +#, c-format +msgid "usage: %s [ -f | -s ] [ name ]\n" +msgstr "÷ñÞóç: %s [ -f | -s ] [ üíïìá ]\n" + +#: src/passwd.c:244 +#, c-format +msgid " %s [ -x max ] [ -n min ] [ -w warn ] [ -i inact ] name\n" +msgstr "" +" %s [ -x ìåã. ] [ -n åëÜ÷. ] [ -w ðñïåéä. ] [ -i áíåíåñãü ] üíïìá\n" + +#: src/passwd.c:247 +#, c-format +msgid " %s { -l | -u | -d | -S | -e } name\n" +msgstr " %s { -l | -u | -d | -S | -e } üíïìá\n" + +#: src/passwd.c:349 +#, c-format +msgid "User %s has a TCFS key, his old password is required.\n" +msgstr "Ï ÷ñÞóôçò %s Ý÷åé êëåéäß TCFS, áðáéôåßôáé ôï ðáëéü óõíèçìáôéêü.\n" + +#: src/passwd.c:350 +msgid "You can use -t option to force the change.\n" +msgstr "" +"Ìðïñåßôå íá ÷ñçóéìïðïéÞóåôå ôçí -t ðáñÜìåôñï ãéá íá åîáíáãêÜóåôå ôçí\n" +"ðñáãìáôïðïßçóç ôçò áëëáãÞò.\n" + +#: src/passwd.c:356 +msgid "Old password:" +msgstr "Ðáëéü Óõíèçìáôéêü:" + +#: src/passwd.c:363 +#, c-format +msgid "Incorrect password for `%s'\n" +msgstr "ÅóöáëìÝíï óõíèçìáôéêü ãéá ôïí `%s'\n" + +#: src/passwd.c:376 +#, c-format +msgid "Warning: user %s has a TCFS key.\n" +msgstr "Ðñïåéäïðïßçóç: Ï ÷ñÞóôçò %s Ý÷åé êëåéäß TCFS.\n" + +#: src/passwd.c:394 +#, c-format +msgid "" +"Enter the new password (minimum of %d, maximum of %d characters)\n" +"Please use a combination of upper and lower case letters and numbers.\n" +msgstr "" +"ÅéóÜãåôå ôï íÝï óõíèçìáôéêü (åëÜ÷éóôï %d, ìÝãéóôï %d ÷áñáêôÞñåò)\n" +"Ðáñáêáëþ ÷ñçóéìïðïéÞóôå Ýíá óõíäõáóìü áðü êåöáëáßá êáé ìéêñÜ ãñÜììáôá\n" +"êáèþò êáé áñéèìïýò.\n" + +#: src/passwd.c:401 +msgid "New password:" +msgstr "ÍÝï Óõíèçìáôéêü:" + +#: src/passwd.c:411 +msgid "Try again.\n" +msgstr "ÎáíáäïêéìÜóôå.\n" + +#: src/passwd.c:420 +msgid "" +"\n" +"Warning: weak password (enter it again to use it anyway).\n" +msgstr "" +"\n" +"Ðñïóï÷Þ: áäýíáìï óõíèçìáôéêü (åéóÜãåôÝ ôï ðÜëé ãéá íá ôï ÷ñçóéìïðïéÞóåôå).\n" + +#: src/passwd.c:429 +msgid "They don't match; try again.\n" +msgstr "Äåí ôáéñéÜæïõí. ÄïêéìÜóôå îáíÜ.\n" + +#: src/passwd.c:514 src/passwd.c:530 +#, c-format +msgid "The password for %s cannot be changed.\n" +msgstr "Ôï óõíèçìáôéêü ãéá ôïí %s äåí ìðïñåß íá áëëÜîåé.\n" + +#: src/passwd.c:558 +#, c-format +msgid "Sorry, the password for %s cannot be changed yet.\n" +msgstr "Óõãíþìç, ôï óõíèçìáôéêü ãéá ôïí %s äåí ìðïñåß íá áëëÜîåé áêüìç.\n" + +#: src/passwd.c:695 +#, c-format +msgid "%s: out of memory\n" +msgstr "%s: äåí õðÜñ÷åé åëåýèåñç ìíÞìç\n" + +#: src/passwd.c:847 +msgid "Cannot lock the TCFS key database; try again later\n" +msgstr "Áäõíáìßá êëåéäþìáôïò ôçò âÜóçò êëåéäéþí ôïõ TCFS. ÄïêéìÜóôå áñãüôåñá\n" + +#: src/passwd.c:853 +msgid "Cannot open the TCFS key database.\n" +msgstr "Áäõíáìßá áíïßãìáôïò ôçò âÜóçò êëåéäéþí ôïõ TCFS.\n" + +#: src/passwd.c:859 +msgid "Error updating the TCFS key database.\n" +msgstr "ÓöÜëìá êáôÜ ôçí áíáíÝùóç ôçò âÜóçò êëåéäéþí ôïõ TCFS.\n" + +#: src/passwd.c:864 +msgid "Cannot commit TCFS changes.\n" +msgstr "Áäõíáìßá õëïðïßçóçò ôùí áëëáãþí óôï TCFS.\n" + +#: src/passwd.c:1071 +#, c-format +msgid "%s: Cannot execute %s" +msgstr "%s: Áäõíáìßá åêôÝëåóçò ôïõ %s" + +#: src/passwd.c:1178 +#, c-format +msgid "%s: repository %s not supported\n" +msgstr "%s: ç áðïèÞêç %s äåí õðïóôçñßæåôáé\n" + +#: src/passwd.c:1265 +#, c-format +msgid "%s: Permission denied\n" +msgstr "%s: ¶äåéá áðïññßöèçêå\n" + +#: src/passwd.c:1289 +#, c-format +msgid "You may not change the password for %s.\n" +msgstr "Äåí ìðïñåßôå íá áëëÜîåôå ôï óõíèçìáôéêü ãéá ôï(í) %s.\n" + +#: src/passwd.c:1354 +#, c-format +msgid "Changing password for %s\n" +msgstr "ÁëëáãÞ óõíèçìáôéêïý ãéá ôïí %s\n" + +#: src/passwd.c:1358 +#, c-format +msgid "The password for %s is unchanged.\n" +msgstr "Ôï óõíèçìáôéêü ãéá ôïí %s äåí Üëëáîå.\n" + +#: src/passwd.c:1414 +msgid "Password changed.\n" +msgstr "Ôï óõíèçìáôéêü Üëëáîå.\n" + +#: src/pwck.c:99 +#, c-format +msgid "Usage: %s [ -qr ] [ passwd [ shadow ] ]\n" +msgstr "×ñÞóç: %s [ -qr ] [ passwd [ shadow ] ]\n" + +#: src/pwck.c:101 +#, c-format +msgid "Usage: %s [ -qr ] [ passwd ]\n" +msgstr "×ñÞóç: %s [ -qr ] [ passwd ]\n" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/pwck.c:286 +msgid "invalid password file entry\n" +msgstr "Ìç Ýãêõñç êáôá÷þñçóç óôï áñ÷åßï óõíèçìáôéêþí\n" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/pwck.c:348 +msgid "duplicate password entry\n" +msgstr "áíôéãñáöÞ êáôá÷þñçóçò óôï áñ÷åßï óõíèçìáôéêþí\n" + +#: src/pwck.c:364 +#, c-format +msgid "invalid user name `%s'\n" +msgstr "Ìç Ýãêõñï üíïìá ÷ñÞóôç `%s'\n" + +#: src/pwck.c:374 +#, c-format +msgid "user %s: bad UID (%d)\n" +msgstr "÷ñÞóôçò %s: ëáíèáóìÝíï UID (%d)\n" + +#. +#. * No primary group, just give a warning +#. +#: src/pwck.c:389 +#, c-format +msgid "user %s: no group %d\n" +msgstr "÷ñÞóôçò %s: êáìéÜ ïìÜäá %d\n" + +#. +#. * Home directory doesn't exist, give a warning +#. +#: src/pwck.c:404 +#, c-format +msgid "user %s: directory %s does not exist\n" +msgstr "÷ñÞóôçò %s: ï êáôÜëïãïò %s äåí õðÜñ÷åé\n" + +#. +#. * Login shell doesn't exist, give a warning +#. +#: src/pwck.c:419 +#, c-format +msgid "user %s: program %s does not exist\n" +msgstr "÷ñÞóôçò %s: ôï ðñüãñáììá %s äåí õðÜñ÷åé\n" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/pwck.c:455 +msgid "invalid shadow password file entry\n" +msgstr "Ìç Ýãêõñç êáôá÷þñçóç óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/pwck.c:517 +msgid "duplicate shadow password entry\n" +msgstr "áíôéãñáöÞ êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#. +#. * Tell the user this entry has no matching +#. * /etc/passwd entry and ask them to delete it. +#. +#: src/pwck.c:541 +msgid "no matching password file entry\n" +msgstr "Äåí âñÝèçêå êáôá÷þñçóç óôï áñ÷åßï óõíèçìáôéêþí ðïõ íá ôáéñßáæåé\n" + +#: src/pwck.c:558 +#, c-format +msgid "user %s: last password change in the future\n" +msgstr "÷ñÞóôçò %s: ôåëåõôáßá áëëáãÞ óõíèçìáôéêïý óôï ìÝëëïí\n" + +#: src/pwconv.c:95 src/pwunconv.c:109 +#, c-format +msgid "%s: can't lock passwd file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/pwconv.c:100 src/pwunconv.c:114 +#, c-format +msgid "%s: can't open passwd file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/pwconv.c:127 +#, c-format +msgid "%s: can't remove shadow entry for %s\n" +msgstr "" +"áäõíáìßá áöáßñåóçò êáôá÷þñçóçò ãéá ôïí %s, áðü ôï áñ÷åßï óêéùäþí " +"óõíèçìáôéêþí\n" + +#: src/pwconv.c:170 +#, c-format +msgid "%s: can't update passwd entry for %s\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò óõíèçìáôéêïý ãéá ôïí %s\n" + +#: src/pwconv.c:177 +#, c-format +msgid "%s: can't update shadow file\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/pwconv.c:181 +#, c-format +msgid "%s: can't update passwd file\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/pwunconv.c:62 +#, c-format +msgid "%s: Shadow passwords are not configured.\n" +msgstr "%s: Ôá óêéþäç óõíèçìáôéêÜ äåí Ý÷ïõí äéáìïñöùèåß.\n" + +#: src/pwunconv.c:172 +#, c-format +msgid "%s: can't update entry for user %s\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò êáôá÷þñçóçò ãéá ôïí ÷ñÞóôç %s\n" + +#: src/pwunconv.c:189 +#, c-format +msgid "%s: can't delete shadow password file\n" +msgstr "%s: Äåí åßíáé äõíáôüí íá äéáãñáöåß ôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#: src/su.c:145 +msgid "Sorry." +msgstr "ËõðÜìáé." + +#: src/su.c:227 +#, c-format +msgid "%s: must be run from a terminal\n" +msgstr "%s: ðñÝðåé íá åêôåëåóôåß áðü ôåñìáôéêü\n" + +#: src/su.c:319 +#, c-format +msgid "%s: pam_start: error %d\n" +msgstr "%s: pam_start: óöÜëìá %d\n" + +#: src/su.c:345 +#, c-format +msgid "Unknown id: %s\n" +msgstr "Áãíùóôç ôáõôüôçôá: %s\n" + +#. access denied (-1) or unexpected value +#: src/su.c:380 src/su.c:395 +#, c-format +msgid "You are not authorized to su %s\n" +msgstr "Äåí Ý÷åôå Üäåéá ãéá su %s\n" + +#. require own password +#: src/su.c:391 +msgid "(Enter your own password.)" +msgstr "(ÅéóÜãåôå ôï äéêü óáò óõíèçìáôéêü.)" + +#: src/su.c:412 +#, c-format +msgid "%s: permission denied (shell).\n" +msgstr "%s: Üäåéá áðïññßöèçêå (öëïéüò)\n" + +#: src/su.c:436 +#, c-format +msgid "" +"%s: %s\n" +"(Ignored)\n" +msgstr "" +"%s: %s\n" +"(ÁãíïÞèçêå)\n" + +#: src/su.c:605 +msgid "No shell\n" +msgstr "Äåí õðÜñ÷åé öëïéüò\n" + +#. must be a password file! +#: src/sulogin.c:144 +msgid "No password file\n" +msgstr "Äåí õðÜñ÷åé áñ÷åßï óõíèçìáôéêþí\n" + +#. +#. * Fail secure +#. +#: src/sulogin.c:186 +msgid "No password entry for 'root'\n" +msgstr "Äåí õðÜñ÷åé êáôá÷þñçóç óõíèçìáôéêïý ãéá ôïí 'root'\n" + +#. +#. * Here we prompt for the root password, or if no password is +#. * given we just exit. +#. +#. get a password for root +#: src/sulogin.c:200 +msgid "" +"\n" +"Type control-d to proceed with normal startup,\n" +"(or give root password for system maintenance):" +msgstr "" +"\n" +"ÐëçêôñïëïãÞóôå control-d ãéá íá óõíå÷ßóåôå ìå ôçí êáíïíéêÞ Ýíáñîç,\n" +"(Þ äþóôå ôï óõíèçìáôéêü ôïõ root ãéá óõíôÞñçóç ôïõ óõóôÞìáôïò):" + +#. make new environment active +#: src/sulogin.c:249 +msgid "Entering System Maintenance Mode\n" +msgstr "¸íáñîç ÊáôÜóôáóçò ÓõíôÞñçóçò ÓõóôÞìáôïò\n" + +#: src/useradd.c:244 +#, c-format +msgid "%s: rebuild the group database\n" +msgstr "%s: åðáíáêôßóôå ôçí âÜóç äåäïìÝíùí ïìÜäùí\n" + +#: src/useradd.c:251 +#, c-format +msgid "%s: rebuild the shadow group database\n" +msgstr "%s: åðáíáêôßóôå ôçí âÜóç äåäïìÝíùí ôùí óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/useradd.c:288 src/usermod.c:941 +#, c-format +msgid "%s: invalid numeric argument `%s'\n" +msgstr "%s: Ìç Ýãêõñç áñéèìçôéêÞ ðáñÜìåôñïò `%s'\n" + +#: src/useradd.c:344 +#, c-format +msgid "%s: unknown gid %s\n" +msgstr "%s: Üãíùóôï gid %s\n" + +#: src/useradd.c:351 src/useradd.c:643 src/useradd.c:1229 src/usermod.c:253 +#: src/usermod.c:1072 +#, c-format +msgid "%s: unknown group %s\n" +msgstr "%s: Üãíùóôç ïìÜäá %s\n" + +#: src/useradd.c:419 +#, c-format +msgid "group=%s,%ld basedir=%s skel=%s\n" +msgstr "ïìÜäá=%s,%ld âáóéêüò_êáôáë=%s óêåë=%s\n" + +#: src/useradd.c:422 +#, c-format +msgid "shell=%s " +msgstr "öëïéüò=%s " + +#: src/useradd.c:424 +#, c-format +msgid "inactive=%ld expire=%s" +msgstr "áíåíåñãü=%ld ëÞîç=%s" + +#: src/useradd.c:428 +#, c-format +msgid "GROUP=%ld\n" +msgstr "ÏÌÁÄÁ=%ld\n" + +#: src/useradd.c:429 +#, c-format +msgid "HOME=%s\n" +msgstr "ÌÇÔÑÉÊÏÓ_ÊÁÔÁËÏÃÏÓ=%s\n" + +#: src/useradd.c:431 +#, c-format +msgid "INACTIVE=%ld\n" +msgstr "ÁÍÅÍÅÑÃÏÓ=%ld\n" + +#: src/useradd.c:432 +#, c-format +msgid "EXPIRE=%s\n" +msgstr "ËÇÎÇ=%s\n" + +#: src/useradd.c:434 +#, c-format +msgid "SHELL=%s\n" +msgstr "ÊÅËÕÖÏÓ=%s\n" + +#: src/useradd.c:435 +#, c-format +msgid "SKEL=%s\n" +msgstr "ÓÊÅË=%s\n" + +#: src/useradd.c:471 +#, c-format +msgid "%s: cannot create new defaults file\n" +msgstr "%s: áäõíáìßá äçìéïõñãßáò íÝïõ áñ÷åßïõ ðñïêáèïñéóìÝíùí ñõèìßóåùí\n" + +#: src/useradd.c:565 src/useradd.c:576 +#, c-format +msgid "%s: rename: %s" +msgstr "%s: ìåôïíïìáóßá: %s" + +#: src/useradd.c:663 src/usermod.c:273 +#, c-format +msgid "%s: group `%s' is a NIS group.\n" +msgstr "%s: Ç ïìÜäá `%s' åßíáé NIS ïìÜäá.\n" + +#: src/useradd.c:671 src/usermod.c:281 +#, c-format +msgid "%s: too many groups specified (max %d).\n" +msgstr "%s: Ðñïóäéïñßóôçêáí õðåñâïëéêÝò ïìÜäåò (ìåã. %d).\n" + +#: src/useradd.c:703 src/usermod.c:313 +#, c-format +msgid "usage: %s\t[-u uid [-o]] [-g group] [-G group,...] \n" +msgstr "÷ñÞóç: %s\t[-u uid [-o]] [-g ïìÜäá] [-G ïìÜäá,...] \n" + +#: src/useradd.c:706 +msgid "\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n" +msgstr "" +"\t\t[-d ìçôñéêüò_êáôÜëïãïò] [-s öëïéüò] [-c ó÷üëéï]\n" +"\t\t[-m [-k êáíüíáò]]\n" + +#: src/useradd.c:709 src/usermod.c:319 +msgid "[-f inactive] [-e expire ] " +msgstr "[-f áíåíåñãü] [-e ëÞîç ] " + +#: src/useradd.c:712 +msgid "[-A program] " +msgstr "[-A ðñüãñáììá] " + +#: src/useradd.c:714 src/usermod.c:324 +msgid "[-p passwd] name\n" +msgstr "[-p óõíèçìáôéêü] üíïìá\n" + +#: src/useradd.c:716 +#, c-format +msgid " %s\t-D [-g group] [-b base] [-s shell]\n" +msgstr " %s\t-D [-g ïìÜäá] [-b âÜóç] [-s öëïéüò]\n" + +#: src/useradd.c:719 +msgid "\t\t[-f inactive] [-e expire ]\n" +msgstr "\t\t[-f áíåíåñãü] [-e ëÞîç ]\n" + +#: src/useradd.c:816 src/usermod.c:446 +#, c-format +msgid "%s: error locking group file\n" +msgstr "%s: ÓöÜëìá êáôÜ ôï êëåßäùìá ôïõ áñ÷åßïõ ïìÜäùí\n" + +#: src/useradd.c:820 src/usermod.c:451 +#, c-format +msgid "%s: error opening group file\n" +msgstr "%s: ÓöÜëìá êáôÜ ôï Üíïéãìá ôïõ áñ÷åßïõ ïìÜäùí\n" + +#: src/useradd.c:825 src/usermod.c:558 +#, c-format +msgid "%s: error locking shadow group file\n" +msgstr "%s: ÓöÜëìá êáôÜ ôï êëåßäùìá ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/useradd.c:830 src/usermod.c:564 +#, c-format +msgid "%s: error opening shadow group file\n" +msgstr "%s: ÓöÜëìá êáôÜ ôï Üíïéãìá ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/useradd.c:1002 +#, c-format +msgid "%s: uid %d is not unique\n" +msgstr "%s: Ôï uid %d äåí åßíáé ìïíáäéêü\n" + +#: src/useradd.c:1032 +#, c-format +msgid "%s: can't get unique uid\n" +msgstr "%s: áäõíáìßá åõñåóçò ìïíáäéêïý uid\n" + +#: src/useradd.c:1140 src/useradd.c:1284 src/usermod.c:1020 src/usermod.c:1031 +#: src/usermod.c:1041 src/usermod.c:1087 src/usermod.c:1122 +#, c-format +msgid "%s: invalid field `%s'\n" +msgstr "%s: Ìç Ýãêõñï ðåäßï `%s'\n" + +#: src/useradd.c:1154 +#, c-format +msgid "%s: invalid base directory `%s'\n" +msgstr "%s: Ìç Ýãêõñïò êáôÜëïãïò âÜóçò `%s'\n" + +#: src/useradd.c:1164 +#, c-format +msgid "%s: invalid comment `%s'\n" +msgstr "%s: Ìç Ýãêõñï ó÷üëéï `%s'\n" + +#: src/useradd.c:1174 +#, c-format +msgid "%s: invalid home directory `%s'\n" +msgstr "%s: Ìç Ýãêõñïò ìçôñéêüò êáôÜëïãïò ÷ñÞóôç `%s'\n" + +#: src/useradd.c:1192 src/usermod.c:1054 +#, c-format +msgid "%s: invalid date `%s'\n" +msgstr "%s: Ìç Ýãêõñç çìåñïìçíßá `%s'\n" + +#: src/useradd.c:1204 +#, c-format +msgid "%s: shadow passwords required for -e\n" +msgstr "%s: óêéþäç óõíèçìáôéêÜ áðáéôïýíôáé ãéá ôï -e\n" + +#: src/useradd.c:1219 +#, c-format +msgid "%s: shadow passwords required for -f\n" +msgstr "%s: óêéþäç óõíèçìáôéêÜ áðáéôïýíôáé ãéá -f\n" + +#: src/useradd.c:1293 +#, c-format +msgid "%s: invalid shell `%s'\n" +msgstr "%s: Ìç Ýãêõñïò öëïéüò `%s'\n" + +#: src/useradd.c:1334 +#, c-format +msgid "%s: invalid user name `%s'\n" +msgstr "%s: Ìç Ýãêõñï üíïìá ÷ñÞóôç `%s'\n" + +#: src/useradd.c:1370 src/userdel.c:262 src/usermod.c:1184 +#, c-format +msgid "%s: cannot rewrite password file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/useradd.c:1375 src/userdel.c:265 src/usermod.c:1189 +#, c-format +msgid "%s: cannot rewrite shadow password file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/useradd.c:1415 src/userdel.c:329 src/usermod.c:1224 +#, c-format +msgid "%s: unable to lock password file\n" +msgstr "%s: Áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/useradd.c:1419 src/userdel.c:333 src/usermod.c:1228 +#, c-format +msgid "%s: unable to open password file\n" +msgstr "%s: Áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ óõíèçìáôéêþí\n" + +#: src/useradd.c:1425 src/userdel.c:338 src/usermod.c:1233 +#, c-format +msgid "%s: cannot lock shadow password file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/useradd.c:1431 src/userdel.c:343 src/usermod.c:1238 +#, c-format +msgid "%s: cannot open shadow password file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò áñ÷åßïõ óêéùäþí óõíèçìáôéêþí\n" + +#: src/useradd.c:1530 src/usermod.c:1325 +#, c-format +msgid "%s: error adding authentication method\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí ðñïóèÞêç ìåèüäïõ åîáêñßâùóçò\n" + +#: src/useradd.c:1553 +#, c-format +msgid "%s: error adding new password entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí ðñïóèÞêç íÝáò êáôá÷þñçóçò óôï áñ÷åßï óõíèçìáôéêþí\n" + +#: src/useradd.c:1568 +#, c-format +msgid "%s: error updating password dbm entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áíáíÝùóç êáôá÷ùñÞóåùí óôï dbm áñ÷åßï óõíèçìáôéêþí\n" + +#: src/useradd.c:1584 src/usermod.c:1384 +#, c-format +msgid "%s: error adding new shadow password entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí ðñïóèÞêç íÝáò êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí " +"óõíèçìáôéêþí\n" + +#: src/useradd.c:1600 src/usermod.c:1399 +#, c-format +msgid "%s: error updating shadow passwd dbm entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áíáíÝùóç êáôá÷ùñÞóåùí óôï dbm áñ÷åßï óêéùäþí " +"óõíèçìáôéêþí\n" + +#: src/useradd.c:1632 +#, c-format +msgid "%s: cannot create directory %s\n" +msgstr "%s: áäõíáìßá äçìéïõñãßáò êáôáëüãïõ %s\n" + +#: src/useradd.c:1709 src/usermod.c:1162 +#, c-format +msgid "%s: user %s exists\n" +msgstr "%s: Ï ÷ñÞóôçò %s õðÜñ÷åé\n" + +#: src/useradd.c:1739 +#, c-format +msgid "%s: warning: CREATE_HOME not supported, please use -m instead.\n" +msgstr "" + +#: src/userdel.c:128 +#, c-format +msgid "usage: %s [-r] name\n" +msgstr "÷ñÞóç: %s [-r] üíïìá\n" + +#: src/userdel.c:175 src/userdel.c:230 +#, c-format +msgid "%s: error updating group entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí áíáíÝùóç êáôá÷ùñÞóçò ïìÜäáò\n" + +#: src/userdel.c:185 src/userdel.c:239 +#, c-format +msgid "%s: cannot update dbm group entry\n" +msgstr "%s: áäõíáìßá áíáíÝùóçò ôçò dbm êáôá÷þñçóçò óôï áñ÷åßï ïìÜäùí\n" + +#: src/userdel.c:270 +#, c-format +msgid "%s: cannot rewrite TCFS key file\n" +msgstr "%s: áäõíáìßá åðáíåããñáöÞò ôïõ áñ÷åßïõ êëåéäéþí ôïõ TCFS\n" + +#: src/userdel.c:350 +#, c-format +msgid "%s: cannot lock TCFS key file\n" +msgstr "%s: áäõíáìßá êëåéäþìáôïò ôïõ áñ÷åßïõ êëåéäéþí ôïõ TCFS\n" + +#: src/userdel.c:354 +#, c-format +msgid "%s: cannot open TCFS key file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò ôïõ áñ÷åßïõ êëåéäéþí ôïõ TCFS\n" + +#: src/userdel.c:363 +#, c-format +msgid "%s: cannot open group file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò áñ÷åßïõ ïìÜäùí\n" + +#: src/userdel.c:373 +#, c-format +msgid "%s: cannot open shadow group file\n" +msgstr "%s: áäõíáìßá áíïßãìáôïò áñ÷åßïõ óêéùäþí óõíèçìáôéêþí ïìÜäùí\n" + +#: src/userdel.c:404 src/userdel.c:419 +#, c-format +msgid "%s: error deleting authentication\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ åîáêñßâùóçò\n" + +#: src/userdel.c:428 +#, c-format +msgid "%s: error deleting password entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ êáôá÷þñçóçò óôï áñ÷åßï óõíèçìáôéêþí\n" + +#: src/userdel.c:431 +#, c-format +msgid "%s: error deleting shadow password entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#: src/userdel.c:440 +#, c-format +msgid "%s: error deleting TCFS entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ êáôá÷þñçóçò ôïõ TCFS\n" + +#: src/userdel.c:453 +#, c-format +msgid "%s: error deleting password dbm entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ êáôá÷þñçóçò óôï dbm áñ÷åßï óõíèçìáôéêþí\n" + +#: src/userdel.c:472 +#, c-format +msgid "%s: error deleting shadow passwd dbm entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ êáôá÷þñçóçò óôï dbm áñ÷åßï óêéùäþí " +"óõíèçìáôéêþí\n" + +#: src/userdel.c:513 +#, c-format +msgid "%s: user %s is currently logged in\n" +msgstr "%s: Ï ÷ñÞóôçò %s âñßóêåôáé óôï óýóôçìá\n" + +#: src/userdel.c:630 +#, c-format +msgid "%s: warning: %s not owned by %s, not removing\n" +msgstr "%s: ðñïåéäïðïßçóç: Ôï %s äåí áíÞêåé óôïí %s, äåí äéáãñÜöåôáé\n" + +#: src/userdel.c:636 +#, c-format +msgid "%s: warning: can't remove " +msgstr "%s: ðñïåéäïðïßçóç: áäõíáìßá äéáãñáöÞò " + +#: src/userdel.c:711 src/usermod.c:968 +#, c-format +msgid "%s: user %s does not exist\n" +msgstr "%s: Ï ÷ñÞóôçò %s äåí õðÜñ÷åé\n" + +#: src/userdel.c:725 src/usermod.c:984 +#, c-format +msgid "%s: user %s is a NIS user\n" +msgstr "%s: Ï ÷ñÞóôçò %s åßíáé NIS ÷ñÞóôçò\n" + +#: src/userdel.c:762 +#, c-format +msgid "%s: %s not owned by %s, not removing\n" +msgstr "%s: Ôï %s äåí áíÞêåé óôïí %s, äåí áöáéñåßôáé\n" + +#: src/userdel.c:785 +#, c-format +msgid "%s: not removing directory %s (would remove home of user %s)\n" +msgstr "" +"%s: Äåí äéáãñÜöåôáé ï êáôÜëïãïò %s (èá áöáéñïýóå ôïí ìçôñéêü êáôÜëïãï ôïõ " +"÷ñÞóôç %s)\n" + +#: src/userdel.c:798 +#, c-format +msgid "%s: error removing directory %s\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ ôïõ êáôáëüãïõ %s\n" + +#: src/usermod.c:316 +msgid "\t\t[-d home [-m]] [-s shell] [-c comment] [-l new_name]\n" +msgstr "" +"\t\t[-d ìçôñéêüò_êáôÜëïãïò [-m]] [-s öëïéüò] [-c ó÷üëéï]\n" +"\t\t[-l íÝï_üíïìá]\n" + +#: src/usermod.c:322 +msgid "[-A {DEFAULT|program},... ] " +msgstr "[-A {DEFAULT|ðñüãñáììá},... ] " + +#: src/usermod.c:478 +#, c-format +msgid "%s: out of memory in update_group\n" +msgstr "%s: äåí õðÜñ÷åé åëåýèåñç ìíÞìç óôï update_group\n" + +#: src/usermod.c:601 +#, c-format +msgid "%s: out of memory in update_gshadow\n" +msgstr "%s: óôï update_gshadow\n" + +#: src/usermod.c:1139 +#, c-format +msgid "%s: no flags given\n" +msgstr "%s: Äåí äüèçêáí åíäåßîåéò\n" + +#: src/usermod.c:1146 +#, c-format +msgid "%s: shadow passwords required for -e and -f\n" +msgstr "%s: óêéþäç óõíèçìáôéêÜ áðáéôïýíôáé ãéá ôï -e êáé -f\n" + +#: src/usermod.c:1167 +#, c-format +msgid "%s: uid %ld is not unique\n" +msgstr "%s: Ôï uid %ld äåí åßíáé ìïíáäéêü\n" + +#: src/usermod.c:1315 +#, c-format +msgid "%s: error deleting authentication method\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí äéáãñáöÞ ìåèüäïõ åîáêñßâùóçò\n" + +#: src/usermod.c:1335 +#, c-format +msgid "%s: error changing authentication method\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí áëëáãÞ ìåèüäïõ åîáêñßâùóçò\n" + +#: src/usermod.c:1352 +#, c-format +msgid "%s: error changing password entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí áëëáãÞ êáôá÷þñçóçò óõíèçìáôéêïý\n" + +#: src/usermod.c:1358 +#, c-format +msgid "%s: error removing password entry\n" +msgstr "%s: ÓöÜëìá êáôÜ ôçí áöáßñåóç êáôá÷þñçóçò óôï áñ÷åßï óõíèçìáôéêþí\n" + +#: src/usermod.c:1366 +#, c-format +msgid "%s: error adding password dbm entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí ðñïóèÞêç íÝáò êáôá÷þñçóçò óôï dbm áñ÷åßï óõíèçìáôéêþí\n" + +#: src/usermod.c:1373 +#, c-format +msgid "%s: error removing passwd dbm entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áöáßñåóç êáôá÷þñçóçò áðü ôï dbm áñ÷åßï óõíèçìáôéêþí\n" + +#: src/usermod.c:1390 +#, c-format +msgid "%s: error removing shadow password entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áöáßñåóç êáôá÷þñçóçò óôï áñ÷åßï óêéùäþí óõíèçìáôéêþí\n" + +#: src/usermod.c:1405 +#, c-format +msgid "%s: error removing shadow passwd dbm entry\n" +msgstr "" +"%s: ÓöÜëìá êáôÜ ôçí áöáßñåóç êáôá÷þñçóçò óôï dbm áñ÷åßï óêéùäþí " +"óõíèçìáôéêþí\n" + +#: src/usermod.c:1436 +#, c-format +msgid "%s: directory %s exists\n" +msgstr "%s: ï êáôÜëïãïò %s õðÜñ÷åé\n" + +#: src/usermod.c:1443 +#, c-format +msgid "%s: can't create %s\n" +msgstr "%s: áäõíáìßá äçìéïõñãßáò ôïõ %s\n" + +#: src/usermod.c:1449 +#, c-format +msgid "%s: can't chown %s\n" +msgstr "%s: Áäõíáìßá áëëáãÞò éäéïêôÞôç(chown) ôïõ %s\n" + +#: src/usermod.c:1465 +#, c-format +msgid "%s: cannot rename directory %s to %s\n" +msgstr "%s: áäõíáìßá ìåôïíïìáóßáò ôïõ êáôáëüãïõ %s óå %s\n" + +#. better leave it alone +#: src/usermod.c:1562 +#, c-format +msgid "%s: warning: %s not owned by %s\n" +msgstr "%s: ðñïåéäïðïßçóç: Ôï %s äåí áíÞêåé óôïí %s\n" + +#: src/usermod.c:1568 +msgid "failed to change mailbox owner" +msgstr "áðïôõ÷ßá áëëáãÞò ôïõ éäéïêôÞôç ôïõ ãñáììáôïêéâùôßïõ" + +#: src/usermod.c:1575 +msgid "failed to rename mailbox" +msgstr "áðïôõ÷ßá ìåôïíïìáóßáò ãñáììáôïêéâùôßïõ" + +#: src/vipw.c:103 +#, c-format +msgid "" +"\n" +"%s: %s is unchanged\n" +msgstr "" +"\n" +"%s: Ôï %s äåí Üëëáîå\n" + +#: src/vipw.c:128 +#, fuzzy +msgid "Couldn't lock file" +msgstr "%s: áäõíáìßá îåêëåéäþìáôïò áñ÷åßïõ\n" + +#: src/vipw.c:135 +msgid "Couldn't make backup" +msgstr "" + +#: src/vipw.c:174 +#, c-format +msgid "%s: can't restore %s: %s (your changes are in %s)\n" +msgstr "%s: áäõíáìßá åðáíáöïñÜò %s: %s (ïé áëëáãÝò åßíáé óôï %s)\n" + +#: src/vipw.c:213 +msgid "" +"Usage:\n" +"`vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n" +"`vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n" +msgstr "" +"×ñÞóç:\n" +"`vipw' óýíôáóåé ôï /etc/passwd `vipw -s' óõíôÜóóåé ôï /etc/shadow\n" +"`vigr' óýíôáóåé ôï /etc/group `vigr -s' óõíôÜóóåé ôï /etc/gshadow\n" + +#~ msgid "Incorrect password for %s.\n" +#~ msgstr "ÅóöáëìÝíï óõíèçìáôéêü ãéá ôïí %s.\n" + +#~ msgid "group not found\n" +#~ msgstr "ç ïìÜäá äåí âñÝèçêå\n" diff --git a/po/pl.gmo b/po/pl.gmo new file mode 100644 index 00000000..1b0d71d7 Binary files /dev/null and b/po/pl.gmo differ diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 00000000..6f9d4237 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,2383 @@ +# shadow.pot Polish translation. +# Copyright (C) 1999 Free Software Foundation, Inc. +# Arkadiusz Mi¶kiewicz , 1999. +# +msgid "" +msgstr "" +"Project-Id-Version: shadow-981228\n" +"POT-Creation-Date: 1999-07-09 20:02+0200\n" +"PO-Revision-Date: 1999-03-02 22:29+01:00\n" +"Last-Translator: Arkadiusz Mi¶kiewicz \n" +"Language-Team: PL \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso8859-2\n" +"Content-Transfer-Encoding: 8bit\n" + +#: libmisc/addgrps.c:60 +#, c-format +msgid "Warning: unknown group %s\n" +msgstr "Ostrze¿enie: nieznana grupa %s\n" + +#: libmisc/addgrps.c:71 +msgid "Warning: too many groups\n" +msgstr "Ostrze¿enie: zbyt wiele grup\n" + +#: libmisc/age.c:104 +msgid "Your password has expired." +msgstr "Twoje has³o straci³o wa¿no¶æ." + +#: libmisc/age.c:107 +msgid "Your password is inactive." +msgstr "Twoje has³o jest nieaktywne." + +#: libmisc/age.c:110 +msgid "Your login has expired." +msgstr "Twoje konto straci³o wa¿no¶æ." + +#: libmisc/age.c:127 +msgid " Contact the system administrator.\n" +msgstr " Skontaktuj siê z administratorem systemu.\n" + +#: libmisc/age.c:130 +msgid " Choose a new password.\n" +msgstr " Wybierz nowe has³o.\n" + +#: libmisc/age.c:228 +#, c-format +msgid "Your password will expire in %ld days.\n" +msgstr "Twoje has³o straci wa¿no¶æ w ci±gu %ld dni.\n" + +#: libmisc/age.c:230 +msgid "Your password will expire tomorrow.\n" +msgstr "Jutro twoje has³o straci wa¿no¶æ.\n" + +#: libmisc/age.c:232 +msgid "Your password will expire today.\n" +msgstr "Dzi¶ twoje has³o straci wa¿no¶æ.\n" + +#: libmisc/chowntty.c:110 +#, c-format +msgid "Unable to change tty %s" +msgstr "Nie mo¿na zmieniæ tty %s" + +#: libmisc/env.c:160 +msgid "Environment overflow\n" +msgstr "Przepe³nienie ¶rodowiska\n" + +#: libmisc/env.c:200 +#, c-format +msgid "You may not change $%s\n" +msgstr "Nie mo¿esz zmieniaæ $%s\n" + +#: libmisc/failure.c:238 +#, c-format +msgid "%d %s since last login. Last was %s on %s.\n" +msgstr "" +"%d %s od ostatniego logowania. Ostatnie logowanie: dnia %s na terminalu " +"%s.\n" + +#: libmisc/failure.c:239 +msgid "failures" +msgstr "niepowodzenia" + +#: libmisc/failure.c:239 +msgid "failure" +msgstr "niepowodzenie" + +#: libmisc/limits.c:365 +msgid "Too many logins.\n" +msgstr "Zbyt wiele otwartych sesji.\n" + +#: libmisc/login_desrpc.c:63 +#, c-format +msgid "Password does not decrypt secret key for %s.\n" +msgstr "Tym has³em nie mo¿na zdeszyfrowaæ tajnego klucza dla %s.\n" + +#: libmisc/login_desrpc.c:69 +#, c-format +msgid "Could not set %s's secret key: is the keyserv daemon running?\n" +msgstr "Nie mogê ustawiæ tajnego klucza dla %s: czy serwer kluczy dzia³a?\n" + +#: libmisc/mail.c:62 libmisc/mail.c:77 +msgid "You have new mail." +msgstr "Masz now± pocztê." + +#: libmisc/mail.c:73 +msgid "No mail." +msgstr "Nie masz poczty." + +#: libmisc/mail.c:75 +msgid "You have mail." +msgstr "Masz pocztê." + +#: libmisc/obscure.c:281 src/passwd.c:311 +#, c-format +msgid "Bad password: %s. " +msgstr "Z³e has³o: %s. " + +#: libmisc/pam_pass.c:42 +#, c-format +msgid "passwd: pam_start() failed, error %d\n" +msgstr "passwd: pam_start() nie powiod³o siê, b³±d %d\n" + +#: libmisc/pam_pass.c:49 +#, c-format +msgid "passwd: %s\n" +msgstr "passwd: %s\n" + +#: libmisc/setupenv.c:205 +#, c-format +msgid "Unable to cd to \"%s\"\n" +msgstr "Nie mogê zmieniæ katalogu na \"%s\"\n" + +#: libmisc/setupenv.c:213 +msgid "No directory, logging in with HOME=/" +msgstr "Brak katalogu, logujê z HOME=/" + +#: libmisc/shell.c:78 +#, c-format +msgid "Executing shell %s\n" +msgstr "Uruchamiam pow³okê %s\n" + +#. +#. * Obviously something is really wrong - I can't figure out +#. * how to execute this stupid shell, so I might as well give +#. * up in disgust ... +#. +#: libmisc/shell.c:122 +#, c-format +msgid "Cannot execute %s" +msgstr "Nie mogê uruchomiæ %s" + +#: libmisc/suauth.c:99 +msgid "Access to su to that account DENIED.\n" +msgstr "Dostêp do polecenia su z tego konta ZABRONIONY.\n" + +#: libmisc/suauth.c:106 +msgid "Password authentication bypassed.\n" +msgstr "Uwierzytelnianie na podstawie has³a pominiête.\n" + +#: libmisc/suauth.c:113 +msgid "Please enter your OWN password as authentication.\n" +msgstr "Proszê wpisz swoje W£ASNE has³o jako has³o uwierzytelniaj±ce.\n" + +#: libmisc/sub.c:61 +#, c-format +msgid "Invalid root directory \"%s\"\n" +msgstr "Nieprawid³owy katalog g³ówny \"%s\"\n" + +#: libmisc/sub.c:73 +#, c-format +msgid "Can't change root directory to \"%s\"\n" +msgstr "Nie mogê zmieniæ g³ównego katalogu na \"%s\"\n" + +#: libmisc/xmalloc.c:28 +#, c-format +msgid "malloc(%d) failed\n" +msgstr "malloc(%d) nie powiod³o siê\n" + +#: lib/dialchk.c:71 +msgid "Dialup Password:" +msgstr "Has³o dostêpu modemowego:" + +#: lib/getdef.c:247 +msgid "Could not allocate space for config info.\n" +msgstr "Nie mogê przydzieliæ miejsca dla informacji o konfiguracji.\n" + +#. +#. * Item was never found. +#. +#: lib/getdef.c:301 +#, c-format +msgid "configuration error - unknown item '%s' (notify administrator)\n" +msgstr "" +"b³±d w konfiguracji - nieznana pozycja '%s' (powiadom administratora)\n" + +#: lib/getdef.c:388 +#, c-format +msgid "error - lookup '%s' failed\n" +msgstr "b³±d - wyszukiwanie '%s' niepowiod³o siê\n" + +#: lib/getdef.c:396 +#, c-format +msgid "%s not found\n" +msgstr "%s nie znaleziony\n" + +#: lib/pwauth.c:54 +msgid "Password: " +msgstr "Has³o: " + +#: lib/pwauth.c:56 +#, c-format +msgid "%s's Password:" +msgstr "Has³o u¿ytkownika %s:" + +#: lib/strerror.c:20 +#, c-format +msgid "Unknown error %d" +msgstr "Nieznany b³±d %d" + +#: src/chage.c:141 +#, c-format +msgid "" +"Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -W warn ]\n" +" [ -I inactive ] [ -E expire ] [ -d last_day ] user\n" +msgstr "" +"U¿ycie: %s [ -l ] [ -m min_dni ] [ -M maks_dni ] [ -W ostrze¿ ]\n" +" [ -I nieaktywne ] [ -E utrata_wa¿no¶ci ] [ -d ostatni_dzieñ ] u¿ytkownik\n" + +#: src/chage.c:143 +#, c-format +msgid "Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -d last_day ] user\n" +msgstr "" +"U¿ycie: %s [ -l ] [ -m min_dni ] [ -M maks_dni ] [ -d ostatni_dzieñ ] " +"u¿ytkownik\n" + +#: src/chage.c:178 +msgid "" +"Enter the new value, or press return for the default\n" +"\n" +msgstr "" +"Wpisz now± warto¶æ lub wci¶nij return by przyj±c warto¶æ domy¶ln±\n" +"\n" + +#: src/chage.c:181 +msgid "Minimum Password Age" +msgstr "Minimalny wiek has³a" + +#: src/chage.c:186 +msgid "Maximum Password Age" +msgstr "Maksymalny wiek has³a" + +#: src/chage.c:192 +msgid "Last Password Change (YYYY-MM-DD)" +msgstr "Ostatnia zmiana has³a (RRRR-MM-DD)" + +#: src/chage.c:201 +msgid "Password Expiration Warning" +msgstr "Ostrze¿enie o utracie wa¿no¶ci has³a" + +#: src/chage.c:206 +msgid "Password Inactive" +msgstr "Has³o nieaktywne" + +#: src/chage.c:212 +msgid "Account Expiration Date (YYYY-MM-DD)" +msgstr "Data utraty wa¿no¶ci konta (RRRR-MM-DD)" + +#. +#. * Start with the easy numbers - the number of days before the +#. * password can be changed, the number of days after which the +#. * password must be chaged, the number of days before the +#. * password expires that the user is told, and the number of +#. * days after the password expires that the account becomes +#. * unusable. +#. +#: src/chage.c:266 +#, c-format +msgid "Minimum:\t%ld\n" +msgstr "Minimum:\\t%ld\n" + +#: src/chage.c:267 +#, c-format +msgid "Maximum:\t%ld\n" +msgstr "Maksimim:\t%ld\n" + +#: src/chage.c:269 +#, c-format +msgid "Warning:\t%ld\n" +msgstr "Ostrze¿enie:\t%ld\n" + +#: src/chage.c:270 +#, c-format +msgid "Inactive:\t%ld\n" +msgstr "Nieaktywne:\t%ld\n" + +#. +#. * The "last change" date is either "Never" or the date the +#. * password was last modified. The date is the number of +#. * days since 1/1/1970. +#. +#: src/chage.c:279 +msgid "Last Change:\t\t" +msgstr "Ostatnia zmiana:\t\t" + +#: src/chage.c:281 src/chage.c:295 +msgid "Never\n" +msgstr "Nigdy\n" + +#. +#. * The password expiration date is determined from the last +#. * change date plus the number of days the password is valid +#. * for. +#. +#: src/chage.c:293 +msgid "Password Expires:\t" +msgstr "Has³o traci wa¿no¶æ:\t" + +#: src/chage.c:468 +#, c-format +msgid "%s: do not include \"l\" with other flags\n" +msgstr "%s: nie ³±cz \"l\" z innymi flagami\n" + +#: src/chage.c:480 src/chage.c:592 src/login.c:532 +#, c-format +msgid "%s: permission denied\n" +msgstr "%s: odmowa dostêpu\n" + +#: src/chage.c:492 src/chpasswd.c:122 +#, c-format +msgid "%s: can't lock password file\n" +msgstr "%s: nie mogê zablokowaæ pliku z has³ami\n" + +#: src/chage.c:498 src/chpasswd.c:126 +#, c-format +msgid "%s: can't open password file\n" +msgstr "%s: nie mogê otworzyæ pliku z has³ami\n" + +#: src/chage.c:505 +#, c-format +msgid "%s: unknown user: %s\n" +msgstr "%s: nieznany u¿ytkownik: %s\n" + +#: src/chage.c:524 +#, c-format +msgid "%s: can't lock shadow password file\n" +msgstr "%s: nie mogê zablokowaæ pliku z ukrytymi has³ami\n" + +#: src/chage.c:531 +#, c-format +msgid "%s: can't open shadow password file\n" +msgstr "%s: nie mogê otworzyæ pliku z ukrytymi has³ami\n" + +#: src/chage.c:613 +#, c-format +msgid "Changing the aging information for %s\n" +msgstr "Zmieniam informacjê o u¿ytkowniku %s\n" + +#: src/chage.c:615 +#, c-format +msgid "%s: error changing fields\n" +msgstr "%s: b³±d podczas zmieniania pól\n" + +#: src/chage.c:642 src/chage.c:705 src/pwunconv.c:184 +#, c-format +msgid "%s: can't update password file\n" +msgstr "%s: nie mogê zaktualizowaæ pliku z has³ami\n" + +#: src/chage.c:672 src/pwunconv.c:179 +#, c-format +msgid "%s: can't update shadow password file\n" +msgstr "%s: nie mogê zaktualizowaæ pliku z ukrytymi has³ami\n" + +#: src/chage.c:721 src/chage.c:736 src/chfn.c:572 src/chsh.c:411 +#: src/passwd.c:827 src/passwd.c:928 +msgid "Error updating the DBM password entry.\n" +msgstr "B³±d podczas aktualizacki bazy hase³ DBM.\n" + +#: src/chage.c:753 +#, c-format +msgid "%s: can't rewrite shadow password file\n" +msgstr "%s: nie mogê przepisaæ pliku z ukrytymi has³ami\n" + +#: src/chage.c:767 +#, c-format +msgid "%s: can't rewrite password file\n" +msgstr "%s: nie mogê przepisaæ pliku z has³ami\n" + +#: src/chage.c:816 +#, c-format +msgid "%s: no aging information present\n" +msgstr "%s: brak informacji\n" + +#: src/chfn.c:108 +#, c-format +msgid "" +"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ]\n" +"\t[ -h home_ph ] [ -o other ] [ user ]\n" +msgstr "" +"U¿ycie: %s [ -f imiê_nazwisko ] [ -r nr_pokoju ] [ -w tel_praca ]\n" +"\t[ -h tel_dom ] [ -o inne ] [ u¿ytkownik ]\n" + +#: src/chfn.c:112 +#, c-format +msgid "" +"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ] [ -h home_ph ]\n" +msgstr "" +"U¿ycie: %s [ -f imiê_nazwisko ] [ -r nr_pokoju ] [ -w tel_praca ] [ -h " +"tel_dom ]\n" + +#: src/chfn.c:164 src/chsh.c:120 +msgid "Enter the new value, or press return for the default\n" +msgstr "Wpisz now± warto¶æ lub wci¶nij return by przyj±c warto¶æ standardow±\n" + +#: src/chfn.c:167 +msgid "Full Name" +msgstr "Imiê i nazwisko" + +#: src/chfn.c:169 +#, c-format +msgid "\tFull Name: %s\n" +msgstr "\tImiê i nazwisko: %s\n" + +#: src/chfn.c:172 +msgid "Room Number" +msgstr "Numer pokoju" + +#: src/chfn.c:174 +#, c-format +msgid "\tRoom Number: %s\n" +msgstr "\tNumer pokoju: %s\n" + +#: src/chfn.c:177 +msgid "Work Phone" +msgstr "Telefon do pracy" + +#: src/chfn.c:179 +#, c-format +msgid "\tWork Phone: %s\n" +msgstr "\tTelefon do pracy: %s\n" + +#: src/chfn.c:182 +msgid "Home Phone" +msgstr "Telefon domowy" + +#: src/chfn.c:184 +#, c-format +msgid "\tHome Phone: %s\n" +msgstr "\tTelefon domowy: %s\n" + +#: src/chfn.c:187 +msgid "Other" +msgstr "Inne" + +#: src/chfn.c:300 src/chfn.c:308 src/chfn.c:316 src/chfn.c:324 src/chfn.c:332 +#: src/chfn.c:393 src/passwd.c:1228 +#, c-format +msgid "%s: Permission denied.\n" +msgstr "%s: Brak praw dostêpu.\n" + +#: src/chfn.c:353 src/chsh.c:226 src/passwd.c:1279 +#, c-format +msgid "%s: Unknown user %s\n" +msgstr "%s: Nieznany u¿ytkownik %s\n" + +#: src/chfn.c:359 src/chsh.c:234 src/passwd.c:1209 +#, c-format +msgid "%s: Cannot determine your user name.\n" +msgstr "%s: Nie mogê ustaliæ twojej nazwy u¿ytkownika.\n" + +#: src/chfn.c:375 src/chsh.c:252 +#, c-format +msgid "%s: cannot change user `%s' on NIS client.\n" +msgstr "%s: nie mogê zmieniæ u¿ytkownika `%s' na kliencie NIS.\n" + +#: src/chfn.c:380 src/chsh.c:259 +#, c-format +msgid "%s: `%s' is the NIS master for this client.\n" +msgstr "%s: `%s' jest nadrzêdnym serwerm NIS dla tego klienta.\n" + +#: src/chfn.c:455 +#, c-format +msgid "Changing the user information for %s\n" +msgstr "Zmieniam informacjê o u¿ytkowniku %s\n" + +#: src/chfn.c:464 +#, c-format +msgid "%s: invalid name: \"%s\"\n" +msgstr "%s: nieprawid³owa nazwa: \"%s\"\n" + +#: src/chfn.c:469 +#, c-format +msgid "%s: invalid room number: \"%s\"\n" +msgstr "%s: nieprawid³owy numer pokoju: \"%s\"\n" + +#: src/chfn.c:474 +#, c-format +msgid "%s: invalid work phone: \"%s\"\n" +msgstr "%s: nieprawid³owy numer telefonu do pracy: \"%s\"\n" + +#: src/chfn.c:479 +#, c-format +msgid "%s: invalid home phone: \"%s\"\n" +msgstr "%s: nieprawid³owy numer telefonu domowego: \"%s\"\n" + +#: src/chfn.c:484 +#, c-format +msgid "%s: \"%s\" contains illegal characters\n" +msgstr "%s: \"%s\" zawiera nieprawid³owe znaki\n" + +#: src/chfn.c:496 +#, c-format +msgid "%s: fields too long\n" +msgstr "%s: pola zbyt d³ugie\n" + +#: src/chfn.c:511 src/chsh.c:349 src/gpasswd.c:583 src/passwd.c:1390 +msgid "Cannot change ID to root.\n" +msgstr "Nie mogê zmieniæ ID na root.\n" + +#: src/chfn.c:524 src/chsh.c:363 src/passwd.c:737 src/passwd.c:882 +msgid "Cannot lock the password file; try again later.\n" +msgstr "Nie mogê zablokowaæ pliku z has³ami; spróbuj pó¼niej.\n" + +#: src/chfn.c:530 src/chsh.c:369 src/passwd.c:742 src/passwd.c:887 +msgid "Cannot open the password file.\n" +msgstr "Nie mogê otworzyæ pliku z has³ami.\n" + +#: src/chfn.c:547 src/chsh.c:384 src/passwd.c:748 src/usermod.c:1272 +#, c-format +msgid "%s: %s not found in /etc/passwd\n" +msgstr "%s: %s nie znaleziony w /etc/passwd\n" + +#: src/chfn.c:564 src/chsh.c:403 src/passwd.c:821 src/passwd.c:922 +#: src/passwd.c:962 +msgid "Error updating the password entry.\n" +msgstr "B³±d podczas aktualizacji wpisu do bazy hase³.\n" + +#: src/chfn.c:587 src/chsh.c:426 src/passwd.c:834 src/passwd.c:935 +msgid "Cannot commit password file changes.\n" +msgstr "Wprowadzenie zmian do pliku passwd jest niemo¿liwe.\n" + +#: src/chfn.c:594 src/chsh.c:433 +msgid "Cannot unlock the password file.\n" +msgstr "Nie mogê usun±c blokady z pliku z has³ami.\n" + +#: src/chpasswd.c:78 +#, c-format +msgid "usage: %s [-e]\n" +msgstr "u¿ycie: %s [-e]\n" + +#: src/chpasswd.c:134 src/pwconv.c:105 +#, c-format +msgid "%s: can't lock shadow file\n" +msgstr "%s: nie mogê zablokowaæ pliku z ukrytymi has³ami\n" + +#: src/chpasswd.c:139 src/gpasswd.c:609 src/pwconv.c:110 src/pwunconv.c:119 +#: src/pwunconv.c:124 +#, c-format +msgid "%s: can't open shadow file\n" +msgstr "%s: nie mogê otworzyæ pliku z ukrytymi has³ami\n" + +#: src/chpasswd.c:161 src/newusers.c:418 +#, c-format +msgid "%s: line %d: line too long\n" +msgstr "%s: linia %d: linia zbyt d³uga\n" + +#: src/chpasswd.c:181 +#, c-format +msgid "%s: line %d: missing new password\n" +msgstr "%s: linia %d: brakuje nowego has³a\n" + +#: src/chpasswd.c:197 +#, c-format +msgid "%s: line %d: unknown user %s\n" +msgstr "%s: linia %d: nieznany u¿ytkownik %s\n" + +#: src/chpasswd.c:249 +#, c-format +msgid "%s: line %d: cannot update password entry\n" +msgstr "%s: linia %d: nie mogê zaktualizowaæ wpisu do bazy hase³\n" + +#: src/chpasswd.c:265 src/newusers.c:538 +#, c-format +msgid "%s: error detected, changes ignored\n" +msgstr "%s: wykryto b³±d, zignorowano modyfikacje\n" + +#: src/chpasswd.c:276 +#, c-format +msgid "%s: error updating shadow file\n" +msgstr "%s: b³±d podczas aktualizacji pliku z ukrytymi has³ami\n" + +#: src/chpasswd.c:284 +#, c-format +msgid "%s: error updating password file\n" +msgstr "%s: b³±d podczas aktualizacji pliku z has³ami\n" + +#: src/chsh.c:106 +#, c-format +msgid "Usage: %s [ -s shell ] [ name ]\n" +msgstr "U¿ycie: %s [ -s pow³oka ] [ nazwa ]\n" + +#: src/chsh.c:121 +msgid "Login Shell" +msgstr "Pow³oka logowania" + +#: src/chsh.c:275 src/chsh.c:288 +#, c-format +msgid "You may not change the shell for %s.\n" +msgstr "Nie mo¿esz zmieniaæ pow³oki dla %s.\n" + +#: src/chsh.c:317 +#, c-format +msgid "Changing the login shell for %s\n" +msgstr "Zmieniam pow³okê logowania dla %s\n" + +#: src/chsh.c:329 +#, c-format +msgid "%s: Invalid entry: %s\n" +msgstr "%s: Nieprawid³owy wpis: %s\n" + +#: src/chsh.c:334 +#, c-format +msgid "%s is an invalid shell.\n" +msgstr "%s jest nieprawid³ow± pow³ok±.\n" + +#: src/dpasswd.c:71 +#, c-format +msgid "Usage: %s [ -(a|d) ] shell\n" +msgstr "U¿ycie: %s [ -(a|d) ] pow³oka\n" + +#: src/dpasswd.c:136 +msgid "Shell password:" +msgstr "Has³o pow³oki:" + +#: src/dpasswd.c:142 +msgid "re-enter Shell password:" +msgstr "Wpisz ponownie has³o pow³oki:" + +#: src/dpasswd.c:149 +#, c-format +msgid "%s: Passwords do not match, try again.\n" +msgstr "%s: Has³a nie pasuj±, spróbuj ponownie.\n" + +#: src/dpasswd.c:169 +#, c-format +msgid "%s: can't create %s" +msgstr "%s: nie mogê utworzyæ %s" + +#: src/dpasswd.c:174 +#, c-format +msgid "%s: can't open %s" +msgstr "%s: nie mogê otworzyæ %s" + +#: src/dpasswd.c:202 +#, c-format +msgid "%s: Shell %s not found.\n" +msgstr "%s: Pow³oka %s nie znaleziona.\n" + +#: src/expiry.c:85 +msgid "Usage: expiry { -f | -c }\n" +msgstr "U¿ycie: expiry { -f | -c }\n" + +#: src/expiry.c:138 +#, c-format +msgid "%s: WARNING! Must be set-UID root!\n" +msgstr "%s: OSTRZE¯ENIE! Program musi posiadaæ SUID root!\n" + +#: src/expiry.c:149 +#, c-format +msgid "%s: unknown user\n" +msgstr "%s: nieznany u¿ytkownik\n" + +#: src/faillog.c:80 +#, c-format +msgid "usage: %s [-a|-u user] [-m max] [-r] [-t days] [-l locksecs]\n" +msgstr "u¿ycie: %s [-a|-u u¿ytkownik] [-m maks] [-r] [-t dni] [-l bloksek]\n" + +#: src/faillog.c:135 src/lastlog.c:95 +#, c-format +msgid "Unknown User: %s\n" +msgstr "Nieznany u¿ytkownik: %s\n" + +#: src/faillog.c:216 +msgid "Username Failures Maximum Latest\n" +msgstr "U¿ytkownik Niepowodzenia Maksymalnie Ostatnio\n" + +#: src/faillog.c:233 +#, c-format +msgid " %s on %s" +msgstr " %s na %s" + +#: src/faillog.c:237 +#, c-format +msgid " [%lds left]" +msgstr " [%lds pozosta³o]" + +#: src/faillog.c:240 +#, c-format +msgid " [%lds lock]" +msgstr " [%lds blokada]" + +#: src/gpasswd.c:91 +#, c-format +msgid "usage: %s [-r|-R] group\n" +msgstr "u¿ycie: %s [-r|-R] grupa\n" + +#: src/gpasswd.c:92 +#, c-format +msgid " %s [-a user] group\n" +msgstr " %s [-a u¿ytkownik] grupa\n" + +#: src/gpasswd.c:93 +#, c-format +msgid " %s [-d user] group\n" +msgstr " %s [-d u¿ytkownik] grupa\n" + +#: src/gpasswd.c:95 +#, c-format +msgid " %s [-A user,...] [-M user,...] group\n" +msgstr " %s [-A u¿ytkownik,...] [-M u¿ytkownik,...] grupa\n" + +#: src/gpasswd.c:98 +#, c-format +msgid " %s [-M user,...] group\n" +msgstr " %s [-M u¿ytkownik,...] grupa\n" + +#: src/gpasswd.c:162 src/gpasswd.c:247 +#, c-format +msgid "%s: unknown user %s\n" +msgstr "%s: nieznany u¿ytkownik %s\n" + +#: src/gpasswd.c:174 +msgid "Permission denied.\n" +msgstr "Dostêp zabroniony.\n" + +#: src/gpasswd.c:259 +#, c-format +msgid "%s: shadow group passwords required for -A\n" +msgstr "%s: plik z ukrytymi has³ami grup wymagany dla -A\n" + +#: src/gpasswd.c:310 +msgid "Who are you?\n" +msgstr "Kim jeste¶?\n" + +#: src/gpasswd.c:330 src/newgrp.c:241 +#, c-format +msgid "unknown group: %s\n" +msgstr "nieznana grupa: %s\n" + +#: src/gpasswd.c:438 +#, c-format +msgid "Adding user %s to group %s\n" +msgstr "Dodajê nowego u¿ytkownika %s do grupy %s\n" + +#: src/gpasswd.c:455 +#, c-format +msgid "Removing user %s from group %s\n" +msgstr "Usuwam u¿ytkownika %s z grupy %s\n" + +#: src/gpasswd.c:468 +#, c-format +msgid "%s: unknown member %s\n" +msgstr "%s: nieznany cz³onek %s\n" + +#: src/gpasswd.c:515 +#, c-format +msgid "%s: Not a tty\n" +msgstr "%s: To nie tty\n" + +#. +#. * A new password is to be entered and it must be encrypted, +#. * etc. The password will be prompted for twice, and both +#. * entries must be identical. There is no need to validate +#. * the old password since the invoker is either the group +#. * owner, or root. +#. +#: src/gpasswd.c:537 +#, c-format +msgid "Changing the password for group %s\n" +msgstr "Zmieniam has³o dla grupy %s\n" + +#: src/gpasswd.c:540 +msgid "New Password:" +msgstr "Nowe has³o:" + +#: src/gpasswd.c:545 src/passwd.c:424 +msgid "Re-enter new password:" +msgstr "Wpisz has³o ponownie:" + +#: src/gpasswd.c:557 +msgid "They don't match; try again" +msgstr "Nie pasuj±; spróbuj ponownie" + +#: src/gpasswd.c:561 +#, c-format +msgid "%s: Try again later\n" +msgstr "%s: Spróbuj ponownie pó¼niej\n" + +#: src/gpasswd.c:591 +#, c-format +msgid "%s: can't get lock\n" +msgstr "%s: nie mogê zablokowaæ\n" + +#: src/gpasswd.c:597 +#, c-format +msgid "%s: can't get shadow lock\n" +msgstr "%s: nie mogê zablokowaæ pliku z ukrytymi has³ami\n" + +#: src/gpasswd.c:603 +#, c-format +msgid "%s: can't open file\n" +msgstr "%s: nie mogê otworzyæ pliku\n" + +#: src/gpasswd.c:615 +#, c-format +msgid "%s: can't update entry\n" +msgstr "%s: nie mogê zaktualizowaæ wpisu\n" + +#: src/gpasswd.c:621 +#, c-format +msgid "%s: can't update shadow entry\n" +msgstr "%s: nie mogê zaktualizowaæ wpisu do pliku z ukrytymi has³ami\n" + +#: src/gpasswd.c:627 +#, c-format +msgid "%s: can't re-write file\n" +msgstr "%s: nie mogê przepisaæ pliku\n" + +#: src/gpasswd.c:633 +#, c-format +msgid "%s: can't re-write shadow file\n" +msgstr "%s: nie mogê przepisaæ pliku z ukrytymi has³ami\n" + +#: src/gpasswd.c:641 +#, c-format +msgid "%s: can't unlock file\n" +msgstr "%s: nie mogê usun±c blokady z pliku\n" + +#: src/gpasswd.c:646 +#, c-format +msgid "%s: can't update DBM files\n" +msgstr "%s: nie mogê zaktualizwoaæ plików DBM\n" + +#: src/gpasswd.c:653 +#, c-format +msgid "%s: can't update DBM shadow files\n" +msgstr "%s: nie mogê zaktualizowaæ pliku DBM z ukrytymi has³ami\n" + +#: src/groupadd.c:106 +msgid "usage: groupadd [-g gid [-o]] group\n" +msgstr "u¿ycie: groupadd [-g gid [-o]] grupa\n" + +#: src/groupadd.c:174 src/groupadd.c:197 src/groupmod.c:184 src/groupmod.c:231 +#: src/useradd.c:932 src/usermod.c:513 src/usermod.c:649 +#, c-format +msgid "%s: error adding new group entry\n" +msgstr "%s: b³±d podczas dodawania nowej grupy\n" + +#: src/groupadd.c:184 src/groupadd.c:207 src/groupmod.c:200 src/useradd.c:943 +#: src/usermod.c:525 src/usermod.c:661 +#, c-format +msgid "%s: cannot add new dbm group entry\n" +msgstr "%s: nie mogê dodaæ nowego wpisu do bazy dbm grup\n" + +#: src/groupadd.c:259 src/useradd.c:997 +#, c-format +msgid "%s: name %s is not unique\n" +msgstr "%s: nazwa %s nie jest niepowtarzalny\n" + +#: src/groupadd.c:274 +#, c-format +msgid "%s: gid %ld is not unique\n" +msgstr "%s: gid %ld nie jest niepowtarzalny\n" + +#: src/groupadd.c:298 +#, c-format +msgid "%s: can't get unique gid\n" +msgstr "%s: nie mogê uzyskaæ niepowtarzalnego gid\n" + +#. +#. * All invalid group names land here. +#. +#: src/groupadd.c:322 src/groupmod.c:342 +#, c-format +msgid "%s: %s is a not a valid group name\n" +msgstr "%s: %s: nie jest prawid³ow± nazw± grupy\n" + +#: src/groupadd.c:351 src/groupmod.c:368 +#, c-format +msgid "%s: invalid group %s\n" +msgstr "%s: nieprawid³owa grupa %s\n" + +#: src/groupadd.c:368 src/useradd.c:1273 +#, c-format +msgid "%s: -O requires NAME=VALUE\n" +msgstr "%s: -O wymaga ZMIENNA=WARTO¦Æ\n" + +#: src/groupadd.c:413 src/groupdel.c:168 src/groupmod.c:404 src/useradd.c:1382 +#: src/userdel.c:273 src/usermod.c:537 +#, c-format +msgid "%s: cannot rewrite group file\n" +msgstr "%s: nie mogê przepisaæ pliku z grupami\n" + +#: src/groupadd.c:419 src/groupdel.c:174 src/groupmod.c:410 src/useradd.c:1390 +#: src/userdel.c:279 src/usermod.c:674 +#, c-format +msgid "%s: cannot rewrite shadow group file\n" +msgstr "%s: nie mogê przepisaæ pliku z ukrytymi grupami\n" + +#: src/groupadd.c:438 src/groupdel.c:193 src/groupmod.c:429 src/userdel.c:359 +#, c-format +msgid "%s: unable to lock group file\n" +msgstr "%s: nie mogê zablokowaæ pliku z grupami\n" + +#: src/groupadd.c:442 src/groupdel.c:197 src/groupmod.c:433 +#, c-format +msgid "%s: unable to open group file\n" +msgstr "%s: nie mogê otworzyæ pliku z grupami\n" + +#: src/groupadd.c:447 src/groupdel.c:202 src/groupmod.c:438 src/userdel.c:368 +#, c-format +msgid "%s: unable to lock shadow group file\n" +msgstr "%s: nie mogê zablokowaæ pliku z ukrytymi grupami\n" + +#: src/groupadd.c:452 src/groupdel.c:207 src/groupmod.c:443 +#, c-format +msgid "%s: unable to open shadow group file\n" +msgstr "%s: nie mogê otworzyæ pliku z ukrytymi grupami\n" + +#: src/groupadd.c:519 +#, c-format +msgid "%s: group %s exists\n" +msgstr "%s: grupa %s istnieje\n" + +#: src/groupdel.c:87 +msgid "usage: groupdel group\n" +msgstr "u¿ycie: groupdel grupa\n" + +#: src/groupdel.c:105 src/groupmod.c:188 src/groupmod.c:235 +#, c-format +msgid "%s: error removing group entry\n" +msgstr "%s: b³±d podczas usuwania grupy\n" + +#: src/groupdel.c:117 src/groupmod.c:207 +#, c-format +msgid "%s: error removing group dbm entry\n" +msgstr "%s: b³±d podczas usuwania wpisu dbm o grupie\n" + +#: src/groupdel.c:132 +#, c-format +msgid "%s: error removing shadow group entry\n" +msgstr "%s: b³±d podczas usuwania wpisu o ukrytej grupie\n" + +#: src/groupdel.c:145 src/groupmod.c:253 +#, c-format +msgid "%s: error removing shadow group dbm entry\n" +msgstr "%s: b³±d podczas usuwania wpisu dbm z pliku ukrytych grup\n" + +#. +#. * Can't remove the group. +#. +#: src/groupdel.c:249 +#, c-format +msgid "%s: cannot remove user's primary group.\n" +msgstr "%s: nie mogê usun±æ podstawowej grupy u¿ytkowników.\n" + +#: src/groupdel.c:306 src/groupmod.c:502 +#, c-format +msgid "%s: group %s does not exist\n" +msgstr "%s: grupa %s nie isnieje\n" + +#: src/groupdel.c:320 src/groupmod.c:518 +#, c-format +msgid "%s: group %s is a NIS group\n" +msgstr "%s: grupa %s jest grup± NIS\n" + +#: src/groupdel.c:326 src/groupmod.c:524 src/userdel.c:731 src/usermod.c:990 +#, c-format +msgid "%s: %s is the NIS master\n" +msgstr "%s: %s jest g³ównym serwerem NIS\n" + +#: src/groupmod.c:106 +msgid "usage: groupmod [-g gid [-o]] [-n name] group\n" +msgstr "u¿ycie: groupmod [-g gid [-o]] [-n nazwa] grupa\n" + +#: src/groupmod.c:166 +#, fuzzy, c-format +msgid "%s: %s not found in /etc/group\n" +msgstr "%s: %s nie znaleziony w /etc/passwd\n" + +#: src/groupmod.c:247 +#, c-format +msgid "%s: cannot add new dbm shadow group entry\n" +msgstr "%s: nie mogê dodaæ nowego wpisu dbm do pliku z ukrytymi grupami\n" + +#: src/groupmod.c:300 +#, c-format +msgid "%s: %ld is not a unique gid\n" +msgstr "%s: %ld nie jest niepowtarzalnym gid\n" + +#: src/groupmod.c:331 +#, c-format +msgid "%s: %s is not a unique name\n" +msgstr "%s: %s nie jest niepowtarzaln± nazw±\n" + +#: src/groups.c:63 +#, c-format +msgid "unknown user %s\n" +msgstr "nieznany u¿ytkownik %s\n" + +#: src/grpck.c:99 +#, c-format +msgid "Usage: %s [ -r ] [ group [ gshadow ] ]\n" +msgstr "U¿ycie: %s [ -r ] [ grupa [ gshadow ] ]\n" + +#: src/grpck.c:101 +#, c-format +msgid "Usage: %s [ -r ] [ group ]\n" +msgstr "U¿ycie: %s [ -r ] [ grupa ]\n" + +#: src/grpck.c:120 src/pwck.c:120 +msgid "No" +msgstr "Nie" + +#: src/grpck.c:235 src/grpck.c:243 src/pwck.c:217 src/pwck.c:226 +#, c-format +msgid "%s: cannot lock file %s\n" +msgstr "%s: nie mogê zablokowaæ pliku %s\n" + +#: src/grpck.c:258 src/grpck.c:266 src/mkpasswd.c:217 src/pwck.c:242 +#: src/pwck.c:251 +#, c-format +msgid "%s: cannot open file %s\n" +msgstr "%s: nie mogê otworzyæ pliku %s\n" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/grpck.c:299 +msgid "invalid group file entry\n" +msgstr "nieprawid³owy wpis do pliku grup\n" + +#: src/grpck.c:300 src/grpck.c:363 src/grpck.c:455 src/grpck.c:518 +#: src/grpck.c:535 src/pwck.c:287 src/pwck.c:349 src/pwck.c:456 src/pwck.c:518 +#: src/pwck.c:542 +#, c-format +msgid "delete line `%s'? " +msgstr "usun±c liniê `%s'? " + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/grpck.c:362 +msgid "duplicate group entry\n" +msgstr "duplikat wpisu grup\n" + +#: src/grpck.c:379 +#, c-format +msgid "invalid group name `%s'\n" +msgstr "nieprawid³owa nazwa grupy `%s'\n" + +#: src/grpck.c:389 +#, c-format +msgid "group %s: bad GID (%d)\n" +msgstr "grupa %s: z³y GID (%d)\n" + +#: src/grpck.c:415 +#, c-format +msgid "group %s: no user %s\n" +msgstr "grupa %s: nie ma u¿ytkownika %s\n" + +#: src/grpck.c:417 src/grpck.c:586 +#, c-format +msgid "delete member `%s'? " +msgstr "skasowaæ cz³onka `%s'? " + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/grpck.c:454 +msgid "invalid shadow group file entry\n" +msgstr "nieprawid³owy wpis do pliku z ukrytymi has³ami\n" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/grpck.c:517 +msgid "duplicate shadow group entry\n" +msgstr "duplikuj±cy siê wpis w pliku ukrytych grup\n" + +#: src/grpck.c:534 +msgid "no matching group file entry\n" +msgstr "brak pasuj±cego wpisu w pliku grup\n" + +#: src/grpck.c:554 +#, c-format +msgid "shadow group %s: no administrative user %s\n" +msgstr "ukryta grupa %s: brak u¿ytkownika administracyjnego %s\n" + +#: src/grpck.c:556 +#, c-format +msgid "delete administrative member `%s'? " +msgstr "usun±æ cz³onka administracyjnego `%s'? " + +#: src/grpck.c:584 +#, c-format +msgid "shadow group %s: no user %s\n" +msgstr "ukryta grupa %s: nie ma u¿ytkownika %s\n" + +#: src/grpck.c:611 src/grpck.c:617 src/pwck.c:573 src/pwck.c:581 +#, c-format +msgid "%s: cannot update file %s\n" +msgstr "%s: nie mogê zaktualizowaæ pliku %s\n" + +#: src/grpck.c:641 src/pwck.c:607 +#, c-format +msgid "%s: the files have been updated; run mkpasswd\n" +msgstr "%s: pliki zosta³y zaktualizowane; uruchom mkpasswd\n" + +#: src/grpck.c:642 src/grpck.c:646 src/pwck.c:608 src/pwck.c:612 +#, c-format +msgid "%s: no changes\n" +msgstr "%s: bez zmian\n" + +#: src/grpck.c:645 src/pwck.c:611 +#, c-format +msgid "%s: the files have been updated\n" +msgstr "%s: pliku zost³y zaktualizowane\n" + +#: src/grpconv.c:63 src/grpunconv.c:64 +#, c-format +msgid "%s: can't lock group file\n" +msgstr "%s: nie mogê zablokowaæ pliku z grupami\n" + +#: src/grpconv.c:68 src/grpunconv.c:69 +#, c-format +msgid "%s: can't open group file\n" +msgstr "%s: nie mogê otworzyæ pliku z grupami\n" + +#: src/grpconv.c:73 src/grpunconv.c:74 +#, c-format +msgid "%s: can't lock shadow group file\n" +msgstr "%s: nie mogê zablokowaæ pliku z przes³oniêtymi grupami\n" + +#: src/grpconv.c:78 src/grpunconv.c:79 +#, c-format +msgid "%s: can't open shadow group file\n" +msgstr "%s: nie mogê otworzyæ pliku z przes³oniêtymi grupami\n" + +#. +#. * This shouldn't happen (the entry exists) but... +#. +#: src/grpconv.c:94 +#, c-format +msgid "%s: can't remove shadow group %s\n" +msgstr "%s: nie mogê usun±æ ukrytej grupy %s\n" + +#: src/grpconv.c:135 src/pwconv.c:161 +#, c-format +msgid "%s: can't update shadow entry for %s\n" +msgstr "%s: nie mogê zaktualizowaæ wpisu ukrytej grupy dla %s\n" + +#: src/grpconv.c:144 src/grpunconv.c:95 +#, c-format +msgid "%s: can't update entry for group %s\n" +msgstr "%s: nie mogê zaktualizowaæ wpisu dla grupy %s\n" + +#: src/grpconv.c:151 src/grpunconv.c:103 +#, c-format +msgid "%s: can't update shadow group file\n" +msgstr "%s: nie mogê zaktualizowaæ pliku z ukrytymi grupami\n" + +#: src/grpconv.c:155 src/grpunconv.c:108 +#, c-format +msgid "%s: can't update group file\n" +msgstr "%s: nie mogê zaktualizowaæ pliku z grupami\n" + +#: src/grpconv.c:170 src/grpunconv.c:129 +#, c-format +msgid "%s: not configured for shadow group support.\n" +msgstr "%s: nie skonfigurowany dla wsparcia ukrytych grup.\n" + +#: src/grpunconv.c:113 +#, c-format +msgid "%s: can't delete shadow group file\n" +msgstr "%s: nie mogê skasowaæ pliku z ukrytymi grupami\n" + +#: src/id.c:57 +msgid "usage: id [ -a ]\n" +msgstr "u¿ycie: id [ -a ]\n" + +#: src/id.c:59 +msgid "usage: id\n" +msgstr "u¿ycie: id\n" + +#: src/id.c:119 +#, c-format +msgid "uid=%d(%s)" +msgstr "uid=%d(%s)" + +#: src/id.c:121 +#, c-format +msgid "uid=%d" +msgstr "uid=%d" + +#: src/id.c:125 +#, c-format +msgid " gid=%d(%s)" +msgstr " gid=%d(%s)" + +#: src/id.c:127 +#, c-format +msgid " gid=%d" +msgstr " gid=%d" + +#: src/id.c:137 +#, c-format +msgid " euid=%d(%s)" +msgstr " euid=%d(%s)" + +#: src/id.c:139 +#, c-format +msgid " euid=%d" +msgstr " euid=%d" + +#: src/id.c:144 +#, c-format +msgid " egid=%d(%s)" +msgstr " egid=%d(%s)" + +#: src/id.c:146 +#, c-format +msgid " egid=%d" +msgstr " egid=%d" + +#. +#. * Start off the group message. It will be of the format +#. * +#. * groups=###(aaa),###(aaa),###(aaa) +#. * +#. * where "###" is a numerical value and "aaa" is the +#. * corresponding name for each respective numerical value. +#. +#: src/id.c:167 +msgid " groups=" +msgstr " grupy=" + +#: src/lastlog.c:168 +msgid "Username Port From Latest\n" +msgstr "U¿ytkownik Port Z Ostatnio\n" + +#: src/lastlog.c:170 +msgid "Username Port Latest\n" +msgstr "U¿ytkownik Port Ostatnio\n" + +#: src/lastlog.c:184 +msgid "**Never logged in**" +msgstr "**Nigdy nie zalogowany**" + +#: src/login.c:199 +#, c-format +msgid "usage: %s [-p] [name]\n" +msgstr "u¿ycie: %s [-p] [nazwa]\n" + +#: src/login.c:202 +#, c-format +msgid " %s [-p] [-h host] [-f name]\n" +msgstr " %s [-p] [-h host] [-f nazwa]\n" + +#: src/login.c:204 +#, c-format +msgid " %s [-p] -r host\n" +msgstr " %s [-p] -r host\n" + +#: src/login.c:290 +msgid "Invalid login time\n" +msgstr "Nieprawid³owy czas logowania\n" + +#: src/login.c:345 +msgid "" +"\n" +"System closed for routine maintenance\n" +msgstr "" +"\n" +"System zamkniêty do rutynowej konserwacji.\n" + +#: src/login.c:355 +msgid "" +"\n" +"[Disconnect bypassed -- root login allowed.]\n" +msgstr "" +"\n" +"[Roz³±czenie pominiête -- zezwolenie na logowanie siê root-a.]\n" + +#: src/login.c:394 +#, c-format +msgid "" +"\n" +"Login timed out after %d seconds.\n" +msgstr "" +"\n" +"Limit czasu logowania przekroczony po %d sekundach.\n" + +#: src/login.c:695 +#, c-format +msgid " on `%.100s' from `%.200s'" +msgstr " na `%s.100s' z `%.200s'" + +#: src/login.c:697 +#, c-format +msgid " on `%.100s'" +msgstr " na `%.100s'" + +#: src/login.c:810 +#, c-format +msgid "" +"\n" +"%s login: " +msgstr "" +"\n" +"%s login: " + +#: src/login.c:812 +msgid "login: " +msgstr "login: " + +#: src/login.c:994 src/sulogin.c:239 +msgid "Login incorrect" +msgstr "Nieprawid³owe logowanie" + +#: src/login.c:1166 +msgid "Warning: login re-enabled after temporary lockout.\n" +msgstr "Ostrze¿enie: logowanie ponownie odblokowanie po czasowej blokadzie.\n" + +#: src/login.c:1176 +#, c-format +msgid "Last login: %s on %s" +msgstr "Ostatnie logowanie: %s na %s" + +#: src/login.c:1179 +#, c-format +msgid "Last login: %.19s on %s" +msgstr "Ostatnie logowanie: %s na %s" + +#: src/login.c:1184 +#, c-format +msgid " from %.*s" +msgstr " z %.*s" + +#: src/login.c:1249 +msgid "Starting rad_login\n" +msgstr "Startujê rad_login\n" + +#: src/mkpasswd.c:49 +#, c-format +msgid "%s: no DBM database on system - no action performed\n" +msgstr "" +"%s: nie ma bazy DBM na tym systemie - ¿adna akcja nie zosta³a podjêta\n" + +#: src/mkpasswd.c:246 src/mkpasswd.c:250 +#, c-format +msgid "%s: cannot overwrite file %s\n" +msgstr "%s: nie mogê nadpisaæ pliku %s\n" + +#: src/mkpasswd.c:264 +#, c-format +msgid "%s: cannot open DBM files for %s\n" +msgstr "%s: nie mogê otworzyæ plików DBM dla %s\n" + +#: src/mkpasswd.c:297 +#, c-format +msgid "%s: the beginning with " +msgstr "%s: rozpoczyna siê od " + +#: src/mkpasswd.c:322 +#, c-format +msgid "%s: error parsing line \"%s\"\n" +msgstr "%s: b³±d podczas przetwarzania lini \"%s\"\n" + +#: src/mkpasswd.c:327 src/mkpasswd.c:329 src/mkpasswd.c:331 src/mkpasswd.c:333 +msgid "adding record for name " +msgstr "dodajê rekord do nazwy " + +#: src/mkpasswd.c:337 src/mkpasswd.c:342 src/mkpasswd.c:346 src/mkpasswd.c:350 +#, c-format +msgid "%s: error adding record for " +msgstr "%s: b³±d podczas dodawania rekordu dla " + +#: src/mkpasswd.c:368 +#, c-format +msgid "added %d entries, longest was %d\n" +msgstr "dodano %d wpisów, najd³u¿szy by³ %d\n" + +#: src/mkpasswd.c:383 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n" +msgstr "U¿ycie: %s [ -vf ] [ -p|g|sp|sg ] plik\n" + +#: src/mkpasswd.c:385 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g|sp ] file\n" +msgstr "U¿ycie: %s [ -vf ] [ -p|g|sp ] plik\n" + +#: src/mkpasswd.c:388 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g ] file\n" +msgstr "U¿ycie: %s [ -vf ] [ -p|g ] plik\n" + +#: src/newgrp.c:67 +msgid "usage: newgrp [ - ] [ group ]\n" +msgstr "u¿ycie: newgrp [ - ] [ grupa ]\n" + +#: src/newgrp.c:69 +msgid "usage: sg group [ command ]\n" +msgstr "u¿ycie: sg grupa [ komenda ]\n" + +#: src/newgrp.c:122 +#, c-format +msgid "unknown uid: %d\n" +msgstr "nieznany uid: %d\n" + +#: src/newgrp.c:190 +#, c-format +msgid "unknown gid: %ld\n" +msgstr "nieznany gid: %ld\n" + +#: src/newgrp.c:236 +#, c-format +msgid "unknown gid: %d\n" +msgstr "nieznany gid: %d\n" + +#. +#. * get the password from her, and set the salt for +#. * the decryption from the group file. +#. +#: src/newgrp.c:291 +msgid "Password:" +msgstr "Has³o:" + +#: src/newgrp.c:309 src/newgrp.c:318 +msgid "Sorry.\n" +msgstr "Wybacz.\n" + +#: src/newgrp.c:350 +msgid "too many groups\n" +msgstr "zbyt wiele grup\n" + +#: src/newusers.c:79 +#, c-format +msgid "Usage: %s [ input ]\n" +msgstr "U¿ycie: %s [ wej¶cie ]\n" + +#: src/newusers.c:367 +#, c-format +msgid "%s: can't lock /etc/passwd.\n" +msgstr "%s: nie mogê zablokowaæ /etc/passwd.\n" + +#: src/newusers.c:378 +#, c-format +msgid "%s: can't lock files, try again later\n" +msgstr "%s: nie mogê zablokowaæ plików, spróbuj pó¼niej\n" + +#: src/newusers.c:393 +#, c-format +msgid "%s: can't open files\n" +msgstr "%s: nie mogê otworzyæ plików\n" + +#: src/newusers.c:438 +#, c-format +msgid "%s: line %d: invalid line\n" +msgstr "%s: linia %d: nieprawid³owa linia\n" + +#: src/newusers.c:456 +#, c-format +msgid "%s: line %d: can't create GID\n" +msgstr "%s: linia %d: nie mogê utworzyæ GID\n" + +#: src/newusers.c:472 +#, c-format +msgid "%s: line %d: can't create UID\n" +msgstr "%s: linia %d: nie mogê utworzyæ UID\n" + +#: src/newusers.c:484 +#, c-format +msgid "%s: line %d: cannot find user %s\n" +msgstr "%s: linia %d: nie mogê znale¶æ u¿ytkownika %s\n" + +#: src/newusers.c:492 +#, c-format +msgid "%s: line %d: can't update password\n" +msgstr "%s: linia %d: nie mogê zaktualizowaæ pliku z has³ami\n" + +#: src/newusers.c:509 +#, c-format +msgid "%s: line %d: mkdir failed\n" +msgstr "%s: linia %d: mkdir nie powiod³o siê\n" + +#: src/newusers.c:513 +#, c-format +msgid "%s: line %d: chown failed\n" +msgstr "%s: linia %d: chown nie powiod³o siê\n" + +#: src/newusers.c:522 +#, c-format +msgid "%s: line %d: can't update entry\n" +msgstr "%s: linia %d: nie mogê zaktualizowaæ wpisu\n" + +#: src/newusers.c:553 +#, c-format +msgid "%s: error updating files\n" +msgstr "%s: b³±d podczas aktualizowania plików\n" + +#: src/passwd.c:241 +#, c-format +msgid "usage: %s [ -f | -s ] [ name ]\n" +msgstr "u¿ycie: %s [ -f | -s ] [ nazwa ]\n" + +#: src/passwd.c:244 +#, c-format +msgid " %s [ -x max ] [ -n min ] [ -w warn ] [ -i inact ] name\n" +msgstr " %s [ -x maks ] [ -n min ] [ -w ostrz ] [ -i nieakty ] nazwa\n" + +#: src/passwd.c:247 +#, c-format +msgid " %s { -l | -u | -d | -S | -e } name\n" +msgstr " %s { -l | -u | -d | -S | -e } nazwa\n" + +#: src/passwd.c:349 +#, c-format +msgid "User %s has a TCFS key, his old password is required.\n" +msgstr "U¿ytkownik %s posiada klucz TCFS, jego stare has³o jest wymagane.\n" + +#: src/passwd.c:350 +msgid "You can use -t option to force the change.\n" +msgstr "Nie mo¿esz u¿ywaæ opcji -t by wymusiæ zmianê.\n" + +#: src/passwd.c:356 +msgid "Old password:" +msgstr "Stare has³o:" + +#: src/passwd.c:363 +#, c-format +msgid "Incorrect password for `%s'\n" +msgstr "Nieprawid³owe has³o `%s'\n" + +#: src/passwd.c:376 +#, c-format +msgid "Warning: user %s has a TCFS key.\n" +msgstr "Ostrze¿enie: u¿ytkownik %s posiada klucz TCFS.\n" + +#: src/passwd.c:394 +#, c-format +msgid "" +"Enter the new password (minimum of %d, maximum of %d characters)\n" +"Please use a combination of upper and lower case letters and numbers.\n" +msgstr "" +"Wpisz nowe has³o (minimum %d, maksimum %d znaków)\n" +"Proszê u¿yj kombinacji wielkich i ma³ych znaków oraz cyfr.\n" + +#: src/passwd.c:401 +msgid "New password:" +msgstr "Nowe has³o:" + +#: src/passwd.c:411 +msgid "Try again.\n" +msgstr "Spróbuj ponownie.\n" + +#: src/passwd.c:420 +msgid "" +"\n" +"Warning: weak password (enter it again to use it anyway).\n" +msgstr "" +"\n" +"Ostrze¿enie: s³abe has³o (jednak wpisz je ponowie je¶li chcesz go u¿yæ).\n" + +#: src/passwd.c:429 +msgid "They don't match; try again.\n" +msgstr "Nie pasuj±; spróbuj ponownie.\n" + +#: src/passwd.c:514 src/passwd.c:530 +#, c-format +msgid "The password for %s cannot be changed.\n" +msgstr "Has³o dla %s nie mo¿e byæ zmienione.\n" + +#: src/passwd.c:558 +#, c-format +msgid "Sorry, the password for %s cannot be changed yet.\n" +msgstr "Wybacz, has³o dla %s nie mo¿e byæ jeszcze zmienione.\n" + +#: src/passwd.c:695 +#, c-format +msgid "%s: out of memory\n" +msgstr "%s: brak pamiêci\n" + +#: src/passwd.c:847 +msgid "Cannot lock the TCFS key database; try again later\n" +msgstr "Nie mogê zablokowaæ bazy kluczy TCFS; spróbuj ponownie\n" + +#: src/passwd.c:853 +msgid "Cannot open the TCFS key database.\n" +msgstr "Nie mogê otworzyæ bazy kluczy TCFS.\n" + +#: src/passwd.c:859 +msgid "Error updating the TCFS key database.\n" +msgstr "B³±d podczas aktualizacji bazy kluczy TCFS.\n" + +#: src/passwd.c:864 +msgid "Cannot commit TCFS changes.\n" +msgstr "Nie mogê potwierdziæ zmian TCFS.\n" + +#: src/passwd.c:1071 +#, c-format +msgid "%s: Cannot execute %s" +msgstr "%s: Nie mogê wykonaæ %s" + +#: src/passwd.c:1178 +#, c-format +msgid "%s: repository %s not supported\n" +msgstr "%s: ropozytorium %s nie jest obs³ugiwane\n" + +#: src/passwd.c:1265 +#, c-format +msgid "%s: Permission denied\n" +msgstr "%s: Dostêp zabroniony\n" + +#: src/passwd.c:1289 +#, c-format +msgid "You may not change the password for %s.\n" +msgstr "Nie mo¿esz zmieniaæ has³a dla %s.\n" + +#: src/passwd.c:1354 +#, c-format +msgid "Changing password for %s\n" +msgstr "Zmieniam has³o dla %s\n" + +#: src/passwd.c:1358 +#, c-format +msgid "The password for %s is unchanged.\n" +msgstr "Has³o dla %s pozostaje niezmienione.\n" + +#: src/passwd.c:1414 +msgid "Password changed.\n" +msgstr "Has³o zmienione.\n" + +#: src/pwck.c:99 +#, c-format +msgid "Usage: %s [ -qr ] [ passwd [ shadow ] ]\n" +msgstr "U¿ycie: %s [ -qr ] [ has³o [ shadow ] ]\n" + +#: src/pwck.c:101 +#, c-format +msgid "Usage: %s [ -qr ] [ passwd ]\n" +msgstr "U¿ycie: %s [ -qr ] [ has³o ]\n" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/pwck.c:286 +msgid "invalid password file entry\n" +msgstr "nieprawid³owy wpis do pliku z has³ami\n" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/pwck.c:348 +msgid "duplicate password entry\n" +msgstr "duplikuj±cy siê wpis w pliku z has³ami\n" + +#: src/pwck.c:364 +#, c-format +msgid "invalid user name `%s'\n" +msgstr "nieprawid³owa nazwa u¿ytkownika `%s'\n" + +#: src/pwck.c:374 +#, c-format +msgid "user %s: bad UID (%d)\n" +msgstr "u¿ytkownik %s: z³y UID (%d)\n" + +#. +#. * No primary group, just give a warning +#. +#: src/pwck.c:389 +#, c-format +msgid "user %s: no group %d\n" +msgstr "u¿ytkownik %s: brak grupy %d\n" + +#. +#. * Home directory doesn't exist, give a warning +#. +#: src/pwck.c:404 +#, c-format +msgid "user %s: directory %s does not exist\n" +msgstr "u¿ytkownik %s: katalog %s nie istnieje\n" + +#. +#. * Login shell doesn't exist, give a warning +#. +#: src/pwck.c:419 +#, c-format +msgid "user %s: program %s does not exist\n" +msgstr "u¿ytkownik %s: program %s nie istnieje\n" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/pwck.c:455 +msgid "invalid shadow password file entry\n" +msgstr "nieprawid³owy wpis w pliku z has³ami\n" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/pwck.c:517 +msgid "duplicate shadow password entry\n" +msgstr "duplikuj±cy siê wpis w pliku z ukrytymi has³ami\n" + +#. +#. * Tell the user this entry has no matching +#. * /etc/passwd entry and ask them to delete it. +#. +#: src/pwck.c:541 +msgid "no matching password file entry\n" +msgstr "brak pasuj±cego wpisu w pliku z has³ami\n" + +#: src/pwck.c:558 +#, c-format +msgid "user %s: last password change in the future\n" +msgstr "u¿ytkownik %s: ostatnia zmiana has³a w przysz³o¶ci\n" + +#: src/pwconv.c:95 src/pwunconv.c:109 +#, c-format +msgid "%s: can't lock passwd file\n" +msgstr "%s: nie mogê zablokowaæ pliku z has³ami\n" + +#: src/pwconv.c:100 src/pwunconv.c:114 +#, c-format +msgid "%s: can't open passwd file\n" +msgstr "%s: nie mogê otworzyæ pliku z has³ami\n" + +#: src/pwconv.c:127 +#, c-format +msgid "%s: can't remove shadow entry for %s\n" +msgstr "%s: nie mogê usun±æ wpisu z pliku z ukrytymi has³ami dla %s\n" + +#: src/pwconv.c:170 +#, c-format +msgid "%s: can't update passwd entry for %s\n" +msgstr "%s: nie mogê zaktualizowaæ wpisu do pliku z has³ami dla %s\n" + +#: src/pwconv.c:177 +#, c-format +msgid "%s: can't update shadow file\n" +msgstr "%s: nie mogê zaktualizowaæ pliku z ukrytymi has³ami\n" + +#: src/pwconv.c:181 +#, c-format +msgid "%s: can't update passwd file\n" +msgstr "%s: nie mogê zaktualizowaæ pliku z has³ami\n" + +#: src/pwunconv.c:62 +#, c-format +msgid "%s: Shadow passwords are not configured.\n" +msgstr "%s: Przes³oniête has³a nie s± skonfigurowane.\n" + +#: src/pwunconv.c:172 +#, c-format +msgid "%s: can't update entry for user %s\n" +msgstr "%s: nie mogê zaktualizowaæ wpisu dla u¿ytkownika %s\n" + +#: src/pwunconv.c:189 +#, c-format +msgid "%s: can't delete shadow password file\n" +msgstr "%s: nie mogê skasowaæ pliku z ukrytymi has³ami\n" + +#: src/su.c:145 +msgid "Sorry." +msgstr "Wybacz." + +#: src/su.c:227 +#, c-format +msgid "%s: must be run from a terminal\n" +msgstr "%s: musisz uruchamiaæ z terminala\n" + +#: src/su.c:319 +#, c-format +msgid "%s: pam_start: error %d\n" +msgstr "%s: pam_start: b³±d %d\n" + +#: src/su.c:345 +#, c-format +msgid "Unknown id: %s\n" +msgstr "Nieznany id: %s\n" + +#. access denied (-1) or unexpected value +#: src/su.c:380 src/su.c:395 +#, c-format +msgid "You are not authorized to su %s\n" +msgstr "Nie masz autoryzacji by u¿ywaæ su %s\n" + +#. require own password +#: src/su.c:391 +msgid "(Enter your own password.)" +msgstr "(Wpisz swoje w³asne has³o.)" + +#: src/su.c:412 +#, c-format +msgid "%s: permission denied (shell).\n" +msgstr "%s: dostêp zabroniony (pow³oka).\n" + +#: src/su.c:436 +#, c-format +msgid "" +"%s: %s\n" +"(Ignored)\n" +msgstr "" +"%s: %s\n" +"(Zignorowano)\n" + +#: src/su.c:605 +msgid "No shell\n" +msgstr "Brak pow³oki\n" + +#. must be a password file! +#: src/sulogin.c:144 +msgid "No password file\n" +msgstr "Brak pliku z has³ami\n" + +#. +#. * Fail secure +#. +#: src/sulogin.c:186 +msgid "No password entry for 'root'\n" +msgstr "Brak wpisu do bazy hase³ dla 'root'\n" + +#. +#. * Here we prompt for the root password, or if no password is +#. * given we just exit. +#. +#. get a password for root +#: src/sulogin.c:200 +msgid "" +"\n" +"Type control-d to proceed with normal startup,\n" +"(or give root password for system maintenance):" +msgstr "" +"\n" +"Wpisz control-d by kontynuowaæ normalny start,\n" +"(lub podaj has³o root-a by przej¶æ do trybu utrzymania systemu):" + +#. make new environment active +#: src/sulogin.c:249 +msgid "Entering System Maintenance Mode\n" +msgstr "Wchodzê w tryb utrzymania systemu\n" + +#: src/useradd.c:244 +#, c-format +msgid "%s: rebuild the group database\n" +msgstr "%s: przebuduj bazê grup\n" + +#: src/useradd.c:251 +#, c-format +msgid "%s: rebuild the shadow group database\n" +msgstr "%s: przebuduj bazê przes³oniêtych hase³\n" + +#: src/useradd.c:288 src/usermod.c:941 +#, c-format +msgid "%s: invalid numeric argument `%s'\n" +msgstr "%s: nieprawid³owy argument numeryczny `%s'\n" + +#: src/useradd.c:344 +#, c-format +msgid "%s: unknown gid %s\n" +msgstr "%s: nieznany gid %s\n" + +#: src/useradd.c:351 src/useradd.c:643 src/useradd.c:1229 src/usermod.c:253 +#: src/usermod.c:1072 +#, c-format +msgid "%s: unknown group %s\n" +msgstr "%s: nieznana grupa %s\n" + +#: src/useradd.c:419 +#, c-format +msgid "group=%s,%ld basedir=%s skel=%s\n" +msgstr "grupa=%s,%ld kat_baz=%s skel=%s\n" + +#: src/useradd.c:422 +#, c-format +msgid "shell=%s " +msgstr "pow³oka=%s " + +#: src/useradd.c:424 +#, c-format +msgid "inactive=%ld expire=%s" +msgstr "nieaktywne=%ld wyga¶niêcie=%s" + +#: src/useradd.c:428 +#, c-format +msgid "GROUP=%ld\n" +msgstr "GRUPA=%ld\n" + +#: src/useradd.c:429 +#, c-format +msgid "HOME=%s\n" +msgstr "KAT_DOM=%s\n" + +#: src/useradd.c:431 +#, c-format +msgid "INACTIVE=%ld\n" +msgstr "NIEAKTYWNE=%ld\n" + +#: src/useradd.c:432 +#, c-format +msgid "EXPIRE=%s\n" +msgstr "WYGA¦NIÊCIE=%s\n" + +#: src/useradd.c:434 +#, c-format +msgid "SHELL=%s\n" +msgstr "POW£OKA=%s\n" + +#: src/useradd.c:435 +#, c-format +msgid "SKEL=%s\n" +msgstr "SKEL=%s\n" + +#: src/useradd.c:471 +#, c-format +msgid "%s: cannot create new defaults file\n" +msgstr "%s: nie mogê utworzyæ nowego pliku ze standardowymi ustawieniami\n" + +#: src/useradd.c:565 src/useradd.c:576 +#, c-format +msgid "%s: rename: %s" +msgstr "%s: zmiana nazwy: %s" + +#: src/useradd.c:663 src/usermod.c:273 +#, c-format +msgid "%s: group `%s' is a NIS group.\n" +msgstr "%s: grupa `%s' jest grup± NIS.\n" + +#: src/useradd.c:671 src/usermod.c:281 +#, c-format +msgid "%s: too many groups specified (max %d).\n" +msgstr "%s: podano zbyt wiele grup (maks %d).\n" + +#: src/useradd.c:703 src/usermod.c:313 +#, c-format +msgid "usage: %s\t[-u uid [-o]] [-g group] [-G group,...] \n" +msgstr "u¿ycie: %s\t[-u uid [-o]] [-g grupa] [-G grupa,...] \n" + +#: src/useradd.c:706 +msgid "\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n" +msgstr "\t\t[-d kat_dom] [-s pow³oka] [-c komentarz] [-m [-k wzór]]\n" + +#: src/useradd.c:709 src/usermod.c:319 +msgid "[-f inactive] [-e expire ] " +msgstr "[-f nieaktywne] [-e utrata_wa¿no¶ci ]" + +#: src/useradd.c:712 +msgid "[-A program] " +msgstr "[-A program] " + +#: src/useradd.c:714 src/usermod.c:324 +msgid "[-p passwd] name\n" +msgstr "[-p has³o] nazwa\n" + +#: src/useradd.c:716 +#, c-format +msgid " %s\t-D [-g group] [-b base] [-s shell]\n" +msgstr " %s\t-D [-g grupa] [-b baza] [-s pow³oka]\n" + +#: src/useradd.c:719 +msgid "\t\t[-f inactive] [-e expire ]\n" +msgstr "\t\t[-f nieaktywne] [-e utrata_wa¿no¶ci ]\n" + +#: src/useradd.c:816 src/usermod.c:446 +#, c-format +msgid "%s: error locking group file\n" +msgstr "%s: b³±d podczas blokowania pliku z grupami\n" + +#: src/useradd.c:820 src/usermod.c:451 +#, c-format +msgid "%s: error opening group file\n" +msgstr "%s: b³±d podczas otwierania pliku z grupami\n" + +#: src/useradd.c:825 src/usermod.c:558 +#, c-format +msgid "%s: error locking shadow group file\n" +msgstr "%s: b³±d podczas blokowania pliku z ukrytymi has³ami\n" + +#: src/useradd.c:830 src/usermod.c:564 +#, c-format +msgid "%s: error opening shadow group file\n" +msgstr "%s: b³±d podczas otwierania pliku z ukrytymi grupami\n" + +#: src/useradd.c:1002 +#, c-format +msgid "%s: uid %d is not unique\n" +msgstr "%s: uid %d nie jest niepowtarzalny\n" + +#: src/useradd.c:1032 +#, c-format +msgid "%s: can't get unique uid\n" +msgstr "%s: nie mogê uzyskaæ niepowtarzalnego uid\n" + +#: src/useradd.c:1140 src/useradd.c:1284 src/usermod.c:1020 src/usermod.c:1031 +#: src/usermod.c:1041 src/usermod.c:1087 src/usermod.c:1122 +#, c-format +msgid "%s: invalid field `%s'\n" +msgstr "%s: nieprawid³owe pole `%s'\n" + +#: src/useradd.c:1154 +#, c-format +msgid "%s: invalid base directory `%s'\n" +msgstr "%s: nieprawid³owy katalog bazowy `%s'\n" + +#: src/useradd.c:1164 +#, c-format +msgid "%s: invalid comment `%s'\n" +msgstr "%s: nieprawid³owy komentarz `%s'\n" + +#: src/useradd.c:1174 +#, c-format +msgid "%s: invalid home directory `%s'\n" +msgstr "%s: nieprawid³owy katalog domowy `%s'\n" + +#: src/useradd.c:1192 src/usermod.c:1054 +#, c-format +msgid "%s: invalid date `%s'\n" +msgstr "%s: nieprawid³owa data `%s'\n" + +#: src/useradd.c:1204 +#, c-format +msgid "%s: shadow passwords required for -e\n" +msgstr "%s: ukryte has³a wymagane dla -e\n" + +#: src/useradd.c:1219 +#, c-format +msgid "%s: shadow passwords required for -f\n" +msgstr "%s: ukryte has³a wymagane dla -f\n" + +#: src/useradd.c:1293 +#, c-format +msgid "%s: invalid shell `%s'\n" +msgstr "%s: nieprawid³owa pow³oka `%s'\n" + +#: src/useradd.c:1334 +#, c-format +msgid "%s: invalid user name `%s'\n" +msgstr "%s: nieprawid³owa nazwa u¿ytkownika `%s'\n" + +#: src/useradd.c:1370 src/userdel.c:262 src/usermod.c:1184 +#, c-format +msgid "%s: cannot rewrite password file\n" +msgstr "%s: nie mogê przepisaæ pliku z has³ami\n" + +#: src/useradd.c:1375 src/userdel.c:265 src/usermod.c:1189 +#, c-format +msgid "%s: cannot rewrite shadow password file\n" +msgstr "%s: nie mogê przepisaæ pliku z ukrytymi has³ami\n" + +#: src/useradd.c:1415 src/userdel.c:329 src/usermod.c:1224 +#, c-format +msgid "%s: unable to lock password file\n" +msgstr "%s: nie mogê zablokowaæ pliku z has³ami\n" + +#: src/useradd.c:1419 src/userdel.c:333 src/usermod.c:1228 +#, c-format +msgid "%s: unable to open password file\n" +msgstr "%s: nie mogê otworzyæ pliku z has³ami\n" + +#: src/useradd.c:1425 src/userdel.c:338 src/usermod.c:1233 +#, c-format +msgid "%s: cannot lock shadow password file\n" +msgstr "%s: nie mogê zablokowaæ pliku z ukrytymi has³ami\n" + +#: src/useradd.c:1431 src/userdel.c:343 src/usermod.c:1238 +#, c-format +msgid "%s: cannot open shadow password file\n" +msgstr "%s: nie mogê otworzyæ pliku z ukrytymi has³ami\n" + +#: src/useradd.c:1530 src/usermod.c:1325 +#, c-format +msgid "%s: error adding authentication method\n" +msgstr "%s: b³±d podczas dodawania metody uwierzytelniania\n" + +#: src/useradd.c:1553 +#, c-format +msgid "%s: error adding new password entry\n" +msgstr "%s: b³±d podczas dodawania nowego wpisu do pliku z has³ami\n" + +#: src/useradd.c:1568 +#, c-format +msgid "%s: error updating password dbm entry\n" +msgstr "%s: b³±d podczas aktualizacji wpisu dbm do pliku z has³ami\n" + +#: src/useradd.c:1584 src/usermod.c:1384 +#, c-format +msgid "%s: error adding new shadow password entry\n" +msgstr "%s: b³±d podczas dodawania nowego wpisu do pliku z ukrytymi has³ami\n" + +#: src/useradd.c:1600 src/usermod.c:1399 +#, c-format +msgid "%s: error updating shadow passwd dbm entry\n" +msgstr "%s: b³±d podczas aktualizacji wpisu dbm do pliku z ukrytymi has³ami\n" + +#: src/useradd.c:1632 +#, c-format +msgid "%s: cannot create directory %s\n" +msgstr "%s: nie mogê utworzyæ katalogu %s\n" + +#: src/useradd.c:1709 src/usermod.c:1162 +#, c-format +msgid "%s: user %s exists\n" +msgstr "%s: u¿ytkownik %s istnieje\n" + +#: src/useradd.c:1739 +#, c-format +msgid "%s: warning: CREATE_HOME not supported, please use -m instead.\n" +msgstr "" + +#: src/userdel.c:128 +#, c-format +msgid "usage: %s [-r] name\n" +msgstr "u¿ycie: %s [-r] nazwa\n" + +#: src/userdel.c:175 src/userdel.c:230 +#, c-format +msgid "%s: error updating group entry\n" +msgstr "%s: b³±d podczas aktualizacji wpisu grupy\n" + +#: src/userdel.c:185 src/userdel.c:239 +#, c-format +msgid "%s: cannot update dbm group entry\n" +msgstr "%s: nie mogê zaktualizowaæ wpisu dbm do pliku z grupami\n" + +#: src/userdel.c:270 +#, c-format +msgid "%s: cannot rewrite TCFS key file\n" +msgstr "%s: nie mogê przepisaæ pliku klucza TCFS\n" + +#: src/userdel.c:350 +#, c-format +msgid "%s: cannot lock TCFS key file\n" +msgstr "%s: nie mogê zablokowaæ pliku klucza TCFS\n" + +#: src/userdel.c:354 +#, c-format +msgid "%s: cannot open TCFS key file\n" +msgstr "%s: nie mogê otworzyæ pliku klucza TCFS\n" + +#: src/userdel.c:363 +#, c-format +msgid "%s: cannot open group file\n" +msgstr "%s: nie mogê otworzyæ pliku z grupami\n" + +#: src/userdel.c:373 +#, c-format +msgid "%s: cannot open shadow group file\n" +msgstr "%s: nie mogê otworzyæ pliku z przes³oniêtymi grupami\n" + +#: src/userdel.c:404 src/userdel.c:419 +#, c-format +msgid "%s: error deleting authentication\n" +msgstr "%s: b³±d podczas usuwania informacji uwierzytelniaj±cej\n" + +#: src/userdel.c:428 +#, c-format +msgid "%s: error deleting password entry\n" +msgstr "%s: b³±d podczas usuwania wpisu do pliku z has³ami\n" + +#: src/userdel.c:431 +#, c-format +msgid "%s: error deleting shadow password entry\n" +msgstr "%s: b³±d podczas usuwania wpisu do pliku z ukrytymi has³ami\n" + +#: src/userdel.c:440 +#, c-format +msgid "%s: error deleting TCFS entry\n" +msgstr "%s: b³±d podczas usuwania wpisu TCFS\n" + +#: src/userdel.c:453 +#, c-format +msgid "%s: error deleting password dbm entry\n" +msgstr "%s: b³±d podczas usuwania wpisu dbm do pliku z has³ami\n" + +#: src/userdel.c:472 +#, c-format +msgid "%s: error deleting shadow passwd dbm entry\n" +msgstr "%s: b³±d podczas usuwania wpisy dbm z pliku z ukrytymi has³ami\n" + +#: src/userdel.c:513 +#, c-format +msgid "%s: user %s is currently logged in\n" +msgstr "%s: u¿ytkownik %s jest aktualnie zalogowany\n" + +#: src/userdel.c:630 +#, c-format +msgid "%s: warning: %s not owned by %s, not removing\n" +msgstr "%s: ostrze¿enie: w³a¶cicielem %s nie jest %s, nie usuwam\n" + +#: src/userdel.c:636 +#, c-format +msgid "%s: warning: can't remove " +msgstr "%s: ostrze¿enie: nie mogê usun±æ " + +#: src/userdel.c:711 src/usermod.c:968 +#, c-format +msgid "%s: user %s does not exist\n" +msgstr "%s: u¿ytkownik %s nie istnieje\n" + +#: src/userdel.c:725 src/usermod.c:984 +#, c-format +msgid "%s: user %s is a NIS user\n" +msgstr "%s: u¿ytkownik %s jest u¿ytkownikiem NIS\n" + +#: src/userdel.c:762 +#, c-format +msgid "%s: %s not owned by %s, not removing\n" +msgstr "%s: w³a¶cicielem %s nie jest %s, nie usuwam\n" + +#: src/userdel.c:785 +#, c-format +msgid "%s: not removing directory %s (would remove home of user %s)\n" +msgstr "%s: nie usuwam katalogu %s (would remove home of user %s)\n" + +#: src/userdel.c:798 +#, c-format +msgid "%s: error removing directory %s\n" +msgstr "%s: b³±d podczas usuwania katalogu %s\n" + +#: src/usermod.c:316 +msgid "\t\t[-d home [-m]] [-s shell] [-c comment] [-l new_name]\n" +msgstr "\t\t[-d kat_dom [-m]] [-s pow³oka] [-c komentarz] [-l nowa_nazwa]\n" + +#: src/usermod.c:322 +msgid "[-A {DEFAULT|program},... ] " +msgstr "[-A {DEFAULT|program},... ] " + +#: src/usermod.c:478 +#, c-format +msgid "%s: out of memory in update_group\n" +msgstr "%s: zabrak³o pamiêci w pdate_group\n" + +#: src/usermod.c:601 +#, c-format +msgid "%s: out of memory in update_gshadow\n" +msgstr "%s: zabrak³o pamiêci w update_gshadow\n" + +#: src/usermod.c:1139 +#, c-format +msgid "%s: no flags given\n" +msgstr "%s: nie podano flag\n" + +#: src/usermod.c:1146 +#, c-format +msgid "%s: shadow passwords required for -e and -f\n" +msgstr "%s: ukryte has³a wymagane dla -e i -f\n" + +#: src/usermod.c:1167 +#, c-format +msgid "%s: uid %ld is not unique\n" +msgstr "%s: uid %ld nie jest niepowtarzalny\n" + +#: src/usermod.c:1315 +#, c-format +msgid "%s: error deleting authentication method\n" +msgstr "%s: b³±d podczas usuwania metody uwierzytelniania\n" + +#: src/usermod.c:1335 +#, c-format +msgid "%s: error changing authentication method\n" +msgstr "%s: b³±d podczas zmiany metody uwierzytelniania\n" + +#: src/usermod.c:1352 +#, c-format +msgid "%s: error changing password entry\n" +msgstr "%s: b³±d podczas zmiany wpisu w pliku z has³ami\n" + +#: src/usermod.c:1358 +#, c-format +msgid "%s: error removing password entry\n" +msgstr "%s: b³±d podczas usuwania wpisu z pliku z has³ami\n" + +#: src/usermod.c:1366 +#, c-format +msgid "%s: error adding password dbm entry\n" +msgstr "%s: b³±d podczas dodawania wpisu dbm do pliku z has³ami\n" + +#: src/usermod.c:1373 +#, c-format +msgid "%s: error removing passwd dbm entry\n" +msgstr "%s: b³±d podczas usuwania wpisu dbm z pliku z has³ami\n" + +#: src/usermod.c:1390 +#, c-format +msgid "%s: error removing shadow password entry\n" +msgstr "%s: b³±d podczas usuwania wpisu z pliku z ukrytymi has³ami\n" + +#: src/usermod.c:1405 +#, c-format +msgid "%s: error removing shadow passwd dbm entry\n" +msgstr "%s: b³±d podczas usuwania wpisu dbm z pliku z ukrytymi has³ami\n" + +#: src/usermod.c:1436 +#, c-format +msgid "%s: directory %s exists\n" +msgstr "%s: katalog %s isnieje\n" + +#: src/usermod.c:1443 +#, c-format +msgid "%s: can't create %s\n" +msgstr "%s: nie mogê utworzyæ %s\n" + +#: src/usermod.c:1449 +#, c-format +msgid "%s: can't chown %s\n" +msgstr "%s: nie mogê zmieniæ w³a¶ciciela %s\n" + +#: src/usermod.c:1465 +#, c-format +msgid "%s: cannot rename directory %s to %s\n" +msgstr "%s: nie mogê zmieniæ nazwy katalogu z %s na %s\n" + +#. better leave it alone +#: src/usermod.c:1562 +#, c-format +msgid "%s: warning: %s not owned by %s\n" +msgstr "%s: ostrze¿enie: w³a¶cicielem %s nie jest %s\n" + +#: src/usermod.c:1568 +msgid "failed to change mailbox owner" +msgstr "nie powiod³a siê zmiana w³a¶ciciela skrzynki pocztowej" + +#: src/usermod.c:1575 +msgid "failed to rename mailbox" +msgstr "zmiana nazwy skrzynki pocztowej nie powiod³a siê" + +#: src/vipw.c:103 +#, c-format +msgid "" +"\n" +"%s: %s is unchanged\n" +msgstr "" +"\n" +"%s: %s jest niezmieniony\n" + +#: src/vipw.c:128 +#, fuzzy +msgid "Couldn't lock file" +msgstr "%s: nie mogê usun±c blokady z pliku\n" + +#: src/vipw.c:135 +msgid "Couldn't make backup" +msgstr "" + +#: src/vipw.c:174 +#, c-format +msgid "%s: can't restore %s: %s (your changes are in %s)\n" +msgstr "%s: nie mogê odzyskaæ %s: %s (twoje zmiany s± w %s)\n" + +#: src/vipw.c:213 +msgid "" +"Usage:\n" +"`vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n" +"`vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n" +msgstr "" +"U¿ycie:\n" +"`vipw' edytuje /etc/passwd `vipw -s' edytuje /etc/shadow\n" +"`vigr' edytuje /etc/group `vigr -s' edytuje /etc/gshadow\n" + +#~ msgid "Incorrect password for %s.\n" +#~ msgstr "Nieprawid³owe has³o dla %s.\n" + +#~ msgid "group not found\n" +#~ msgstr "grupa nie znaleziona\n" diff --git a/po/shadow.pot b/po/shadow.pot new file mode 100644 index 00000000..af4c47ad --- /dev/null +++ b/po/shadow.pot @@ -0,0 +1,2341 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 1999-07-09 20:02+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: ENCODING\n" + +#: libmisc/addgrps.c:60 +#, c-format +msgid "Warning: unknown group %s\n" +msgstr "" + +#: libmisc/addgrps.c:71 +msgid "Warning: too many groups\n" +msgstr "" + +#: libmisc/age.c:104 +msgid "Your password has expired." +msgstr "" + +#: libmisc/age.c:107 +msgid "Your password is inactive." +msgstr "" + +#: libmisc/age.c:110 +msgid "Your login has expired." +msgstr "" + +#: libmisc/age.c:127 +msgid " Contact the system administrator.\n" +msgstr "" + +#: libmisc/age.c:130 +msgid " Choose a new password.\n" +msgstr "" + +#: libmisc/age.c:228 +#, c-format +msgid "Your password will expire in %ld days.\n" +msgstr "" + +#: libmisc/age.c:230 +msgid "Your password will expire tomorrow.\n" +msgstr "" + +#: libmisc/age.c:232 +msgid "Your password will expire today.\n" +msgstr "" + +#: libmisc/chowntty.c:110 +#, c-format +msgid "Unable to change tty %s" +msgstr "" + +#: libmisc/env.c:160 +msgid "Environment overflow\n" +msgstr "" + +#: libmisc/env.c:200 +#, c-format +msgid "You may not change $%s\n" +msgstr "" + +#: libmisc/failure.c:238 +#, c-format +msgid "%d %s since last login. Last was %s on %s.\n" +msgstr "" + +#: libmisc/failure.c:239 +msgid "failures" +msgstr "" + +#: libmisc/failure.c:239 +msgid "failure" +msgstr "" + +#: libmisc/limits.c:365 +msgid "Too many logins.\n" +msgstr "" + +#: libmisc/login_desrpc.c:63 +#, c-format +msgid "Password does not decrypt secret key for %s.\n" +msgstr "" + +#: libmisc/login_desrpc.c:69 +#, c-format +msgid "Could not set %s's secret key: is the keyserv daemon running?\n" +msgstr "" + +#: libmisc/mail.c:62 libmisc/mail.c:77 +msgid "You have new mail." +msgstr "" + +#: libmisc/mail.c:73 +msgid "No mail." +msgstr "" + +#: libmisc/mail.c:75 +msgid "You have mail." +msgstr "" + +#: libmisc/obscure.c:281 src/passwd.c:311 +#, c-format +msgid "Bad password: %s. " +msgstr "" + +#: libmisc/pam_pass.c:42 +#, c-format +msgid "passwd: pam_start() failed, error %d\n" +msgstr "" + +#: libmisc/pam_pass.c:49 +#, c-format +msgid "passwd: %s\n" +msgstr "" + +#: libmisc/setupenv.c:205 +#, c-format +msgid "Unable to cd to \"%s\"\n" +msgstr "" + +#: libmisc/setupenv.c:213 +msgid "No directory, logging in with HOME=/" +msgstr "" + +#: libmisc/shell.c:78 +#, c-format +msgid "Executing shell %s\n" +msgstr "" + +#. +#. * Obviously something is really wrong - I can't figure out +#. * how to execute this stupid shell, so I might as well give +#. * up in disgust ... +#. +#: libmisc/shell.c:122 +#, c-format +msgid "Cannot execute %s" +msgstr "" + +#: libmisc/suauth.c:99 +msgid "Access to su to that account DENIED.\n" +msgstr "" + +#: libmisc/suauth.c:106 +msgid "Password authentication bypassed.\n" +msgstr "" + +#: libmisc/suauth.c:113 +msgid "Please enter your OWN password as authentication.\n" +msgstr "" + +#: libmisc/sub.c:61 +#, c-format +msgid "Invalid root directory \"%s\"\n" +msgstr "" + +#: libmisc/sub.c:73 +#, c-format +msgid "Can't change root directory to \"%s\"\n" +msgstr "" + +#: libmisc/xmalloc.c:28 +#, c-format +msgid "malloc(%d) failed\n" +msgstr "" + +#: lib/dialchk.c:71 +msgid "Dialup Password:" +msgstr "" + +#: lib/getdef.c:247 +msgid "Could not allocate space for config info.\n" +msgstr "" + +#. +#. * Item was never found. +#. +#: lib/getdef.c:301 +#, c-format +msgid "configuration error - unknown item '%s' (notify administrator)\n" +msgstr "" + +#: lib/getdef.c:388 +#, c-format +msgid "error - lookup '%s' failed\n" +msgstr "" + +#: lib/getdef.c:396 +#, c-format +msgid "%s not found\n" +msgstr "" + +#: lib/pwauth.c:54 +msgid "Password: " +msgstr "" + +#: lib/pwauth.c:56 +#, c-format +msgid "%s's Password:" +msgstr "" + +#: lib/strerror.c:20 +#, c-format +msgid "Unknown error %d" +msgstr "" + +#: src/chage.c:141 +#, c-format +msgid "" +"Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -W warn ]\n" +" [ -I inactive ] [ -E expire ] [ -d last_day ] user\n" +msgstr "" + +#: src/chage.c:143 +#, c-format +msgid "Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -d last_day ] user\n" +msgstr "" + +#: src/chage.c:178 +msgid "" +"Enter the new value, or press return for the default\n" +"\n" +msgstr "" + +#: src/chage.c:181 +msgid "Minimum Password Age" +msgstr "" + +#: src/chage.c:186 +msgid "Maximum Password Age" +msgstr "" + +#: src/chage.c:192 +msgid "Last Password Change (YYYY-MM-DD)" +msgstr "" + +#: src/chage.c:201 +msgid "Password Expiration Warning" +msgstr "" + +#: src/chage.c:206 +msgid "Password Inactive" +msgstr "" + +#: src/chage.c:212 +msgid "Account Expiration Date (YYYY-MM-DD)" +msgstr "" + +#. +#. * Start with the easy numbers - the number of days before the +#. * password can be changed, the number of days after which the +#. * password must be chaged, the number of days before the +#. * password expires that the user is told, and the number of +#. * days after the password expires that the account becomes +#. * unusable. +#. +#: src/chage.c:266 +#, c-format +msgid "Minimum:\t%ld\n" +msgstr "" + +#: src/chage.c:267 +#, c-format +msgid "Maximum:\t%ld\n" +msgstr "" + +#: src/chage.c:269 +#, c-format +msgid "Warning:\t%ld\n" +msgstr "" + +#: src/chage.c:270 +#, c-format +msgid "Inactive:\t%ld\n" +msgstr "" + +#. +#. * The "last change" date is either "Never" or the date the +#. * password was last modified. The date is the number of +#. * days since 1/1/1970. +#. +#: src/chage.c:279 +msgid "Last Change:\t\t" +msgstr "" + +#: src/chage.c:281 src/chage.c:295 +msgid "Never\n" +msgstr "" + +#. +#. * The password expiration date is determined from the last +#. * change date plus the number of days the password is valid +#. * for. +#. +#: src/chage.c:293 +msgid "Password Expires:\t" +msgstr "" + +#: src/chage.c:468 +#, c-format +msgid "%s: do not include \"l\" with other flags\n" +msgstr "" + +#: src/chage.c:480 src/chage.c:592 src/login.c:532 +#, c-format +msgid "%s: permission denied\n" +msgstr "" + +#: src/chage.c:492 src/chpasswd.c:122 +#, c-format +msgid "%s: can't lock password file\n" +msgstr "" + +#: src/chage.c:498 src/chpasswd.c:126 +#, c-format +msgid "%s: can't open password file\n" +msgstr "" + +#: src/chage.c:505 +#, c-format +msgid "%s: unknown user: %s\n" +msgstr "" + +#: src/chage.c:524 +#, c-format +msgid "%s: can't lock shadow password file\n" +msgstr "" + +#: src/chage.c:531 +#, c-format +msgid "%s: can't open shadow password file\n" +msgstr "" + +#: src/chage.c:613 +#, c-format +msgid "Changing the aging information for %s\n" +msgstr "" + +#: src/chage.c:615 +#, c-format +msgid "%s: error changing fields\n" +msgstr "" + +#: src/chage.c:642 src/chage.c:705 src/pwunconv.c:184 +#, c-format +msgid "%s: can't update password file\n" +msgstr "" + +#: src/chage.c:672 src/pwunconv.c:179 +#, c-format +msgid "%s: can't update shadow password file\n" +msgstr "" + +#: src/chage.c:721 src/chage.c:736 src/chfn.c:572 src/chsh.c:411 +#: src/passwd.c:827 src/passwd.c:928 +msgid "Error updating the DBM password entry.\n" +msgstr "" + +#: src/chage.c:753 +#, c-format +msgid "%s: can't rewrite shadow password file\n" +msgstr "" + +#: src/chage.c:767 +#, c-format +msgid "%s: can't rewrite password file\n" +msgstr "" + +#: src/chage.c:816 +#, c-format +msgid "%s: no aging information present\n" +msgstr "" + +#: src/chfn.c:108 +#, c-format +msgid "" +"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ]\n" +"\t[ -h home_ph ] [ -o other ] [ user ]\n" +msgstr "" + +#: src/chfn.c:112 +#, c-format +msgid "" +"Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ] [ -h home_ph ]\n" +msgstr "" + +#: src/chfn.c:164 src/chsh.c:120 +msgid "Enter the new value, or press return for the default\n" +msgstr "" + +#: src/chfn.c:167 +msgid "Full Name" +msgstr "" + +#: src/chfn.c:169 +#, c-format +msgid "\tFull Name: %s\n" +msgstr "" + +#: src/chfn.c:172 +msgid "Room Number" +msgstr "" + +#: src/chfn.c:174 +#, c-format +msgid "\tRoom Number: %s\n" +msgstr "" + +#: src/chfn.c:177 +msgid "Work Phone" +msgstr "" + +#: src/chfn.c:179 +#, c-format +msgid "\tWork Phone: %s\n" +msgstr "" + +#: src/chfn.c:182 +msgid "Home Phone" +msgstr "" + +#: src/chfn.c:184 +#, c-format +msgid "\tHome Phone: %s\n" +msgstr "" + +#: src/chfn.c:187 +msgid "Other" +msgstr "" + +#: src/chfn.c:300 src/chfn.c:308 src/chfn.c:316 src/chfn.c:324 src/chfn.c:332 +#: src/chfn.c:393 src/passwd.c:1228 +#, c-format +msgid "%s: Permission denied.\n" +msgstr "" + +#: src/chfn.c:353 src/chsh.c:226 src/passwd.c:1279 +#, c-format +msgid "%s: Unknown user %s\n" +msgstr "" + +#: src/chfn.c:359 src/chsh.c:234 src/passwd.c:1209 +#, c-format +msgid "%s: Cannot determine your user name.\n" +msgstr "" + +#: src/chfn.c:375 src/chsh.c:252 +#, c-format +msgid "%s: cannot change user `%s' on NIS client.\n" +msgstr "" + +#: src/chfn.c:380 src/chsh.c:259 +#, c-format +msgid "%s: `%s' is the NIS master for this client.\n" +msgstr "" + +#: src/chfn.c:455 +#, c-format +msgid "Changing the user information for %s\n" +msgstr "" + +#: src/chfn.c:464 +#, c-format +msgid "%s: invalid name: \"%s\"\n" +msgstr "" + +#: src/chfn.c:469 +#, c-format +msgid "%s: invalid room number: \"%s\"\n" +msgstr "" + +#: src/chfn.c:474 +#, c-format +msgid "%s: invalid work phone: \"%s\"\n" +msgstr "" + +#: src/chfn.c:479 +#, c-format +msgid "%s: invalid home phone: \"%s\"\n" +msgstr "" + +#: src/chfn.c:484 +#, c-format +msgid "%s: \"%s\" contains illegal characters\n" +msgstr "" + +#: src/chfn.c:496 +#, c-format +msgid "%s: fields too long\n" +msgstr "" + +#: src/chfn.c:511 src/chsh.c:349 src/gpasswd.c:583 src/passwd.c:1390 +msgid "Cannot change ID to root.\n" +msgstr "" + +#: src/chfn.c:524 src/chsh.c:363 src/passwd.c:737 src/passwd.c:882 +msgid "Cannot lock the password file; try again later.\n" +msgstr "" + +#: src/chfn.c:530 src/chsh.c:369 src/passwd.c:742 src/passwd.c:887 +msgid "Cannot open the password file.\n" +msgstr "" + +#: src/chfn.c:547 src/chsh.c:384 src/passwd.c:748 src/usermod.c:1272 +#, c-format +msgid "%s: %s not found in /etc/passwd\n" +msgstr "" + +#: src/chfn.c:564 src/chsh.c:403 src/passwd.c:821 src/passwd.c:922 +#: src/passwd.c:962 +msgid "Error updating the password entry.\n" +msgstr "" + +#: src/chfn.c:587 src/chsh.c:426 src/passwd.c:834 src/passwd.c:935 +msgid "Cannot commit password file changes.\n" +msgstr "" + +#: src/chfn.c:594 src/chsh.c:433 +msgid "Cannot unlock the password file.\n" +msgstr "" + +#: src/chpasswd.c:78 +#, c-format +msgid "usage: %s [-e]\n" +msgstr "" + +#: src/chpasswd.c:134 src/pwconv.c:105 +#, c-format +msgid "%s: can't lock shadow file\n" +msgstr "" + +#: src/chpasswd.c:139 src/gpasswd.c:609 src/pwconv.c:110 src/pwunconv.c:119 +#: src/pwunconv.c:124 +#, c-format +msgid "%s: can't open shadow file\n" +msgstr "" + +#: src/chpasswd.c:161 src/newusers.c:418 +#, c-format +msgid "%s: line %d: line too long\n" +msgstr "" + +#: src/chpasswd.c:181 +#, c-format +msgid "%s: line %d: missing new password\n" +msgstr "" + +#: src/chpasswd.c:197 +#, c-format +msgid "%s: line %d: unknown user %s\n" +msgstr "" + +#: src/chpasswd.c:249 +#, c-format +msgid "%s: line %d: cannot update password entry\n" +msgstr "" + +#: src/chpasswd.c:265 src/newusers.c:538 +#, c-format +msgid "%s: error detected, changes ignored\n" +msgstr "" + +#: src/chpasswd.c:276 +#, c-format +msgid "%s: error updating shadow file\n" +msgstr "" + +#: src/chpasswd.c:284 +#, c-format +msgid "%s: error updating password file\n" +msgstr "" + +#: src/chsh.c:106 +#, c-format +msgid "Usage: %s [ -s shell ] [ name ]\n" +msgstr "" + +#: src/chsh.c:121 +msgid "Login Shell" +msgstr "" + +#: src/chsh.c:275 src/chsh.c:288 +#, c-format +msgid "You may not change the shell for %s.\n" +msgstr "" + +#: src/chsh.c:317 +#, c-format +msgid "Changing the login shell for %s\n" +msgstr "" + +#: src/chsh.c:329 +#, c-format +msgid "%s: Invalid entry: %s\n" +msgstr "" + +#: src/chsh.c:334 +#, c-format +msgid "%s is an invalid shell.\n" +msgstr "" + +#: src/dpasswd.c:71 +#, c-format +msgid "Usage: %s [ -(a|d) ] shell\n" +msgstr "" + +#: src/dpasswd.c:136 +msgid "Shell password:" +msgstr "" + +#: src/dpasswd.c:142 +msgid "re-enter Shell password:" +msgstr "" + +#: src/dpasswd.c:149 +#, c-format +msgid "%s: Passwords do not match, try again.\n" +msgstr "" + +#: src/dpasswd.c:169 +#, c-format +msgid "%s: can't create %s" +msgstr "" + +#: src/dpasswd.c:174 +#, c-format +msgid "%s: can't open %s" +msgstr "" + +#: src/dpasswd.c:202 +#, c-format +msgid "%s: Shell %s not found.\n" +msgstr "" + +#: src/expiry.c:85 +msgid "Usage: expiry { -f | -c }\n" +msgstr "" + +#: src/expiry.c:138 +#, c-format +msgid "%s: WARNING! Must be set-UID root!\n" +msgstr "" + +#: src/expiry.c:149 +#, c-format +msgid "%s: unknown user\n" +msgstr "" + +#: src/faillog.c:80 +#, c-format +msgid "usage: %s [-a|-u user] [-m max] [-r] [-t days] [-l locksecs]\n" +msgstr "" + +#: src/faillog.c:135 src/lastlog.c:95 +#, c-format +msgid "Unknown User: %s\n" +msgstr "" + +#: src/faillog.c:216 +msgid "Username Failures Maximum Latest\n" +msgstr "" + +#: src/faillog.c:233 +#, c-format +msgid " %s on %s" +msgstr "" + +#: src/faillog.c:237 +#, c-format +msgid " [%lds left]" +msgstr "" + +#: src/faillog.c:240 +#, c-format +msgid " [%lds lock]" +msgstr "" + +#: src/gpasswd.c:91 +#, c-format +msgid "usage: %s [-r|-R] group\n" +msgstr "" + +#: src/gpasswd.c:92 +#, c-format +msgid " %s [-a user] group\n" +msgstr "" + +#: src/gpasswd.c:93 +#, c-format +msgid " %s [-d user] group\n" +msgstr "" + +#: src/gpasswd.c:95 +#, c-format +msgid " %s [-A user,...] [-M user,...] group\n" +msgstr "" + +#: src/gpasswd.c:98 +#, c-format +msgid " %s [-M user,...] group\n" +msgstr "" + +#: src/gpasswd.c:162 src/gpasswd.c:247 +#, c-format +msgid "%s: unknown user %s\n" +msgstr "" + +#: src/gpasswd.c:174 +msgid "Permission denied.\n" +msgstr "" + +#: src/gpasswd.c:259 +#, c-format +msgid "%s: shadow group passwords required for -A\n" +msgstr "" + +#: src/gpasswd.c:310 +msgid "Who are you?\n" +msgstr "" + +#: src/gpasswd.c:330 src/newgrp.c:241 +#, c-format +msgid "unknown group: %s\n" +msgstr "" + +#: src/gpasswd.c:438 +#, c-format +msgid "Adding user %s to group %s\n" +msgstr "" + +#: src/gpasswd.c:455 +#, c-format +msgid "Removing user %s from group %s\n" +msgstr "" + +#: src/gpasswd.c:468 +#, c-format +msgid "%s: unknown member %s\n" +msgstr "" + +#: src/gpasswd.c:515 +#, c-format +msgid "%s: Not a tty\n" +msgstr "" + +#. +#. * A new password is to be entered and it must be encrypted, +#. * etc. The password will be prompted for twice, and both +#. * entries must be identical. There is no need to validate +#. * the old password since the invoker is either the group +#. * owner, or root. +#. +#: src/gpasswd.c:537 +#, c-format +msgid "Changing the password for group %s\n" +msgstr "" + +#: src/gpasswd.c:540 +msgid "New Password:" +msgstr "" + +#: src/gpasswd.c:545 src/passwd.c:424 +msgid "Re-enter new password:" +msgstr "" + +#: src/gpasswd.c:557 +msgid "They don't match; try again" +msgstr "" + +#: src/gpasswd.c:561 +#, c-format +msgid "%s: Try again later\n" +msgstr "" + +#: src/gpasswd.c:591 +#, c-format +msgid "%s: can't get lock\n" +msgstr "" + +#: src/gpasswd.c:597 +#, c-format +msgid "%s: can't get shadow lock\n" +msgstr "" + +#: src/gpasswd.c:603 +#, c-format +msgid "%s: can't open file\n" +msgstr "" + +#: src/gpasswd.c:615 +#, c-format +msgid "%s: can't update entry\n" +msgstr "" + +#: src/gpasswd.c:621 +#, c-format +msgid "%s: can't update shadow entry\n" +msgstr "" + +#: src/gpasswd.c:627 +#, c-format +msgid "%s: can't re-write file\n" +msgstr "" + +#: src/gpasswd.c:633 +#, c-format +msgid "%s: can't re-write shadow file\n" +msgstr "" + +#: src/gpasswd.c:641 +#, c-format +msgid "%s: can't unlock file\n" +msgstr "" + +#: src/gpasswd.c:646 +#, c-format +msgid "%s: can't update DBM files\n" +msgstr "" + +#: src/gpasswd.c:653 +#, c-format +msgid "%s: can't update DBM shadow files\n" +msgstr "" + +#: src/groupadd.c:106 +msgid "usage: groupadd [-g gid [-o]] group\n" +msgstr "" + +#: src/groupadd.c:174 src/groupadd.c:197 src/groupmod.c:184 src/groupmod.c:231 +#: src/useradd.c:932 src/usermod.c:513 src/usermod.c:649 +#, c-format +msgid "%s: error adding new group entry\n" +msgstr "" + +#: src/groupadd.c:184 src/groupadd.c:207 src/groupmod.c:200 src/useradd.c:943 +#: src/usermod.c:525 src/usermod.c:661 +#, c-format +msgid "%s: cannot add new dbm group entry\n" +msgstr "" + +#: src/groupadd.c:259 src/useradd.c:997 +#, c-format +msgid "%s: name %s is not unique\n" +msgstr "" + +#: src/groupadd.c:274 +#, c-format +msgid "%s: gid %ld is not unique\n" +msgstr "" + +#: src/groupadd.c:298 +#, c-format +msgid "%s: can't get unique gid\n" +msgstr "" + +#. +#. * All invalid group names land here. +#. +#: src/groupadd.c:322 src/groupmod.c:342 +#, c-format +msgid "%s: %s is a not a valid group name\n" +msgstr "" + +#: src/groupadd.c:351 src/groupmod.c:368 +#, c-format +msgid "%s: invalid group %s\n" +msgstr "" + +#: src/groupadd.c:368 src/useradd.c:1273 +#, c-format +msgid "%s: -O requires NAME=VALUE\n" +msgstr "" + +#: src/groupadd.c:413 src/groupdel.c:168 src/groupmod.c:404 src/useradd.c:1382 +#: src/userdel.c:273 src/usermod.c:537 +#, c-format +msgid "%s: cannot rewrite group file\n" +msgstr "" + +#: src/groupadd.c:419 src/groupdel.c:174 src/groupmod.c:410 src/useradd.c:1390 +#: src/userdel.c:279 src/usermod.c:674 +#, c-format +msgid "%s: cannot rewrite shadow group file\n" +msgstr "" + +#: src/groupadd.c:438 src/groupdel.c:193 src/groupmod.c:429 src/userdel.c:359 +#, c-format +msgid "%s: unable to lock group file\n" +msgstr "" + +#: src/groupadd.c:442 src/groupdel.c:197 src/groupmod.c:433 +#, c-format +msgid "%s: unable to open group file\n" +msgstr "" + +#: src/groupadd.c:447 src/groupdel.c:202 src/groupmod.c:438 src/userdel.c:368 +#, c-format +msgid "%s: unable to lock shadow group file\n" +msgstr "" + +#: src/groupadd.c:452 src/groupdel.c:207 src/groupmod.c:443 +#, c-format +msgid "%s: unable to open shadow group file\n" +msgstr "" + +#: src/groupadd.c:519 +#, c-format +msgid "%s: group %s exists\n" +msgstr "" + +#: src/groupdel.c:87 +msgid "usage: groupdel group\n" +msgstr "" + +#: src/groupdel.c:105 src/groupmod.c:188 src/groupmod.c:235 +#, c-format +msgid "%s: error removing group entry\n" +msgstr "" + +#: src/groupdel.c:117 src/groupmod.c:207 +#, c-format +msgid "%s: error removing group dbm entry\n" +msgstr "" + +#: src/groupdel.c:132 +#, c-format +msgid "%s: error removing shadow group entry\n" +msgstr "" + +#: src/groupdel.c:145 src/groupmod.c:253 +#, c-format +msgid "%s: error removing shadow group dbm entry\n" +msgstr "" + +#. +#. * Can't remove the group. +#. +#: src/groupdel.c:249 +#, c-format +msgid "%s: cannot remove user's primary group.\n" +msgstr "" + +#: src/groupdel.c:306 src/groupmod.c:502 +#, c-format +msgid "%s: group %s does not exist\n" +msgstr "" + +#: src/groupdel.c:320 src/groupmod.c:518 +#, c-format +msgid "%s: group %s is a NIS group\n" +msgstr "" + +#: src/groupdel.c:326 src/groupmod.c:524 src/userdel.c:731 src/usermod.c:990 +#, c-format +msgid "%s: %s is the NIS master\n" +msgstr "" + +#: src/groupmod.c:106 +msgid "usage: groupmod [-g gid [-o]] [-n name] group\n" +msgstr "" + +#: src/groupmod.c:166 +#, c-format +msgid "%s: %s not found in /etc/group\n" +msgstr "" + +#: src/groupmod.c:247 +#, c-format +msgid "%s: cannot add new dbm shadow group entry\n" +msgstr "" + +#: src/groupmod.c:300 +#, c-format +msgid "%s: %ld is not a unique gid\n" +msgstr "" + +#: src/groupmod.c:331 +#, c-format +msgid "%s: %s is not a unique name\n" +msgstr "" + +#: src/groups.c:63 +#, c-format +msgid "unknown user %s\n" +msgstr "" + +#: src/grpck.c:99 +#, c-format +msgid "Usage: %s [ -r ] [ group [ gshadow ] ]\n" +msgstr "" + +#: src/grpck.c:101 +#, c-format +msgid "Usage: %s [ -r ] [ group ]\n" +msgstr "" + +#: src/grpck.c:120 src/pwck.c:120 +msgid "No" +msgstr "" + +#: src/grpck.c:235 src/grpck.c:243 src/pwck.c:217 src/pwck.c:226 +#, c-format +msgid "%s: cannot lock file %s\n" +msgstr "" + +#: src/grpck.c:258 src/grpck.c:266 src/mkpasswd.c:217 src/pwck.c:242 +#: src/pwck.c:251 +#, c-format +msgid "%s: cannot open file %s\n" +msgstr "" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/grpck.c:299 +msgid "invalid group file entry\n" +msgstr "" + +#: src/grpck.c:300 src/grpck.c:363 src/grpck.c:455 src/grpck.c:518 +#: src/grpck.c:535 src/pwck.c:287 src/pwck.c:349 src/pwck.c:456 src/pwck.c:518 +#: src/pwck.c:542 +#, c-format +msgid "delete line `%s'? " +msgstr "" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/grpck.c:362 +msgid "duplicate group entry\n" +msgstr "" + +#: src/grpck.c:379 +#, c-format +msgid "invalid group name `%s'\n" +msgstr "" + +#: src/grpck.c:389 +#, c-format +msgid "group %s: bad GID (%d)\n" +msgstr "" + +#: src/grpck.c:415 +#, c-format +msgid "group %s: no user %s\n" +msgstr "" + +#: src/grpck.c:417 src/grpck.c:586 +#, c-format +msgid "delete member `%s'? " +msgstr "" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/grpck.c:454 +msgid "invalid shadow group file entry\n" +msgstr "" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/grpck.c:517 +msgid "duplicate shadow group entry\n" +msgstr "" + +#: src/grpck.c:534 +msgid "no matching group file entry\n" +msgstr "" + +#: src/grpck.c:554 +#, c-format +msgid "shadow group %s: no administrative user %s\n" +msgstr "" + +#: src/grpck.c:556 +#, c-format +msgid "delete administrative member `%s'? " +msgstr "" + +#: src/grpck.c:584 +#, c-format +msgid "shadow group %s: no user %s\n" +msgstr "" + +#: src/grpck.c:611 src/grpck.c:617 src/pwck.c:573 src/pwck.c:581 +#, c-format +msgid "%s: cannot update file %s\n" +msgstr "" + +#: src/grpck.c:641 src/pwck.c:607 +#, c-format +msgid "%s: the files have been updated; run mkpasswd\n" +msgstr "" + +#: src/grpck.c:642 src/grpck.c:646 src/pwck.c:608 src/pwck.c:612 +#, c-format +msgid "%s: no changes\n" +msgstr "" + +#: src/grpck.c:645 src/pwck.c:611 +#, c-format +msgid "%s: the files have been updated\n" +msgstr "" + +#: src/grpconv.c:63 src/grpunconv.c:64 +#, c-format +msgid "%s: can't lock group file\n" +msgstr "" + +#: src/grpconv.c:68 src/grpunconv.c:69 +#, c-format +msgid "%s: can't open group file\n" +msgstr "" + +#: src/grpconv.c:73 src/grpunconv.c:74 +#, c-format +msgid "%s: can't lock shadow group file\n" +msgstr "" + +#: src/grpconv.c:78 src/grpunconv.c:79 +#, c-format +msgid "%s: can't open shadow group file\n" +msgstr "" + +#. +#. * This shouldn't happen (the entry exists) but... +#. +#: src/grpconv.c:94 +#, c-format +msgid "%s: can't remove shadow group %s\n" +msgstr "" + +#: src/grpconv.c:135 src/pwconv.c:161 +#, c-format +msgid "%s: can't update shadow entry for %s\n" +msgstr "" + +#: src/grpconv.c:144 src/grpunconv.c:95 +#, c-format +msgid "%s: can't update entry for group %s\n" +msgstr "" + +#: src/grpconv.c:151 src/grpunconv.c:103 +#, c-format +msgid "%s: can't update shadow group file\n" +msgstr "" + +#: src/grpconv.c:155 src/grpunconv.c:108 +#, c-format +msgid "%s: can't update group file\n" +msgstr "" + +#: src/grpconv.c:170 src/grpunconv.c:129 +#, c-format +msgid "%s: not configured for shadow group support.\n" +msgstr "" + +#: src/grpunconv.c:113 +#, c-format +msgid "%s: can't delete shadow group file\n" +msgstr "" + +#: src/id.c:57 +msgid "usage: id [ -a ]\n" +msgstr "" + +#: src/id.c:59 +msgid "usage: id\n" +msgstr "" + +#: src/id.c:119 +#, c-format +msgid "uid=%d(%s)" +msgstr "" + +#: src/id.c:121 +#, c-format +msgid "uid=%d" +msgstr "" + +#: src/id.c:125 +#, c-format +msgid " gid=%d(%s)" +msgstr "" + +#: src/id.c:127 +#, c-format +msgid " gid=%d" +msgstr "" + +#: src/id.c:137 +#, c-format +msgid " euid=%d(%s)" +msgstr "" + +#: src/id.c:139 +#, c-format +msgid " euid=%d" +msgstr "" + +#: src/id.c:144 +#, c-format +msgid " egid=%d(%s)" +msgstr "" + +#: src/id.c:146 +#, c-format +msgid " egid=%d" +msgstr "" + +#. +#. * Start off the group message. It will be of the format +#. * +#. * groups=###(aaa),###(aaa),###(aaa) +#. * +#. * where "###" is a numerical value and "aaa" is the +#. * corresponding name for each respective numerical value. +#. +#: src/id.c:167 +msgid " groups=" +msgstr "" + +#: src/lastlog.c:168 +msgid "Username Port From Latest\n" +msgstr "" + +#: src/lastlog.c:170 +msgid "Username Port Latest\n" +msgstr "" + +#: src/lastlog.c:184 +msgid "**Never logged in**" +msgstr "" + +#: src/login.c:199 +#, c-format +msgid "usage: %s [-p] [name]\n" +msgstr "" + +#: src/login.c:202 +#, c-format +msgid " %s [-p] [-h host] [-f name]\n" +msgstr "" + +#: src/login.c:204 +#, c-format +msgid " %s [-p] -r host\n" +msgstr "" + +#: src/login.c:290 +msgid "Invalid login time\n" +msgstr "" + +#: src/login.c:345 +msgid "" +"\n" +"System closed for routine maintenance\n" +msgstr "" + +#: src/login.c:355 +msgid "" +"\n" +"[Disconnect bypassed -- root login allowed.]\n" +msgstr "" + +#: src/login.c:394 +#, c-format +msgid "" +"\n" +"Login timed out after %d seconds.\n" +msgstr "" + +#: src/login.c:695 +#, c-format +msgid " on `%.100s' from `%.200s'" +msgstr "" + +#: src/login.c:697 +#, c-format +msgid " on `%.100s'" +msgstr "" + +#: src/login.c:810 +#, c-format +msgid "" +"\n" +"%s login: " +msgstr "" + +#: src/login.c:812 +msgid "login: " +msgstr "" + +#: src/login.c:994 src/sulogin.c:239 +msgid "Login incorrect" +msgstr "" + +#: src/login.c:1166 +msgid "Warning: login re-enabled after temporary lockout.\n" +msgstr "" + +#: src/login.c:1176 +#, c-format +msgid "Last login: %s on %s" +msgstr "" + +#: src/login.c:1179 +#, c-format +msgid "Last login: %.19s on %s" +msgstr "" + +#: src/login.c:1184 +#, c-format +msgid " from %.*s" +msgstr "" + +#: src/login.c:1249 +msgid "Starting rad_login\n" +msgstr "" + +#: src/mkpasswd.c:49 +#, c-format +msgid "%s: no DBM database on system - no action performed\n" +msgstr "" + +#: src/mkpasswd.c:246 src/mkpasswd.c:250 +#, c-format +msgid "%s: cannot overwrite file %s\n" +msgstr "" + +#: src/mkpasswd.c:264 +#, c-format +msgid "%s: cannot open DBM files for %s\n" +msgstr "" + +#: src/mkpasswd.c:297 +#, c-format +msgid "%s: the beginning with " +msgstr "" + +#: src/mkpasswd.c:322 +#, c-format +msgid "%s: error parsing line \"%s\"\n" +msgstr "" + +#: src/mkpasswd.c:327 src/mkpasswd.c:329 src/mkpasswd.c:331 src/mkpasswd.c:333 +msgid "adding record for name " +msgstr "" + +#: src/mkpasswd.c:337 src/mkpasswd.c:342 src/mkpasswd.c:346 src/mkpasswd.c:350 +#, c-format +msgid "%s: error adding record for " +msgstr "" + +#: src/mkpasswd.c:368 +#, c-format +msgid "added %d entries, longest was %d\n" +msgstr "" + +#: src/mkpasswd.c:383 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n" +msgstr "" + +#: src/mkpasswd.c:385 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g|sp ] file\n" +msgstr "" + +#: src/mkpasswd.c:388 +#, c-format +msgid "Usage: %s [ -vf ] [ -p|g ] file\n" +msgstr "" + +#: src/newgrp.c:67 +msgid "usage: newgrp [ - ] [ group ]\n" +msgstr "" + +#: src/newgrp.c:69 +msgid "usage: sg group [ command ]\n" +msgstr "" + +#: src/newgrp.c:122 +#, c-format +msgid "unknown uid: %d\n" +msgstr "" + +#: src/newgrp.c:190 +#, c-format +msgid "unknown gid: %ld\n" +msgstr "" + +#: src/newgrp.c:236 +#, c-format +msgid "unknown gid: %d\n" +msgstr "" + +#. +#. * get the password from her, and set the salt for +#. * the decryption from the group file. +#. +#: src/newgrp.c:291 +msgid "Password:" +msgstr "" + +#: src/newgrp.c:309 src/newgrp.c:318 +msgid "Sorry.\n" +msgstr "" + +#: src/newgrp.c:350 +msgid "too many groups\n" +msgstr "" + +#: src/newusers.c:79 +#, c-format +msgid "Usage: %s [ input ]\n" +msgstr "" + +#: src/newusers.c:367 +#, c-format +msgid "%s: can't lock /etc/passwd.\n" +msgstr "" + +#: src/newusers.c:378 +#, c-format +msgid "%s: can't lock files, try again later\n" +msgstr "" + +#: src/newusers.c:393 +#, c-format +msgid "%s: can't open files\n" +msgstr "" + +#: src/newusers.c:438 +#, c-format +msgid "%s: line %d: invalid line\n" +msgstr "" + +#: src/newusers.c:456 +#, c-format +msgid "%s: line %d: can't create GID\n" +msgstr "" + +#: src/newusers.c:472 +#, c-format +msgid "%s: line %d: can't create UID\n" +msgstr "" + +#: src/newusers.c:484 +#, c-format +msgid "%s: line %d: cannot find user %s\n" +msgstr "" + +#: src/newusers.c:492 +#, c-format +msgid "%s: line %d: can't update password\n" +msgstr "" + +#: src/newusers.c:509 +#, c-format +msgid "%s: line %d: mkdir failed\n" +msgstr "" + +#: src/newusers.c:513 +#, c-format +msgid "%s: line %d: chown failed\n" +msgstr "" + +#: src/newusers.c:522 +#, c-format +msgid "%s: line %d: can't update entry\n" +msgstr "" + +#: src/newusers.c:553 +#, c-format +msgid "%s: error updating files\n" +msgstr "" + +#: src/passwd.c:241 +#, c-format +msgid "usage: %s [ -f | -s ] [ name ]\n" +msgstr "" + +#: src/passwd.c:244 +#, c-format +msgid " %s [ -x max ] [ -n min ] [ -w warn ] [ -i inact ] name\n" +msgstr "" + +#: src/passwd.c:247 +#, c-format +msgid " %s { -l | -u | -d | -S | -e } name\n" +msgstr "" + +#: src/passwd.c:349 +#, c-format +msgid "User %s has a TCFS key, his old password is required.\n" +msgstr "" + +#: src/passwd.c:350 +msgid "You can use -t option to force the change.\n" +msgstr "" + +#: src/passwd.c:356 +msgid "Old password:" +msgstr "" + +#: src/passwd.c:363 +#, c-format +msgid "Incorrect password for `%s'\n" +msgstr "" + +#: src/passwd.c:376 +#, c-format +msgid "Warning: user %s has a TCFS key.\n" +msgstr "" + +#: src/passwd.c:394 +#, c-format +msgid "" +"Enter the new password (minimum of %d, maximum of %d characters)\n" +"Please use a combination of upper and lower case letters and numbers.\n" +msgstr "" + +#: src/passwd.c:401 +msgid "New password:" +msgstr "" + +#: src/passwd.c:411 +msgid "Try again.\n" +msgstr "" + +#: src/passwd.c:420 +msgid "" +"\n" +"Warning: weak password (enter it again to use it anyway).\n" +msgstr "" + +#: src/passwd.c:429 +msgid "They don't match; try again.\n" +msgstr "" + +#: src/passwd.c:514 src/passwd.c:530 +#, c-format +msgid "The password for %s cannot be changed.\n" +msgstr "" + +#: src/passwd.c:558 +#, c-format +msgid "Sorry, the password for %s cannot be changed yet.\n" +msgstr "" + +#: src/passwd.c:695 +#, c-format +msgid "%s: out of memory\n" +msgstr "" + +#: src/passwd.c:847 +msgid "Cannot lock the TCFS key database; try again later\n" +msgstr "" + +#: src/passwd.c:853 +msgid "Cannot open the TCFS key database.\n" +msgstr "" + +#: src/passwd.c:859 +msgid "Error updating the TCFS key database.\n" +msgstr "" + +#: src/passwd.c:864 +msgid "Cannot commit TCFS changes.\n" +msgstr "" + +#: src/passwd.c:1071 +#, c-format +msgid "%s: Cannot execute %s" +msgstr "" + +#: src/passwd.c:1178 +#, c-format +msgid "%s: repository %s not supported\n" +msgstr "" + +#: src/passwd.c:1265 +#, c-format +msgid "%s: Permission denied\n" +msgstr "" + +#: src/passwd.c:1289 +#, c-format +msgid "You may not change the password for %s.\n" +msgstr "" + +#: src/passwd.c:1354 +#, c-format +msgid "Changing password for %s\n" +msgstr "" + +#: src/passwd.c:1358 +#, c-format +msgid "The password for %s is unchanged.\n" +msgstr "" + +#: src/passwd.c:1414 +msgid "Password changed.\n" +msgstr "" + +#: src/pwck.c:99 +#, c-format +msgid "Usage: %s [ -qr ] [ passwd [ shadow ] ]\n" +msgstr "" + +#: src/pwck.c:101 +#, c-format +msgid "Usage: %s [ -qr ] [ passwd ]\n" +msgstr "" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/pwck.c:286 +msgid "invalid password file entry\n" +msgstr "" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/pwck.c:348 +msgid "duplicate password entry\n" +msgstr "" + +#: src/pwck.c:364 +#, c-format +msgid "invalid user name `%s'\n" +msgstr "" + +#: src/pwck.c:374 +#, c-format +msgid "user %s: bad UID (%d)\n" +msgstr "" + +#. +#. * No primary group, just give a warning +#. +#: src/pwck.c:389 +#, c-format +msgid "user %s: no group %d\n" +msgstr "" + +#. +#. * Home directory doesn't exist, give a warning +#. +#: src/pwck.c:404 +#, c-format +msgid "user %s: directory %s does not exist\n" +msgstr "" + +#. +#. * Login shell doesn't exist, give a warning +#. +#: src/pwck.c:419 +#, c-format +msgid "user %s: program %s does not exist\n" +msgstr "" + +#. +#. * Tell the user this entire line is bogus and +#. * ask them to delete it. +#. +#: src/pwck.c:455 +msgid "invalid shadow password file entry\n" +msgstr "" + +#. +#. * Tell the user this entry is a duplicate of +#. * another and ask them to delete it. +#. +#: src/pwck.c:517 +msgid "duplicate shadow password entry\n" +msgstr "" + +#. +#. * Tell the user this entry has no matching +#. * /etc/passwd entry and ask them to delete it. +#. +#: src/pwck.c:541 +msgid "no matching password file entry\n" +msgstr "" + +#: src/pwck.c:558 +#, c-format +msgid "user %s: last password change in the future\n" +msgstr "" + +#: src/pwconv.c:95 src/pwunconv.c:109 +#, c-format +msgid "%s: can't lock passwd file\n" +msgstr "" + +#: src/pwconv.c:100 src/pwunconv.c:114 +#, c-format +msgid "%s: can't open passwd file\n" +msgstr "" + +#: src/pwconv.c:127 +#, c-format +msgid "%s: can't remove shadow entry for %s\n" +msgstr "" + +#: src/pwconv.c:170 +#, c-format +msgid "%s: can't update passwd entry for %s\n" +msgstr "" + +#: src/pwconv.c:177 +#, c-format +msgid "%s: can't update shadow file\n" +msgstr "" + +#: src/pwconv.c:181 +#, c-format +msgid "%s: can't update passwd file\n" +msgstr "" + +#: src/pwunconv.c:62 +#, c-format +msgid "%s: Shadow passwords are not configured.\n" +msgstr "" + +#: src/pwunconv.c:172 +#, c-format +msgid "%s: can't update entry for user %s\n" +msgstr "" + +#: src/pwunconv.c:189 +#, c-format +msgid "%s: can't delete shadow password file\n" +msgstr "" + +#: src/su.c:145 +msgid "Sorry." +msgstr "" + +#: src/su.c:227 +#, c-format +msgid "%s: must be run from a terminal\n" +msgstr "" + +#: src/su.c:319 +#, c-format +msgid "%s: pam_start: error %d\n" +msgstr "" + +#: src/su.c:345 +#, c-format +msgid "Unknown id: %s\n" +msgstr "" + +#. access denied (-1) or unexpected value +#: src/su.c:380 src/su.c:395 +#, c-format +msgid "You are not authorized to su %s\n" +msgstr "" + +#. require own password +#: src/su.c:391 +msgid "(Enter your own password.)" +msgstr "" + +#: src/su.c:412 +#, c-format +msgid "%s: permission denied (shell).\n" +msgstr "" + +#: src/su.c:436 +#, c-format +msgid "" +"%s: %s\n" +"(Ignored)\n" +msgstr "" + +#: src/su.c:605 +msgid "No shell\n" +msgstr "" + +#. must be a password file! +#: src/sulogin.c:144 +msgid "No password file\n" +msgstr "" + +#. +#. * Fail secure +#. +#: src/sulogin.c:186 +msgid "No password entry for 'root'\n" +msgstr "" + +#. +#. * Here we prompt for the root password, or if no password is +#. * given we just exit. +#. +#. get a password for root +#: src/sulogin.c:200 +msgid "" +"\n" +"Type control-d to proceed with normal startup,\n" +"(or give root password for system maintenance):" +msgstr "" + +#. make new environment active +#: src/sulogin.c:249 +msgid "Entering System Maintenance Mode\n" +msgstr "" + +#: src/useradd.c:244 +#, c-format +msgid "%s: rebuild the group database\n" +msgstr "" + +#: src/useradd.c:251 +#, c-format +msgid "%s: rebuild the shadow group database\n" +msgstr "" + +#: src/useradd.c:288 src/usermod.c:941 +#, c-format +msgid "%s: invalid numeric argument `%s'\n" +msgstr "" + +#: src/useradd.c:344 +#, c-format +msgid "%s: unknown gid %s\n" +msgstr "" + +#: src/useradd.c:351 src/useradd.c:643 src/useradd.c:1229 src/usermod.c:253 +#: src/usermod.c:1072 +#, c-format +msgid "%s: unknown group %s\n" +msgstr "" + +#: src/useradd.c:419 +#, c-format +msgid "group=%s,%ld basedir=%s skel=%s\n" +msgstr "" + +#: src/useradd.c:422 +#, c-format +msgid "shell=%s " +msgstr "" + +#: src/useradd.c:424 +#, c-format +msgid "inactive=%ld expire=%s" +msgstr "" + +#: src/useradd.c:428 +#, c-format +msgid "GROUP=%ld\n" +msgstr "" + +#: src/useradd.c:429 +#, c-format +msgid "HOME=%s\n" +msgstr "" + +#: src/useradd.c:431 +#, c-format +msgid "INACTIVE=%ld\n" +msgstr "" + +#: src/useradd.c:432 +#, c-format +msgid "EXPIRE=%s\n" +msgstr "" + +#: src/useradd.c:434 +#, c-format +msgid "SHELL=%s\n" +msgstr "" + +#: src/useradd.c:435 +#, c-format +msgid "SKEL=%s\n" +msgstr "" + +#: src/useradd.c:471 +#, c-format +msgid "%s: cannot create new defaults file\n" +msgstr "" + +#: src/useradd.c:565 src/useradd.c:576 +#, c-format +msgid "%s: rename: %s" +msgstr "" + +#: src/useradd.c:663 src/usermod.c:273 +#, c-format +msgid "%s: group `%s' is a NIS group.\n" +msgstr "" + +#: src/useradd.c:671 src/usermod.c:281 +#, c-format +msgid "%s: too many groups specified (max %d).\n" +msgstr "" + +#: src/useradd.c:703 src/usermod.c:313 +#, c-format +msgid "usage: %s\t[-u uid [-o]] [-g group] [-G group,...] \n" +msgstr "" + +#: src/useradd.c:706 +msgid "\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n" +msgstr "" + +#: src/useradd.c:709 src/usermod.c:319 +msgid "[-f inactive] [-e expire ] " +msgstr "" + +#: src/useradd.c:712 +msgid "[-A program] " +msgstr "" + +#: src/useradd.c:714 src/usermod.c:324 +msgid "[-p passwd] name\n" +msgstr "" + +#: src/useradd.c:716 +#, c-format +msgid " %s\t-D [-g group] [-b base] [-s shell]\n" +msgstr "" + +#: src/useradd.c:719 +msgid "\t\t[-f inactive] [-e expire ]\n" +msgstr "" + +#: src/useradd.c:816 src/usermod.c:446 +#, c-format +msgid "%s: error locking group file\n" +msgstr "" + +#: src/useradd.c:820 src/usermod.c:451 +#, c-format +msgid "%s: error opening group file\n" +msgstr "" + +#: src/useradd.c:825 src/usermod.c:558 +#, c-format +msgid "%s: error locking shadow group file\n" +msgstr "" + +#: src/useradd.c:830 src/usermod.c:564 +#, c-format +msgid "%s: error opening shadow group file\n" +msgstr "" + +#: src/useradd.c:1002 +#, c-format +msgid "%s: uid %d is not unique\n" +msgstr "" + +#: src/useradd.c:1032 +#, c-format +msgid "%s: can't get unique uid\n" +msgstr "" + +#: src/useradd.c:1140 src/useradd.c:1284 src/usermod.c:1020 src/usermod.c:1031 +#: src/usermod.c:1041 src/usermod.c:1087 src/usermod.c:1122 +#, c-format +msgid "%s: invalid field `%s'\n" +msgstr "" + +#: src/useradd.c:1154 +#, c-format +msgid "%s: invalid base directory `%s'\n" +msgstr "" + +#: src/useradd.c:1164 +#, c-format +msgid "%s: invalid comment `%s'\n" +msgstr "" + +#: src/useradd.c:1174 +#, c-format +msgid "%s: invalid home directory `%s'\n" +msgstr "" + +#: src/useradd.c:1192 src/usermod.c:1054 +#, c-format +msgid "%s: invalid date `%s'\n" +msgstr "" + +#: src/useradd.c:1204 +#, c-format +msgid "%s: shadow passwords required for -e\n" +msgstr "" + +#: src/useradd.c:1219 +#, c-format +msgid "%s: shadow passwords required for -f\n" +msgstr "" + +#: src/useradd.c:1293 +#, c-format +msgid "%s: invalid shell `%s'\n" +msgstr "" + +#: src/useradd.c:1334 +#, c-format +msgid "%s: invalid user name `%s'\n" +msgstr "" + +#: src/useradd.c:1370 src/userdel.c:262 src/usermod.c:1184 +#, c-format +msgid "%s: cannot rewrite password file\n" +msgstr "" + +#: src/useradd.c:1375 src/userdel.c:265 src/usermod.c:1189 +#, c-format +msgid "%s: cannot rewrite shadow password file\n" +msgstr "" + +#: src/useradd.c:1415 src/userdel.c:329 src/usermod.c:1224 +#, c-format +msgid "%s: unable to lock password file\n" +msgstr "" + +#: src/useradd.c:1419 src/userdel.c:333 src/usermod.c:1228 +#, c-format +msgid "%s: unable to open password file\n" +msgstr "" + +#: src/useradd.c:1425 src/userdel.c:338 src/usermod.c:1233 +#, c-format +msgid "%s: cannot lock shadow password file\n" +msgstr "" + +#: src/useradd.c:1431 src/userdel.c:343 src/usermod.c:1238 +#, c-format +msgid "%s: cannot open shadow password file\n" +msgstr "" + +#: src/useradd.c:1530 src/usermod.c:1325 +#, c-format +msgid "%s: error adding authentication method\n" +msgstr "" + +#: src/useradd.c:1553 +#, c-format +msgid "%s: error adding new password entry\n" +msgstr "" + +#: src/useradd.c:1568 +#, c-format +msgid "%s: error updating password dbm entry\n" +msgstr "" + +#: src/useradd.c:1584 src/usermod.c:1384 +#, c-format +msgid "%s: error adding new shadow password entry\n" +msgstr "" + +#: src/useradd.c:1600 src/usermod.c:1399 +#, c-format +msgid "%s: error updating shadow passwd dbm entry\n" +msgstr "" + +#: src/useradd.c:1632 +#, c-format +msgid "%s: cannot create directory %s\n" +msgstr "" + +#: src/useradd.c:1709 src/usermod.c:1162 +#, c-format +msgid "%s: user %s exists\n" +msgstr "" + +#: src/useradd.c:1739 +#, c-format +msgid "%s: warning: CREATE_HOME not supported, please use -m instead.\n" +msgstr "" + +#: src/userdel.c:128 +#, c-format +msgid "usage: %s [-r] name\n" +msgstr "" + +#: src/userdel.c:175 src/userdel.c:230 +#, c-format +msgid "%s: error updating group entry\n" +msgstr "" + +#: src/userdel.c:185 src/userdel.c:239 +#, c-format +msgid "%s: cannot update dbm group entry\n" +msgstr "" + +#: src/userdel.c:270 +#, c-format +msgid "%s: cannot rewrite TCFS key file\n" +msgstr "" + +#: src/userdel.c:350 +#, c-format +msgid "%s: cannot lock TCFS key file\n" +msgstr "" + +#: src/userdel.c:354 +#, c-format +msgid "%s: cannot open TCFS key file\n" +msgstr "" + +#: src/userdel.c:363 +#, c-format +msgid "%s: cannot open group file\n" +msgstr "" + +#: src/userdel.c:373 +#, c-format +msgid "%s: cannot open shadow group file\n" +msgstr "" + +#: src/userdel.c:404 src/userdel.c:419 +#, c-format +msgid "%s: error deleting authentication\n" +msgstr "" + +#: src/userdel.c:428 +#, c-format +msgid "%s: error deleting password entry\n" +msgstr "" + +#: src/userdel.c:431 +#, c-format +msgid "%s: error deleting shadow password entry\n" +msgstr "" + +#: src/userdel.c:440 +#, c-format +msgid "%s: error deleting TCFS entry\n" +msgstr "" + +#: src/userdel.c:453 +#, c-format +msgid "%s: error deleting password dbm entry\n" +msgstr "" + +#: src/userdel.c:472 +#, c-format +msgid "%s: error deleting shadow passwd dbm entry\n" +msgstr "" + +#: src/userdel.c:513 +#, c-format +msgid "%s: user %s is currently logged in\n" +msgstr "" + +#: src/userdel.c:630 +#, c-format +msgid "%s: warning: %s not owned by %s, not removing\n" +msgstr "" + +#: src/userdel.c:636 +#, c-format +msgid "%s: warning: can't remove " +msgstr "" + +#: src/userdel.c:711 src/usermod.c:968 +#, c-format +msgid "%s: user %s does not exist\n" +msgstr "" + +#: src/userdel.c:725 src/usermod.c:984 +#, c-format +msgid "%s: user %s is a NIS user\n" +msgstr "" + +#: src/userdel.c:762 +#, c-format +msgid "%s: %s not owned by %s, not removing\n" +msgstr "" + +#: src/userdel.c:785 +#, c-format +msgid "%s: not removing directory %s (would remove home of user %s)\n" +msgstr "" + +#: src/userdel.c:798 +#, c-format +msgid "%s: error removing directory %s\n" +msgstr "" + +#: src/usermod.c:316 +msgid "\t\t[-d home [-m]] [-s shell] [-c comment] [-l new_name]\n" +msgstr "" + +#: src/usermod.c:322 +msgid "[-A {DEFAULT|program},... ] " +msgstr "" + +#: src/usermod.c:478 +#, c-format +msgid "%s: out of memory in update_group\n" +msgstr "" + +#: src/usermod.c:601 +#, c-format +msgid "%s: out of memory in update_gshadow\n" +msgstr "" + +#: src/usermod.c:1139 +#, c-format +msgid "%s: no flags given\n" +msgstr "" + +#: src/usermod.c:1146 +#, c-format +msgid "%s: shadow passwords required for -e and -f\n" +msgstr "" + +#: src/usermod.c:1167 +#, c-format +msgid "%s: uid %ld is not unique\n" +msgstr "" + +#: src/usermod.c:1315 +#, c-format +msgid "%s: error deleting authentication method\n" +msgstr "" + +#: src/usermod.c:1335 +#, c-format +msgid "%s: error changing authentication method\n" +msgstr "" + +#: src/usermod.c:1352 +#, c-format +msgid "%s: error changing password entry\n" +msgstr "" + +#: src/usermod.c:1358 +#, c-format +msgid "%s: error removing password entry\n" +msgstr "" + +#: src/usermod.c:1366 +#, c-format +msgid "%s: error adding password dbm entry\n" +msgstr "" + +#: src/usermod.c:1373 +#, c-format +msgid "%s: error removing passwd dbm entry\n" +msgstr "" + +#: src/usermod.c:1390 +#, c-format +msgid "%s: error removing shadow password entry\n" +msgstr "" + +#: src/usermod.c:1405 +#, c-format +msgid "%s: error removing shadow passwd dbm entry\n" +msgstr "" + +#: src/usermod.c:1436 +#, c-format +msgid "%s: directory %s exists\n" +msgstr "" + +#: src/usermod.c:1443 +#, c-format +msgid "%s: can't create %s\n" +msgstr "" + +#: src/usermod.c:1449 +#, c-format +msgid "%s: can't chown %s\n" +msgstr "" + +#: src/usermod.c:1465 +#, c-format +msgid "%s: cannot rename directory %s to %s\n" +msgstr "" + +#. better leave it alone +#: src/usermod.c:1562 +#, c-format +msgid "%s: warning: %s not owned by %s\n" +msgstr "" + +#: src/usermod.c:1568 +msgid "failed to change mailbox owner" +msgstr "" + +#: src/usermod.c:1575 +msgid "failed to rename mailbox" +msgstr "" + +#: src/vipw.c:103 +#, c-format +msgid "" +"\n" +"%s: %s is unchanged\n" +msgstr "" + +#: src/vipw.c:128 +msgid "Couldn't lock file" +msgstr "" + +#: src/vipw.c:135 +msgid "Couldn't make backup" +msgstr "" + +#: src/vipw.c:174 +#, c-format +msgid "%s: can't restore %s: %s (your changes are in %s)\n" +msgstr "" + +#: src/vipw.c:213 +msgid "" +"Usage:\n" +"`vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n" +"`vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n" +msgstr "" diff --git a/po/stamp-cat-id b/po/stamp-cat-id new file mode 100644 index 00000000..9788f702 --- /dev/null +++ b/po/stamp-cat-id @@ -0,0 +1 @@ +timestamp diff --git a/redhat/Makefile.am b/redhat/Makefile.am new file mode 100644 index 00000000..4e9ac2fa --- /dev/null +++ b/redhat/Makefile.am @@ -0,0 +1,8 @@ +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + +EXTRA_DIST = README shadow-utils.spec shadow-utils.spec.in \ + shadow-970616-fix.patch shadow-970616-glibc.patch \ + shadow-970616-rh.patch shadow-970616-utuser.patch \ + shadow-970616.login.defs shadow-970616.useradd \ + shadow-utils-970616.spec diff --git a/redhat/Makefile.in b/redhat/Makefile.in new file mode 100644 index 00000000..dc4e2c88 --- /dev/null +++ b/redhat/Makefile.in @@ -0,0 +1,201 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# This is a dummy Makefile.am to get automake work flawlessly, +# and also cooperate to make a distribution for `make dist' + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +EXTRA_DIST = README shadow-utils.spec shadow-utils.spec.in \ + shadow-970616-fix.patch shadow-970616-glibc.patch \ + shadow-970616-rh.patch shadow-970616-utuser.patch \ + shadow-970616.login.defs shadow-970616.useradd \ + shadow-utils-970616.spec +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = shadow-utils.spec +DIST_COMMON = README Makefile.am Makefile.in shadow-utils.spec.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +all: Makefile + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps redhat/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +shadow-utils.spec: $(top_builddir)/config.status shadow-utils.spec.in + cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = redhat + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: + @$(NORMAL_INSTALL) + +install-data: + @$(NORMAL_INSTALL) + +install: install-exec install-data all + @: + +uninstall: + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-generic + +clean: clean-generic mostlyclean + +distclean: distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: tags distdir info dvi installcheck install-exec install-data \ +install uninstall all installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/redhat/README b/redhat/README new file mode 100644 index 00000000..96739e7f --- /dev/null +++ b/redhat/README @@ -0,0 +1,29 @@ +Included here are the patches from the shadow-utils-970616-11.src.rpm +(RedHat 5.0 updates). I'd like to make it possible to build binary +packages for all Linux distributions "out of the box" from the same +upstream sources. This needs more work for RedHat 5.0, and I only have +RedHat 4.2 (hint hint). If you have any suggestions regarding this +package, please contact me. Perhaps the necessary changes can be +included in the standard sources, so that everything can be build with +one simple command (rpm -ta shadow-xxxxxx.tar.gz). + +One suggestion for the shadow-utils-970616-11 patch: instead of adding +new (sometimes quite distribution-specific) options to useradd (and +symlinking adduser -> useradd), I'd suggest to use a program or script +called "adduser" that implements the distribution-specific UID/GID +allocation etc. and runs useradd to do all the dirty work (modifying +password files etc.). Also, please don't change the default behaviour +of useradd, which is to create the home directory only if the -m option +is specified). I'd like to keep useradd simple, and compatible with +other implementations (the user* and group* commands are quite similar +to commands with the same names found on many commercial UN*X systems). + +I'd suggest to take a look at the adduser-3.x package from the Debian +distribution. It's a perl script, which shouldn't be too hard to modify +to suit the requirements of Red Hat, or any other Linux distribution. +It runs programs from the shadow suite to do the actual password file +modifications, is reasonably user friendly, and configurable. + +Comments? + +--marekm diff --git a/redhat/shadow-970616-fix.patch b/redhat/shadow-970616-fix.patch new file mode 100644 index 00000000..341f11a4 --- /dev/null +++ b/redhat/shadow-970616-fix.patch @@ -0,0 +1,256 @@ +--- shadow-970616/libmisc/Makefile.in.fix Sun Jun 15 20:05:05 1997 ++++ shadow-970616/libmisc/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -99,13 +99,6 @@ + + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status +- + mostlyclean-noinstLIBRARIES: + + clean-noinstLIBRARIES: +--- shadow-970616/man/Makefile.in.fix Sun Jun 15 20:05:05 1997 ++++ shadow-970616/man/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -72,12 +72,6 @@ + TAR = tar + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + install-man: $(MANS) + $(mkinstalldirs) $(mandir)/man8 + $(mkinstalldirs) $(mandir)/man1 +--- shadow-970616/lib/Makefile.in.fix Sun Jun 15 20:05:06 1997 ++++ shadow-970616/lib/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -123,12 +123,6 @@ + default: all + + +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status +- + mostlyclean-noinstLIBRARIES: + + clean-noinstLIBRARIES: +--- shadow-970616/src/useradd.c.fix Tue Dec 30 14:09:29 1997 ++++ shadow-970616/src/useradd.c Tue Dec 30 14:37:22 1997 +@@ -570,8 +570,7 @@ + */ + + static int +-get_groups(list) +- char *list; ++get_groups(char *list) + { + char *cp; + const struct group *grp; +@@ -606,7 +605,7 @@ + * GID values, otherwise the string is looked up as is. + */ + +- grp = getgr_nam_gid(*list); ++ grp = getgr_nam_gid(list); + + /* + * There must be a match, either by GID value or by +@@ -1401,25 +1400,6 @@ + Prog); + fail_exit (1); + } +-#endif +- if (do_grp_update) { +- if (! gr_close ()) { +- fprintf (stderr, "%s: cannot rewrite group file\n", +- Prog); +- fail_exit (1); +- } +- (void) gr_unlock (); +-#ifdef SHADOWGRP +- if (is_shadow_grp && ! sgr_close ()) { +- fprintf (stderr, "%s: cannot rewrite shadow group file\n", +- Prog); +- fail_exit (1); +- } +- if (is_shadow_grp) +- sgr_unlock (); +-#endif +- } +-#ifdef SHADOWPWD + if (is_shadow_pwd) + spw_unlock (); + #endif +@@ -1758,7 +1738,6 @@ + /* + * Write out the new group file entry. + */ +- + if (! gr_update (&grp)) { + fprintf (stderr, "%s: error adding new group entry\n", Prog); + fail_exit (10); +@@ -1801,6 +1780,8 @@ + #endif /* SHADOWGRP */ + SYSLOG((LOG_INFO, "new group: name=%s, gid=%d\n", + user_name, user_gid)); ++ /* we need to remeber we have to close the group file... */ ++ do_grp_update++; + } + + /* +--- shadow-970616/src/Makefile.in.fix Sun Jun 15 20:05:08 1997 ++++ shadow-970616/src/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -251,12 +251,6 @@ + default: all + + +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status +- + mostlyclean-usbinPROGRAMS: + + clean-usbinPROGRAMS: +--- shadow-970616/contrib/Makefile.in.fix Sun Jun 15 20:05:09 1997 ++++ shadow-970616/contrib/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -60,12 +60,6 @@ + TAR = tar + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + tags: TAGS + TAGS: + +--- shadow-970616/debian/Makefile.in.fix Sun Jun 15 20:05:09 1997 ++++ shadow-970616/debian/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -64,12 +64,6 @@ + TAR = tar + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + tags: TAGS + TAGS: + +--- shadow-970616/doc/Makefile.in.fix Sun Jun 15 20:05:09 1997 ++++ shadow-970616/doc/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -61,12 +61,6 @@ + TAR = tar + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + tags: TAGS + TAGS: + +--- shadow-970616/etc/Makefile.in.fix Sun Jun 15 20:05:09 1997 ++++ shadow-970616/etc/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -60,12 +60,6 @@ + TAR = tar + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + tags: TAGS + TAGS: + +--- shadow-970616/old/Makefile.in.fix Sun Jun 15 20:05:10 1997 ++++ shadow-970616/old/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -61,12 +61,6 @@ + TAR = tar + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + tags: TAGS + TAGS: + +--- shadow-970616/shlib/Makefile.in.fix Sun Jun 15 20:05:10 1997 ++++ shadow-970616/shlib/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -60,11 +60,6 @@ + default: all + + +-$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in +- cd $(top_srcdir) && automake $(subdir)/Makefile +- +-Makefile: $(top_builddir)/config.status Makefile.in +- cd $(top_builddir) && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= ./config.status + tags: TAGS + TAGS: + +--- shadow-970616/configure.in.fix Sun Jun 15 19:42:47 1997 ++++ shadow-970616/configure.in Tue Dec 30 14:09:29 1997 +@@ -38,7 +38,7 @@ + AC_CHECK_HEADERS(gshadow.h shadow.h lastlog.h) + + AC_EGREP_HEADER(ut_host, utmp.h, AC_DEFINE(UT_HOST)) +-AC_EGREP_HEADER(ut_name, utmp.h, AC_DEFINE(UT_USER, ut_name)) ++AC_EGREP_HEADER(ut_user, utmp.h, AC_DEFINE(UT_USER, ut_user)) + AC_EGREP_HEADER(ll_host, lastlog.h, AC_DEFINE(HAVE_LL_HOST)) + + dnl Checks for typedefs, structures, and compiler characteristics. +--- shadow-970616/Makefile.in.fix Sun Jun 15 20:05:08 1997 ++++ shadow-970616/Makefile.in Tue Dec 30 14:09:29 1997 +@@ -64,28 +64,6 @@ + TAR = tar + default: all + +- +-$(srcdir)/Makefile.in: Makefile.am configure.in +- cd $(srcdir) && automake Makefile +- +-# For an explanation of the following Makefile rules, see node +-# `Automatic Remaking' in GNU Autoconf documentation. +-Makefile: Makefile.in config.status +- CONFIG_FILES=$@ CONFIG_HEADERS= ./config.status +-config.status: configure +- ./config.status --recheck +-$(srcdir)/configure: configure.in $(ACLOCAL) $(CONFIGURE_DEPENDENCIES) +- cd $(srcdir) && autoconf +- +-$(CONFIG_HEADER): stamp-h +-stamp-h: $(CONFIG_HEADER_IN) config.status +- CONFIG_FILES= CONFIG_HEADERS=$(CONFIG_HEADER) ./config.status +- @echo timestamp > stamp-h +-$(srcdir)/$(CONFIG_HEADER_IN): stamp-h.in +-$(srcdir)/stamp-h.in: configure.in $(ACLOCAL) $(ACCONFIG) $(CONFIG_TOP) $(CONFIG_BOT) +- cd $(srcdir) && autoheader +- echo timestamp > $(srcdir)/stamp-h.in +- + # This directory's subdirectories are mostly independent; you can cd + # into them and run `make' without going through this Makefile. + # To change the values of `make' variables: instead of editing Makefiles, diff --git a/redhat/shadow-970616-glibc.patch b/redhat/shadow-970616-glibc.patch new file mode 100644 index 00000000..ecd7039e --- /dev/null +++ b/redhat/shadow-970616-glibc.patch @@ -0,0 +1,11 @@ +--- shadow-970616/libmisc/strtoday.c.ewt Thu Nov 13 19:25:25 1997 ++++ shadow-970616/libmisc/strtoday.c Thu Nov 13 19:27:57 1997 +@@ -28,7 +28,7 @@ + */ + + #if !defined(__GLIBC__) +-#define _XOPEN_SOURCE ++#define _XOPEN_SOURCE 500 + #endif + + #include diff --git a/redhat/shadow-970616-rh.patch b/redhat/shadow-970616-rh.patch new file mode 100644 index 00000000..3b3e34d3 --- /dev/null +++ b/redhat/shadow-970616-rh.patch @@ -0,0 +1,1242 @@ +--- shadow-970616/man/shadowconfig.8.rh Thu May 1 14:18:17 1997 ++++ shadow-970616/man/shadowconfig.8 Fri Dec 12 15:36:29 1997 +@@ -14,7 +14,3 @@ + will print an error message and exit with a nonzero code if it finds + anything awry. If that happens, you should correct the error and run + it again. +-.PP +-Read +-.I /usr/doc/passwd/README.debian.gz +-for a brief introduction to shadow passwords and related features. +--- shadow-970616/man/useradd.8.rh Thu May 1 19:15:12 1997 ++++ shadow-970616/man/useradd.8 Fri Dec 12 15:36:29 1997 +@@ -50,13 +50,15 @@ + .RB [ -G + .IR group [,...]] + .RB [ -m " [" -k +-.IR skeleton_dir ]] ++.IR skeleton_dir ] " |" " " -M ] + .RB [ -s + .IR shell ] + .br + .RB [ -u + .IR uid " [" + .BR -o ]] ++.RB [ -n ] ++.RB [ -r ] + .I login + .TP 8 + .B useradd +@@ -81,6 +83,8 @@ + The new user account will be entered into the system files as needed, + the home directory will be created, and initial files copied, depending + on the command line options. ++The version provided with Red Hat Linux will create a group for each ++user added to the system, unless \fB-n\fR option is given. + The options which apply to the \fBuseradd\fR command are + .IP "\fB-A {\fImethod\fR|\fBDEFAULT\fR},..." + The value of the user's authentication method. +@@ -128,6 +132,21 @@ + option. + The default is to not create the directory and to not copy any + files. ++.IP \fB-M\fR ++The user home directory will not be created, even if the system ++wide settings from \fI/etc/login.defs\fR is to create home dirs. ++.IP \fB-n\fR ++A group having the same name as the user being added to the system ++will be created by default. This option will turn off this Red Hat ++Linux specific behavior. ++.IP \fB-r\fR ++This flag is used to create a system account. That is, an user with an ++UID lower than value of UID_MIN defined in \fI/etc/login.defs\fR. Note ++that \fBuseradd\fR will not create a home directory for such an user, ++regardless of the default setting in \fI/etc/login.defs\fR. ++You have to specify \fB-m\fR option if you want a home directory ++for a system account to be created. ++This is an option added by Red Hat. + .IP "\fB-s \fIshell\fR" + The name of the user's login shell. + The default is to leave this field blank, which causes the system +@@ -168,19 +187,24 @@ + .SH NOTES + The system administrator is responsible for placing the default + user files in the \fI/etc/skel\fR directory. ++.br ++This version of useradd was modified by Red Hat to suit Red Hat ++user/group convention. + .SH CAVEATS + You may not add a user to an NIS group. + This must be performed on the NIS server. + .SH FILES +-/etc/passwd \- user account information ++\fB/etc/passwd\fR \- user account information ++.br ++\fB/etc/shadow\fR \- secure user account information + .br +-/etc/shadow \- secure user account information ++\fB/etc/group\fR \- group information + .br +-/etc/group \- group information ++\fB/etc/default/useradd\fR \- default information + .br +-/etc/default/useradd \- default information ++\fB/etc/login.defs\fR \- system-wide settings + .br +-/etc/skel \- directory containing default files ++\fB/etc/skel\fR \- directory containing default files + .SH SEE ALSO + .BR chfn (1), + .BR chsh (1), +--- shadow-970616/man/groupadd.8.rh Thu May 1 19:15:06 1997 ++++ shadow-970616/man/groupadd.8 Fri Dec 12 15:36:29 1997 +@@ -32,7 +32,7 @@ + groupadd \- Create a new group + .SH SYNOPSIS + .B groupadd +-[\fB-g\fI gid \fR[\fB-o\fR]] ++[\fB-g\fI gid \fR[\fB-o\fR]] [\fB-r\fR] [\fB-f\fR] + .I group + .SH DESCRIPTION + The \fBgroupadd\fR command +@@ -44,9 +44,29 @@ + The numerical value of the group's ID. + This value must be unique, unless the \fB-o\fR option is used. + The value must be non-negative. +-The default is to use the smallest ID value greater than 99 and ++The default is to use the smallest ID value greater than 500 and + greater than every other group. +-Values between 0 and 99 are typically reserved for system accounts. ++Values between 0 and 499 are typically reserved for \fIsystem accounts\fR. ++.IP \fB-r\fR ++This flag instructs \fBgroupadd\fR to add a \fIsystem ++account\fR. First available \fIgid\fR lower than 499 will be ++automatically selected unless \fB-g\fR option is given also on the ++command line. ++.br ++This is an option added by Red Hat Software. ++.IP \fB-f\fR ++This is \fIforce\fR flag. This will stop \fBgroupadd\fR exit with ++error when the group about to be added already exists on the ++system. If that is the case, the group won't be altered (or added ++again, for that matter). ++.br ++This option also modifies the way \fB-g\fR option works. When you ++request a \fIgid\fR that it is not unique and you don't give \fB-o\fR ++option too, the group creation will fall back to the standard behavior ++(adding a group as neither \fB-g\fR or \fB-o\fR options were ++specified). ++.br ++This is an option added by Red Hat Software. + .SH FILES + /etc/group \- group account information + .br +--- shadow-970616/lib/getdef.c.rh Thu May 1 19:14:40 1997 ++++ shadow-970616/lib/getdef.c Fri Dec 12 15:36:29 1997 +@@ -61,6 +61,7 @@ + #ifdef HAVE_LIBCRACK + { "CRACKLIB_DICTPATH", NULL }, + #endif ++ { "CREATE_HOME", NULL }, + { "DEFAULT_HOME", NULL }, + { "DIALUPS_CHECK_ENAB", NULL }, + { "ENVIRON_FILE", NULL }, +@@ -171,7 +172,7 @@ + if ((d = def_find(item)) == NULL || d->value == NULL) + return 0; + +- return (strcmp(d->value, "yes") == 0); ++ return (strcasecmp(d->value, "yes") == 0); + } + + +--- shadow-970616/src/useradd.c.rh Sun Jun 1 01:25:40 1997 ++++ shadow-970616/src/useradd.c Fri Dec 12 15:58:04 1997 +@@ -60,7 +60,7 @@ + #define USER_DEFAULTS_FILE "/etc/default/useradd" + #define NEW_USER_FILE "/etc/default/nuaddXXXXXX" + #endif +- ++ + /* + * Needed for MkLinux DR1/2/2.1 - J. + */ +@@ -71,22 +71,22 @@ + /* + * These defaults are used if there is no defaults file. + */ +-static gid_t def_group = 1; ++static gid_t def_group = 100; + static char *def_gname = "other"; + static char *def_home = "/home"; +-static char *def_shell = ""; ++static char *def_shell = "/dev/null"; + static char *def_template = SKEL_DIR; + #ifdef SHADOWPWD + static long def_inactive = -1; + static char *def_expire = ""; + #endif + +-static char def_file[] = USER_DEFAULTS_FILE; ++static char def_file[] = USER_DEFAULTS_FILE; + + #define VALID(s) (strcspn (s, ":\n") == strlen (s)) + + static char *user_name = ""; +-static char *user_pass = "!"; ++static char *user_pass = "!!"; + static uid_t user_id; + static gid_t user_gid; + static char *user_comment = ""; +@@ -114,10 +114,13 @@ + sflg = 0, /* shell program for new account */ + cflg = 0, /* comment (GECOS) field for new account */ + mflg = 0, /* create user's home directory if it doesn't exist */ +- kflg = 0, /* specify a directory to fill new user directory */ ++ Mflg = 0, /* do NOT create user's home directory no matter what */ ++ kflg = 0, /* specify a directory to fill new user directory */ + fflg = 0, /* days until account with expired password is locked */ + eflg = 0, /* days since 1970-01-01 when account is locked */ +- Dflg = 0; /* set/show new user default values */ ++ Dflg = 0, /* set/show new user default values */ ++ nflg = 0, /* do not add a group for this user */ ++ rflg = 0; /* create a system account */ + + #ifdef AUTH_METHODS + static int Aflg = 0; /* specify authentication method for user */ +@@ -168,6 +171,7 @@ + * exit status values + */ + #define E_SUCCESS 0 /* success */ ++#define E_LOCKING 1 /* locking error */ + #define E_USAGE 2 /* bad command syntax */ + #define E_BAD_ARG 3 /* invalid argument to option */ + #define E_UID_IN_USE 4 /* uid already in use (and no -o) */ +@@ -177,19 +181,19 @@ + #define E_HOMEDIR 12 /* can't create home directory */ + + #ifdef SVR4 +-#define DGROUP "defgroup=" +-#define HOME "defparent=" +-#define SHELL "defshell=" +-#define INACT "definact=" +-#define EXPIRE "defexpire=" +-#define SKEL "defskel=" ++#define DGROUP "defgroup=" ++#define HOME "defparent=" ++#define SHELL "defshell=" ++#define INACT "definact=" ++#define EXPIRE "defexpire=" ++#define SKEL "defskel=" + #else +-#define DGROUP "GROUP=" +-#define HOME "HOME=" +-#define SHELL "SHELL=" +-#define INACT "INACTIVE=" +-#define EXPIRE "EXPIRE=" +-#define SKEL "SKEL=" ++#define DGROUP "GROUP=" ++#define HOME "HOME=" ++#define SHELL "SHELL=" ++#define INACT "INACTIVE=" ++#define EXPIRE "EXPIRE=" ++#define SKEL "SKEL=" + #endif + + /* +@@ -679,7 +683,7 @@ + #ifdef AUTH_METHODS + fprintf(stderr, "[-A program] "); + #endif +- fprintf(stderr, "[-p passwd] name\n"); ++ fprintf(stderr, "[-p passwd] [-n] [-r] name\n"); + + fprintf(stderr, " %s\t-D [-g group] [-b base] [-s shell]" + #ifdef SHADOWPWD +@@ -771,153 +775,129 @@ + static void + grp_update() + { +- const struct group *grp; +- struct group *ngrp; ++ const struct group *grp; ++ struct group *ngrp; + #ifdef SHADOWGRP +- const struct sgrp *sgrp; +- struct sgrp *nsgrp; ++ const struct sgrp *sgrp; ++ struct sgrp *nsgrp; + #endif + +- /* +- * Lock and open the group file. This will load all of the group +- * entries. +- */ ++ /* ++ * Scan through the entire group file looking for the groups that ++ * the user is a member of. ++ */ + +- if (! gr_lock ()) { +- fprintf (stderr, "%s: error locking group file\n", Prog); +- exit (1); +- } +- if (! gr_open (O_RDWR)) { +- fprintf (stderr, "%s: error opening group file\n", Prog); +- exit (1); +- } +-#ifdef SHADOWGRP +- if (is_shadow_grp && ! sgr_lock ()) { +- fprintf (stderr, "%s: error locking shadow group file\n", Prog); +- exit (1); +- } +- if (is_shadow_grp && ! sgr_open (O_RDWR)) { +- fprintf (stderr, "%s: error opening shadow group file\n", Prog); +- exit (1); +- } +-#endif ++ for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) { + + /* +- * Scan through the entire group file looking for the groups that +- * the user is a member of. ++ * See if the user specified this group as one of their ++ * concurrent groups. + */ + +- for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) { ++ if (!is_on_list(user_groups, grp->gr_name)) ++ continue; + +- /* +- * See if the user specified this group as one of their +- * concurrent groups. +- */ +- +- if (!is_on_list(user_groups, grp->gr_name)) +- continue; +- +- /* +- * Make a copy - gr_update() will free() everything +- * from the old entry, and we need it later. +- */ ++ /* ++ * Make a copy - gr_update() will free() everything ++ * from the old entry, and we need it later. ++ */ + +- ngrp = __gr_dup(grp); +- if (!ngrp) { +- exit(13); /* XXX */ +- } ++ ngrp = __gr_dup(grp); ++ if (!ngrp) { ++ exit(13); /* XXX */ ++ } + +- /* +- * Add the username to the list of group members and +- * update the group entry to reflect the change. +- */ ++ /* ++ * Add the username to the list of group members and ++ * update the group entry to reflect the change. ++ */ + +- ngrp->gr_mem = add_list (ngrp->gr_mem, user_name); +- if (! gr_update (ngrp)) { +- fprintf (stderr, "%s: error adding new group entry\n", +- Prog); +- fail_exit (1); +- } ++ ngrp->gr_mem = add_list (ngrp->gr_mem, user_name); ++ if (! gr_update (ngrp)) { ++ fprintf (stderr, "%s: error adding new group entry\n", ++ Prog); ++ fail_exit (1); ++ } + #ifdef NDBM +- /* +- * Update the DBM group file with the new entry as well. +- */ ++ /* ++ * Update the DBM group file with the new entry as well. ++ */ + +- if (! gr_dbm_update (ngrp)) { +- fprintf (stderr, "%s: cannot add new dbm group entry\n", +- Prog); +- fail_exit (1); +- } else +- gr_dbm_added++; +-#endif +- SYSLOG((LOG_INFO, "add `%s' to group `%s'\n", +- user_name, ngrp->gr_name)); +- } ++ if (! gr_dbm_update (ngrp)) { ++ fprintf (stderr, "%s: cannot add new dbm group entry\n", ++ Prog); ++ fail_exit (1); ++ } else ++ gr_dbm_added++; ++#endif ++ SYSLOG((LOG_INFO, "add `%s' to group `%s'\n", ++ user_name, ngrp->gr_name)); ++ } + #ifdef NDBM +- endgrent (); ++ endgrent (); + #endif + + #ifdef SHADOWGRP +- if (!is_shadow_grp) +- return; ++ if (!is_shadow_grp) ++ return; + +- /* +- * Scan through the entire shadow group file looking for the groups +- * that the user is a member of. The administrative list isn't +- * modified. +- */ ++ /* ++ * Scan through the entire shadow group file looking for the groups ++ * that the user is a member of. The administrative list isn't ++ * modified. ++ */ + +- for (sgr_rewind (), sgrp = sgr_next ();sgrp;sgrp = sgr_next ()) { ++ for (sgr_rewind (), sgrp = sgr_next ();sgrp;sgrp = sgr_next ()) { + +- /* +- * See if the user specified this group as one of their +- * concurrent groups. +- */ ++ /* ++ * See if the user specified this group as one of their ++ * concurrent groups. ++ */ + +- if (!gr_locate(sgrp->sg_name)) +- continue; ++ if (!gr_locate(sgrp->sg_name)) ++ continue; + +- if (!is_on_list(user_groups, sgrp->sg_name)) +- continue; ++ if (!is_on_list(user_groups, sgrp->sg_name)) ++ continue; + +- /* +- * Make a copy - sgr_update() will free() everything +- * from the old entry, and we need it later. +- */ ++ /* ++ * Make a copy - sgr_update() will free() everything ++ * from the old entry, and we need it later. ++ */ + +- nsgrp = __sgr_dup(sgrp); +- if (!nsgrp) { +- exit(13); /* XXX */ +- } ++ nsgrp = __sgr_dup(sgrp); ++ if (!nsgrp) { ++ exit(13); /* XXX */ ++ } + +- /* +- * Add the username to the list of group members and +- * update the group entry to reflect the change. +- */ ++ /* ++ * Add the username to the list of group members and ++ * update the group entry to reflect the change. ++ */ + +- nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_name); +- if (! sgr_update (nsgrp)) { +- fprintf (stderr, "%s: error adding new group entry\n", +- Prog); +- fail_exit (1); +- } ++ nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_name); ++ if (! sgr_update (nsgrp)) { ++ fprintf (stderr, "%s: error adding new group entry\n", ++ Prog); ++ fail_exit (1); ++ } + #ifdef NDBM +- /* +- * Update the DBM group file with the new entry as well. +- */ ++ /* ++ * Update the DBM group file with the new entry as well. ++ */ + +- if (! sg_dbm_update (nsgrp)) { +- fprintf (stderr, "%s: cannot add new dbm group entry\n", +- Prog); +- fail_exit (1); +- } else +- sg_dbm_added++; ++ if (! sg_dbm_update (nsgrp)) { ++ fprintf (stderr, "%s: cannot add new dbm group entry\n", ++ Prog); ++ fail_exit (1); ++ } else ++ sg_dbm_added++; + #endif /* NDBM */ +- SYSLOG((LOG_INFO, "add `%s' to shadow group `%s'\n", +- user_name, nsgrp->sg_name)); +- } ++ SYSLOG((LOG_INFO, "add `%s' to shadow group `%s'\n", ++ user_name, nsgrp->sg_name)); ++ } + #ifdef NDBM +- endsgent (); ++ endsgent (); + #endif /* NDBM */ + #endif /* SHADOWGRP */ + } +@@ -936,8 +916,13 @@ + const struct passwd *pwd; + uid_t uid_min, uid_max; + +- uid_min = getdef_num("UID_MIN", 100); +- uid_max = getdef_num("UID_MAX", 60000); ++ if (!rflg) { ++ uid_min = getdef_num("UID_MIN", 500); ++ uid_max = getdef_num("UID_MAX", 60000); ++ } else { ++ uid_min = 1; ++ uid_max = 499; ++ } + + /* + * Start with some UID value if the user didn't provide us with +@@ -1003,6 +988,88 @@ + } + } + ++/* ++ * find_new_gid - find the next available GID ++ * ++ * find_new_gid() locates the next highest unused GID in the group ++ * file, or checks the given group ID against the existing ones for ++ * uniqueness. ++ */ ++ ++static void ++find_new_gid() ++{ ++ const struct group *grp; ++ gid_t gid_min, gid_max; ++ ++ if (!rflg) { ++ gid_min = getdef_num("GID_MIN", 500); ++ gid_max = getdef_num("GID_MAX", 60000); ++ } else { ++ gid_min = 1; ++ gid_max = 499; ++ } ++ ++ /* ++ * Start with some GID value if the user didn't provide us with ++ * one already. ++ */ ++ ++ user_gid = gid_min; ++ ++ /* ++ * Search the entire group file, either looking for this ++ * GID (if the user specified one with -g) or looking for the ++ * largest unused value. ++ */ ++ ++#ifdef NO_GETGRENT ++ gr_rewind(); ++ while ((grp = gr_next())) ++#else ++ setgrent(); ++ while ((grp = getgrent())) ++#endif ++ { ++ if (strcmp(user_name, grp->gr_name) == 0) { ++ user_gid = grp->gr_gid; ++ return; ++ } ++ if (grp->gr_gid >= user_gid) { ++ if (grp->gr_gid > gid_max) ++ continue; ++ user_gid = grp->gr_gid + 1; ++ } ++ } ++#ifndef NO_GETGRENT /* RH Linux does have this, so ... */ ++ /* A quick test gets here: if the UID is available ++ * as a GID, go ahead and use it */ ++ if (!getgrgid(user_id)) { ++ user_gid = user_id; ++ return; ++ } ++#endif ++ if (user_gid == gid_max + 1) { ++ for (user_gid = gid_min; user_gid < gid_max; user_gid++) { ++#ifdef NO_GETGRENT ++ gr_rewind(); ++ while ((grp = gr_next()) && grp->gr_gid != user_gid) ++ ; ++ if (!grp) ++ break; ++#else ++ if (!getgrgid(user_gid)) ++ break; ++#endif ++ } ++ if (user_gid == gid_max) { ++ fprintf(stderr, "%s: can't get unique gid (run out of GIDs)\n", ++ Prog); ++ fail_exit(4); ++ } ++ } ++} ++ + #ifdef AUTH_METHODS + /* + * convert_auth - convert the argument list to a authentication list +@@ -1099,9 +1166,9 @@ + int arg; + + #ifdef SHADOWPWD +-#define FLAGS "A:Du:og:G:d:s:c:mk:p:f:e:b:" ++#define FLAGS "A:Du:og:G:d:s:c:mMk:p:f:e:b:nr" + #else +-#define FLAGS "A:Du:og:G:d:s:c:mk:p:b:" ++#define FLAGS "A:Du:og:G:d:s:c:mMk:p:b:nr" + #endif + while ((arg = getopt(argc, argv, FLAGS)) != EOF) { + #undef FLAGS +@@ -1251,6 +1318,15 @@ + user_id = get_number(optarg); + uflg++; + break; ++ case 'n': ++ nflg++; ++ break; ++ case 'r': ++ rflg++; ++ break; ++ case 'M': ++ Mflg++; ++ break; + default: + usage (); + } +@@ -1261,9 +1337,12 @@ + * Certain options are only valid in combination with others. + * Check it here so that they can be specified in any order. + */ +- if ((oflg && !uflg) || (kflg && !mflg)) ++ if (kflg && !mflg) + usage(); + ++ if (mflg && Mflg) /* the admin is not decided .. create or not ? */ ++ usage(); ++ + /* + * Either -D or username is required. Defaults can be set with -D + * for the -b, -e, -f, -g, -s options only. +@@ -1312,39 +1391,53 @@ + static void + close_files() + { +- if (! pw_close ()) { +- fprintf (stderr, "%s: cannot rewrite password file\n", Prog); +- fail_exit (1); +- } ++ if (! pw_close ()) { ++ fprintf (stderr, "%s: cannot rewrite password file\n", Prog); ++ fail_exit (1); ++ } + #ifdef SHADOWPWD +- if (is_shadow_pwd && ! spw_close ()) { +- fprintf (stderr, "%s: cannot rewrite shadow password file\n", +- Prog); +- fail_exit (1); ++ if (is_shadow_pwd && ! spw_close ()) { ++ fprintf (stderr, "%s: cannot rewrite shadow password file\n", ++ Prog); ++ fail_exit (1); ++ } ++#endif ++ if (do_grp_update) { ++ if (! gr_close ()) { ++ fprintf (stderr, "%s: cannot rewrite group file\n", ++ Prog); ++ fail_exit (1); + } +-#endif +- if (do_grp_update) { +- if (! gr_close ()) { +- fprintf (stderr, "%s: cannot rewrite group file\n", +- Prog); +- fail_exit (1); +- } +- (void) gr_unlock (); ++ (void) gr_unlock (); + #ifdef SHADOWGRP +- if (is_shadow_grp && ! sgr_close ()) { +- fprintf (stderr, "%s: cannot rewrite shadow group file\n", +- Prog); +- fail_exit (1); +- } +- if (is_shadow_grp) +- sgr_unlock (); +-#endif ++ if (is_shadow_grp && ! sgr_close ()) { ++ fprintf (stderr, "%s: cannot rewrite shadow group file\n", ++ Prog); ++ fail_exit (1); + } ++ if (is_shadow_grp) ++ sgr_unlock (); ++#endif ++ } + #ifdef SHADOWPWD +- if (is_shadow_pwd) +- spw_unlock (); ++ if (is_shadow_pwd) ++ spw_unlock (); + #endif +- (void) pw_unlock (); ++ (void) pw_unlock (); ++ if (! gr_close ()) { ++ fprintf (stderr, "%s: cannot rewrite group file\n", Prog); ++ fail_exit (10); ++ } ++ (void) gr_unlock (); ++#ifdef SHADOWGRP ++ if (is_shadow_grp && ! sgr_close ()) { ++ fprintf (stderr, "%s: cannot rewrite shadow group file\n", ++ Prog); ++ fail_exit (10); ++ } ++ if (is_shadow_grp) ++ sgr_unlock (); ++#endif /* SHADOWGRP */ + } + + /* +@@ -1353,27 +1446,47 @@ + * open_files() opens the two password files. + */ + +-static void +-open_files() ++static void open_files(void) + { +- if (!pw_lock_first()) { +- fprintf (stderr, "%s: unable to lock password file\n", Prog); +- exit (1); +- } +- if (! pw_open (O_RDWR)) { +- fprintf (stderr, "%s: unable to open password file\n", Prog); +- exit (1); +- } ++ if (!pw_lock_first()) { ++ fprintf (stderr, "%s: unable to lock password file\n", Prog); ++ exit (1); ++ } ++ if (! pw_open (O_RDWR)) { ++ fprintf (stderr, "%s: unable to open password file\n", Prog); ++ exit (1); ++ } + #ifdef SHADOWPWD +- if (is_shadow_pwd && ! spw_lock ()) { +- fprintf (stderr, "%s: cannot lock shadow password file\n", Prog); +- exit (1); +- } +- if (is_shadow_pwd && ! spw_open (O_RDWR)) { +- fprintf (stderr, "%s: cannot open shadow password file\n", Prog); +- exit (1); +- } +-#endif ++ if (is_shadow_pwd && ! spw_lock ()) { ++ fprintf (stderr, "%s: cannot lock shadow password file\n", Prog); ++ exit (1); ++ } ++ if (is_shadow_pwd && ! spw_open (O_RDWR)) { ++ fprintf (stderr, "%s: cannot open shadow password file\n", Prog); ++ exit (1); ++ } ++#endif ++ if (! gr_lock ()) { ++ fprintf (stderr, "%s: unable to lock group file\n", Prog); ++ exit (E_LOCKING); ++ } ++ if (! gr_open (O_RDWR)) { ++ fprintf (stderr, "%s: unable to open group file\n", Prog); ++ fail_exit (10); ++ } ++#ifdef SHADOWGRP ++ if (is_shadow_grp && ! sgr_lock ()) { ++ fprintf (stderr, "%s: unable to lock shadow group file\n", ++ Prog); ++ fail_exit (E_LOCKING); ++ } ++ if (is_shadow_grp && ! sgr_open (O_RDWR)) { ++ fprintf (stderr, "%s: unable to open shadow group file\n", ++ Prog); ++ fail_exit (10); ++ } ++#endif /* SHADOWGRP*/ ++ + } + + +@@ -1424,9 +1537,6 @@ + struct spwd spent; + #endif + +- if (! oflg) +- find_new_uid (); +- + #ifdef AUTH_METHODS + if (Aflg) { + convert_auth(user_auth, auth_arg); +@@ -1582,6 +1692,117 @@ + } + } + ++/* a fake something */ ++static char *empty_list = NULL; ++ ++/* ++ * new_grent - initialize the values in a group file entry ++ * ++ * new_grent() takes all of the values that have been entered and ++ * fills in a (struct group) with them. ++ */ ++ ++static void ++new_grent(grent) ++ struct group *grent; ++{ ++ bzero ((char *) grent, sizeof *grent); ++ grent->gr_name = user_name; ++ grent->gr_passwd = "x"; ++ grent->gr_gid = user_gid; ++ grent->gr_mem = &empty_list; ++} ++ ++#ifdef SHADOWGRP ++/* ++ * new_sgent - initialize the values in a shadow group file entry ++ * ++ * new_sgent() takes all of the values that have been entered and ++ * fills in a (struct sgrp) with them. ++ */ ++ ++static void ++new_sgent(sgent) ++ struct sgrp *sgent; ++{ ++ bzero ((char *) sgent, sizeof *sgent); ++ sgent->sg_name = user_name; ++ sgent->sg_passwd = "!"; ++ sgent->sg_adm = &empty_list; ++ sgent->sg_mem = &empty_list; ++} ++#endif /* SHADOWGRP */ ++ ++/* ++ * grp_update - add new group file entries ++ * ++ * grp_update() writes the new records to the group files. ++ */ ++ ++static void grp_add() ++{ ++ struct group grp; ++#ifdef SHADOWGRP ++ struct sgrp sgrp; ++#endif /* SHADOWGRP */ ++ ++ /* ++ * Create the initial entries for this new group. ++ */ ++ ++ new_grent (&grp); ++#ifdef SHADOWGRP ++ new_sgent (&sgrp); ++#endif /* SHADOWGRP */ ++ ++ /* ++ * Write out the new group file entry. ++ */ ++ ++ if (! gr_update (&grp)) { ++ fprintf (stderr, "%s: error adding new group entry\n", Prog); ++ fail_exit (10); ++ } ++#ifdef NDBM ++ ++ /* ++ * Update the DBM group file with the new entry as well. ++ */ ++ ++ if (gr_dbm_present() && ! gr_dbm_update (&grp)) { ++ fprintf (stderr, "%s: cannot add new dbm group entry\n", Prog); ++ fail_exit (10); ++ } ++ endgrent (); ++#endif /* NDBM */ ++ ++#ifdef SHADOWGRP ++ ++ /* ++ * Write out the new shadow group entries as well. ++ */ ++ ++ if (is_shadow_grp && ! sgr_update (&sgrp)) { ++ fprintf (stderr, "%s: error adding new group entry\n", Prog); ++ fail_exit (10); ++ } ++#ifdef NDBM ++ ++ /* ++ * Update the DBM group file with the new entry as well. ++ */ ++ ++ if (is_shadow_grp && sg_dbm_present() && ! sg_dbm_update (&sgrp)) { ++ fprintf (stderr, "%s: cannot add new dbm group entry\n", Prog); ++ fail_exit (10); ++ } ++ endsgent (); ++#endif /* NDBM */ ++#endif /* SHADOWGRP */ ++ SYSLOG((LOG_INFO, "new group: name=%s, gid=%d\n", ++ user_name, user_gid)); ++} ++ + /* + * main - useradd command + */ +@@ -1591,76 +1812,100 @@ + int argc; + char **argv; + { +- /* +- * Get my name so that I can use it to report errors. +- */ ++ /* ++ * Get my name so that I can use it to report errors. ++ */ + +- Prog = Basename(argv[0]); ++ Prog = Basename(argv[0]); + +- openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); ++ openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + #ifdef SHADOWPWD +- is_shadow_pwd = (access(SHADOW_FILE, 0) == 0); ++ is_shadow_pwd = (access(SHADOW_FILE, 0) == 0); + #endif + #ifdef SHADOWGRP +- is_shadow_grp = (access(SGROUP_FILE, 0) == 0); ++ is_shadow_grp = (access(SGROUP_FILE, 0) == 0); + #endif + +- /* +- * The open routines for the NDBM files don't use read-write +- * as the mode, so we have to clue them in. +- */ ++ /* ++ * The open routines for the NDBM files don't use read-write ++ * as the mode, so we have to clue them in. ++ */ + + #ifdef NDBM +- pw_dbm_mode = O_RDWR; ++ pw_dbm_mode = O_RDWR; + #ifdef SHADOWPWD +- sp_dbm_mode = O_RDWR; ++ sp_dbm_mode = O_RDWR; + #endif +- gr_dbm_mode = O_RDWR; ++ gr_dbm_mode = O_RDWR; + #ifdef SHADOWGRP +- sg_dbm_mode = O_RDWR; ++ sg_dbm_mode = O_RDWR; + #endif + #endif +- get_defaults(); ++ get_defaults(); + +- process_flags(argc, argv); ++ process_flags(argc, argv); + +- /* +- * See if we are messing with the defaults file, or creating +- * a new user. +- */ ++ if (!rflg) /* for system accounts defaults are ignored ++ * == do not create */ ++ if (getdef_bool("CREATE_HOME")) ++ mflg = 1; + +- if (Dflg) { +- if (gflg || bflg || fflg || eflg || sflg) +- exit (set_defaults () ? 1:0); ++ if (Mflg) /* absolutely sure that we do not create home dirs */ ++ mflg = 0; ++ /* ++ * See if we are messing with the defaults file, or creating ++ * a new user. ++ */ + +- show_defaults (); +- exit (0); +- } ++ if (Dflg) { ++ if (gflg || bflg || fflg || eflg || sflg) ++ exit (set_defaults () ? 1:0); + +- /* +- * Start with a quick check to see if the user exists. +- */ ++ show_defaults (); ++ exit (0); ++ } + +- if (getpwnam(user_name)) { +- fprintf(stderr, "%s: user %s exists\n", Prog, user_name); +- exit(E_NAME_IN_USE); +- } ++ /* ++ * Start with a quick check to see if the user exists. ++ */ + +- /* +- * Do the hard stuff - open the files, create the user entries, +- * create the home directory, then close and update the files. +- */ +- +- open_files (); ++ if (getpwnam(user_name)) { ++ if (!oflg) { ++ fprintf(stderr, "%s: user %s exists\n", Prog, user_name); ++ exit(E_NAME_IN_USE); ++ } else { ++ exit (E_SUCCESS); ++ } ++ } + +- usr_update (); ++ /* ++ * Do the hard stuff - open the files, create the user entries, ++ * create the home directory, then close and update the files. ++ */ ++ ++ open_files (); ++ ++ /* first, seek for a valid uid to use for this user. ++ * We do this because later we can use the uid we found as ++ * gid too ... --rh */ ++ if (! uflg) ++ find_new_uid (); ++ ++ /* do we have to add a group for that user ? */ ++ if (! (nflg || gflg)) { ++ find_new_gid(); ++ grp_add(); ++ } ++ ++ usr_update (); ++ ++ if (mflg) { ++ create_home (); ++ copy_tree (def_template, user_home, user_id, user_gid); ++ } ++ close_files (); + +- if (mflg) { +- create_home (); +- copy_tree (def_template, user_home, user_id, user_gid); +- } +- close_files (); +- exit(E_SUCCESS); +- /*NOTREACHED*/ ++ exit(E_SUCCESS); ++ /*NOTREACHED*/ + } +--- shadow-970616/src/groupadd.c.rh Thu May 1 19:07:11 1997 ++++ shadow-970616/src/groupadd.c Fri Dec 12 15:36:29 1997 +@@ -61,6 +61,11 @@ + oflg = 0, /* permit non-unique group ID to be specified with -g */ + gflg = 0; /* ID value for the new group */ + ++/* For adding "system" accounts */ ++static int system_flag = 0; ++static int force_flag = 0; ++#define MIN_GID 10 ++ + #ifdef NDBM + extern int gr_dbm_mode; + extern int sg_dbm_mode; +@@ -75,7 +80,7 @@ + static void + usage() + { +- fprintf (stderr, "usage: groupadd [-g gid [-o]] group\n"); ++ fprintf (stderr, "usage: groupadd [-g gid [-o]] [-r] [-f] group\n"); + exit (2); + } + +@@ -202,8 +207,13 @@ + const struct group *grp; + gid_t gid_min, gid_max; + +- gid_min = getdef_num("GID_MIN", 100); +- gid_max = getdef_num("GID_MAX", 60000); ++ if (!system_flag) { ++ gid_min = getdef_num("GID_MIN", 500); ++ gid_max = getdef_num("GID_MAX", 60000); ++ } else { ++ gid_min = MIN_GID; ++ gid_max = getdef_num("GID_MIN", 499); ++ } + + /* + * Start with some GID value if the user didn't provide us with +@@ -227,16 +237,34 @@ + while ((grp = getgrent())) { + #endif + if (strcmp(group_name, grp->gr_name) == 0) { ++ if (!force_flag) { + fprintf(stderr, "%s: name %s is not unique\n", + Prog, group_name); + fail_exit(9); ++ } else { ++ fail_exit(0); ++ } + } + if (gflg && group_id == grp->gr_gid) { ++ if (!force_flag) { + fprintf(stderr, "%s: gid %ld is not unique\n", + Prog, (long) group_id); + fail_exit(4); ++ } else { ++ /* we invalidate the gflg and search again */ ++ gflg = 0; ++ if (oflg) ++ oflg = 0; ++ /* now, start at the begining... */ ++#ifdef NO_GETGRENT ++ gr_rewind(); ++#else ++ setgrent(); ++#endif ++ continue; ++ } + } +- if (! gflg && grp->gr_gid >= group_id) { ++ if (!gflg && grp->gr_gid >= group_id) { + if (grp->gr_gid > gid_max) + continue; + group_id = grp->gr_gid + 1; +@@ -298,42 +326,49 @@ + process_flags(argc, argv) + int argc; + char **argv; +-{ +- extern int optind; +- extern char *optarg; +- char *end; +- int arg; ++ { ++ extern int optind; ++ extern char *optarg; ++ char *end; ++ int arg; + +- while ((arg = getopt (argc, argv, "og:")) != EOF) { ++ while ((arg = getopt (argc, argv, "og:rf")) != EOF) { + switch (arg) { +- case 'g': +- gflg++; +- if (! isdigit (optarg[0])) +- usage (); +- +- group_id = strtol (optarg, &end, 10); +- if (*end != '\0') { +- fprintf (stderr, "%s: invalid group %s\n", +- Prog, optarg); +- fail_exit (3); +- } +- break; +- case 'o': +- if (! gflg) +- usage (); +- +- oflg++; +- break; +- default: +- usage (); ++ case 'g': ++ gflg++; ++ if (! isdigit (optarg[0])) ++ usage (); ++ ++ group_id = strtol (optarg, &end, 10); ++ if (*end != '\0') { ++ fprintf (stderr, "%s: invalid group %s\n", ++ Prog, optarg); ++ fail_exit (3); ++ } ++ break; ++ case 'o': ++ if (! gflg) ++ usage (); ++ ++ oflg++; ++ break; ++ case 'r': /* "system" group */ ++ system_flag++; ++ break; ++ case 'f': /* "force" - don't exit with error if group already exist */ ++ force_flag++; ++ break; ++ ++ default: ++ usage (); + } +- } +- if (optind != argc - 1) ++ } ++ if (optind != argc - 1) + usage (); + +- group_name = argv[argc - 1]; +- check_new_name (); +-} ++ group_name = argv[argc - 1]; ++ check_new_name (); ++ } + + /* + * close_files - close all of the files that were opened +@@ -448,8 +483,12 @@ + */ + + if (getgrnam(group_name)) { ++ if ( !force_flag) { + fprintf (stderr, "%s: group %s exists\n", Prog, group_name); + exit(9); ++ } else { ++ exit(0); ++ } + } + + /* diff --git a/redhat/shadow-970616-utuser.patch b/redhat/shadow-970616-utuser.patch new file mode 100644 index 00000000..2c27cb25 --- /dev/null +++ b/redhat/shadow-970616-utuser.patch @@ -0,0 +1,12 @@ +--- shadow-970616/configure.in.ewt Thu Nov 13 16:43:25 1997 ++++ shadow-970616/configure.in Thu Nov 13 16:43:34 1997 +@@ -38,7 +38,8 @@ + AC_CHECK_HEADERS(gshadow.h shadow.h lastlog.h) + + AC_EGREP_HEADER(ut_host, utmp.h, AC_DEFINE(UT_HOST)) +-AC_EGREP_HEADER(ut_name, utmp.h, AC_DEFINE(UT_USER, ut_name)) ++AC_EGREP_HEADER(ut_name, utmp.h, AC_DEFINE(UT_USER, ut_user), ++ AC_EGREP_HEADER(ut_name, utmp.h, AC_DEFINE(UT_USER, ut_name))) + AC_EGREP_HEADER(ll_host, lastlog.h, AC_DEFINE(HAVE_LL_HOST)) + + dnl Checks for typedefs, structures, and compiler characteristics. diff --git a/redhat/shadow-970616.login.defs b/redhat/shadow-970616.login.defs new file mode 100644 index 00000000..6f578df7 --- /dev/null +++ b/redhat/shadow-970616.login.defs @@ -0,0 +1,57 @@ +# *REQUIRED* +# Directory where mailboxes reside, _or_ name of file, relative to the +# home directory. If you _do_ define both, MAIL_DIR takes precedence. +# QMAIL_DIR is for Qmail +# +#QMAIL_DIR Maildir +MAIL_DIR /var/spool/mail +#MAIL_FILE .mail + +# Password aging controls: +# +# PASS_MAX_DAYS Maximum number of days a password may be used. +# PASS_MIN_DAYS Minimum number of days allowed between password changes. +# PASS_MIN_LEN Minimum acceptable password length. +# PASS_WARN_AGE Number of days warning given before a password expires. +# +PASS_MAX_DAYS 99999 +PASS_MIN_DAYS 0 +PASS_MIN_LEN 5 +PASS_WARN_AGE 7 + +# +# Min/max values for automatic uid selection in useradd +# +UID_MIN 500 +UID_MAX 60000 + +# +# Min/max values for automatic gid selection in groupadd +# +GID_MIN 500 +GID_MAX 60000 + +# +# Require password before chfn/chsh can make any changes. +# +CHFN_AUTH yes + +# +# Don't allow users to change their "real name" using chfn. +# +CHFN_RESTRICT yes + +# +# If defined, this command is run when removing a user. +# It should remove any at/cron/print jobs etc. owned by +# the user to be removed (passed as the first argument). +# +#USERDEL_CMD /usr/sbin/userdel_local + +# +# If useradd should create home directories for users by default +# On RH systems, we do. This option is ORed with the -m flag on +# useradd command line. +# +CREATE_HOME yes + diff --git a/redhat/shadow-970616.useradd b/redhat/shadow-970616.useradd new file mode 100644 index 00000000..ae81dbb3 --- /dev/null +++ b/redhat/shadow-970616.useradd @@ -0,0 +1,7 @@ +# useradd defaults file +GROUP=100 +HOME=/home +INACTIVE=-1 +EXPIRE= +SHELL=/bin/bash +SKEL=/etc/skel diff --git a/redhat/shadow-utils-970616.spec b/redhat/shadow-utils-970616.spec new file mode 100644 index 00000000..4fc4dc1c --- /dev/null +++ b/redhat/shadow-utils-970616.spec @@ -0,0 +1,137 @@ +Summary: Shadow password file utilities for Linux +Name: shadow-utils +Version: 970616 +Release: 11 +Source0: ftp://ftp.ists.pwr.wroc.pl/pub/linux/shadow/beta/shadow-970616.tar.gz +Source1: shadow-970616.login.defs +Source2: shadow-970616.useradd +Patch0: shadow-970616-rh.patch +Patch1: shadow-970616-utuser.patch +Patch2: shadow-970616-glibc.patch +Patch3: shadow-970616-fix.patch +Copyright: BSD +Group: Utilities/System +BuildRoot: /var/tmp/shadow-utils +Obsoletes: adduser + +%changelog +* Tue Dec 30 1997 Cristian Gafton +- updated the spec file +- updated the patch so that new accounts created on shadowed system won't + confuse pam_pwdb anymore ('!!' default password instead on '!') +- fixed a bug that made useradd -G segfault +- the check for the ut_user is now patched into configure + +* Thu Nov 13 1997 Erik Troan +- added patch for XOPEN oddities in glibc headers +- check for ut_user before checking for ut_name -- this works around some + confusion on glibc 2.1 due to the utmpx header not defining the ut_name + compatibility stuff. I used a gross sed hack here because I couldn't make + automake work properly on the sparc (this could be a glibc 2.0.99 problem + though). The utuser patch works fine, but I don't apply it. +- sleep after running autoconf + +* Thu Nov 06 1997 Cristian Gafton +- added forgot lastlog command to the spec file + +* Mon Oct 26 1997 Cristian Gafton +- obsoletes adduser + +* Thu Oct 23 1997 Cristian Gafton +- modified groupadd; updated the patch + +* Fri Sep 12 1997 Cristian Gafton +- updated to 970616 +- changed useradd to meet RH specs +- fixed some bugs + +* Tue Jun 17 1997 Erik Troan +- built against glibc + +%description +This package includes the programs necessary to convert standard +UNIX password files to the shadow password format, as well as +programs for command-line management of the user's accounts. + - 'pwconv' converts everything to the shadow password format. + - 'pwunconv' unconverts from shadow passwords, generating a file + in the current directory called npasswd that is a standard UNIX + password file. + - 'pwck' checks the integrity of the password and shadow files. + - 'lastlog' prints out the last login times of all users. + - 'useradd', 'userdel' and 'usermod' for accounts management. + - 'groupadd', 'groupdel' and 'groupmod' for group management. + +A number of man pages are also included that relate to these utilities, +and shadow passwords in general. + +%prep +# This is just a few of the core utilities from the shadow suite... +# packaged up for use w/PAM +%setup -n shadow-970616 +%patch -p1 -b .rh +#%patch1 -p1 -b .utname +%patch2 -p1 -b .xopen +%patch3 -p1 -b .fix + +%build +autoheader +autoconf +sleep 2 +CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix=/usr +make + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/usr +make install prefix=/$RPM_BUILD_ROOT/usr +mkdir -p $RPM_BUILD_ROOT/etc/default +install -m 0600 -o root $RPM_SOURCE_DIR/shadow-970616.useradd $RPM_BUILD_ROOT/etc/default/useradd +install -m 0644 -o root $RPM_SOURCE_DIR/shadow-970616.login.defs $RPM_BUILD_ROOT/etc/login.defs +install -m 0500 -o root src/pwconv $RPM_BUILD_ROOT/usr/sbin +install -m 0500 -o root src/pwunconv $RPM_BUILD_ROOT/usr/sbin +ln -s pwconv $RPM_BUILD_ROOT/usr/sbin/pwconv5 +install -m 0644 -o root man/pw*conv.8 $RPM_BUILD_ROOT/usr/man/man8 +ln -s pwconv.8 $RPM_BUILD_ROOT/usr/man/man8/pwconv5.8 +ln -s useradd $RPM_BUILD_ROOT/usr/sbin/adduser +ln -s useradd.8 $RPM_BUILD_ROOT/usr/man/man8/adduser.8 + +%files +%doc doc/ANNOUNCE doc/CHANGES doc/HOWTO +%doc doc/LICENSE doc/README doc/README.linux +%dir /etc/default +/usr/sbin/adduser +/usr/sbin/useradd +/usr/sbin/usermod +/usr/sbin/userdel +/usr/sbin/groupadd +/usr/sbin/groupdel +/usr/sbin/groupmod +/usr/sbin/grpck +/usr/sbin/pwck +/usr/bin/chage +/usr/bin/gpasswd +/usr/sbin/lastlog +# /usr/sbin/vipw +/usr/sbin/chpasswd +/usr/sbin/newusers +/usr/sbin/pw*conv* +/usr/man/man1/chage.1 +/usr/man/man1/gpasswd.1 +/usr/man/man3/shadow.3 +/usr/man/man5/shadow.5 +/usr/man/man8/adduser.8 +/usr/man/man8/chpasswd.8 +/usr/man/man8/group*.8 +/usr/man/man8/user*.8 +/usr/man/man8/pwck.8 +/usr/man/man8/grpck.8 +/usr/man/man8/newusers.8 +# /usr/man/man8/shadowconfig.8 +/usr/man/man8/pw*conv*.8 +# /usr/man/man8/vipw.8 +/usr/man/man8/lastlog.8 +%config /etc/login.defs +%config /etc/default/useradd + +%clean +rm -rf $RPM_BUILD_ROOT diff --git a/redhat/shadow-utils.spec b/redhat/shadow-utils.spec new file mode 100644 index 00000000..388de43a --- /dev/null +++ b/redhat/shadow-utils.spec @@ -0,0 +1,151 @@ +# shadow-utils.spec generated automatically from shadow-utils.spec.in +# $Id: shadow-utils.spec.in,v 1.2 1999/06/07 16:40:45 marekm Exp $ +Summary: Shadow password file utilities for Linux +Name: shadow-utils +Version: 19990709 +Release: 1 +Copyright: Free +Group: Utilities/System +Source: ftp://ftp.ists.pwr.wroc.pl/pub/linux/shadow/shadow-19990709.tar.gz +BuildRoot: /var/tmp/shadow-utils +Packager: Timo Karjalainen +# Obsoletes: adduser + +%description +This package includes the programs necessary to convert traditional +V7 UNIX password files to the SVR4 shadow password format and additional +tools to work with shadow passwords. + - 'pwconv' converts everything to the shadow password format. + - 'pwunconv' converts back to non-shadow passwords. + - 'pwck' checks the integrity of the password and shadow files. + - 'lastlog' prints out the last login times of all users. + - 'useradd', 'userdel', 'usermod' to manage user accounts. + - 'groupadd', 'groupdel', 'groupmod' to manage groups. + +A number of man pages are also included that relate to these utilities, +and shadow passwords in general. + +%changelog + +* Sun Dec 14 1997 Marek Michalkiewicz + +- Lots of changes, see doc/CHANGES for more details + +* Sun Jun 08 1997 Timo Karjalainen + +- Initial release + +%prep +# This is just a few of the core utilities from the shadow suite... +# packaged up for use w/PAM +%setup -n shadow-19990709 + +%build +# shared lib support is untested, so... +CFLAGS="$RPM_OPT_FLAGS" ./configure --disable-shared --prefix=/usr --exec-prefix=/usr +make + +%install +if [ -d $RPM_BUILD_ROOT ] ; then + rm -rf $RPM_BUILD_ROOT +fi +mkdir -p $RPM_BUILD_ROOT/usr +# neato trick, heh ? :-) +./configure --prefix=$RPM_BUILD_ROOT/usr +make install +mkdir -p $RPM_BUILD_ROOT/etc/default + +# FIXME +#install -m 0600 -o root $RPM_SOURCE_DIR/shadow-970616.useradd $RPM_BUILD_ROOT/etc/default/useradd +#install -m 0644 -o root $RPM_SOURCE_DIR/shadow-970616.login.defs $RPM_BUILD_ROOT/etc/login.defs +#ln -s useradd $RPM_BUILD_ROOT/usr/sbin/adduser +#ln -s useradd.8 $RPM_BUILD_ROOT/usr/man/man8/adduser.8 + +#make prefix=$RPM_BUILD_ROOT/usr exec_prefix=$RPM_BUILD_ROOT/usr install +#touch $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} +#chmod 640 $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} +#chown root $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} +#chgrp root $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%doc doc/ANNOUNCE doc/CHANGES doc/HOWTO +%doc doc/LICENSE doc/README doc/README.linux +%dir /etc/default +%config /etc/default/useradd +# %config /etc/limits +# %config /etc/login.access +%config /etc/login.defs +# %config /etc/limits +# %config /etc/porttime +# %config /etc/securetty +# %config /etc/shells +# %config /etc/suauth +# /bin/login +# /bin/su +/usr/bin/chage +# /usr/bin/chfn +# /usr/bin/chsh +# /usr/bin/expiry +# /usr/bin/faillog +/usr/bin/gpasswd +/usr/bin/lastlog +# /usr/bin/newgrp +# /usr/bin/passwd +# /usr/bin/sg +/usr/man/man1/chage.1 +# /usr/man/man1/chfn.1 +# /usr/man/man1/chsh.1 +/usr/man/man1/gpasswd.1 +# /usr/man/man1/login.1 +# /usr/man/man1/passwd.1 +# /usr/man/man1/sg.1 +# /usr/man/man1/su.1 +/usr/man/man3/shadow.3 +# /usr/man/man5/faillog.5 +# /usr/man/man5/limits.5 +# /usr/man/man5/login.access.5 +# /usr/man/man5/login.defs.5 +# /usr/man/man5/passwd.5 +# /usr/man/man5/porttime.5 +/usr/man/man5/shadow.5 +# /usr/man/man5/suauth.5 +# /usr/man/man8/adduser.8 +/usr/man/man8/chpasswd.8 +# /usr/man/man8/faillog.8 +/usr/man/man8/groupadd.8 +/usr/man/man8/groupdel.8 +/usr/man/man8/groupmod.8 +/usr/man/man8/grpck.8 +/usr/man/man8/lastlog.8 +# /usr/man/man8/logoutd.8 +/usr/man/man8/newusers.8 +/usr/man/man8/pwck.8 +/usr/man/man8/pwconv.8 +# /usr/man/man8/shadowconfig.8 +/usr/man/man8/useradd.8 +/usr/man/man8/userdel.8 +/usr/man/man8/usermod.8 +# /usr/man/man8/vigr.8 +# /usr/man/man8/vipw.8 +# /usr/sbin/adduser +/usr/sbin/chpasswd +/usr/sbin/groupadd +/usr/sbin/groupdel +/usr/sbin/groupmod +/usr/sbin/grpck +/usr/sbin/grpconv +/usr/sbin/grpunconv +# /usr/sbin/logoutd +/usr/sbin/newusers +/usr/sbin/pwck +/usr/sbin/pwconv +/usr/sbin/pwunconv +# /usr/sbin/shadowconfig +/usr/sbin/useradd +/usr/sbin/userdel +/usr/sbin/usermod +# /usr/sbin/vigr +# /usr/sbin/vipw diff --git a/redhat/shadow-utils.spec.in b/redhat/shadow-utils.spec.in new file mode 100644 index 00000000..e29f8a1b --- /dev/null +++ b/redhat/shadow-utils.spec.in @@ -0,0 +1,151 @@ +# shadow-utils.spec generated automatically from shadow-utils.spec.in +# $Id: shadow-utils.spec.in,v 1.2 1999/06/07 16:40:45 marekm Exp $ +Summary: Shadow password file utilities for Linux +Name: shadow-utils +Version: @VERSION@ +Release: 1 +Copyright: Free +Group: Utilities/System +Source: ftp://ftp.ists.pwr.wroc.pl/pub/linux/shadow/shadow-@VERSION@.tar.gz +BuildRoot: /var/tmp/shadow-utils +Packager: Timo Karjalainen +# Obsoletes: adduser + +%description +This package includes the programs necessary to convert traditional +V7 UNIX password files to the SVR4 shadow password format and additional +tools to work with shadow passwords. + - 'pwconv' converts everything to the shadow password format. + - 'pwunconv' converts back to non-shadow passwords. + - 'pwck' checks the integrity of the password and shadow files. + - 'lastlog' prints out the last login times of all users. + - 'useradd', 'userdel', 'usermod' to manage user accounts. + - 'groupadd', 'groupdel', 'groupmod' to manage groups. + +A number of man pages are also included that relate to these utilities, +and shadow passwords in general. + +%changelog + +* Sun Dec 14 1997 Marek Michalkiewicz + +- Lots of changes, see doc/CHANGES for more details + +* Sun Jun 08 1997 Timo Karjalainen + +- Initial release + +%prep +# This is just a few of the core utilities from the shadow suite... +# packaged up for use w/PAM +%setup -n shadow-@VERSION@ + +%build +# shared lib support is untested, so... +CFLAGS="$RPM_OPT_FLAGS" ./configure --disable-shared --prefix=/usr --exec-prefix=/usr +make + +%install +if [ -d $RPM_BUILD_ROOT ] ; then + rm -rf $RPM_BUILD_ROOT +fi +mkdir -p $RPM_BUILD_ROOT/usr +# neato trick, heh ? :-) +./configure --prefix=$RPM_BUILD_ROOT/usr +make install +mkdir -p $RPM_BUILD_ROOT/etc/default + +# FIXME +#install -m 0600 -o root $RPM_SOURCE_DIR/shadow-970616.useradd $RPM_BUILD_ROOT/etc/default/useradd +#install -m 0644 -o root $RPM_SOURCE_DIR/shadow-970616.login.defs $RPM_BUILD_ROOT/etc/login.defs +#ln -s useradd $RPM_BUILD_ROOT/usr/sbin/adduser +#ln -s useradd.8 $RPM_BUILD_ROOT/usr/man/man8/adduser.8 + +#make prefix=$RPM_BUILD_ROOT/usr exec_prefix=$RPM_BUILD_ROOT/usr install +#touch $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} +#chmod 640 $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} +#chown root $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} +#chgrp root $RPM_BUILD_ROOT/etc/{login.defs,default/useradd} + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%doc doc/ANNOUNCE doc/CHANGES doc/HOWTO +%doc doc/LICENSE doc/README doc/README.linux +%dir /etc/default +%config /etc/default/useradd +# %config /etc/limits +# %config /etc/login.access +%config /etc/login.defs +# %config /etc/limits +# %config /etc/porttime +# %config /etc/securetty +# %config /etc/shells +# %config /etc/suauth +# /bin/login +# /bin/su +/usr/bin/chage +# /usr/bin/chfn +# /usr/bin/chsh +# /usr/bin/expiry +# /usr/bin/faillog +/usr/bin/gpasswd +/usr/bin/lastlog +# /usr/bin/newgrp +# /usr/bin/passwd +# /usr/bin/sg +/usr/man/man1/chage.1 +# /usr/man/man1/chfn.1 +# /usr/man/man1/chsh.1 +/usr/man/man1/gpasswd.1 +# /usr/man/man1/login.1 +# /usr/man/man1/passwd.1 +# /usr/man/man1/sg.1 +# /usr/man/man1/su.1 +/usr/man/man3/shadow.3 +# /usr/man/man5/faillog.5 +# /usr/man/man5/limits.5 +# /usr/man/man5/login.access.5 +# /usr/man/man5/login.defs.5 +# /usr/man/man5/passwd.5 +# /usr/man/man5/porttime.5 +/usr/man/man5/shadow.5 +# /usr/man/man5/suauth.5 +# /usr/man/man8/adduser.8 +/usr/man/man8/chpasswd.8 +# /usr/man/man8/faillog.8 +/usr/man/man8/groupadd.8 +/usr/man/man8/groupdel.8 +/usr/man/man8/groupmod.8 +/usr/man/man8/grpck.8 +/usr/man/man8/lastlog.8 +# /usr/man/man8/logoutd.8 +/usr/man/man8/newusers.8 +/usr/man/man8/pwck.8 +/usr/man/man8/pwconv.8 +# /usr/man/man8/shadowconfig.8 +/usr/man/man8/useradd.8 +/usr/man/man8/userdel.8 +/usr/man/man8/usermod.8 +# /usr/man/man8/vigr.8 +# /usr/man/man8/vipw.8 +# /usr/sbin/adduser +/usr/sbin/chpasswd +/usr/sbin/groupadd +/usr/sbin/groupdel +/usr/sbin/groupmod +/usr/sbin/grpck +/usr/sbin/grpconv +/usr/sbin/grpunconv +# /usr/sbin/logoutd +/usr/sbin/newusers +/usr/sbin/pwck +/usr/sbin/pwconv +/usr/sbin/pwunconv +# /usr/sbin/shadowconfig +/usr/sbin/useradd +/usr/sbin/userdel +/usr/sbin/usermod +# /usr/sbin/vigr +# /usr/sbin/vipw diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000..be5206bb --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,90 @@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +# Watch out; note the difference between prefix & exec_prefix. +# Normally configure sets exec_prefix to root when prefix is /usr. + +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +ubindir = ${prefix}/bin +usbindir = ${prefix}/sbin +localedir = $(datadir)/locale + +noinst_HEADERS = patchlevel.h + +DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@ + +# XXX why are login and su in /bin anyway (other than for +# historical reasons)? +# +# if the system is screwed so badly that it can't mount /usr, +# you can (hopefully) boot single user, and then you're root +# so you don't need these programs for recovery. +# +# also /lib/libshadow.so.x.xx (if any) could be moved to /usr/lib +# and installation would be much simpler (just two directories, +# $prefix/bin and $prefix/sbin, no install-data hacks...) + +bin_PROGRAMS = login \ + su +ubin_PROGRAMS = faillog lastlog \ + chage chfn chsh expiry gpasswd newgrp passwd +usbin_PROGRAMS = chpasswd dpasswd groupadd groupdel groupmod \ + logoutd mkpasswd newusers \ + useradd userdel usermod grpck pwck vipw \ + grpconv grpunconv pwconv pwunconv + +EXTRA_DIST = shadowconfig.sh + +# id and groups are from gnu, sulogin from sysvinit, +# also suid programs are installed by hand. +# XXX installation by hand breaks libtool shared lib support +# (the wrapper scripts get installed instead of binaries), +# so we now chmod the programs by hand after normal installation. + +suidbins = su +suidubins = chage chfn chsh expiry gpasswd newgrp passwd + +install-exec-hook: + for i in $(suidbins); do \ + chmod 4755 $(bindir)/$$i; \ + done + +install-data-hook: + for i in $(suidubins); do \ + chmod 4755 $(ubindir)/$$i; \ + done + rm -f $(ubindir)/sg + ln -s newgrp $(ubindir)/sg + +noinst_PROGRAMS = groups id sulogin + +#install-exec-local: +# $(mkinstalldirs) $(bindir) +# for i in $(suidbins); do \ +# $(INSTALL) -m 4755 $$i $(bindir); \ +# done +# $(mkinstalldirs) $(ubindir) +# for i in $(suidubins); do \ +# $(INSTALL) -m 4755 $$i $(ubindir); \ +# done +# rm -f $(bindir)/sg +# ln -s $(ubindir)/newgrp $(bindir)/sg +# +#noinst_PROGRAMS = id groups \ +# su \ +# chage chfn chsh expiry gpasswd newgrp passwd \ +# sulogin + +shlibs = ../lib/libshadow.la +# With glibc2, almost all programs need libcrypt for some reason, +# even those that don't actually use crypt(). +LDADD = ${shlibs} ../libmisc/libmisc.a ../lib/libshadow.a @INTLLIBS@ @LIBCRYPT@ @LIBTCFS@ @LIBSKEY@ +INCLUDES = -I${top_srcdir}/lib -I$(top_srcdir)/libmisc + +chfn_LDADD = ${LDADD} @LIBPAM@ +chsh_LDADD = ${LDADD} @LIBPAM@ +login_LDADD = ${LDADD} @LIBPAM@ +passwd_LDADD = ${LDADD} @LIBCRACK@ @LIBPAM@ +su_LDADD = ${LDADD} @LIBPAM@ + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 00000000..53251bde --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,873 @@ +# Makefile.in generated automatically by automake 1.3 from Makefile.am + +# Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = /bin/sh + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DISTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CPP = @CPP@ +DATADIRNAME = @DATADIRNAME@ +GENCAT = @GENCAT@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GT_NO = @GT_NO@ +GT_YES = @GT_YES@ +INCLUDE_LOCALE_H = @INCLUDE_LOCALE_H@ +INSTOBJEXT = @INSTOBJEXT@ +INTLDEPS = @INTLDEPS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +LD = @LD@ +LIBCRACK = @LIBCRACK@ +LIBCRYPT = @LIBCRYPT@ +LIBPAM = @LIBPAM@ +LIBSKEY = @LIBSKEY@ +LIBTCFS = @LIBTCFS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +NM = @NM@ +PACKAGE = @PACKAGE@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +U = @U@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +YACC = @YACC@ +l = @l@ + +AUTOMAKE_OPTIONS = 1.0 foreign + +# Watch out; note the difference between prefix & exec_prefix. +# Normally configure sets exec_prefix to root when prefix is /usr. + +bindir = ${exec_prefix}/bin +sbindir = ${exec_prefix}/sbin +ubindir = ${prefix}/bin +usbindir = ${prefix}/sbin +localedir = $(datadir)/locale + +noinst_HEADERS = patchlevel.h + +DEFS = -DLOCALEDIR=\"$(localedir)\" -I. -I$(srcdir) -I.. @DEFS@ + +# XXX why are login and su in /bin anyway (other than for +# historical reasons)? +# +# if the system is screwed so badly that it can't mount /usr, +# you can (hopefully) boot single user, and then you're root +# so you don't need these programs for recovery. +# +# also /lib/libshadow.so.x.xx (if any) could be moved to /usr/lib +# and installation would be much simpler (just two directories, +# $prefix/bin and $prefix/sbin, no install-data hacks...) + +bin_PROGRAMS = login \ + su +ubin_PROGRAMS = faillog lastlog \ + chage chfn chsh expiry gpasswd newgrp passwd +usbin_PROGRAMS = chpasswd dpasswd groupadd groupdel groupmod \ + logoutd mkpasswd newusers \ + useradd userdel usermod grpck pwck vipw \ + grpconv grpunconv pwconv pwunconv + +EXTRA_DIST = shadowconfig.sh + +# id and groups are from gnu, sulogin from sysvinit, +# also suid programs are installed by hand. +# XXX installation by hand breaks libtool shared lib support +# (the wrapper scripts get installed instead of binaries), +# so we now chmod the programs by hand after normal installation. + +suidbins = su +suidubins = chage chfn chsh expiry gpasswd newgrp passwd + +noinst_PROGRAMS = groups id sulogin + +#install-exec-local: +# $(mkinstalldirs) $(bindir) +# for i in $(suidbins); do \ +# $(INSTALL) -m 4755 $$i $(bindir); \ +# done +# $(mkinstalldirs) $(ubindir) +# for i in $(suidubins); do \ +# $(INSTALL) -m 4755 $$i $(ubindir); \ +# done +# rm -f $(bindir)/sg +# ln -s $(ubindir)/newgrp $(bindir)/sg +# +#noinst_PROGRAMS = id groups \ +# su \ +# chage chfn chsh expiry gpasswd newgrp passwd \ +# sulogin + +shlibs = ../lib/libshadow.la +# With glibc2, almost all programs need libcrypt for some reason, +# even those that don't actually use crypt(). +LDADD = ${shlibs} ../libmisc/libmisc.a ../lib/libshadow.a @INTLLIBS@ @LIBCRYPT@ @LIBTCFS@ @LIBSKEY@ +INCLUDES = -I${top_srcdir}/lib -I$(top_srcdir)/libmisc + +chfn_LDADD = ${LDADD} @LIBPAM@ +chsh_LDADD = ${LDADD} @LIBPAM@ +login_LDADD = ${LDADD} @LIBPAM@ +passwd_LDADD = ${LDADD} @LIBCRACK@ @LIBPAM@ +su_LDADD = ${LDADD} @LIBPAM@ +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(ubin_PROGRAMS) \ +$(usbin_PROGRAMS) + +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +login_SOURCES = login.c +login_OBJECTS = login.o +login_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +login_LDFLAGS = +su_SOURCES = su.c +su_OBJECTS = su.o +su_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +su_LDFLAGS = +groups_SOURCES = groups.c +groups_OBJECTS = groups.o +groups_LDADD = $(LDADD) +groups_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +groups_LDFLAGS = +id_SOURCES = id.c +id_OBJECTS = id.o +id_LDADD = $(LDADD) +id_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +id_LDFLAGS = +sulogin_SOURCES = sulogin.c +sulogin_OBJECTS = sulogin.o +sulogin_LDADD = $(LDADD) +sulogin_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +sulogin_LDFLAGS = +faillog_SOURCES = faillog.c +faillog_OBJECTS = faillog.o +faillog_LDADD = $(LDADD) +faillog_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +faillog_LDFLAGS = +lastlog_SOURCES = lastlog.c +lastlog_OBJECTS = lastlog.o +lastlog_LDADD = $(LDADD) +lastlog_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +lastlog_LDFLAGS = +chage_SOURCES = chage.c +chage_OBJECTS = chage.o +chage_LDADD = $(LDADD) +chage_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +chage_LDFLAGS = +chfn_SOURCES = chfn.c +chfn_OBJECTS = chfn.o +chfn_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +chfn_LDFLAGS = +chsh_SOURCES = chsh.c +chsh_OBJECTS = chsh.o +chsh_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +chsh_LDFLAGS = +expiry_SOURCES = expiry.c +expiry_OBJECTS = expiry.o +expiry_LDADD = $(LDADD) +expiry_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +expiry_LDFLAGS = +gpasswd_SOURCES = gpasswd.c +gpasswd_OBJECTS = gpasswd.o +gpasswd_LDADD = $(LDADD) +gpasswd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +gpasswd_LDFLAGS = +newgrp_SOURCES = newgrp.c +newgrp_OBJECTS = newgrp.o +newgrp_LDADD = $(LDADD) +newgrp_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +newgrp_LDFLAGS = +passwd_SOURCES = passwd.c +passwd_OBJECTS = passwd.o +passwd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +passwd_LDFLAGS = +chpasswd_SOURCES = chpasswd.c +chpasswd_OBJECTS = chpasswd.o +chpasswd_LDADD = $(LDADD) +chpasswd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +chpasswd_LDFLAGS = +dpasswd_SOURCES = dpasswd.c +dpasswd_OBJECTS = dpasswd.o +dpasswd_LDADD = $(LDADD) +dpasswd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +dpasswd_LDFLAGS = +groupadd_SOURCES = groupadd.c +groupadd_OBJECTS = groupadd.o +groupadd_LDADD = $(LDADD) +groupadd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +groupadd_LDFLAGS = +groupdel_SOURCES = groupdel.c +groupdel_OBJECTS = groupdel.o +groupdel_LDADD = $(LDADD) +groupdel_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +groupdel_LDFLAGS = +groupmod_SOURCES = groupmod.c +groupmod_OBJECTS = groupmod.o +groupmod_LDADD = $(LDADD) +groupmod_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +groupmod_LDFLAGS = +logoutd_SOURCES = logoutd.c +logoutd_OBJECTS = logoutd.o +logoutd_LDADD = $(LDADD) +logoutd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +logoutd_LDFLAGS = +mkpasswd_SOURCES = mkpasswd.c +mkpasswd_OBJECTS = mkpasswd.o +mkpasswd_LDADD = $(LDADD) +mkpasswd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +mkpasswd_LDFLAGS = +newusers_SOURCES = newusers.c +newusers_OBJECTS = newusers.o +newusers_LDADD = $(LDADD) +newusers_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +newusers_LDFLAGS = +useradd_SOURCES = useradd.c +useradd_OBJECTS = useradd.o +useradd_LDADD = $(LDADD) +useradd_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +useradd_LDFLAGS = +userdel_SOURCES = userdel.c +userdel_OBJECTS = userdel.o +userdel_LDADD = $(LDADD) +userdel_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +userdel_LDFLAGS = +usermod_SOURCES = usermod.c +usermod_OBJECTS = usermod.o +usermod_LDADD = $(LDADD) +usermod_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +usermod_LDFLAGS = +grpck_SOURCES = grpck.c +grpck_OBJECTS = grpck.o +grpck_LDADD = $(LDADD) +grpck_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +grpck_LDFLAGS = +pwck_SOURCES = pwck.c +pwck_OBJECTS = pwck.o +pwck_LDADD = $(LDADD) +pwck_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +pwck_LDFLAGS = +vipw_SOURCES = vipw.c +vipw_OBJECTS = vipw.o +vipw_LDADD = $(LDADD) +vipw_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +vipw_LDFLAGS = +grpconv_SOURCES = grpconv.c +grpconv_OBJECTS = grpconv.o +grpconv_LDADD = $(LDADD) +grpconv_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +grpconv_LDFLAGS = +grpunconv_SOURCES = grpunconv.c +grpunconv_OBJECTS = grpunconv.o +grpunconv_LDADD = $(LDADD) +grpunconv_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +grpunconv_LDFLAGS = +pwconv_SOURCES = pwconv.c +pwconv_OBJECTS = pwconv.o +pwconv_LDADD = $(LDADD) +pwconv_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +pwconv_LDFLAGS = +pwunconv_SOURCES = pwunconv.c +pwunconv_OBJECTS = pwunconv.o +pwunconv_LDADD = $(LDADD) +pwunconv_DEPENDENCIES = ../lib/libshadow.la ../libmisc/libmisc.a \ +../lib/libshadow.a +pwunconv_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) +LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@ +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP = --best +SOURCES = login.c su.c groups.c id.c sulogin.c faillog.c lastlog.c chage.c chfn.c chsh.c expiry.c gpasswd.c newgrp.c passwd.c chpasswd.c dpasswd.c groupadd.c groupdel.c groupmod.c logoutd.c mkpasswd.c newusers.c useradd.c userdel.c usermod.c grpck.c pwck.c vipw.c grpconv.c grpunconv.c pwconv.c pwunconv.c +OBJECTS = login.o su.o groups.o id.o sulogin.o faillog.o lastlog.o chage.o chfn.o chsh.o expiry.o gpasswd.o newgrp.o passwd.o chpasswd.o dpasswd.o groupadd.o groupdel.o groupmod.o logoutd.o mkpasswd.o newusers.o useradd.o userdel.o usermod.o grpck.o pwck.o vipw.o grpconv.o grpunconv.o pwconv.o pwunconv.o + +all: Makefile $(PROGRAMS) $(HEADERS) + +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps src/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-binPROGRAMS: + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +distclean-binPROGRAMS: + +maintainer-clean-binPROGRAMS: + +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(bin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(bindir)/`echo $$p|sed '$(transform)'`; \ + done + +mostlyclean-noinstPROGRAMS: + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +distclean-noinstPROGRAMS: + +maintainer-clean-noinstPROGRAMS: + +mostlyclean-ubinPROGRAMS: + +clean-ubinPROGRAMS: + -test -z "$(ubin_PROGRAMS)" || rm -f $(ubin_PROGRAMS) + +distclean-ubinPROGRAMS: + +maintainer-clean-ubinPROGRAMS: + +install-ubinPROGRAMS: $(ubin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(ubindir) + @list='$(ubin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(ubindir)/`echo $$p|sed '$(transform)'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(ubindir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; \ + done + +uninstall-ubinPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(ubin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(ubindir)/`echo $$p|sed '$(transform)'`; \ + done + +mostlyclean-usbinPROGRAMS: + +clean-usbinPROGRAMS: + -test -z "$(usbin_PROGRAMS)" || rm -f $(usbin_PROGRAMS) + +distclean-usbinPROGRAMS: + +maintainer-clean-usbinPROGRAMS: + +install-usbinPROGRAMS: $(usbin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(usbindir) + @list='$(usbin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(usbindir)/`echo $$p|sed '$(transform)'`"; \ + $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(usbindir)/`echo $$p|sed '$(transform)'`; \ + else :; fi; \ + done + +uninstall-usbinPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(usbin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(usbindir)/`echo $$p|sed '$(transform)'`; \ + done + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +login: $(login_OBJECTS) $(login_DEPENDENCIES) + @rm -f login + $(LINK) $(login_LDFLAGS) $(login_OBJECTS) $(login_LDADD) $(LIBS) + +su: $(su_OBJECTS) $(su_DEPENDENCIES) + @rm -f su + $(LINK) $(su_LDFLAGS) $(su_OBJECTS) $(su_LDADD) $(LIBS) + +groups: $(groups_OBJECTS) $(groups_DEPENDENCIES) + @rm -f groups + $(LINK) $(groups_LDFLAGS) $(groups_OBJECTS) $(groups_LDADD) $(LIBS) + +id: $(id_OBJECTS) $(id_DEPENDENCIES) + @rm -f id + $(LINK) $(id_LDFLAGS) $(id_OBJECTS) $(id_LDADD) $(LIBS) + +sulogin: $(sulogin_OBJECTS) $(sulogin_DEPENDENCIES) + @rm -f sulogin + $(LINK) $(sulogin_LDFLAGS) $(sulogin_OBJECTS) $(sulogin_LDADD) $(LIBS) + +faillog: $(faillog_OBJECTS) $(faillog_DEPENDENCIES) + @rm -f faillog + $(LINK) $(faillog_LDFLAGS) $(faillog_OBJECTS) $(faillog_LDADD) $(LIBS) + +lastlog: $(lastlog_OBJECTS) $(lastlog_DEPENDENCIES) + @rm -f lastlog + $(LINK) $(lastlog_LDFLAGS) $(lastlog_OBJECTS) $(lastlog_LDADD) $(LIBS) + +chage: $(chage_OBJECTS) $(chage_DEPENDENCIES) + @rm -f chage + $(LINK) $(chage_LDFLAGS) $(chage_OBJECTS) $(chage_LDADD) $(LIBS) + +chfn: $(chfn_OBJECTS) $(chfn_DEPENDENCIES) + @rm -f chfn + $(LINK) $(chfn_LDFLAGS) $(chfn_OBJECTS) $(chfn_LDADD) $(LIBS) + +chsh: $(chsh_OBJECTS) $(chsh_DEPENDENCIES) + @rm -f chsh + $(LINK) $(chsh_LDFLAGS) $(chsh_OBJECTS) $(chsh_LDADD) $(LIBS) + +expiry: $(expiry_OBJECTS) $(expiry_DEPENDENCIES) + @rm -f expiry + $(LINK) $(expiry_LDFLAGS) $(expiry_OBJECTS) $(expiry_LDADD) $(LIBS) + +gpasswd: $(gpasswd_OBJECTS) $(gpasswd_DEPENDENCIES) + @rm -f gpasswd + $(LINK) $(gpasswd_LDFLAGS) $(gpasswd_OBJECTS) $(gpasswd_LDADD) $(LIBS) + +newgrp: $(newgrp_OBJECTS) $(newgrp_DEPENDENCIES) + @rm -f newgrp + $(LINK) $(newgrp_LDFLAGS) $(newgrp_OBJECTS) $(newgrp_LDADD) $(LIBS) + +passwd: $(passwd_OBJECTS) $(passwd_DEPENDENCIES) + @rm -f passwd + $(LINK) $(passwd_LDFLAGS) $(passwd_OBJECTS) $(passwd_LDADD) $(LIBS) + +chpasswd: $(chpasswd_OBJECTS) $(chpasswd_DEPENDENCIES) + @rm -f chpasswd + $(LINK) $(chpasswd_LDFLAGS) $(chpasswd_OBJECTS) $(chpasswd_LDADD) $(LIBS) + +dpasswd: $(dpasswd_OBJECTS) $(dpasswd_DEPENDENCIES) + @rm -f dpasswd + $(LINK) $(dpasswd_LDFLAGS) $(dpasswd_OBJECTS) $(dpasswd_LDADD) $(LIBS) + +groupadd: $(groupadd_OBJECTS) $(groupadd_DEPENDENCIES) + @rm -f groupadd + $(LINK) $(groupadd_LDFLAGS) $(groupadd_OBJECTS) $(groupadd_LDADD) $(LIBS) + +groupdel: $(groupdel_OBJECTS) $(groupdel_DEPENDENCIES) + @rm -f groupdel + $(LINK) $(groupdel_LDFLAGS) $(groupdel_OBJECTS) $(groupdel_LDADD) $(LIBS) + +groupmod: $(groupmod_OBJECTS) $(groupmod_DEPENDENCIES) + @rm -f groupmod + $(LINK) $(groupmod_LDFLAGS) $(groupmod_OBJECTS) $(groupmod_LDADD) $(LIBS) + +logoutd: $(logoutd_OBJECTS) $(logoutd_DEPENDENCIES) + @rm -f logoutd + $(LINK) $(logoutd_LDFLAGS) $(logoutd_OBJECTS) $(logoutd_LDADD) $(LIBS) + +mkpasswd: $(mkpasswd_OBJECTS) $(mkpasswd_DEPENDENCIES) + @rm -f mkpasswd + $(LINK) $(mkpasswd_LDFLAGS) $(mkpasswd_OBJECTS) $(mkpasswd_LDADD) $(LIBS) + +newusers: $(newusers_OBJECTS) $(newusers_DEPENDENCIES) + @rm -f newusers + $(LINK) $(newusers_LDFLAGS) $(newusers_OBJECTS) $(newusers_LDADD) $(LIBS) + +useradd: $(useradd_OBJECTS) $(useradd_DEPENDENCIES) + @rm -f useradd + $(LINK) $(useradd_LDFLAGS) $(useradd_OBJECTS) $(useradd_LDADD) $(LIBS) + +userdel: $(userdel_OBJECTS) $(userdel_DEPENDENCIES) + @rm -f userdel + $(LINK) $(userdel_LDFLAGS) $(userdel_OBJECTS) $(userdel_LDADD) $(LIBS) + +usermod: $(usermod_OBJECTS) $(usermod_DEPENDENCIES) + @rm -f usermod + $(LINK) $(usermod_LDFLAGS) $(usermod_OBJECTS) $(usermod_LDADD) $(LIBS) + +grpck: $(grpck_OBJECTS) $(grpck_DEPENDENCIES) + @rm -f grpck + $(LINK) $(grpck_LDFLAGS) $(grpck_OBJECTS) $(grpck_LDADD) $(LIBS) + +pwck: $(pwck_OBJECTS) $(pwck_DEPENDENCIES) + @rm -f pwck + $(LINK) $(pwck_LDFLAGS) $(pwck_OBJECTS) $(pwck_LDADD) $(LIBS) + +vipw: $(vipw_OBJECTS) $(vipw_DEPENDENCIES) + @rm -f vipw + $(LINK) $(vipw_LDFLAGS) $(vipw_OBJECTS) $(vipw_LDADD) $(LIBS) + +grpconv: $(grpconv_OBJECTS) $(grpconv_DEPENDENCIES) + @rm -f grpconv + $(LINK) $(grpconv_LDFLAGS) $(grpconv_OBJECTS) $(grpconv_LDADD) $(LIBS) + +grpunconv: $(grpunconv_OBJECTS) $(grpunconv_DEPENDENCIES) + @rm -f grpunconv + $(LINK) $(grpunconv_LDFLAGS) $(grpunconv_OBJECTS) $(grpunconv_LDADD) $(LIBS) + +pwconv: $(pwconv_OBJECTS) $(pwconv_DEPENDENCIES) + @rm -f pwconv + $(LINK) $(pwconv_LDFLAGS) $(pwconv_OBJECTS) $(pwconv_LDADD) $(LIBS) + +pwunconv: $(pwunconv_OBJECTS) $(pwunconv_DEPENDENCIES) + @rm -f pwunconv + $(LINK) $(pwunconv_LDFLAGS) $(pwunconv_OBJECTS) $(pwunconv_LDADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $(SOURCES) $(HEADERS) $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = src + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file; \ + done +chage.o: chage.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwio.h \ + ../lib/shadowio.h +chfn.o: chfn.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwio.h \ + ../lib/getdef.h ../lib/pwauth.h +chpasswd.o: chpasswd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwio.h \ + ../lib/shadowio.h +chsh.o: chsh.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwio.h \ + ../lib/getdef.h ../lib/pwauth.h +dpasswd.o: dpasswd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/dialup.h +expiry.o: expiry.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +faillog.o: faillog.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/faillog.h +gpasswd.o: gpasswd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/groupio.h \ + ../lib/sgroupio.h +groupadd.o: groupadd.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/prototypes.h ../libmisc/chkname.h \ + ../lib/getdef.h ../lib/groupio.h ../lib/sgroupio.h +groupdel.o: groupdel.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/groupio.h \ + ../lib/sgroupio.h +groupmod.o: groupmod.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../libmisc/chkname.h \ + ../lib/groupio.h ../lib/sgroupio.h +groups.o: groups.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +grpck.o: grpck.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../libmisc/chkname.h \ + ../lib/commonio.h ../lib/groupio.h ../lib/sgroupio.h +grpconv.o: grpconv.c ../config.h ../lib/prototypes.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/groupio.h ../lib/sgroupio.h \ + ../lib/rcsid.h +grpunconv.o: grpunconv.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/groupio.h \ + ../lib/sgroupio.h +id.o: id.c ../config.h ../lib/rcsid.h ../lib/defines.h ../lib/gshadow_.h +lastlog.o: lastlog.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +login.o: login.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/faillog.h \ + ../libmisc/failure.h ../lib/pwauth.h ../lib/getdef.h \ + ../lib/dialchk.h +logoutd.o: logoutd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +mkpasswd.o: mkpasswd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h +newgrp.o: newgrp.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h +newusers.o: newusers.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h \ + ../lib/pwio.h ../lib/groupio.h ../lib/shadowio.h +passwd.o: passwd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwauth.h \ + ../lib/shadowio.h ../lib/pwio.h ../lib/getdef.h +pwck.o: pwck.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../libmisc/chkname.h \ + ../lib/commonio.h ../lib/pwio.h ../lib/shadowio.h +pwconv.o: pwconv.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwio.h \ + ../lib/shadowio.h ../lib/getdef.h +pwunconv.o: pwunconv.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/prototypes.h ../lib/pwio.h \ + ../lib/shadowio.h +sulogin.o: sulogin.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h \ + ../lib/pwauth.h +su.o: su.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/pwauth.h \ + ../lib/getdef.h +useradd.o: useradd.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../libmisc/chkname.h \ + ../lib/pwauth.h ../lib/faillog.h ../lib/groupio.h \ + ../lib/sgroupio.h ../lib/pwio.h ../lib/shadowio.h \ + ../lib/getdef.h +userdel.o: userdel.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../lib/getdef.h \ + ../lib/pwauth.h ../lib/groupio.h ../lib/pwio.h \ + ../lib/shadowio.h ../lib/sgroupio.h +usermod.o: usermod.c ../config.h ../lib/rcsid.h ../lib/prototypes.h \ + ../lib/defines.h ../lib/gshadow_.h ../libmisc/chkname.h \ + ../lib/faillog.h ../lib/pwauth.h ../lib/getdef.h \ + ../lib/groupio.h ../lib/sgroupio.h ../lib/pwio.h \ + ../lib/shadowio.h +vipw.o: vipw.c ../config.h ../lib/rcsid.h ../lib/defines.h \ + ../lib/gshadow_.h ../lib/prototypes.h ../lib/pwio.h \ + ../lib/shadowio.h ../lib/groupio.h ../lib/sgroupio.h + +info: +dvi: +check: all + $(MAKE) +installcheck: +install-exec: install-binPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) install-exec-hook + +install-data: install-ubinPROGRAMS install-usbinPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) install-data-hook + +install: install-exec install-data all + @: + +uninstall: uninstall-binPROGRAMS uninstall-ubinPROGRAMS uninstall-usbinPROGRAMS + +install-strip: + $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' INSTALL_SCRIPT='$(INSTALL_PROGRAM)' install +installdirs: + $(mkinstalldirs) $(DATADIR)$(bindir) $(DATADIR)$(ubindir) \ + $(DATADIR)$(usbindir) + + +mostlyclean-generic: + -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(DISTCLEANFILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +mostlyclean: mostlyclean-binPROGRAMS mostlyclean-noinstPROGRAMS \ + mostlyclean-ubinPROGRAMS mostlyclean-usbinPROGRAMS \ + mostlyclean-compile mostlyclean-libtool \ + mostlyclean-tags mostlyclean-generic + +clean: clean-binPROGRAMS clean-noinstPROGRAMS clean-ubinPROGRAMS \ + clean-usbinPROGRAMS clean-compile clean-libtool \ + clean-tags clean-generic mostlyclean + +distclean: distclean-binPROGRAMS distclean-noinstPROGRAMS \ + distclean-ubinPROGRAMS distclean-usbinPROGRAMS \ + distclean-compile distclean-libtool distclean-tags \ + distclean-generic clean + -rm -f config.status + -rm -f libtool + +maintainer-clean: maintainer-clean-binPROGRAMS \ + maintainer-clean-noinstPROGRAMS \ + maintainer-clean-ubinPROGRAMS \ + maintainer-clean-usbinPROGRAMS maintainer-clean-compile \ + maintainer-clean-libtool maintainer-clean-tags \ + maintainer-clean-generic distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \ +maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \ +mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \ +clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS \ +mostlyclean-ubinPROGRAMS distclean-ubinPROGRAMS clean-ubinPROGRAMS \ +maintainer-clean-ubinPROGRAMS uninstall-ubinPROGRAMS \ +install-ubinPROGRAMS mostlyclean-usbinPROGRAMS distclean-usbinPROGRAMS \ +clean-usbinPROGRAMS maintainer-clean-usbinPROGRAMS \ +uninstall-usbinPROGRAMS install-usbinPROGRAMS mostlyclean-compile \ +distclean-compile clean-compile maintainer-clean-compile \ +mostlyclean-libtool distclean-libtool clean-libtool \ +maintainer-clean-libtool tags mostlyclean-tags distclean-tags \ +clean-tags maintainer-clean-tags distdir info dvi installcheck \ +install-exec install-data install uninstall all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +install-exec-hook: + for i in $(suidbins); do \ + chmod 4755 $(bindir)/$$i; \ + done + +install-data-hook: + for i in $(suidubins); do \ + chmod 4755 $(ubindir)/$$i; \ + done + rm -f $(ubindir)/sg + ln -s newgrp $(ubindir)/sg + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/chage.c b/src/chage.c new file mode 100644 index 00000000..3de78398 --- /dev/null +++ b/src/chage.c @@ -0,0 +1,821 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: chage.c,v 1.15 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +#include + +/* + * chage depends on some form of aging being present. It makes no sense + * to have a program that has no input. + */ + +#ifdef SHADOWPWD +#ifndef AGING +#define AGING +#endif /* AGING */ +#else /* !SHADOWPWD */ +#if !defined(ATT_AGE) && defined(AGING) +#undef AGING +#endif /* !ATT_AGE && AGING */ +#endif /* SHADOWPWD */ + +static char *Prog; + +#ifdef AGING /*{*/ + +/* + * Global variables + */ + +static long mindays; +static long maxdays; +static long lastday; +#ifdef SHADOWPWD +static long warndays; +static long inactdays; +static long expdays; +#endif + +/* + * External identifiers + */ + +extern long a64l(); +extern char *l64a(); + +#include "pwio.h" + +#ifdef SHADOWPWD +#include "shadowio.h" +#endif + +extern int optind; +extern char *optarg; +#ifdef NDBM +extern int pw_dbm_mode; +#ifdef SHADOWPWD +extern int sp_dbm_mode; +#endif +#endif + +/* + * #defines for messages. This facilitates foreign language conversion + * since all messages are defined right here. + */ + +/* + * xgettext doesn't like #defines, so now we only leave untranslated + * messages here. -MM + */ + +#define AGE_CHANGED "changed password expiry for %s\n" +#define LOCK_FAIL "failed locking %s\n" +#define OPEN_FAIL "failed opening %s\n" +#define WRITE_FAIL "failed updating %s\n" +#define CLOSE_FAIL "failed rewriting %s\n" + +#define EPOCH "1969-12-31" + +#ifdef SHADOWPWD +#define DBMERROR2 "error updating DBM shadow entry.\n" +#else +#define DBMERROR2 "error updating DBM passwd entry.\n" +#endif + +/* local function prototypes */ +static void usage P_((void)); +static void date_to_str P_((char *, size_t, time_t)); +static int new_fields P_((void)); +static void print_date P_((time_t)); +static void list_fields P_((void)); +int main P_((int, char **)); +static void cleanup P_((int)); + +/* + * usage - print command line syntax and exit + */ + +static void +usage(void) +{ +#ifdef SHADOWPWD + fprintf(stderr, _("Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -W warn ]\n [ -I inactive ] [ -E expire ] [ -d last_day ] user\n"), Prog); +#else + fprintf(stderr, _("Usage: %s [ -l ] [ -m min_days ] [ -M max_days ] [ -d last_day ] user\n"), Prog); +#endif + exit(1); +} + +static void +date_to_str(char *buf, size_t maxsize, time_t date) +{ + struct tm *tp; + + tp = gmtime(&date); +#ifdef HAVE_STRFTIME + strftime(buf, maxsize, "%Y-%m-%d", tp); +#else + snprintf(buf, maxsize, "%04d-%02d-%02d", + tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday); +#endif /* HAVE_STRFTIME */ +} + +/* + * new_fields - change the user's password aging information interactively. + * + * prompt the user for all of the password age values. set the fields + * from the user's response, or leave alone if nothing was entered. the + * value (-1) is used to indicate the field should be removed if possible. + * any other negative value is an error. very large positive values will + * be handled elsewhere. + */ + +static int +new_fields(void) +{ + char buf[200]; + char *cp; + + printf(_("Enter the new value, or press return for the default\n\n")); + + snprintf(buf, sizeof buf, "%ld", mindays); + change_field(buf, sizeof buf, _("Minimum Password Age")); + if (((mindays = strtol (buf, &cp, 10)) == 0 && *cp) || mindays < -1) + return 0; + + snprintf(buf, sizeof buf, "%ld", maxdays); + change_field(buf, sizeof buf, _("Maximum Password Age")); + if (((maxdays = strtol (buf, &cp, 10)) == 0 && *cp) || maxdays < -1) + return 0; + + date_to_str(buf, sizeof buf, lastday * SCALE); + + change_field(buf, sizeof buf, _("Last Password Change (YYYY-MM-DD)")); + + if (strcmp (buf, EPOCH) == 0) + lastday = -1; + else if ((lastday = strtoday (buf)) == -1) + return 0; + +#ifdef SHADOWPWD + snprintf(buf, sizeof buf, "%ld", warndays); + change_field (buf, sizeof buf, _("Password Expiration Warning")); + if (((warndays = strtol (buf, &cp, 10)) == 0 && *cp) || warndays < -1) + return 0; + + snprintf(buf, sizeof buf, "%ld", inactdays); + change_field(buf, sizeof buf, _("Password Inactive")); + if (((inactdays = strtol (buf, &cp, 10)) == 0 && *cp) || inactdays < -1) + return 0; + + date_to_str(buf, sizeof buf, expdays * SCALE); + + change_field(buf, sizeof buf, _("Account Expiration Date (YYYY-MM-DD)")); + + if (strcmp (buf, EPOCH) == 0) + expdays = -1; + else if ((expdays = strtoday (buf)) == -1) + return 0; +#endif /* SHADOWPWD */ + + return 1; +} + +static void +print_date(time_t date) +{ +#ifdef HAVE_STRFTIME + struct tm *tp; + char buf[80]; + + tp = gmtime(&date); + strftime(buf, sizeof buf, "%b %d, %Y", tp); + puts(buf); +#else + struct tm *tp; + char *cp; + + tp = gmtime(&date); + cp = asctime(tp); + printf("%6.6s, %4.4s\n", cp + 4, cp + 20); +#endif +} + +/* + * list_fields - display the current values of the expiration fields + * + * display the password age information from the password fields. date + * values will be displayed as a calendar date, or the word "Never" if + * the date is 1/1/70, which is day number 0. + */ + +static void +list_fields(void) +{ + long changed = 0; + long expires; + + /* + * Start with the easy numbers - the number of days before the + * password can be changed, the number of days after which the + * password must be chaged, the number of days before the + * password expires that the user is told, and the number of + * days after the password expires that the account becomes + * unusable. + */ + + printf(_("Minimum:\t%ld\n"), mindays); + printf(_("Maximum:\t%ld\n"), maxdays); +#ifdef SHADOWPWD + printf(_("Warning:\t%ld\n"), warndays); + printf(_("Inactive:\t%ld\n"), inactdays); +#endif + + /* + * The "last change" date is either "Never" or the date the + * password was last modified. The date is the number of + * days since 1/1/1970. + */ + + printf(_("Last Change:\t\t")); + if (lastday <= 0) { + printf(_("Never\n")); + } else { + changed = lastday * SCALE; + print_date(changed); + } + + /* + * The password expiration date is determined from the last + * change date plus the number of days the password is valid + * for. + */ + + printf(_("Password Expires:\t")); + if (lastday <= 0 || maxdays >= 10000*(DAY/SCALE) || maxdays <= 0) { + printf (_("Never\n")); + } else { + expires = changed + maxdays * SCALE; + print_date(expires); + } + +#ifdef SHADOWPWD + /* + * The account becomes inactive if the password is expired + * for more than "inactdays". The expiration date is calculated + * and the number of inactive days is added. The resulting date + * is when the active will be disabled. + */ + + printf ("Password Inactive:\t"); + if (lastday <= 0 || inactdays <= 0 || + maxdays >= 10000*(DAY/SCALE) || maxdays <= 0) { + printf ("Never\n"); + } else { + expires = changed + (maxdays + inactdays) * SCALE; + print_date(expires); + } + + /* + * The account will expire on the given date regardless of the + * password expiring or not. + */ + + printf ("Account Expires:\t"); + if (expdays <= 0) { + printf ("Never\n"); + } else { + expires = expdays * SCALE; + print_date(expires); + } +#endif +} + +/* + * chage - change a user's password aging information + * + * This command controls the password aging information. + * + * The valid options are + * + * -m minimum number of days before password change (*) + * -M maximim number of days before password change (*) + * -d last password change date (*) + * -l password aging information + * -W expiration warning days (*) + * -I password inactive after expiration (*) + * -E account expiration date (*) + * + * (*) requires root permission to execute. + * + * All of the time fields are entered in the internal format + * which is either seconds or days. + * + * The options -W, -I and -E all depend on the SHADOWPWD + * macro being defined. + */ + +int +main(int argc, char **argv) +{ + int flag; + int lflg = 0; + int mflg = 0; + int Mflg = 0; + int dflg = 0; +#ifdef SHADOWPWD + int Wflg = 0; + int Iflg = 0; + int Eflg = 0; + const struct spwd *sp; + struct spwd spwd; +#else + char new_age[5]; +#endif + uid_t ruid = getuid (); + const struct passwd *pw; + struct passwd pwent; + char name[BUFSIZ]; + + sanitize_env(); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * Get the program name so that error messages can use it. + */ + + Prog = Basename(argv[0]); + + openlog("chage", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); +#ifdef NDBM +#ifdef SHADOWPWD + sp_dbm_mode = O_RDWR; +#endif + pw_dbm_mode = O_RDWR; +#endif + + /* + * Parse the flags. The difference between password file + * formats includes the number of fields, and whether the + * dates are entered as days or weeks. Shadow password + * file info =must= be entered in days, while regular + * password file info =must= be entered in weeks. + */ + +#ifdef SHADOWPWD +#define FLAGS "lm:M:W:I:E:d:" +#else +#define FLAGS "lm:M:d:" +#endif + while ((flag = getopt(argc, argv, FLAGS)) != EOF) { +#undef FLAGS + switch (flag) { + case 'l': + lflg++; + break; + case 'm': + mflg++; + mindays = strtol (optarg, 0, 10); + break; + case 'M': + Mflg++; + maxdays = strtol (optarg, 0, 10); + break; + case 'd': + dflg++; + if (strchr (optarg, '/')) + lastday = strtoday (optarg); + else + lastday = strtol (optarg, 0, 10); + break; +#ifdef SHADOWPWD + case 'W': + Wflg++; + warndays = strtol (optarg, 0, 10); + break; + case 'I': + Iflg++; + inactdays = strtol (optarg, 0, 10); + break; + case 'E': + Eflg++; + if (strchr (optarg, '/')) + expdays = strtoday (optarg); + else + expdays = strtol (optarg, 0, 10); + break; +#endif + default: + usage (); + } + } + + /* + * Make certain the flags do not conflict and that there is + * a user name on the command line. + */ + + if (argc != optind + 1) + usage (); + +#ifdef SHADOWPWD + if (lflg && (mflg || Mflg || dflg || Wflg || Iflg || Eflg)) +#else + if (lflg && (mflg || Mflg || dflg)) +#endif + { + fprintf (stderr, _("%s: do not include \"l\" with other flags\n"), Prog); + closelog(); + usage (); + } + + /* + * An unprivileged user can ask for their own aging information, + * but only root can change it, or list another user's aging + * information. + */ + + if (ruid != 0 && ! lflg) { + fprintf (stderr, _("%s: permission denied\n"), Prog); + closelog(); + exit (1); + } + + /* + * Lock and open the password file. This loads all of the + * password file entries into memory. Then we get a pointer + * to the password file entry for the requested user. + */ + + if (!pw_lock()) { + fprintf(stderr, _("%s: can't lock password file\n"), Prog); + SYSLOG((LOG_ERR, LOCK_FAIL, PASSWD_FILE)); + closelog(); + exit(1); + } + if (!pw_open((ruid != 0 || lflg) ? O_RDONLY:O_RDWR)) { + fprintf(stderr, _("%s: can't open password file\n"), Prog); + cleanup(1); + SYSLOG((LOG_ERR, OPEN_FAIL, PASSWD_FILE)); + closelog(); + exit(1); + } + if (!(pw = pw_locate(argv[optind]))) { + fprintf(stderr, _("%s: unknown user: %s\n"), Prog, argv[optind]); + cleanup(1); + closelog(); + exit(1); + } + + pwent = *pw; + STRFCPY(name, pwent.pw_name); + +#ifdef SHADOWPWD + /* + * For shadow password files we have to lock the file and + * read in the entries as was done for the password file. + * The user entries does not have to exist in this case; + * a new entry will be created for this user if one does + * not exist already. + */ + + if (!spw_lock()) { + fprintf(stderr, _("%s: can't lock shadow password file\n"), Prog); + cleanup(1); + SYSLOG((LOG_ERR, LOCK_FAIL, SHADOW_FILE)); + closelog(); + exit(1); + } + if (!spw_open((ruid != 0 || lflg) ? O_RDONLY:O_RDWR)) { + fprintf(stderr, _("%s: can't open shadow password file\n"), Prog); + cleanup(2); + SYSLOG((LOG_ERR, OPEN_FAIL, SHADOW_FILE)); + closelog(); + exit(1); + } + + sp = spw_locate(argv[optind]); + + /* + * Set the fields that aren't being set from the command line + * from the password file. + */ + + if (sp) { + spwd = *sp; + + if (! Mflg) + maxdays = spwd.sp_max; + if (! mflg) + mindays = spwd.sp_min; + if (! dflg) + lastday = spwd.sp_lstchg; + if (! Wflg) + warndays = spwd.sp_warn; + if (! Iflg) + inactdays = spwd.sp_inact; + if (! Eflg) + expdays = spwd.sp_expire; + } +#ifdef ATT_AGE + else +#endif /* ATT_AGE */ +#endif /* SHADOWPWD */ +#ifdef ATT_AGE + { + if (pwent.pw_age && strlen (pwent.pw_age) >= 2) { + if (! Mflg) + maxdays = c64i (pwent.pw_age[0]) * (WEEK/SCALE); + if (! mflg) + mindays = c64i (pwent.pw_age[1]) * (WEEK/SCALE); + if (! dflg && strlen (pwent.pw_age) == 4) + lastday = a64l (pwent.pw_age+2) * (WEEK/SCALE); + } else { + mindays = 0; + maxdays = 10000L * (DAY/SCALE); + lastday = -1; + } +#ifdef SHADOWPWD + warndays = inactdays = expdays = -1; +#endif /* SHADOWPWD */ + } +#endif /* ATT_AGE */ + + /* + * Print out the expiration fields if the user has + * requested the list option. + */ + + if (lflg) { + if (ruid != 0 && ruid != pwent.pw_uid) { + fprintf(stderr, _("%s: permission denied\n"), Prog); + closelog(); + exit(1); + } + list_fields(); + cleanup(2); + closelog(); + exit(0); + } + + /* + * If none of the fields were changed from the command line, + * let the user interactively change them. + */ + +#ifdef SHADOWPWD + if (! mflg && ! Mflg && ! dflg && ! Wflg && ! Iflg && ! Eflg) +#else + if (! mflg && ! Mflg && ! dflg) +#endif + { + printf(_("Changing the aging information for %s\n"), name); + if (!new_fields()) { + fprintf(stderr, _("%s: error changing fields\n"), Prog); + cleanup(2); + closelog(); + exit(1); + } + } + +#ifdef SHADOWPWD + /* + * There was no shadow entry. The new entry will have the + * encrypted password transferred from the normal password + * file along with the aging information. + */ + + if (sp == 0) { + sp = &spwd; + memzero(&spwd, sizeof spwd); + + spwd.sp_namp = xstrdup (pwent.pw_name); + spwd.sp_pwdp = xstrdup (pwent.pw_passwd); + spwd.sp_flag = -1; + + pwent.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ +#ifdef ATT_AGE + pwent.pw_age = ""; +#endif + if (!pw_update(&pwent)) { + fprintf(stderr, _("%s: can't update password file\n"), Prog); + cleanup(2); + SYSLOG((LOG_ERR, WRITE_FAIL, PASSWD_FILE)); + closelog(); + exit(1); + } +#ifdef NDBM + (void) pw_dbm_update (&pwent); + endpwent (); +#endif + } +#endif /* SHADOWPWD */ + +#ifdef SHADOWPWD + + /* + * Copy the fields back to the shadow file entry and + * write the modified entry back to the shadow file. + * Closing the shadow and password files will commit + * any changes that have been made. + */ + + spwd.sp_max = maxdays; + spwd.sp_min = mindays; + spwd.sp_lstchg = lastday; + spwd.sp_warn = warndays; + spwd.sp_inact = inactdays; + spwd.sp_expire = expdays; + + if (!spw_update(&spwd)) { + fprintf(stderr, _("%s: can't update shadow password file\n"), Prog); + cleanup(2); + SYSLOG((LOG_ERR, WRITE_FAIL, SHADOW_FILE)); + closelog(); + exit(1); + } +#else /* !SHADOWPWD */ + + /* + * fill in the new_age string with the new values + */ + + if (maxdays > (63 * 7) && mindays == 0) { + new_age[0] = '\0'; + } else { + if (maxdays > (63 * 7)) + maxdays = 63 * 7; + + if (mindays > (63 * 7)) + mindays = 63 * 7; + + new_age[0] = i64c (maxdays / 7); + new_age[1] = i64c ((mindays + 6) / 7); + + if (lastday == 0) + new_age[2] = '\0'; + else + strcpy (new_age + 2, l64a (lastday / 7)); + + } + pwent.pw_age = new_age; + + if (!pw_update(&pwent)) { + fprintf(stderr, _("%s: can't update password file\n"), Prog); + cleanup(2); + SYSLOG((LOG_ERR, WRITE_FAIL, PASSWD_FILE)); + closelog(); + exit(1); + } +#endif /* SHADOWPWD */ + +#ifdef NDBM +#ifdef SHADOWPWD + + /* + * See if the shadow DBM file exists and try to update it. + */ + + if (sp_dbm_present() && !sp_dbm_update(&spwd)) { + fprintf(stderr, _("Error updating the DBM password entry.\n")); + cleanup(2); + SYSLOG((LOG_ERR, DBMERROR2)); + closelog(); + exit(1); + } + endspent(); + +#else /* !SHADOWPWD */ + + /* + * See if the password DBM file exists and try to update it. + */ + + if (pw_dbm_present() && !pw_dbm_update(&pwent)) { + fprintf(stderr, _("Error updating the DBM password entry.\n")); + cleanup(2); + SYSLOG((LOG_ERR, DBMERROR2)); + closelog(); + exit(1); + } + endpwent (); +#endif /* SHADOWPWD */ +#endif /* NDBM */ + +#ifdef SHADOWPWD + /* + * Now close the shadow password file, which will cause all + * of the entries to be re-written. + */ + + if (!spw_close()) { + fprintf(stderr, _("%s: can't rewrite shadow password file\n"), Prog); + cleanup(2); + SYSLOG((LOG_ERR, CLOSE_FAIL, SHADOW_FILE)); + closelog(); + exit(1); + } +#endif /* SHADOWPWD */ + + /* + * Close the password file. If any entries were modified, the + * file will be re-written. + */ + + if (!pw_close()) { + fprintf(stderr, _("%s: can't rewrite password file\n"), Prog); + cleanup(2); + SYSLOG((LOG_ERR, CLOSE_FAIL, PASSWD_FILE)); + closelog(); + exit(1); + } + cleanup(2); + SYSLOG((LOG_INFO, AGE_CHANGED, name)); + closelog(); + exit(0); + /*NOTREACHED*/ +} + +/* + * cleanup - unlock any locked password files + */ + +static void +cleanup(int state) +{ + switch (state) { + case 2: +#ifdef SHADOWPWD + spw_unlock (); +#endif + case 1: + pw_unlock (); + case 0: + break; + } +} + +#else /*} !AGING {*/ + +/* + * chage - but there is no age info! + */ + +int +main(int argc, char **argv) +{ + char *Prog; + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + fprintf (stderr, _("%s: no aging information present\n"), Prog); + exit(1); +} + +#endif /*} AGING */ + diff --git a/src/chfn.c b/src/chfn.c new file mode 100644 index 00000000..c9b2b0ed --- /dev/null +++ b/src/chfn.c @@ -0,0 +1,602 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: chfn.c,v 1.15 1999/07/09 18:02:43 marekm Exp $") + +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +#include +#include "pwio.h" +#include "getdef.h" +#include "pwauth.h" + +#ifdef HAVE_SHADOW_H +#include +#endif + +#ifdef USE_PAM +#include "pam_defs.h" +#endif + +/* + * Global variables. + */ + +static char *Prog; +static char fullnm[BUFSIZ]; +static char roomno[BUFSIZ]; +static char workph[BUFSIZ]; +static char homeph[BUFSIZ]; +static char slop[BUFSIZ]; +static int amroot; + +/* + * External identifiers + */ + +extern int optind; +extern char *optarg; +#ifdef NDBM +extern int pw_dbm_mode; +#endif + +/* + * #defines for messages. This facilitates foreign language conversion + * since all messages are defined right here. + */ + +#define WRONGPWD2 "incorrect password for `%s'" +#define PWDBUSY2 "can't lock /etc/passwd\n" +#define OPNERROR2 "can't open /etc/passwd\n" +#define UPDERROR2 "error updating passwd entry\n" +#define DBMERROR2 "error updating DBM passwd entry.\n" +#define NOTROOT2 "can't setuid(0).\n" +#define CLSERROR2 "can't rewrite /etc/passwd.\n" +#define UNLKERROR2 "can't unlock /etc/passwd.\n" +#define CHGGECOS "changed user `%s' information.\n" + +/* local function prototypes */ +static void usage P_((void)); +static int may_change_field P_((int)); +static void new_fields P_((void)); +static char *copy_field P_((char *, char *, char *)); +int main P_((int, char **)); + +/* + * usage - print command line syntax and exit + */ + +static void +usage(void) +{ + if (amroot) + fprintf(stderr, + _("Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ]\n\t[ -h home_ph ] [ -o other ] [ user ]\n"), + Prog); + else + fprintf(stderr, + _("Usage: %s [ -f full_name ] [ -r room_no ] [ -w work_ph ] [ -h home_ph ]\n"), + Prog); + exit(1); +} + + +static int +may_change_field(int field) +{ + const char *cp; + + /* + * CHFN_RESTRICT can now specify exactly which fields may be + * changed by regular users, by using any combination of the + * following letters: + * f - full name + * r - room number + * w - work phone + * h - home phone + * + * This makes it possible to disallow changing the room number + * information, for example - this feature was suggested by + * Maciej 'Tycoon' Majchrowski. + * + * For backward compatibility, "yes" is equivalent to "rwh", + * "no" is equivalent to "frwh". Only root can change anything + * if the string is empty or not defined at all. + */ + if (amroot) + return 1; + cp = getdef_str("CHFN_RESTRICT"); + if (!cp) + cp = ""; + else if (strcmp(cp, "yes") == 0) + cp = "rwh"; + else if (strcmp(cp, "no") == 0) + cp = "frwh"; + if (strchr(cp, field)) + return 1; + return 0; +} + +/* + * new_fields - change the user's GECOS information interactively + * + * prompt the user for each of the four fields and fill in the fields + * from the user's response, or leave alone if nothing was entered. + */ + +static void +new_fields(void) +{ + printf(_("Enter the new value, or press return for the default\n")); + + if (may_change_field('f')) + change_field(fullnm, sizeof fullnm, _("Full Name")); + else + printf(_("\tFull Name: %s\n"), fullnm); + + if (may_change_field('r')) + change_field(roomno, sizeof roomno, _("Room Number")); + else + printf(_("\tRoom Number: %s\n"), roomno); + + if (may_change_field('w')) + change_field(workph, sizeof workph, _("Work Phone")); + else + printf(_("\tWork Phone: %s\n"), workph); + + if (may_change_field('h')) + change_field(homeph, sizeof homeph, _("Home Phone")); + else + printf(_("\tHome Phone: %s\n"), homeph); + + if (amroot) + change_field(slop, sizeof slop, _("Other")); +} + +/* + * copy_field - get the next field from the gecos field + * + * copy_field copies the next field from the gecos field, returning a + * pointer to the field which follows, or NULL if there are no more + * fields. + * + * in - the current GECOS field + * out - where to copy the field to + * extra - fields with '=' get copied here + */ + +static char * +copy_field(char *in, char *out, char *extra) +{ + char *cp = NULL; + + while (in) { + if ((cp = strchr (in, ','))) + *cp++ = '\0'; + + if (! strchr (in, '=')) + break; + + if (extra) { + if (extra[0]) + strcat (extra, ","); + + strcat (extra, in); + } + in = cp; + } + if (in && out) + strcpy (out, in); + + return cp; +} + + +/* + * chfn - change a user's password file information + * + * This command controls the GECOS field information in the + * password file entry. + * + * The valid options are + * + * -f full name + * -r room number + * -w work phone number + * -h home phone number + * -o other information (*) + * + * (*) requires root permission to execute. + */ + +int +main(int argc, char **argv) +{ + char *cp; /* temporary character pointer */ + const struct passwd *pw; /* password file entry */ + struct passwd pwent; /* modified password file entry */ + char old_gecos[BUFSIZ]; /* buffer for old GECOS fields */ + char new_gecos[BUFSIZ]; /* buffer for new GECOS fields */ + int flag; /* flag currently being processed */ + int fflg = 0; /* -f - set full name */ + int rflg = 0; /* -r - set room number */ + int wflg = 0; /* -w - set work phone number */ + int hflg = 0; /* -h - set home phone number */ + int oflg = 0; /* -o - set other information */ + char *user; + + sanitize_env(); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * This command behaves different for root and non-root + * users. + */ + + amroot = (getuid () == 0); +#ifdef NDBM + pw_dbm_mode = O_RDWR; +#endif + + /* + * Get the program name. The program name is used as a + * prefix to most error messages. It is also used as input + * to the openlog() function for error logging. + */ + + Prog = Basename(argv[0]); + + openlog("chfn", LOG_PID, LOG_AUTH); + + /* + * The remaining arguments will be processed one by one and + * executed by this command. The name is the last argument + * if it does not begin with a "-", otherwise the name is + * determined from the environment and must agree with the + * real UID. Also, the UID will be checked for any commands + * which are restricted to root only. + */ + + while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) { + switch (flag) { + case 'f': + if (!may_change_field('f')) { + fprintf(stderr, _("%s: Permission denied.\n"), Prog); + exit(1); + } + fflg++; + STRFCPY(fullnm, optarg); + break; + case 'r': + if (!may_change_field('r')) { + fprintf(stderr, _("%s: Permission denied.\n"), Prog); + exit(1); + } + rflg++; + STRFCPY(roomno, optarg); + break; + case 'w': + if (!may_change_field('w')) { + fprintf(stderr, _("%s: Permission denied.\n"), Prog); + exit(1); + } + wflg++; + STRFCPY(workph, optarg); + break; + case 'h': + if (!may_change_field('h')) { + fprintf(stderr, _("%s: Permission denied.\n"), Prog); + exit(1); + } + hflg++; + STRFCPY(homeph, optarg); + break; + case 'o': + if (!amroot) { + fprintf(stderr, _("%s: Permission denied.\n"), Prog); + exit(1); + } + oflg++; + STRFCPY(slop, optarg); + break; + default: + usage(); + } + } + + /* + * Get the name of the user to check. It is either + * the command line name, or the name getlogin() + * returns. + */ + + if (optind < argc) { + user = argv[optind]; + pw = getpwnam(user); + if (!pw) { + fprintf(stderr, _("%s: Unknown user %s\n"), Prog, user); + exit(1); + } + } else { + pw = get_my_pwent(); + if (!pw) { + fprintf(stderr, _("%s: Cannot determine your user name.\n"), Prog); + exit(1); + } + user = xstrdup(pw->pw_name); + } + +#ifdef USE_NIS + /* + * Now we make sure this is a LOCAL password entry for + * this user ... + */ + + if (__ispwNIS ()) { + char *nis_domain; + char *nis_master; + + fprintf (stderr, _("%s: cannot change user `%s' on NIS client.\n"), Prog, user); + + if (! yp_get_default_domain (&nis_domain) && + ! yp_master (nis_domain, "passwd.byname", + &nis_master)) { + fprintf (stderr, _("%s: `%s' is the NIS master for this client.\n"), Prog, nis_master); + } + exit (1); + } +#endif + + /* + * Non-privileged users are only allowed to change the + * gecos field if the UID of the user matches the current + * real UID. + */ + + if (!amroot && pw->pw_uid != getuid()) { + fprintf (stderr, _("%s: Permission denied.\n"), Prog); + closelog(); + exit(1); + } + + /* + * Non-privileged users are optionally authenticated + * (must enter the password of the user whose information + * is being changed) before any changes can be made. + * Idea from util-linux chfn/chsh. --marekm + */ + + if (!amroot && getdef_bool("CHFN_AUTH")) + passwd_check(pw->pw_name, pw->pw_passwd, "chfn"); + + /* + * Now get the full name. It is the first comma separated field + * in the GECOS field. + */ + + STRFCPY(old_gecos, pw->pw_gecos); + cp = copy_field (old_gecos, fflg ? (char *) 0:fullnm, slop); + + /* + * Now get the room number. It is the next comma separated field, + * if there is indeed one. + */ + + if (cp) + cp = copy_field (cp, rflg ? (char *) 0:roomno, slop); + + /* + * Now get the work phone number. It is the third field. + */ + + if (cp) + cp = copy_field (cp, wflg ? (char *) 0:workph, slop); + + /* + * Now get the home phone number. It is the fourth field. + */ + + if (cp) + cp = copy_field (cp, hflg ? (char *) 0:homeph, slop); + + /* + * Anything left over is "slop". + */ + + if (cp && !oflg) { + if (slop[0]) + strcat (slop, ","); + + strcat (slop, cp); + } + + /* + * If none of the fields were changed from the command line, + * let the user interactively change them. + */ + + if (!fflg && !rflg && !wflg && !hflg && !oflg) { + printf(_("Changing the user information for %s\n"), user); + new_fields(); + } + + /* + * Check all of the fields for valid information + */ + + if (valid_field(fullnm, ":,=")) { + fprintf(stderr, _("%s: invalid name: \"%s\"\n"), Prog, fullnm); + closelog(); + exit(1); + } + if (valid_field(roomno, ":,=")) { + fprintf(stderr, _("%s: invalid room number: \"%s\"\n"), Prog, roomno); + closelog(); + exit(1); + } + if (valid_field(workph, ":,=")) { + fprintf(stderr, _("%s: invalid work phone: \"%s\"\n"), Prog, workph); + closelog(); + exit(1); + } + if (valid_field (homeph, ":,=")) { + fprintf(stderr, _("%s: invalid home phone: \"%s\"\n"), Prog, homeph); + closelog(); + exit(1); + } + if (valid_field(slop, ":")) { + fprintf(stderr, _("%s: \"%s\" contains illegal characters\n"), Prog, slop); + closelog(); + exit(1); + } + + /* + * Build the new GECOS field by plastering all the pieces together, + * if they will fit ... + */ + + if (strlen(fullnm) + strlen(roomno) + strlen(workph) + + strlen(homeph) + strlen(slop) > (unsigned int) 80) { + fprintf(stderr, _("%s: fields too long\n"), Prog); + closelog(); + exit(1); + } + snprintf(new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s", + fullnm, roomno, workph, homeph, slop[0] ? "," : "", slop); + + /* + * Before going any further, raise the ulimit to prevent + * colliding into a lowered ulimit, and set the real UID + * to root to protect against unexpected signals. Any + * keyboard signals are set to be ignored. + */ + + if (setuid(0)) { + fprintf(stderr, _("Cannot change ID to root.\n")); + SYSLOG((LOG_ERR, NOTROOT2)); + closelog(); + exit(1); + } + pwd_init(); + + /* + * The passwd entry is now ready to be committed back to + * the password file. Get a lock on the file and open it. + */ + + if (!pw_lock()) { + fprintf(stderr, _("Cannot lock the password file; try again later.\n")); + SYSLOG((LOG_WARN, PWDBUSY2)); + closelog(); + exit(1); + } + if (!pw_open(O_RDWR)) { + fprintf(stderr, _("Cannot open the password file.\n")); + pw_unlock(); + SYSLOG((LOG_ERR, OPNERROR2)); + closelog(); + exit(1); + } + + /* + * Get the entry to update using pw_locate() - we want the real + * one from /etc/passwd, not the one from getpwnam() which could + * contain the shadow password if (despite the warnings) someone + * enables AUTOSHADOW (or SHADOW_COMPAT in libc). --marekm + */ + pw = pw_locate(user); + if (!pw) { + pw_unlock(); + fprintf(stderr, + _("%s: %s not found in /etc/passwd\n"), Prog, user); + exit(1); + } + + /* + * Make a copy of the entry, then change the gecos field. The other + * fields remain unchanged. + */ + pwent = *pw; + pwent.pw_gecos = new_gecos; + + /* + * Update the passwd file entry. If there is a DBM file, + * update that entry as well. + */ + + if (!pw_update(&pwent)) { + fprintf(stderr, _("Error updating the password entry.\n")); + pw_unlock(); + SYSLOG((LOG_ERR, UPDERROR2)); + closelog(); + exit(1); + } +#ifdef NDBM + if (pw_dbm_present() && !pw_dbm_update(&pwent)) { + fprintf(stderr, _("Error updating the DBM password entry.\n")); + pw_unlock (); + SYSLOG((LOG_ERR, DBMERROR2)); + closelog(); + exit(1); + } + endpwent(); +#endif + + /* + * Changes have all been made, so commit them and unlock the + * file. + */ + + if (!pw_close()) { + fprintf(stderr, _("Cannot commit password file changes.\n")); + pw_unlock(); + SYSLOG((LOG_ERR, CLSERROR2)); + closelog(); + exit(1); + } + if (!pw_unlock()) { + fprintf(stderr, _("Cannot unlock the password file.\n")); + SYSLOG((LOG_ERR, UNLKERROR2)); + closelog(); + exit(1); + } + SYSLOG((LOG_INFO, CHGGECOS, user)); + closelog(); + exit (0); +} diff --git a/src/chpasswd.c b/src/chpasswd.c new file mode 100644 index 00000000..09ba0061 --- /dev/null +++ b/src/chpasswd.c @@ -0,0 +1,290 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * chpasswd - update passwords in batch + * + * chpasswd reads standard input for a list of colon separated + * user names and new passwords. the appropriate password + * files are updated to reflect the changes. because the + * changes are made in a batch fashion, the user must run + * the mkpasswd command after this command terminates since + * no password updates occur until the very end. + * + * 1997/07/29: Modified to take "-e" argument which specifies that + * the passwords have already been encrypted. + * -- Jay Soffian + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: chpasswd.c,v 1.9 1999/06/07 16:40:45 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include +#include +#include "pwio.h" +#ifdef SHADOWPWD +#include "shadowio.h" +#endif + +static char *Prog; +static int eflg = 0; +#ifdef SHADOWPWD +static int is_shadow_pwd; +#endif + +extern char *crypt_make_salt P_((void)); +extern char *l64a(); + +/* local function prototypes */ +static void usage P_((void)); +int main P_((int, char **)); + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("usage: %s [-e]\n"), Prog); + exit(1); +} + +int +main(int argc, char **argv) +{ + char buf[BUFSIZ]; + char *name; + char *newpwd; + char *cp; +#ifdef SHADOWPWD + const struct spwd *sp; + struct spwd newsp; +#endif + const struct passwd *pw; + struct passwd newpw; +#ifdef ATT_AGE + char newage[5]; +#endif + int errors = 0; + int line = 0; + long now = time ((long *) 0) / (24L*3600L); + int ok; + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* XXX - use getopt() */ + if (!(argc == 1 || (argc == 2 && !strcmp(argv[1], "-e")))) + usage(); + if (argc == 2) + eflg = 1; + + /* + * Lock the password file and open it for reading. This will + * bring all of the entries into memory where they may be + * updated. + */ + + if (!pw_lock()) { + fprintf(stderr, _("%s: can't lock password file\n"), Prog); + exit(1); + } + if (! pw_open (O_RDWR)) { + fprintf(stderr, _("%s: can't open password file\n"), Prog); + pw_unlock(); + exit(1); + } +#ifdef SHADOWPWD + is_shadow_pwd = spw_file_present(); + if (is_shadow_pwd) { + if (!spw_lock()) { + fprintf(stderr, _("%s: can't lock shadow file\n"), Prog); + pw_unlock(); + exit(1); + } + if (!spw_open(O_RDWR)) { + fprintf(stderr, _("%s: can't open shadow file\n"), Prog); + pw_unlock(); + spw_unlock(); + exit(1); + } + } +#endif + + /* + * Read each line, separating the user name from the password. + * The password entry for each user will be looked up in the + * appropriate file (shadow or passwd) and the password changed. + * For shadow files the last change date is set directly, for + * passwd files the last change date is set in the age only if + * aging information is present. + */ + + while (fgets (buf, sizeof buf, stdin) != (char *) 0) { + line++; + if ((cp = strrchr (buf, '\n'))) { + *cp = '\0'; + } else { + fprintf(stderr, _("%s: line %d: line too long\n"), + Prog, line); + errors++; + continue; + } + + /* + * The username is the first field. It is separated + * from the password with a ":" character which is + * replaced with a NUL to give the new password. The + * new password will then be encrypted in the normal + * fashion with a new salt generated, unless the '-e' + * is given, in which case it is assumed to already be + * encrypted. + */ + + name = buf; + if ((cp = strchr (name, ':'))) { + *cp++ = '\0'; + } else { + fprintf(stderr, _("%s: line %d: missing new password\n"), + Prog, line); + errors++; + continue; + } + newpwd = cp; + if (!eflg) + cp = pw_encrypt(newpwd, crypt_make_salt()); + + /* + * Get the password file entry for this user. The user + * must already exist. + */ + + pw = pw_locate(name); + if (!pw) { + fprintf (stderr, _("%s: line %d: unknown user %s\n"), + Prog, line, name); + errors++; + continue; + } + +#ifdef SHADOWPWD + if (is_shadow_pwd) + sp = spw_locate(name); + else + sp = NULL; +#endif + + /* + * The freshly encrypted new password is merged into + * the user's password file entry and the last password + * change date is set to the current date. + */ + +#ifdef SHADOWPWD + if (sp) { + newsp = *sp; + newsp.sp_pwdp = cp; + newsp.sp_lstchg = now; + } else +#endif + { + newpw = *pw; + newpw.pw_passwd = cp; +#ifdef ATT_AGE + if (newpw.pw_age[0]) { + strcpy(newage, newpw.pw_age); + strcpy(newage + 2, l64a(now / 7)); + newpw.pw_age = newage; + } +#endif + } + + /* + * The updated password file entry is then put back + * and will be written to the password file later, after + * all the other entries have been updated as well. + */ + +#ifdef SHADOWPWD + if (sp) + ok = spw_update(&newsp); + else +#endif + ok = pw_update(&newpw); + + if (!ok) { + fprintf(stderr, _("%s: line %d: cannot update password entry\n"), + Prog, line); + errors++; + continue; + } + } + + /* + * Any detected errors will cause the entire set of changes + * to be aborted. Unlocking the password file will cause + * all of the changes to be ignored. Otherwise the file is + * closed, causing the changes to be written out all at + * once, and then unlocked afterwards. + */ + + if (errors) { + fprintf(stderr, _("%s: error detected, changes ignored\n"), Prog); +#ifdef SHADOWPWD + if (is_shadow_pwd) + spw_unlock(); +#endif + pw_unlock(); + exit(1); + } +#ifdef SHADOWPWD + if (is_shadow_pwd) { + if (!spw_close()) { + fprintf(stderr, _("%s: error updating shadow file\n"), Prog); + pw_unlock(); + exit(1); + } + spw_unlock(); + } +#endif + if (!pw_close()) { + fprintf(stderr, _("%s: error updating password file\n"), Prog); + exit(1); + } + pw_unlock(); + + return (0); +} diff --git a/src/chsh.c b/src/chsh.c new file mode 100644 index 00000000..9737ff20 --- /dev/null +++ b/src/chsh.c @@ -0,0 +1,439 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: chsh.c,v 1.15 1999/07/09 18:02:43 marekm Exp $") + +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +#include +#include "pwio.h" +#include "getdef.h" +#include "pwauth.h" + +#ifdef HAVE_SHADOW_H +#include +#endif + +#ifdef USE_PAM +#include "pam_defs.h" +#endif + +#ifndef SHELLS_FILE +#define SHELLS_FILE "/etc/shells" +#endif + +/* + * Global variables. + */ + +static char *Prog; /* Program name */ +static int amroot; /* Real UID is root */ +static char loginsh[BUFSIZ]; /* Name of new login shell */ + +/* + * External identifiers + */ + +extern int optind; +extern char *optarg; +#ifdef NDBM +extern int pw_dbm_mode; +#endif + +/* + * #defines for messages. This facilitates foreign language conversion + * since all messages are defined right here. + */ + +#define WRONGPWD2 "incorrect password for `%s'" +#define NOPERM2 "can't change shell for `%s'\n" +#define PWDBUSY2 "can't lock /etc/passwd\n" +#define OPNERROR2 "can't open /etc/passwd\n" +#define UPDERROR2 "error updating passwd entry\n" +#define DBMERROR2 "error updating DBM passwd entry.\n" +#define NOTROOT2 "can't setuid(0).\n" +#define CLSERROR2 "can't rewrite /etc/passwd.\n" +#define UNLKERROR2 "can't unlock /etc/passwd.\n" +#define CHGSHELL "changed user `%s' shell to `%s'\n" + +/* local function prototypes */ +static void usage P_((void)); +static void new_fields P_((void)); +static int restricted_shell P_((const char *)); +int main P_((int, char **)); + +/* + * usage - print command line syntax and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("Usage: %s [ -s shell ] [ name ]\n"), Prog); + exit(1); +} + +/* + * new_fields - change the user's login shell information interactively + * + * prompt the user for the login shell and change it according to the + * response, or leave it alone if nothing was entered. + */ + +static void +new_fields(void) +{ + printf(_("Enter the new value, or press return for the default\n")); + change_field(loginsh, sizeof loginsh, _("Login Shell")); +} + +/* + * restricted_shell - return true if the named shell begins with 'r' or 'R' + * + * If the first letter of the filename is 'r' or 'R', the shell is + * considered to be restricted. + */ + +static int +restricted_shell(const char *sh) +{ +#if 0 + char *cp = Basename((char *) sh); + return *cp == 'r' || *cp == 'R'; +#else + /* + * Shells not listed in /etc/shells are considered to be + * restricted. Changed this to avoid confusion with "rc" + * (the plan9 shell - not restricted despite the name + * starting with 'r'). --marekm + */ + return !check_shell(sh); +#endif +} + + +/* + * chsh - this command controls changes to the user's shell + * + * The only supported option is -s which permits the + * the login shell to be set from the command line. + */ + +int +main(int argc, char **argv) +{ + char *user; /* User name */ + int flag; /* Current command line flag */ + int sflg = 0; /* -s - set shell from command line */ + const struct passwd *pw; /* Password entry from /etc/passwd */ + struct passwd pwent; /* New password entry */ + + sanitize_env(); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * This command behaves different for root and non-root + * users. + */ + + amroot = getuid () == 0; +#ifdef NDBM + pw_dbm_mode = O_RDWR; +#endif + + /* + * Get the program name. The program name is used as a + * prefix to most error messages. It is also used as input + * to the openlog() function for error logging. + */ + + Prog = Basename(argv[0]); + + openlog("chsh", LOG_PID, LOG_AUTH); + + /* + * There is only one option, but use getopt() anyway to + * keep things consistent. + */ + + while ((flag = getopt (argc, argv, "s:")) != EOF) { + switch (flag) { + case 's': + sflg++; + STRFCPY(loginsh, optarg); + break; + default: + usage (); + } + } + + /* + * There should be only one remaining argument at most + * and it should be the user's name. + */ + + if (argc > optind + 1) + usage (); + + /* + * Get the name of the user to check. It is either + * the command line name, or the name getlogin() + * returns. + */ + + if (optind < argc) { + user = argv[optind]; + pw = getpwnam(user); + if (!pw) { + fprintf(stderr, + _("%s: Unknown user %s\n"), + Prog, user); + exit(1); + } + } else { + pw = get_my_pwent(); + if (!pw) { + fprintf(stderr, + _("%s: Cannot determine your user name.\n"), + Prog); + exit(1); + } + user = xstrdup(pw->pw_name); + } + +#ifdef USE_NIS + /* + * Now we make sure this is a LOCAL password entry for + * this user ... + */ + + if (__ispwNIS ()) { + char *nis_domain; + char *nis_master; + + fprintf(stderr, + _("%s: cannot change user `%s' on NIS client.\n"), + Prog, user); + + if (! yp_get_default_domain (&nis_domain) && + ! yp_master (nis_domain, "passwd.byname", + &nis_master)) { + fprintf(stderr, + _("%s: `%s' is the NIS master for this client.\n"), + Prog, nis_master); + } + exit (1); + } +#endif + + /* + * Non-privileged users are only allowed to change the + * shell if the UID of the user matches the current + * real UID. + */ + + if (! amroot && pw->pw_uid != getuid()) { + SYSLOG((LOG_WARN, NOPERM2, user)); + closelog(); + fprintf(stderr, _("You may not change the shell for %s.\n"), + user); + exit(1); + } + + /* + * Non-privileged users are only allowed to change the + * shell if it is not a restricted one. + */ + + if (! amroot && restricted_shell(pw->pw_shell)) { + SYSLOG((LOG_WARN, NOPERM2, user)); + closelog(); + fprintf(stderr, _("You may not change the shell for %s.\n"), + user); + exit(1); + } + + /* + * Non-privileged users are optionally authenticated + * (must enter the password of the user whose information + * is being changed) before any changes can be made. + * Idea from util-linux chfn/chsh. --marekm + */ + + if (!amroot && getdef_bool("CHFN_AUTH")) + passwd_check(pw->pw_name, pw->pw_passwd, "chsh"); + + /* + * Now get the login shell. Either get it from the password + * file, or use the value from the command line. + */ + + if (! sflg) + STRFCPY(loginsh, pw->pw_shell); + + /* + * If the login shell was not set on the command line, + * let the user interactively change it. + */ + + if (! sflg) { + printf(_("Changing the login shell for %s\n"), user); + new_fields(); + } + + /* + * Check all of the fields for valid information. The shell + * field may not contain any illegal characters. Non-privileged + * users are restricted to using the shells in /etc/shells. + * The shell must be executable by the user. + */ + + if (valid_field (loginsh, ":,=")) { + fprintf(stderr, _("%s: Invalid entry: %s\n"), Prog, loginsh); + closelog(); + exit(1); + } + if (!amroot && (!check_shell(loginsh) || access(loginsh, X_OK) != 0)) { + fprintf(stderr, _("%s is an invalid shell.\n"), loginsh); + closelog(); + exit(1); + } + + /* + * Before going any further, raise the ulimit to prevent + * colliding into a lowered ulimit, and set the real UID + * to root to protect against unexpected signals. Any + * keyboard signals are set to be ignored. + */ + + if (setuid(0)) { + SYSLOG((LOG_ERR, NOTROOT2)); + closelog(); + fprintf (stderr, _("Cannot change ID to root.\n")); + exit(1); + } + pwd_init(); + + /* + * The passwd entry is now ready to be committed back to + * the password file. Get a lock on the file and open it. + */ + + if (!pw_lock()) { + SYSLOG((LOG_WARN, PWDBUSY2)); + closelog(); + fprintf(stderr, + _("Cannot lock the password file; try again later.\n")); + exit(1); + } + if (! pw_open (O_RDWR)) { + SYSLOG((LOG_ERR, OPNERROR2)); + closelog(); + fprintf(stderr, _("Cannot open the password file.\n")); + pw_unlock(); + exit(1); + } + + /* + * Get the entry to update using pw_locate() - we want the real + * one from /etc/passwd, not the one from getpwnam() which could + * contain the shadow password if (despite the warnings) someone + * enables AUTOSHADOW (or SHADOW_COMPAT in libc). --marekm + */ + pw = pw_locate(user); + if (!pw) { + pw_unlock(); + fprintf(stderr, + _("%s: %s not found in /etc/passwd\n"), Prog, user); + exit(1); + } + + /* + * Make a copy of the entry, then change the shell field. The other + * fields remain unchanged. + */ + pwent = *pw; + pwent.pw_shell = loginsh; + + /* + * Update the passwd file entry. If there is a DBM file, + * update that entry as well. + */ + + if (!pw_update(&pwent)) { + SYSLOG((LOG_ERR, UPDERROR2)); + closelog(); + fprintf(stderr, _("Error updating the password entry.\n")); + pw_unlock(); + exit(1); + } +#ifdef NDBM + if (pw_dbm_present() && ! pw_dbm_update (&pwent)) { + SYSLOG((LOG_ERR, DBMERROR2)); + closelog(); + fprintf (stderr, _("Error updating the DBM password entry.\n")); + pw_unlock(); + exit(1); + } + endpwent(); +#endif + + /* + * Changes have all been made, so commit them and unlock the + * file. + */ + + if (!pw_close()) { + SYSLOG((LOG_ERR, CLSERROR2)); + closelog(); + fprintf(stderr, _("Cannot commit password file changes.\n")); + pw_unlock(); + exit(1); + } + if (!pw_unlock()) { + SYSLOG((LOG_ERR, UNLKERROR2)); + closelog(); + fprintf(stderr, _("Cannot unlock the password file.\n")); + exit(1); + } + SYSLOG((LOG_INFO, CHGSHELL, user, loginsh)); + closelog(); + exit (0); +} diff --git a/src/dpasswd.c b/src/dpasswd.c new file mode 100644 index 00000000..eeb22ce5 --- /dev/null +++ b/src/dpasswd.c @@ -0,0 +1,261 @@ +/* + * Copyright 1990 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: dpasswd.c,v 1.9 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" +#include "dialup.h" + +#define DTMP "/etc/d_passwd.tmp" + +/* + * Prompts and messages go here. + */ + +#define DIALCHG "changed password for %s\n" +#define DIALADD "added password for %s\n" +#define DIALREM "removed password for %s\n" + +static int aflg = 0; +static int dflg = 0; +static char *Prog; + +extern int optind; +extern char *optarg; + +extern char *crypt_make_salt P_((void)); +extern char *getpass(); + +/* local function prototypes */ +static void usage P_((void)); +int main P_((int, char **)); + +static void +usage(void) +{ + fprintf(stderr, _("Usage: %s [ -(a|d) ] shell\n"), Prog); + exit(1); +} + +int +main(int argc, char **argv) +{ + struct dialup *dial; + struct dialup dent; + struct stat sb; + FILE *fp; + char *sh = 0; + char *cp; + char pass[BUFSIZ]; + int fd; + int found = 0; + int opt; + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + while ((opt = getopt (argc, argv, "a:d:")) != EOF) { + switch (opt) { + case 'a': + aflg++; + sh = optarg; + break; + case 'd': + dflg++; + sh = optarg; + break; + default: + usage (); + } + } + if (! aflg && ! dflg) + aflg++; + + if (! sh) { + if (optind >= argc) + usage (); + else + sh = argv[optind]; + } + if (aflg + dflg != 1) + usage (); + + /* + * Add a new shell to the password file, or update an existing + * entry. Begin by getting an encrypted password for this + * shell. + */ + + if (aflg) { + int tries = 3; + + dent.du_shell = sh; + dent.du_passwd = ""; /* XXX warning: const */ + +again: + if (! (cp = getpass(_("Shell password:")))) + exit (1); + + STRFCPY(pass, cp); + strzero(cp); + + if (! (cp = getpass(_("re-enter Shell password:")))) + exit (1); + + if (strcmp (pass, cp)) { + strzero(pass); + strzero(cp); + fprintf(stderr, + _("%s: Passwords do not match, try again.\n"), + Prog); + + if (--tries) + goto again; + + exit(1); + } + strzero(cp); + dent.du_passwd = pw_encrypt(pass, crypt_make_salt()); + strzero(pass); + } + + /* + * Create the temporary file for the updated dialup password + * information to be placed into. Turn it into a (FILE *) + * for use by putduent(). + */ + + if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) { + snprintf(pass, sizeof pass, _("%s: can't create %s"), Prog, DTMP); + perror (pass); + exit (1); + } + if (! (fp = fdopen (fd, "r+"))) { + snprintf(pass, sizeof pass, _("%s: can't open %s"), Prog, DTMP); + perror (pass); + unlink (DTMP); + exit (1); + } + + /* + * Scan the dialup password file for the named entry, + * copying out other entries along the way. Copying + * stops when a match is found or the file runs out. + */ + + while ((dial = getduent ())) { + if (strcmp (dial->du_shell, sh) == 0) { + found = 1; + break; + } + if (putduent (dial, fp)) + goto failure; + } + + /* + * To delete the entry, just don't copy it. To update + * the entry, output the modified version - works with + * new entries as well. + */ + + if (dflg && ! found) { + fprintf(stderr, _("%s: Shell %s not found.\n"), Prog, sh); + goto failure; + } + if (aflg) + if (putduent (&dent, fp)) + goto failure; + + /* + * Now copy out the remaining entries. Flush and close the + * new file before doing anything nasty to the existing + * file. + */ + + + while ((dial = getduent ())) + if (putduent (dial, fp)) + goto failure; + + if (fflush (fp)) + goto failure; + + fclose (fp); + + /* + * If the original file did not exist, we must create a new + * file with owner "root" and mode 400. Otherwise we copy + * the modes from the existing file to the new file. + * + * After this is done the new file will replace the old file. + */ + + pwd_init(); + + if (! stat (DIALPWD, &sb)) { + chown (DTMP, sb.st_uid, sb.st_gid); + chmod (DTMP, sb.st_mode); + unlink (DIALPWD); + } else { + chown (DTMP, 0, 0); + chmod (DTMP, 0400); + } + if (! link (DTMP, DIALPWD)) + unlink (DTMP); + + if (aflg && ! found) + SYSLOG((LOG_INFO, DIALADD, sh)); + else if (aflg && found) + SYSLOG((LOG_INFO, DIALCHG, sh)); + else if (dflg) + SYSLOG((LOG_INFO, DIALREM, sh)); + + closelog(); + sync (); + exit (0); + +failure: + unlink (DTMP); + closelog(); + exit (1); +} diff --git a/src/expiry.c b/src/expiry.c new file mode 100644 index 00000000..d0a913b9 --- /dev/null +++ b/src/expiry.c @@ -0,0 +1,211 @@ +/* + * Copyright 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: expiry.c,v 1.8 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" +#include "defines.h" +#include + +#ifndef AGING +#if defined(HAVE_USERSEC_H) || defined(SHADOWPWD) +#define AGING 1 +#endif +#endif + +int main P_((int, char **)); + +#if !defined(SHADOWPWD) && !defined(AGING) /*{*/ + +/* + * Not much to do here ... + */ + +int +main(int argc, char **argv) +{ + exit (0); +} + +#else /*} AGING || SHADOWPWD {*/ + +/* local function prototypes */ +static RETSIGTYPE catch P_((int)); +static void usage P_((void)); + +/* + * catch - signal catcher + */ + +static RETSIGTYPE +catch(int sig) +{ + exit (10); +} + +/* + * usage - print syntax message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("Usage: expiry { -f | -c }\n")); + exit(10); +} + +/* + * expiry - check and enforce password expiration policy + * + * expiry checks (-c) the current password expiraction and + * forces (-f) changes when required. It is callable as a + * normal user command. + */ + +int +main(int argc, char **argv) +{ + struct passwd *pwd; +#ifdef SHADOWPWD + struct spwd *spwd; +#endif + char *Prog = argv[0]; + + sanitize_env(); + + /* + * Start by disabling all of the keyboard signals. + */ + + signal (SIGHUP, catch); + signal (SIGINT, catch); + signal (SIGQUIT, catch); +#ifdef SIGTSTP + signal (SIGTSTP, catch); +#endif + + /* + * expiry takes one of two arguments. The default action + * is to give the usage message. + */ + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc != 2 || (strcmp (argv[1], "-f") && strcmp (argv[1], "-c"))) + usage (); + +#if 0 /* could be setgid shadow with /etc/shadow mode 0640 */ + /* + * Make sure I am root. Can't open /etc/shadow without root + * authority. + */ + + if (geteuid () != 0) { + fprintf(stderr, _("%s: WARNING! Must be set-UID root!\n"), + argv[0]); + exit(10); + } +#endif + + /* + * Get user entries for /etc/passwd and /etc/shadow + */ + + if (!(pwd = get_my_pwent())) { + fprintf(stderr, _("%s: unknown user\n"), Prog); + exit(10); + } +#ifdef SHADOWPWD + spwd = getspnam(pwd->pw_name); +#endif + + /* + * If checking accounts, use agecheck() function. + */ + + if (strcmp (argv[1], "-c") == 0) { + + /* + * Print out number of days until expiration. + */ + +#ifdef SHADOWPWD + agecheck (pwd, spwd); +#else + agecheck (pwd); +#endif + + /* + * Exit with status indicating state of account -- + */ + +#ifdef SHADOWPWD + exit (isexpired (pwd, spwd)); +#else + exit (isexpired (pwd)); +#endif + } + + /* + * If forcing password change, use expire() function. + */ + + if (strcmp (argv[1], "-f") == 0) { + + /* + * Just call expire(). It will force the change + * or give a message indicating what to do. And + * it doesn't return at all unless the account + * is unexpired. + */ + +#ifdef SHADOWPWD + expire (pwd, spwd); +#else + expire (pwd); +#endif + exit (0); + } + + /* + * Can't get here ... + */ + + usage (); + exit (1); +} +#endif /*}*/ diff --git a/src/faillog.c b/src/faillog.c new file mode 100644 index 00000000..492a9978 --- /dev/null +++ b/src/faillog.c @@ -0,0 +1,380 @@ +/* + * Copyright 1989 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: faillog.c,v 1.9 1999/07/09 18:02:43 marekm Exp $") + +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" +#include "faillog.h" + +static char *Prog; /* program name */ +static FILE *fail; /* failure file stream */ +static uid_t user; /* one single user, specified on command line */ +static int days; /* number of days to consider for print command */ +static time_t seconds; /* that number of days in seconds */ + +static int + aflg = 0, /* set if all users are to be printed always */ + uflg = 0, /* set if user is a valid user id */ + tflg = 0; /* print is restricted to most recent days */ + +static struct stat statbuf; /* fstat buffer for file size */ + +#if !defined(UNISTD_H) && !defined(STDLIB_H) +extern char *optarg; +#endif + +#define NOW (time((time_t *) 0)) + +/* local function prototypes */ +static void usage P_((void)); +int main P_((int, char **)); +static void print P_((void)); +static void print_one P_((const struct faillog *, uid_t)); +static void reset P_((void)); +static int reset_one P_((uid_t)); +static void setmax P_((int)); +static void setmax_one P_((uid_t, int)); +static void set_locktime P_((long)); +static void set_locktime_one P_((uid_t, long)); + + +static void +usage(void) +{ + fprintf(stderr, + _("usage: %s [-a|-u user] [-m max] [-r] [-t days] [-l locksecs]\n"), + Prog); + exit(1); +} + +int +main(int argc, char **argv) +{ + int c, anyflag = 0; + struct passwd *pwent; + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* try to open for read/write, if that fails - read only */ + + fail = fopen(FAILLOG_FILE, "r+"); + if (!fail) + fail = fopen(FAILLOG_FILE, "r"); + if (!fail) { + perror(FAILLOG_FILE); + exit(1); + } + while ((c = getopt(argc, argv, "al:m:pru:t:")) != EOF) { + switch (c) { + case 'a': + aflg++; + if (uflg) + usage(); + break; + case 'l': + set_locktime((long) atoi(optarg)); + anyflag++; + break; + case 'm': + setmax(atoi(optarg)); + anyflag++; + break; + case 'p': + print(); + anyflag++; + break; + case 'r': + reset(); + anyflag++; + break; + case 'u': + if (aflg) + usage(); + + pwent = getpwnam(optarg); + if (!pwent) { + fprintf(stderr, _("Unknown User: %s\n"), optarg); + exit(1); + } + uflg++; + user = pwent->pw_uid; + break; + case 't': + days = atoi(optarg); + seconds = days * DAY; + tflg++; + break; + default: + usage(); + } + } + /* no flags implies -a -p (= print information for all users) */ + if (!(anyflag || aflg || tflg || uflg)) + aflg++; + /* (-a or -t days or -u user) and no other flags implies -p + (= print information for selected users) */ + if (!anyflag && (aflg || tflg || uflg)) + print(); + fclose(fail); + return 0; + /*NOTREACHED*/ +} + +static void +print(void) +{ + uid_t uid; + off_t offset; + struct faillog faillog; + + if (uflg) { + offset = user * sizeof faillog; + if (fstat(fileno(fail), &statbuf)) { + perror(FAILLOG_FILE); + return; + } + if (offset >= statbuf.st_size) + return; + + fseek(fail, (off_t) user * sizeof faillog, SEEK_SET); + if (fread((char *) &faillog, sizeof faillog, 1, fail) == 1) + print_one(&faillog, user); + else + perror(FAILLOG_FILE); + } else { + for (uid = 0; + fread((char *) &faillog, sizeof faillog, 1, fail) == 1; + uid++) { + + if (aflg == 0 && faillog.fail_cnt == 0) + continue; + + if (aflg == 0 && tflg && + NOW - faillog.fail_time > seconds) + continue; + + if (aflg && faillog.fail_time == 0) + continue; + + print_one(&faillog, uid); + } + } +} + +static void +print_one(const struct faillog *fl, uid_t uid) +{ + static int once; + char *cp; + struct tm *tm; + time_t now; + struct passwd *pwent; +#ifdef HAVE_STRFTIME + char ptime[80]; +#endif + + if (!once) { + printf(_("Username Failures Maximum Latest\n")); + once++; + } + pwent = getpwuid(uid); + time(&now); + tm = localtime(&fl->fail_time); +#ifdef HAVE_STRFTIME + strftime(ptime, sizeof(ptime), "%a %b %e %H:%M:%S %z %Y",tm); + cp = ptime; +#else + cp = asctime(tm); + cp[24] = '\0'; +#endif + if (pwent) { + printf("%-12s %4d %4d", + pwent->pw_name, fl->fail_cnt, fl->fail_max); + if (fl->fail_time) { + printf(_(" %s on %s"), cp, fl->fail_line); + if (fl->fail_locktime) { + if (fl->fail_time + fl->fail_locktime > now + && fl->fail_cnt) + printf(_(" [%lds left]"), + fl->fail_time + fl->fail_locktime - now); + else + printf(_(" [%lds lock]"), fl->fail_locktime); + } + } + putchar('\n'); + } +} + +static void +reset(void) +{ + uid_t uid; + + if (uflg) + reset_one(user); + else + for (uid = 0; reset_one(uid); uid++) + ; +} + +static int +reset_one(uid_t uid) +{ + off_t offset; + struct faillog faillog; + + offset = uid * sizeof faillog; + if (fstat(fileno(fail), &statbuf)) { + perror(FAILLOG_FILE); + return 0; + } + if (offset >= statbuf.st_size) + return 0; + + if (fseek(fail, offset, SEEK_SET) != 0) { + perror(FAILLOG_FILE); + return 0; + } + if (fread((char *) &faillog, sizeof faillog, 1, fail) != 1) { + if (!feof(fail)) + perror(FAILLOG_FILE); + + return 0; + } + if (faillog.fail_cnt == 0) + return 1; /* don't fill in no holes ... */ + + faillog.fail_cnt = 0; + + if (fseek(fail, offset, SEEK_SET) == 0 + && fwrite((char *) &faillog, sizeof faillog, 1, fail) == 1) { + fflush(fail); + return 1; + } else { + perror(FAILLOG_FILE); + } + return 0; +} + +static void +setmax(int max) +{ + struct passwd *pwent; + + if (uflg) { + setmax_one(user, max); + } else { + setpwent(); + while ((pwent = getpwent())) + setmax_one(pwent->pw_uid, max); + } +} + +static void +setmax_one(uid_t uid, int max) +{ + off_t offset; + struct faillog faillog; + + offset = uid * sizeof faillog; + + if (fseek(fail, offset, SEEK_SET) != 0) { + perror(FAILLOG_FILE); + return; + } + if (fread((char *) &faillog, sizeof faillog, 1, fail) != 1) { + if (!feof(fail)) + perror(FAILLOG_FILE); + memzero(&faillog, sizeof faillog); + } + faillog.fail_max = max; + + if (fseek(fail, offset, SEEK_SET) == 0 + && fwrite((char *) &faillog, sizeof faillog, 1, fail) == 1) + fflush(fail); + else + perror(FAILLOG_FILE); +} + +/* + * XXX - this needs to be written properly some day, right now it is + * a quick cut-and-paste hack from the above two functions. --marekm + */ +static void +set_locktime(long locktime) +{ + struct passwd *pwent; + + if (uflg) { + set_locktime_one(user, locktime); + } else { + setpwent(); + while ((pwent = getpwent())) + set_locktime_one(pwent->pw_uid, locktime); + } +} + +static void +set_locktime_one(uid_t uid, long locktime) +{ + off_t offset; + struct faillog faillog; + + offset = uid * sizeof faillog; + + if (fseek(fail, offset, SEEK_SET) != 0) { + perror(FAILLOG_FILE); + return; + } + if (fread((char *) &faillog, sizeof faillog, 1, fail) != 1) { + if (!feof(fail)) + perror(FAILLOG_FILE); + memzero(&faillog, sizeof faillog); + } + faillog.fail_locktime = locktime; + + if (fseek(fail, offset, SEEK_SET) == 0 + && fwrite((char *) &faillog, sizeof faillog, 1, fail) == 1) + fflush(fail); + else + perror(FAILLOG_FILE); +} diff --git a/src/gpasswd.c b/src/gpasswd.c new file mode 100644 index 00000000..eb123510 --- /dev/null +++ b/src/gpasswd.c @@ -0,0 +1,662 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: gpasswd.c,v 1.14 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" + +#include "groupio.h" +#ifdef SHADOWGRP +#include "sgroupio.h" +#endif + +static char *Prog; +#ifdef SHADOWGRP +static int is_shadowgrp; +#endif + +static int + aflg = 0, + Aflg = 0, + dflg = 0, + Mflg = 0, + rflg = 0, + Rflg = 0; + +#ifndef RETRIES +#define RETRIES 3 +#endif + +extern char *crypt_make_salt P_((void)); +extern int optind; +extern char *optarg; +#ifdef NDBM +#ifdef SHADOWGRP +extern int sg_dbm_mode; +#endif +extern int gr_dbm_mode; +#endif + +/* local function prototypes */ +static void usage P_((void)); +static RETSIGTYPE die P_((int)); +static int check_list P_((const char *)); +int main P_((int, char **)); + +/* + * usage - display usage message + */ + +static void +usage(void) +{ + fprintf(stderr, _("usage: %s [-r|-R] group\n"), Prog); + fprintf(stderr, _(" %s [-a user] group\n"), Prog); + fprintf(stderr, _(" %s [-d user] group\n"), Prog); +#ifdef SHADOWGRP + fprintf(stderr, _(" %s [-A user,...] [-M user,...] group\n"), + Prog); +#else + fprintf(stderr, _(" %s [-M user,...] group\n"), Prog); +#endif + exit (1); +} + +/* + * die - set or reset termio modes. + * + * die() is called before processing begins. signal() is then + * called with die() as the signal handler. If signal later + * calls die() with a signal number, the terminal modes are + * then reset. + */ + +static RETSIGTYPE +die(int killed) +{ + static TERMIO sgtty; + + if (killed) + STTY(0, &sgtty); + else + GTTY(0, &sgtty); + + if (killed) { + putchar ('\n'); + fflush (stdout); + exit (killed); + } +} + +/* + * check_list - check a comma-separated list of user names for validity + * + * check_list scans a comma-separated list of user names and checks + * that each listed name exists. + */ + +static int +check_list(const char *users) +{ + const char *start, *end; + char username[32]; + int errors = 0; + int len; + + for (start = users; start && *start; start = end) { + if ((end = strchr (start, ','))) { + len = end - start; + end++; + } else { + len = strlen(start); + } + + if (len > sizeof(username) - 1) + len = sizeof(username) - 1; + strncpy(username, start, len); + username[len] = '\0'; + + /* + * This user must exist. + */ + + if (!getpwnam(username)) { + fprintf(stderr, _("%s: unknown user %s\n"), + Prog, username); + errors++; + } + } + return errors; +} + + +static void +failure(void) +{ + fprintf(stderr, _("Permission denied.\n")); + exit(1); + /*NOTREACHED*/ +} + + +/* + * gpasswd - administer the /etc/group file + * + * -a user add user to the named group + * -d user remove user from the named group + * -r remove password from the named group + * -R restrict access to the named group + * -A user,... make list of users the administrative users + * -M user,... make list of users the group members + */ + +int +main(int argc, char **argv) +{ + int flag; + char *cp; + int amroot; + int retries; + struct group *gr = NULL; + struct group grent; + static char pass[BUFSIZ]; +#ifdef SHADOWGRP + struct sgrp *sg = NULL; + struct sgrp sgent; + char *admins = NULL; +#endif + struct passwd *pw = NULL; + char *myname; + char *user = NULL; + char *group = NULL; + char *members = NULL; + + sanitize_env(); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * Make a note of whether or not this command was invoked + * by root. This will be used to bypass certain checks + * later on. Also, set the real user ID to match the + * effective user ID. This will prevent the invoker from + * issuing signals which would interfer with this command. + */ + + amroot = getuid () == 0; +#ifdef NDBM +#ifdef SHADOWGRP + sg_dbm_mode = O_RDWR; +#endif + gr_dbm_mode = O_RDWR; +#endif + + Prog = Basename(argv[0]); + + openlog("gpasswd", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + setbuf (stdout, (char *) 0); + setbuf (stderr, (char *) 0); + +#ifdef SHADOWGRP + is_shadowgrp = sgr_file_present(); +#endif + while ((flag = getopt (argc, argv, "a:d:grRA:M:")) != EOF) { + switch (flag) { + case 'a': /* add a user */ + user = optarg; + if (!getpwnam(user)) { + fprintf(stderr, _("%s: unknown user %s\n"), + Prog, user); + exit(1); + } + aflg++; + break; +#ifdef SHADOWGRP + case 'A': + if (!amroot) + failure(); + if (!is_shadowgrp) { + fprintf(stderr, + _("%s: shadow group passwords required for -A\n"), + Prog); + exit(2); + } + admins = optarg; + if (check_list(admins)) + exit(1); + Aflg++; + break; +#endif + case 'd': /* delete a user */ + dflg++; + user = optarg; + break; + case 'g': /* no-op from normal password */ + break; + case 'M': + if (!amroot) + failure(); + members = optarg; + if (check_list(members)) + exit(1); + Mflg++; + break; + case 'r': /* remove group password */ + rflg++; + break; + case 'R': /* restrict group password */ + Rflg++; + break; + default: + usage(); + } + } + + /* + * Make sure exclusive flags are exclusive + */ + + if (aflg + dflg + rflg + Rflg + (Aflg || Mflg) > 1) + usage (); + + /* + * Determine the name of the user that invoked this command. + * This is really hit or miss because there are so many ways + * that command can be executed and so many ways to trip up + * the routines that report the user name. + */ + + pw = get_my_pwent(); + if (!pw) { + fprintf(stderr, _("Who are you?\n")); + exit(1); + } + myname = xstrdup(pw->pw_name); + + /* + * Get the name of the group that is being affected. The group + * entry will be completely replicated so it may be modified + * later on. + */ + + /* + * XXX - should get the entry using gr_locate() and modify + * that, getgrnam() could give us a NIS group. --marekm + */ + + if (! (group = argv[optind])) + usage (); + + if (! (gr = getgrnam (group))) { + fprintf (stderr, _("unknown group: %s\n"), group); + exit (1); + } + grent = *gr; + grent.gr_name = xstrdup(gr->gr_name); + grent.gr_passwd = xstrdup(gr->gr_passwd); + + grent.gr_mem = dup_list(gr->gr_mem); +#ifdef SHADOWGRP + if ((sg = getsgnam (group))) { + sgent = *sg; + sgent.sg_name = xstrdup(sg->sg_name); + sgent.sg_passwd = xstrdup(sg->sg_passwd); + + sgent.sg_mem = dup_list(sg->sg_mem); + sgent.sg_adm = dup_list(sg->sg_adm); + } else { + sgent.sg_name = xstrdup(group); + sgent.sg_passwd = grent.gr_passwd; + grent.gr_passwd = "!"; /* XXX warning: const */ + + sgent.sg_mem = dup_list(grent.gr_mem); + + sgent.sg_adm = (char **) xmalloc(sizeof(char *) * 2); +#ifdef FIRST_MEMBER_IS_ADMIN + if (sgent.sg_mem[0]) { + sgent.sg_adm[0] = xstrdup(sgent.sg_mem[0]); + sgent.sg_adm[1] = 0; + } else +#endif + sgent.sg_adm[0] = 0; + + sg = &sgent; + } + + /* + * The policy here for changing a group is that 1) you must be + * root or 2). you must be listed as an administrative member. + * Administrative members can do anything to a group that the + * root user can. + */ + + if (!amroot && !is_on_list(sgent.sg_adm, myname)) + failure(); +#else /* ! SHADOWGRP */ + +#ifdef FIRST_MEMBER_IS_ADMIN + /* + * The policy here for changing a group is that 1) you must bes + * root or 2) you must be the first listed member of the group. + * The first listed member of a group can do anything to that + * group that the root user can. The rationale for this hack is + * that the FIRST user is probably the most important user in + * this entire group. + */ + + if (! amroot) { + if (grent.gr_mem[0] == (char *) 0) + failure(); + + if (strcmp(grent.gr_mem[0], myname) != 0) + failure(); + } +#else + /* + * This feature enabled by default could be a security problem + * when installed on existing systems where the first group + * member might be just a normal user... --marekm + */ + + if (!amroot) + failure(); +#endif + +#endif /* SHADOWGRP */ + + /* + * Removing a password is straight forward. Just set the + * password field to a "". + */ + + if (rflg) { + grent.gr_passwd = ""; /* XXX warning: const */ +#ifdef SHADOWGRP + sgent.sg_passwd = ""; /* XXX warning: const */ +#endif + SYSLOG((LOG_INFO, "remove password from group %s by %s\n", group, myname)); + goto output; + } else if (Rflg) { + /* + * Same thing for restricting the group. Set the password + * field to "!". + */ + + grent.gr_passwd = "!"; /* XXX warning: const */ +#ifdef SHADOWGRP + sgent.sg_passwd = "!"; /* XXX warning: const */ +#endif + SYSLOG((LOG_INFO, "restrict access to group %s by %s\n", group, myname)); + goto output; + } + + /* + * Adding a member to a member list is pretty straightforward + * as well. Call the appropriate routine and split. + */ + + if (aflg) { + printf(_("Adding user %s to group %s\n"), user, group); + grent.gr_mem = add_list (grent.gr_mem, user); +#ifdef SHADOWGRP + sgent.sg_mem = add_list (sgent.sg_mem, user); +#endif + SYSLOG((LOG_INFO, "add member %s to group %s by %s\n", user, group, myname)); + goto output; + } + + /* + * Removing a member from the member list is the same deal + * as adding one, except the routine is different. + */ + + if (dflg) { + int removed = 0; + + printf(_("Removing user %s from group %s\n"), user, group); + + if (is_on_list(grent.gr_mem, user)) { + removed = 1; + grent.gr_mem = del_list (grent.gr_mem, user); + } +#ifdef SHADOWGRP + if (is_on_list(sgent.sg_mem, user)) { + removed = 1; + sgent.sg_mem = del_list (sgent.sg_mem, user); + } +#endif + if (! removed) { + fprintf(stderr, _("%s: unknown member %s\n"), + Prog, user); + exit (1); + } + SYSLOG((LOG_INFO, "remove member %s from group %s by %s\n", + user, group, myname)); + goto output; + } + +#ifdef SHADOWGRP + /* + * Replacing the entire list of administators is simple. Check the + * list to make sure everyone is a real user. Then slap the new + * list in place. + */ + + if (Aflg) { + SYSLOG((LOG_INFO, "set administrators of %s to %s\n", + group, admins)); + sgent.sg_adm = comma_to_list(admins); + if (!Mflg) + goto output; + } +#endif + + /* + * Replacing the entire list of members is simple. Check the list + * to make sure everyone is a real user. Then slap the new list + * in place. + */ + + if (Mflg) { + SYSLOG((LOG_INFO,"set members of %s to %s\n",group,members)); +#ifdef SHADOWGRP + sgent.sg_mem = comma_to_list(members); +#endif + grent.gr_mem = comma_to_list(members); + goto output; + } + + /* + * If the password is being changed, the input and output must + * both be a tty. The typical keyboard signals are caught + * so the termio modes can be restored. + */ + + if (! isatty (0) || ! isatty (1)) { + fprintf(stderr, _("%s: Not a tty\n"), Prog); + exit (1); + } + + die (0); /* save tty modes */ + + signal (SIGHUP, die); + signal (SIGINT, die); + signal (SIGQUIT, die); + signal (SIGTERM, die); +#ifdef SIGTSTP + signal (SIGTSTP, die); +#endif + + /* + * A new password is to be entered and it must be encrypted, + * etc. The password will be prompted for twice, and both + * entries must be identical. There is no need to validate + * the old password since the invoker is either the group + * owner, or root. + */ + + printf(_("Changing the password for group %s\n"), group); + + for (retries = 0; retries < RETRIES; retries++) { + if (! (cp = getpass(_("New Password:")))) + exit (1); + + STRFCPY(pass, cp); + strzero(cp); + if (! (cp = getpass (_("Re-enter new password:")))) + exit (1); + + if (strcmp(pass, cp) == 0) { + strzero(cp); + break; + } + + strzero(cp); + memzero(pass, sizeof pass); + + if (retries + 1 < RETRIES) + puts(_("They don't match; try again")); + } + + if (retries == RETRIES) { + fprintf(stderr, _("%s: Try again later\n"), Prog); + exit(1); + } + + cp = pw_encrypt(pass, crypt_make_salt()); + memzero(pass, sizeof pass); +#ifdef SHADOWGRP + sgent.sg_passwd = cp; +#else + grent.gr_passwd = cp; +#endif + SYSLOG((LOG_INFO, "change the password for group %s by %s\n", group, myname)); + + /* + * This is the common arrival point to output the new group + * file. The freshly crafted entry is in allocated space. + * The group file will be locked and opened for writing. The + * new entry will be output, etc. + */ + +output: + if (setuid(0)) { + fprintf(stderr, _("Cannot change ID to root.\n")); + SYSLOG((LOG_ERR, "can't setuid(0)")); + closelog(); + exit(1); + } + pwd_init(); + + if (! gr_lock ()) { + fprintf(stderr, _("%s: can't get lock\n"), Prog); + SYSLOG((LOG_WARN, "failed to get lock for /etc/group\n")); + exit (1); + } +#ifdef SHADOWGRP + if (is_shadowgrp && ! sgr_lock ()) { + fprintf(stderr, _("%s: can't get shadow lock\n"), Prog); + SYSLOG((LOG_WARN, "failed to get lock for /etc/gshadow\n")); + exit (1); + } +#endif + if (! gr_open (O_RDWR)) { + fprintf(stderr, _("%s: can't open file\n"), Prog); + SYSLOG((LOG_WARN, "cannot open /etc/group\n")); + exit (1); + } +#ifdef SHADOWGRP + if (is_shadowgrp && ! sgr_open (O_RDWR)) { + fprintf(stderr, _("%s: can't open shadow file\n"), Prog); + SYSLOG((LOG_WARN, "cannot open /etc/gshadow\n")); + exit (1); + } +#endif + if (! gr_update (&grent)) { + fprintf(stderr, _("%s: can't update entry\n"), Prog); + SYSLOG((LOG_WARN, "cannot update /etc/group\n")); + exit (1); + } +#ifdef SHADOWGRP + if (is_shadowgrp && ! sgr_update (&sgent)) { + fprintf(stderr, _("%s: can't update shadow entry\n"), Prog); + SYSLOG((LOG_WARN, "cannot update /etc/gshadow\n")); + exit (1); + } +#endif + if (! gr_close ()) { + fprintf(stderr, _("%s: can't re-write file\n"), Prog); + SYSLOG((LOG_WARN, "cannot re-write /etc/group\n")); + exit (1); + } +#ifdef SHADOWGRP + if (is_shadowgrp && ! sgr_close ()) { + fprintf(stderr, _("%s: can't re-write shadow file\n"), Prog); + SYSLOG((LOG_WARN, "cannot re-write /etc/gshadow\n")); + exit (1); + } + if (is_shadowgrp) + sgr_unlock (); +#endif + if (! gr_unlock ()) { + fprintf(stderr, _("%s: can't unlock file\n"), Prog); + exit (1); + } +#ifdef NDBM + if (gr_dbm_present() && ! gr_dbm_update (&grent)) { + fprintf(stderr, _("%s: can't update DBM files\n"), Prog); + SYSLOG((LOG_WARN, "cannot update /etc/group DBM files\n")); + exit (1); + } + endgrent (); +#ifdef SHADOWGRP + if (is_shadowgrp && sg_dbm_present() && ! sg_dbm_update (&sgent)) { + fprintf(stderr, _("%s: can't update DBM shadow files\n"), Prog); + SYSLOG((LOG_WARN, "cannot update /etc/gshadow DBM files\n")); + exit (1); + } + endsgent (); +#endif +#endif + exit (0); + /*NOTREACHED*/ +} diff --git a/src/groupadd.c b/src/groupadd.c new file mode 100644 index 00000000..6af3861c --- /dev/null +++ b/src/groupadd.c @@ -0,0 +1,538 @@ +/* + * Copyright 1991 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: groupadd.c,v 1.14 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include + +#include "defines.h" +#include "prototypes.h" +#include "chkname.h" + +#include "getdef.h" + +#include "groupio.h" + +#ifdef SHADOWGRP +#include "sgroupio.h" + +static int is_shadow_grp; +#endif + +/* + * exit status values + */ + +#define E_SUCCESS 0 /* success */ +#define E_USAGE 2 /* invalid command syntax */ +#define E_BAD_ARG 3 /* invalid argument to option */ +#define E_GID_IN_USE 4 /* gid not unique (when -o not used) */ +#define E_NAME_IN_USE 9 /* group name nut unique */ +#define E_GRP_UPDATE 10 /* can't update group file */ + +static char *group_name; +static gid_t group_id; +static char *empty_list = NULL; + +static char *Prog; + +static int oflg = 0; /* permit non-unique group ID to be specified with -g */ +static int gflg = 0; /* ID value for the new group */ +static int fflg = 0; /* if group already exists, do nothing and exit(0) */ + +#ifdef NDBM +extern int gr_dbm_mode; +extern int sg_dbm_mode; +#endif + +extern int optind; +extern char *optarg; + +/* local function prototypes */ +static void usage P_((void)); +static void new_grent P_((struct group *)); +#ifdef SHADOWGRP +static void new_sgent P_((struct sgrp *)); +#endif +static void grp_update P_((void)); +static void find_new_gid P_((void)); +static void check_new_name P_((void)); +static void process_flags P_((int, char **)); +static void close_files P_((void)); +static void open_files P_((void)); +static void fail_exit P_((int)); +int main P_((int, char **)); + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("usage: groupadd [-g gid [-o]] group\n")); + exit(E_USAGE); +} + +/* + * new_grent - initialize the values in a group file entry + * + * new_grent() takes all of the values that have been entered and + * fills in a (struct group) with them. + */ + +static void +new_grent(struct group *grent) +{ + memzero(grent, sizeof *grent); + grent->gr_name = group_name; + grent->gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ + grent->gr_gid = group_id; + grent->gr_mem = &empty_list; +} + +#ifdef SHADOWGRP +/* + * new_sgent - initialize the values in a shadow group file entry + * + * new_sgent() takes all of the values that have been entered and + * fills in a (struct sgrp) with them. + */ + +static void +new_sgent(struct sgrp *sgent) +{ + memzero(sgent, sizeof *sgent); + sgent->sg_name = group_name; + sgent->sg_passwd = "!"; /* XXX warning: const */ + sgent->sg_adm = &empty_list; + sgent->sg_mem = &empty_list; +} +#endif /* SHADOWGRP */ + +/* + * grp_update - add new group file entries + * + * grp_update() writes the new records to the group files. + */ + +static void +grp_update(void) +{ + struct group grp; +#ifdef SHADOWGRP + struct sgrp sgrp; +#endif /* SHADOWGRP */ + + /* + * Create the initial entries for this new group. + */ + + new_grent (&grp); +#ifdef SHADOWGRP + new_sgent (&sgrp); +#endif /* SHADOWGRP */ + + /* + * Write out the new group file entry. + */ + + if (! gr_update (&grp)) { + fprintf(stderr, _("%s: error adding new group entry\n"), Prog); + fail_exit(E_GRP_UPDATE); + } +#ifdef NDBM + + /* + * Update the DBM group file with the new entry as well. + */ + + if (gr_dbm_present() && ! gr_dbm_update (&grp)) { + fprintf(stderr, _("%s: cannot add new dbm group entry\n"), Prog); + fail_exit(E_GRP_UPDATE); + } + endgrent (); +#endif /* NDBM */ + +#ifdef SHADOWGRP + + /* + * Write out the new shadow group entries as well. + */ + + if (is_shadow_grp && ! sgr_update (&sgrp)) { + fprintf(stderr, _("%s: error adding new group entry\n"), Prog); + fail_exit(E_GRP_UPDATE); + } +#ifdef NDBM + + /* + * Update the DBM group file with the new entry as well. + */ + + if (is_shadow_grp && sg_dbm_present() && ! sg_dbm_update (&sgrp)) { + fprintf(stderr, _("%s: cannot add new dbm group entry\n"), Prog); + fail_exit(E_GRP_UPDATE); + } + endsgent (); +#endif /* NDBM */ +#endif /* SHADOWGRP */ + SYSLOG((LOG_INFO, "new group: name=%s, gid=%d\n", + group_name, group_id)); +} + +/* + * find_new_gid - find the next available GID + * + * find_new_gid() locates the next highest unused GID in the group + * file, or checks the given group ID against the existing ones for + * uniqueness. + */ + +static void +find_new_gid(void) +{ + const struct group *grp; + gid_t gid_min, gid_max; + + gid_min = getdef_num("GID_MIN", 100); + gid_max = getdef_num("GID_MAX", 60000); + + /* + * Start with some GID value if the user didn't provide us with + * one already. + */ + + if (! gflg) + group_id = gid_min; + + /* + * Search the entire group file, either looking for this + * GID (if the user specified one with -g) or looking for the + * largest unused value. + */ + +#ifdef NO_GETGRENT + gr_rewind(); + while ((grp = gr_next())) { +#else + setgrent(); + while ((grp = getgrent())) { +#endif + if (strcmp(group_name, grp->gr_name) == 0) { + if (fflg) { + fail_exit(E_SUCCESS); + } + fprintf(stderr, _("%s: name %s is not unique\n"), + Prog, group_name); + fail_exit(E_NAME_IN_USE); + } + if (gflg && group_id == grp->gr_gid) { + if (fflg) { + /* turn off -g and search again */ + gflg = 0; +#ifdef NO_GETGRENT + gr_rewind(); +#else + setgrent(); +#endif + continue; + } + fprintf(stderr, _("%s: gid %ld is not unique\n"), + Prog, (long) group_id); + fail_exit(E_GID_IN_USE); + } + if (! gflg && grp->gr_gid >= group_id) { + if (grp->gr_gid > gid_max) + continue; + group_id = grp->gr_gid + 1; + } + } + if (!gflg && group_id == gid_max + 1) { + for (group_id = gid_min; group_id < gid_max; group_id++) { +#ifdef NO_GETGRENT + gr_rewind(); + while ((grp = gr_next()) && grp->gr_gid != group_id) + ; + if (!grp) + break; +#else + if (!getgrgid(group_id)) + break; +#endif + } + if (group_id == gid_max) { + fprintf(stderr, _("%s: can't get unique gid\n"), + Prog); + fail_exit(E_GID_IN_USE); + } + } +} + +/* + * check_new_name - check the new name for validity + * + * check_new_name() insures that the new name doesn't contain + * any illegal characters. + */ + +static void +check_new_name(void) +{ + if (check_group_name(group_name)) + return; + + /* + * All invalid group names land here. + */ + + fprintf(stderr, _("%s: %s is a not a valid group name\n"), + Prog, group_name); + + exit(E_BAD_ARG); +} + +/* + * process_flags - perform command line argument setting + * + * process_flags() interprets the command line arguments and sets + * the values that the user will be created with accordingly. The + * values are checked for sanity. + */ + +static void +process_flags(int argc, char **argv) +{ + char *cp; + int arg; + + while ((arg = getopt(argc, argv, "og:O:f")) != EOF) { + switch (arg) { + case 'g': + gflg++; + if (! isdigit (optarg[0])) + usage (); + + group_id = strtol(optarg, &cp, 10); + if (*cp != '\0') { + fprintf(stderr, _("%s: invalid group %s\n"), + Prog, optarg); + fail_exit(E_BAD_ARG); + } + break; + case 'o': + oflg++; + break; + case 'O': + /* + * override login.defs defaults (-O name=value) + * example: -O GID_MIN=100 -O GID_MAX=499 + * note: -O GID_MIN=10,GID_MAX=499 doesn't work yet + */ + cp = strchr(optarg, '='); + if (!cp) { + fprintf(stderr, + _("%s: -O requires NAME=VALUE\n"), + Prog); + exit(E_BAD_ARG); + } + /* terminate name, point to value */ + *cp++ = '\0'; + if (putdef_str(optarg, cp) < 0) + exit(E_BAD_ARG); + break; + case 'f': + /* + * "force" - do nothing, just exit(0), if the + * specified group already exists. With -g, if + * specified gid already exists, choose another + * (unique) gid (turn off -g). Based on the + * RedHat's patch from shadow-utils-970616-9. + */ + fflg++; + break; + default: + usage(); + } + } + + if (oflg && !gflg) + usage(); + + if (optind != argc - 1) + usage(); + + group_name = argv[argc - 1]; + check_new_name(); +} + +/* + * close_files - close all of the files that were opened + * + * close_files() closes all of the files that were opened for this + * new group. This causes any modified entries to be written out. + */ + +static void +close_files(void) +{ + if (!gr_close()) { + fprintf(stderr, _("%s: cannot rewrite group file\n"), Prog); + fail_exit(E_GRP_UPDATE); + } + gr_unlock(); +#ifdef SHADOWGRP + if (is_shadow_grp && !sgr_close()) { + fprintf(stderr, _("%s: cannot rewrite shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } + if (is_shadow_grp) + sgr_unlock (); +#endif /* SHADOWGRP */ +} + +/* + * open_files - lock and open the group files + * + * open_files() opens the two group files. + */ + +static void +open_files(void) +{ + if (! gr_lock ()) { + fprintf(stderr, _("%s: unable to lock group file\n"), Prog); + exit(E_GRP_UPDATE); + } + if (! gr_open (O_RDWR)) { + fprintf(stderr, _("%s: unable to open group file\n"), Prog); + fail_exit(E_GRP_UPDATE); + } +#ifdef SHADOWGRP + if (is_shadow_grp && ! sgr_lock ()) { + fprintf(stderr, _("%s: unable to lock shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } + if (is_shadow_grp && ! sgr_open (O_RDWR)) { + fprintf(stderr, _("%s: unable to open shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } +#endif /* SHADOWGRP */ +} + +/* + * fail_exit - exit with an error code after unlocking files + */ + +static void +fail_exit(int code) +{ + (void) gr_unlock (); +#ifdef SHADOWGRP + if (is_shadow_grp) + sgr_unlock (); +#endif + exit (code); +} + +/* + * main - groupadd command + */ + +int +main(int argc, char **argv) +{ + + /* + * Get my name so that I can use it to report errors. + */ + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + +#ifdef SHADOWGRP + is_shadow_grp = sgr_file_present(); +#endif + + /* + * The open routines for the DBM files don't use read-write + * as the mode, so we have to clue them in. + */ + +#ifdef NDBM + gr_dbm_mode = O_RDWR; +#ifdef SHADOWGRP + sg_dbm_mode = O_RDWR; +#endif /* SHADOWGRP */ +#endif /* NDBM */ + process_flags(argc, argv); + + /* + * Start with a quick check to see if the group exists. + */ + + if (getgrnam(group_name)) { + if (fflg) { + exit(E_SUCCESS); + } + fprintf(stderr, _("%s: group %s exists\n"), Prog, group_name); + exit(E_NAME_IN_USE); + } + + /* + * Do the hard stuff - open the files, create the group entries, + * then close and update the files. + */ + + open_files(); + + if (!gflg || !oflg) + find_new_gid(); + + grp_update(); + + close_files(); + exit(E_SUCCESS); + /*NOTREACHED*/ +} diff --git a/src/groupdel.c b/src/groupdel.c new file mode 100644 index 00000000..82e9b311 --- /dev/null +++ b/src/groupdel.c @@ -0,0 +1,352 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: groupdel.c,v 1.10 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" + +static char *group_name; +static char *Prog; +static int errors; + +#ifdef NDBM +extern int gr_dbm_mode; +extern int sg_dbm_mode; +#endif + +#include "groupio.h" + +#ifdef SHADOWGRP +#include "sgroupio.h" + +static int is_shadow_grp; +#endif + +/* + * exit status values + */ + +#define E_SUCCESS 0 /* success */ +#define E_USAGE 2 /* invalid command syntax */ +#define E_NOTFOUND 6 /* specified group doesn't exist */ +#define E_GROUP_BUSY 8 /* can't remove user's primary group */ +#define E_GRP_UPDATE 10 /* can't update group file */ + +/* local function prototypes */ +static void usage P_((void)); +static void grp_update P_((void)); +static void close_files P_((void)); +static void open_files P_((void)); +static void group_busy P_((gid_t)); +int main P_((int, char **)); + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("usage: groupdel group\n")); + exit(E_USAGE); +} + +/* + * grp_update - update group file entries + * + * grp_update() writes the new records to the group files. + */ + +static void +grp_update(void) +{ +#ifdef NDBM + struct group *ogrp; +#endif + + if (!gr_remove(group_name)) { + fprintf(stderr, _("%s: error removing group entry\n"), Prog); + errors++; + } +#ifdef NDBM + + /* + * Update the DBM group file + */ + + if (gr_dbm_present()) { + if ((ogrp = getgrnam (group_name)) && + ! gr_dbm_remove (ogrp)) { + fprintf(stderr, _("%s: error removing group dbm entry\n"), + Prog); + errors++; + } + } + endgrent (); +#endif /* NDBM */ + +#ifdef SHADOWGRP + + /* + * Delete the shadow group entries as well. + */ + + if (is_shadow_grp && ! sgr_remove (group_name)) { + fprintf(stderr, _("%s: error removing shadow group entry\n"), + Prog); + errors++; + } +#ifdef NDBM + + /* + * Update the DBM shadow group file + */ + + if (is_shadow_grp && sg_dbm_present()) { + if (! sg_dbm_remove (group_name)) { + fprintf(stderr, + _("%s: error removing shadow group dbm entry\n"), + Prog); + errors++; + } + } + endsgent (); +#endif /* NDBM */ +#endif /* SHADOWGRP */ + SYSLOG((LOG_INFO, "remove group `%s'\n", group_name)); + return; +} + +/* + * close_files - close all of the files that were opened + * + * close_files() closes all of the files that were opened for this + * new group. This causes any modified entries to be written out. + */ + +static void +close_files(void) +{ + if (!gr_close()) { + fprintf(stderr, _("%s: cannot rewrite group file\n"), Prog); + errors++; + } + gr_unlock(); +#ifdef SHADOWGRP + if (is_shadow_grp && !sgr_close()) { + fprintf(stderr, _("%s: cannot rewrite shadow group file\n"), + Prog); + errors++; + } + if (is_shadow_grp) + sgr_unlock(); +#endif /* SHADOWGRP */ +} + +/* + * open_files - lock and open the group files + * + * open_files() opens the two group files. + */ + +static void +open_files(void) +{ + if (!gr_lock()) { + fprintf(stderr, _("%s: unable to lock group file\n"), Prog); + exit(E_GRP_UPDATE); + } + if (!gr_open(O_RDWR)) { + fprintf(stderr, _("%s: unable to open group file\n"), Prog); + exit(E_GRP_UPDATE); + } +#ifdef SHADOWGRP + if (is_shadow_grp && !sgr_lock()) { + fprintf(stderr, _("%s: unable to lock shadow group file\n"), + Prog); + exit(E_GRP_UPDATE); + } + if (is_shadow_grp && !sgr_open(O_RDWR)) { + fprintf(stderr, _("%s: unable to open shadow group file\n"), + Prog); + exit(E_GRP_UPDATE); + } +#endif /* SHADOWGRP */ +} + +/* + * group_busy - check if this is any user's primary group + * + * group_busy verifies that this group is not the primary group + * for any user. You must remove all users before you remove + * the group. + */ + +static void +group_busy(gid_t gid) +{ + struct passwd *pwd; + + /* + * Nice slow linear search. + */ + + setpwent (); + + while ((pwd = getpwent ()) && pwd->pw_gid != gid) + ; + + endpwent (); + + /* + * If pwd isn't NULL, it stopped becaues the gid's matched. + */ + + if (pwd == (struct passwd *) 0) + return; + + /* + * Can't remove the group. + */ + + fprintf(stderr, _("%s: cannot remove user's primary group.\n"), Prog); + exit(E_GROUP_BUSY); +} + +/* + * main - groupdel command + * + * The syntax of the groupdel command is + * + * groupdel group + * + * The named group will be deleted. + */ + +int +main(int argc, char **argv) +{ + struct group *grp; + + /* + * Get my name so that I can use it to report errors. + */ + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc != 2) + usage (); + + group_name = argv[1]; + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + +#ifdef SHADOWGRP + is_shadow_grp = sgr_file_present(); +#endif + + /* + * The open routines for the DBM files don't use read-write + * as the mode, so we have to clue them in. + */ + +#ifdef NDBM + gr_dbm_mode = O_RDWR; +#ifdef SHADOWGRP + sg_dbm_mode = O_RDWR; +#endif /* SHADOWGRP */ +#endif /* NDBM */ + + /* + * Start with a quick check to see if the group exists. + */ + + if (! (grp = getgrnam(group_name))) { + fprintf(stderr, _("%s: group %s does not exist\n"), + Prog, group_name); + exit(E_NOTFOUND); + } +#ifdef USE_NIS + + /* + * Make sure this isn't a NIS group + */ + + if (__isgrNIS ()) { + char *nis_domain; + char *nis_master; + + fprintf(stderr, _("%s: group %s is a NIS group\n"), + Prog, group_name); + + if (! yp_get_default_domain (&nis_domain) && + ! yp_master (nis_domain, "group.byname", + &nis_master)) { + fprintf (stderr, _("%s: %s is the NIS master\n"), + Prog, nis_master); + } + exit(E_NOTFOUND); + } +#endif + + /* + * Now check to insure that this isn't the primary group of + * anyone. + */ + + group_busy (grp->gr_gid); + + /* + * Do the hard stuff - open the files, delete the group entries, + * then close and update the files. + */ + + open_files (); + + grp_update (); + + close_files (); + exit(errors == 0 ? E_SUCCESS : E_GRP_UPDATE); + /*NOTREACHED*/ +} diff --git a/src/groupmod.c b/src/groupmod.c new file mode 100644 index 00000000..a12e78e8 --- /dev/null +++ b/src/groupmod.c @@ -0,0 +1,549 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: groupmod.c,v 1.12 1999/07/09 18:02:43 marekm Exp $") + +#include +#include +#include +#include +#include + +#include "prototypes.h" +#include "chkname.h" +#include "defines.h" + +#include "groupio.h" + +#ifdef SHADOWGRP +#include "sgroupio.h" + +static int is_shadow_grp; +#endif + +/* + * exit status values + */ + +#define E_SUCCESS 0 /* success */ +#define E_USAGE 2 /* invalid command syntax */ +#define E_BAD_ARG 3 /* invalid argument to option */ +#define E_GID_IN_USE 4 /* gid already in use (and no -o) */ +#define E_NOTFOUND 6 /* specified group doesn't exist */ +#define E_NAME_IN_USE 9 /* group name already in use */ +#define E_GRP_UPDATE 10 /* can't update group file */ + +static char *group_name; +static char *group_newname; +static gid_t group_id; +static gid_t group_newid; + +static char *Prog; + +static int + oflg = 0, /* permit non-unique group ID to be specified with -g */ + gflg = 0, /* new ID value for the group */ + nflg = 0; /* a new name has been specified for the group */ + +#ifdef NDBM +extern int gr_dbm_mode; +extern int sg_dbm_mode; +#endif + +extern int optind; +extern char *optarg; + +/* local function prototypes */ +static void usage P_((void)); +static void new_grent P_((struct group *)); +#ifdef SHADOWGRP +static void new_sgent P_((struct sgrp *)); +#endif +static void grp_update P_((void)); +static void check_new_gid P_((void)); +static void check_new_name P_((void)); +static void process_flags P_((int, char **)); +static void close_files P_((void)); +static void open_files P_((void)); +int main P_((int, char **)); + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("usage: groupmod [-g gid [-o]] [-n name] group\n")); + exit(E_USAGE); +} + +/* + * new_grent - updates the values in a group file entry + * + * new_grent() takes all of the values that have been entered and + * fills in a (struct group) with them. + */ + +static void +new_grent(struct group *grent) +{ + if (nflg) + grent->gr_name = xstrdup (group_newname); + + if (gflg) + grent->gr_gid = group_newid; +} + +#ifdef SHADOWGRP +/* + * new_sgent - updates the values in a shadow group file entry + * + * new_sgent() takes all of the values that have been entered and + * fills in a (struct sgrp) with them. + */ + +static void +new_sgent(struct sgrp *sgent) +{ + if (nflg) + sgent->sg_name = xstrdup (group_newname); +} +#endif /* SHADOWGRP */ + +/* + * grp_update - update group file entries + * + * grp_update() writes the new records to the group files. + */ + +static void +grp_update(void) +{ + struct group grp; + const struct group *ogrp; +#ifdef SHADOWGRP + struct sgrp sgrp; + const struct sgrp *osgrp = NULL; +#endif /* SHADOWGRP */ + + /* + * Get the current settings for this group. + */ + + ogrp = gr_locate(group_name); + if (!ogrp) { + fprintf(stderr, + _("%s: %s not found in /etc/group\n"), + Prog, group_name); + exit(E_GRP_UPDATE); + } + grp = *ogrp; + new_grent (&grp); +#ifdef SHADOWGRP + if (is_shadow_grp && (osgrp = sgr_locate(group_name))) { + sgrp = *osgrp; + new_sgent (&sgrp); + } +#endif /* SHADOWGRP */ + + /* + * Write out the new group file entry. + */ + + if (!gr_update(&grp)) { + fprintf(stderr, _("%s: error adding new group entry\n"), Prog); + exit(E_GRP_UPDATE); + } + if (nflg && !gr_remove(group_name)) { + fprintf(stderr, _("%s: error removing group entry\n"), Prog); + exit(E_GRP_UPDATE); + } +#ifdef NDBM + + /* + * Update the DBM group file with the new entry as well. + */ + + if (gr_dbm_present()) { + if (!gr_dbm_update(&grp)) { + fprintf(stderr, + _("%s: cannot add new dbm group entry\n"), + Prog); + exit(E_GRP_UPDATE); + } + if (nflg && (ogrp = getgrnam(group_name)) && + !gr_dbm_remove(ogrp)) { + fprintf(stderr, + _("%s: error removing group dbm entry\n"), + Prog); + exit(E_GRP_UPDATE); + } + endgrent (); + } +#endif /* NDBM */ + +#ifdef SHADOWGRP + + /* + * Make sure there was a shadow entry to begin with. Skip + * down to "out" if there wasn't. Can't just return because + * there might be some syslogging to do. + */ + + if (! osgrp) + goto out; + + /* + * Write out the new shadow group entries as well. + */ + + if (!sgr_update(&sgrp)) { + fprintf(stderr, _("%s: error adding new group entry\n"), Prog); + exit(E_GRP_UPDATE); + } + if (nflg && !sgr_remove(group_name)) { + fprintf(stderr, _("%s: error removing group entry\n"), Prog); + exit(E_GRP_UPDATE); + } +#ifdef NDBM + + /* + * Update the DBM shadow group file with the new entry as well. + */ + + if (sg_dbm_present()) { + if (!sg_dbm_update(&sgrp)) { + fprintf(stderr, + _("%s: cannot add new dbm shadow group entry\n"), + Prog); + exit(E_GRP_UPDATE); + } + if (nflg && ! sg_dbm_remove (group_name)) { + fprintf (stderr, + _("%s: error removing shadow group dbm entry\n"), + Prog); + exit(E_GRP_UPDATE); + } + endsgent (); + } +#endif /* NDBM */ +out: +#endif /* SHADOWGRP */ + + if (nflg) + SYSLOG((LOG_INFO, "change group `%s' to `%s'\n", + group_name, group_newname)); + + if (gflg) + SYSLOG((LOG_INFO, "change gid for `%s' to %d\n", + nflg ? group_newname:group_name, group_newid)); +} + +/* + * check_new_gid - check the new GID value for uniqueness + * + * check_new_gid() insures that the new GID value is unique. + */ + +static void +check_new_gid(void) +{ + /* + * First, the easy stuff. If the ID can be duplicated, or if + * the ID didn't really change, just return. If the ID didn't + * change, turn off those flags. No sense doing needless work. + */ + + if (group_id == group_newid) { + gflg = 0; + return; + } + + if (oflg || ! getgrgid (group_newid)) + return; + + /* + * Tell the user what they did wrong. + */ + + fprintf(stderr, + _("%s: %ld is not a unique gid\n"), + Prog, (long) group_newid); + exit(E_GID_IN_USE); +} + +/* + * check_new_name - check the new name for uniqueness + * + * check_new_name() insures that the new name does not exist + * already. You can't have the same name twice, period. + */ + +static void +check_new_name(void) +{ + /* + * Make sure they are actually changing the name. + */ + + if (strcmp(group_name, group_newname) == 0) { + nflg = 0; + return; + } + + if (check_group_name(group_newname)) { + + /* + * If the entry is found, too bad. + */ + + if (getgrnam(group_newname)) { + fprintf(stderr, _("%s: %s is not a unique name\n"), + Prog, group_newname); + exit(E_NAME_IN_USE); + } + return; + } + + /* + * All invalid group names land here. + */ + + fprintf(stderr, _("%s: %s is a not a valid group name\n"), + Prog, group_newname); + exit(E_BAD_ARG); +} + +/* + * process_flags - perform command line argument setting + * + * process_flags() interprets the command line arguments and sets + * the values that the user will be created with accordingly. The + * values are checked for sanity. + */ + +static void +process_flags(int argc, char **argv) +{ + char *end; + int arg; + + while ((arg = getopt (argc, argv, "og:n:")) != EOF) { + switch (arg) { + case 'g': + gflg++; + group_newid = strtol(optarg, &end, 10); + if (*end != '\0') { + fprintf(stderr, + _("%s: invalid group %s\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + break; + case 'n': + nflg++; + group_newname = optarg; + break; + case 'o': + oflg++; + break; + default: + usage (); + } + } + if (oflg && !gflg) + usage(); + + if (optind != argc - 1) + usage(); + + group_name = argv[argc - 1]; +} + +/* + * close_files - close all of the files that were opened + * + * close_files() closes all of the files that were opened for this + * new group. This causes any modified entries to be written out. + */ + +static void +close_files(void) +{ + if (!gr_close()) { + fprintf(stderr, _("%s: cannot rewrite group file\n"), Prog); + exit(E_GRP_UPDATE); + } + gr_unlock(); +#ifdef SHADOWGRP + if (is_shadow_grp && !sgr_close()) { + fprintf(stderr, _("%s: cannot rewrite shadow group file\n"), + Prog); + exit(E_GRP_UPDATE); + } + if (is_shadow_grp) + sgr_unlock (); +#endif /* SHADOWGRP */ +} + +/* + * open_files - lock and open the group files + * + * open_files() opens the two group files. + */ + +static void +open_files(void) +{ + if (!gr_lock()) { + fprintf(stderr, _("%s: unable to lock group file\n"), Prog); + exit(E_GRP_UPDATE); + } + if (!gr_open(O_RDWR)) { + fprintf(stderr, _("%s: unable to open group file\n"), Prog); + exit(E_GRP_UPDATE); + } +#ifdef SHADOWGRP + if (is_shadow_grp && !sgr_lock()) { + fprintf(stderr, _("%s: unable to lock shadow group file\n"), + Prog); + exit(E_GRP_UPDATE); + } + if (is_shadow_grp && !sgr_open(O_RDWR)) { + fprintf(stderr, _("%s: unable to open shadow group file\n"), + Prog); + exit(E_GRP_UPDATE); + } +#endif /* SHADOWGRP */ +} + +/* + * main - groupmod command + * + * The syntax of the groupmod command is + * + * groupmod [ -g gid [ -o ]] [ -n name ] group + * + * The flags are + * -g - specify a new group ID value + * -o - permit the group ID value to be non-unique + * -n - specify a new group name + */ + +int +main(int argc, char **argv) +{ + struct group *grp; + + /* + * Get my name so that I can use it to report errors. + */ + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + +#ifdef SHADOWGRP + is_shadow_grp = sgr_file_present(); +#endif + + /* + * The open routines for the DBM files don't use read-write + * as the mode, so we have to clue them in. + */ + +#ifdef NDBM + gr_dbm_mode = O_RDWR; +#ifdef SHADOWGRP + sg_dbm_mode = O_RDWR; +#endif /* SHADOWGRP */ +#endif /* NDBM */ + process_flags (argc, argv); + + /* + * Start with a quick check to see if the group exists. + */ + + if (!(grp = getgrnam(group_name))) { + fprintf(stderr, _("%s: group %s does not exist\n"), + Prog, group_name); + exit(E_NOTFOUND); + } else + group_id = grp->gr_gid; + +#ifdef USE_NIS + + /* + * Now make sure it isn't an NIS group. + */ + + if (__isgrNIS ()) { + char *nis_domain; + char *nis_master; + + fprintf(stderr, _("%s: group %s is a NIS group\n"), + Prog, group_name); + + if (! yp_get_default_domain (&nis_domain) && + ! yp_master (nis_domain, "group.byname", + &nis_master)) { + fprintf(stderr, _("%s: %s is the NIS master\n"), + Prog, nis_master); + } + exit(E_NOTFOUND); + } +#endif + + if (gflg) + check_new_gid (); + + if (nflg) + check_new_name (); + + /* + * Do the hard stuff - open the files, create the group entries, + * then close and update the files. + */ + + open_files (); + + grp_update (); + + close_files (); + exit(E_SUCCESS); + /*NOTREACHED*/ +} diff --git a/src/groups.c b/src/groups.c new file mode 100644 index 00000000..b3d4d23f --- /dev/null +++ b/src/groups.c @@ -0,0 +1,184 @@ +/* + * Copyright 1991 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: groups.c,v 1.5 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +/* local function prototypes */ +static void print_groups P_((const char *)); +int main P_((int, char **)); + +/* + * print_groups - print the groups which the named user is a member of + * + * print_groups() scans the groups file for the list of groups + * which the user is listed as being a member of. + */ + +static void +print_groups(const char *member) +{ + int groups = 0; + struct group *grp; + struct passwd *pwd; + int flag = 0; + + setgrent (); + + if ((pwd = getpwnam(member)) == 0) { + fprintf(stderr, _("unknown user %s\n"), member); + exit(1); + } + while ((grp = getgrent ())) { + if (is_on_list(grp->gr_mem, member)) { + if (groups++) + putchar (' '); + + printf ("%s", grp->gr_name); + if (grp->gr_gid == pwd->pw_gid) + flag = 1; + } + } + if (! flag && (grp = getgrgid (pwd->pw_gid))) { + if (groups++) + putchar (' '); + + printf ("%s", grp->gr_name); + } + if (groups) + putchar ('\n'); +} + +/* + * groups - print out the groups a process is a member of + */ + +int +main(int argc, char **argv) +{ +#ifdef HAVE_GETGROUPS + int ngroups; + GETGROUPS_T groups[NGROUPS_MAX]; + int pri_grp; + int i; + struct group *gr; +#else + char *logname; + char *getlogin(); +#endif + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc == 1) { + + /* + * Called with no arguments - give the group set + * for the current user. + */ + +#ifdef HAVE_GETGROUPS + /* + * This system supports concurrent group sets, so + * I can ask the system to tell me which groups are + * currently set for this process. + */ + + ngroups = getgroups(NGROUPS_MAX, groups); + if (ngroups < 0) { + perror("getgroups"); + exit(1); + } + + /* + * The groupset includes the primary group as well. + */ + + pri_grp = getegid (); + for (i = 0;i < ngroups;i++) + if (pri_grp == (int) groups[i]) + break; + + if (i != ngroups) + pri_grp = -1; + + /* + * Print out the name of every group in the current + * group set. Unknown groups are printed as their + * decimal group ID values. + */ + + if (pri_grp != -1) { + if ((gr = getgrgid (pri_grp))) + printf ("%s", gr->gr_name); + else + printf ("%d", pri_grp); + } + + for (i = 0;i < ngroups;i++) { + if (i || pri_grp != -1) + putchar (' '); + + if ((gr = getgrgid (groups[i]))) + printf ("%s", gr->gr_name); + else + printf ("%ld", (long) groups[i]); + } + putchar ('\n'); +#else + /* + * This system does not have the getgroups() system + * call, so I must check the groups file directly. + */ + + if ((logname = getlogin ())) + print_groups (logname); + else + exit (1); +#endif + } else { + + /* + * The invoker wanted to know about some other + * user. Use that name to look up the groups instead. + */ + + print_groups (argv[1]); + } + exit (0); +} diff --git a/src/grpck.c b/src/grpck.c new file mode 100644 index 00000000..47cd91d9 --- /dev/null +++ b/src/grpck.c @@ -0,0 +1,650 @@ +/* + * Copyright 1992 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: grpck.c,v 1.12 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" +#include "chkname.h" +#include + +#include "commonio.h" + +#include "groupio.h" +extern void __gr_del_entry P_((const struct commonio_entry *)); +extern struct commonio_entry *__gr_get_head P_((void)); + +#ifdef SHADOWGRP +#include "sgroupio.h" +extern void __sgr_del_entry P_((const struct commonio_entry *)); +extern struct commonio_entry *__sgr_get_head P_((void)); +#endif + +/* + * Exit codes + */ + +#define E_OKAY 0 +#define E_USAGE 1 +#define E_BAD_ENTRY 2 +#define E_CANT_OPEN 3 +#define E_CANT_LOCK 4 +#define E_CANT_UPDATE 5 + +/* + * Global variables + */ + +extern int optind; +extern char *optarg; + +/* + * Local variables + */ + +static char *Prog; +static const char *grp_file = GROUP_FILE; +#ifdef SHADOWGRP +static const char *sgr_file = SGROUP_FILE; +#endif +static int read_only = 0; + +/* local function prototypes */ +static void usage P_((void)); +static int yes_or_no P_((void)); +static void delete_member P_((char **, const char *)); +int main P_((int, char **)); + +/* + * usage - print syntax message and exit + */ + +static void +usage(void) +{ +#ifdef SHADOWGRP + fprintf(stderr, _("Usage: %s [ -r ] [ group [ gshadow ] ]\n"), Prog); +#else + fprintf(stderr, _("Usage: %s [ -r ] [ group ]\n"), Prog); +#endif + exit(E_USAGE); +} + +/* + * yes_or_no - get answer to question from the user + */ + +static int +yes_or_no(void) +{ + char buf[80]; + + /* + * In read-only mode all questions are answered "no". + */ + + if (read_only) { + puts(_("No")); + return 0; + } + + /* + * Get a line and see what the first character is. + */ + + if (fgets(buf, sizeof buf, stdin)) + return buf[0] == 'y' || buf[0] == 'Y'; + + return 0; +} + +/* + * delete_member - delete an entry in a list of members + */ + +static void +delete_member(char **list, const char *member) +{ + int i; + + for (i = 0; list[i]; i++) + if (list[i] == member) + break; + + if (list[i]) + for (; list[i]; i++) + list[i] = list[i + 1]; +} + +/* + * grpck - verify group file integrity + */ + +int +main(int argc, char **argv) +{ + int arg; + int errors = 0; + int deleted = 0; + int i; + struct commonio_entry *gre, *tgre; + struct group *grp; +#ifdef SHADOWGRP + struct commonio_entry *sge, *tsge; + struct sgrp *sgr; + int is_shadow = 0; +#endif + + /* + * Get my name so that I can use it to report errors. + */ + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + /* + * Parse the command line arguments + */ + + while ((arg = getopt(argc, argv, "qr")) != EOF) { + switch (arg) { + case 'q': + /* quiet - ignored for now */ + break; + case 'r': + read_only = 1; + break; + default: + usage(); + } + } + + /* + * Make certain we have the right number of arguments + */ + +#ifdef SHADOWGRP + if (optind != argc && optind + 1 != argc && optind + 2 != argc) +#else + if (optind != argc && optind + 1 != argc) +#endif + usage(); + + /* + * If there are two left over filenames, use those as the + * group and group password filenames. + */ + + if (optind != argc) { + grp_file = argv[optind]; + gr_name(grp_file); + } +#ifdef SHADOWGRP + if (optind + 2 == argc) { + sgr_file = argv[optind + 1]; + sgr_name(sgr_file); + is_shadow = 1; + } else if (optind == argc) + is_shadow = sgr_file_present(); +#endif + + /* + * Lock the files if we aren't in "read-only" mode + */ + + if (!read_only) { + if (!gr_lock()) { + fprintf(stderr, _("%s: cannot lock file %s\n"), Prog, grp_file); + if (optind == argc) + SYSLOG((LOG_WARN,"cannot lock %s\n",grp_file)); + closelog(); + exit(E_CANT_LOCK); + } +#ifdef SHADOWGRP + if (is_shadow && !sgr_lock()) { + fprintf(stderr, _("%s: cannot lock file %s\n"), Prog, sgr_file); + if (optind == argc) + SYSLOG((LOG_WARN,"cannot lock %s\n",sgr_file)); + closelog(); + exit(E_CANT_LOCK); + } +#endif + } + + /* + * Open the files. Use O_RDONLY if we are in read_only mode, + * O_RDWR otherwise. + */ + + if (!gr_open(read_only ? O_RDONLY : O_RDWR)) { + fprintf(stderr, _("%s: cannot open file %s\n"), Prog, grp_file); + if (optind == argc) + SYSLOG((LOG_WARN, "cannot open %s\n", grp_file)); + closelog(); + exit(E_CANT_OPEN); + } +#ifdef SHADOWGRP + if (is_shadow && !sgr_open(read_only ? O_RDONLY : O_RDWR)) { + fprintf(stderr, _("%s: cannot open file %s\n"), Prog, sgr_file); + if (optind == argc) + SYSLOG((LOG_WARN, "cannot open %s\n", sgr_file)); + closelog(); + exit(E_CANT_OPEN); + } +#endif + + /* + * Loop through the entire group file. + */ + + for (gre = __gr_get_head(); gre; gre = gre->next) { + /* + * Skip all NIS entries. + */ + + if (gre->line[0] == '+' || gre->line[0] == '-') + continue; + + /* + * Start with the entries that are completely corrupt. + * They have no (struct group) entry because they couldn't + * be parsed properly. + */ + + if (!gre->entry) { + + /* + * Tell the user this entire line is bogus and + * ask them to delete it. + */ + + printf(_("invalid group file entry\n")); + printf(_("delete line `%s'? "), gre->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (!yes_or_no()) + continue; + + /* + * All group file deletions wind up here. This + * code removes the current entry from the linked + * list. When done, it skips back to the top of + * the loop to try out the next list element. + */ + +delete_gr: + SYSLOG((LOG_INFO, "delete group line `%s'\n", + gre->line)); + deleted++; + + __gr_del_entry(gre); + continue; + } + + /* + * Group structure is good, start using it. + */ + + grp = gre->entry; + + /* + * Make sure this entry has a unique name. + */ + + for (tgre = __gr_get_head(); tgre; tgre = tgre->next) { + + const struct group *ent = tgre->entry; + + /* + * Don't check this entry + */ + + if (tgre == gre) + continue; + + /* + * Don't check invalid entries. + */ + + if (!ent) + continue; + + if (strcmp(grp->gr_name, ent->gr_name) != 0) + continue; + + /* + * Tell the user this entry is a duplicate of + * another and ask them to delete it. + */ + + puts(_("duplicate group entry\n")); + printf(_("delete line `%s'? "), gre->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (yes_or_no()) + goto delete_gr; + } + + /* + * Check for invalid group names. --marekm + */ + if (!check_group_name(grp->gr_name)) { + errors++; + printf(_("invalid group name `%s'\n"), grp->gr_name); + } + + /* + * Check for a Slackware bug. Make sure GID is not -1 + * (it has special meaning for some syscalls). --marekm + */ + + if (grp->gr_gid == (gid_t) -1) { + errors++; + printf(_("group %s: bad GID (%d)\n"), + grp->gr_name, (int) grp->gr_gid); + } + + /* + * Workaround for a NYS libc 5.3.12 bug on RedHat 4.2 - + * groups with no members are returned as groups with + * one member "", causing grpck to fail. --marekm + */ + + if (grp->gr_mem[0] && !grp->gr_mem[1] && *(grp->gr_mem[0]) == '\0') + grp->gr_mem[0] = (char *) 0; + + /* + * Make sure each member exists + */ + + for (i = 0; grp->gr_mem[i]; i++) { + if (getpwnam(grp->gr_mem[i])) + continue; + /* + * Can't find this user. Remove them + * from the list. + */ + + errors++; + printf(_("group %s: no user %s\n"), + grp->gr_name, grp->gr_mem[i]); + printf(_("delete member `%s'? "), grp->gr_mem[i]); + + if (!yes_or_no()) + continue; + + SYSLOG((LOG_INFO, "delete member `%s' group `%s'\n", + grp->gr_mem[i], grp->gr_name)); + deleted++; + delete_member(grp->gr_mem, grp->gr_mem[i]); + gre->changed = 1; + __gr_set_changed(); + } + } + +#ifdef SHADOWGRP + if (!is_shadow) + goto shadow_done; + + /* + * Loop through the entire shadow group file. + */ + + for (sge = __sgr_get_head(); sge; sge = sge->next) { + + /* + * Start with the entries that are completely corrupt. + * They have no (struct sgrp) entry because they couldn't + * be parsed properly. + */ + + if (!sge->entry) { + + /* + * Tell the user this entire line is bogus and + * ask them to delete it. + */ + + printf(_("invalid shadow group file entry\n")); + printf(_("delete line `%s'? "), sge->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (!yes_or_no()) + continue; + + /* + * All shadow group file deletions wind up here. + * This code removes the current entry from the + * linked list. When done, it skips back to the + * top of the loop to try out the next list element. + */ + +delete_sg: + SYSLOG((LOG_INFO, "delete shadow line `%s'\n", + sge->line)); + deleted++; + + __sgr_del_entry(sge); + continue; + } + + /* + * Shadow group structure is good, start using it. + */ + + sgr = sge->entry; + + /* + * Make sure this entry has a unique name. + */ + + for (tsge = __sgr_get_head(); tsge; tsge = tsge->next) { + + const struct sgrp *ent = tsge->entry; + + /* + * Don't check this entry + */ + + if (tsge == sge) + continue; + + /* + * Don't check invalid entries. + */ + + if (!ent) + continue; + + if (strcmp(sgr->sg_name, ent->sg_name) != 0) + continue; + + /* + * Tell the user this entry is a duplicate of + * another and ask them to delete it. + */ + + puts(_("duplicate shadow group entry\n")); + printf(_("delete line `%s'? "), sge->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (yes_or_no()) + goto delete_sg; + } + + /* + * Make sure this entry exists in the /etc/group file. + */ + + if (!gr_locate(sgr->sg_name)) { + puts(_("no matching group file entry\n")); + printf(_("delete line `%s'? "), sge->line); + errors++; + if (yes_or_no()) + goto delete_sg; + } + + /* + * Make sure each administrator exists + */ + + for (i = 0; sgr->sg_adm[i]; i++) { + if (getpwnam(sgr->sg_adm[i])) + continue; + /* + * Can't find this user. Remove them + * from the list. + */ + + errors++; + printf(_("shadow group %s: no administrative user %s\n"), + sgr->sg_name, sgr->sg_adm[i]); + printf(_("delete administrative member `%s'? "), sgr->sg_adm[i]); + + if (!yes_or_no()) + continue; + + SYSLOG((LOG_INFO, + "delete admin `%s' from shadow group `%s'\n", + sgr->sg_adm[i], sgr->sg_name)); + deleted++; + delete_member(sgr->sg_adm, sgr->sg_adm[i]); + sge->changed = 1; + __sgr_set_changed(); + } + + /* + * Make sure each member exists + */ + + for (i = 0; sgr->sg_mem[i]; i++) { + if (getpwnam(sgr->sg_mem[i])) + continue; + + /* + * Can't find this user. Remove them + * from the list. + */ + + errors++; + printf(_("shadow group %s: no user %s\n"), + sgr->sg_name, sgr->sg_mem[i]); + printf(_("delete member `%s'? "), sgr->sg_mem[i]); + + if (!yes_or_no()) + continue; + + SYSLOG((LOG_INFO, + "delete member `%s' from shadow group `%s'\n", + sgr->sg_mem[i], sgr->sg_name)); + deleted++; + delete_member(sgr->sg_mem, sgr->sg_mem[i]); + sge->changed = 1; + __sgr_set_changed(); + } + } + +shadow_done: +#endif /* SHADOWGRP */ + + /* + * All done. If there were no deletions we can just abandon any + * changes to the files. + */ + + if (deleted) { + if (!gr_close()) { + fprintf(stderr, _("%s: cannot update file %s\n"), + Prog, grp_file); + exit(E_CANT_UPDATE); + } +#ifdef SHADOWGRP + if (is_shadow && !sgr_close()) { + fprintf(stderr, _("%s: cannot update file %s\n"), + Prog, sgr_file); + exit(E_CANT_UPDATE); + } +#endif + } + + /* + * Don't be anti-social - unlock the files when you're done. + */ + +#ifdef SHADOWGRP + if (is_shadow) + sgr_unlock(); +#endif + (void) gr_unlock(); + + /* + * Tell the user what we did and exit. + */ + + if (errors) +#ifdef NDBM + printf(deleted ? + _("%s: the files have been updated; run mkpasswd\n") : + _("%s: no changes\n"), Prog); +#else + printf(deleted ? + _("%s: the files have been updated\n") : + _("%s: no changes\n"), Prog); +#endif + + exit(errors ? E_BAD_ENTRY : E_OKAY); +} diff --git a/src/grpconv.c b/src/grpconv.c new file mode 100644 index 00000000..3a62d123 --- /dev/null +++ b/src/grpconv.c @@ -0,0 +1,174 @@ +/* + * grpconv - create or update /etc/gshadow with information from + * /etc/group. + * + * Copyright (C) 1996, Marek Michalkiewicz + * + * This program may be freely used and distributed. If you improve + * it, please send me your changes. Thanks! + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "prototypes.h" + +#ifdef SHADOWGRP + +#include "groupio.h" +#include "sgroupio.h" + +#include "rcsid.h" +RCSID(PKG_VER "$Id: grpconv.c,v 1.10 1999/07/09 18:02:43 marekm Exp $") + +static int group_locked = 0; +static int gshadow_locked = 0; + +/* local function prototypes */ +static void fail_exit P_((int)); +int main P_((int, char **)); + +static void +fail_exit(int status) +{ + if (group_locked) + gr_unlock(); + if (gshadow_locked) + sgr_unlock(); + exit(status); +} + +int +main(int argc, char **argv) +{ + const struct group *gr; + struct group grent; + const struct sgrp *sg; + struct sgrp sgent; + char *Prog = argv[0]; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (!gr_lock()) { + fprintf(stderr, _("%s: can't lock group file\n"), Prog); + fail_exit(5); + } + group_locked++; + if (!gr_open(O_RDWR)) { + fprintf(stderr, _("%s: can't open group file\n"), Prog); + fail_exit(1); + } + + if (!sgr_lock()) { + fprintf(stderr, _("%s: can't lock shadow group file\n"), Prog); + fail_exit(5); + } + gshadow_locked++; + if (!sgr_open(O_CREAT | O_RDWR)) { + fprintf(stderr, _("%s: can't open shadow group file\n"), Prog); + fail_exit(1); + } + + /* + * Remove /etc/gshadow entries for groups not in /etc/group. + */ + sgr_rewind(); + while ((sg = sgr_next())) { + if (gr_locate(sg->sg_name)) + continue; + + if (!sgr_remove(sg->sg_name)) { + /* + * This shouldn't happen (the entry exists) but... + */ + fprintf(stderr, _("%s: can't remove shadow group %s\n"), + Prog, sg->sg_name); + fail_exit(3); + } + } + + /* + * Update shadow group passwords if non-shadow password is not "x". + * Add any missing shadow group entries. + */ + gr_rewind(); + while ((gr = gr_next())) { + sg = sgr_locate(gr->gr_name); + if (sg) { +#if 0 /* because of sg_mem, but see below */ + if (strcmp(gr->gr_passwd, SHADOW_PASSWD_STRING) == 0) + continue; +#endif + /* update existing shadow group entry */ + sgent = *sg; + if (strcmp(gr->gr_passwd, SHADOW_PASSWD_STRING) != 0) + sgent.sg_passwd = gr->gr_passwd; + } else { + static char *empty = 0; + + /* add new shadow group entry */ + memset(&sgent, 0, sizeof sgent); + sgent.sg_name = gr->gr_name; + sgent.sg_passwd = gr->gr_passwd; + sgent.sg_adm = ∅ + } + /* + * XXX - sg_mem is redundant, it is currently always a copy + * of gr_mem. Very few programs actually use sg_mem, and + * all of them are in the shadow suite... Maybe this field + * could be used for something else? Any suggestions? + */ + sgent.sg_mem = gr->gr_mem; + + if (!sgr_update(&sgent)) { + fprintf(stderr, + _("%s: can't update shadow entry for %s\n"), + Prog, sgent.sg_name); + fail_exit(3); + } + /* remove password from /etc/group */ + grent = *gr; + grent.gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ + if (!gr_update(&grent)) { + fprintf(stderr, + _("%s: can't update entry for group %s\n"), + Prog, grent.gr_name); + fail_exit(3); + } + } + + if (!sgr_close()) { + fprintf(stderr, _("%s: can't update shadow group file\n"), Prog); + fail_exit(3); + } + if (!gr_close()) { + fprintf(stderr, _("%s: can't update group file\n"), Prog); + fail_exit(3); + } + sgr_unlock(); + gr_unlock(); + return 0; +} +#else /* !SHADOWGRP */ +int +main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + fprintf(stderr, _("%s: not configured for shadow group support.\n"), + argv[0]); + exit(1); +} +#endif /* !SHADOWGRP */ diff --git a/src/grpunconv.c b/src/grpunconv.c new file mode 100644 index 00000000..3f836ed6 --- /dev/null +++ b/src/grpunconv.c @@ -0,0 +1,132 @@ +/* + * grpunconv - update /etc/group with information from /etc/gshadow. + * + * Copyright (C) 1996, Michael Meskes + * using sources from Marek Michalkiewicz + * + * This program may be freely used and distributed. If you improve + * it, please send me your changes. Thanks! + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: grpunconv.c,v 1.9 1999/07/09 18:02:43 marekm Exp $") + +#include +#include +#include +#include +#include +#include + +#include +#include "prototypes.h" + +#ifdef SHADOWGRP + +#include "groupio.h" +#include "sgroupio.h" + +static int group_locked = 0; +static int gshadow_locked = 0; + +/* local function prototypes */ +static void fail_exit P_((int)); +int main P_((int, char **)); + +static void +fail_exit(int status) +{ + if (group_locked) + gr_unlock(); + if (gshadow_locked) + sgr_unlock(); + exit(status); +} + +int +main(int argc, char **argv) +{ + const struct group *gr; + struct group grent; + const struct sgrp *sg; + char *Prog = argv[0]; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (!sgr_file_present()) + exit(0); /* no /etc/gshadow, nothing to do */ + + if (!gr_lock()) { + fprintf(stderr, _("%s: can't lock group file\n"), Prog); + fail_exit(5); + } + group_locked++; + if (!gr_open(O_RDWR)) { + fprintf(stderr, _("%s: can't open group file\n"), Prog); + fail_exit(1); + } + + if (!sgr_lock()) { + fprintf(stderr, _("%s: can't lock shadow group file\n"), Prog); + fail_exit(5); + } + gshadow_locked++; + if (!sgr_open(O_RDWR)) { + fprintf(stderr, _("%s: can't open shadow group file\n"), Prog); + fail_exit(1); + } + + /* + * Update group passwords if non-shadow password is "x". + */ + gr_rewind(); + while ((gr = gr_next())) { + sg = sgr_locate(gr->gr_name); + if (sg && strcmp(gr->gr_passwd, SHADOW_PASSWD_STRING) == 0) { + /* add password to /etc/group */ + grent = *gr; + grent.gr_passwd = sg->sg_passwd; + if (!gr_update(&grent)) { + fprintf(stderr, + _("%s: can't update entry for group %s\n"), + Prog, grent.gr_name); + fail_exit(3); + } + } + } + + if (!sgr_close()) { + fprintf(stderr, _("%s: can't update shadow group file\n"), Prog); + fail_exit(3); + } + + if (!gr_close()) { + fprintf(stderr, _("%s: can't update group file\n"), Prog); + fail_exit(3); + } + + if (unlink(SGROUP_FILE) != 0) { + fprintf(stderr, _("%s: can't delete shadow group file\n"), Prog); + fail_exit(3); + } + + sgr_unlock(); + gr_unlock(); + return 0; +} +#else /* !SHADOWGRP */ +int +main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + fprintf(stderr, _("%s: not configured for shadow group support.\n"), argv[0]); + exit(1); +} +#endif /* !SHADOWGRP */ diff --git a/src/id.c b/src/id.c new file mode 100644 index 00000000..fa452f89 --- /dev/null +++ b/src/id.c @@ -0,0 +1,188 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * id - print current process user identification information + * + * Print the current process identifiers. This includes the + * UID, GID, effective-UID and effective-GID. Optionally print + * the concurrent group set if the current system supports it. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: id.c,v 1.5 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include "defines.h" + +/* local function prototypes */ +static void usage P_((void)); +int main P_((int, char **)); + +static void +usage(void) +{ +#ifdef HAVE_GETGROUPS + fprintf(stderr, _("usage: id [ -a ]\n")); +#else + fprintf(stderr, _("usage: id\n")); +#endif + exit(1); +} + +/*ARGSUSED*/ +int +main(int argc, char **argv) +{ + uid_t ruid, euid; + gid_t rgid, egid; + int i; +/* + * This block of declarations is particularly strained because of several + * different ways of doing concurrent groups. Old BSD systems used int + * for gid's, but short for the type passed to getgroups(). Newer systems + * use gid_t for everything. Some systems have a small and fixed NGROUPS, + * usually about 16 or 32. Others use bigger values. + */ +#ifdef HAVE_GETGROUPS + GETGROUPS_T groups[NGROUPS_MAX]; + int ngroups; + int aflg = 0; +#endif + struct passwd *pw; + struct group *gr; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + +#ifdef HAVE_GETGROUPS + /* + * See if the -a flag has been given to print out the + * concurrent group set. + */ + + if (argc > 1) { + if (argc > 2 || strcmp (argv[1], "-a")) + usage(); + else + aflg = 1; + } +#else + if (argc > 1) + usage(); +#endif + + ruid = getuid(); + euid = geteuid(); + rgid = getgid(); + egid = getegid(); + + /* + * Print out the real user ID and group ID. If the user or + * group does not exist, just give the numerical value. + */ + + pw = getpwuid(ruid); + if (pw) + printf(_("uid=%d(%s)"), (int) ruid, pw->pw_name); + else + printf(_("uid=%d"), (int) ruid); + + gr = getgrgid(rgid); + if (gr) + printf(_(" gid=%d(%s)"), (int) rgid, gr->gr_name); + else + printf(_(" gid=%d"), (int) rgid); + + /* + * Print out the effective user ID and group ID if they are + * different from the real values. + */ + + if (ruid != euid) { + pw = getpwuid(euid); + if (pw) + printf(_(" euid=%d(%s)"), (int) euid, pw->pw_name); + else + printf(_(" euid=%d"), (int) euid); + } + if (rgid != egid) { + gr = getgrgid(egid); + if (gr) + printf(_(" egid=%d(%s)"), (int) egid, gr->gr_name); + else + printf(_(" egid=%d"), (int) egid); + } + +#ifdef HAVE_GETGROUPS + /* + * Print out the concurrent group set if the user has requested + * it. The group numbers will be printed followed by their + * names. + */ + + if (aflg && (ngroups = getgroups (NGROUPS_MAX, groups)) != -1) { + + /* + * Start off the group message. It will be of the format + * + * groups=###(aaa),###(aaa),###(aaa) + * + * where "###" is a numerical value and "aaa" is the + * corresponding name for each respective numerical value. + */ + + printf(_(" groups=")); + for (i = 0; i < ngroups; i++) { + if (i) + putchar(','); + + gr = getgrgid(groups[i]); + if (gr) + printf("%d(%s)", (int) groups[i], gr->gr_name); + else + printf("%d", (int) groups[i]); + } + } +#endif + + /* + * Finish off the line. + */ + + putchar('\n'); + exit(0); + /*NOTREACHED*/ +} diff --git a/src/lastlog.c b/src/lastlog.c new file mode 100644 index 00000000..fc7eb143 --- /dev/null +++ b/src/lastlog.c @@ -0,0 +1,193 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: lastlog.c,v 1.5 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" +#if HAVE_LASTLOG_H +#include +#else +#include "lastlog_.h" +#endif + +/* + * Needed for MkLinux DR1/2/2.1 - J. + */ +#ifndef LASTLOG_FILE +#define LASTLOG_FILE "/var/log/lastlog" +#endif + +static FILE *lastlogfile; /* lastlog file stream */ +static off_t user; /* one single user, specified on command line */ +static int days; /* number of days to consider for print command */ +static time_t seconds; /* that number of days in seconds */ + +static int uflg = 0; /* set if user is a valid user id */ +static int tflg = 0; /* print is restricted to most recent days */ +static struct lastlog lastlog; /* scratch structure to play with ... */ +static struct stat statbuf; /* fstat buffer for file size */ +static struct passwd *pwent; + +extern char *optarg; + +#define NOW (time ((time_t *) 0)) + +/* local function prototypes */ +int main P_((int, char **)); +static void print P_((void)); +static void print_one P_((const struct passwd *)); + +int +main(int argc, char **argv) +{ + int c; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if ((lastlogfile = fopen (LASTLOG_FILE,"r")) == (FILE *) 0) { + perror (LASTLOG_FILE); + exit (1); + } + while ((c = getopt (argc, argv, "u:t:")) != EOF) { + switch (c) { + case 'u': + pwent = getpwnam (optarg); + if (!pwent) { + fprintf(stderr, + _("Unknown User: %s\n"), + optarg); + exit (1); + } + uflg++; + user = pwent->pw_uid; + break; + case 't': + days = atoi (optarg); + seconds = days * DAY; + tflg++; + break; + } + } + print (); + fclose (lastlogfile); + exit (0); + /*NOTREACHED*/ +} + +static void +print(void) +{ + off_t offset; + + if (uflg) { + offset = (unsigned long) user * sizeof lastlog; + if (fstat (fileno (lastlogfile), &statbuf)) { + perror(LASTLOG_FILE); + return; + } + if (offset >= statbuf.st_size) + return; + + fseek (lastlogfile, offset, SEEK_SET); + if (fread ((char *) &lastlog, sizeof lastlog, 1, + lastlogfile) == 1) + print_one (pwent); + else + perror (LASTLOG_FILE); + } else { + setpwent (); + while ((pwent = getpwent ())) { + user = pwent->pw_uid; + offset = (unsigned long) user * sizeof lastlog; + fseek (lastlogfile, offset, SEEK_SET); + if (fread ((char *) &lastlog, sizeof lastlog, 1, + lastlogfile) != 1) + continue; + + if (tflg && NOW - lastlog.ll_time > seconds) + continue; + + print_one (pwent); + } + } +} + +static void +print_one(const struct passwd *pw) +{ + static int once; + char *cp; + struct tm *tm; +#ifdef HAVE_STRFTIME + char ptime[80]; +#endif + + if (! pw) + return; + + if (! once) { +#ifdef HAVE_LL_HOST + printf(_("Username Port From Latest\n")); +#else + printf(_("Username Port Latest\n")); +#endif + once++; + } + tm = localtime (&lastlog.ll_time); +#ifdef HAVE_STRFTIME + strftime(ptime, sizeof(ptime), "%a %b %e %H:%M:%S %z %Y", tm); + cp = ptime; +#else + cp = asctime (tm); + cp[24] = '\0'; +#endif + + if(lastlog.ll_time == (time_t) 0) + cp = _("**Never logged in**\0"); + +#ifdef HAVE_LL_HOST + printf ("%-16s %-8.8s %-16.16s %s\n", pw->pw_name, + lastlog.ll_line, lastlog.ll_host, cp); +#else + printf ("%-16s\t%-8.8s %s\n", pw->pw_name, + lastlog.ll_line, cp); +#endif +} diff --git a/src/login.c b/src/login.c new file mode 100644 index 00000000..f4906cba --- /dev/null +++ b/src/login.c @@ -0,0 +1,1260 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: login.c,v 1.15 1999/06/07 16:40:45 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include +#include +#include +#include +#include +#if HAVE_UTMPX_H +#include +#else +#include +#endif +#include + +#if HAVE_LASTLOG_H +#include +#else +#include "lastlog_.h" +#endif + +#include "faillog.h" +#include "failure.h" +#include "pwauth.h" +#include "getdef.h" +#include "dialchk.h" + +#ifdef SVR4_SI86_EUA +#include +#include +#endif + +#ifdef RADIUS +/* + * Support for RADIUS authentication based on a hacked util-linux login + * source sent to me by Jon Lewis. Not tested. You need to link login + * with the radauth.c file (not included here - it doesn't have a clear + * copyright statement, and I don't want to have problems with Debian + * putting the whole package in non-free because of this). --marekm + */ +#include "radlogin.h" +#endif + +#ifdef UT_ADDR +#include +#endif + +#ifdef USE_PAM_not_yet +#include "pam_defs.h" + +static const struct pam_conv conv = { + misc_conv, + NULL +}; + +static pam_handle_t *pamh = NULL; + +#define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ + fprintf(stderr,"\n%s\n",PAM_STRERROR(pamh, retcode)); \ + syslog(LOG_ERR,"%s",PAM_STRERROR(pamh, retcode)); \ + pam_end(pamh, retcode); exit(1); \ + } +#define PAM_END { retcode = pam_close_session(pamh,0); \ + pam_end(pamh,retcode); } + +#endif /* USE_PAM_not_yet */ + +/* + * Needed for MkLinux DR1/2/2.1 - J. + */ +#ifndef LASTLOG_FILE +#define LASTLOG_FILE "/var/log/lastlog" +#endif + +const char *hostname = ""; + +struct passwd pwent; +#if HAVE_UTMPX_H +struct utmpx utxent, failent; +struct utmp utent; +#else +struct utmp utent, failent; +#endif +struct lastlog lastlog; +static int pflg = 0; +static int fflg = 0; +#ifdef RLOGIN +static int rflg = 0; +#else +#define rflg 0 +#endif +static int hflg = 0; +static int preauth_flag = 0; + +/* + * Global variables. + */ + +static char *Prog; +static int amroot; +static int timeout; + +/* + * External identifiers. + */ + +extern char **newenvp; +extern size_t newenvc; + +extern char *tz P_((const char *)); +extern void subsystem P_((const struct passwd *)); +extern void dolastlog P_((struct lastlog *, const struct passwd *, const char *, const char *)); + +extern int optind; +extern char *optarg; +extern char **environ; + +extern int login_access P_((const char *user, const char *from)); +extern void login_fbtab P_((const char *tty, uid_t uid, gid_t gid)); + +#ifndef ALARM +#define ALARM 60 +#endif + +#ifndef RETRIES +#define RETRIES 3 +#endif + +static struct faillog faillog; + +#define NO_SHADOW "no shadow password for `%s'%s\n" +#define BAD_PASSWD "invalid password for `%s'%s\n" +#define BAD_DIALUP "invalid dialup password for `%s' on `%s'\n" +#define BAD_TIME "invalid login time for `%s'%s\n" +#define BAD_ROOT_LOGIN "ILLEGAL ROOT LOGIN%s\n" +#define ROOT_LOGIN "ROOT LOGIN%s\n" +#define FAILURE_CNT "exceeded failure limit for `%s'%s\n" +#define REG_LOGIN "`%s' logged in%s\n" +#define LOGIN_REFUSED "LOGIN `%s' REFUSED%s\n" +#define REENABLED2 \ + "login `%s' re-enabled after temporary lockout (%d failures).\n" +#define MANY_FAILS "REPEATED login failures%s\n" + +/* local function prototypes */ +static void usage P_((void)); +static void setup_tty P_((void)); +static void bad_time_notify P_((void)); +static void check_flags P_((int, char * const *)); +static void check_nologin P_((void)); +static void init_env P_((void)); +static RETSIGTYPE alarm_handler P_((int)); +int main P_((int, char **)); + +/* + * usage - print login command usage and exit + * + * login [ name ] + * login -r hostname (for rlogind) + * login -h hostname (for telnetd, etc.) + * login -f name (for pre-authenticated login: datakit, xterm, etc.) + */ + +static void +usage(void) +{ + fprintf(stderr, _("usage: %s [-p] [name]\n"), Prog); + if (!amroot) + exit(1); + fprintf(stderr, _(" %s [-p] [-h host] [-f name]\n"), Prog); +#ifdef RLOGIN + fprintf(stderr, _(" %s [-p] -r host\n"), Prog); +#endif + exit(1); +} + + +static void +setup_tty(void) +{ + TERMIO termio; + + GTTY(0, &termio); /* get terminal characteristics */ + + /* + * Add your favorite terminal modes here ... + */ + +#ifndef USE_SGTTY + termio.c_lflag |= ISIG|ICANON|ECHO|ECHOE; + termio.c_iflag |= ICRNL; + +#if defined(ECHOKE) && defined(ECHOCTL) + termio.c_lflag |= ECHOKE|ECHOCTL; +#endif +#if defined(ECHOPRT) && defined(NOFLSH) && defined(TOSTOP) + termio.c_lflag &= ~(ECHOPRT|NOFLSH|TOSTOP); +#endif +#ifdef ONLCR + termio.c_oflag |= ONLCR; +#endif + +#ifdef SUN4 + + /* + * Terminal setup for SunOS 4.1 courtesy of Steve Allen + * at UCO/Lick. + */ + + termio.c_cc[VEOF] = '\04'; + termio.c_cflag &= ~CSIZE; + termio.c_cflag |= (PARENB|CS7); + termio.c_lflag |= (ISIG|ICANON|ECHO|IEXTEN); + termio.c_iflag |= (BRKINT|IGNPAR|ISTRIP|IMAXBEL|ICRNL|IXON); + termio.c_iflag &= ~IXANY; + termio.c_oflag |= (XTABS|OPOST|ONLCR); +#endif +#if 0 + termio.c_cc[VERASE] = getdef_num("ERASECHAR", '\b'); + termio.c_cc[VKILL] = getdef_num("KILLCHAR", '\025'); +#else + /* leave these values unchanged if not specified in login.defs */ + termio.c_cc[VERASE] = getdef_num("ERASECHAR", termio.c_cc[VERASE]); + termio.c_cc[VKILL] = getdef_num("KILLCHAR", termio.c_cc[VKILL]); +#endif + + /* + * ttymon invocation prefers this, but these settings won't come into + * effect after the first username login + */ + +#else +#endif /* !BSD */ + STTY(0, &termio); +} + + +/* + * Tell the user that this is not the right time to login at this tty + */ +static void +bad_time_notify(void) +{ +#ifdef HUP_MESG_FILE + FILE *mfp; + + if ((mfp = fopen(HUP_MESG_FILE, "r")) != NULL) { + int c; + + while ((c = fgetc(mfp)) != EOF) { + if (c == '\n') + putchar('\r'); + putchar(c); + } + fclose(mfp); + } else +#endif + printf(_("Invalid login time\n")); + fflush(stdout); +} + + +static void +check_flags(int argc, char * const *argv) +{ + int arg; + + /* + * Check the flags for proper form. Every argument starting with + * "-" must be exactly two characters long. This closes all the + * clever rlogin, telnet, and getty holes. + */ + for (arg = 1; arg < argc; arg++) { + if (argv[arg][0] == '-' && strlen(argv[arg]) > 2) + usage(); + } +} + + +static void +check_nologin(void) +{ + char *fname; + + /* + * Check to see if system is turned off for non-root users. + * This would be useful to prevent users from logging in + * during system maintenance. We make sure the message comes + * out for root so she knows to remove the file if she's + * forgotten about it ... + */ + + fname = getdef_str("NOLOGINS_FILE"); + if (fname != NULL && access(fname, F_OK) == 0) { + FILE *nlfp; + int c; + + /* + * Cat the file if it can be opened, otherwise just + * print a default message + */ + + if ((nlfp = fopen (fname, "r"))) { + while ((c = getc (nlfp)) != EOF) { + if (c == '\n') + putchar ('\r'); + + putchar (c); + } + fflush (stdout); + fclose (nlfp); + } else + printf(_("\nSystem closed for routine maintenance\n")); + /* + * Non-root users must exit. Root gets the message, but + * gets to login. + */ + + if (pwent.pw_uid != 0) { + closelog(); + exit(0); + } + printf(_("\n[Disconnect bypassed -- root login allowed.]\n")); + } +} + + +static void +init_env(void) +{ + char *cp, *tmp; + + if ((tmp = getenv("LANG"))) { + addenv("LANG", tmp); + } + + /* + * Add the timezone environmental variable so that time functions + * work correctly. + */ + + if ((tmp = getenv("TZ"))) { + addenv("TZ", tmp); + } else if ((cp = getdef_str("ENV_TZ"))) + addenv(*cp == '/' ? tz(cp) : cp, NULL); + + /* + * Add the clock frequency so that profiling commands work + * correctly. + */ + + if ((tmp = getenv("HZ"))) { + addenv("HZ", tmp); + } else if ((cp = getdef_str("ENV_HZ"))) + addenv(cp, NULL); +} + + +static RETSIGTYPE +alarm_handler(int sig) +{ + fprintf(stderr, _("\nLogin timed out after %d seconds.\n"), timeout); + exit(0); +} + + +/* + * login - create a new login session for a user + * + * login is typically called by getty as the second step of a + * new user session. getty is responsible for setting the line + * characteristics to a reasonable set of values and getting + * the name of the user to be logged in. login may also be + * called to create a new user session on a pty for a variety + * of reasons, such as X servers or network logins. + * + * the flags which login supports are + * + * -p - preserve the environment + * -r - perform autologin protocol for rlogin + * -f - do not perform authentication, user is preauthenticated + * -h - the name of the remote host + */ + +int +main(int argc, char **argv) +{ + char username[32]; + char tty[BUFSIZ]; +#ifdef RLOGIN + char term[128] = ""; +#endif +#ifdef HAVE_STRFTIME + char ptime[80]; +#endif + int reason = PW_LOGIN; + int delay; + int retries; + int failed; + int flag; + int subroot = 0; + int is_console; + const char *cp; + char *tmp; + char fromhost[512]; + struct passwd *pwd; + char **envp = environ; + static char temp_pw[2]; + static char temp_shell[] = "/bin/sh"; +#ifdef USE_PAM_not_yet + int retcode; + pid_t child; +#endif /* USE_PAM_not_yet */ +#ifdef SHADOWPWD + struct spwd *spwd=NULL; +#endif +#ifdef RADIUS + RAD_USER_DATA rad_user_data; + int is_rad_login; +#endif +#if defined(RADIUS) || defined(DES_RPC) || defined(KERBEROS) + /* from pwauth.c */ + extern char *clear_pass; + extern int wipe_clear_pass; + + /* + * We may need the password later, don't want pw_auth() to wipe it + * (we do it ourselves when it is no longer needed). --marekm + */ + wipe_clear_pass = 0; +#endif + + /* + * Some quick initialization. + */ + + sanitize_env(); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + initenv(); + + username[0] = '\0'; + amroot = (getuid() == 0); + Prog = Basename(argv[0]); + + check_flags(argc, argv); + + while ((flag = getopt(argc, argv, "d:f:h:pr:")) != EOF) { + switch (flag) { + case 'p': + pflg++; + break; + case 'f': + /* + * username must be a separate token + * (-f root, *not* -froot). --marekm + */ + if (optarg != argv[optind - 1]) + usage(); + fflg++; + STRFCPY(username, optarg); + break; +#ifdef RLOGIN + case 'r': + rflg++; + hostname = optarg; + reason = PW_RLOGIN; + break; +#endif + case 'h': + hflg++; + hostname = optarg; + reason = PW_TELNET; + break; + case 'd': + /* "-d device" ignored for compatibility */ + break; + default: + usage(); + } + } + +#ifdef RLOGIN + /* + * Neither -h nor -f should be combined with -r. + */ + + if (rflg && (hflg || fflg)) + usage(); +#endif + + /* + * Allow authentication bypass only if real UID is zero. + */ + + if ((rflg || fflg || hflg) && !amroot) { + fprintf(stderr, _("%s: permission denied\n"), Prog); + exit(1); + } + + if (!isatty(0) || !isatty(1) || !isatty(2)) + exit(1); /* must be a terminal */ + +#if 0 + /* + * Get the utmp file entry and get the tty name from it. The + * current process ID must match the process ID in the utmp + * file if there are no additional flags on the command line. + */ + checkutmp(!rflg && !fflg && !hflg); +#else + /* + * Be picky if run by normal users (possible if installed setuid + * root), but not if run by root. This way it still allows logins + * even if your getty is broken, or if something corrupts utmp, + * but users must "exec login" which will use the existing utmp + * entry (will not overwrite remote hostname). --marekm + */ + checkutmp(!amroot); +#endif + STRFCPY(tty, utent.ut_line); + is_console = console(tty); + + if (rflg || hflg) { +#ifdef UT_ADDR + struct hostent *he; + + /* + * Fill in the ut_addr field (remote login IP address). + * XXX - login from util-linux does it, but this is not + * the right place to do it. The program that starts + * login (telnetd, rlogind) knows the IP address, so it + * should create the utmp entry and fill in ut_addr. + * gethostbyname() is not 100% reliable (the remote host + * may be unknown, etc.). --marekm + */ + if ((he = gethostbyname(hostname))) { + utent.ut_addr = *((int32_t *)(he->h_addr_list[0])); +#endif +#ifdef UT_HOST + strncpy(utent.ut_host, hostname, sizeof(utent.ut_host)); +#endif +#if HAVE_UTMPX_H + strncpy(utxent.ut_host, hostname, sizeof(utxent.ut_host)); +#endif + /* + * Add remote hostname to the environment. I think + * (not sure) I saw it once on Irix. --marekm + */ + addenv("REMOTEHOST", hostname); + } +#ifdef __linux__ +/* workaround for init/getty leaving junk in ut_host at least in some + version of RedHat. --marekm */ + else if (amroot) + memzero(utent.ut_host, sizeof utent.ut_host); +#endif + if (hflg && fflg) { + reason = PW_RLOGIN; + preauth_flag++; + } +#ifdef RLOGIN + if (rflg && do_rlogin(hostname, username, sizeof username, term, sizeof term)) + preauth_flag++; +#endif + + openlog("login", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + setup_tty(); + + umask(getdef_num("UMASK", 077)); + + { + /* + * Use the ULIMIT in the login.defs file, and if + * there isn't one, use the default value. The + * user may have one for themselves, but otherwise, + * just take what you get. + */ + + long limit = getdef_long("ULIMIT", -1L); + + if (limit != -1) + set_filesize_limit(limit); + } + + /* + * The entire environment will be preserved if the -p flag + * is used. + */ + + if (pflg) + while (*envp) /* add inherited environment, */ + addenv(*envp++, NULL); /* some variables change later */ + +#ifdef RLOGIN + if (term[0] != '\0') + addenv("TERM", term); + else +#endif + /* preserve TERM from getty */ + if (!pflg && (tmp = getenv("TERM"))) + addenv("TERM", tmp); + + init_env(); + + if (optind < argc) { /* get the user name */ + if (rflg || fflg) + usage(); + +#ifdef SVR4 + /* + * The "-h" option can't be used with a command-line username, + * because telnetd invokes us as: login -h host TERM=... + */ + + if (! hflg) +#endif + { + STRFCPY(username, argv[optind]); + strzero(argv[optind]); + ++optind; + } + } +#ifdef SVR4 + /* + * check whether ttymon has done the prompt for us already + */ + + { + char *ttymon_prompt; + + if ((ttymon_prompt = getenv("TTYPROMPT")) != NULL && + (*ttymon_prompt != 0)) { + /* read name, without prompt */ + login_prompt((char *)0, username, sizeof username); + } + } +#endif /* SVR4 */ + if (optind < argc) /* now set command line variables */ + set_env(argc - optind, &argv[optind]); + + if (rflg || hflg) + cp = hostname; + else +#ifdef UT_HOST + if (utent.ut_host[0]) + cp = utent.ut_host; + else +#endif +#if HAVE_UTMPX_H + if (utxent.ut_host[0]) + cp = utxent.ut_host; + else +#endif + cp = ""; + + if (*cp) + snprintf(fromhost, sizeof fromhost, + _(" on `%.100s' from `%.200s'"), tty, cp); + else + snprintf(fromhost, sizeof fromhost, _(" on `%.100s'"), tty); + +top: + /* only allow ALARM sec. for login */ + signal(SIGALRM, alarm_handler); + timeout = getdef_num("LOGIN_TIMEOUT", ALARM); + if (timeout > 0) + alarm(timeout); + + environ = newenvp; /* make new environment active */ + delay = getdef_num("FAIL_DELAY", 1); + retries = getdef_num("LOGIN_RETRIES", RETRIES); + +#ifdef USE_PAM_not_yet + retcode = pam_start("login", username, &conv, &pamh); + if(retcode != PAM_SUCCESS) { + fprintf(stderr,"login: PAM Failure, aborting: %s\n", + PAM_STRERROR(pamh, retcode)); + syslog(LOG_ERR,"Couldn't initialize PAM: %s", + PAM_STRERROR(pamh, retcode)); + exit(99); + } + /* hostname & tty are either set to NULL or their correct values, + depending on how much we know */ + retcode = pam_set_item(pamh, PAM_RHOST, hostname); + PAM_FAIL_CHECK; + retcode = pam_set_item(pamh, PAM_TTY, tty); + PAM_FAIL_CHECK; + + /* if fflg == 1, then the user has already been authenticated */ + if (!fflg || (getuid() != 0)) { + int failcount = 0; + + /* there may be better ways to deal with some of these + conditions, but at least this way I don't think we'll + be giving away information... */ + /* Perhaps someday we can trust that all PAM modules will + pay attention to failure count and get rid of + MAX_LOGIN_TRIES? */ + + retcode = pam_authenticate(pamh, 0); + while ((failcount++ < retries) && + ((retcode == PAM_AUTH_ERR) || + (retcode == PAM_USER_UNKNOWN) || + (retcode == PAM_CRED_INSUFFICIENT) || + (retcode == PAM_AUTHINFO_UNAVAIL))) { + pam_get_item(pamh, PAM_USER, (const void **) &username); + syslog(LOG_NOTICE,"FAILED LOGIN %d FROM %s FOR %s, %s", + failcount, hostname, username, + PAM_STRERROR(pamh, retcode)); + fprintf(stderr,"Login incorrect\n\n"); + pam_set_item(pamh,PAM_USER,NULL); + retcode = pam_authenticate(pamh, 0); + } + + if (retcode != PAM_SUCCESS) { + pam_get_item(pamh, PAM_USER, (const void **) &username); + + if (retcode == PAM_MAXTRIES) + syslog(LOG_NOTICE, + "TOO MANY LOGIN TRIES (%d) FROM %s FOR %s, %s", + failcount, hostname, username, + PAM_STRERROR(pamh, retcode)); + else + syslog(LOG_NOTICE, + "FAILED LOGIN SESSION FROM %s FOR %s, %s", + hostname, username, + PAM_STRERROR(pamh, retcode)); + + fprintf(stderr,"\nLogin incorrect\n"); + pam_end(pamh, retcode); + exit(0); + } + + retcode = pam_acct_mgmt(pamh, 0); + + if(retcode == PAM_NEW_AUTHTOK_REQD) { + retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); + } + + PAM_FAIL_CHECK; + } + + /* Grab the user information out of the password file for future usage + First get the username that we are actually using, though. + */ + retcode = pam_get_item(pamh, PAM_USER, (const void **) &username); + setpwent(); + pwd = getpwnam(username); + if (pwd) + initgroups(username, pwd->pw_gid); + + retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED); + PAM_FAIL_CHECK; + + retcode = pam_open_session(pamh, 0); + PAM_FAIL_CHECK; + + +#else /* ! USE_PAM_not_yet */ + while (1) { /* repeatedly get login/password pairs */ + failed = 0; /* haven't failed authentication yet */ +#ifdef RADIUS + is_rad_login = 0; +#endif + if (! username[0]) { /* need to get a login id */ + if (subroot) { + closelog (); + exit (1); + } + preauth_flag = 0; +#ifndef LOGIN_PROMPT +#ifdef __linux__ /* hostname login: - like in util-linux login */ + login_prompt(_("\n%s login: "), username, sizeof username); +#else + login_prompt(_("login: "), username, sizeof username); +#endif +#else + login_prompt(LOGIN_PROMPT, username, sizeof username); +#endif + continue; + } + if (! (pwd = getpwnam(username))) { + pwent.pw_name = username; + strcpy(temp_pw, "!"); + pwent.pw_passwd = temp_pw; + pwent.pw_shell = temp_shell; + + preauth_flag = 0; + failed = 1; + } else { + pwent = *pwd; + } +#ifdef SHADOWPWD + spwd = NULL; + if (pwd && strcmp(pwd->pw_passwd, SHADOW_PASSWD_STRING) == 0) { + spwd = getspnam(username); + if (spwd) + pwent.pw_passwd = spwd->sp_pwdp; + else + SYSLOG((LOG_WARN, NO_SHADOW, username, fromhost)); + } +#endif /* SHADOWPWD */ + + /* + * If the encrypted password begins with a "!", the account + * is locked and the user cannot login, even if they have + * been "pre-authenticated." + */ + if (pwent.pw_passwd[0] == '!' || pwent.pw_passwd[0] == '*') + failed = 1; + + /* + * The -r and -f flags provide a name which has already + * been authenticated by some server. + */ + if (preauth_flag) + goto auth_ok; + + /* + * No password prompt if logging in from listed ttys + * (local console). Passwords don't help much if you + * have physical access to the hardware anyway... + * Suggested by Pavel Machek . + * NOTE: password still required for root logins! + */ + if (pwd && (pwent.pw_uid != 0) + && is_listed("NO_PASSWORD_CONSOLE", tty, 0)) { + temp_pw[0] = '\0'; + pwent.pw_passwd = temp_pw; + } + + if (pw_auth(pwent.pw_passwd, username, reason, (char *) 0) == 0) + goto auth_ok; + +#ifdef RADIUS + /* + * If normal passwd authentication didn't work, try radius. + */ + + if (failed) { + pwd = rad_authenticate(&rad_user_data, username, + clear_pass ? clear_pass : ""); + if (pwd) { + is_rad_login = 1; + pwent = *pwd; + failed = 0; + goto auth_ok; + } + } +#endif /* RADIUS */ + + /* + * Don't log unknown usernames - I mistyped the password for + * username at least once... Should probably use LOG_AUTHPRIV + * for those who really want to log them. --marekm + */ + SYSLOG((LOG_WARN, BAD_PASSWD, + (pwd || getdef_bool("LOG_UNKFAIL_ENAB")) ? + username : "UNKNOWN", fromhost)); + failed = 1; + +auth_ok: + /* + * This is the point where all authenticated users + * wind up. If you reach this far, your password has + * been authenticated and so on. + */ + +#if defined(RADIUS) && !(defined(DES_RPC) || defined(KERBEROS)) + if (clear_pass) { + strzero(clear_pass); + clear_pass = NULL; + } +#endif + + if (getdef_bool("DIALUPS_CHECK_ENAB")) { + alarm (30); + + if (! dialcheck (tty, pwent.pw_shell[0] ? + pwent.pw_shell:"/bin/sh")) { + SYSLOG((LOG_WARN, BAD_DIALUP, username, tty)); + failed = 1; + } + } + + if (! failed && pwent.pw_name && pwent.pw_uid == 0 && + ! is_console) { + SYSLOG((LOG_CRIT, BAD_ROOT_LOGIN, fromhost)); + failed = 1; + } +#ifdef LOGIN_ACCESS + if (!failed && !login_access(username, *hostname ? hostname : tty)) { + SYSLOG((LOG_WARN, LOGIN_REFUSED, username, fromhost)); + failed = 1; + } +#endif + if (pwd && getdef_bool("FAILLOG_ENAB") && + ! failcheck (pwent.pw_uid, &faillog, failed)) { + SYSLOG((LOG_CRIT, FAILURE_CNT, username, fromhost)); + failed = 1; + } + if (! failed) + break; + + /* don't log non-existent users */ + if (pwd && getdef_bool("FAILLOG_ENAB")) + failure (pwent.pw_uid, tty, &faillog); + if (getdef_str("FTMP_FILE") != NULL) { + const char *failent_user; + +#if HAVE_UTMPX_H + failent = utxent; + gettimeofday(&(failent.ut_tv), NULL); +#else + failent = utent; + time(&failent.ut_time); +#endif + if (pwd) { + failent_user = pwent.pw_name; + } else { + if (getdef_bool("LOG_UNKFAIL_ENAB")) + failent_user = username; + else + failent_user = "UNKNOWN"; + } + strncpy(failent.ut_user, failent_user, sizeof(failent.ut_user)); +#ifdef USER_PROCESS + failent.ut_type = USER_PROCESS; +#endif + failtmp(&failent); + } + memzero(username, sizeof username); + + if (--retries <= 0) + SYSLOG((LOG_CRIT, MANY_FAILS, fromhost)); +#if 1 + /* + * If this was a passwordless account and we get here, + * login was denied (securetty, faillog, etc.). There + * was no password prompt, so do it now (will always + * fail - the bad guys won't see that the passwordless + * account exists at all). --marekm + */ + + if (pwent.pw_passwd[0] == '\0') + pw_auth("!", username, reason, (char *) 0); +#endif + /* + * Wait a while (a la SVR4 /usr/bin/login) before attempting + * to login the user again. If the earlier alarm occurs + * before the sleep() below completes, login will exit. + */ + + if (delay > 0) + sleep(delay); + + puts(_("Login incorrect")); + + /* allow only one attempt with -r or -f */ + if (rflg || fflg || retries <= 0) { + closelog(); + exit(1); + } + } /* while (1) */ +#endif /* ! USE_PAM_not_yet */ + (void) alarm (0); /* turn off alarm clock */ +#if 1 + /* + * porttime checks moved here, after the user has been + * authenticated. now prints a message, as suggested + * by Ivan Nejgebauer . --marekm + */ + if (getdef_bool("PORTTIME_CHECKS_ENAB") && + !isttytime(pwent.pw_name, tty, time ((time_t *) 0))) { + SYSLOG((LOG_WARN, BAD_TIME, username, fromhost)); + closelog(); + bad_time_notify(); + exit(1); + } +#endif + + check_nologin(); + + if (getenv("IFS")) /* don't export user IFS ... */ + addenv("IFS= \t\n", NULL); /* ... instead, set a safe IFS */ + + setutmp(username, tty, hostname); /* make entry in utmp & wtmp files */ + if (pwent.pw_shell[0] == '*') { /* subsystem root */ + subsystem (&pwent); /* figure out what to execute */ + subroot++; /* say i was here again */ + endpwent (); /* close all of the file which were */ + endgrent (); /* open in the original rooted file */ +#ifdef SHADOWPWD + endspent (); /* system. they will be re-opened */ +#endif +#ifdef SHADOWGRP + endsgent (); /* in the new rooted file system */ +#endif + goto top; /* go do all this all over again */ + } + if (getdef_bool("LASTLOG_ENAB")) /* give last login and log this one */ + dolastlog(&lastlog, &pwent, utent.ut_line, hostname); + +#ifdef SVR4_SI86_EUA + sysi86(SI86LIMUSER, EUA_ADD_USER); /* how do we test for fail? */ +#endif + +#ifdef AGING + /* + * Have to do this while we still have root privileges, otherwise + * we don't have access to /etc/shadow. expire() closes password + * files, and changes to the user in the child before executing + * the passwd program. --marekm + */ +#ifdef SHADOWPWD + if (spwd) { /* check for age of password */ + if (expire (&pwent, spwd)) { + pwd = getpwnam(username); + spwd = getspnam(username); + if (pwd) + pwent = *pwd; + } + } +#else +#ifdef ATT_AGE + if (pwent.pw_age && pwent.pw_age[0]) { + if (expire (&pwent)) { + pwd = getpwnam(username); + if (pwd) + pwent = *pwd; + } + } +#endif /* ATT_AGE */ +#endif /* SHADOWPWD */ +#endif /* AGING */ + +#ifdef RADIUS + if (is_rad_login) { + char whofilename[128]; + FILE *whofile; + + snprintf(whofilename, sizeof whofilename, "/var/log/radacct/%.20s", tty); + whofile = fopen(whofilename, "w"); + if (whofile) { + fprintf(whofile, "%s\n", username); + fclose(whofile); + } + } +#endif + setup_limits(&pwent); /* nice, ulimit etc. */ + chown_tty(tty, &pwent); + +#ifdef LOGIN_FBTAB + /* + * XXX - not supported yet. Change permissions and ownerships of + * devices like floppy/audio/mouse etc. for console logins, based + * on /etc/fbtab or /etc/logindevperm configuration files (Suns do + * this with their framebuffer devices). Problems: + * + * - most systems (except BSD) don't have that nice revoke() system + * call to ensure the previous user didn't leave a process holding + * one of these devices open or mmap'ed. Any volunteers to do it + * in Linux? + * + * - what to do with different users logged in on different virtual + * consoles? Maybe permissions should be changed only on user's + * request, by running a separate (setuid root) program? + * + * - init/telnetd/rlogind/whatever should restore permissions after + * the user logs out. + * + * Try the new CONSOLE_GROUPS feature instead. It adds specified + * groups (like "floppy") to the group set if the user is logged in + * on the console. This still has the first problem (users leaving + * processes with these devices open), but doesn't need to change + * any permissions, just make them 0660 root:floppy etc. --marekm + * + * Warning: users can still gain permanent access to these groups + * unless any user-writable filesystems are mounted with the "nosuid" + * option. Alternatively, the kernel could be modified to prevent + * ordinary users from setting the setgid bit on executables. + */ + login_fbtab(tty, pwent.pw_uid, pwent.pw_gid); +#endif + + if (setup_uid_gid(&pwent, is_console)) + exit(1); + +#ifdef KERBEROS + if (clear_pass) + login_kerberos(username, clear_pass); +#endif +#ifdef DES_RPC + if (clear_pass) + login_desrpc(clear_pass); +#endif +#if defined(DES_RPC) || defined(KERBEROS) + if (clear_pass) + strzero(clear_pass); +#endif + + setup_env(&pwent); /* set env vars, cd to the home dir */ + +#ifdef USE_PAM_not_yet + { + int i; + const char * const * env; + + env = (const char * const *) pam_getenvlist(pamh); + while (env && *env) { + addenv(*env, NULL); + env++; + } + } +#endif + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (!hushed(&pwent)) { + addenv("HUSHLOGIN=FALSE", NULL); + motd(); /* print the message of the day */ + if (getdef_bool("FAILLOG_ENAB") && faillog.fail_cnt != 0) { + failprint(&faillog); + /* Reset the lockout times if logged in */ + if (faillog.fail_max && + faillog.fail_cnt >= faillog.fail_max) { + puts(_("Warning: login re-enabled after temporary lockout.\n")); + SYSLOG((LOG_WARN, REENABLED2, username, + (int) faillog.fail_cnt)); + } + } + if (getdef_bool("LASTLOG_ENAB") && lastlog.ll_time != 0) { +#ifdef HAVE_STRFTIME + strftime(ptime, sizeof(ptime), + "%a %b %e %H:%M:%S %z %Y", + localtime(&lastlog.ll_time)); + printf(_("Last login: %s on %s"), + ptime, lastlog.ll_line); +#else + printf(_("Last login: %.19s on %s"), + ctime(&lastlog.ll_time), lastlog.ll_line); +#endif +#ifdef HAVE_LL_HOST /* SVR4 || __linux__ || SUN4 */ + if (lastlog.ll_host[0]) + printf(_(" from %.*s"), + (int) sizeof lastlog.ll_host, + lastlog.ll_host); +#endif + printf(".\n"); + } +#ifdef AGING +#ifdef SHADOWPWD + agecheck(&pwent, spwd); +#else + agecheck(&pwent); +#endif +#endif /* AGING */ + mailcheck(); /* report on the status of mail */ + } else + addenv("HUSHLOGIN=TRUE", NULL); + + if (getdef_str("TTYTYPE_FILE") != NULL && getenv("TERM") == NULL) + ttytype (tty); + + signal(SIGQUIT, SIG_DFL); /* default quit signal */ + signal(SIGTERM, SIG_DFL); /* default terminate signal */ + signal(SIGALRM, SIG_DFL); /* default alarm signal */ + signal(SIGHUP, SIG_DFL); /* added this. --marekm */ + +#ifdef USE_PAM_not_yet + /* We must fork before setuid() because we need to call + * pam_close_session() as root. + */ + /* Note: not true in other (non-Linux) PAM implementations, where + the parent process of login (init, telnetd, ...) is responsible + for calling pam_close_session(). This avoids an extra process + for each login. Maybe we should do this on Linux too? -MM */ + signal(SIGINT, SIG_IGN); + child = fork(); + if (child < 0) { + /* error in fork() */ + fprintf(stderr,"login: failure forking: %s", strerror(errno)); + PAM_END; + exit(0); + } else if (child) { + /* parent - wait for child to finish, then cleanup session */ + wait(NULL); + PAM_END; + exit(0); + } + /* child */ +#endif + signal(SIGINT, SIG_DFL); /* default interrupt signal */ + + endpwent(); /* stop access to password file */ + endgrent(); /* stop access to group file */ +#ifdef SHADOWPWD + endspent(); /* stop access to shadow passwd file */ +#endif +#ifdef SHADOWGRP + endsgent(); /* stop access to shadow group file */ +#endif + if (pwent.pw_uid == 0) + SYSLOG((LOG_NOTICE, ROOT_LOGIN, fromhost)); + else if (getdef_bool("LOG_OK_LOGINS")) + SYSLOG((LOG_INFO, REG_LOGIN, username, fromhost)); + closelog(); +#ifdef RADIUS + if (is_rad_login) { + printf(_("Starting rad_login\n")); + rad_login(&rad_user_data); + exit(0); + } +#endif + if ((tmp = getdef_str("FAKE_SHELL")) != NULL) { + shell(tmp, pwent.pw_shell); /* fake shell */ + } + shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */ + /*NOTREACHED*/ + return 0; +} diff --git a/src/logoutd.c b/src/logoutd.c new file mode 100644 index 00000000..200cc4fd --- /dev/null +++ b/src/logoutd.c @@ -0,0 +1,316 @@ +/* + * Copyright 1991 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: logoutd.c,v 1.13 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "defines.h" + +#ifdef SVR4 +#include +#endif + +#ifdef SVR4 +#define signal sigset +#endif + +static char *Prog; + +static char *mesg_buf = "login time exceeded\r\n"; /* XXX warning: const */ +static int mesg_len = 21; +static int mesg_size; + +#ifndef HUP_MESG_FILE +#define HUP_MESG_FILE "/etc/logoutd.mesg" +#endif + +/* local function prototypes */ +static RETSIGTYPE reload_mesg P_((int)); +static int check_login P_((const struct utmp *)); +int main P_((int, char **)); + +/* + * reload_mesg - reload the message that is output when killing a process + */ + +static RETSIGTYPE +reload_mesg(int sig) +{ + int fd; + struct stat sb; + + signal (sig, reload_mesg); + + if (stat (HUP_MESG_FILE, &sb)) + return; + + if ((sb.st_mode & S_IFMT) != S_IFREG) + return; + + if ((fd = open (HUP_MESG_FILE, O_RDONLY)) != -1) { + if (sb.st_size + 1 > mesg_size) { + if (mesg_buf && mesg_size) + free (mesg_buf); + + mesg_len = sb.st_size; + mesg_size = mesg_len + 1; + if (! (mesg_buf = (char *) malloc (mesg_len + 1))) + goto end; + } else + mesg_len = sb.st_size; + + if (read (fd, mesg_buf, mesg_len) != mesg_len) { + mesg_len = 0; + goto end; + } + } else + return; + +end: + close (fd); +} + +/* + * check_login - check if user (struct utmp) allowed to stay logged in + */ +static int +check_login(const struct utmp *ut) +{ + char user[sizeof(ut->ut_user) + 1]; + time_t now; + + /* + * ut_user may not have the terminating NUL. + */ + strncpy(user, ut->ut_user, sizeof(ut->ut_user)); + user[sizeof(ut->ut_user)] = '\0'; + + time(&now); + + /* + * Check if they are allowed to be logged in right now. + */ + if (!isttytime(user, ut->ut_line, now)) + return 0; +#if 0 + /* + * Check for how long they are allowed to stay logged in. + * XXX - not implemented yet. Need to add a new field to + * /etc/porttime (login time limit in minutes, or no limit, + * based on username, tty, and time of login). + */ + if (now - ut->ut_time > get_time_limit(user, ut->ut_line, ut->ut_time)) + return 0; +#endif + return 1; +} + +/* + * logoutd - logout daemon to enforce /etc/porttime file policy + * + * logoutd is started at system boot time and enforces the login + * time and port restrictions specified in /etc/porttime. The + * utmp file is periodically scanned and offending users are logged + * off from the system. + */ + +int +main(int argc, char **argv) +{ + int i; + int status; + struct utmp *ut; + char user[sizeof(ut->ut_user) + 1]; /* terminating NUL */ + char tty_name[sizeof(ut->ut_line) + 6]; /* /dev/ + NUL */ + int tty_fd; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + +#ifndef DEBUG + for (i = 0;close (i) == 0;i++) + ; + +#ifdef HAVE_SETPGRP +#ifdef SETPGRP_VOID + setpgrp(); /* USG */ +#else + setpgrp(getpid(), getpid()); +#endif +#else /* !HAVE_SETPGRP */ + setpgid(getpid(), getpid()); /* BSD || SUN || SUN4 */ +#endif /* !HAVE_SETPGRP */ + + reload_mesg (SIGHUP); + + /* + * Put this process in the background. + */ + + if ((i = fork ())) + exit (i < 0 ? 1:0); +#endif /* !DEBUG */ + + /* + * Start syslogging everything + */ + + Prog = Basename(argv[0]); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + /* + * Scan the UTMP file once per minute looking for users that + * are not supposed to still be logged in. + */ + + while (1) { +#ifndef DEBUG + sleep(60); +#endif + + /* + * Attempt to re-open the utmp file. The file is only + * open while it is being used. + */ + + setutent(); + + /* + * Read all of the entries in the utmp file. The entries + * for login sessions will be checked to see if the user + * is permitted to be signed on at this time. + */ + + while ((ut = getutent())) { +#ifdef USER_PROCESS + if (ut->ut_type != USER_PROCESS) + continue; +#endif + if (ut->ut_user[0] == '\0') + continue; + if (check_login(ut)) + continue; + + /* + * Put the rest of this in a child process. This + * keeps the scan from waiting on other ports to die. + */ + + if (fork() != 0) + continue; + + if (strncmp(ut->ut_line, "/dev/", 5) != 0) + strcpy(tty_name, "/dev/"); + else + tty_name[0] = '\0'; + + strcat(tty_name, ut->ut_line); +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + if ((tty_fd = open (tty_name, + O_WRONLY|O_NDELAY|O_NOCTTY)) != -1) { +/* Suggested by Ivan Nejgebauar : set OPOST + before writing the message. --marekm */ + TERMIO oldt, newt; + + GTTY(tty_fd, &oldt); + newt = oldt; +#ifdef OPOST + newt.c_oflag |= OPOST; +#else /* XXX - I'm too young to know bsd sgtty, sorry :). --marekm */ +#endif + STTY(tty_fd, &newt); + write (tty_fd, mesg_buf, mesg_len); + STTY(tty_fd, &oldt); + close (tty_fd); + sleep(10); + } +#ifdef USER_PROCESS /* USG_UTMP */ + if (ut->ut_pid > 1) { + kill(- ut->ut_pid, SIGHUP); + sleep(10); + kill(- ut->ut_pid, SIGKILL); + } +#else /* BSD || SUN || SUN4 */ + /* + * vhangup() the line to kill try and kill + * whatever is out there using it. + */ + + if ((tty_fd = open (tty_name, O_RDONLY|O_NDELAY)) == -1) + continue; + + vhangup (tty_fd); + close (tty_fd); +#endif /* BSD || SUN || SUN4 */ + +#if 0 + SYSLOG((LOG_NOTICE, + "logged off user `%.*s' on `%.*s'\n", + (int) sizeof(ut->ut_user), ut->ut_user, + (int) sizeof(ut->ut_line), ut->ut_line)); +#else + /* avoid gcc warnings about %.*s in syslog() */ + strncpy(user, ut->ut_line, sizeof(user) - 1); + user[sizeof(user) - 1] = '\0'; + + SYSLOG((LOG_NOTICE, "logged off user `%s' on `%s'\n", + user, tty_name)); +#endif + + /* + * This child has done all it can, drop dead. + */ + + exit (0); + } + + endutent(); + + /* + * Reap any dead babies ... + */ + + while (wait (&status) != -1) + ; + } + return 1; /* not reached */ +} diff --git a/src/mkpasswd.c b/src/mkpasswd.c new file mode 100644 index 00000000..8f7c2834 --- /dev/null +++ b/src/mkpasswd.c @@ -0,0 +1,395 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: mkpasswd.c,v 1.6 1999/06/07 16:40:45 marekm Exp $") + +#include +#include "prototypes.h" +#include "defines.h" +#include + +#if !defined(NDBM) /*{*/ +int +main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + fprintf(stderr, + _("%s: no DBM database on system - no action performed\n"), + argv[0]); + return 0; +} + +#else /*} defined(NDBM) {*/ + +#include +#include + +#include +#include + +extern DBM *pw_dbm; +extern DBM *gr_dbm; +#ifdef SHADOWPWD +extern DBM *sp_dbm; +#endif +#ifdef SHADOWGRP +extern DBM *sg_dbm; +#endif +char *fgetsx(); + +#ifdef SHADOWPWD +#ifdef SHADOWGRP +#define USAGE _("Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n") +#else /* !SHADOWGRP */ +#define USAGE _("Usage: %s [ -vf ] [ -p|g|sp ] file\n") +#endif /* SHADOWGRP */ +#else /* !SHADOWPWD */ +#define USAGE _("Usage: %s [ -vf ] [ -p|g ] file\n") +#endif /* SHADOWPWD */ + +char *Progname; +int vflg = 0; +int fflg = 0; +int gflg = 0; +int sflg = 0; /* -s flag -- leave in, makes code nicer */ +int pflg = 0; + +extern struct passwd *sgetpwent(); +extern int pw_dbm_update(); + +extern struct group *sgetgrent(); +extern int gr_dbm_update(); + +#ifdef SHADOWPWD +extern struct spwd *sgetspent(); +extern int sp_dbm_update(); +#endif + +#ifdef SHADOWGRP +extern struct sgrp *sgetsgent(); +extern int sg_dbm_update(); +#endif + +/* local function prototypes */ +int main P_((int, char **)); +static void usage P_((void)); + +/* + * mkpasswd - create DBM files for /etc/passwd-like input file + * + * mkpasswd takes an an argument the name of a file in /etc/passwd format + * and creates a DBM file keyed by user ID and name. The output files have + * the same name as the input file, with .dir and .pag appended. + * + * this command will also create look-aside files for + * /etc/group, /etc/shadow, and /etc/gshadow. + */ + +int +main(int argc, char **argv) +{ + extern int optind; + extern char *optarg; + FILE *fp; /* File pointer for input file */ + char *file; /* Name of input file */ + char *dir; /* Name of .dir file */ + char *pag; /* Name of .pag file */ + char *cp; /* Temporary character pointer */ + int flag; /* Flag for command line option */ + int cnt = 0; /* Number of entries in database */ + int longest = 0; /* Longest entry in database */ + int len; /* Length of input line */ + int errors = 0; /* Count of errors processing file */ + char buf[BUFSIZ*8]; /* Input line from file */ + struct passwd *passwd=NULL; /* Pointer to password file entry */ + + struct group *group=NULL; /* Pointer to group file entry */ +#ifdef SHADOWPWD + struct spwd *shadow=NULL; /* Pointer to shadow passwd entry */ +#endif +#ifdef SHADOWGRP + struct sgrp *gshadow=NULL; /* Pointer to shadow group entry */ +#endif + DBM *dbm; /* Pointer to new NDBM files */ + DBM *dbm_open(); /* Function to open NDBM files */ + + /* + * Figure out what my name is. I will use this later ... + */ + + Progname = Basename(argv[0]); + + /* + * Figure out what the flags might be ... + */ + + while ((flag = getopt (argc, argv, "fvpgs")) != EOF) { + switch (flag) { + case 'v': + vflg++; + break; + case 'f': + fflg++; + break; + case 'g': + gflg++; +#ifndef SHADOWGRP + if (sflg) + usage (); +#endif + if (pflg) + usage (); + + break; +#if defined(SHADOWPWD) || defined(SHADOWGRP) + case 's': + sflg++; +#ifndef SHADOWGRP + if (gflg) + usage (); +#endif + break; +#endif + case 'p': + pflg++; + if (gflg) + usage (); + + break; + default: + usage(); + } + } + + /* + * Backwards compatibility fix for -p flag ... + */ + +#ifdef SHADOWPWD + if (! sflg && ! gflg) +#else + if (! gflg) +#endif + pflg++; + + /* + * The last and only remaining argument must be the file name + */ + + if (argc - 1 != optind) + usage (); + + file = argv[optind]; + + if (! (fp = fopen (file, "r"))) { + fprintf (stderr, _("%s: cannot open file %s\n"), Progname, file); + exit (1); + } + + /* + * Make the filenames for the two DBM files. + */ + + dir = xmalloc (strlen (file) + 5); /* space for .dir file */ + strcat (strcpy (dir, file), ".dir"); + + pag = xmalloc (strlen (file) + 5); /* space for .pag file */ + strcat (strcpy (pag, file), ".pag"); + + /* + * Remove existing files if requested. + */ + + if (fflg) { + (void) unlink (dir); + (void) unlink (pag); + } + + /* + * Create the two DBM files - it is an error for these files + * to have existed already. + */ + + if (access(dir, F_OK) == 0) { + fprintf (stderr, _("%s: cannot overwrite file %s\n"), Progname, dir); + exit (1); + } + if (access(pag, F_OK) == 0) { + fprintf (stderr, _("%s: cannot overwrite file %s\n"), Progname, pag); + exit (1); + } + + if (sflg) + umask(077); + else + umask(022); + + /* + * Now the DBM database gets initialized + */ + + if (! (dbm = dbm_open (file, O_RDWR|O_CREAT, 0644))) { + fprintf (stderr, _("%s: cannot open DBM files for %s\n"), Progname, file); + exit (1); + } + if (gflg) { +#ifdef SHADOWGRP + if (sflg) + sg_dbm = dbm; + else +#endif + gr_dbm = dbm; + } else { +#ifdef SHADOWPWD + if (sflg) + sp_dbm = dbm; + else +#endif + pw_dbm = dbm; + } + + /* + * Read every line in the password file and convert it into a + * data structure to be put in the DBM database files. + */ + + while (fgetsx (buf, BUFSIZ, fp) != NULL) { + + /* + * Get the next line and strip off the trailing newline + * character. + */ + + buf[sizeof buf - 1] = '\0'; + if (! (cp = strchr (buf, '\n'))) { + fprintf (stderr, _("%s: the beginning with "%.16s ..." is too long\n"), Progname, buf); + exit (1); + } + *cp = '\0'; + len = strlen (buf); + +#ifdef USE_NIS + /* + * Parse the password file line into a (struct passwd). + * Erroneous lines cause error messages, but that's + * all. YP lines are ignored completely. + */ + + if (buf[0] == '-' || buf[0] == '+') + continue; +#endif + if (! (((! sflg && pflg) && (passwd = sgetpwent (buf))) +#ifdef SHADOWPWD + || ((sflg && pflg) && (shadow = sgetspent (buf))) +#endif + || ((! sflg && gflg) && (group = sgetgrent (buf))) +#ifdef SHADOWGRP + || ((sflg && gflg) && (gshadow = sgetsgent (buf))) +#endif + )) { + fprintf (stderr, _("%s: error parsing line \"%s\"\n"), Progname, buf); + errors++; + continue; + } + if (vflg) { + if (!sflg && pflg) printf (_("adding record for name "%s"\n"), passwd->pw_name); +#ifdef SHADOWPWD + if (sflg && pflg) printf (_("adding record for name "%s"\n"), shadow->sp_namp); +#endif + if (!sflg && gflg) printf (_("adding record for name "%s"\n"), group->gr_name); +#ifdef SHADOWGRP + if (sflg && gflg) printf (_("adding record for name "%s"\n"), gshadow->sg_name); +#endif + } + if (! sflg && pflg && ! pw_dbm_update (passwd)) + fprintf (stderr, _("%s: error adding record for "%s"\n"), + Progname, passwd->pw_name); + +#ifdef SHADOWPWD + if (sflg && pflg && ! sp_dbm_update (shadow)) + fprintf (stderr, _("%s: error adding record for "%s"\n"), + Progname, shadow->sp_namp); +#endif + if (! sflg && gflg && ! gr_dbm_update (group)) + fprintf (stderr, _("%s: error adding record for "%s"\n"), + Progname, group->gr_name); +#ifdef SHADOWGRP + if (sflg && gflg && ! sg_dbm_update (gshadow)) + fprintf (stderr, _("%s: error adding record for "%s"\n"), + Progname, gshadow->sg_name); +#endif /* SHADOWGRP */ + + /* + * Update the longest record and record count + */ + + if (len > longest) + longest = len; + cnt++; + } + + /* + * Tell the user how things went ... + */ + + if (vflg) + printf (_("added %d entries, longest was %d\n"), cnt, longest); + + exit (errors); + /*NOTREACHED*/ +} + +/* + * usage - print error message and exit + */ + +static void +usage(void) +{ +#ifdef SHADOWPWD +#ifdef SHADOWGRP + fprintf (stderr, _("Usage: %s [ -vf ] [ -p|g|sp|sg ] file\n"), Progname); +#else /* !SHADOWGRP */ + fprintf (stderr, _("Usage: %s [ -vf ] [ -p|g|sp ] file\n"), Progname); +#endif /* SHADOWGRP */ +#else /* !SHADOWPWD */ + fprintf (stderr, _("Usage: %s [ -vf ] [ -p|g ] file\n"), Progname); +#endif /* SHADOWPWD */ + + + exit (1); + /*NOTREACHED*/ +} +#endif /*} defined(NDBM) */ diff --git a/src/newgrp.c b/src/newgrp.c new file mode 100644 index 00000000..523b9e20 --- /dev/null +++ b/src/newgrp.c @@ -0,0 +1,479 @@ +/* + * Copyright 1990 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: newgrp.c,v 1.13 1999/07/09 18:02:43 marekm Exp $") + +#include +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" + +#include "getdef.h" + +extern char **environ; + +#ifdef HAVE_SETGROUPS +static int ngroups; +static GETGROUPS_T *grouplist; +#endif + +static char *Prog; +static int is_newgrp; + +/* local function prototypes */ +static void usage P_((void)); +int main P_((int, char **)); + +/* + * usage - print command usage message + */ + +static void +usage(void) +{ + if (is_newgrp) + fprintf (stderr, _("usage: newgrp [ - ] [ group ]\n")); + else + fprintf (stderr, _("usage: sg group [ command ]\n")); +} + +/* + * newgrp - change the invokers current real and effective group id + */ + +int +main(int argc, char **argv) +{ + int initflag = 0; + int needspasswd = 0; + int i; + int cflag = 0; + gid_t gid; + char *cp; + const char *cpasswd, *name, *prog; + char *group = NULL; + char *command=NULL; + char **envp = environ; + struct passwd *pwd; + struct group *grp; +#ifdef SHADOWPWD + struct spwd *spwd; +#endif +#ifdef SHADOWGRP + struct sgrp *sgrp; +#endif + + sanitize_env(); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * save my name for error messages and save my real gid incase + * of errors. if there is an error i have to exec a new login + * shell for the user since her old shell won't have fork'd to + * create the process. skip over the program name to the next + * command line argument. + */ + + Prog = Basename(argv[0]); + is_newgrp = (strcmp(Prog, "newgrp") == 0); + openlog(is_newgrp ? "newgrp" : "sg", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + gid = getgid(); + argc--; argv++; + + initenv(); + + pwd = get_my_pwent(); + if (!pwd) { + fprintf (stderr, _("unknown uid: %d\n"), (int) getuid()); + SYSLOG((LOG_WARN, "unknown uid %d\n", (int) getuid())); + closelog(); + exit(1); + } + name = pwd->pw_name; + + /* + * Parse the command line. There are two accepted flags. The + * first is "-", which for newgrp means to re-create the entire + * environment as though a login had been performed, and "-c", + * which for sg causes a command string to be executed. + * + * The next argument, if present, must be the new group name. + * Any remaining remaining arguments will be used to execute a + * command as the named group. If the group name isn't present, + * I just use the login group ID of the current user. + * + * The valid syntax are + * newgrp [ - ] [ groupid ] + * newgrp [ -l ] [ groupid ] + * sg [ - ] + * sg [ - ] groupid [ command ] + */ + + if (argc > 0 && (!strcmp(argv[0], "-") || !strcmp(argv[0], "-l"))) { + argc--; argv++; + initflag = 1; + } + if (!is_newgrp) { + /* + * Do the command line for everything that is + * not "newgrp". + */ + + if (argc > 0 && argv[0][0] != '-') { + group = argv[0]; + argc--; argv++; + } else { + usage (); + closelog(); + exit (1); + } + if (argc > 0) { + command = argv[1]; + cflag++; + } + } else { + + /* + * Do the command line for "newgrp". It's just + * making sure there aren't any flags and getting + * the new group name. + */ + + if (argc > 0 && argv[0][0] == '-') { + usage (); + goto failure; + } else if (argv[0] != (char *) 0) { + group = argv[0]; + } else { + + /* + * get the group file entry for her login group id. + * the entry must exist, simply to be annoying. + */ + + if (! (grp = getgrgid (pwd->pw_gid))) { + fprintf(stderr, _("unknown gid: %ld\n"), + (long) pwd->pw_gid); + SYSLOG((LOG_CRIT, "unknown gid: %ld\n", + (long) pwd->pw_gid)); + goto failure; + } + } + } + +#ifdef HAVE_SETGROUPS + /* + * get the current users groupset. the new group will be + * added to the concurrent groupset if there is room, otherwise + * you get a nasty message but at least your real and effective + * group id's are set. + */ + + /* don't use getgroups(0, 0) - it doesn't work on some systems */ + i = 16; + for (;;) { + grouplist = (GETGROUPS_T *) xmalloc(i * sizeof(GETGROUPS_T)); + ngroups = getgroups(i, grouplist); + /* XXX Bug#38672 + login: newgrp/sg fails with user in 17 groups */ + if (i > ngroups && !(ngroups == -1 && errno == EINVAL)) + break; + /* not enough room, so try allocating a larger buffer */ + free(grouplist); + i *= 2; + } + if (ngroups < 0) { + perror("getgroups"); + exit(1); + } +#endif /* HAVE_SETGROUPS */ + + /* + * now we put her in the new group. the password file entry for + * her current user id has been gotten. if there was no optional + * group argument she will have her real and effective group id + * set to the value from her password file entry. otherwise + * we validate her access to the specified group. + */ + + if (group == (char *) 0) { + if (! (grp = getgrgid (pwd->pw_gid))) { + fprintf (stderr, _("unknown gid: %d\n"), pwd->pw_gid); + goto failure; + } + group = grp->gr_name; + } else if (! (grp = getgrnam (group))) { + fprintf (stderr, _("unknown group: %s\n"), group); + goto failure; + } +#ifdef SHADOWGRP + if ((sgrp = getsgnam (group))) { + grp->gr_passwd = sgrp->sg_passwd; + grp->gr_mem = sgrp->sg_mem; + } +#endif + + /* + * see if she is a member of this group. + * if she isn't a member, she needs to provide the + * group password. if there is no group password, she + * will be denied access anyway. + */ + + if (!is_on_list(grp->gr_mem, name)) + needspasswd = 1; + + /* + * if she does not have either a shadowed password, + * or a regular password, and the group has a password, + * she needs to give the group password. + */ + +#ifdef SHADOWPWD + if ((spwd = getspnam (name))) + pwd->pw_passwd = spwd->sp_pwdp; +#endif + + if (pwd->pw_passwd[0] == '\0' && grp->gr_passwd[0]) + needspasswd = 1; + + /* + * now i see about letting her into the group she requested. + * if she is the root user, i'll let her in without having to + * prompt for the password. otherwise i ask for a password + * if she flunked one of the tests above. note that she + * won't have to provide the password to her login group even + * if she isn't listed as a member. + */ + + if (getuid () != 0 && needspasswd) { + + /* + * get the password from her, and set the salt for + * the decryption from the group file. + */ + + if (! (cp = getpass (_("Password:")))) + goto failure; + + /* + * encrypt the key she gave us using the salt from + * the password in the group file. the result of + * this encryption must match the previously + * encrypted value in the file. + */ + + cpasswd = pw_encrypt (cp, grp->gr_passwd); + strzero(cp); + + if (grp->gr_passwd[0] == '\0') { + /* + * there is no password, print out "Sorry" and give up + */ + sleep(1); + fputs (_("Sorry.\n"), stderr); + goto failure; + } + + if (strcmp (cpasswd, grp->gr_passwd) != 0) { + SYSLOG((LOG_INFO, + "Invalid password for group `%s' from `%s'\n", + group, name)); + sleep(1); + fputs (_("Sorry.\n"), stderr); + goto failure; + } + } + + /* + * all successful validations pass through this point. the + * group id will be set, and the group added to the concurrent + * groupset. + */ + +#ifdef USE_SYSLOG + if (getdef_bool ("SYSLOG_SG_ENAB")) + SYSLOG((LOG_INFO, "user `%s' switched to group `%s'\n", + name, group)); +#endif + gid = grp->gr_gid; + +#ifdef HAVE_SETGROUPS + /* + * i am going to try to add her new group id to her concurrent + * group set. if the group id is already present i'll just + * skip this part. if the group doesn't fit, i'll complain + * loudly and skip this part ... + */ + + for (i = 0;i < ngroups;i++) { + if (gid == grouplist[i]) + break; + } + if (i == ngroups) { + if (ngroups >= NGROUPS_MAX) { + fprintf (stderr, _("too many groups\n")); + } else { + grouplist[ngroups++] = gid; + if (setgroups(ngroups, grouplist)) { + perror("setgroups"); + } + } + } +#endif + +okay: + /* + * i set her group id either to the value she requested, or + * to the original value if the newgrp failed. + */ + + if (setgid(gid)) + perror("setgid"); + + if (setuid(getuid())) { + perror("setuid"); + exit(1); + } + + /* + * see if the "-c" flag was used. if it was, i just create a + * shell command for her using the argument that followed the + * "-c" flag. + */ + + if (cflag) { + closelog(); + execl("/bin/sh", "sh", "-c", command, (char *) 0); + if (errno == ENOENT) { + perror("/bin/sh"); + exit(127); + } else { + perror("/bin/sh"); + exit(126); + } + } + + /* + * i have to get the pathname of her login shell. as a favor, + * i'll try her environment for a $SHELL value first, and + * then try the password file entry. obviously this shouldn't + * be in the restricted command directory since it could be + * used to leave the restricted environment. + */ + + if (! initflag && (cp = getenv ("SHELL"))) + prog = cp; + else if (pwd->pw_shell && pwd->pw_shell[0]) + prog = pwd->pw_shell; + else + prog = "/bin/sh"; + + /* + * now i try to find the basename of the login shell. this + * will become argv[0] of the spawned command. + */ + + cp = Basename((char *) prog); + +#ifdef SHADOWPWD + endspent (); +#endif +#ifdef SHADOWGRP + endsgent (); +#endif + endpwent (); + endgrent (); + + /* + * switch back to her home directory if i am doing login + * initialization. + */ + + if (initflag) { + if (chdir (pwd->pw_dir)) + perror("chdir"); + + while (*envp) { + if (strncmp (*envp, "PATH=", 5) == 0 || + strncmp (*envp, "HOME=", 5) == 0 || + strncmp (*envp, "SHELL=", 6) == 0 || + strncmp (*envp, "TERM=", 5) == 0) + addenv(*envp, NULL); + + envp++; + } + } else { + while (*envp) + addenv(*envp++, NULL); + } + + /* + * exec the login shell and go away. we are trying to get + * back to the previous environment which should be the + * user's login shell. + */ + + shell(prog, initflag ? (char *)0 : cp); + /*NOTREACHED*/ + +failure: + /* + * this is where all failures land. the group id will not + * have been set, so the setgid() below will set me to the + * original group id i had when i was invoked. + */ + + /* + * only newgrp needs to re-exec the user's shell. that is + * because the shell doesn't recognize "sg", so it doesn't + * "exec" this command. + */ + + if (!is_newgrp) { + closelog(); + exit (1); + } + + /* + * The GID is still set to the old value, so now I can + * give the user back her shell. + */ + + goto okay; +} diff --git a/src/newusers.c b/src/newusers.c new file mode 100644 index 00000000..a9141330 --- /dev/null +++ b/src/newusers.c @@ -0,0 +1,571 @@ +/* + * Copyright 1990 - 1993, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * newusers - create users from a batch file + * + * newusers creates a collection of entries in /etc/passwd + * and related files by reading a passwd-format file and + * adding entries in the related directories. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: newusers.c,v 1.10 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include "prototypes.h" +#include "defines.h" +#include +#include +#include +#include + +static char *Prog; + +extern char *crypt_make_salt P_((void)); + +#include "getdef.h" +#include "pwio.h" +#include "groupio.h" + +#ifdef SHADOWPWD +#include "shadowio.h" + +static int is_shadow; +#endif + +/* local function prototypes */ +static void usage P_((void)); +static int add_group P_((const char *, const char *, gid_t *)); +static int add_user P_((const char *, const char *, uid_t *, gid_t)); +static void update_passwd P_((struct passwd *, const char *)); +static int add_passwd P_((struct passwd *, const char *)); +int main P_((int, char **)); + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("Usage: %s [ input ]\n"), Prog); + exit(1); +} + +/* + * add_group - create a new group or add a user to an existing group + */ + +static int +add_group(const char *name, const char *gid, gid_t *ngid) +{ + const struct passwd *pwd; + const struct group *grp; + struct group grent; + char *members[2]; + int i; + + /* + * Start by seeing if the named group already exists. This + * will be very easy to deal with if it does. + */ + + if ((grp = gr_locate (gid))) { +add_member: + grent = *grp; + *ngid = grent.gr_gid; + for (i = 0;grent.gr_mem[i] != (char *) 0;i++) + if (strcmp (grent.gr_mem[i], name) == 0) + return 0; + + grent.gr_mem = (char **) xmalloc (sizeof (char *) * (i + 2)); + memcpy (grent.gr_mem, grp->gr_mem, sizeof (char *) * (i + 2)); + grent.gr_mem[i] = xstrdup (name); + grent.gr_mem[i + 1] = (char *) 0; + + return ! gr_update (&grent); + } + + /* + * The group did not exist, so I try to figure out what the + * GID is going to be. The gid parameter is probably "", meaning + * I figure out the GID from the password file. I want the UID + * and GID to match, unless the GID is already used. + */ + + if (gid[0] == '\0') { + i = 100; + for (pw_rewind ();(pwd = pw_next ());) { + if (pwd->pw_uid >= i) + i = pwd->pw_uid + 1; + } + for (gr_rewind ();(grp = gr_next ());) { + if (grp->gr_gid == i) { + i = -1; + break; + } + } + } else if (gid[0] >= '0' && gid[0] <= '9') { + + /* + * The GID is a number, which means either this is a brand new + * group, or an existing group. For existing groups I just add + * myself as a member, just like I did earlier. + */ + + i = atoi (gid); + for (gr_rewind ();(grp = gr_next ());) + if (grp->gr_gid == i) + goto add_member; + } else + + /* + * The last alternative is that the GID is a name which is not + * already the name of an existing group, and I need to figure + * out what group ID that group name is going to have. + */ + + i = -1; + + /* + * If I don't have a group ID by now, I'll go get the + * next one. + */ + + if (i == -1) { + for (i = 100, gr_rewind ();(grp = gr_next ());) + if (grp->gr_gid >= i) + i = grp->gr_gid + 1; + } + + /* + * Now I have all of the fields required to create the new + * group. + */ + + if (gid[0] && (gid[0] <= '0' || gid[0] >= '9')) + grent.gr_name = xstrdup(gid); + else + grent.gr_name = xstrdup(name); + + grent.gr_passwd = "x"; /* XXX warning: const */ + grent.gr_gid = i; + members[0] = xstrdup(name); + members[1] = (char *) 0; + grent.gr_mem = members; + + *ngid = grent.gr_gid; + return ! gr_update (&grent); +} + +/* + * add_user - create a new user ID + */ + +static int +add_user(const char *name, const char *uid, uid_t *nuid, gid_t gid) +{ + const struct passwd *pwd; + struct passwd pwent; + uid_t i; + + /* + * The first guess for the UID is either the numerical UID + * that the caller provided, or the next available UID. + */ + + if (uid[0] >= '0' && uid[0] <= '9') { + i = atoi (uid); + } else if (uid[0] && (pwd = pw_locate (uid))) { + i = pwd->pw_uid; + } else { + i = 100; + for (pw_rewind ();(pwd = pw_next ());) + if (pwd->pw_uid >= i) + i = pwd->pw_uid + 1; + } + + /* + * I don't want to fill in the entire password structure + * members JUST YET, since there is still more data to be + * added. So, I fill in the parts that I have. + */ + + pwent.pw_name = xstrdup(name); + pwent.pw_passwd = "x"; /* XXX warning: const */ +#ifdef ATT_AGE + pwent.pw_age = ""; +#endif +#ifdef ATT_COMMENT + pwent.pw_comment = ""; +#endif +#ifdef BSD_QUOTA + pwent.pw_quota = 0; +#endif + pwent.pw_uid = i; + pwent.pw_gid = gid; + pwent.pw_gecos = ""; /* XXX warning: const */ + pwent.pw_dir = ""; /* XXX warning: const */ + pwent.pw_shell = ""; /* XXX warning: const */ + + *nuid = i; + return ! pw_update (&pwent); +} + +static void +update_passwd(struct passwd *pwd, const char *passwd) +{ + pwd->pw_passwd = pw_encrypt(passwd, crypt_make_salt()); +#ifdef ATT_AGE + if (strlen(pwd->pw_age) == 4) { + static char newage[5]; + extern char *l64a(); + + strcpy(newage, pwd->pw_age); + strcpy(newage + 2, l64a(time((time_t *) 0) / WEEK)); + pwd->pw_age = newage; + } +#endif +} + +/* + * add_passwd - add or update the encrypted password + */ + +static int +add_passwd(struct passwd *pwd, const char *passwd) +{ +#ifdef SHADOWPWD + const struct spwd *sp; + struct spwd spent; +#endif + + /* + * In the case of regular password files, this is real + * easy - pwd points to the entry in the password file. + * Shadow files are harder since there are zillions of + * things to do ... + */ + + if (!is_shadow) { + update_passwd(pwd, passwd); + return 0; + } + +#ifdef SHADOWPWD + /* + * Do the first and easiest shadow file case. The user + * already exists in the shadow password file. + */ + + if ((sp = spw_locate (pwd->pw_name))) { + spent = *sp; + spent.sp_pwdp = pw_encrypt(passwd, crypt_make_salt()); + return ! spw_update (&spent); + } + + /* + * Pick the next easiest case - the user has an encrypted + * password which isn't equal to "x". The password was set + * to "x" earlier when the entry was created, so this user + * would have to have had the password set someplace else. + */ + + if (strcmp (pwd->pw_passwd, "x") != 0) { + update_passwd(pwd, passwd); + return 0; + } + + /* + * Now the really hard case - I need to create an entirely + * new shadow password file entry. + */ + + spent.sp_namp = pwd->pw_name; + spent.sp_pwdp = pw_encrypt(passwd, crypt_make_salt()); + spent.sp_lstchg = time((time_t *) 0) / SCALE; + spent.sp_min = getdef_num("PASS_MIN_DAYS", 0); + /* 10000 is infinity this week */ + spent.sp_max = getdef_num("PASS_MAX_DAYS", 10000); + spent.sp_warn = getdef_num("PASS_WARN_AGE", -1); + spent.sp_inact = -1; + spent.sp_expire = -1; + spent.sp_flag = -1; + + return ! spw_update (&spent); +#endif +} + +int +main(int argc, char **argv) +{ + char buf[BUFSIZ]; + char *fields[8]; + int nfields; + char *cp; + const struct passwd *pw; + struct passwd newpw; + int errors = 0; + int line = 0; + uid_t uid; + gid_t gid; + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (argc > 1 && argv[1][0] == '-') + usage (); + + if (argc == 2) { + if (! freopen (argv[1], "r", stdin)) { + snprintf(buf, sizeof buf, "%s: %s", Prog, argv[1]); + perror (buf); + exit (1); + } + } + + /* + * Lock the password files and open them for update. This will + * bring all of the entries into memory where they may be + * searched for an modified, or new entries added. The password + * file is the key - if it gets locked, assume the others can + * be locked right away. + */ + + if (!pw_lock()) { + fprintf (stderr, _("%s: can't lock /etc/passwd.\n"), Prog); + exit (1); + } +#ifdef SHADOWPWD + is_shadow = spw_file_present(); + + if ((is_shadow && !spw_lock()) || !gr_lock()) +#else + if (!gr_lock()) +#endif + { + fprintf (stderr, _("%s: can't lock files, try again later\n"), + Prog); + (void) pw_unlock (); +#ifdef SHADOWPWD + if (is_shadow) + spw_unlock(); +#endif + exit (1); + } +#ifdef SHADOWPWD + if (!pw_open(O_RDWR) || (is_shadow && !spw_open(O_RDWR)) || !gr_open(O_RDWR)) +#else + if (!pw_open(O_RDWR) || !gr_open(O_RDWR)) +#endif + { + fprintf (stderr, _("%s: can't open files\n"), Prog); + (void) pw_unlock (); +#ifdef SHADOWPWD + if (is_shadow) + spw_unlock(); +#endif + (void) gr_unlock (); + exit (1); + } + + /* + * Read each line. The line has the same format as a password + * file entry, except that certain fields are not contrained to + * be numerical values. If a group ID is entered which does + * not already exist, an attempt is made to allocate the same + * group ID as the numerical user ID. Should that fail, the + * next available group ID over 100 is allocated. The pw_gid + * field will be updated with that value. + */ + + while (fgets (buf, sizeof buf, stdin) != (char *) 0) { + line++; + if ((cp = strrchr (buf, '\n'))) { + *cp = '\0'; + } else { + fprintf (stderr, _("%s: line %d: line too long\n"), + Prog, line); + errors++; + continue; + } + + /* + * Break the string into fields and screw around with + * them. There MUST be 7 colon separated fields, + * although the values aren't that particular. + */ + + for (cp = buf, nfields = 0;nfields < 7;nfields++) { + fields[nfields] = cp; + if ((cp = strchr (cp, ':'))) + *cp++ = '\0'; + else + break; + } + if (nfields != 6) { + fprintf (stderr, _("%s: line %d: invalid line\n"), + Prog, line); + continue; + } + + /* + * Now the fields are processed one by one. The first + * field to be processed is the group name. A new + * group will be created if the group name is non-numeric + * and does not already exist. The named user will be + * the only member. If there is no named group to be a + * member of, the UID will be figured out and that value + * will be a candidate for a new group, if that group ID + * exists, a whole new group ID will be made up. + */ + + if (! (pw = pw_locate (fields[0])) && + add_group (fields[0], fields[3], &gid)) { + fprintf (stderr, _("%s: line %d: can't create GID\n"), + Prog, line); + errors++; + continue; + } + + /* + * Now we work on the user ID. It has to be specified + * either as a numerical value, or left blank. If it + * is a numerical value, that value will be used, otherwise + * the next available user ID is computed and used. After + * this there will at least be a (struct passwd) for the + * user. + */ + + if (! pw && add_user (fields[0], fields[2], &uid, gid)) { + fprintf (stderr, _("%s: line %d: can't create UID\n"), + Prog, line); + errors++; + continue; + } + + /* + * The password, gecos field, directory, and shell fields + * all come next. + */ + + if (! (pw = pw_locate (fields[0]))) { + fprintf (stderr, _("%s: line %d: cannot find user %s\n"), + Prog, line, fields[0]); + errors++; + continue; + } + newpw = *pw; + + if (add_passwd (&newpw, fields[1])) { + fprintf (stderr, _("%s: line %d: can't update password\n"), + Prog, line); + errors++; + continue; + } + if (fields[4][0]) + newpw.pw_gecos = fields[4]; + + if (fields[5][0]) + newpw.pw_dir = fields[5]; + + if (fields[6][0]) + newpw.pw_shell = fields[6]; + + if (newpw.pw_dir[0] && access(newpw.pw_dir, F_OK)) { + if (mkdir (newpw.pw_dir, + 0777 & ~getdef_num("UMASK", 077))) + fprintf (stderr, _("%s: line %d: mkdir failed\n"), + Prog, line); + else if (chown (newpw.pw_dir, + newpw.pw_uid, newpw.pw_gid)) + fprintf (stderr, _("%s: line %d: chown failed\n"), + Prog, line); + } + + /* + * Update the password entry with the new changes made. + */ + + if (! pw_update (&newpw)) { + fprintf (stderr, _("%s: line %d: can't update entry\n"), + Prog, line); + errors++; + continue; + } + } + + /* + * Any detected errors will cause the entire set of changes + * to be aborted. Unlocking the password file will cause + * all of the changes to be ignored. Otherwise the file is + * closed, causing the changes to be written out all at + * once, and then unlocked afterwards. + */ + + if (errors) { + fprintf (stderr, _("%s: error detected, changes ignored\n"), Prog); + (void) gr_unlock (); +#ifdef SHADOWPWD + if (is_shadow) + spw_unlock(); +#endif + (void) pw_unlock (); + exit (1); + } +#ifdef SHADOWPWD + if (!pw_close() || (is_shadow && !spw_close()) || !gr_close()) +#else + if (!pw_close() || ! gr_close()) +#endif + { + fprintf (stderr, _("%s: error updating files\n"), Prog); + (void) gr_unlock (); +#ifdef SHADOWPWD + if (is_shadow) + spw_unlock(); +#endif + (void) pw_unlock (); + exit (1); + } + (void) gr_unlock (); +#ifdef SHADOWPWD + if (is_shadow) + spw_unlock(); +#endif + (void) pw_unlock (); + + exit (0); + /*NOTREACHED*/ +} diff --git a/src/passwd.c b/src/passwd.c new file mode 100644 index 00000000..1f4480d1 --- /dev/null +++ b/src/passwd.c @@ -0,0 +1,1417 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: passwd.c,v 1.17 1999/07/09 18:02:43 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_USERSEC_H +#include +#include +#include +#endif + +#ifndef GPASSWD_PROGRAM +#define GPASSWD_PROGRAM "gpasswd" +#endif + +#ifndef CHFN_PROGRAM +#define CHFN_PROGRAM "chfn" +#endif + +#ifndef CHSH_PROGRAM +#define CHSH_PROGRAM "chsh" +#endif + +#include +#ifndef HAVE_USERSEC_H +#ifdef SHADOWPWD +#ifndef AGING +#define AGING 0 +#endif /* !AGING */ +#endif /* SHADOWPWD */ +#endif /* !HAVE_USERSEC_H */ +#include "pwauth.h" + +#ifdef HAVE_TCFS +#include +#include "tcfsio.h" +#endif + +#ifdef SHADOWPWD +#include "shadowio.h" +#endif +#include "pwio.h" +#include "getdef.h" + +/* + * exit status values + */ + +#define E_SUCCESS 0 /* success */ +#define E_NOPERM 1 /* permission denied */ +#define E_USAGE 2 /* invalid combination of options */ +#define E_FAILURE 3 /* unexpected failure, nothing done */ +#define E_MISSING 4 /* unexpected failure, passwd file missing */ +#define E_PWDBUSY 5 /* passwd file busy, try again later */ +#define E_BAD_ARG 6 /* invalid argument to option */ + +/* + * Global variables + */ + +#ifdef HAVE_USERSEC_H +int minage = 0; /* Minimum age in weeks */ +int maxage = 10000; /* Maximum age in weeks */ +#endif + +static char *name; /* The name of user whose password is being changed */ +static char *myname; /* The current user's name */ +static char *Prog; /* Program name */ +static int amroot; /* The real UID was 0 */ + +static int + lflg = 0, /* -l - lock account */ + uflg = 0, /* -u - unlock account */ + dflg = 0, /* -d - delete password */ +#ifdef AGING + xflg = 0, /* -x - set maximum days */ + nflg = 0, /* -n - set minimum days */ + eflg = 0, /* -e - force password change */ + kflg = 0, /* -k - change only if expired */ +#endif +#ifdef SHADOWPWD + wflg = 0, /* -w - set warning days */ + iflg = 0, /* -i - set inactive days */ +#endif + qflg = 0, /* -q - quiet mode */ + aflg = 0, /* -a - show status for all users */ + Sflg = 0; /* -S - show password status */ + +/* + * set to 1 if there are any flags which require root privileges, + * and require username to be specified + */ +static int anyflag = 0; + +#ifdef AGING +static long age_min = 0; /* Minimum days before change */ +static long age_max = 0; /* Maximum days until change */ +#ifdef SHADOWPWD +static long warn = 0; /* Warning days before change */ +static long inact = 0; /* Days without change before locked */ +#endif +#endif + +static int do_update_age = 0; + +#ifndef USE_PAM +static char crypt_passwd[128]; /* The "old-style" password, if present */ +static int do_update_pwd = 0; +#endif + +#ifdef HAVE_TCFS +static struct tcfspwd *tcfspword; +static int tcfs_force = 0; +#endif + +/* + * External identifiers + */ + +extern char *crypt_make_salt P_((void)); +#ifdef ATT_AGE +extern char *l64a(); +#endif + +extern int optind; /* Index into argv[] for current option */ +extern char *optarg; /* Pointer to current option value */ + +#ifndef HAVE_USERSEC_H +#ifdef NDBM +extern int sp_dbm_mode; +extern int pw_dbm_mode; +#endif +#endif + + +#define WRONGPWD2 "incorrect password for `%s'" +#define CANTCHANGE2 "password locked for `%s'" + +#define TOOSOON2 "now < minimum age for `%s'" + +#define EXECFAILED2 "cannot execute %s" +#define NOPERM2 "can't change pwd for `%s'" + +#define PWDBUSY2 "can't lock password file" +#define OPNERROR2 "can't open password file" +#define UPDERROR2 "error updating password entry" +#define CLSERROR2 "can't rewrite password file" +#define DBMERROR2 "error updaring dbm password entry" + +#ifdef HAVE_TCFS +#define TCFSPWDBUSY2 "can't lock TCFS key database" +#define TCFSOPNERROR2 "can't open TCFS key database" +#define TCFSUPDERROR2 "error updating TCFS key database" +#define TCFSCLSERROR2 "can't rewrite TCFS key database" +#endif + +#define NOTROOT2 "can't setuid(0)" +#define CHGPASSWD "password for `%s' changed by `%s'" +#define NOCHGPASSWD "did not change password for `%s'" + +/* local function prototypes */ +static void usage P_((int)); +#ifndef USE_PAM +#ifdef AUTH_METHODS +static char *get_password P_((const char *)); +static int uses_default_method P_((const char *)); +#endif /* AUTH_METHODS */ +static int reuse P_((const char *, const struct passwd *)); +static int new_password P_((const struct passwd *)); +#ifdef SHADOWPWD +static void check_password P_((const struct passwd *, const struct spwd *)); +#else /* !SHADOWPWD */ +static void check_password P_((const struct passwd *)); +#endif /* !SHADOWPWD */ +static char *insert_crypt_passwd P_((const char *, const char *)); +#endif /* !USE_PAM */ +static char *date_to_str P_((time_t)); +static const char *pw_status P_((const char *)); +static void print_status P_((const struct passwd *)); +static void fail_exit P_((int)); +static void oom P_((void)); +static char *update_crypt_pw P_((char *)); +static void update_noshadow P_((void)); +#ifdef SHADOWPWD +static void update_shadow P_((void)); +#endif +#ifdef HAVE_TCFS +static void update_tcfs P_((void)); +#endif +#ifdef HAVE_USERSEC_H +static void update_userpw P_((char *)); +#endif +static long getnumber P_((const char *)); +int main P_((int, char **)); + +/* + * usage - print command usage and exit + */ + +static void +usage(int status) +{ + fprintf(stderr, _("usage: %s [ -f | -s ] [ name ]\n"), Prog); + if (amroot) { + fprintf(stderr, + _(" %s [ -x max ] [ -n min ] [ -w warn ] [ -i inact ] name\n"), + Prog); + fprintf(stderr, + _(" %s { -l | -u | -d | -S | -e } name\n"), + Prog); + } + exit(status); +} + +#ifndef USE_PAM +#ifdef AUTH_METHODS +/* + * get_password - locate encrypted password in authentication list + */ + +static char * +get_password(const char *list) +{ + char *cp, *end; + static char buf[257]; + + STRFCPY(buf, list); + for (cp = buf;cp;cp = end) { + if ((end = strchr (cp, ';'))) + *end++ = 0; + + if (cp[0] == '@') + continue; + + return cp; + } + return (char *) 0; +} + +/* + * uses_default_method - determine if "old-style" password present + * + * uses_default_method determines if a "old-style" password is present + * in the authentication string, and if one is present it extracts it. + */ + +static int +uses_default_method(const char *methods) +{ + char *cp; + + if ((cp = get_password (methods))) { + STRFCPY(crypt_passwd, cp); + return 1; + } + return 0; +} +#endif /* AUTH_METHODS */ + +static int +reuse(const char *pass, const struct passwd *pw) +{ +#ifdef HAVE_LIBCRACK_HIST + const char *reason; +#ifdef HAVE_LIBCRACK_PW + const char *FascistHistoryPw P_((const char *,const struct passwd *)); + reason = FascistHistory(pass, pw); +#else + const char *FascistHistory P_((const char *, int)); + reason = FascistHistory(pass, pw->pw_uid); +#endif + if (reason) { + printf(_("Bad password: %s. "), reason); + return 1; + } +#endif + return 0; +} + +/* + * new_password - validate old password and replace with new + * (both old and new in global "char crypt_passwd[128]") + */ + +/*ARGSUSED*/ +static int +new_password(const struct passwd *pw) +{ + char *clear; /* Pointer to clear text */ + char *cipher; /* Pointer to cipher text */ + char *cp; /* Pointer to getpass() response */ + char orig[200]; /* Original password */ + char pass[200]; /* New password */ + int i; /* Counter for retries */ + int warned; + int pass_max_len; +#ifdef HAVE_LIBCRACK_HIST + int HistUpdate P_((const char *, const char *)); +#endif + + /* + * Authenticate the user. The user will be prompted for their + * own password. + */ + +#ifdef HAVE_TCFS + tcfs_force = tcfs_force && amroot; + + if ((tcfs_locate(name) && !tcfs_force) || (!amroot && crypt_passwd[0])) { + if (amroot) { + printf(_("User %s has a TCFS key, his old password is required.\n"), name); + printf(_("You can use -t option to force the change.\n")); + } +#else + if (! amroot && crypt_passwd[0]) { +#endif + + if (!(clear = getpass(_("Old password:")))) + return -1; + + cipher = pw_encrypt(clear, crypt_passwd); + if (strcmp(cipher, crypt_passwd) != 0) { + SYSLOG((LOG_WARN, WRONGPWD2, pw->pw_name)); + sleep(1); + fprintf(stderr, _("Incorrect password for `%s'\n"), + pw->pw_name); + return -1; + } + STRFCPY(orig, clear); +#ifdef HAVE_TCFS + STRFCPY(tcfspword->tcfsorig, clear); +#endif + strzero(clear); + strzero(cipher); + } else { +#ifdef HAVE_TCFS + if (tcfs_locate(name)) + printf(_("Warning: user %s has a TCFS key.\n"), name); +#endif + orig[0] = '\0'; + } + + /* + * Get the new password. The user is prompted for the new password + * and has five tries to get it right. The password will be tested + * for strength, unless it is the root user. This provides an escape + * for initial login passwords. + */ + + if (getdef_bool("MD5_CRYPT_ENAB")) + pass_max_len = 127; + else + pass_max_len = getdef_num("PASS_MAX_LEN", 8); + + if (!qflg) + printf(_("\ +Enter the new password (minimum of %d, maximum of %d characters)\n\ +Please use a combination of upper and lower case letters and numbers.\n"), + getdef_num("PASS_MIN_LEN", 5), pass_max_len); + + warned = 0; + for (i = getdef_num("PASS_CHANGE_TRIES", 5); i > 0; i--) { + if (!(cp = getpass(_("New password:")))) { + memzero(orig, sizeof orig); + return -1; + } + if (warned && strcmp(pass, cp) != 0) + warned = 0; + STRFCPY(pass, cp); + strzero(cp); + + if (!amroot && (!obscure(orig, pass, pw) || reuse(pass, pw))) { + printf(_("Try again.\n")); + continue; + } + /* + * If enabled, warn about weak passwords even if you are root + * (enter this password again to use it anyway). --marekm + */ + if (amroot && !warned && getdef_bool("PASS_ALWAYS_WARN") + && (!obscure(orig, pass, pw) || reuse(pass, pw))) { + printf(_("\nWarning: weak password (enter it again to use it anyway).\n")); + warned++; + continue; + } + if (!(cp = getpass(_("Re-enter new password:")))) { + memzero(orig, sizeof orig); + return -1; + } + if (strcmp (cp, pass)) + fprintf(stderr, _("They don't match; try again.\n")); + else { + strzero(cp); + break; + } + } + memzero(orig, sizeof orig); + + if (i == 0) { + memzero(pass, sizeof pass); + return -1; + } + +#ifdef HAVE_TCFS + STRFCPY(tcfspword->tcfspass, pass); +#endif + + /* + * Encrypt the password, then wipe the cleartext password. + */ + + cp = pw_encrypt(pass, crypt_make_salt()); + memzero(pass, sizeof pass); + +#ifdef HAVE_LIBCRACK_HIST + HistUpdate(pw->pw_name, crypt_passwd); +#endif + STRFCPY(crypt_passwd, cp); + return 0; +} + +/* + * check_password - test a password to see if it can be changed + * + * check_password() sees if the invoker has permission to change the + * password for the given user. + */ + +#ifdef SHADOWPWD +static void +check_password(const struct passwd *pw, const struct spwd *sp) +{ +#else +static void +check_password(const struct passwd *pw) +{ +#endif + time_t now, last, ok; + int exp_status; +#ifdef HAVE_USERSEC_H + struct userpw *pu; +#endif + +#ifdef SHADOWPWD + exp_status = isexpired(pw, sp); +#else + exp_status = isexpired(pw); +#endif + + /* + * If not expired and the "change only if expired" option + * (idea from PAM) was specified, do nothing... --marekm + */ + if (kflg && exp_status == 0) + exit(E_SUCCESS); + + /* + * Root can change any password any time. + */ + + if (amroot) + return; + + time(&now); + +#ifdef SHADOWPWD + /* + * Expired accounts cannot be changed ever. Passwords + * which are locked may not be changed. Passwords where + * min > max may not be changed. Passwords which have + * been inactive too long cannot be changed. + */ + + if (sp->sp_pwdp[0] == '!' || exp_status > 1 || + (sp->sp_max >= 0 && sp->sp_min > sp->sp_max)) { + fprintf(stderr, _("The password for %s cannot be changed.\n"), + sp->sp_namp); + SYSLOG((LOG_WARN, CANTCHANGE2, sp->sp_namp)); + closelog(); + exit(E_NOPERM); + } + + /* + * Passwords may only be changed after sp_min time is up. + */ + + last = sp->sp_lstchg * SCALE; + ok = last + (sp->sp_min > 0 ? sp->sp_min * SCALE : 0); + +#else /* !SHADOWPWD */ + if (pw->pw_passwd[0] == '!' || exp_status > 1) { + fprintf(stderr, _("The password for %s cannot be changed.\n"), + pw->pw_name); + SYSLOG((LOG_WARN, CANTCHANGE2, pw->pw_name)); + closelog(); + exit(E_NOPERM); + } +#ifdef ATT_AGE + /* + * Can always be changed if there is no age info + */ + + if (! pw->pw_age[0]) + return; + + last = a64l (pw->pw_age + 2) * WEEK; + ok = last + c64i (pw->pw_age[1]) * WEEK; +#else /* !ATT_AGE */ +#ifdef HAVE_USERSEC_H + pu = getuserpw(pw->pw_name); + last = pu ? pu->upw_lastupdate : 0L; + ok = last + (minage > 0 ? minage * WEEK : 0); +#else + last = 0; + ok = 0; +#endif +#endif /* !ATT_AGE */ +#endif /* !SHADOWPWD */ + if (now < ok) { + fprintf(stderr, _("Sorry, the password for %s cannot be changed yet.\n"), pw->pw_name); + SYSLOG((LOG_WARN, TOOSOON2, pw->pw_name)); + closelog(); + exit(E_NOPERM); + } +} + +/* + * insert_crypt_passwd - add an "old-style" password to authentication string + * result now malloced to avoid overflow, just in case. --marekm + */ +static char * +insert_crypt_passwd(const char *string, const char *passwd) +{ +#ifdef AUTH_METHODS + if (string && *string) { + char *cp, *result; + + result = xmalloc(strlen(string) + strlen(passwd) + 1); + cp = result; + while (*string) { + if (string[0] == ';') { + *cp++ = *string++; + } else if (string[0] == '@') { + while (*string && *string != ';') + *cp++ = *string++; + } else { + while (*passwd) + *cp++ = *passwd++; + + while (*string && *string != ';') + string++; + } + } + *cp = '\0'; + return result; + } +#endif + return xstrdup(passwd); +} +#endif /* !USE_PAM */ + +static char * +date_to_str(time_t t) +{ + static char buf[80]; + struct tm *tm; + + tm = gmtime(&t); +#ifdef HAVE_STRFTIME + strftime(buf, sizeof buf, "%m/%d/%Y", tm); +#else + snprintf(buf, sizeof buf, "%02d/%02d/%04d", + tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900); +#endif + return buf; +} + +static const char * +pw_status(const char *pass) +{ + if (*pass == '*' || *pass == '!') + return "L"; + if (*pass == '\0') + return "NP"; + return "P"; +} + +/* + * print_status - print current password status + */ + +static void +print_status(const struct passwd *pw) +{ +#ifdef SHADOWPWD + struct spwd *sp; +#endif +#ifdef HAVE_USERSEC_H + struct userpw *pu; +#endif + +#ifdef SHADOWPWD + sp = getspnam(pw->pw_name); + if (sp) { + printf("%s %s %s %ld %ld %ld %ld\n", + pw->pw_name, + pw_status(sp->sp_pwdp), + date_to_str(sp->sp_lstchg * SCALE), + (sp->sp_min * SCALE) / DAY, + (sp->sp_max * SCALE) / DAY, + (sp->sp_warn * SCALE) / DAY, + (sp->sp_inact * SCALE) / DAY); + } else +#endif + { +#ifdef HAVE_USERSEC_H + pu = getuserpw(name); + printf("%s %s %s %d %d\n", + pw->pw_name, + pw_status(pw->pw_passwd), + date_to_str(pu ? pu->upw_lastupdate : 0L), + minage > 0 ? minage * 7 : 0, + maxage > 0 ? maxage * 7 : 10000); +#else /* !HAVE_USERSEC_H */ +#ifdef ATT_AGE + printf("%s %s %s %d %d\n", + pw->pw_name, + pw_status(pw->pw_passwd), + date_to_str(strlen(pw->pw_age) > 2 ? + a64l(pw->pw_age + 2) * WEEK : 0L), + pw->pw_age[0] ? c64i(pw->pw_age[1]) * 7 : 0, + pw->pw_age[0] ? c64i(pw->pw_age[0]) * 7 : 10000); +#else + printf("%s %s\n", pw->pw_name, pw_status(pw->pw_passwd)); +#endif +#endif /* !HAVE_USERSEC_H */ + } +} + + +static void +fail_exit(int status) +{ + pw_unlock(); +#ifdef SHADOWPWD + spw_unlock(); +#endif +#ifdef HAVE_TCFS + tcfs_unlock(); +#endif + exit(status); +} + +static void +oom(void) +{ + fprintf(stderr, _("%s: out of memory\n"), Prog); + fail_exit(E_FAILURE); +} + +static char * +update_crypt_pw(char *cp) +{ +#ifndef USE_PAM + if (do_update_pwd) + cp = insert_crypt_passwd(cp, crypt_passwd); +#endif + + if (dflg) + cp = ""; /* XXX warning: const */ + + if (uflg && *cp == '!') + cp++; + + if (lflg && *cp != '!') { + char *newpw = xmalloc(strlen(cp) + 2); + + strcpy(newpw, "!"); + strcat(newpw, cp); + cp = newpw; + } + return cp; +} + + +static void +update_noshadow(void) +{ + const struct passwd *pw; + struct passwd *npw; +#ifdef ATT_AGE + char age[5]; + long week = time((time_t *) 0) / WEEK; + char *cp; +#endif + + if (!pw_lock()) { + fprintf(stderr, + _("Cannot lock the password file; try again later.\n")); + SYSLOG((LOG_WARN, PWDBUSY2)); + exit(E_PWDBUSY); + } + if (!pw_open(O_RDWR)) { + fprintf(stderr, _("Cannot open the password file.\n")); + SYSLOG((LOG_ERR, OPNERROR2)); + fail_exit(E_MISSING); + } + pw = pw_locate(name); + if (!pw) { + fprintf(stderr, _("%s: %s not found in /etc/passwd\n"), + Prog, name); + fail_exit(E_NOPERM); + } + npw = __pw_dup(pw); + if (!npw) + oom(); + npw->pw_passwd = update_crypt_pw(npw->pw_passwd); +#ifdef ATT_AGE + memzero(age, sizeof(age)); + STRFCPY(age, npw->pw_age); + + /* + * Just changing the password - update the last change date + * if there is one, otherwise the age just disappears. + */ + if (do_update_age) { + if (strlen(age) > 2) { + cp = l64a(week); + age[2] = cp[0]; + age[3] = cp[1]; + } else { + age[0] = '\0'; + } + } + + if (xflg) { + if (age_max > 0) + age[0] = i64c((age_max + 6) / 7); + else + age[0] = '.'; + + if (age[1] == '\0') + age[1] = '.'; + } + if (nflg) { + if (age[0] == '\0') + age[0] = 'z'; + + if (age_min > 0) + age[1] = i64c((age_min + 6) / 7); + else + age[1] = '.'; + } + /* + * The last change date is added by -n or -x if it's + * not already there. + */ + if ((nflg || xflg) && strlen(age) <= 2) { + cp = l64a(week); + age[2] = cp[0]; + age[3] = cp[1]; + } + + /* + * Force password change - if last change date is + * present, it will be set to (today - max - 1 week). + * Otherwise, just set min = max = 0 (will disappear + * when password is changed). + */ + if (eflg) { + if (strlen(age) > 2) { + cp = l64a(week - c64i(age[0]) - 1); + age[2] = cp[0]; + age[3] = cp[1]; + } else { + strcpy(age, ".."); + } + } + + npw->pw_age = age; +#endif + if (!pw_update(npw)) { + fprintf(stderr, _("Error updating the password entry.\n")); + SYSLOG((LOG_ERR, UPDERROR2)); + fail_exit(E_FAILURE); + } +#ifdef NDBM + if (pw_dbm_present() && !pw_dbm_update(npw)) { + fprintf(stderr, _("Error updating the DBM password entry.\n")); + SYSLOG((LOG_ERR, DBMERROR2)); + fail_exit(E_FAILURE); + } + endpwent(); +#endif + if (!pw_close()) { + fprintf(stderr, _("Cannot commit password file changes.\n")); + SYSLOG((LOG_ERR, CLSERROR2)); + fail_exit(E_FAILURE); + } + pw_unlock(); +} + +#ifdef HAVE_TCFS +static void +update_tcfs(void) +{ + if (!tcfs_force) { + if (!tcfs_lock()) { + fprintf(stderr, _("Cannot lock the TCFS key database; try again later\n")); + SYSLOG((LOG_WARN, TCFSPWDBUSY2)); + exit(E_PWDBUSY); + } + if (!tcfs_open(O_RDWR)) { + fprintf(stderr, + _("Cannot open the TCFS key database.\n")); + SYSLOG((LOG_WARN, TCFSOPNERROR2)); + fail_exit(E_MISSING); + } + if (!tcfs_update(name, tcfspword)) { + fprintf(stderr, + _("Error updating the TCFS key database.\n")); + SYSLOG((LOG_ERR, TCFSUPDERROR2)); + fail_exit(E_FAILURE); + } + if (!tcfs_close()) { + fprintf(stderr, _("Cannot commit TCFS changes.\n")); + SYSLOG((LOG_ERR, TCFSCLSERROR2)); + fail_exit(E_FAILURE); + } + tcfs_unlock(); + } +} +#endif /* HAVE_TCFS */ + +#ifdef SHADOWPWD +static void +update_shadow(void) +{ + const struct spwd *sp; + struct spwd *nsp; + + if (!spw_lock()) { + fprintf(stderr, + _("Cannot lock the password file; try again later.\n")); + SYSLOG((LOG_WARN, PWDBUSY2)); + exit(E_PWDBUSY); + } + if (!spw_open(O_RDWR)) { + fprintf(stderr, _("Cannot open the password file.\n")); + SYSLOG((LOG_ERR, OPNERROR2)); + fail_exit(E_FAILURE); + } + sp = spw_locate(name); + if (!sp) { + /* Try to update the password in /etc/passwd instead. */ + spw_close(); + update_noshadow(); + spw_unlock(); + return; + } + nsp = __spw_dup(sp); + if (!nsp) + oom(); + nsp->sp_pwdp = update_crypt_pw(nsp->sp_pwdp); + if (xflg) + nsp->sp_max = (age_max * DAY) / SCALE; + if (nflg) + nsp->sp_min = (age_min * DAY) / SCALE; + if (wflg) + nsp->sp_warn = (warn * DAY) / SCALE; + if (iflg) + nsp->sp_inact = (inact * DAY) / SCALE; + if (do_update_age) + nsp->sp_lstchg = time((time_t *) 0) / SCALE; + /* + * Force change on next login, like SunOS 4.x passwd -e or + * Solaris 2.x passwd -f. Solaris 2.x seems to do the same + * thing (set sp_lstchg to 0). + */ + if (eflg) + nsp->sp_lstchg = 0; + + if (!spw_update(nsp)) { + fprintf(stderr, _("Error updating the password entry.\n")); + SYSLOG((LOG_ERR, UPDERROR2)); + fail_exit(E_FAILURE); + } +#ifdef NDBM + if (sp_dbm_present() && !sp_dbm_update(nsp)) { + fprintf(stderr, _("Error updating the DBM password entry.\n")); + SYSLOG((LOG_ERR, DBMERROR2)); + fail_exit(E_FAILURE); + } + endspent(); +#endif + if (!spw_close()) { + fprintf(stderr, _("Cannot commit password file changes.\n")); + SYSLOG((LOG_ERR, CLSERROR2)); + fail_exit(E_FAILURE); + } + spw_unlock(); +} +#endif /* SHADOWPWD */ + +#ifdef HAVE_USERSEC_H +static void +update_userpw(char *cp) +{ + struct userpw userpw; + + /* + * AIX very conveniently has its own mechanism for updating + * passwords. Use it instead ... + */ + + strcpy(userpw.upw_name, name); + userpw.upw_passwd = update_crypt_pw(cp); + userpw.upw_lastupdate = time (0); + userpw.upw_flags = 0; + + setpwdb(S_WRITE); + + if (putuserpw(&userpw)) { + fprintf(stderr, _("Error updating the password entry.\n")); + SYSLOG((LOG_ERR, UPDERROR2)); + closelog(); + exit(E_FAILURE); + } + endpwdb(); +} +#endif + +static long +getnumber(const char *str) +{ + long val; + char *cp; + + val = strtol(str, &cp, 10); + if (*cp) + usage(E_BAD_ARG); + return val; +} + +/* + * passwd - change a user's password file information + * + * This command controls the password file and commands which are + * used to modify it. + * + * The valid options are + * + * -l lock the named account (*) + * -u unlock the named account (*) + * -d delete the password for the named account (*) + * -e expire the password for the named account (*) + * -x # set sp_max to # days (*) + * -n # set sp_min to # days (*) + * -w # set sp_warn to # days (*) + * -i # set sp_inact to # days (*) + * -S show password status of named account + * -g execute gpasswd command to interpret flags + * -f execute chfn command to interpret flags + * -s execute chsh command to interpret flags + * -k change password only if expired + * -t force 'passwd' to change the password regardless of TCFS + * + * (*) requires root permission to execute. + * + * All of the time fields are entered in days and converted to the + * appropriate internal format. For finer resolute the chage + * command must be used. + */ + +int +main(int argc, char **argv) +{ + int flag; /* Current option to process */ + const struct passwd *pw; /* Password file entry for user */ +#ifndef USE_PAM + char *cp; /* Miscellaneous character pointing */ +#ifdef SHADOWPWD + const struct spwd *sp; /* Shadow file entry for user */ +#endif +#endif + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * The program behaves differently when executed by root + * than when executed by a normal user. + */ + amroot = (getuid () == 0); + + /* + * Get the program name. The program name is used as a + * prefix to most error messages. + */ + Prog = Basename(argv[0]); + + sanitize_env(); + + openlog("passwd", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + /* + * Start with the flags which cause another command to be + * executed. The effective UID will be set back to the + * real UID and the new command executed with the flags + * + * These flags are deprecated, may change in a future + * release. Please run these programs directly. --marekm + */ + + if (argc > 1 && argv[1][0] == '-' && strchr ("gfs", argv[1][1])) { + char buf[200]; + + setuid(getuid()); + switch (argv[1][1]) { + case 'g': + argv[1] = GPASSWD_PROGRAM; /* XXX warning: const */ + break; + case 'f': + argv[1] = CHFN_PROGRAM; /* XXX warning: const */ + break; + case 's': + argv[1] = CHSH_PROGRAM; /* XXX warning: const */ + break; + default: + usage(E_BAD_ARG); + } + snprintf(buf, sizeof buf, _("%s: Cannot execute %s"), + Prog, argv[1]); + execvp(argv[1], &argv[1]); + perror(buf); + SYSLOG((LOG_ERR, EXECFAILED2, argv[1])); + closelog(); + exit(E_FAILURE); + } + + /* + * The remaining arguments will be processed one by one and + * executed by this command. The name is the last argument + * if it does not begin with a "-", otherwise the name is + * determined from the environment and must agree with the + * real UID. Also, the UID will be checked for any commands + * which are restricted to root only. + */ + +#ifdef SHADOWPWD +#define FLAGS "adlqr:uSekn:x:i:w:" +#ifdef HAVE_TCFS +#undef FLAGS +#define FLAGS "adlqr:uSekn:x:i:w:t" +#endif +#else +#ifdef AGING +#define FLAGS "adlqr:uSekn:x:" +#ifdef HAVE_TCFS +#undef FLAGS +#define FLAGS "adlqr:uSekn:x:t" +#endif +#else +#define FLAGS "adlqr:uS" +#ifdef HAVE_TCFS +#undef FLAGS +#define FLAGS "adlqr:uSt" +#endif +#endif +#endif + while ((flag = getopt(argc, argv, FLAGS)) != EOF) { +#undef FLAGS + switch (flag) { +#ifdef AGING + case 'x': + age_max = getnumber(optarg); + xflg++; + anyflag = 1; + break; + case 'n': + age_min = getnumber(optarg); + nflg++; + anyflag = 1; + break; +#ifdef HAVE_TCFS + case 't': + tcfs_force = 1; + break; +#endif +#ifdef SHADOWPWD + case 'w': + warn = getnumber(optarg); + if (warn >= -1) + wflg++; + anyflag = 1; + break; + case 'i': + inact = getnumber(optarg); + if (inact >= -1) + iflg++; + anyflag = 1; + break; +#endif /* SHADOWPWD */ + case 'e': + eflg++; + anyflag = 1; + break; + case 'k': + /* change only if expired, like Linux-PAM passwd -k. */ + kflg++; /* ok for users */ + break; +#endif /* AGING */ + case 'a': + aflg++; + break; + case 'q': + qflg++; /* ok for users */ + break; + case 'S': + Sflg++; /* ok for users */ + break; + case 'd': + dflg++; + anyflag = 1; + break; + case 'l': + lflg++; + anyflag = 1; + break; + case 'u': + uflg++; + anyflag = 1; + break; + case 'r': + /* -r repository (files|nis|nisplus) */ + /* only "files" supported for now */ + if (strcmp(optarg, "files") != 0) { + fprintf(stderr, + _("%s: repository %s not supported\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + break; + default: + usage(E_BAD_ARG); + } + } + +#ifdef HAVE_USERSEC_H + /* + * The aging information lives someplace else. Get it from the + * login.cfg file + */ + + if (getconfattr(SC_SYS_PASSWD, SC_MINAGE, &minage, SEC_INT)) + minage = -1; + + if (getconfattr(SC_SYS_PASSWD, SC_MAXAGE, &maxage, SEC_INT)) + maxage = -1; +#endif /* HAVE_USERSEC_H */ + + /* + * Now I have to get the user name. The name will be gotten + * from the command line if possible. Otherwise it is figured + * out from the environment. + */ + + pw = get_my_pwent(); + if (!pw) { + fprintf(stderr, _("%s: Cannot determine your user name.\n"), + Prog); + exit(E_NOPERM); + } + myname = xstrdup(pw->pw_name); + if (optind < argc) + name = argv[optind]; + else + name = myname; + + /* + * The -a flag requires -S, no other flags, no username, and + * you must be root. --marekm + */ + + if (aflg) { + if (anyflag || !Sflg || (optind < argc)) + usage(E_USAGE); + if (!amroot) { + fprintf(stderr, _("%s: Permission denied.\n"), Prog); + exit(E_NOPERM); + } + setpwent(); + while ((pw = getpwent())) + print_status(pw); + exit(E_SUCCESS); + } + +#if 0 + /* + * Allow certain users (administrators) to change passwords of + * certain users. Not implemented yet... --marekm + */ + if (may_change_passwd(myname, name)) + amroot = 1; +#endif + + /* + * If any of the flags were given, a user name must be supplied + * on the command line. Only an unadorned command line doesn't + * require the user's name be given. Also, -x, -n, -w, -i, -e, -d, + * -l, -u may appear with each other. -S, -k must appear alone. + */ + + /* + * -S now ok for normal users (check status of my own account), + * and doesn't require username. --marekm + */ + + if (anyflag && optind >= argc) + usage(E_USAGE); + + if (anyflag + Sflg + kflg > 1) + usage(E_USAGE); + + if (anyflag && !amroot) { + fprintf(stderr, _("%s: Permission denied\n"), Prog); + exit(E_NOPERM); + } + +#ifdef NDBM + endpwent(); + pw_dbm_mode = O_RDWR; +#ifdef SHADOWPWD + sp_dbm_mode = O_RDWR; +#endif +#endif + + pw = getpwnam(name); + if (!pw) { + fprintf(stderr, _("%s: Unknown user %s\n"), Prog, name); + exit(E_NOPERM); + } + + /* + * Now I have a name, let's see if the UID for the name + * matches the current real UID. + */ + + if (!amroot && pw->pw_uid != getuid ()) { + fprintf(stderr, _("You may not change the password for %s.\n"), + name); + SYSLOG((LOG_WARN, NOPERM2, name)); + closelog(); + exit(E_NOPERM); + } + + if (Sflg) { + print_status(pw); + exit(E_SUCCESS); + } + +#ifndef USE_PAM +#ifdef SHADOWPWD + /* + * The user name is valid, so let's get the shadow file + * entry. + */ + + sp = getspnam(name); + if (!sp) + sp = pwd_to_spwd(pw); + + cp = sp->sp_pwdp; +#else + cp = pw->pw_passwd; +#endif + + /* + * If there are no other flags, just change the password. + */ + + if (!anyflag) { +#ifdef AUTH_METHODS + if (strchr(cp, '@')) { + if (pw_auth(cp, name, PW_CHANGE, (char *)0)) { + SYSLOG((LOG_INFO, NOCHGPASSWD, name)); + closelog(); + exit(E_NOPERM); + } else if (! uses_default_method(cp)) { + do_update_age = 1; + goto done; + } + } else +#endif + STRFCPY(crypt_passwd, cp); + + /* + * See if the user is permitted to change the password. + * Otherwise, go ahead and set a new password. + */ + +#ifdef SHADOWPWD + check_password(pw, sp); +#else + check_password(pw); +#endif + +#ifdef HAVE_TCFS + tcfspword = (struct tcfspwd *)calloc(1, sizeof (struct tcfspwd)); +#endif + /* + * Let the user know whose password is being changed. + */ + if (!qflg) + printf(_("Changing password for %s\n"), name); + + if (new_password(pw)) { + fprintf(stderr, + _("The password for %s is unchanged.\n"), + name); + closelog(); + exit(E_NOPERM); + } + do_update_pwd = 1; + do_update_age = 1; + } + +#ifdef AUTH_METHODS +done: +#endif +#endif /* !USE_PAM */ + /* + * Before going any further, raise the ulimit to prevent + * colliding into a lowered ulimit, and set the real UID + * to root to protect against unexpected signals. Any + * keyboard signals are set to be ignored. + */ + + pwd_init(); + + /* + * Don't set the real UID for PAM... + */ +#ifdef USE_PAM + if (!anyflag) { + do_pam_passwd(name, qflg, kflg); + exit(E_SUCCESS); + } +#endif /* USE_PAM */ + if (setuid(0)) { + fprintf(stderr, _("Cannot change ID to root.\n")); + SYSLOG((LOG_ERR, NOTROOT2)); + closelog(); + exit(E_NOPERM); + } +#ifdef HAVE_USERSEC_H + update_userpw(pw->pw_passwd); +#else /* !HAVE_USERSEC_H */ + +#ifdef SHADOWPWD + if (spw_file_present()) + update_shadow(); + else +#endif + update_noshadow(); + +#ifdef HAVE_TCFS + if (tcfs_locate(name) && tcfs_file_present()) + update_tcfs(); +#endif +#endif /* !HAVE_USERSEC_H */ + SYSLOG((LOG_INFO, CHGPASSWD, name, myname)); + closelog(); + if (!qflg) + printf(_("Password changed.\n")); + exit(E_SUCCESS); + /*NOTREACHED*/ +} diff --git a/src/patchlevel.h b/src/patchlevel.h new file mode 100644 index 00000000..3fb8dce4 --- /dev/null +++ b/src/patchlevel.h @@ -0,0 +1,58 @@ +/* + * Copyright 1991 - 1995, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Revision History + * 11/25/91 3.1.1 patchlevel 14 + * Added "login.defs" to Makefile + * 12/02/91 3.1.2 patchlevel 15 + * Bugs found by users + * 12/28/91 3.1.3 patchlevel 16 + * Changes for SunOS 4.1.1 + * 02/08/92 3.1.4 patchlevel 17 + * Changes for SVR4, plus bug fixes + * 04/03/92 3.2.1 patchlevel 18 + * Minor bug fixes, new baseline + * 07/07/92 3.2.2 patchlevel 20 + * Added administrator defined authentication + * 11/04/92 3.2.3 patchlevel 21 + * Bug fixes for SVR4 + * 07/23/93 3.3.0 patchlevel 23 + * New baseline release + * 08/23/93 3.3.1 patchlevel 24 + * Bug fixes for SunOS 4.1.1 + * 08/27/93 3.3.2 patchlevel 25 + * Initial NIS support changes + * 12/03/95 3.3.3 patchlevel 26 + * This is the Linux beta baseline. Marek will + * change the name some other day. -- jfh + * $Id: patchlevel.h,v 1.2 1997/05/01 23:07:16 marekm Exp $ + */ + +#define RELEASE 3 +#define PATCHLEVEL 26 +#define VERSION "3.3.3" diff --git a/src/pwck.c b/src/pwck.c new file mode 100644 index 00000000..f30241b0 --- /dev/null +++ b/src/pwck.c @@ -0,0 +1,617 @@ +/* + * Copyright 1992 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: pwck.c,v 1.13 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" +#include "chkname.h" +#include + +#include "commonio.h" + +#include "pwio.h" +extern void __pw_del_entry P_((const struct commonio_entry *)); +extern struct commonio_entry *__pw_get_head P_((void)); + +#ifdef SHADOWPWD +#include "shadowio.h" +extern void __spw_del_entry P_((const struct commonio_entry *)); +extern struct commonio_entry *__spw_get_head P_((void)); +#endif + +/* + * Exit codes + */ + +#define E_OKAY 0 +#define E_USAGE 1 +#define E_BADENTRY 2 +#define E_CANTOPEN 3 +#define E_CANTLOCK 4 +#define E_CANTUPDATE 5 + +/* + * Global variables + */ + +extern int optind; +extern char *optarg; + +/* + * Local variables + */ + +static char *Prog; +static const char *pwd_file = PASSWD_FILE; +#ifdef SHADOWPWD +static const char *spw_file = SHADOW_FILE; +#endif +static int read_only = 0; +static int quiet = 0; /* don't report warnings, only errors */ + +/* local function prototypes */ +static void usage P_((void)); +static int yes_or_no P_((void)); +int main P_((int, char **)); + +/* + * usage - print syntax message and exit + */ + +static void +usage(void) +{ +#ifdef SHADOWPWD + fprintf(stderr, _("Usage: %s [ -qr ] [ passwd [ shadow ] ]\n"), Prog); +#else + fprintf(stderr, _("Usage: %s [ -qr ] [ passwd ]\n"), Prog); +#endif + exit(E_USAGE); +} + +/* + * yes_or_no - get answer to question from the user + */ + +static int +yes_or_no(void) +{ + char buf[80]; + + /* + * In read-only mode all questions are answered "no". + */ + + if (read_only) { + puts(_("No")); + return 0; + } + + /* + * Get a line and see what the first character is. + */ + + if (fgets(buf, sizeof buf, stdin)) + return buf[0] == 'y' || buf[0] == 'Y'; + + return 0; +} + +/* + * pwck - verify password file integrity + */ + +int +main(int argc, char **argv) +{ + int arg; + int errors = 0; + int deleted = 0; + struct commonio_entry *pfe, *tpfe; + struct passwd *pwd; +#ifdef SHADOWPWD + struct commonio_entry *spe, *tspe; + struct spwd *spw; + int is_shadow = 0; +#endif + + /* + * Get my name so that I can use it to report errors. + */ + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + /* + * Parse the command line arguments + */ + + while ((arg = getopt(argc, argv, "eqr")) != EOF) { + switch (arg) { + case 'e': /* added for Debian shadow-961025-2 compatibility */ + case 'q': + quiet = 1; + break; + case 'r': + read_only = 1; + break; + default: + usage(); + } + } + + /* + * Make certain we have the right number of arguments + */ + +#ifdef SHADOWPWD + if (optind != argc && optind + 1 != argc && optind + 2 != argc) +#else + if (optind != argc && optind + 1 != argc) +#endif + usage(); + + /* + * If there are two left over filenames, use those as the + * password and shadow password filenames. + */ + + if (optind != argc) { + pwd_file = argv[optind]; + pw_name(pwd_file); + } +#ifdef SHADOWPWD + if (optind + 2 == argc) { + spw_file = argv[optind + 1]; + spw_name(spw_file); + is_shadow = 1; + } else if (optind == argc) + is_shadow = spw_file_present(); +#endif + + /* + * Lock the files if we aren't in "read-only" mode + */ + + if (!read_only) { + if (!pw_lock()) { + fprintf(stderr, _("%s: cannot lock file %s\n"), + Prog, pwd_file); + if (optind == argc) + SYSLOG((LOG_WARN,"cannot lock %s\n",pwd_file)); + closelog(); + exit(E_CANTLOCK); + } +#ifdef SHADOWPWD + if (is_shadow && !spw_lock()) { + fprintf(stderr, _("%s: cannot lock file %s\n"), + Prog, spw_file); + if (optind == argc) + SYSLOG((LOG_WARN,"cannot lock %s\n",spw_file)); + closelog(); + exit(E_CANTLOCK); + } +#endif + } + + /* + * Open the files. Use O_RDONLY if we are in read_only mode, + * O_RDWR otherwise. + */ + + if (!pw_open(read_only ? O_RDONLY:O_RDWR)) { + fprintf(stderr, _("%s: cannot open file %s\n"), + Prog, pwd_file); + if (optind == argc) + SYSLOG((LOG_WARN, "cannot open %s\n", pwd_file)); + closelog(); + exit(E_CANTOPEN); + } +#ifdef SHADOWPWD + if (is_shadow && !spw_open(read_only ? O_RDONLY : O_RDWR)) { + fprintf(stderr, _("%s: cannot open file %s\n"), + Prog, spw_file); + if (optind == argc) + SYSLOG((LOG_WARN, "cannot open %s\n", spw_file)); + closelog(); + exit(E_CANTOPEN); + } +#endif + + /* + * Loop through the entire password file. + */ + + for (pfe = __pw_get_head(); pfe; pfe = pfe->next) { + /* + * If this is a NIS line, skip it. You can't "know" what + * NIS is going to do without directly asking NIS ... + */ + + if (pfe->line[0] == '+' || pfe->line[0] == '-') + continue; + + /* + * Start with the entries that are completely corrupt. + * They have no (struct passwd) entry because they couldn't + * be parsed properly. + */ + + if (!pfe->entry) { + + /* + * Tell the user this entire line is bogus and + * ask them to delete it. + */ + + printf(_("invalid password file entry\n")); + printf(_("delete line `%s'? "), pfe->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (!yes_or_no()) + continue; + + /* + * All password file deletions wind up here. This + * code removes the current entry from the linked + * list. When done, it skips back to the top of + * the loop to try out the next list element. + */ + +delete_pw: + SYSLOG((LOG_INFO, "delete passwd line `%s'\n", + pfe->line)); + deleted++; + + __pw_del_entry(pfe); + continue; + } + + /* + * Password structure is good, start using it. + */ + + pwd = pfe->entry; + + /* + * Make sure this entry has a unique name. + */ + + for (tpfe = __pw_get_head(); tpfe; tpfe = tpfe->next) { + const struct passwd *ent = tpfe->entry; + + /* + * Don't check this entry + */ + + if (tpfe == pfe) + continue; + + /* + * Don't check invalid entries. + */ + + if (!ent) + continue; + + if (strcmp(pwd->pw_name, ent->pw_name) != 0) + continue; + + /* + * Tell the user this entry is a duplicate of + * another and ask them to delete it. + */ + + puts(_("duplicate password entry\n")); + printf(_("delete line `%s'? "), pfe->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (yes_or_no()) + goto delete_pw; + } + + /* + * Check for invalid usernames. --marekm + */ + if (!check_user_name(pwd->pw_name)) { + printf(_("invalid user name `%s'\n"), pwd->pw_name); + errors++; + } + + /* + * Check for a Slackware bug. Make sure UID is not -1 + * (it has special meaning for some syscalls). --marekm + */ + + if (pwd->pw_uid == (uid_t) -1) { + printf(_("user %s: bad UID (%d)\n"), + pwd->pw_name, (int) pwd->pw_uid); + errors++; + } + + /* + * Make sure the primary group exists + */ + + if (!quiet && !getgrgid(pwd->pw_gid)) { + + /* + * No primary group, just give a warning + */ + + printf(_("user %s: no group %d\n"), + pwd->pw_name, (int) pwd->pw_gid); + errors++; + } + + /* + * Make sure the home directory exists + */ + + if (!quiet && access(pwd->pw_dir, F_OK)) { + + /* + * Home directory doesn't exist, give a warning + */ + + printf(_("user %s: directory %s does not exist\n"), + pwd->pw_name, pwd->pw_dir); + errors++; + } + + /* + * Make sure the login shell is executable + */ + + if (!quiet && pwd->pw_shell[0] && access(pwd->pw_shell, F_OK)) { + + /* + * Login shell doesn't exist, give a warning + */ + + printf(_("user %s: program %s does not exist\n"), + pwd->pw_name, pwd->pw_shell); + errors++; + } + } + +#ifdef SHADOWPWD + if (!is_shadow) + goto shadow_done; + + /* + * Loop through the entire shadow password file. + */ + + for (spe = __spw_get_head(); spe; spe = spe->next) { + /* + * If this is a NIS line, skip it. You can't "know" what + * NIS is going to do without directly asking NIS ... + */ + + if (spe->line[0] == '+' || spe->line[0] == '-') + continue; + + /* + * Start with the entries that are completely corrupt. + * They have no (struct spwd) entry because they couldn't + * be parsed properly. + */ + + if (!spe->entry) { + + /* + * Tell the user this entire line is bogus and + * ask them to delete it. + */ + + printf(_("invalid shadow password file entry\n")); + printf(_("delete line `%s'? "), spe->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (!yes_or_no()) + continue; + + /* + * All shadow file deletions wind up here. This + * code removes the current entry from the linked + * list. When done, it skips back to the top of + * the loop to try out the next list element. + */ + +delete_spw: + SYSLOG((LOG_INFO, "delete shadow line `%s'\n", + spe->line)); + deleted++; + + __spw_del_entry(spe); + continue; + } + + /* + * Shadow password structure is good, start using it. + */ + + spw = spe->entry; + + /* + * Make sure this entry has a unique name. + */ + + for (tspe = __spw_get_head(); tspe; tspe = tspe->next) { + const struct spwd *ent = tspe->entry; + + /* + * Don't check this entry + */ + + if (tspe == spe) + continue; + + /* + * Don't check invalid entries. + */ + + if (!ent) + continue; + + if (strcmp(spw->sp_namp, ent->sp_namp) != 0) + continue; + + /* + * Tell the user this entry is a duplicate of + * another and ask them to delete it. + */ + + puts(_("duplicate shadow password entry\n")); + printf(_("delete line `%s'? "), spe->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (yes_or_no()) + goto delete_spw; + } + + /* + * Make sure this entry exists in the /etc/passwd + * file. + */ + + if (!pw_locate(spw->sp_namp)) { + + /* + * Tell the user this entry has no matching + * /etc/passwd entry and ask them to delete it. + */ + + puts(_("no matching password file entry\n")); + printf(_("delete line `%s'? "), spe->line); + errors++; + + /* + * prompt the user to delete the entry or not + */ + + if (yes_or_no()) + goto delete_spw; + } + + /* + * Warn if last password change in the future. --marekm + */ + + if (!quiet && spw->sp_lstchg > time((time_t *)0) / SCALE) { + printf(_("user %s: last password change in the future\n"), spw->sp_namp); + errors++; + } + } + +shadow_done: +#endif + + /* + * All done. If there were no deletions we can just abandon any + * changes to the files. + */ + + if (deleted) { + if (!pw_close()) { + fprintf(stderr, _("%s: cannot update file %s\n"), + Prog, pwd_file); + SYSLOG((LOG_WARN, "cannot update %s\n", pwd_file)); + closelog(); + exit(E_CANTUPDATE); + } +#ifdef SHADOWPWD + if (is_shadow && !spw_close()) { + fprintf(stderr, _("%s: cannot update file %s\n"), + Prog, spw_file); + SYSLOG((LOG_WARN, "cannot update %s\n", spw_file)); + closelog(); + exit(E_CANTUPDATE); + } +#endif + } + + /* + * Don't be anti-social - unlock the files when you're done. + */ + +#ifdef SHADOWPWD + if (is_shadow) + spw_unlock(); +#endif + (void) pw_unlock(); + + /* + * Tell the user what we did and exit. + */ + + if (errors) +#ifdef NDBM + printf(deleted ? + _("%s: the files have been updated; run mkpasswd\n") : + _("%s: no changes\n"), Prog); +#else + printf(deleted ? + _("%s: the files have been updated\n") : + _("%s: no changes\n"), Prog); +#endif + + closelog(); + exit(errors ? E_BADENTRY : E_OKAY); +} diff --git a/src/pwconv.c b/src/pwconv.c new file mode 100644 index 00000000..fcaad97d --- /dev/null +++ b/src/pwconv.c @@ -0,0 +1,188 @@ +/* + * pwconv - create or update /etc/shadow with information from + * /etc/passwd. + * + * It is more like SysV pwconv, slightly different from the + * original Shadow pwconv. Depends on "x" as password in + * /etc/passwd which means that the password has already been + * moved to /etc/shadow. There is no need to move /etc/npasswd + * to /etc/passwd, password files are updated using library + * routines with proper locking. + * + * Can be used to update /etc/shadow after adding/deleting users + * by editing /etc/passwd. There is no man page yet, but this + * program should be close to pwconv(1M) on Solaris 2.x. + * + * Warning: make sure that all users have "x" as the password in + * /etc/passwd before running this program for the first time on + * a system which already has shadow passwords. Anything else + * (like "*" from old versions of the shadow suite) will replace + * the user's encrypted password in /etc/shadow. + * + * Doesn't currently support pw_age information in /etc/passwd, + * and doesn't support DBM files. Add it if you need it... + * + * Copyright (C) 1996-1997, Marek Michalkiewicz + * + * This program may be freely used and distributed for any purposes. + * If you improve it, please send me your changes. Thanks! + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: pwconv.c,v 1.10 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "prototypes.h" +#include "defines.h" +#include "pwio.h" +#include "shadowio.h" +#include "getdef.h" + +/* + * exit status values + */ + +#define E_SUCCESS 0 /* success */ +#define E_NOPERM 1 /* permission denied */ +#define E_USAGE 2 /* bad command syntax */ +#define E_FAILURE 3 /* unexpected failure, nothing done */ +#define E_MISSING 4 /* unexpected failure, passwd file missing */ +#define E_PWDBUSY 5 /* passwd file(s) busy */ +#define E_BADENTRY 6 /* bad shadow entry */ + +static int + shadow_locked = 0, + passwd_locked = 0; + +/* local function prototypes */ +static void fail_exit P_((int)); +int main P_((int, char **)); + +static void +fail_exit(int status) +{ + if (shadow_locked) + spw_unlock(); + if (passwd_locked) + pw_unlock(); + exit(status); +} + +int +main(int argc, char **argv) +{ + const struct passwd *pw; + struct passwd pwent; + const struct spwd *sp; + struct spwd spent; + char *Prog = argv[0]; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + if (!pw_lock()) { + fprintf(stderr, _("%s: can't lock passwd file\n"), Prog); + fail_exit(E_PWDBUSY); + } + passwd_locked++; + if (!pw_open(O_RDWR)) { + fprintf(stderr, _("%s: can't open passwd file\n"), Prog); + fail_exit(E_MISSING); + } + + if (!spw_lock()) { + fprintf(stderr, _("%s: can't lock shadow file\n"), Prog); + fail_exit(E_PWDBUSY); + } + shadow_locked++; + if (!spw_open(O_CREAT | O_RDWR)) { + fprintf(stderr, _("%s: can't open shadow file\n"), Prog); + fail_exit(E_FAILURE); + } + + /* + * Remove /etc/shadow entries for users not in /etc/passwd. + */ + spw_rewind(); + while ((sp = spw_next())) { + if (pw_locate(sp->sp_namp)) + continue; + + if (!spw_remove(sp->sp_namp)) { + /* + * This shouldn't happen (the entry exists) but... + */ + fprintf(stderr, + _("%s: can't remove shadow entry for %s\n"), + Prog, sp->sp_namp); + fail_exit(E_FAILURE); + } + } + + /* + * Update shadow entries which don't have "x" as pw_passwd. + * Add any missing shadow entries. + */ + pw_rewind(); + while ((pw = pw_next())) { + sp = spw_locate(pw->pw_name); + if (sp) { + /* do we need to update this entry? */ + if (strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) + continue; + /* update existing shadow entry */ + spent = *sp; + } else { + /* add new shadow entry */ + memset(&spent, 0, sizeof spent); + spent.sp_namp = pw->pw_name; + spent.sp_min = getdef_num("PASS_MIN_DAYS", -1); + spent.sp_max = getdef_num("PASS_MAX_DAYS", -1); + spent.sp_warn = getdef_num("PASS_WARN_AGE", -1); + spent.sp_inact = -1; + spent.sp_expire = -1; + spent.sp_flag = -1; + } + spent.sp_pwdp = pw->pw_passwd; + spent.sp_lstchg = time((time_t *) 0) / (24L*3600L); + if (!spw_update(&spent)) { + fprintf(stderr, + _("%s: can't update shadow entry for %s\n"), + Prog, spent.sp_namp); + fail_exit(E_FAILURE); + } + /* remove password from /etc/passwd */ + pwent = *pw; + pwent.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ + if (!pw_update(&pwent)) { + fprintf(stderr, + _("%s: can't update passwd entry for %s\n"), + Prog, pwent.pw_name); + fail_exit(E_FAILURE); + } + } + + if (!spw_close()) { + fprintf(stderr, _("%s: can't update shadow file\n"), Prog); + fail_exit(E_FAILURE); + } + if (!pw_close()) { + fprintf(stderr, _("%s: can't update passwd file\n"), Prog); + fail_exit(E_FAILURE); + } + chmod(PASSWD_FILE "-", 0600); /* /etc/passwd- (backup file) */ + spw_unlock(); + pw_unlock(); + exit(E_SUCCESS); +} diff --git a/src/pwunconv.c b/src/pwunconv.c new file mode 100644 index 00000000..6e6a172b --- /dev/null +++ b/src/pwunconv.c @@ -0,0 +1,197 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * pwunconv - restore old password file from shadow password file. + * + * Pwunconv copies the password file information from the shadow + * password file, merging entries from an optional existing shadow + * file. + * + * Modifed by Guy Maor to acquire necessary locks + * and modify the files in place. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: pwunconv.c,v 1.8 1999/06/07 16:40:45 marekm Exp $") + +#include "defines.h" +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "pwio.h" +#include "shadowio.h" + +#ifndef SHADOWPWD +int +main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + fprintf(stderr, _("%s: Shadow passwords are not configured.\n"), + argv[0]); + exit(1); +} + +#else /*{*/ + +char *l64a (); + +static int shadow_locked = 0, + passwd_locked = 0; + +/* local function prototypes */ +static void fail_exit P_((int)); +int main P_((int, char **)); + +static void +fail_exit(int status) +{ + if (shadow_locked) + spw_unlock(); + if (passwd_locked) + pw_unlock(); + exit(status); +} + + +int +main(int argc, char **argv) +{ + const struct passwd *pw; + struct passwd pwent; + const struct spwd *spwd; +#ifdef ATT_AGE + char newage[5]; +#endif + char *Prog = argv[0]; + + setlocale (LC_ALL, ""); + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + + if (!spw_file_present()) + /* shadow not installed, do nothing */ + exit(0); + + if (!pw_lock()) { + fprintf(stderr, _("%s: can't lock passwd file\n"), Prog); + fail_exit(5); + } + passwd_locked++; + if (!pw_open(O_RDWR)) { + fprintf(stderr, _("%s: can't open passwd file\n"), Prog); + fail_exit(1); + } + + if (!spw_lock()) { + fprintf(stderr, _("%s: can't open shadow file\n"), Prog); + fail_exit(5); + } + shadow_locked++; + if (!spw_open(O_RDWR)) { + fprintf(stderr, _("%s: can't open shadow file\n"), Prog); + fail_exit(1); + } + + pw_rewind(); + while ((pw = pw_next())) { + if (!(spwd = spw_locate(pw->pw_name))) + continue; + + pwent = *pw; + + /* + * Update password if non-shadow is "x". + */ + if (strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) + pwent.pw_passwd = spwd->sp_pwdp; + + /* + * Password aging works differently in the two different systems. + * With shadow password files you apparently must have some aging + * information. The maxweeks or minweeks may not map exactly. + * In pwconv we set max == 10000, which is about 30 years. Here + * we have to undo that kludge. So, if maxdays == 10000, no aging + * information is put into the new file. Otherwise, the days are + * converted to weeks and so on. + */ + +#ifdef ATT_AGE + if (spwd->sp_max > (63*WEEK/SCALE) && spwd->sp_max < 10000) + spwd->sp_max = (63*WEEK/SCALE); /* 10000 is infinity */ + + if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 && + spwd->sp_max >= 0 && spwd->sp_max <= 63*7) { + if (spwd->sp_lstchg == -1) + spwd->sp_lstchg = 0; + + spwd->sp_max /= WEEK/SCALE; /* turn it into weeks */ + spwd->sp_min /= WEEK/SCALE; + spwd->sp_lstchg /= WEEK/SCALE; + + strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) + + spwd->sp_min * (64L) + spwd->sp_max), 5); + pwent.pw_age = newage; + } else + pwent.pw_age = ""; +#endif /* ATT_AGE */ + if (!pw_update(&pwent)) { + fprintf(stderr, + _("%s: can't update entry for user %s\n"), + Prog, pwent.pw_name); + fail_exit(3); + } + } + + if (!spw_close()) { + fprintf(stderr, _("%s: can't update shadow password file\n"), Prog); + fail_exit(3); + } + + if (!pw_close()) { + fprintf(stderr, _("%s: can't update password file\n"), Prog); + fail_exit(3); + } + + if (unlink(SHADOW) != 0) { + fprintf(stderr, _("%s: can't delete shadow password file\n"), Prog); + fail_exit(3); + } + + spw_unlock(); + pw_unlock(); + return 0; +} +#endif diff --git a/src/shadowconfig.sh b/src/shadowconfig.sh new file mode 100755 index 00000000..17b8aa9e --- /dev/null +++ b/src/shadowconfig.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# turn shadow passwords on or off on a Debian system + +set -e + +permfix () { + [ -f $1 ] || return 0 + chown root:shadow $1 + chmod 2755 $1 +} +export -f permfix + +shadowon () { +bash<<- EOF + set -e + + permfix /usr/X11R6/bin/xlock + permfix /usr/X11R6/bin/xtrlock + permfix /bin/vlock + + pwck -q + grpck + pwconv + grpconv + cd /etc + chown root:root passwd group + chmod 644 passwd group + chown root:shadow shadow gshadow + chmod 640 shadow gshadow +EOF +} + +shadowoff () { +bash<<- EOF + set -e + pwck -q + grpck + pwunconv + grpunconv + cd /etc + # sometimes the passwd perms get munged + chown root:root passwd group + chmod 644 passwd group +EOF +} + +case "$1" in + "on") + if shadowon ; then + echo Shadow passwords are now on. + else + echo Please correct the error and rerun \`$0 on\' + exit 1 + fi + ;; + "off") + if shadowoff ; then + echo Shadow passwords are now off. + else + echo Please correct the error and rerun \`$0 off\' + exit 1 + fi + ;; + *) + echo Usage: $0 on \| off + ;; +esac diff --git a/src/su.c b/src/su.c new file mode 100644 index 00000000..3f4f4309 --- /dev/null +++ b/src/su.c @@ -0,0 +1,633 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: su.c,v 1.13 1999/06/07 16:40:45 marekm Exp $") + +#include +#include + +#ifdef USE_PAM +#include "pam_defs.h" + +static const struct pam_conv conv = { + misc_conv, + NULL +}; + +static pam_handle_t *pamh = NULL; +#endif + +#include "prototypes.h" +#include "defines.h" + +#include +#include +#include +#include "pwauth.h" +#include "getdef.h" + +/* + * Assorted #defines to control su's behavior + */ + +/* + * Global variables + */ + +/* needed by sulog.c */ +char name[BUFSIZ]; +char oldname[BUFSIZ]; + +static char *Prog; + +struct passwd pwent; + +/* + * External identifiers + */ + +extern char **newenvp; +extern size_t newenvc; + +extern void sulog P_((const char *, int)); +extern void subsystem P_((const struct passwd *)); +extern char *tz P_((const char *)); +extern int check_su_auth P_((const char *, const char *)); +extern char **environ; + +/* local function prototypes */ +int main P_((int, char **)); + +#ifndef USE_PAM + +static RETSIGTYPE die P_((int)); +static int iswheel P_((const char *)); + +/* + * die - set or reset termio modes. + * + * die() is called before processing begins. signal() is then + * called with die() as the signal handler. If signal later + * calls die() with a signal number, the terminal modes are + * then reset. + */ + +static RETSIGTYPE +die(int killed) +{ + static TERMIO sgtty; + + if (killed) + STTY(0, &sgtty); + else + GTTY(0, &sgtty); + + if (killed) { + closelog(); + exit(killed); + } +} + +static int +iswheel(const char *username) +{ + struct group *grp; + + grp = getgrgid(0); + if (!grp || !grp->gr_mem) + return 0; + return is_on_list(grp->gr_mem, username); +} +#endif /* !USE_PAM */ + + +static void +su_failure(const char *tty) +{ + sulog(tty, 0); /* log failed attempt */ +#ifdef USE_SYSLOG + if (getdef_bool("SYSLOG_SU_ENAB")) + SYSLOG((pwent.pw_uid ? LOG_INFO:LOG_NOTICE, + "- %s %s-%s\n", tty, + oldname[0] ? oldname:"???", + name[0] ? name:"???")); + closelog(); +#endif + puts(_("Sorry.")); + exit(1); +} + + +/* + * su - switch user id + * + * su changes the user's ids to the values for the specified user. + * if no new user name is specified, "root" is used by default. + * + * The only valid option is a "-" character, which is interpreted + * as requiring a new login session to be simulated. + * + * Any additional arguments are passed to the user's shell. In + * particular, the argument "-c" will cause the next argument to + * be interpreted as a command by the common shell programs. + */ + +int +main(int argc, char **argv) +{ + char *cp; + const char *tty = 0; /* Name of tty SU is run from */ + int doshell = 0; + int fakelogin = 0; + int amroot = 0; + uid_t my_uid; + struct passwd *pw = 0; + char **envp = environ; +#ifdef USE_PAM + int ret; +#else /* !USE_PAM */ + RETSIGTYPE (*oldsig)(); + int is_console = 0; +#ifdef SHADOWPWD + struct spwd *spwd = 0; +#endif +#ifdef SU_ACCESS + char *oldpass; +#endif +#endif /* !USE_PAM */ + + sanitize_env(); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * Get the program name. The program name is used as a + * prefix to most error messages. + */ + + Prog = Basename(argv[0]); + + openlog("su", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + + initenv(); + + my_uid = getuid(); + amroot = (my_uid == 0); + + /* + * Get the tty name. Entries will be logged indicating that + * the user tried to change to the named new user from the + * current terminal. + */ + + if (isatty(0) && (cp = ttyname(0))) { + if (strncmp (cp, "/dev/", 5) == 0) + tty = cp + 5; + else + tty = cp; +#ifndef USE_PAM + is_console = console(tty); +#endif + } else { + /* + * Be more paranoid, like su from SimplePAMApps. --marekm + */ + if (!amroot) { + fprintf(stderr, _("%s: must be run from a terminal\n"), + Prog); + exit(1); + } + tty = "???"; + } + + /* + * Process the command line arguments. + */ + + argc--; argv++; /* shift out command name */ + + if (argc > 0 && strcmp(argv[0], "-") == 0) { + fakelogin = 1; + argc--; argv++; /* shift ... */ + } + + /* + * If a new login is being set up, the old environment will + * be ignored and a new one created later on. + */ + + if (! fakelogin) + while (*envp) + addenv(*envp++, NULL); + + if (fakelogin && (cp=getdef_str("ENV_TZ"))) + addenv(*cp == '/' ? tz(cp) : cp, NULL); + + /* + * The clock frequency will be reset to the login value if required + */ + + if (fakelogin && (cp=getdef_str("ENV_HZ")) ) + addenv(cp, NULL); /* set the default $HZ, if one */ + + /* + * The terminal type will be left alone if it is present in the + * environment already. + */ + + if (fakelogin && (cp = getenv ("TERM"))) + addenv("TERM", cp); + + /* + * The next argument must be either a user ID, or some flag to + * a subshell. Pretty sticky since you can't have an argument + * which doesn't start with a "-" unless you specify the new user + * name. Any remaining arguments will be passed to the user's + * login shell. + */ + + if (argc > 0 && argv[0][0] != '-') { + STRFCPY(name, argv[0]); /* use this login id */ + argc--; argv++; /* shift ... */ + } + if (! name[0]) /* use default user ID */ + (void) strcpy (name, "root"); + + doshell = argc == 0; /* any arguments remaining? */ + + /* + * Get the user's real name. The current UID is used to determine + * who has executed su. That user ID must exist. + */ + + pw = get_my_pwent(); + if (!pw) { + SYSLOG((LOG_CRIT, "Unknown UID: %d\n", (int) my_uid)); + su_failure(tty); + } + STRFCPY(oldname, pw->pw_name); + +#ifndef USE_PAM +#ifdef SU_ACCESS + /* + * Sort out the password of user calling su, in case needed later + * -- chris + */ +#ifdef SHADOWPWD + if ((spwd = getspnam(oldname))) + pw->pw_passwd = spwd->sp_pwdp; +#endif + oldpass = xstrdup(pw->pw_passwd); +#endif /* SU_ACCESS */ +#endif /* !USE_PAM */ + +#ifdef USE_PAM + ret = pam_start("su", name, &conv, &pamh); + if (ret != PAM_SUCCESS) { + SYSLOG((LOG_ERR, "pam_start: error %d\n", ret); + fprintf(stderr, _("%s: pam_start: error %d\n"), Prog, ret)); + exit(1); + } + + ret = pam_set_item(pamh, PAM_TTY, (const void *) tty); + if (ret == PAM_SUCCESS) + ret = pam_set_item(pamh, PAM_RUSER, (const void *) oldname); + if (ret != PAM_SUCCESS) { + SYSLOG((LOG_ERR, "pam_set_item: %s\n", PAM_STRERROR(pamh, ret))); + fprintf(stderr, "%s: %s\n", Prog, PAM_STRERROR(pamh, ret)); + pam_end(pamh, ret); + exit(1); + } +#endif /* USE_PAM */ + +top: + /* + * This is the common point for validating a user whose name + * is known. It will be reached either by normal processing, + * or if the user is to be logged into a subsystem root. + * + * The password file entries for the user is gotten and the + * account validated. + */ + + if (!(pw = getpwnam(name))) { + (void) fprintf (stderr, _("Unknown id: %s\n"), name); + closelog(); + exit(1); + } + +#ifndef USE_PAM +#ifdef SHADOWPWD + spwd = NULL; + if (strcmp(pw->pw_passwd, SHADOW_PASSWD_STRING) == 0 && (spwd = getspnam(name))) + pw->pw_passwd = spwd->sp_pwdp; +#endif +#endif /* !USE_PAM */ + pwent = *pw; + +#ifndef USE_PAM + /* + * BSD systems only allow "wheel" to SU to root. USG systems + * don't, so we make this a configurable option. + */ + + /* The original Shadow 3.3.2 did this differently. Do it like BSD: + + - check for uid 0 instead of name "root" - there are systems + with several root accounts under different names, + + - check the contents of /etc/group instead of the current group + set (you must be listed as a member, GID 0 is not sufficient). + + In addition to this traditional feature, we now have complete + su access control (allow, deny, no password, own password). + Thanks to Chris Evans . */ + + if (!amroot) { + if (pwent.pw_uid == 0 && getdef_bool("SU_WHEEL_ONLY") + && !iswheel(oldname)) { + fprintf(stderr, _("You are not authorized to su %s\n"), name); + exit(1); + } +#ifdef SU_ACCESS + switch (check_su_auth(oldname, name)) { + case 0: /* normal su, require target user's password */ + break; + case 1: /* require no password */ + pwent.pw_passwd = ""; /* XXX warning: const */ + break; + case 2: /* require own password */ + puts(_("(Enter your own password.)")); + pwent.pw_passwd = oldpass; + break; + default: /* access denied (-1) or unexpected value */ + fprintf(stderr, _("You are not authorized to su %s\n"), name); + exit(1); + } +#endif /* SU_ACCESS */ + } +#endif /* !USE_PAM */ + + /* + * Set the default shell. + */ +#if 0 + /* + * XXX - GNU and *BSD versions of su support the -m option. + * Need to add some option parsing code. + */ + if (mflg) { + if (!amroot && !check_shell(pwent.pw_shell)) { + fprintf(stderr, _("%s: permission denied (shell).\n"), Prog); + exit(1); + } + if ((cp = getenv("SHELL"))) + pwent.pw_shell = cp; + } +#endif + + if (pwent.pw_shell[0] == '\0') + pwent.pw_shell = "/bin/sh"; /* XXX warning: const */ + +#ifdef USE_PAM + ret = pam_authenticate(pamh, 0); + if (ret != PAM_SUCCESS) { + SYSLOG((LOG_ERR, "pam_authenticate: %s\n", + PAM_STRERROR(pamh, ret))); + fprintf(stderr, "%s: %s\n", Prog, PAM_STRERROR(pamh, ret)); + pam_end(pamh, ret); + su_failure(tty); + } + + ret = pam_acct_mgmt(pamh, 0); + if (ret != PAM_SUCCESS) { + if (amroot) { + fprintf(stderr, _("%s: %s\n(Ignored)\n"), Prog, PAM_STRERROR(pamh, ret)); + } else { + SYSLOG((LOG_ERR, "pam_acct_mgmt: %s\n", + PAM_STRERROR(pamh, ret))); + fprintf(stderr, "%s: %s\n", Prog, PAM_STRERROR(pamh, ret)); + pam_end(pamh, ret); + su_failure(tty); + } + } +#else /* !USE_PAM */ + /* + * Set up a signal handler in case the user types QUIT. + */ + + die (0); + oldsig = signal (SIGQUIT, die); + + /* + * See if the system defined authentication method is being used. + * The first character of an administrator defined method is an + * '@' character. + */ + + if (! amroot && pw_auth (pwent.pw_passwd, name, PW_SU, (char *) 0)) { + SYSLOG((pwent.pw_uid ? LOG_NOTICE:LOG_WARN, + "Authentication failed for %s\n", name)); + su_failure(tty); + } + signal (SIGQUIT, oldsig); + + /* + * Check to see if the account is expired. root gets to + * ignore any expired accounts, but normal users can't become + * a user with an expired password. + */ + + if (! amroot) { +#ifdef SHADOWPWD + if (!spwd) + spwd = pwd_to_spwd(&pwent); + + if (isexpired(&pwent, spwd)) { + SYSLOG((pwent.pw_uid ? LOG_WARN : LOG_CRIT, + "Expired account %s\n", name)); + su_failure(tty); + } +#else +#if defined(ATT_AGE) && defined(AGING) + else if (pwent.pw_age[0] && + isexpired (&pwent)) { + SYSLOG((pwent.pw_uid ? LOG_WARN:LOG_CRIT, + "Expired account %s\n", name)); + su_failure(tty); + } +#endif /* ATT_AGE */ +#endif + } + + /* + * Check to see if the account permits "su". root gets to + * ignore any restricted accounts, but normal users can't become + * a user if there is a "SU" entry in the /etc/porttime file + * denying access to the account. + */ + + if (! amroot) { + if (! isttytime (pwent.pw_name, "SU", time ((time_t *) 0))) { + SYSLOG((pwent.pw_uid ? LOG_WARN : LOG_CRIT, + "SU by %s to restricted account %s\n", + oldname, name)); + su_failure(tty); + } + } +#endif /* !USE_PAM */ + + cp = getdef_str(pwent.pw_uid == 0 ? "ENV_SUPATH" : "ENV_PATH"); + addenv(cp ? cp : "PATH=/bin:/usr/bin", NULL); + + environ = newenvp; /* make new environment active */ + + if (getenv ("IFS")) /* don't export user IFS ... */ + addenv("IFS= \t\n", NULL); /* ... instead, set a safe IFS */ + + if (pwent.pw_shell[0] == '*') { /* subsystem root required */ + subsystem (&pwent); /* figure out what to execute */ + endpwent (); +#ifdef SHADOWPWD + endspent (); +#endif + goto top; + } + + sulog (tty, 1); /* save SU information */ + endpwent (); +#ifdef SHADOWPWD + endspent (); +#endif +#ifdef USE_SYSLOG + if (getdef_bool("SYSLOG_SU_ENAB")) + SYSLOG((LOG_INFO, "+ %s %s-%s\n", tty, + oldname[0] ? oldname:"???", name[0] ? name:"???")); +#endif + +#ifdef USE_PAM + /* set primary group id and supplementary groups */ + if (setup_groups(&pwent)) { + pam_end(pamh, PAM_ABORT); + exit(1); + } + + /* pam_setcred() may do things like resource limits, console groups, + and much more, depending on the configured modules */ + ret = pam_setcred(pamh, PAM_ESTABLISH_CRED); + if (ret != PAM_SUCCESS) { + SYSLOG((LOG_ERR, "pam_setcred: %s\n", PAM_STRERROR(pamh, ret))); + fprintf(stderr, "%s: %s\n", Prog, PAM_STRERROR(pamh, ret)); + pam_end(pamh, ret); + exit(1); + } + + /* become the new user */ + if (change_uid(&pwent)) { + pam_setcred(pamh, PAM_DELETE_CRED); + pam_end(pamh, PAM_ABORT); + exit(1); + } + + /* now we are done using PAM */ + pam_end(pamh, PAM_SUCCESS); + +#else /* !USE_PAM */ + if (!amroot) /* no limits if su from root */ + setup_limits(&pwent); + + if (setup_uid_gid(&pwent, is_console)) + exit(1); +#endif /* !USE_PAM */ + + if (fakelogin) + setup_env(&pwent); +#if 1 /* Suggested by Joey Hess. XXX - is this right? */ + else + addenv("HOME", pwent.pw_dir); +#endif + + /* + * This is a workaround for Linux libc bug/feature (?) - the + * /dev/log file descriptor is open without the close-on-exec + * flag and used to be passed to the new shell. There is + * "fcntl(LogFile, F_SETFD, 1)" in libc/misc/syslog.c, but + * it is commented out (at least in 5.4.33). Why? --marekm + */ + closelog(); + + /* + * See if the user has extra arguments on the command line. In + * that case they will be provided to the new user's shell as + * arguments. + */ + + if (! doshell) { + + /* + * Use new user's shell from /etc/passwd and create an + * argv with the rest of the command line included. + */ + + argv[-1] = pwent.pw_shell; + (void) execv (pwent.pw_shell, &argv[-1]); + (void) fprintf (stderr, _("No shell\n")); + SYSLOG((LOG_WARN, "Cannot execute %s\n", pwent.pw_shell)); + closelog(); + exit (1); + } + if (fakelogin) { + char *arg0; + +#if 0 /* XXX - GNU su doesn't do this. --marekm */ + if (! hushed (&pwent)) { + motd (); + mailcheck (); + } +#endif + cp = getdef_str("SU_NAME"); + if (!cp) + cp = Basename(pwent.pw_shell); + + arg0 = xmalloc(strlen(cp) + 2); + arg0[0] = '-'; + strcpy(arg0 + 1, cp); + cp = arg0; + } else + cp = Basename(pwent.pw_shell); + + shell(pwent.pw_shell, cp); + /*NOTREACHED*/ + exit(1); +} diff --git a/src/sulogin.c b/src/sulogin.c new file mode 100644 index 00000000..a977cc25 --- /dev/null +++ b/src/sulogin.c @@ -0,0 +1,281 @@ +/* + * Copyright 1989 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: sulogin.c,v 1.9 1999/06/07 16:40:45 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include "getdef.h" + +#if HAVE_UTMPX_H +#include +#else +#include +#endif + +#include +#include +#include +#include +#include "pwauth.h" + +static char name[BUFSIZ]; +static char pass[BUFSIZ]; + +static struct passwd pwent; +#if 0 +#if HAVE_UTMPX_H +static struct utmpx utent; +#else +static struct utmp utent; +#endif +#endif + + +extern char **newenvp; +extern size_t newenvc; + +extern char **environ; +extern char *tz P_((const char *)); + +#ifndef ALARM +#define ALARM 60 +#endif + +/* local function prototypes */ +static RETSIGTYPE catch P_((int)); +int main P_((int, char **)); + +static RETSIGTYPE +catch(int sig) +{ + exit(1); +} + +/* syslogd is usually not running at the time when sulogin is typically + called, cluttering the screen with unnecessary messages. Suggested + by Ivan Nejgebauer . --marekm */ +#undef USE_SYSLOG + +/*ARGSUSED*/ +int +main(int argc, char **argv) +{ + char *cp; + char **envp = environ; + TERMIO termio; + +#ifdef USE_SGTTY + ioctl (0, TIOCGETP, &termio); + termio.sg_flags |= (ECHO|CRMOD); + termio.sg_flags &= ~(RAW|CBREAK); + ioctl (0, TIOCSETN, &termio); +#endif +#ifdef USE_TERMIO + ioctl (0, TCGETA, &termio); + termio.c_iflag |= (ICRNL|IXON); + termio.c_oflag |= (OPOST|ONLCR); + termio.c_cflag |= (CREAD); + termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK); + ioctl (0, TCSETAF, &termio); +#endif +#ifdef USE_TERMIOS + tcgetattr (0, &termio); + termio.c_iflag |= (ICRNL|IXON); + termio.c_oflag |= (CREAD); + termio.c_lflag |= (ECHO|ECHOE|ECHOK|ICANON|ISIG); + tcsetattr (0, TCSANOW, &termio); +#endif + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + +#ifdef USE_SYSLOG + openlog ("sulogin", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); +#endif + initenv(); + if (argc > 1) { + close (0); + close (1); + close (2); + + if (open (argv[1], O_RDWR) >= 0) { + dup (0); + dup (0); + } else { +#ifdef USE_SYSLOG + syslog (LOG_WARN, "cannot open %s\n", argv[1]); + closelog (); +#endif + exit (1); + } + } + if (access(PASSWD_FILE, F_OK) == -1) { /* must be a password file! */ + printf(_("No password file\n")); +#ifdef USE_SYSLOG + syslog(LOG_WARN, "No password file\n"); + closelog (); +#endif + exit (1); + } +#if !defined(DEBUG) && defined(SULOGIN_ONLY_INIT) + if (getppid () != 1) { /* parent must be INIT */ +#ifdef USE_SYSLOG + syslog (LOG_WARN, "Pid == %d, not 1\n", getppid ()); + closelog (); +#endif + exit (1); + } +#endif + if (! isatty (0) || ! isatty (1) || ! isatty (2)) { +#ifdef USE_SYSLOG + closelog (); +#endif + exit (1); /* must be a terminal */ + } + while (*envp) /* add inherited environment, */ + addenv(*envp++, NULL); /* some variables change later */ + + if ((cp = getdef_str("ENV_TZ"))) + addenv(*cp == '/' ? tz(cp) : cp, NULL); + if ((cp = getdef_str("ENV_HZ"))) + addenv(cp, NULL); /* set the default $HZ, if one */ + (void) strcpy (name, "root"); /* KLUDGE!!! */ + + signal (SIGALRM, catch); /* exit if the timer expires */ + alarm (ALARM); /* only wait so long ... */ + + while (1) { /* repeatedly get login/password pairs */ + entry (name, &pwent); /* get entry from password file */ + if (pwent.pw_name == (char *) 0) { + + /* + * Fail secure + */ + + printf(_("No password entry for 'root'\n")); +#ifdef USE_SYSLOG + syslog (LOG_WARN, "No password entry for 'root'\n"); + closelog (); +#endif + exit (1); + } + + /* + * Here we prompt for the root password, or if no password is + * given we just exit. + */ + + /* get a password for root */ + cp = getpass(_("\nType control-d to proceed with normal startup,\n(or give root password for system maintenance):")); + /* + * XXX - can't enter single user mode if root password is empty. + * I think this doesn't happen very often :-). But it will work + * with standard getpass() (no NULL on EOF). --marekm + */ + if (!cp || !*cp) { +#ifdef USE_SYSLOG + syslog (LOG_INFO, "Normal startup\n"); + closelog (); +#endif + puts("\n"); +#ifdef TELINIT + execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) 0); +#endif + exit (0); + } else { + STRFCPY(pass, cp); + strzero(cp); + } +#ifdef AUTH_METHODS + if (pwent.pw_name && pwent.pw_passwd[0] == '@') { + if (pw_auth (pwent.pw_passwd + 1, name, PW_LOGIN, (char *) 0)) { +#ifdef USE_SYSLOG + syslog (LOG_WARN, + "Incorrect root authentication"); +#endif + continue; + } + goto auth_done; + } +#endif + if (valid (pass, &pwent)) /* check encrypted passwords ... */ + break; /* ... encrypted passwords matched */ + +#ifdef USE_SYSLOG + syslog (LOG_WARN, "Incorrect root password\n"); +#endif + sleep(2); + puts (_("Login incorrect")); + } +#ifdef AUTH_METHODS +auth_done: +#endif + strzero(pass); + alarm (0); + signal (SIGALRM, SIG_DFL); + environ = newenvp; /* make new environment active */ + + puts(_("Entering System Maintenance Mode\n")); +#ifdef USE_SYSLOG + syslog (LOG_INFO, "System Maintenance Mode\n"); +#endif + +#if 0 /* do we need all this? we are logging in as root anyway... --marekm */ + /* + * Normally there would be a utmp entry for login to mung on + * to get the tty name, date, etc. from. We don't need all that + * stuff because we won't update the utmp or wtmp files. BUT!, + * we do need the tty name so we can set the permissions and + * ownership. + */ + + if ((cp = ttyname (0))) { /* found entry in /dev/ */ + if (strncmp(cp, "/dev/", 5) == 0) + cp += 5; + + strncpy(utent.ut_line, cp, sizeof utent.ut_line); + } + if (getenv ("IFS")) /* don't export user IFS ... */ + addenv("IFS= \t\n", NULL); /* ... instead, set a safe IFS */ + + setup (&pwent, 0); /* set UID, GID, HOME, etc ... */ +#endif + +#ifdef USE_SYSLOG + closelog (); +#endif + shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */ + /*NOTREACHED*/ + return (0); +} diff --git a/src/useradd.c b/src/useradd.c new file mode 100644 index 00000000..dc233949 --- /dev/null +++ b/src/useradd.c @@ -0,0 +1,1746 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: useradd.c,v 1.16 1999/06/07 16:40:45 marekm Exp $") + +#include "prototypes.h" +#include "defines.h" +#include "chkname.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pwauth.h" +#if HAVE_LASTLOG_H +#include +#else +#include "lastlog_.h" +#endif +#include "faillog.h" + +#ifndef SKEL_DIR +#define SKEL_DIR "/etc/skel" +#endif + +#ifndef USER_DEFAULTS_FILE +#define USER_DEFAULTS_FILE "/etc/default/useradd" +#define NEW_USER_FILE "/etc/default/nuaddXXXXXX" +#endif + +/* + * Needed for MkLinux DR1/2/2.1 - J. + */ +#ifndef LASTLOG_FILE +#define LASTLOG_FILE "/var/log/lastlog" +#endif + +/* + * These defaults are used if there is no defaults file. + */ +static gid_t def_group = 100; +static const char *def_gname = "other"; +static const char *def_home = "/home"; +static const char *def_shell = ""; +static const char *def_template = SKEL_DIR; +#ifdef SHADOWPWD +static long def_inactive = -1; +static const char *def_expire = ""; +#endif + +static char def_file[] = USER_DEFAULTS_FILE; + +#define VALID(s) (strcspn (s, ":\n") == strlen (s)) + +static const char *user_name = ""; +static const char *user_pass = "!"; +static uid_t user_id; +static gid_t user_gid; +static const char *user_comment = ""; +static const char *user_home = ""; +static const char *user_shell = ""; +#ifdef SHADOWPWD +static long user_expire = -1; +static int is_shadow_pwd; +#endif +#ifdef SHADOWGRP +static int is_shadow_grp; +#endif +static char *user_groups[NGROUPS_MAX+1]; /* NULL-terminated list */ +static int do_grp_update = 0; /* group files need to be updated */ + +static char *Prog; + +static int + uflg = 0, /* specify user ID for new account */ + oflg = 0, /* permit non-unique user ID to be specified with -u */ + gflg = 0, /* primary group ID for new account */ + Gflg = 0, /* secondary group set for new account */ + dflg = 0, /* home directory for new account */ + bflg = 0, /* new default root of home directory */ + sflg = 0, /* shell program for new account */ + cflg = 0, /* comment (GECOS) field for new account */ + mflg = 0, /* create user's home directory if it doesn't exist */ + kflg = 0, /* specify a directory to fill new user directory */ + fflg = 0, /* days until account with expired password is locked */ + eflg = 0, /* days since 1970-01-01 when account is locked */ + Dflg = 0; /* set/show new user default values */ + +#ifdef AUTH_METHODS +static int Aflg = 0; /* specify authentication method for user */ +static char user_auth[1024]; +static char *auth_arg; +#endif + +extern char *optarg; +extern int optind; + +#ifdef NDBM +extern int pw_dbm_mode; +#ifdef SHADOWPWD +extern int sp_dbm_mode; +#endif +extern int gr_dbm_mode; +#ifdef SHADOWGRP +extern int sg_dbm_mode; +#endif +#endif + +static int home_added; + +#ifdef NDBM +static int pw_dbm_added; +static int gr_dbm_added; +#ifdef SHADOWPWD +static int sp_dbm_added; +#endif +#ifdef SHADOWGRP +static int sg_dbm_added; +#endif +#endif /* NDBM */ + +#include "groupio.h" + +#ifdef SHADOWGRP +#include "sgroupio.h" +#endif + +#include "pwio.h" + +#ifdef SHADOWPWD +#include "shadowio.h" +#endif + +#include "getdef.h" + +/* + * exit status values + */ +#define E_SUCCESS 0 /* success */ +#define E_PW_UPDATE 1 /* can't update password file */ +#define E_USAGE 2 /* bad command syntax */ +#define E_BAD_ARG 3 /* invalid argument to option */ +#define E_UID_IN_USE 4 /* uid already in use (and no -o) */ +#define E_NOTFOUND 6 /* specified group doesn't exist */ +#define E_NAME_IN_USE 9 /* username already in use */ +#define E_GRP_UPDATE 10 /* can't update group file */ +#define E_HOMEDIR 12 /* can't create home directory */ + +#ifdef SVR4 +#define DGROUP "defgroup=" +#define HOME "defparent=" +#define SHELL "defshell=" +#define INACT "definact=" +#define EXPIRE "defexpire=" +#define SKEL "defskel=" +#else +#define DGROUP "GROUP=" +#define HOME "HOME=" +#define SHELL "SHELL=" +#define INACT "INACTIVE=" +#define EXPIRE "EXPIRE=" +#define SKEL "SKEL=" +#endif + +/* local function prototypes */ +static void fail_exit P_((int)); +static struct group *getgr_nam_gid P_((const char *)); +static long get_number P_((const char *)); +static void get_defaults P_((void)); +static void show_defaults P_((void)); +static int set_defaults P_((void)); +static int get_groups P_((char *)); +static void usage P_((void)); +static void new_pwent P_((struct passwd *)); +#ifdef SHADOWPWD +static long scale_age P_((long)); +static void new_spent P_((struct spwd *)); +#endif +static void grp_update P_((void)); +static void find_new_uid P_((void)); +#ifdef AUTH_METHODS +static void convert_auth P_((char *, const char *)); +static int valid_auth P_((const char *)); +#endif +static void process_flags P_((int argc, char **argv)); +static void close_files P_((void)); +static void open_files P_((void)); +static void faillog_reset P_((uid_t)); +static void lastlog_reset P_((uid_t)); +static void usr_update P_((void)); +static void create_home P_((void)); +int main P_((int, char **)); + +/* + * fail_exit - undo as much as possible + */ + +static void +fail_exit(int code) +{ +#ifdef NDBM + struct passwd pwent; + + if (pw_dbm_added) { + pwent.pw_name = user_name; + pwent.pw_uid = user_id; + pw_dbm_remove(&pwent); + } + if (gr_dbm_added) + fprintf(stderr, _("%s: rebuild the group database\n"), Prog); +#ifdef SHADOWPWD + if (sp_dbm_added) + sp_dbm_remove(user_name); +#endif +#ifdef SHADOWGRP + if (sg_dbm_added) + fprintf(stderr, _("%s: rebuild the shadow group database\n"), + Prog); +#endif +#endif /* NDBM */ + if (home_added) + rmdir(user_home); + + SYSLOG((LOG_INFO, "failed adding user `%s', data deleted\n", + user_name)); + exit(code); +} + + +static struct group * +getgr_nam_gid(const char *name) +{ + gid_t gid; + char *ep; + + gid = strtol(name, &ep, 10); + if (*name != '\0' && *ep == '\0') /* valid numeric gid */ + return getgrgid(gid); + + return getgrnam(name); +} + + +static long +get_number(const char *cp) +{ + long val; + char *ep; + + val = strtol(cp, &ep, 10); + if (*cp != '\0' && *ep == '\0') /* valid number */ + return val; + + fprintf(stderr, _("%s: invalid numeric argument `%s'\n"), Prog, cp); + exit(E_BAD_ARG); +} + +#define MATCH(x,y) (strncmp((x),(y),strlen(y)) == 0) + +/* + * get_defaults - read the defaults file + * + * get_defaults() reads the defaults file for this command. It sets + * the various values from the file, or uses built-in default values + * if the file does not exist. + */ + +static void +get_defaults(void) +{ + FILE *fp; + char buf[1024]; + char *cp, *ep; + const struct group *grp; + long val; + + /* + * Open the defaults file for reading. + */ + + if (!(fp = fopen(def_file, "r"))) + return; + + /* + * Read the file a line at a time. Only the lines that have + * relevant values are used, everything else can be ignored. + */ + + while (fgets(buf, sizeof buf, fp)) { + if ((cp = strrchr (buf, '\n'))) + *cp = '\0'; + + if (!(cp = strchr(buf, '='))) + continue; + + cp++; + + /* + * Primary GROUP identifier + */ + + if (MATCH(buf, DGROUP)) { + val = strtol(cp, &ep, 10); + if (*cp != '\0' && *ep == '\0') { /* valid number */ + def_group = val; + if ((grp = getgrgid(def_group))) { + def_gname = xstrdup(grp->gr_name); + } else { + fprintf(stderr, + _("%s: unknown gid %s\n"), + Prog, cp); + } + } else if ((grp = getgrnam(cp))) { + def_group = grp->gr_gid; + def_gname = xstrdup(cp); + } else { + fprintf(stderr, _("%s: unknown group %s\n"), + Prog, cp); + } + } + + /* + * Default HOME filesystem + */ + + else if (MATCH(buf, HOME)) { + def_home = xstrdup(cp); + } + + /* + * Default Login Shell command + */ + + else if (MATCH(buf, SHELL)) { + def_shell = xstrdup(cp); + } + +#ifdef SHADOWPWD + /* + * Default Password Inactive value + */ + + else if (MATCH(buf, INACT)) { + val = strtol(cp, &ep, 10); + if (*cp != '\0' && *ep == '\0') /* valid number */ + def_inactive = val; + else + def_inactive = -1; + } + + /* + * Default account expiration date + */ + + else if (MATCH(buf, EXPIRE)) { + def_expire = xstrdup(cp); + } +#endif + + /* + * Default Skeleton information + */ + + else if (MATCH(buf, SKEL)) { + if (*cp == '\0') + cp = SKEL_DIR; /* XXX warning: const */ + + def_template = xstrdup(cp); + } + } +} + + +/* + * show_defaults - show the contents of the defaults file + * + * show_defaults() displays the values that are used from the default + * file and the built-in values. + */ + +static void +show_defaults(void) +{ +#ifdef SVR4 + printf(_("group=%s,%ld basedir=%s skel=%s\n"), + def_gname, (long) def_group, def_home, def_template); + + printf(_("shell=%s "), def_shell); +#ifdef SHADOWPWD + printf(_("inactive=%ld expire=%s"), def_inactive, def_expire); +#endif + printf("\n"); +#else /* !SVR4 */ + printf(_("GROUP=%ld\n"), (long) def_group); + printf(_("HOME=%s\n"), def_home); +#ifdef SHADOWPWD + printf(_("INACTIVE=%ld\n"), def_inactive); + printf(_("EXPIRE=%s\n"), def_expire); +#endif + printf(_("SHELL=%s\n"), def_shell); + printf(_("SKEL=%s\n"), def_template); +#endif /* !SVR4 */ +} + +/* + * set_defaults - write new defaults file + * + * set_defaults() re-writes the defaults file using the values that + * are currently set. Duplicated lines are pruned, missing lines are + * added, and unrecognized lines are copied as is. + */ + +static int +set_defaults(void) +{ + FILE *ifp; + FILE *ofp; + char buf[1024]; + static char new_file[] = NEW_USER_FILE; + char *cp; + int out_group = 0; + int out_home = 0; + int out_inactive = 0; + int out_expire = 0; + int out_shell = 0; + int out_skel = 0; +#ifdef SVR4 + int out_gname = 0; +#endif + + /* + * Create a temporary file to copy the new output to. + */ + + mktemp (new_file); + if (!(ofp = fopen (new_file, "w"))) { + fprintf(stderr, _("%s: cannot create new defaults file\n"), + Prog); + return -1; + } + + /* + * Open the existing defaults file and copy the lines to the + * temporary file, using any new values. Each line is checked + * to insure that it is not output more than once. + */ + + if (!(ifp = fopen(def_file, "r"))) { + fprintf(ofp, "# useradd defaults file\n"); + goto skip; + } + + while (fgets(buf, sizeof buf, ifp)) { + if ((cp = strrchr(buf, '\n'))) + *cp = '\0'; + + if (!out_group && MATCH(buf, DGROUP)) { + fprintf(ofp, DGROUP "%d\n", (int) def_group); + out_group++; + } +#ifdef SVR4 + else if (!out_gname && MATCH(buf, "defgname=")) { + fprintf(ofp, "defgname=%s\n", def_gname); + out_gname++; + } +#endif + else if (!out_home && MATCH(buf, HOME)) { + fprintf(ofp, HOME "%s\n", def_home); + out_home++; +#ifdef SHADOWPWD + } else if (!out_inactive && MATCH(buf, INACT)) { + fprintf(ofp, INACT "%ld\n", def_inactive); + out_inactive++; + } else if (!out_expire && MATCH(buf, EXPIRE)) { + fprintf(ofp, EXPIRE "%s\n", def_expire); + out_expire++; + } +#endif + else if (!out_shell && MATCH(buf, SHELL)) { + fprintf(ofp, SHELL "%s\n", def_shell); + out_shell++; + } + else if (!out_skel && MATCH(buf, SKEL)) { + fprintf(ofp, SKEL "%s\n", def_template); + out_skel++; + } + else + fprintf(ofp, "%s\n", buf); + } + fclose(ifp); + +skip: + /* + * Check each line to insure that every line was output. This + * causes new values to be added to a file which did not previously + * have an entry for that value. + */ + + if (!out_group) + fprintf(ofp, DGROUP "%d\n", (int) def_group); + if (!out_home) + fprintf(ofp, HOME "%s\n", def_home); +#ifdef SHADOWPWD + if (!out_inactive) + fprintf(ofp, INACT "%ld\n", def_inactive); + if (!out_expire) + fprintf(ofp, EXPIRE "%s\n", def_expire); +#endif + if (!out_shell) + fprintf(ofp, SHELL "%s\n", def_shell); + if (!out_skel) + fprintf(ofp, SKEL "%s\n", def_template); + + /* + * Flush and close the file. Check for errors to make certain + * the new file is intact. + */ + + fflush(ofp); + if (ferror(ofp) || fclose(ofp)) { + unlink(new_file); + return -1; + } + + /* + * Rename the current default file to its backup name. + */ + + snprintf(buf, sizeof buf, "%s-", def_file); + if (rename(def_file, buf) && errno != ENOENT) { + snprintf(buf, sizeof buf, _("%s: rename: %s"), Prog, def_file); + perror(buf); + unlink(new_file); + return -1; + } + + /* + * Rename the new default file to its correct name. + */ + + if (rename(new_file, def_file)) { + snprintf(buf, sizeof buf, _("%s: rename: %s"), Prog, new_file); + perror(buf); + return -1; + } +#ifdef SHADOWPWD + SYSLOG((LOG_INFO, + "defaults: group=%d, home=%s, inactive=%ld, expire=%s\n", + (int) def_group, def_home, def_inactive, def_expire)); +#else + SYSLOG((LOG_INFO, "defaults: group=%d, home=%s\n", + (int) def_group, def_home)); +#endif + return 0; +} + +/* + * get_groups - convert a list of group names to an array of group IDs + * + * get_groups() takes a comma-separated list of group names and + * converts it to a NULL-terminated array. Any unknown group + * names are reported as errors. + */ + +static int +get_groups(char *list) +{ + char *cp; + const struct group *grp; + int errors = 0; + int ngroups = 0; + + /* + * Initialize the list to be empty + */ + + user_groups[0] = (char *) 0; + + if (! *list) + return 0; + + /* + * So long as there is some data to be converted, strip off + * each name and look it up. A mix of numerical and string + * values for group identifiers is permitted. + */ + + do { + /* + * Strip off a single name from the list + */ + + if ((cp = strchr (list, ','))) + *cp++ = '\0'; + + /* + * Names starting with digits are treated as numerical + * GID values, otherwise the string is looked up as is. + */ + + grp = getgr_nam_gid(list); + + /* + * There must be a match, either by GID value or by + * string name. + */ + + if (! grp) { + fprintf(stderr, _("%s: unknown group %s\n"), + Prog, list); + errors++; + } + list = cp; + + /* + * If the group doesn't exist, don't dump core... + * Instead, try the next one. --marekm + */ + if (! grp) + continue; + +#ifdef USE_NIS + /* + * Don't add this group if they are an NIS group. Tell + * the user to go to the server for this group. + */ + + if (__isgrNIS ()) { + fprintf(stderr, _("%s: group `%s' is a NIS group.\n"), + Prog, grp->gr_name); + continue; + } +#endif + + if (ngroups == NGROUPS_MAX) { + fprintf(stderr, + _("%s: too many groups specified (max %d).\n"), + Prog, ngroups); + break; + } + + /* + * Add the group name to the user's list of groups. + */ + + user_groups[ngroups++] = xstrdup(grp->gr_name); + } while (list); + + user_groups[ngroups] = (char *) 0; + + /* + * Any errors in finding group names are fatal + */ + + if (errors) + return -1; + + return 0; +} + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, + _("usage: %s\t[-u uid [-o]] [-g group] [-G group,...] \n"), + Prog); + fprintf(stderr, + _("\t\t[-d home] [-s shell] [-c comment] [-m [-k template]]\n")); + fprintf(stderr, "\t\t"); +#ifdef SHADOWPWD + fprintf(stderr, _("[-f inactive] [-e expire ] ")); +#endif +#ifdef AUTH_METHODS + fprintf(stderr, _("[-A program] ")); +#endif + fprintf(stderr, _("[-p passwd] name\n")); + + fprintf(stderr, _(" %s\t-D [-g group] [-b base] [-s shell]\n"), + Prog); +#ifdef SHADOWPWD + fprintf(stderr, _("\t\t[-f inactive] [-e expire ]\n")); +#endif + + exit(E_USAGE); +} + +/* + * new_pwent - initialize the values in a password file entry + * + * new_pwent() takes all of the values that have been entered and + * fills in a (struct passwd) with them. + */ + +static void +new_pwent(struct passwd *pwent) +{ + memzero(pwent, sizeof *pwent); + pwent->pw_name = (char *) user_name; +#ifdef SHADOWPWD + if (is_shadow_pwd) + pwent->pw_passwd = (char *) SHADOW_PASSWD_STRING; + else +#endif + pwent->pw_passwd = (char *) user_pass; + +#ifdef ATT_AGE + pwent->pw_age = (char *) ""; +#endif + pwent->pw_uid = user_id; + pwent->pw_gid = user_gid; + pwent->pw_gecos = (char *) user_comment; +#ifdef ATT_COMMENT + pwent->pw_comment = (char *) ""; +#endif +#ifdef BSD_QUOTA + pwent->pw_quota = (char *) ""; +#endif + pwent->pw_dir = (char *) user_home; + pwent->pw_shell = (char *) user_shell; +} + +#ifdef SHADOWPWD +static long +scale_age(long x) +{ + if (x <= 0) + return x; + + return x * (DAY/SCALE); +} + +/* + * new_spent - initialize the values in a shadow password file entry + * + * new_spent() takes all of the values that have been entered and + * fills in a (struct spwd) with them. + */ + +static void +new_spent(struct spwd *spent) +{ + memzero(spent, sizeof *spent); + spent->sp_namp = (char *) user_name; + spent->sp_pwdp = (char *) user_pass; + spent->sp_lstchg = time((time_t *) 0) / SCALE; + spent->sp_min = scale_age(getdef_num("PASS_MIN_DAYS", -1)); + spent->sp_max = scale_age(getdef_num("PASS_MAX_DAYS", -1)); + spent->sp_warn = scale_age(getdef_num("PASS_WARN_AGE", -1)); + spent->sp_inact = scale_age(def_inactive); + spent->sp_expire = scale_age(user_expire); + spent->sp_flag = -1; +} +#endif + +/* + * grp_update - add user to secondary group set + * + * grp_update() takes the secondary group set given in user_groups + * and adds the user to each group given by that set. + */ + +static void +grp_update(void) +{ + const struct group *grp; + struct group *ngrp; +#ifdef SHADOWGRP + const struct sgrp *sgrp; + struct sgrp *nsgrp; +#endif + + /* + * Lock and open the group file. This will load all of the group + * entries. + */ + + if (! gr_lock ()) { + fprintf(stderr, _("%s: error locking group file\n"), Prog); + fail_exit(E_GRP_UPDATE); + } + if (! gr_open (O_RDWR)) { + fprintf(stderr, _("%s: error opening group file\n"), Prog); + fail_exit(E_GRP_UPDATE); + } +#ifdef SHADOWGRP + if (is_shadow_grp && ! sgr_lock ()) { + fprintf(stderr, _("%s: error locking shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } + if (is_shadow_grp && ! sgr_open (O_RDWR)) { + fprintf(stderr, _("%s: error opening shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } +#endif + + /* + * Scan through the entire group file looking for the groups that + * the user is a member of. + */ + + for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) { + + /* + * See if the user specified this group as one of their + * concurrent groups. + */ + + if (!is_on_list(user_groups, grp->gr_name)) + continue; + + /* + * Make a copy - gr_update() will free() everything + * from the old entry, and we need it later. + */ + + ngrp = __gr_dup(grp); + if (!ngrp) { + fail_exit(E_GRP_UPDATE); /* XXX */ + } + + /* + * Add the username to the list of group members and + * update the group entry to reflect the change. + */ + + ngrp->gr_mem = add_list (ngrp->gr_mem, user_name); + if (!gr_update(ngrp)) { + fprintf(stderr, "%s: error adding new group entry\n", + Prog); + fail_exit(E_GRP_UPDATE); + } +#ifdef NDBM + /* + * Update the DBM group file with the new entry as well. + */ + + if (!gr_dbm_update(ngrp)) { + fprintf(stderr, "%s: cannot add new dbm group entry\n", + Prog); + fail_exit(E_GRP_UPDATE); + } else + gr_dbm_added++; +#endif + SYSLOG((LOG_INFO, "add `%s' to group `%s'\n", + user_name, ngrp->gr_name)); + } +#ifdef NDBM + endgrent (); +#endif + +#ifdef SHADOWGRP + if (!is_shadow_grp) + return; + + /* + * Scan through the entire shadow group file looking for the groups + * that the user is a member of. The administrative list isn't + * modified. + */ + + for (sgr_rewind (), sgrp = sgr_next ();sgrp;sgrp = sgr_next ()) { + + /* + * See if the user specified this group as one of their + * concurrent groups. + */ + + if (!gr_locate(sgrp->sg_name)) + continue; + + if (!is_on_list(user_groups, sgrp->sg_name)) + continue; + + /* + * Make a copy - sgr_update() will free() everything + * from the old entry, and we need it later. + */ + + nsgrp = __sgr_dup(sgrp); + if (!nsgrp) { + fail_exit(E_GRP_UPDATE); /* XXX */ + } + + /* + * Add the username to the list of group members and + * update the group entry to reflect the change. + */ + + nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_name); + if (!sgr_update(nsgrp)) { + fprintf(stderr, + _("%s: error adding new group entry\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } +#ifdef NDBM + /* + * Update the DBM group file with the new entry as well. + */ + + if (!sg_dbm_update(nsgrp)) { + fprintf(stderr, + _("%s: cannot add new dbm group entry\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } else + sg_dbm_added++; +#endif /* NDBM */ + SYSLOG((LOG_INFO, "add `%s' to shadow group `%s'\n", + user_name, nsgrp->sg_name)); + } +#ifdef NDBM + endsgent (); +#endif /* NDBM */ +#endif /* SHADOWGRP */ +} + +/* + * find_new_uid - find the next available UID + * + * find_new_uid() locates the next highest unused UID in the password + * file, or checks the given user ID against the existing ones for + * uniqueness. + */ + +static void +find_new_uid(void) +{ + const struct passwd *pwd; + uid_t uid_min, uid_max; + + uid_min = getdef_num("UID_MIN", 100); + uid_max = getdef_num("UID_MAX", 60000); + + /* + * Start with some UID value if the user didn't provide us with + * one already. + */ + + if (! uflg) + user_id = uid_min; + + /* + * Search the entire password file, either looking for this + * UID (if the user specified one with -u) or looking for the + * largest unused value. + */ + +#ifdef NO_GETPWENT + pw_rewind(); + while ((pwd = pw_next())) { +#else /* using getpwent() we can check against NIS users etc. */ + setpwent(); + while ((pwd = getpwent())) { +#endif + if (strcmp(user_name, pwd->pw_name) == 0) { + fprintf(stderr, _("%s: name %s is not unique\n"), + Prog, user_name); + exit(E_NAME_IN_USE); + } + if (uflg && user_id == pwd->pw_uid) { + fprintf(stderr, _("%s: uid %d is not unique\n"), + Prog, (int) user_id); + exit(E_UID_IN_USE); + } + if (! uflg && pwd->pw_uid >= user_id) { + if (pwd->pw_uid > uid_max) + continue; + user_id = pwd->pw_uid + 1; + } + } + /* + * If a user with uid equal to UID_MAX exists, the above algorithm + * will give us UID_MAX+1 even if not unique. Search for the first + * free uid starting with UID_MIN (it's O(n*n) but can be avoided + * by not having users with uid equal to UID_MAX). --marekm + */ + if (!uflg && user_id == uid_max + 1) { + for (user_id = uid_min; user_id < uid_max; user_id++) { +#ifdef NO_GETPWENT + pw_rewind(); + while ((pwd = pw_next()) && pwd->pw_uid != user_id) + ; + if (!pwd) + break; +#else + if (!getpwuid(user_id)) + break; +#endif + } + if (user_id == uid_max) { + fprintf(stderr, _("%s: can't get unique uid\n"), + Prog); + fail_exit(E_UID_IN_USE); + } + } +} + +#ifdef AUTH_METHODS +/* + * convert_auth - convert the argument list to a authentication list + */ + +static void +convert_auth(char *auths, const char *list) +{ + char *cp, *end; + char buf[257]; + + /* + * Copy each method. DEFAULT is replaced by an encrypted string + * if one can be found in the current authentication list. + */ + + strcpy(buf, list); + auths[0] = '\0'; + for (cp = buf; cp; cp = end) { + if (auths[0]) + strcat(auths, ";"); + + if ((end = strchr(cp, ','))) + *end++ = '\0'; + + if (strcmp(cp, "DEFAULT") == 0) { + strcat(auths, user_pass); + } else { + strcat(auths, "@"); + strcat(auths, cp); + } + } +} + +/* + * valid_auth - check authentication list for validity + */ + +static int +valid_auth(const char *methods) +{ + char *cp, *end; + char buf[257]; + int default_cnt = 0; + + /* + * Cursory checks, length and illegal characters + */ + + if ((int) strlen (methods) > 256) + return 0; + + if (! VALID (methods)) + return 0; + + /* + * Pick each method apart and check it. + */ + + strcpy (buf, methods); + for (cp = buf;cp;cp = end) { + if ((end = strchr (cp, ','))) + *end++ = '\0'; + + if (strcmp (cp, "DEFAULT") == 0) { + if (default_cnt++ > 0) + return 0; + } + } + return 1; +} +#endif /* AUTH_METHODS */ + +/* + * process_flags - perform command line argument setting + * + * process_flags() interprets the command line arguments and sets + * the values that the user will be created with accordingly. The + * values are checked for sanity. + */ + +static void +process_flags(int argc, char **argv) +{ + const struct group *grp; + int anyflag = 0; + int arg; + char *cp; + +#ifdef SHADOWPWD +#define FLAGS "A:Du:og:G:d:s:c:mk:p:f:e:b:O:M" +#else +#define FLAGS "A:Du:og:G:d:s:c:mk:p:b:O:M" +#endif + while ((arg = getopt(argc, argv, FLAGS)) != EOF) { +#undef FLAGS + switch (arg) { +#ifdef AUTH_METHODS + case 'A': + if (! valid_auth (optarg)) { + fprintf(stderr, + _("%s: invalid field `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + auth_arg = optarg; + Aflg++; + break; +#endif + case 'b': + if (!Dflg) + usage (); + + if (!VALID(optarg) || optarg[0] != '/') { + fprintf(stderr, + _("%s: invalid base directory `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + def_home = optarg; + bflg++; + break; + case 'c': + if (!VALID(optarg)) { + fprintf(stderr, + _("%s: invalid comment `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + user_comment = optarg; + cflg++; + break; + case 'd': + if (!VALID(optarg) || optarg[0] != '/') { + fprintf(stderr, + _("%s: invalid home directory `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + user_home = optarg; + dflg++; + break; + case 'D': + if (anyflag) + usage(); + Dflg++; + break; +#ifdef SHADOWPWD + case 'e': + if (*optarg) { + user_expire = strtoday(optarg); + if (user_expire == -1) { + fprintf(stderr, + _("%s: invalid date `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + } else + user_expire = -1; + + /* + * -e "" is allowed - it's a no-op without /etc/shadow + */ + if (*optarg && !is_shadow_pwd) { + fprintf(stderr, + _("%s: shadow passwords required for -e\n"), + Prog); + exit(E_USAGE); + } + if (Dflg) + def_expire = optarg; + eflg++; + break; + case 'f': + def_inactive = get_number(optarg); + /* + * -f -1 is allowed - it's a no-op without /etc/shadow + */ + if (def_inactive != -1 && !is_shadow_pwd) { + fprintf(stderr, + _("%s: shadow passwords required for -f\n"), + Prog); + exit(E_USAGE); + } + fflg++; + break; +#endif + case 'g': + grp = getgr_nam_gid(optarg); + if (!grp) { + fprintf(stderr, _("%s: unknown group %s\n"), + Prog, optarg); + exit(E_NOTFOUND); + } + if (Dflg) { + def_group = grp->gr_gid; + def_gname = optarg; + } else { + user_gid = grp->gr_gid; + } + gflg++; + break; + case 'G': + if (get_groups(optarg)) + exit(E_NOTFOUND); + if (user_groups[0]) + do_grp_update++; + Gflg++; + break; + case 'k': + def_template = optarg; + kflg++; + break; + case 'm': + mflg++; + break; + case 'M': + /* + * don't create home dir - this is the default, + * ignored for RedHat/PLD adduser compatibility. + */ + break; + case 'o': + oflg++; + break; + case 'O': + /* + * override login.defs defaults (-O name=value) + * example: -O UID_MIN=100 -O UID_MAX=499 + * note: -O UID_MIN=10,UID_MAX=499 doesn't work yet + */ + cp = strchr(optarg, '='); + if (!cp) { + fprintf(stderr, + _("%s: -O requires NAME=VALUE\n"), + Prog); + exit(E_BAD_ARG); + } + /* terminate name, point to value */ + *cp++ = '\0'; + if (putdef_str(optarg, cp) < 0) + exit(E_BAD_ARG); + break; + case 'p': /* set encrypted password */ + if (!VALID(optarg)) { + fprintf(stderr, _("%s: invalid field `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + user_pass = optarg; + break; + case 's': + if (!VALID(optarg) || (optarg[0] && + (optarg[0] != '/' && optarg[0] != '*'))) { + fprintf(stderr, _("%s: invalid shell `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + user_shell = optarg; + def_shell = optarg; + sflg++; + break; + case 'u': + user_id = get_number(optarg); + uflg++; + break; + default: + usage(); + } + anyflag++; + } + + /* + * Certain options are only valid in combination with others. + * Check it here so that they can be specified in any order. + */ + if ((oflg && !uflg) || (kflg && !mflg)) + usage(); + + /* + * Either -D or username is required. Defaults can be set with -D + * for the -b, -e, -f, -g, -s options only. + */ + if (Dflg) { + if (optind != argc) + usage(); + + if (uflg || oflg || Gflg || dflg || cflg || mflg) + usage(); + } else { + if (optind != argc - 1) + usage(); + + user_name = argv[optind]; + if (!check_user_name(user_name)) { + fprintf(stderr, _("%s: invalid user name `%s'\n"), + Prog, user_name); + exit(E_BAD_ARG); + } + if (!dflg) { + char *uh; + + uh = xmalloc(strlen(def_home) + strlen(user_name) + 2); + sprintf(uh, "%s/%s", def_home, user_name); + user_home = uh; + } + } + +#ifdef SHADOWPWD + if (!eflg) + user_expire = strtoday(def_expire); +#endif + + if (!gflg) + user_gid = def_group; + + if (!sflg) + user_shell = def_shell; +} + +/* + * close_files - close all of the files that were opened + * + * close_files() closes all of the files that were opened for this + * new user. This causes any modified entries to be written out. + */ + +static void +close_files(void) +{ + if (!pw_close()) { + fprintf(stderr, _("%s: cannot rewrite password file\n"), Prog); + fail_exit(E_PW_UPDATE); + } +#ifdef SHADOWPWD + if (is_shadow_pwd && !spw_close()) { + fprintf(stderr, _("%s: cannot rewrite shadow password file\n"), + Prog); + fail_exit(E_PW_UPDATE); + } +#endif + if (do_grp_update) { + if (!gr_close()) { + fprintf(stderr, _("%s: cannot rewrite group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } + gr_unlock(); +#ifdef SHADOWGRP + if (is_shadow_grp && !sgr_close()) { + fprintf (stderr, + _("%s: cannot rewrite shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } + if (is_shadow_grp) + sgr_unlock(); +#endif + } +#ifdef SHADOWPWD + if (is_shadow_pwd) + spw_unlock(); +#endif + pw_unlock(); +} + +/* + * open_files - lock and open the password files + * + * open_files() opens the two password files. + */ + +static void +open_files(void) +{ + if (!pw_lock()) { + fprintf(stderr, _("%s: unable to lock password file\n"), Prog); + exit(E_PW_UPDATE); + } + if (!pw_open(O_RDWR)) { + fprintf(stderr, _("%s: unable to open password file\n"), Prog); + pw_unlock(); + exit(E_PW_UPDATE); + } +#ifdef SHADOWPWD + if (is_shadow_pwd && !spw_lock()) { + fprintf(stderr, _("%s: cannot lock shadow password file\n"), + Prog); + pw_unlock(); + exit(E_PW_UPDATE); + } + if (is_shadow_pwd && !spw_open(O_RDWR)) { + fprintf(stderr, _("%s: cannot open shadow password file\n"), + Prog); + spw_unlock(); + pw_unlock(); + exit(E_PW_UPDATE); + } +#endif +} + + +static void +faillog_reset(uid_t uid) +{ + struct faillog fl; + int fd; + + fd = open(FAILLOG_FILE, O_RDWR); + if (fd >= 0) { + memzero(&fl, sizeof(fl)); + lseek(fd, (off_t) sizeof(fl) * uid, SEEK_SET); + write(fd, &fl, sizeof(fl)); + close(fd); + } +} + +static void +lastlog_reset(uid_t uid) +{ + struct lastlog ll; + int fd; + + fd = open(LASTLOG_FILE, O_RDWR); + if (fd >= 0) { + memzero(&ll, sizeof(ll)); + lseek(fd, (off_t) sizeof(ll) * uid, SEEK_SET); + write(fd, &ll, sizeof(ll)); + close(fd); + } +} + +/* + * usr_update - create the user entries + * + * usr_update() creates the password file entries for this user + * and will update the group entries if required. + */ + +static void +usr_update(void) +{ + struct passwd pwent; +#ifdef SHADOWPWD + struct spwd spent; +#endif + + if (! oflg) + find_new_uid (); + +#ifdef AUTH_METHODS + if (Aflg) { + convert_auth(user_auth, auth_arg); + user_pass = user_auth; + } +#endif + + /* + * Fill in the password structure with any new fields, making + * copies of strings. + */ + + new_pwent (&pwent); +#ifdef SHADOWPWD + new_spent (&spent); +#endif + + /* + * Create a syslog entry. We need to do this now in case anything + * happens so we know what we were trying to accomplish. + */ + +#ifdef AUTH_METHODS + SYSLOG((LOG_INFO, + "new user: name=%s, uid=%d, gid=%d, home=%s, shell=%s, auth=%s\n", + user_name, user_id, user_gid, user_home, user_shell, + Aflg ? auth_arg : "DEFAULT")); +#else + SYSLOG((LOG_INFO, + "new user: name=%s, uid=%d, gid=%d, home=%s, shell=%s\n", + user_name, user_id, user_gid, user_home, user_shell)); +#endif + +#ifdef AUTH_METHODS + /* + * Attempt to add the new user to any authentication programs + * which have been requested. Since this is more likely to fail + * than the update of the password file, we do this first. + */ + + if (Aflg && pw_auth(user_auth, pwent.pw_name, PW_ADD, (char *) 0)) { + fprintf(stderr, _("%s: error adding authentication method\n"), + Prog); + fail_exit(E_PW_UPDATE); /* XXX */ + } +#endif /* AUTH_METHODS */ + + /* + * Initialize faillog and lastlog entries for this UID in case + * it belongs to a previously deleted user. We do it only if + * no user with this UID exists yet (entries for shared UIDs + * are left unchanged). --marekm + */ + + if (!getpwuid(user_id)) { + faillog_reset(user_id); + lastlog_reset(user_id); + } + + /* + * Put the new (struct passwd) in the table. + */ + + if (! pw_update (&pwent)) { + fprintf(stderr, _("%s: error adding new password entry\n"), + Prog); + exit(E_PW_UPDATE); + } + +#ifdef NDBM + /* + * Update the DBM files. This creates the user before the flat + * files are updated. This is safe before the password field is + * either locked, or set to a valid authentication string. + */ + + if (pw_dbm_present()) { + if (!pw_dbm_update(&pwent)) { + fprintf(stderr, + _("%s: error updating password dbm entry\n"), + Prog); + exit(E_PW_UPDATE); + } else + pw_dbm_added = 1; + } + endpwent(); +#endif + +#ifdef SHADOWPWD + /* + * Put the new (struct spwd) in the table. + */ + + if (is_shadow_pwd && !spw_update(&spent)) { + fprintf(stderr, + _("%s: error adding new shadow password entry\n"), + Prog); + exit(E_PW_UPDATE); + } + +#ifdef NDBM + /* + * Update the DBM files for the shadow password. This entry is + * output before the entry in the flat file, but this is safe as + * the password is locked or the authentication string has the + * proper values. + */ + + if (is_shadow_pwd && sp_dbm_present()) { + if (!sp_dbm_update(&spent)) { + fprintf(stderr, + _("%s: error updating shadow passwd dbm entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } else + sp_dbm_added++; + endspent(); + } +#endif +#endif /* SHADOWPWD */ + + /* + * Do any group file updates for this user. + */ + + if (do_grp_update) + grp_update(); +} + +/* + * create_home - create the user's home directory + * + * create_home() creates the user's home directory if it does not + * already exist. It will be created mode 755 owned by the user + * with the user's default group. + */ + +static void +create_home(void) +{ + if (access(user_home, F_OK)) { + /* XXX - create missing parent directories. --marekm */ + if (mkdir (user_home, 0)) { + fprintf(stderr, _("%s: cannot create directory %s\n"), + Prog, user_home); + fail_exit(E_HOMEDIR); + } + chown (user_home, user_id, user_gid); +#if 1 + chmod(user_home, 0777 & ~getdef_num("UMASK", 077)); +#else + chmod (user_home, 0755); +#endif + home_added++; + } +} + +/* + * main - useradd command + */ + +int +main(int argc, char **argv) +{ + /* + * Get my name so that I can use it to report errors. + */ + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + +#ifdef SHADOWPWD + is_shadow_pwd = spw_file_present(); +#endif +#ifdef SHADOWGRP + is_shadow_grp = sgr_file_present(); +#endif + + /* + * The open routines for the NDBM files don't use read-write + * as the mode, so we have to clue them in. + */ + +#ifdef NDBM + pw_dbm_mode = O_RDWR; +#ifdef SHADOWPWD + sp_dbm_mode = O_RDWR; +#endif + gr_dbm_mode = O_RDWR; +#ifdef SHADOWGRP + sg_dbm_mode = O_RDWR; +#endif +#endif + get_defaults(); + + process_flags(argc, argv); + + /* + * See if we are messing with the defaults file, or creating + * a new user. + */ + + if (Dflg) { + if (gflg || bflg || fflg || eflg || sflg) + exit (set_defaults () ? 1:0); + + show_defaults(); + exit(E_SUCCESS); + } + + /* + * Start with a quick check to see if the user exists. + */ + + if (getpwnam(user_name)) { + fprintf(stderr, _("%s: user %s exists\n"), Prog, user_name); + exit(E_NAME_IN_USE); + } + + /* + * Do the hard stuff - open the files, create the user entries, + * create the home directory, then close and update the files. + */ + + open_files (); + + usr_update (); + + if (mflg) { + create_home (); + copy_tree (def_template, user_home, user_id, user_gid); + } else if (getdef_str("CREATE_HOME")) { + /* + * RedHat added the CREATE_HOME option in login.defs in their + * version of shadow-utils (which makes -m the default, with + * new -M option to turn it off). Unfortunately, this + * changes the way useradd works (it can be run by scripts + * expecting some standard behaviour), compared to other + * Unices and other Linux distributions, and also adds a lot + * of confusion :-(. + * So we now recognize CREATE_HOME and give a warning here + * (better than "configuration error ... notify administrator" + * errors in every program that reads /etc/login.defs). -MM + */ + fprintf(stderr, + _("%s: warning: CREATE_HOME not supported, please use -m instead.\n"), + Prog); + } + + close_files (); + exit(E_SUCCESS); + /*NOTREACHED*/ +} diff --git a/src/userdel.c b/src/userdel.c new file mode 100644 index 00000000..6acc5b5f --- /dev/null +++ b/src/userdel.c @@ -0,0 +1,816 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: userdel.c,v 1.15 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" +#include "getdef.h" +#include "pwauth.h" + +/* + * exit status values + */ +#define E_SUCCESS 0 +#define E_PW_UPDATE 1 /* can't update password file */ +#define E_USAGE 2 /* bad command syntax */ +#define E_NOTFOUND 6 /* specified user doesn't exist */ +#define E_USER_BUSY 8 /* user currently logged in */ +#define E_GRP_UPDATE 10 /* can't update group file */ +#define E_HOMEDIR 12 /* can't remove home directory */ + +static char *user_name; +static uid_t user_id; +static char *user_home; + +static char *Prog; +static int fflg = 0, rflg = 0; + +#ifdef NDBM +extern int pw_dbm_mode; +#ifdef SHADOWPWD +extern int sp_dbm_mode; +#endif +extern int gr_dbm_mode; +#ifdef SHADOWGRP +extern int sg_dbm_mode; +#endif +#endif + +#include "groupio.h" +#include "pwio.h" + +#ifdef SHADOWPWD +#include "shadowio.h" +#endif + +#ifdef HAVE_TCFS +#include +#include "tcfsio.h" +#endif + +#ifdef SHADOWGRP +#include "sgroupio.h" +#endif + +#ifdef SHADOWPWD +static int is_shadow_pwd; +#endif +#ifdef SHADOWGRP +static int is_shadow_grp; +#endif + +extern int optind; + +/* local function prototypes */ +static void usage P_((void)); +static void update_groups P_((void)); +static void close_files P_((void)); +static void fail_exit P_((int)); +static void open_files P_((void)); +static void update_user P_((void)); +static void user_busy P_((const char *, uid_t)); +static void user_cancel P_((const char *)); +#ifdef EXTRA_CHECK_HOME_DIR +static int path_prefix P_((const char *, const char *)); +#endif +static int is_owner P_((uid_t, const char *)); +#ifndef NO_REMOVE_MAILBOX +static void remove_mailbox P_((void)); +#endif +int main P_((int, char **)); + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, _("usage: %s [-r] name\n"), Prog); + exit(E_USAGE); +} + +/* + * update_groups - delete user from secondary group set + * + * update_groups() takes the user name that was given and searches + * the group files for membership in any group. + */ + +static void +update_groups(void) +{ + const struct group *grp; + struct group *ngrp; +#ifdef SHADOWGRP + const struct sgrp *sgrp; + struct sgrp *nsgrp; +#endif /* SHADOWGRP */ + + /* + * Scan through the entire group file looking for the groups that + * the user is a member of. + */ + + for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) { + + /* + * See if the user specified this group as one of their + * concurrent groups. + */ + + if (!is_on_list(grp->gr_mem, user_name)) + continue; + + /* + * Delete the username from the list of group members and + * update the group entry to reflect the change. + */ + + ngrp = __gr_dup(grp); + if (!ngrp) { + exit(13); /* XXX */ + } + ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); + if (!gr_update(ngrp)) + fprintf(stderr, _("%s: error updating group entry\n"), + Prog); + + /* + * Update the DBM group file with the new entry as well. + */ + +#ifdef NDBM + if (!gr_dbm_update(ngrp)) + fprintf(stderr, + _("%s: cannot update dbm group entry\n"), + Prog); +#endif /* NDBM */ + SYSLOG((LOG_INFO, "delete `%s' from group `%s'\n", + user_name, ngrp->gr_name)); + } +#ifdef NDBM + endgrent (); +#endif /* NDBM */ +#ifdef SHADOWGRP + if (!is_shadow_grp) + return; + + /* + * Scan through the entire shadow group file looking for the groups + * that the user is a member of. Both the administrative list and + * the ordinary membership list is checked. + */ + + for (sgr_rewind (), sgrp = sgr_next ();sgrp;sgrp = sgr_next ()) { + int was_member, was_admin; + + /* + * See if the user specified this group as one of their + * concurrent groups. + */ + + was_member = is_on_list(sgrp->sg_mem, user_name); + was_admin = is_on_list(sgrp->sg_adm, user_name); + + if (!was_member && !was_admin) + continue; + + nsgrp = __sgr_dup(sgrp); + if (!nsgrp) { + exit(13); /* XXX */ + } + + if (was_member) + nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); + + if (was_admin) + nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); + + if (!sgr_update(nsgrp)) + fprintf(stderr, _("%s: error updating group entry\n"), + Prog); +#ifdef NDBM + /* + * Update the DBM group file with the new entry as well. + */ + + if (!sg_dbm_update(nsgrp)) + fprintf(stderr, + _("%s: cannot update dbm group entry\n"), + Prog); +#endif /* NDBM */ + SYSLOG((LOG_INFO, "delete `%s' from shadow group `%s'\n", + user_name, nsgrp->sg_name)); + } +#ifdef NDBM + endsgent (); +#endif /* NDBM */ +#endif /* SHADOWGRP */ +} + +/* + * close_files - close all of the files that were opened + * + * close_files() closes all of the files that were opened for this + * new user. This causes any modified entries to be written out. + */ + +static void +close_files(void) +{ + if (!pw_close()) + fprintf(stderr, _("%s: cannot rewrite password file\n"), Prog); +#ifdef SHADOWPWD + if (is_shadow_pwd && !spw_close()) + fprintf(stderr, _("%s: cannot rewrite shadow password file\n"), + Prog); +#endif +#ifdef HAVE_TCFS + if (!tcfs_close()) + fprintf(stderr, _("%s: cannot rewrite TCFS key file\n"), Prog); +#endif + if (! gr_close ()) + fprintf(stderr, _("%s: cannot rewrite group file\n"), + Prog); + + (void) gr_unlock (); +#ifdef SHADOWGRP + if (is_shadow_grp && !sgr_close()) + fprintf(stderr, _("%s: cannot rewrite shadow group file\n"), + Prog); + + if (is_shadow_grp) + (void) sgr_unlock(); +#endif +#ifdef SHADOWPWD + if (is_shadow_pwd) + (void) spw_unlock(); +#endif +#ifdef HAVE_TCFS + (void) tcfs_unlock(); +#endif + (void) pw_unlock(); +} + +/* + * fail_exit - exit with a failure code after unlocking the files + */ + +static void +fail_exit(int code) +{ + (void) pw_unlock (); + (void) gr_unlock (); +#ifdef SHADOWPWD + if (is_shadow_pwd) + spw_unlock (); +#endif +#ifdef SHADOWGRP + if (is_shadow_grp) + sgr_unlock (); +#endif +#ifdef HAVE_TCFS + (void) tcfs_unlock (); +#endif + + exit(code); +} + +/* + * open_files - lock and open the password files + * + * open_files() opens the two password files. + */ + +static void +open_files(void) +{ + if (!pw_lock()) { + fprintf(stderr, _("%s: unable to lock password file\n"), Prog); + exit(E_PW_UPDATE); + } + if (! pw_open (O_RDWR)) { + fprintf(stderr, _("%s: unable to open password file\n"), Prog); + fail_exit(E_PW_UPDATE); + } +#ifdef SHADOWPWD + if (is_shadow_pwd && ! spw_lock ()) { + fprintf(stderr, _("%s: cannot lock shadow password file\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + if (is_shadow_pwd && ! spw_open (O_RDWR)) { + fprintf(stderr, _("%s: cannot open shadow password file\n"), + Prog); + fail_exit(E_PW_UPDATE); + } +#endif +#ifdef HAVE_TCFS + if (!tcfs_lock()) { + fprintf(stderr, _("%s: cannot lock TCFS key file\n"), Prog); + fail_exit(E_PW_UPDATE); + } + if (!tcfs_open(O_RDWR)) { + fprintf(stderr, _("%s: cannot open TCFS key file\n"), Prog); + fail_exit(E_PW_UPDATE); + } +#endif + if (! gr_lock ()) { + fprintf(stderr, _("%s: unable to lock group file\n"), Prog); + fail_exit(E_GRP_UPDATE); + } + if (! gr_open (O_RDWR)) { + fprintf(stderr, _("%s: cannot open group file\n"), Prog); + fail_exit(E_GRP_UPDATE); + } +#ifdef SHADOWGRP + if (is_shadow_grp && ! sgr_lock ()) { + fprintf(stderr, _("%s: unable to lock shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } + if (is_shadow_grp && ! sgr_open (O_RDWR)) { + fprintf(stderr, _("%s: cannot open shadow group file\n"), + Prog); + fail_exit(E_GRP_UPDATE); + } +#endif +} + +/* + * update_user - delete the user entries + * + * update_user() deletes the password file entries for this user + * and will update the group entries as required. + */ + +static void +update_user(void) +{ +#if defined(AUTH_METHODS) || defined(NDBM) + struct passwd *pwd; +#endif +#ifdef AUTH_METHODS +#ifdef SHADOWPWD + struct spwd *spwd; + + if (is_shadow_pwd && (spwd = spw_locate (user_name)) && + spwd->sp_pwdp[0] == '@') { + if (pw_auth (spwd->sp_pwdp + 1, user_name, PW_DELETE, (char *) 0)) { + SYSLOG((LOG_ERR, + "failed deleting auth `%s' for user `%s'\n", + spwd->sp_pwdp + 1, user_name)); + fprintf(stderr, + _("%s: error deleting authentication\n"), + Prog); + } else { + SYSLOG((LOG_INFO, + "delete auth `%s' for user `%s'\n", + spwd->sp_pwdp + 1, user_name)); + } + } +#endif /* SHADOWPWD */ + if ((pwd = pw_locate(user_name)) && pwd->pw_passwd[0] == '@') { + if (pw_auth(pwd->pw_passwd + 1, user_name, PW_DELETE, (char *) 0)) { + SYSLOG((LOG_ERR, + "failed deleting auth `%s' for user `%s'\n", + pwd->pw_passwd + 1, user_name)); + fprintf(stderr, + _("%s: error deleting authentication\n"), + Prog); + } else { + SYSLOG((LOG_INFO, "delete auth `%s' for user `%s'\n", + pwd->pw_passwd + 1, user_name); + } + } +#endif /* AUTH_METHODS */ + if (!pw_remove(user_name)) + fprintf(stderr, _("%s: error deleting password entry\n"), Prog); +#ifdef SHADOWPWD + if (is_shadow_pwd && ! spw_remove (user_name)) + fprintf(stderr, _("%s: error deleting shadow password entry\n"), + Prog); +#endif +#ifdef HAVE_TCFS + if (tcfs_locate (user_name)) { + if (!tcfs_remove (user_name)) { + SYSLOG((LOG_ERR, + "failed deleting TCFS entry for user `%s'\n", + user_name)); + fprintf(stderr, _("%s: error deleting TCFS entry\n"), + Prog); + } else { + SYSLOG((LOG_INFO, + "delete TCFS entry for user `%s'\n", + user_name)); + } + } +#endif /* HAVE_TCFS */ +#ifdef NDBM + if (pw_dbm_present()) { + if ((pwd = getpwnam (user_name)) && ! pw_dbm_remove (pwd)) + fprintf(stderr, + _("%s: error deleting password dbm entry\n"), + Prog); + } + + /* + * If the user's UID is a duplicate the duplicated entry needs + * to be updated so that a UID match can be found in the DBM + * files. + */ + + for (pw_rewind (), pwd = pw_next ();pwd;pwd = pw_next ()) { + if (pwd->pw_uid == user_id) { + pw_dbm_update (pwd); + break; + } + } +#ifdef SHADOWPWD + if (is_shadow_pwd && sp_dbm_present() && !sp_dbm_remove(user_name)) + fprintf(stderr, + _("%s: error deleting shadow passwd dbm entry\n"), + Prog); + + endspent (); +#endif + endpwent (); +#endif /* NDBM */ + SYSLOG((LOG_INFO, "delete user `%s'\n", user_name)); +} + +/* + * user_busy - see if user is logged in. + * + * XXX - should probably check if there are any processes owned + * by this user. Also, I think this check should be in usermod + * as well (at least when changing username or uid). --marekm + */ + +static void +user_busy(const char *name, uid_t uid) +{ + struct utmp *utent; + + /* + * We see if the user is logged in by looking for the user name + * in the utmp file. + */ + + setutent (); + + while ((utent = getutent ())) { +#ifdef USER_PROCESS + if (utent->ut_type != USER_PROCESS) + continue; +#else + if (utent->ut_user[0] == '\0') + continue; +#endif + if (strncmp(utent->ut_user, name, sizeof utent->ut_user)) + continue; + + fprintf(stderr, _("%s: user %s is currently logged in\n"), + Prog, name); + exit(E_USER_BUSY); + } +} + +/* + * user_cancel - cancel cron and at jobs + * + * user_cancel removes the crontab and any at jobs for a user + */ + +/* + * We used to have all this stuff hardcoded here, but now + * we just run an external script - it may need to do other + * things as well (like removing print jobs) and we may not + * want to recompile userdel too often. Below is a sample + * script (should work at least on Debian 1.1). --marekm +========== +#! /bin/sh + +# Check for the required argument. +if [ $# != 1 ]; then + echo Usage: $0 username + exit 1 +fi + +# Remove cron jobs. +crontab -r -u $1 + +# Remove at jobs. XXX - will remove any jobs owned by the +# same UID, even if it was shared by a different username. +# at really should store the username somewhere, and atrm +# should support an option to remove all jobs owned by the +# specified user - for now we have to do this ugly hack... +find /var/spool/cron/atjobs -name "[^.]*" -type f -user $1 -exec rm {} \; + +# Remove print jobs. +lprm $1 + +# All done. +exit 0 +========== + */ + +static void +user_cancel(const char *user) +{ + char *cmd; + int pid, wpid; + int status; + + if (!(cmd = getdef_str("USERDEL_CMD"))) + return; + + pid = fork(); + if (pid == 0) { + execl(cmd, cmd, user, (char *) 0); + if (errno == ENOENT) { + perror(cmd); + _exit(127); + } else { + perror(cmd); + _exit(126); + } + } else if (pid == -1) { + perror("fork"); + return; + } + + do { + wpid = wait(&status); + } while (wpid != pid && wpid != -1); +} + +#ifdef EXTRA_CHECK_HOME_DIR +static int +path_prefix(const char *s1, const char *s2) +{ + return (strncmp(s2, s1, strlen(s1)) == 0); +} +#endif + +static int +is_owner(uid_t uid, const char *path) +{ + struct stat st; + + if (stat(path, &st)) + return -1; + return (st.st_uid == uid); +} + +#ifndef NO_REMOVE_MAILBOX +static void +remove_mailbox(void) +{ + const char *maildir; + char mailfile[1024]; + int i; + + maildir = getdef_str("MAIL_DIR"); +#ifdef MAIL_SPOOL_DIR + if (!maildir && !getdef_str("MAIL_FILE")) + maildir = MAIL_SPOOL_DIR; +#endif + if (!maildir) + return; + + snprintf(mailfile, sizeof mailfile, "%s/%s", maildir, user_name); + if (fflg) { + unlink(mailfile); /* always remove, ignore errors */ + return; + } + i = is_owner(user_id, mailfile); + if (i == 0) { + fprintf(stderr, + _("%s: warning: %s not owned by %s, not removing\n"), + Prog, mailfile, user_name); + return; + } else if (i == -1) + return; /* mailbox doesn't exist */ + if (unlink(mailfile)) { + fprintf(stderr, _("%s: warning: can't remove "), Prog); + perror(mailfile); + } +} +#endif + +/* + * main - userdel command + */ + +int +main(int argc, char **argv) +{ + struct passwd *pwd; + int arg; + int errors = 0; + + /* + * Get my name so that I can use it to report errors. + */ + + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + +#ifdef SHADOWPWD + is_shadow_pwd = spw_file_present(); +#endif + +#ifdef SHADOWGRP + is_shadow_grp = sgr_file_present(); +#endif + + /* + * The open routines for the DBM files don't use read-write + * as the mode, so we have to clue them in. + */ + +#ifdef NDBM + pw_dbm_mode = O_RDWR; +#ifdef SHADOWPWD + sp_dbm_mode = O_RDWR; +#endif + gr_dbm_mode = O_RDWR; +#ifdef SHADOWGRP + sg_dbm_mode = O_RDWR; +#endif +#endif + while ((arg = getopt (argc, argv, "fr")) != EOF) { + switch (arg) { + case 'f': /* force remove even if not owned by user */ + fflg++; + break; + case 'r': /* remove home dir and mailbox */ + rflg++; + break; + default: + usage(); + } + } + + if (optind + 1 != argc) + usage (); + + /* + * Start with a quick check to see if the user exists. + */ + + user_name = argv[argc - 1]; + + if (! (pwd = getpwnam (user_name))) { + fprintf(stderr, _("%s: user %s does not exist\n"), + Prog, user_name); + exit(E_NOTFOUND); + } +#ifdef USE_NIS + + /* + * Now make sure it isn't an NIS user. + */ + + if (__ispwNIS ()) { + char *nis_domain; + char *nis_master; + + fprintf(stderr, _("%s: user %s is a NIS user\n"), + Prog, user_name); + + if (! yp_get_default_domain (&nis_domain) && + ! yp_master (nis_domain, "passwd.byname", + &nis_master)) { + fprintf(stderr, _("%s: %s is the NIS master\n"), + Prog, nis_master); + } + exit(E_NOTFOUND); + } +#endif + user_id = pwd->pw_uid; + user_home = xstrdup(pwd->pw_dir); + + /* + * Check to make certain the user isn't logged in. + */ + + user_busy (user_name, user_id); + + /* + * Do the hard stuff - open the files, create the user entries, + * create the home directory, then close and update the files. + */ + + open_files (); + + update_user (); + update_groups (); + +#ifndef NO_REMOVE_MAILBOX + if (rflg) + remove_mailbox(); +#endif + + if (rflg && !fflg && !is_owner(user_id, user_home)) { + fprintf(stderr, _("%s: %s not owned by %s, not removing\n"), + Prog, user_home, user_name); + rflg = 0; + errors++; + } + +/* This may be slow, the above should be good enough. */ +#ifdef EXTRA_CHECK_HOME_DIR + if (rflg && !fflg) { + /* + * For safety, refuse to remove the home directory + * if it would result in removing some other user's + * home directory. Still not perfect so be careful, + * but should prevent accidents if someone has /home + * or / as home directory... --marekm + */ + setpwent(); + while ((pwd = getpwent())) { + if (strcmp(pwd->pw_name, user_name) == 0) + continue; + + if (path_prefix(user_home, pwd->pw_dir)) { + fprintf(stderr, + _("%s: not removing directory %s (would remove home of user %s)\n"), + Prog, user_home, pwd->pw_name); + + rflg = 0; + errors++; + break; + } + } + } +#endif + + if (rflg) { + if (remove_tree(user_home) || rmdir(user_home)) { + fprintf(stderr, _("%s: error removing directory %s\n"), + Prog, user_home); + + errors++; + } + } + + /* + * Cancel any crontabs or at jobs. Have to do this before we + * remove the entry from /etc/passwd. + */ + + user_cancel(user_name); + + close_files (); + + exit(errors ? E_HOMEDIR : E_SUCCESS); + /*NOTREACHED*/ +} diff --git a/src/usermod.c b/src/usermod.c new file mode 100644 index 00000000..915cb3a7 --- /dev/null +++ b/src/usermod.c @@ -0,0 +1,1664 @@ +/* + * Copyright 1991 - 1994, Julianne Frances Haugh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Julianne F. Haugh nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: usermod.c,v 1.17 1999/06/07 16:40:45 marekm Exp $") + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "prototypes.h" +#include "defines.h" +#include "chkname.h" +#include "faillog.h" +#if HAVE_LASTLOG_H +#include +#else +#include "lastlog_.h" +#endif +#include "pwauth.h" +#include "getdef.h" + +/* + * exit status values + * for E_GRP_UPDATE and E_NOSPACE (not used yet), other update requests + * will be implemented (as documented in the Solaris 2.x man page). + */ +#define E_SUCCESS 0 /* success */ +#define E_PW_UPDATE 1 /* can't update password file */ +#define E_USAGE 2 /* invalid command syntax */ +#define E_BAD_ARG 3 /* invalid argument to option */ +#define E_UID_IN_USE 4 /* uid already in use (and no -o) */ +/* #define E_BAD_PWFILE 5 */ /* passwd file contains errors */ +#define E_NOTFOUND 6 /* specified user/group doesn't exist */ +#define E_USER_BUSY 8 /* user to modify is logged in */ +#define E_NAME_IN_USE 9 /* username already in use */ +#define E_GRP_UPDATE 10 /* can't update group file */ +/* #define E_NOSPACE 11 */ /* insufficient space to move home dir */ +#define E_HOMEDIR 12 /* unable to complete home dir move */ + +#define VALID(s) (strcspn (s, ":\n") == strlen (s)) + +static char *user_name; +static char *user_newname; +static char *user_pass; +static uid_t user_id; +static uid_t user_newid; +static gid_t user_gid; +static gid_t user_newgid; +static char *user_comment; +static char *user_home; +static char *user_newhome; +static char *user_shell; +#ifdef SHADOWPWD +static long user_expire; +static long user_inactive; +#endif +static char *user_groups[NGROUPS_MAX+1]; /* NULL-terminated list */ + +static char *Prog; + +#ifdef AUTH_METHODS +static char *auth_arg; +static char user_auth[BUFSIZ]; +static int Aflg = 0; /* specify user defined authentication method */ +#else +#define Aflg 0 +#endif + +static int + uflg = 0, /* specify new user ID */ + oflg = 0, /* permit non-unique user ID to be specified with -u */ + gflg = 0, /* new primary group ID */ + Gflg = 0, /* new secondary group set */ + dflg = 0, /* new home directory */ + sflg = 0, /* new shell program */ + cflg = 0, /* new comment (GECOS) field */ + mflg = 0, /* create user's home directory if it doesn't exist */ +#ifdef SHADOWPWD + fflg = 0, /* days until account with expired password is locked */ + eflg = 0, /* days since 1970-01-01 when account becomes expired */ +#endif + pflg = 0, /* new encrypted password */ + lflg = 0; /* new user name */ + +#ifdef NDBM +extern int pw_dbm_mode; +#ifdef SHADOWPWD +extern int sp_dbm_mode; +#endif +extern int gr_dbm_mode; +#ifdef SHADOWGRP +extern int sg_dbm_mode; +#endif +#endif + +#ifdef SHADOWPWD +static int is_shadow_pwd; +#endif +#ifdef SHADOWGRP +static int is_shadow_grp; +#endif + +#include "groupio.h" + +#ifdef SHADOWGRP +#include "sgroupio.h" +#endif + +#include "pwio.h" + +#ifdef SHADOWPWD +#include "shadowio.h" +#endif + +extern char *optarg; +extern int optind; + +/* local function prototypes */ +static int get_groups P_((char *)); +static void usage P_((void)); +static void new_pwent P_((struct passwd *)); +#ifdef SHADOWPWD +static void new_spent P_((struct spwd *)); +#endif +static void fail_exit P_((int)); +static int update_group P_((void)); +#ifdef SHADOWGRP +static int update_gshadow P_((void)); +#endif +static int grp_update P_((void)); +#ifdef AUTH_METHODS +static char *get_password P_((const char *)); +static void split_auths P_((char *, char **)); +static void update_auths P_((const char *, const char *, char *)); +static void add_auths P_((const char *, const char *, char *)); +static void delete_auths P_((const char *, const char *, char *)); +static void convert_auth P_((char *, const char *, const char *)); +static int valid_auth P_((const char *)); +#endif +static long get_number P_((const char *)); +static void process_flags P_((int, char **)); +static void close_files P_((void)); +static void open_files P_((void)); +static void usr_update P_((void)); +static void move_home P_((void)); +static void update_files P_((void)); +#ifndef NO_MOVE_MAILBOX +static void move_mailbox P_((void)); +#endif +int main P_((int, char **)); + +/* Had to move this over from useradd.c since we have groups named + * "56k-family"... ergh. + * --Pac. */ +static struct group * +getgr_nam_gid(const char *name) +{ + gid_t gid; + char *ep; + + gid = strtol(name, &ep, 10); + if (*name != '\0' && *ep == '\0') /* valid numeric gid */ + return getgrgid(gid); + + return getgrnam(name); +} + + +/* + * get_groups - convert a list of group names to an array of group IDs + * + * get_groups() takes a comma-separated list of group names and + * converts it to a NULL-terminated array. Any unknown group + * names are reported as errors. + */ + +static int +get_groups(char *list) +{ + char *cp; + const struct group *grp; + int errors = 0; + int ngroups = 0; + + /* + * Initialize the list to be empty + */ + + user_groups[0] = (char *) 0; + + if (! *list) + return 0; + + /* + * So long as there is some data to be converted, strip off + * each name and look it up. A mix of numerical and string + * values for group identifiers is permitted. + */ + + do { + /* + * Strip off a single name from the list + */ + if ((cp = strchr (list, ','))) + *cp++ = '\0'; + + /* + * Names starting with digits are treated as numerical + * GID values, otherwise the string is looked up as is. + */ + grp = getgr_nam_gid(list); + + /* + * There must be a match, either by GID value or by + * string name. + */ + if (!grp) { + fprintf(stderr, _("%s: unknown group %s\n"), + Prog, list); + errors++; + } + list = cp; + + /* + * If the group doesn't exist, don't dump core... + * Instead, try the next one. --marekm + */ + if (! grp) + continue; + +#ifdef USE_NIS + /* + * Don't add this group if they are an NIS group. Tell + * the user to go to the server for this group. + */ + + if (__isgrNIS ()) { + fprintf(stderr, _("%s: group `%s' is a NIS group.\n"), + Prog, grp->gr_name); + continue; + } +#endif + + if (ngroups == NGROUPS_MAX) { + fprintf(stderr, + _("%s: too many groups specified (max %d).\n"), + Prog, ngroups); + break; + } + + /* + * Add the group name to the user's list of groups. + */ + + user_groups[ngroups++] = xstrdup(grp->gr_name); + } while (list); + + user_groups[ngroups] = (char *) 0; + + /* + * Any errors in finding group names are fatal + */ + + if (errors) + return -1; + + return 0; +} + +/* + * usage - display usage message and exit + */ + +static void +usage(void) +{ + fprintf(stderr, + _("usage: %s\t[-u uid [-o]] [-g group] [-G group,...] \n"), + Prog); + fprintf(stderr, + _("\t\t[-d home [-m]] [-s shell] [-c comment] [-l new_name]\n")); + fprintf(stderr, "\t\t"); +#ifdef SHADOWPWD + fprintf(stderr, _("[-f inactive] [-e expire ] ")); +#endif +#ifdef AUTH_METHODS + fprintf(stderr, _("[-A {DEFAULT|program},... ] ")); +#endif + fprintf(stderr, _("[-p passwd] name\n")); + exit(E_USAGE); +} + +/* + * new_pwent - initialize the values in a password file entry + * + * new_pwent() takes all of the values that have been entered and + * fills in a (struct passwd) with them. + */ + +static void +new_pwent(struct passwd *pwent) +{ + if (lflg) { + SYSLOG((LOG_INFO, "change user name `%s' to `%s'\n", + pwent->pw_name, user_newname)); + pwent->pw_name = xstrdup (user_newname); + } +#ifdef SHADOWPWD + if (!is_shadow_pwd) +#endif + if (pflg) { + SYSLOG((LOG_INFO, "change user `%s' password\n", + pwent->pw_name)); + pwent->pw_passwd = xstrdup(user_pass); + } + if (uflg) { + SYSLOG((LOG_INFO, "change user `%s' UID from `%d' to `%d'\n", + pwent->pw_name, pwent->pw_uid, user_newid)); + pwent->pw_uid = user_newid; + } + if (gflg) { + SYSLOG((LOG_INFO, "change user `%s' GID from `%d' to `%d'\n", + pwent->pw_name, pwent->pw_gid, user_newgid)); + pwent->pw_gid = user_newgid; + } + if (cflg) + pwent->pw_gecos = user_comment; + + if (dflg) { + SYSLOG((LOG_INFO, "change user `%s' home from `%s' to `%s'\n", + pwent->pw_name, pwent->pw_dir, user_newhome)); + pwent->pw_dir = user_newhome; + } + if (sflg) { + SYSLOG((LOG_INFO, "change user `%s' shell from `%s' to `%s'\n", + pwent->pw_name, pwent->pw_shell, user_shell)); + pwent->pw_shell = user_shell; + } +} + +#ifdef SHADOWPWD +/* + * new_spent - initialize the values in a shadow password file entry + * + * new_spent() takes all of the values that have been entered and + * fills in a (struct spwd) with them. + */ + +static void +new_spent(struct spwd *spent) +{ + if (lflg) + spent->sp_namp = xstrdup (user_newname); + + if (fflg) { + SYSLOG((LOG_INFO, + "change user `%s' inactive from `%ld' to `%ld'\n", + spent->sp_namp, spent->sp_inact, user_inactive)); + spent->sp_inact = user_inactive; + } + if (eflg) { + /* XXX - dates might be better than numbers of days. --marekm */ + SYSLOG((LOG_INFO, + "change user `%s' expiration from `%ld' to `%ld'\n", + spent->sp_namp, spent->sp_expire, user_expire)); + spent->sp_expire = user_expire; + } + if (pflg) { + SYSLOG((LOG_INFO, "change user `%s' password\n", + spent->sp_namp)); + spent->sp_pwdp = xstrdup(user_pass); + } +} +#endif /* SHADOWPWD */ + +/* + * fail_exit - exit with an error code after unlocking files + */ + +static void +fail_exit(int code) +{ + (void) gr_unlock (); +#ifdef SHADOWGRP + if (is_shadow_grp) + sgr_unlock (); +#endif +#ifdef SHADOWPWD + if (is_shadow_pwd) + spw_unlock (); +#endif + (void) pw_unlock (); + exit(code); +} + + +static int +update_group(void) +{ + int is_member; + int was_member; + int changed; + const struct group *grp; + struct group *ngrp; + + /* + * Lock and open the group file. This will load all of the group + * entries. + */ + if (! gr_lock ()) { + fprintf(stderr, _("%s: error locking group file\n"), Prog); + SYSLOG((LOG_ERR, "error locking group file")); + return -1; + } + if (! gr_open (O_RDWR)) { + fprintf(stderr, _("%s: error opening group file\n"), Prog); + SYSLOG((LOG_ERR, "error opening group file")); + gr_unlock(); + return -1; + } + + changed = 0; + + /* + * Scan through the entire group file looking for the groups that + * the user is a member of. + */ + while ((grp = gr_next())) { + + /* + * See if the user specified this group as one of their + * concurrent groups. + */ + was_member = is_on_list(grp->gr_mem, user_name); + is_member = Gflg && is_on_list(user_groups, grp->gr_name); + + if (!was_member && !is_member) + continue; + + ngrp = __gr_dup(grp); + if (!ngrp) { + fprintf(stderr, + _("%s: out of memory in update_group\n"), + Prog); + gr_unlock(); + return -1; + } + + if (was_member && (!Gflg || is_member)) { + if (lflg) { + ngrp->gr_mem = del_list(ngrp->gr_mem, + user_name); + ngrp->gr_mem = add_list(ngrp->gr_mem, + user_newname); + changed = 1; + SYSLOG((LOG_INFO, + "change `%s' to `%s' in group `%s'\n", + user_name, user_newname, + ngrp->gr_name)); + } + } else if (was_member && Gflg && !is_member) { + ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); + changed = 1; + SYSLOG((LOG_INFO, "delete `%s' from group `%s'\n", + user_name, ngrp->gr_name)); + } else if (!was_member && Gflg && is_member) { + ngrp->gr_mem = add_list (ngrp->gr_mem, + lflg ? user_newname:user_name); + changed = 1; + SYSLOG((LOG_INFO, "add `%s' to group `%s'\n", + lflg ? user_newname:user_name, ngrp->gr_name)); + } + if (!changed) + continue; + + changed = 0; + if (! gr_update (ngrp)) { + fprintf(stderr, _("%s: error adding new group entry\n"), + Prog); + SYSLOG((LOG_ERR, "error adding group entry")); + gr_unlock(); + return -1; + } +#ifdef NDBM + /* + * Update the DBM group file with the new entry as well. + */ + if (! gr_dbm_update (ngrp)) { + fprintf(stderr, + _("%s: cannot add new dbm group entry\n"), + Prog); + SYSLOG((LOG_ERR, "error adding dbm group entry")); + gr_unlock(); + return -1; + } +#endif /* NDBM */ + } +#ifdef NDBM + endgrent (); +#endif /* NDBM */ + if (!gr_close()) { + fprintf(stderr, _("%s: cannot rewrite group file\n"), + Prog); + gr_unlock(); + return -1; + } + gr_unlock(); + return 0; +} + +#ifdef SHADOWGRP +static int +update_gshadow(void) +{ + int is_member; + int was_member; + int was_admin; + int changed; + const struct sgrp *sgrp; + struct sgrp *nsgrp; + + if (!sgr_lock()) { + fprintf(stderr, _("%s: error locking shadow group file\n"), + Prog); + SYSLOG((LOG_ERR, "error locking shadow group file")); + return -1; + } + if (!sgr_open(O_RDWR)) { + fprintf(stderr, _("%s: error opening shadow group file\n"), + Prog); + SYSLOG((LOG_ERR, "error opening shadow group file")); + sgr_unlock(); + return -1; + } + + changed = 0; + + /* + * Scan through the entire shadow group file looking for the groups + * that the user is a member of. + */ + while ((sgrp = sgr_next())) { + + /* + * See if the user was a member of this group + */ + was_member = is_on_list(sgrp->sg_mem, user_name); + + /* + * See if the user was an administrator of this group + */ + was_admin = is_on_list(sgrp->sg_adm, user_name); + + /* + * See if the user specified this group as one of their + * concurrent groups. + */ + is_member = Gflg && is_on_list(user_groups, sgrp->sg_name); + + if (!was_member && !was_admin && !is_member) + continue; + + nsgrp = __sgr_dup(sgrp); + if (!nsgrp) { + fprintf(stderr, + _("%s: out of memory in update_gshadow\n"), + Prog); + sgr_unlock(); + return -1; + } + + if (was_admin && lflg) { + nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); + nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); + changed = 1; + SYSLOG((LOG_INFO, + "change admin `%s' to `%s' in shadow group `%s'\n", + user_name, user_newname, nsgrp->sg_name)); + } + if (was_member && (!Gflg || is_member)) { + if (lflg) { + nsgrp->sg_mem = del_list (nsgrp->sg_mem, + user_name); + nsgrp->sg_mem = add_list (nsgrp->sg_mem, + user_newname); + changed = 1; + SYSLOG((LOG_INFO, + "change `%s' to `%s' in shadow group `%s'\n", + user_name, user_newname, nsgrp->sg_name)); + } + } else if (was_member && Gflg && !is_member) { + nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); + changed = 1; + SYSLOG((LOG_INFO, + "delete `%s' from shadow group `%s'\n", + user_name, nsgrp->sg_name)); + } else if (!was_member && Gflg && is_member) { + nsgrp->sg_mem = add_list (nsgrp->sg_mem, + lflg ? user_newname:user_name); + changed = 1; + SYSLOG((LOG_INFO, "add `%s' to shadow group `%s'\n", + lflg ? user_newname:user_name,nsgrp->sg_name)); + } + if (!changed) + continue; + + changed = 0; + + /* + * Update the group entry to reflect the changes. + */ + if (! sgr_update (nsgrp)) { + fprintf(stderr, + _("%s: error adding new group entry\n"), + Prog); + SYSLOG((LOG_ERR, "error adding shadow group entry\n")); + sgr_unlock(); + return -1; + } +#ifdef NDBM + /* + * Update the DBM group file with the new entry as well. + */ + if (! sg_dbm_update (nsgrp)) { + fprintf(stderr, + _("%s: cannot add new dbm group entry\n"), + Prog); + SYSLOG((LOG_ERR, + "error adding dbm shadow group entry\n")); + sgr_unlock(); + return -1; + } +#endif /* NDBM */ + } +#ifdef NDBM + endsgent (); +#endif /* NDBM */ + if (!sgr_close()) { + fprintf(stderr, _("%s: cannot rewrite shadow group file\n"), + Prog); + sgr_unlock(); + return -1; + } + sgr_unlock(); + return 0; +} +#endif /* SHADOWGRP */ + +/* + * grp_update - add user to secondary group set + * + * grp_update() takes the secondary group set given in user_groups + * and adds the user to each group given by that set. + */ + +static int +grp_update(void) +{ + int ret; + + ret = update_group(); +#ifdef SHADOWGRP + if (!ret && is_shadow_grp) + ret = update_gshadow(); +#endif + return ret; +} + +#ifdef AUTH_METHODS +/* + * get_password - locate encrypted password in authentication list + */ + +static char * +get_password(const char *list) +{ + char *cp, *end; + static char buf[257]; + + strcpy (buf, list); + for (cp = buf;cp;cp = end) { + if ((end = strchr (cp, ';'))) + *end++ = 0; + + if (cp[0] == '@') + continue; + + return cp; + } + return (char *) 0; +} + +/* + * split_auths - break up comma list into (char *) array + */ + +static void +split_auths(char *list, char **array) +{ + char *cp, *end; + int i = 0; + + for (cp = list;cp;cp = end) { + if ((end = strchr (cp, ';'))) + *end++ = '\0'; + + array[i++] = cp; + } + array[i] = 0; +} + +/* + * update_auths - find list of methods to update + */ + +static void +update_auths(const char *old, const char *new, char *update) +{ + char oldbuf[257], newbuf[257]; + char *oldv[32], *newv[32], *updatev[32]; + int i, j, k; + + strcpy (oldbuf, old); + split_auths (oldbuf, oldv); + + strcpy (newbuf, new); + split_auths (newbuf, newv); + + for (i = j = k = 0;oldv[i];i++) { + for (j = 0;newv[j];j++) + if (strcmp (oldv[i], newv[j]) != 0) + break; + + if (newv[j] != (char *) 0) + updatev[k++] = oldv[i]; + } + updatev[k] = 0; + + update[0] = '\0'; + for (i = 0;updatev[i];i++) { + if (i) + strcat (update, ";"); + + strcat (update, updatev[i]); + } +} + +/* + * add_auths - find list of methods to add + */ + +static void +add_auths(const char *old, const char *new, char *add) +{ + char oldbuf[257], newbuf[257]; + char *oldv[32], *newv[32], *addv[32]; + int i, j, k; + + strcpy (oldbuf, old); + split_auths (oldbuf, oldv); + + strcpy (newbuf, new); + split_auths (newbuf, newv); + + for (i = j = k = 0;newv[i];i++) { + for (j = 0;oldv[j];j++) + if (strcmp (oldv[i], newv[j]) == 0) + break; + + if (oldv[j] == (char *) 0) + addv[k++] = newv[i]; + } + addv[k] = 0; + + add[0] = '\0'; + for (i = 0;addv[i];i++) { + if (i) + strcat (add, ";"); + + strcat (add, addv[i]); + } +} + +/* + * delete_auths - find list of methods to delete + */ + +static void +delete_auths(const char *old, const char *new, char *remove) +{ + char oldbuf[257], newbuf[257]; + char *oldv[32], *newv[32], *removev[32]; + int i, j, k; + + strcpy (oldbuf, old); + split_auths (oldbuf, oldv); + + strcpy (newbuf, new); + split_auths (newbuf, newv); + + for (i = j = k = 0;oldv[i];i++) { + for (j = 0;newv[j];j++) + if (strcmp (oldv[i], newv[j]) == 0) + break; + + if (newv[j] == (char *) 0) + removev[k++] = oldv[i]; + } + removev[k] = 0; + + remove[0] = '\0'; + for (i = 0;removev[i];i++) { + if (i) + strcat (remove, ";"); + + strcat (remove, removev[i]); + } +} + +/* + * convert_auth - convert the argument list to a authentication list + */ + +static void +convert_auth(char *auths, const char *oldauths, const char *list) +{ + char *cp, *end; + char *old; + char buf[257]; + + /* + * Copy each method. DEFAULT is replaced by an encrypted string + * if one can be found in the current authentication list. + */ + + strcpy (buf, list); + auths[0] = '\0'; + for (cp = buf;cp;cp = end) { + if (auths[0]) + strcat (auths, ";"); + + if ((end = strchr (cp, ','))) + *end++ = '\0'; + + if (strcmp (cp, "DEFAULT") == 0) { + if ((old = get_password (oldauths))) + strcat (auths, old); + else + strcat (auths, "!"); + } else { + strcat (auths, "@"); + strcat (auths, cp); + } + } +} + +/* + * valid_auth - check authentication list for validity + */ + +static int +valid_auth(const char *methods) +{ + char *cp, *end; + char buf[257]; + int default_cnt = 0; + + /* + * Cursory checks, length and illegal characters + */ + + if ((int) strlen (methods) > 256) + return 0; + + if (! VALID (methods)) + return 0; + + /* + * Pick each method apart and check it. + */ + + strcpy (buf, methods); + for (cp = buf;cp;cp = end) { + if ((end = strchr (cp, ','))) + *end++ = '\0'; + + if (strcmp (cp, "DEFAULT") == 0) { + if (default_cnt++ > 0) + return 0; + } + } + return 1; +} +#endif + +static long +get_number(const char *cp) +{ + long val; + char *ep; + + val = strtol(cp, &ep, 10); + if (*cp != '\0' && *ep == '\0') /* valid number */ + return val; + + fprintf(stderr, _("%s: invalid numeric argument `%s'\n"), Prog, cp); + exit(E_BAD_ARG); +} + +/* + * process_flags - perform command line argument setting + * + * process_flags() interprets the command line arguments and sets + * the values that the user will be created with accordingly. The + * values are checked for sanity. + */ + +static void +process_flags(int argc, char **argv) +{ + const struct group *grp; + const struct passwd *pwd; +#ifdef SHADOWPWD + const struct spwd *spwd = NULL; +#endif + int anyflag = 0; + int arg; + + if (argc == 1 || argv[argc - 1][0] == '-') + usage (); + + if (! (pwd = getpwnam (argv[argc - 1]))) { + fprintf(stderr, _("%s: user %s does not exist\n"), + Prog, argv[argc - 1]); + exit(E_NOTFOUND); + } + user_name = argv[argc - 1]; + +#ifdef USE_NIS + + /* + * Now make sure it isn't an NIS user. + */ + + if (__ispwNIS ()) { + char *nis_domain; + char *nis_master; + + fprintf(stderr, _("%s: user %s is a NIS user\n"), + Prog, user_name); + + if (! yp_get_default_domain (&nis_domain) && + ! yp_master (nis_domain, "passwd.byname", + &nis_master)) { + fprintf(stderr, _("%s: %s is the NIS master\n"), + Prog, nis_master); + } + exit(E_NOTFOUND); + } +#endif + user_id = pwd->pw_uid; + user_gid = pwd->pw_gid; + user_comment = xstrdup(pwd->pw_gecos); + user_home = xstrdup(pwd->pw_dir); + user_shell = xstrdup(pwd->pw_shell); + +#ifdef SHADOWPWD + if (is_shadow_pwd && (spwd = getspnam (user_name))) { + user_expire = spwd->sp_expire; + user_inactive = spwd->sp_inact; + } +#endif +#ifdef SHADOWPWD +#define FLAGS "A:u:og:G:d:s:c:mf:e:l:p:" +#else +#define FLAGS "A:u:og:G:d:s:c:ml:p:" +#endif + while ((arg = getopt(argc, argv, FLAGS)) != EOF) { +#undef FLAGS + switch (arg) { +#ifdef AUTH_METHODS + case 'A': + if (! valid_auth (optarg)) { + fprintf(stderr, + _("%s: invalid field `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + auth_arg = optarg; + Aflg++; + break; +#endif + case 'c': + if (! VALID (optarg)) { + fprintf(stderr, + _("%s: invalid field `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + user_comment = optarg; + cflg++; + break; + case 'd': + if (! VALID (optarg)) { + fprintf(stderr, + _("%s: invalid field `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + dflg++; + user_newhome = optarg; + break; +#ifdef SHADOWPWD + case 'e': + if (*optarg) { + user_expire = strtoday(optarg); + if (user_expire == -1) { + fprintf(stderr, + _("%s: invalid date `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + user_expire *= DAY/SCALE; + } else + user_expire = -1; + eflg++; + break; + case 'f': + user_inactive = get_number(optarg); + fflg++; + break; +#endif + case 'g': + grp = getgr_nam_gid(optarg); + if (!grp) { + fprintf(stderr, + _("%s: unknown group %s\n"), + Prog, optarg); + exit(E_NOTFOUND); + } + user_newgid = grp->gr_gid; + gflg++; + break; + case 'G': + if (get_groups(optarg)) + exit(E_NOTFOUND); + Gflg++; + break; + case 'l': + if (!check_user_name(optarg)) { + fprintf(stderr, + _("%s: invalid field `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + + /* + * If the name does not really change, we + * mustn't set the flag as this will cause + * rather serious problems later! + */ + + if (strcmp (user_name, optarg)) + lflg++; + + user_newname = optarg; + break; + case 'm': + if (! dflg) + usage (); + + mflg++; + break; + case 'o': + if (! uflg) + usage (); + + oflg++; + break; + case 'p': + user_pass = optarg; + pflg++; + break; + case 's': + if (! VALID (optarg)) { + fprintf(stderr, + _("%s: invalid field `%s'\n"), + Prog, optarg); + exit(E_BAD_ARG); + } + user_shell = optarg; + sflg++; + break; + case 'u': + user_newid = get_number(optarg); + uflg++; + break; + default: + usage (); + } + anyflag++; + } + if (anyflag == 0) { + fprintf(stderr, _("%s: no flags given\n"), Prog); + exit(E_USAGE); + } + +#ifdef SHADOWPWD + if (!is_shadow_pwd && (eflg || fflg)) { + fprintf(stderr, + _("%s: shadow passwords required for -e and -f\n"), + Prog); + exit(E_USAGE); + } +#endif + + if (optind != argc - 1) + usage (); + + if (dflg && strcmp (user_home, user_newhome) == 0) + dflg = mflg = 0; + + if (uflg && user_id == user_newid) + uflg = oflg = 0; + + if (lflg && getpwnam (user_newname)) { + fprintf(stderr, _("%s: user %s exists\n"), Prog, user_newname); + exit(E_NAME_IN_USE); + } + + if (uflg && !oflg && getpwuid(user_newid)) { + fprintf(stderr, _("%s: uid %ld is not unique\n"), + Prog, (long) user_newid); + exit(E_UID_IN_USE); + } +} + +/* + * close_files - close all of the files that were opened + * + * close_files() closes all of the files that were opened for this + * new user. This causes any modified entries to be written out. + */ + +static void +close_files(void) +{ + if (! pw_close ()) { + fprintf(stderr, _("%s: cannot rewrite password file\n"), Prog); + fail_exit(E_PW_UPDATE); + } +#ifdef SHADOWPWD + if (is_shadow_pwd && ! spw_close ()) { + fprintf(stderr, _("%s: cannot rewrite shadow password file\n"), + Prog); + fail_exit(E_PW_UPDATE); + } +#endif +#ifdef SHADOWPWD + if (is_shadow_pwd) + spw_unlock (); +#endif + (void) pw_unlock (); + + /* + * Close the DBM and/or flat files + */ + + endpwent (); +#ifdef SHADOWPWD + endspent (); +#endif + endgrent (); +#ifdef SHADOWGRP + endsgent (); +#endif +} + +/* + * open_files - lock and open the password files + * + * open_files() opens the two password files. + */ + +static void +open_files(void) +{ + if (!pw_lock()) { + fprintf(stderr, _("%s: unable to lock password file\n"), Prog); + exit(E_PW_UPDATE); + } + if (! pw_open (O_RDWR)) { + fprintf(stderr, _("%s: unable to open password file\n"), Prog); + fail_exit(E_PW_UPDATE); + } +#ifdef SHADOWPWD + if (is_shadow_pwd && ! spw_lock ()) { + fprintf(stderr, _("%s: cannot lock shadow password file\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + if (is_shadow_pwd && ! spw_open (O_RDWR)) { + fprintf(stderr, _("%s: cannot open shadow password file\n"), + Prog); + fail_exit(E_PW_UPDATE); + } +#endif +} + +/* + * usr_update - create the user entries + * + * usr_update() creates the password file entries for this user + * and will update the group entries if required. + */ + +static void +usr_update(void) +{ + struct passwd pwent; + const struct passwd *pwd; +#ifdef SHADOWPWD + struct spwd spent; + const struct spwd *spwd = NULL; +#endif +#ifdef AUTH_METHODS + char old_auth[BUFSIZ]; + char auth_buf[BUFSIZ]; +#endif + + /* + * Locate the entry in /etc/passwd, which MUST exist. + */ + + pwd = pw_locate(user_name); + if (!pwd) { + fprintf(stderr, _("%s: %s not found in /etc/passwd\n"), + Prog, user_name); + fail_exit(E_NOTFOUND); + } + pwent = *pwd; + new_pwent (&pwent); + +#ifdef SHADOWPWD + + /* + * Locate the entry in /etc/shadow. It doesn't have to + * exist, and won't be created if it doesn't. + */ + + if (is_shadow_pwd && (spwd = spw_locate(user_name))) { + spent = *spwd; + new_spent (&spent); + } +#endif + +#ifdef AUTH_METHODS + +#ifdef SHADOWPWD + strcpy (old_auth, spwd ? spent.sp_pwdp : pwent.pw_passwd); +#else + strcpy (old_auth, pwent.pw_passwd); +#endif + + if (Aflg) + convert_auth (user_auth, old_auth, auth_arg); + + /* + * XXX - this code needs some checking, changing the user name with + * "usermod -l new old" clears the password for this user :-(. + * For now, just don't define AUTH_METHODS and all will be well. + * Most programs don't support "administrator defined authentication + * methods" and PAM (when done) will be better anyway :-). --marekm + */ + if (lflg || (Aflg && strcmp (old_auth, user_auth) != 0)) { + delete_auths (old_auth, user_auth, auth_buf); + if (auth_buf[0] && pw_auth (auth_buf, user_name, + PW_DELETE, (char *) 0)) { + fprintf(stderr, + _("%s: error deleting authentication method\n"), + Prog); + SYSLOG((LOG_ERR, "error deleting auth for `%s'\n", + user_name)); + fail_exit(E_PW_UPDATE); + } + add_auths (old_auth, user_auth, auth_buf); + if (auth_buf[0] == '@' && pw_auth (auth_buf, + lflg ? user_newname:user_name, PW_ADD, (char *) 0)) { + fprintf(stderr, + _("%s: error adding authentication method\n"), + Prog); + SYSLOG((LOG_ERR, "error adding auth for `%s'\n", + lflg ? user_newname:user_name)); + fail_exit(E_PW_UPDATE); + } + update_auths (old_auth, user_auth, auth_buf); + if (lflg && auth_buf[0] == '@' && pw_auth (auth_buf, + user_newname, PW_CHANGE, user_name)) { + fprintf(stderr, + _("%s: error changing authentication method\n"), + Prog); + SYSLOG((LOG_ERR, "error changing auth for `%s'\n", + lflg ? user_newname:user_name)); + fail_exit(E_PW_UPDATE); + } +#ifdef SHADOWPWD + if (spwd) + spent.sp_pwdp = user_auth; + else +#endif + pwent.pw_passwd = user_auth; + } +#endif /* AUTH_METHODS */ + if (lflg || uflg || gflg || cflg || dflg || sflg || Aflg || pflg) { + if (! pw_update (&pwent)) { + fprintf(stderr, + _("%s: error changing password entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + if (lflg && ! pw_remove (user_name)) { + fprintf(stderr, + _("%s: error removing password entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } +#ifdef NDBM + if (pw_dbm_present()) { + if (! pw_dbm_update (&pwent)) { + fprintf(stderr, + _("%s: error adding password dbm entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + if (lflg && (pwd = getpwnam (user_name)) && + ! pw_dbm_remove (pwd)) { + fprintf(stderr, + _("%s: error removing passwd dbm entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + } +#endif + } +#ifdef SHADOWPWD + if (spwd && (lflg || eflg || fflg || Aflg || pflg)) { + if (! spw_update (&spent)) { + fprintf(stderr, + _("%s: error adding new shadow password entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + if (lflg && ! spw_remove (user_name)) { + fprintf(stderr, + _("%s: error removing shadow password entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + } +#ifdef NDBM + if (spwd && sp_dbm_present()) { + if (! sp_dbm_update (&spent)) { + fprintf(stderr, + _("%s: error updating shadow passwd dbm entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + if (lflg && ! sp_dbm_remove (user_name)) { + fprintf(stderr, + _("%s: error removing shadow passwd dbm entry\n"), + Prog); + fail_exit(E_PW_UPDATE); + } + } +#endif /* NDBM */ +#endif /* SHADOWPWD */ +} + +/* + * move_home - move the user's home directory + * + * move_home() moves the user's home directory to a new location. + * The files will be copied if the directory cannot simply be + * renamed. + */ + +static void +move_home(void) +{ + struct stat sb; + + if (mflg && stat (user_home, &sb) == 0) { + /* + * Don't try to move it if it is not a directory + * (but /dev/null for example). --marekm + */ + if (!S_ISDIR(sb.st_mode)) + return; + + if (access(user_newhome, F_OK) == 0) { + fprintf(stderr, _("%s: directory %s exists\n"), + Prog, user_newhome); + fail_exit(E_HOMEDIR); + } else if (rename (user_home, user_newhome)) { + if (errno == EXDEV) { + if (mkdir (user_newhome, sb.st_mode & 0777)) { + fprintf(stderr, + _("%s: can't create %s\n"), + Prog, user_newhome); + } + if (chown (user_newhome, + sb.st_uid, sb.st_gid)) { + fprintf(stderr, + _("%s: can't chown %s\n"), + Prog, user_newhome); + rmdir (user_newhome); + fail_exit(E_HOMEDIR); + } + if (copy_tree (user_home, user_newhome, + uflg ? user_newid:-1, + gflg ? user_newgid:-1) == 0 && + remove_tree (user_home) == 0 && + rmdir (user_home) == 0) + return; + + (void) remove_tree (user_newhome); + (void) rmdir (user_newhome); + } + fprintf(stderr, + _("%s: cannot rename directory %s to %s\n"), + Prog, user_home, user_newhome); + fail_exit(E_HOMEDIR); + } + } + if (uflg || gflg) + chown (dflg ? user_newhome:user_home, + uflg ? user_newid:user_id, + gflg ? user_newgid:user_gid); +} + +/* + * update_files - update the lastlog and faillog files + */ + +static void +update_files(void) +{ + struct lastlog ll; + struct faillog fl; + int fd; + + /* + * Relocate the "lastlog" entries for the user. The old entry + * is left alone in case the UID was shared. It doesn't hurt + * anything to just leave it be. + */ + + if ((fd = open(LASTLOG_FILE, O_RDWR)) != -1) { + lseek(fd, (off_t) user_id * sizeof ll, SEEK_SET); + if (read(fd, (char *) &ll, sizeof ll) == sizeof ll) { + lseek(fd, (off_t) user_newid * sizeof ll, SEEK_SET); + write(fd, (char *) &ll, sizeof ll); + } + close(fd); + } + + /* + * Relocate the "faillog" entries in the same manner. + */ + + if ((fd = open(FAILLOG_FILE, O_RDWR)) != -1) { + lseek(fd, (off_t) user_id * sizeof fl, SEEK_SET); + if (read(fd, (char *) &fl, sizeof fl) == sizeof fl) { + lseek(fd, (off_t) user_newid * sizeof fl, SEEK_SET); + write(fd, (char *) &fl, sizeof fl); + } + close(fd); + } +} + +#ifndef NO_MOVE_MAILBOX +/* + * This is the new and improved code to carefully chown/rename the user's + * mailbox. Maybe I am too paranoid but the mail spool dir sometimes + * happens to be mode 1777 (this makes mail user agents work without + * being setgid mail, but is NOT recommended; they all should be fixed + * to use movemail). --marekm + */ +static void +move_mailbox(void) +{ + const char *maildir; + char mailfile[1024], newmailfile[1024]; + int fd; + struct stat st; + + maildir = getdef_str("MAIL_DIR"); +#ifdef MAIL_SPOOL_DIR + if (!maildir && !getdef_str("MAIL_FILE")) + maildir = MAIL_SPOOL_DIR; +#endif + if (!maildir) + return; + + /* + * O_NONBLOCK is to make sure open won't hang on mandatory locks. + * We do fstat/fchown to make sure there are no races (someone + * replacing /var/spool/mail/luser with a hard link to /etc/passwd + * between stat and chown). --marekm + */ + + snprintf(mailfile, sizeof mailfile, "%s/%s", maildir, user_name); + fd = open(mailfile, O_RDONLY | O_NONBLOCK, 0); + if (fd < 0) { + /* no need for warnings if the mailbox doesn't exist */ + if (errno != ENOENT) + perror(mailfile); + return; + } + if (fstat(fd, &st) < 0) { + perror("fstat"); + close(fd); + return; + } + if (st.st_uid != user_id) { + /* better leave it alone */ + fprintf(stderr, _("%s: warning: %s not owned by %s\n"), + Prog, mailfile, user_name); + close(fd); + return; + } + if (uflg && fchown(fd, user_newid, (gid_t) -1) < 0) + perror(_("failed to change mailbox owner")); + + close(fd); + + if (lflg) { + snprintf(newmailfile, sizeof newmailfile, "%s/%s", maildir, user_newname); + if (link(mailfile, newmailfile) || unlink(mailfile)) + perror(_("failed to rename mailbox")); + } +} +#endif + +/* + * main - usermod command + */ + +int +main(int argc, char **argv) +{ + int grp_err = 0; + + /* + * Get my name so that I can use it to report errors. + */ + Prog = Basename(argv[0]); + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH); + +#ifdef SHADOWPWD + is_shadow_pwd = spw_file_present(); +#endif +#ifdef SHADOWGRP + is_shadow_grp = sgr_file_present(); +#endif + + /* + * The open routines for the NDBM files don't use read-write + * as the mode, so we have to clue them in. + */ + +#ifdef NDBM + pw_dbm_mode = O_RDWR; +#ifdef SHADOWPWD + sp_dbm_mode = O_RDWR; +#endif + gr_dbm_mode = O_RDWR; +#ifdef SHADOWGRP + sg_dbm_mode = O_RDWR; +#endif +#endif /* NDBM */ + process_flags (argc, argv); + + /* + * Do the hard stuff - open the files, change the user entries, + * change the home directory, then close and update the files. + */ + + open_files(); + + usr_update(); + + close_files(); + + if (Gflg || lflg) + grp_err = grp_update(); + + if (mflg) + move_home(); + +#ifndef NO_MOVE_MAILBOX + if (lflg || uflg) + move_mailbox(); +#endif + + if (uflg) { + update_files(); + + /* + * Change the UID on all of the files owned by `user_id' + * to `user_newid' in the user's home directory. + */ + + chown_tree(dflg ? user_newhome:user_home, + user_id, user_newid, + user_gid, gflg ? user_newgid:user_gid); + } + + if (grp_err) + exit(E_GRP_UPDATE); + + exit(E_SUCCESS); + /*NOTREACHED*/ +} diff --git a/src/vipw.c b/src/vipw.c new file mode 100644 index 00000000..d799796f --- /dev/null +++ b/src/vipw.c @@ -0,0 +1,239 @@ +/* + vipw, vigr edit the password or group file + with -s will edit shadow or gshadow file + + Copyright (C) 1997 Guy Maor + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ + +#include + +#include "rcsid.h" +RCSID(PKG_VER "$Id: vipw.c,v 1.1 1999/07/09 18:02:43 marekm Exp $") + +#include "defines.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "prototypes.h" +#include "pwio.h" +#include "shadowio.h" +#include "groupio.h" +#include "sgroupio.h" + + +static const char *progname, *filename, *fileeditname; +static int filelocked = 0, createedit = 0; +static int (*unlock)(); + +/* local function prototypes */ +static int create_backup_file P_((FILE *, const char *, struct stat *)); +static void vipwexit P_((const char *, int, int)); +static void vipwedit P_((const char *, int (*) P_((void)), int (*) P_((void)))); +int main P_((int, char **)); + +static int +create_backup_file(FILE *fp, const char *backup, struct stat *sb) +{ + struct utimbuf ub; + FILE *bkfp; + int c; + mode_t mask; + + mask = umask(077); + bkfp = fopen(backup, "w"); + umask(mask); + if (!bkfp) return -1; + + rewind(fp); + while ((c = getc(fp)) != EOF) { + if (putc(c, bkfp) == EOF) break; + } + + if (c != EOF || fflush(bkfp)) { + fclose(bkfp); + unlink(backup); + return -1; + } + if (fclose(bkfp)) { + unlink(backup); + return -1; + } + + ub.actime = sb->st_atime; + ub.modtime = sb->st_mtime; + if (utime(backup, &ub) || + chmod(backup, sb->st_mode) || + chown(backup, sb->st_uid, sb->st_gid)) { + unlink(backup); + return -1; + } + return 0; +} + + +static void +vipwexit(const char *msg, int syserr, int ret) +{ + int err = errno; + if (filelocked) (*unlock)(); + if (createedit) unlink(fileeditname); + if (msg) fprintf(stderr, "%s: %s", progname, msg); + if (syserr) fprintf(stderr, ": %s", strerror(err)); + fprintf(stderr, _("\n%s: %s is unchanged\n"), progname, filename); + exit(ret); +} + +#ifndef DEFAULT_EDITOR +#define DEFAULT_EDITOR "vi" +#endif + +static void +vipwedit(const char *file, int (*file_lock) P_((void)), int (*file_unlock) P_((void))) +{ + const char *editor; + pid_t pid; + struct stat st1, st2; + int status; + FILE *f; + char filebackup[1024], fileedit[1024]; + + snprintf(filebackup, sizeof filebackup, "%s-", file); + snprintf(fileedit, sizeof fileedit, "%s.edit", file); + unlock = file_unlock; + filename = file; + fileeditname = fileedit; + + if (access(file, F_OK)) vipwexit(file, 1, 1); + if (!file_lock()) vipwexit(_("Couldn't lock file"), errno, 5); + filelocked = 1; + + /* edited copy has same owners, perm */ + if (stat(file, &st1)) vipwexit(file, 1, 1); + if (!(f = fopen(file, "r"))) vipwexit(file, 1, 1); + if (create_backup_file(f, fileedit, &st1)) + vipwexit(_("Couldn't make backup"), errno, 1); + createedit = 1; + + editor = getenv("VISUAL"); + if (!editor) + editor = getenv("EDITOR"); + if (!editor) + editor = DEFAULT_EDITOR; + + if ((pid = fork()) == -1) vipwexit("fork", 1, 1); + else if (!pid) { + execlp(editor, editor, fileedit, (char *) 0); + fprintf(stderr, "%s: %s: %s\n", progname, editor, strerror(errno)); + exit(1); + } + + for (;;) { + pid = waitpid(pid, &status, WUNTRACED); + if (WIFSTOPPED(status)) { + kill(getpid(), SIGSTOP); + kill(getpid(), SIGCONT); + } + else break; + } + + if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status)) + vipwexit(editor, 1, 1); + + if (stat(fileedit, &st2)) vipwexit(fileedit, 1, 1); + if (st1.st_mtime == st2.st_mtime) vipwexit(0, 0, 0); + + /* XXX - here we should check fileedit for errors; if there are any, + ask the user what to do (edit again, save changes anyway, or quit + without saving). Use pwck or grpck to do the check. --marekm */ + + createedit = 0; + unlink(filebackup); + link(file, filebackup); + if (rename(fileedit, file) == -1) { + fprintf(stderr, _("%s: can't restore %s: %s (your changes are in %s)\n"), + progname, file, strerror(errno), fileedit); + vipwexit(0,0,1); + } + + (*file_unlock)(); +} + + +int +main(int argc, char **argv) +{ + int flag; + int editshadow = 0; + char *c; + int e = 1; + int do_vipw; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + progname = ((c = strrchr(*argv, '/')) ? c+1 : *argv); + do_vipw = (strcmp(progname, "vigr") != 0); + + while ((flag = getopt(argc, argv, "ghps")) != EOF) { + switch (flag) { + case 'p': + do_vipw = 1; + break; + case 'g': + do_vipw = 0; + break; + case 's': + editshadow = 1; + break; + case 'h': + e = 0; + default: + printf(_("Usage:\n\ +`vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n\ +`vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n\ +")); + exit(e); + } + } + + if (do_vipw) { +#ifdef SHADOWPWD + if (editshadow) + vipwedit(SHADOW_FILE, spw_lock, spw_unlock); + else +#endif + vipwedit(PASSWD_FILE, pw_lock, pw_unlock); + } + else { +#ifdef SHADOWGRP + if (editshadow) + vipwedit(SGROUP_FILE, sgr_lock, sgr_unlock); + else +#endif + vipwedit(GROUP_FILE, gr_lock, gr_unlock); + } + + return 0; +} diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 00000000..9788f702 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +timestamp