From 45c6603cc86c5881b00ac40e0f9fe548c30ff6be Mon Sep 17 00:00:00 2001 From: nekral-guest Date: Sun, 7 Oct 2007 11:44:02 +0000 Subject: [PATCH] [svn-upgrade] Integrating new upstream version, shadow (19990709) --- ABOUT-NLS | 226 + Makefile.am | 6 + Makefile.in | 350 ++ acconfig.h | 154 + aclocal.m4 | 868 ++++ ansi2knr.1 | 36 + ansi2knr.c | 574 +++ config.guess | 975 +++++ config.h.in | 456 ++ config.sub | 965 +++++ configure | 6506 +++++++++++++++++++++++++++++ configure.in | 313 ++ contrib/Makefile.am | 5 + contrib/Makefile.in | 196 + contrib/README | 10 + contrib/adduser-old.c | 300 ++ contrib/adduser.c | 502 +++ contrib/adduser.sh | 90 + contrib/adduser2.sh | 743 ++++ contrib/atudel | 85 + contrib/pwdauth.c | 308 ++ contrib/rpasswd.c | 591 +++ contrib/shadow-anonftp.patch | 147 + contrib/udbachk.v012.tgz | Bin 0 -> 20228 bytes debian/FILES | 70 + debian/Makefile.am | 9 + debian/Makefile.in | 200 + debian/changelog | 175 + debian/checksums | 7 + debian/control | 41 + debian/login.conffiles | 6 + debian/login.copyright | 76 + debian/login.postinst | 42 + debian/login.postrm | 6 + debian/login.preinst | 4 + debian/login.prerm | 8 + debian/logoutd | 42 + debian/passwd.conffiles | 1 + debian/passwd.copyright | 55 + debian/passwd.postinst | 38 + debian/porttime | 8 + debian/rules | 135 + debian/secure-su.README | 4 + debian/secure-su.conffiles | 1 + debian/secure-su.copyright | 54 + debian/secure-su.postrm | 12 + debian/secure-su.preinst | 14 + debian/securetty | 14 + debian/tar.c | 409 ++ doc/ANNOUNCE | 48 + doc/CHANGES | 625 +++ doc/HOWTO | 1918 +++++++++ doc/INSTALL | 176 + doc/LICENSE | 118 + doc/LSM | 19 + doc/Makefile.am | 7 + doc/Makefile.in | 198 + doc/README | 253 ++ doc/README.debian | 68 + doc/README.limits | 66 + doc/README.linux | 162 + doc/README.mirrors | 57 + doc/README.nls | 30 + doc/README.pam | 36 + doc/README.platforms | 33 + doc/README.shadow-paper | 25 + doc/README.sun4 | 39 + doc/WISHLIST | 61 + doc/console.c.spec.txt | 36 + doc/cracklib26.diff | 340 ++ etc/Makefile.am | 7 + etc/Makefile.in | 285 ++ etc/limits | 28 + etc/login.access | 54 + etc/login.defs | 214 + etc/login.defs.linux | 340 ++ etc/pam.d/Makefile.am | 4 + etc/pam.d/Makefile.in | 195 + etc/pam.d/passwd | 5 + etc/pam.d/su | 7 + etc/shells | 10 + etc/suauth | 4 + install-sh | 250 ++ intl/ChangeLog | 1086 +++++ intl/Makefile.in | 214 + intl/VERSION | 1 + intl/bindtextdom.c | 203 + intl/cat-compat.c | 262 ++ intl/dcgettext.c | 655 +++ intl/dgettext.c | 59 + intl/explodename.c | 197 + intl/finddomain.c | 216 + intl/gettext.c | 70 + intl/gettext.h | 105 + intl/gettextP.h | 89 + intl/hash-string.h | 59 + intl/intl-compat.c | 76 + intl/l10nflist.c | 411 ++ intl/libgettext.h | 182 + intl/linux-msg.sed | 100 + intl/loadinfo.h | 78 + intl/loadmsgcat.c | 220 + intl/localealias.c | 438 ++ intl/po2tbl.sed.in | 102 + intl/textdomain.c | 108 + intl/xopen-msg.sed | 104 + lib/Makefile.am | 57 + lib/Makefile.in | 430 ++ lib/commonio.c | 739 ++++ lib/commonio.h | 101 + lib/defines.h | 319 ++ lib/dialchk.c | 77 + lib/dialchk.h | 16 + lib/dialup.c | 169 + lib/dialup.h | 66 + lib/encrypt.c | 123 + lib/faillog.h | 55 + lib/fputsx.c | 80 + lib/getdef.c | 400 ++ lib/getdef.h | 11 + lib/getpass.c | 268 ++ lib/grdbm.c | 211 + lib/groupio.c | 185 + lib/groupio.h | 12 + lib/grpack.c | 95 + lib/gsdbm.c | 167 + lib/gshadow.c | 528 +++ lib/gshadow_.h | 71 + lib/gspack.c | 150 + lib/lastlog_.h | 50 + lib/lockpw.c | 114 + lib/md5.c | 261 ++ lib/md5.h | 27 + lib/md5crypt.c | 151 + lib/mkdir.c | 60 + lib/pam_defs.h | 21 + lib/port.c | 439 ++ lib/port.h | 81 + lib/prototypes.h | 213 + lib/putgrent.c | 75 + lib/putpwent.c | 72 + lib/putspent.c | 103 + lib/pwauth.c | 548 +++ lib/pwauth.h | 60 + lib/pwdbm.c | 143 + lib/pwio.c | 187 + lib/pwio.h | 12 + lib/pwpack.c | 163 + lib/rad64.c | 126 + lib/rcsid.h | 22 + lib/rename.c | 91 + lib/rmdir.c | 59 + lib/sgetgrent.c | 140 + lib/sgetpwent.c | 136 + lib/sgetspent.c | 198 + lib/sgroupio.c | 213 + lib/sgroupio.h | 13 + lib/shadow.c | 592 +++ lib/shadow_.h | 89 + lib/shadowio.c | 172 + lib/shadowio.h | 13 + lib/snprintf.c | 320 ++ lib/snprintf.h | 51 + lib/spdbm.c | 116 + lib/sppack.c | 113 + lib/strcasecmp.c | 25 + lib/strdup.c | 16 + lib/strerror.c | 23 + lib/strstr.c | 55 + lib/tcfsio.c | 90 + lib/tcfsio.h | 14 + lib/utent.c | 114 + libmisc/Makefile.am | 20 + libmisc/Makefile.in | 418 ++ libmisc/addgrps.c | 89 + libmisc/age.c | 235 ++ libmisc/basename.c | 22 + libmisc/chkname.c | 73 + libmisc/chkname.h | 15 + libmisc/chkshell.c | 98 + libmisc/chowndir.c | 126 + libmisc/chowntty.c | 127 + libmisc/console.c | 115 + libmisc/copydir.c | 411 ++ libmisc/entry.c | 99 + libmisc/env.c | 250 ++ libmisc/failure.c | 278 ++ libmisc/failure.h | 44 + libmisc/fields.c | 104 + libmisc/getdate.c | 2006 +++++++++ libmisc/getdate.h | 8 + libmisc/getdate.y | 1024 +++++ libmisc/hushed.c | 90 + libmisc/isexpired.c | 173 + libmisc/limits.c | 394 ++ libmisc/list.c | 234 ++ libmisc/log.c | 100 + libmisc/login_access.c | 340 ++ libmisc/login_desrpc.c | 77 + libmisc/login_krb.c | 61 + libmisc/loginprompt.c | 165 + libmisc/mail.c | 79 + libmisc/motd.c | 69 + libmisc/myname.c | 41 + libmisc/obscure.c | 286 ++ libmisc/pam_pass.c | 58 + libmisc/pwd2spwd.c | 103 + libmisc/pwd_init.c | 73 + libmisc/pwdcheck.c | 69 + libmisc/rlogin.c | 170 + libmisc/salt.c | 70 + libmisc/setugid.c | 134 + libmisc/setup.c | 72 + libmisc/setupenv.c | 277 ++ libmisc/shell.c | 126 + libmisc/strtoday.c | 207 + libmisc/suauth.c | 201 + libmisc/sub.c | 78 + libmisc/sulog.c | 77 + libmisc/ttytype.c | 89 + libmisc/tz.c | 67 + libmisc/ulimit.c | 34 + libmisc/utmp.c | 478 +++ libmisc/valid.c | 101 + libmisc/xmalloc.c | 38 + ltconfig | 1519 +++++++ ltmain.sh | 2453 +++++++++++ man/Makefile.am | 32 + man/Makefile.in | 370 ++ man/chage.1 | 109 + man/chfn.1 | 66 + man/chpasswd.8 | 62 + man/chsh.1 | 66 + man/dpasswd.8 | 55 + man/faillog.5 | 59 + man/faillog.8 | 100 + man/gpasswd.1 | 73 + man/groupadd.8 | 64 + man/groupdel.8 | 60 + man/groupmod.8 | 66 + man/groups.1 | 57 + man/grpck.8 | 101 + man/id.1 | 54 + man/lastlog.8 | 63 + man/limits.5 | 74 + man/login.1 | 134 + man/login.access.5 | 52 + man/login.defs.5 | 563 +++ man/logoutd.8 | 51 + man/mkpasswd.8 | 81 + man/newgrp.1 | 80 + man/newusers.8 | 68 + man/passwd.1 | 190 + man/passwd.5 | 111 + man/porttime.5 | 84 + man/pw_auth.3 | 159 + man/pwauth.8 | 67 + man/pwck.8 | 107 + man/pwconv.8 | 63 + man/shadow.3 | 148 + man/shadow.5 | 99 + man/shadowconfig.8 | 24 + man/su.1 | 83 + man/suauth.5 | 112 + man/sulogin.8 | 88 + man/useradd.8 | 197 + man/userdel.8 | 69 + man/usermod.8 | 153 + man/vipw.8 | 29 + missing | 188 + mkinstalldirs | 40 + old/Makefile.am | 7 + old/Makefile.in | 198 + old/Makefile.linux | 751 ++++ old/Makefile.sun4 | 685 +++ old/Makefile.svr4 | 681 +++ old/Makefile.xenix | 723 ++++ old/config.h.linux | 454 ++ old/config.h.sun4 | 189 + old/config.h.svr4 | 217 + old/config.h.xenix | 224 + old/orig-config.h | 454 ++ old/pwconv-old.8 | 66 + old/pwconv-old.c | 217 + old/pwconv.8 | 59 + old/pwd.h.m4 | 138 + old/pwunconv-old.8 | 57 + old/pwunconv-old.c | 150 + old/pwunconv.8 | 51 + old/scologin.c | 107 + old/vipw.8 | 69 + po/ChangeLog | 0 po/Makefile.in.in | 248 ++ po/POTFILES.in | 123 + po/cat-id-tbl.c | 500 +++ po/el.gmo | Bin 0 -> 41942 bytes po/el.po | 2428 +++++++++++ po/pl.gmo | Bin 0 -> 40606 bytes po/pl.po | 2383 +++++++++++ po/shadow.pot | 2341 +++++++++++ po/stamp-cat-id | 1 + redhat/Makefile.am | 8 + redhat/Makefile.in | 201 + redhat/README | 29 + redhat/shadow-970616-fix.patch | 256 ++ redhat/shadow-970616-glibc.patch | 11 + redhat/shadow-970616-rh.patch | 1242 ++++++ redhat/shadow-970616-utuser.patch | 12 + redhat/shadow-970616.login.defs | 57 + redhat/shadow-970616.useradd | 7 + redhat/shadow-utils-970616.spec | 137 + redhat/shadow-utils.spec | 151 + redhat/shadow-utils.spec.in | 151 + src/Makefile.am | 90 + src/Makefile.in | 873 ++++ src/chage.c | 821 ++++ src/chfn.c | 602 +++ src/chpasswd.c | 290 ++ src/chsh.c | 439 ++ src/dpasswd.c | 261 ++ src/expiry.c | 211 + src/faillog.c | 380 ++ src/gpasswd.c | 662 +++ src/groupadd.c | 538 +++ src/groupdel.c | 352 ++ src/groupmod.c | 549 +++ src/groups.c | 184 + src/grpck.c | 650 +++ src/grpconv.c | 174 + src/grpunconv.c | 132 + src/id.c | 188 + src/lastlog.c | 193 + src/login.c | 1260 ++++++ src/logoutd.c | 316 ++ src/mkpasswd.c | 395 ++ src/newgrp.c | 479 +++ src/newusers.c | 571 +++ src/passwd.c | 1417 +++++++ src/patchlevel.h | 58 + src/pwck.c | 617 +++ src/pwconv.c | 188 + src/pwunconv.c | 197 + src/shadowconfig.sh | 67 + src/su.c | 633 +++ src/sulogin.c | 281 ++ src/useradd.c | 1746 ++++++++ src/userdel.c | 816 ++++ src/usermod.c | 1664 ++++++++ src/vipw.c | 239 ++ stamp-h.in | 1 + 350 files changed, 89554 insertions(+) create mode 100644 ABOUT-NLS create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 acconfig.h create mode 100644 aclocal.m4 create mode 100644 ansi2knr.1 create mode 100644 ansi2knr.c create mode 100755 config.guess create mode 100644 config.h.in create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.in create mode 100644 contrib/Makefile.am create mode 100644 contrib/Makefile.in create mode 100644 contrib/README create mode 100644 contrib/adduser-old.c create mode 100644 contrib/adduser.c create mode 100755 contrib/adduser.sh create mode 100755 contrib/adduser2.sh create mode 100755 contrib/atudel create mode 100644 contrib/pwdauth.c create mode 100644 contrib/rpasswd.c create mode 100644 contrib/shadow-anonftp.patch create mode 100644 contrib/udbachk.v012.tgz create mode 100644 debian/FILES create mode 100644 debian/Makefile.am create mode 100644 debian/Makefile.in create mode 100644 debian/changelog create mode 100755 debian/checksums create mode 100644 debian/control create mode 100644 debian/login.conffiles create mode 100644 debian/login.copyright create mode 100644 debian/login.postinst create mode 100644 debian/login.postrm create mode 100644 debian/login.preinst create mode 100644 debian/login.prerm create mode 100644 debian/logoutd create mode 100644 debian/passwd.conffiles create mode 100644 debian/passwd.copyright create mode 100644 debian/passwd.postinst create mode 100644 debian/porttime create mode 100755 debian/rules create mode 100644 debian/secure-su.README create mode 100644 debian/secure-su.conffiles create mode 100644 debian/secure-su.copyright create mode 100644 debian/secure-su.postrm create mode 100644 debian/secure-su.preinst create mode 100644 debian/securetty create mode 100644 debian/tar.c create mode 100644 doc/ANNOUNCE create mode 100644 doc/CHANGES create mode 100644 doc/HOWTO create mode 100644 doc/INSTALL create mode 100644 doc/LICENSE create mode 100644 doc/LSM create mode 100644 doc/Makefile.am create mode 100644 doc/Makefile.in create mode 100644 doc/README create mode 100644 doc/README.debian create mode 100644 doc/README.limits create mode 100644 doc/README.linux create mode 100644 doc/README.mirrors create mode 100644 doc/README.nls create mode 100644 doc/README.pam create mode 100644 doc/README.platforms create mode 100644 doc/README.shadow-paper create mode 100644 doc/README.sun4 create mode 100644 doc/WISHLIST create mode 100644 doc/console.c.spec.txt create mode 100644 doc/cracklib26.diff create mode 100644 etc/Makefile.am create mode 100644 etc/Makefile.in create mode 100644 etc/limits create mode 100644 etc/login.access create mode 100644 etc/login.defs create mode 100644 etc/login.defs.linux create mode 100644 etc/pam.d/Makefile.am create mode 100644 etc/pam.d/Makefile.in create mode 100644 etc/pam.d/passwd create mode 100644 etc/pam.d/su create mode 100644 etc/shells create mode 100644 etc/suauth create mode 100755 install-sh create mode 100644 intl/ChangeLog create mode 100644 intl/Makefile.in create mode 100644 intl/VERSION create mode 100644 intl/bindtextdom.c create mode 100644 intl/cat-compat.c create mode 100644 intl/dcgettext.c create mode 100644 intl/dgettext.c create mode 100644 intl/explodename.c create mode 100644 intl/finddomain.c create mode 100644 intl/gettext.c create mode 100644 intl/gettext.h create mode 100644 intl/gettextP.h create mode 100644 intl/hash-string.h create mode 100644 intl/intl-compat.c create mode 100644 intl/l10nflist.c create mode 100644 intl/libgettext.h create mode 100644 intl/linux-msg.sed create mode 100644 intl/loadinfo.h create mode 100644 intl/loadmsgcat.c create mode 100644 intl/localealias.c create mode 100644 intl/po2tbl.sed.in create mode 100644 intl/textdomain.c create mode 100644 intl/xopen-msg.sed create mode 100644 lib/Makefile.am create mode 100644 lib/Makefile.in create mode 100644 lib/commonio.c create mode 100644 lib/commonio.h create mode 100644 lib/defines.h create mode 100644 lib/dialchk.c create mode 100644 lib/dialchk.h create mode 100644 lib/dialup.c create mode 100644 lib/dialup.h create mode 100644 lib/encrypt.c create mode 100644 lib/faillog.h create mode 100644 lib/fputsx.c create mode 100644 lib/getdef.c create mode 100644 lib/getdef.h create mode 100644 lib/getpass.c create mode 100644 lib/grdbm.c create mode 100644 lib/groupio.c create mode 100644 lib/groupio.h create mode 100644 lib/grpack.c create mode 100644 lib/gsdbm.c create mode 100644 lib/gshadow.c create mode 100644 lib/gshadow_.h create mode 100644 lib/gspack.c create mode 100644 lib/lastlog_.h create mode 100644 lib/lockpw.c create mode 100644 lib/md5.c create mode 100644 lib/md5.h create mode 100644 lib/md5crypt.c create mode 100644 lib/mkdir.c create mode 100644 lib/pam_defs.h create mode 100644 lib/port.c create mode 100644 lib/port.h create mode 100644 lib/prototypes.h create mode 100644 lib/putgrent.c create mode 100644 lib/putpwent.c create mode 100644 lib/putspent.c create mode 100644 lib/pwauth.c create mode 100644 lib/pwauth.h create mode 100644 lib/pwdbm.c create mode 100644 lib/pwio.c create mode 100644 lib/pwio.h create mode 100644 lib/pwpack.c create mode 100644 lib/rad64.c create mode 100644 lib/rcsid.h create mode 100644 lib/rename.c create mode 100644 lib/rmdir.c create mode 100644 lib/sgetgrent.c create mode 100644 lib/sgetpwent.c create mode 100644 lib/sgetspent.c create mode 100644 lib/sgroupio.c create mode 100644 lib/sgroupio.h create mode 100644 lib/shadow.c create mode 100644 lib/shadow_.h create mode 100644 lib/shadowio.c create mode 100644 lib/shadowio.h create mode 100644 lib/snprintf.c create mode 100644 lib/snprintf.h create mode 100644 lib/spdbm.c create mode 100644 lib/sppack.c create mode 100644 lib/strcasecmp.c create mode 100644 lib/strdup.c create mode 100644 lib/strerror.c create mode 100644 lib/strstr.c create mode 100644 lib/tcfsio.c create mode 100644 lib/tcfsio.h create mode 100644 lib/utent.c create mode 100644 libmisc/Makefile.am create mode 100644 libmisc/Makefile.in create mode 100644 libmisc/addgrps.c create mode 100644 libmisc/age.c create mode 100644 libmisc/basename.c create mode 100644 libmisc/chkname.c create mode 100644 libmisc/chkname.h create mode 100644 libmisc/chkshell.c create mode 100644 libmisc/chowndir.c create mode 100644 libmisc/chowntty.c create mode 100644 libmisc/console.c create mode 100644 libmisc/copydir.c create mode 100644 libmisc/entry.c create mode 100644 libmisc/env.c create mode 100644 libmisc/failure.c create mode 100644 libmisc/failure.h create mode 100644 libmisc/fields.c create mode 100644 libmisc/getdate.c create mode 100644 libmisc/getdate.h create mode 100644 libmisc/getdate.y create mode 100644 libmisc/hushed.c create mode 100644 libmisc/isexpired.c create mode 100644 libmisc/limits.c create mode 100644 libmisc/list.c create mode 100644 libmisc/log.c create mode 100644 libmisc/login_access.c create mode 100644 libmisc/login_desrpc.c create mode 100644 libmisc/login_krb.c create mode 100644 libmisc/loginprompt.c create mode 100644 libmisc/mail.c create mode 100644 libmisc/motd.c create mode 100644 libmisc/myname.c create mode 100644 libmisc/obscure.c create mode 100644 libmisc/pam_pass.c create mode 100644 libmisc/pwd2spwd.c create mode 100644 libmisc/pwd_init.c create mode 100644 libmisc/pwdcheck.c create mode 100644 libmisc/rlogin.c create mode 100644 libmisc/salt.c create mode 100644 libmisc/setugid.c create mode 100644 libmisc/setup.c create mode 100644 libmisc/setupenv.c create mode 100644 libmisc/shell.c create mode 100644 libmisc/strtoday.c create mode 100644 libmisc/suauth.c create mode 100644 libmisc/sub.c create mode 100644 libmisc/sulog.c create mode 100644 libmisc/ttytype.c create mode 100644 libmisc/tz.c create mode 100644 libmisc/ulimit.c create mode 100644 libmisc/utmp.c create mode 100644 libmisc/valid.c create mode 100644 libmisc/xmalloc.c create mode 100755 ltconfig create mode 100644 ltmain.sh create mode 100644 man/Makefile.am create mode 100644 man/Makefile.in create mode 100644 man/chage.1 create mode 100644 man/chfn.1 create mode 100644 man/chpasswd.8 create mode 100644 man/chsh.1 create mode 100644 man/dpasswd.8 create mode 100644 man/faillog.5 create mode 100644 man/faillog.8 create mode 100644 man/gpasswd.1 create mode 100644 man/groupadd.8 create mode 100644 man/groupdel.8 create mode 100644 man/groupmod.8 create mode 100644 man/groups.1 create mode 100644 man/grpck.8 create mode 100644 man/id.1 create mode 100644 man/lastlog.8 create mode 100644 man/limits.5 create mode 100644 man/login.1 create mode 100644 man/login.access.5 create mode 100644 man/login.defs.5 create mode 100644 man/logoutd.8 create mode 100644 man/mkpasswd.8 create mode 100644 man/newgrp.1 create mode 100644 man/newusers.8 create mode 100644 man/passwd.1 create mode 100644 man/passwd.5 create mode 100644 man/porttime.5 create mode 100644 man/pw_auth.3 create mode 100644 man/pwauth.8 create mode 100644 man/pwck.8 create mode 100644 man/pwconv.8 create mode 100644 man/shadow.3 create mode 100644 man/shadow.5 create mode 100644 man/shadowconfig.8 create mode 100644 man/su.1 create mode 100644 man/suauth.5 create mode 100644 man/sulogin.8 create mode 100644 man/useradd.8 create mode 100644 man/userdel.8 create mode 100644 man/usermod.8 create mode 100644 man/vipw.8 create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 old/Makefile.am create mode 100644 old/Makefile.in create mode 100644 old/Makefile.linux create mode 100644 old/Makefile.sun4 create mode 100644 old/Makefile.svr4 create mode 100644 old/Makefile.xenix create mode 100644 old/config.h.linux create mode 100644 old/config.h.sun4 create mode 100644 old/config.h.svr4 create mode 100644 old/config.h.xenix create mode 100644 old/orig-config.h create mode 100644 old/pwconv-old.8 create mode 100644 old/pwconv-old.c create mode 100644 old/pwconv.8 create mode 100644 old/pwd.h.m4 create mode 100644 old/pwunconv-old.8 create mode 100644 old/pwunconv-old.c create mode 100644 old/pwunconv.8 create mode 100644 old/scologin.c create mode 100644 old/vipw.8 create mode 100644 po/ChangeLog create mode 100644 po/Makefile.in.in create mode 100644 po/POTFILES.in create mode 100644 po/cat-id-tbl.c create mode 100644 po/el.gmo create mode 100644 po/el.po create mode 100644 po/pl.gmo create mode 100644 po/pl.po create mode 100644 po/shadow.pot create mode 100644 po/stamp-cat-id create mode 100644 redhat/Makefile.am create mode 100644 redhat/Makefile.in create mode 100644 redhat/README create mode 100644 redhat/shadow-970616-fix.patch create mode 100644 redhat/shadow-970616-glibc.patch create mode 100644 redhat/shadow-970616-rh.patch create mode 100644 redhat/shadow-970616-utuser.patch create mode 100644 redhat/shadow-970616.login.defs create mode 100644 redhat/shadow-970616.useradd create mode 100644 redhat/shadow-utils-970616.spec create mode 100644 redhat/shadow-utils.spec create mode 100644 redhat/shadow-utils.spec.in create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/chage.c create mode 100644 src/chfn.c create mode 100644 src/chpasswd.c create mode 100644 src/chsh.c create mode 100644 src/dpasswd.c create mode 100644 src/expiry.c create mode 100644 src/faillog.c create mode 100644 src/gpasswd.c create mode 100644 src/groupadd.c create mode 100644 src/groupdel.c create mode 100644 src/groupmod.c create mode 100644 src/groups.c create mode 100644 src/grpck.c create mode 100644 src/grpconv.c create mode 100644 src/grpunconv.c create mode 100644 src/id.c create mode 100644 src/lastlog.c create mode 100644 src/login.c create mode 100644 src/logoutd.c create mode 100644 src/mkpasswd.c create mode 100644 src/newgrp.c create mode 100644 src/newusers.c create mode 100644 src/passwd.c create mode 100644 src/patchlevel.h create mode 100644 src/pwck.c create mode 100644 src/pwconv.c create mode 100644 src/pwunconv.c create mode 100755 src/shadowconfig.sh create mode 100644 src/su.c create mode 100644 src/sulogin.c create mode 100644 src/useradd.c create mode 100644 src/userdel.c create mode 100644 src/usermod.c create mode 100644 src/vipw.c create mode 100644 stamp-h.in 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 0000000000000000000000000000000000000000..82bd320412905ccc23dd3f557f7943eb25489845 GIT binary patch literal 20228 zcmV((K;XY0iwFSIVs?CKmEWTvDJRM zy)AwcLOk8s%Kg?qZ6S7^KH1*d>2$ZcLUg*_?e+O1A!6`{_02XBvl6N&VFCFbEs#^Pq`xl@tEQi^0M#Vn2{ zu@eYSi6jz3DZCJb>-%y92v&Lh-sW7zn||av{_5&Tj-9!myjWeCxUSHq*mA|jX;*Cc zf!O!}tHs7lj+`*@U_3HFyQ?cIiM?6&+4ZFp0;U+2jk94*0!(;gpj{|qY z4&fKtp#~KjBk@mlrna#;^upb{<^w0hf6wj&l8IZI4+Q!|P02kQ1_IBIkUjqVxRubJ2GKPyCGpM_B&F2}3D* zo;UR_|1-Y!U>U9?0<7RM#(<)tadP9tau*$iaGg-Za^#`YAI=k?Awi6r5U_%1n-6`6CC8pCL-0}#Y>gvoDo0{ScyPsAq@k~A z5N{(u>?9BmcZKv|K2GCf*X*GYHboR8k~+9Oa&gfN*EN9LTj4uNwzRc?{fx^I`boq+ zjb@TPDe!pXfrE$WI#+T$_nU|UfW?QS^LM8g=VJflckyAr*V{ii|9uyLlW7FA@>((~ zFPQlrUIr1ZdJ48GtEyWm5636qEVf=SctODx%k(fHy5)|x8?;2=xgbT)W zzw!`?<456y*aYBAkh=onJp`wwxB*L*n2?mzipw+2HpNlswwmCGwjm=@O6*^QGG9Bv zF!n|h`1Ad~Xm>kLo;Srsf8XW-jS~V&;0%WAj&ze5$l_)tDEcA z4`KoKe1KC#xb?HS`m@JV;^oMT5z+LOH8zn6*l>PKB_l5?4f)=%I2Hrbg|S<;ncU8# zDi4DzF6@(dfy|FUjsQF5#{$eEU?k78X8R4~wxNd_E^$uGg9rR|?)eEEHJ$HJRzg-P zj>hDEZooaD360`t2A(O92527|@|ge%51W`{(Zl z=cj|S{eJ($o0S?RChU7_C7{FJ>BX6bA-`M(>A%~5bNWHUu%oWP!%#wFGGNI52Xrjp zMh#c`Ob#W9-~=-~aqakXiQWm$l$ZyOx@v+iT2sVe1pAcmZT*K0^62oB(kio=o zOiqRaXaOIo2=R&T_D+Tm+?}Qv@cGdMGv|HmXgG)kd~+gQjBDdK3Pc2fP>jJbs#Z}XhrP46N5>%L)5D_^p{0Bb zRU-*e2Zo6s4M9kE3;6Zv$=jpDi{AeE(do$mk-`y3Yf!5u;3}zBb|R@KIpqDW!S^~t zzwAgepW;p-r(D;eD0Bh|^(pwD1i1yl=>%ZFk{5eeWOsL0iMaLPb^s0zJj*UI{W`}T z$aD@-2DZ?D<(dCu6;o>3o&CuGt?;95WS@647_z0iLD)~+gXSI}$QKPc=w-4&-akL4 zaTNe7N9jx`J|l%uzc@-;DL$WtQQsb=Y$EW&xi_*0oG*m|uEwfuJuf1rlXuk|Mr!oWF zx!yqJioK#197On;6Jt>jPv!w6LW-s8VDm}Ca5^veI3uC~kEoBI#oj6(z&~m_Bd9gO zNe&FQCUU(tTKn46P&(#U0L?NW4*C@^lMF^j^9mqkAzBP|m_ebst3bvXh<0C9P}dpM zRQi=Lerd3+tzdu4ed9{*U1AmE6;iW5i@b{DvJ z?cv|fLzmQxkt(7rb&-=NKaZwH2X_z-l4t-Q>+Jf`?3#4A!^Z9^AMzw6yiNmyC?2RL z6TS{}175^YfL$XhgVDH=Zx9(Q5F;=O)sZi;KK5djFszo2i-(;@{4mn1;UA=BvpU=F zb>xl2`j@7#Ki&c;{RJ_R$f%b|(p-|0<1Nni8Kj9y`r|r&wuX5jGG7uN z(9M6~8I;kOE!bMi1DZe`B+3+O-c$HRdl@+Ln25%Z%J`uO4{20~cL;a9bSC3~Vv|O| znNLa1s*@MA>Kabw%9+TVT=W^sjom~sREL_`nPJo@XO{cSjOIT9Or!b$pzWWT4n%@V zsy2HnE5$zKbioX~bA5(A8A!_HhVNa;26u)aqe0feg)7X*%#o^N%=vc}#Yw|>>7|TO z`&20B>+5uI)*IrBcq!5k0J0LxWFEsF8=VHb18imI*WB7`zF2GQCD~{jM!(*}uFi0m zYj8)6qBJCowAdn5U!DW5beOdxsCucz3@pcUPsdrDf*6eg^FZcy#Uvh!P6NC-UdGfB<3|so=AKx4vDV-_2EzCF@h*dC z?0X^<8+v651iLv&g)M}Ro^74RWeocx*-E?EqVEcO1VI~DoYs9dhM zOu)fPcX&&`w6MN|U$?~Ru_z(GAz50Yd@u(8SI?F=NE!q<1{z#@3Y4%ybv;&oxJ5*l zE|7k5{s$Td>PfR^v9dfFFY!a=g&F0UvQXSm#cEhtz&a=icwad z0zM`@Nu*lo9nqO9Fv)d}QEye_BPVeR;gamhM1tRPR#Dl@N%X@OPd!NT2C z2z_a|FsW(U2-I@n*_KuOf{b^zws!5=tO~A}v!WC zT`rea+Ep`7<|*dlIrCp;m`Z5maC`enX~m>^#bm(>tGX^N%N5x$+j){FJ}b6i@=2!6 z*Rh1i&TTu0hmKLLzVg!dFyJ7tNA4!r_DZ!(W&`NJ5zFwpUVC@?{-CDQ3NVe(o!!>i z=9&h&nQQ&ouuhV~);3$Y=2U(W#6-*uKoNRD1H-@J=X9oTd~80b??znYER+r!MiNYM zv)yCE136|Ja!;IG93MBx;~b5vT5vZG_liMsMrtAfnOTiH)2dskBBI>4TbiJgi2I|h zmhdHBEYTH=3GTR|o%$JhQNqN%P01}0&=o!^(LxNkA%Hp5h%b{=G9QnPATejCgR>xe z6dbKB3LCrVNgh8Yzl#A|)j2J&71|WJ6~xS2FXRg`wz0JFLWH>UBqcX%x2$9aSx-|# z$RVe(-gE8ewT8~HG-w(QP@kc2@%;vMo#6-EUYZ0L*=w`I@rHO+w8{?XVP&jbC(OwJ z6!>ucYg;kH!R~&8drzNg&9fW;LXmf?o!KI0Cw$ zLApshoS+I!N^SaKMC-+HXJ@8+6r$~s8sbn6h4y>XoKilDohH&SE-rfO2vnIC@0({G-^^Tf7W>Ip?di7QzAY;B>Aga7C4(C z^Gr;=Q4Vg4-7yp%orJ1=A{nMk1+18Cf2N-1||`uJ4n1fqXbF_-n>QrDLU4(8Bj2CZDe^ zE14fg&g5I@>AySeogehixurZf*@qmjV5il2cZtAiyF5NUIb0sS|E=g#^2yNd!e2=K zzmfdq(EHzt{yoU#;;7_Si$w=u^OwN}p5hK{rdC-N8_;%m7j2VorR@%ErYc$zTmRj` z@$q24cX;vs;N-l2r^T9rYDv@wC$D?IpPh4t4leib-T4Ca#hPr%4Gs?uPy3Mj9~{3~ zM0mcOTZk7HK)k24R@dk)@h%92y73Zsx4{29Va&7; zh3FTmv>SYVa^-R6c|+AE-&}*Le4PU`4zoXO>f@(6Q~aoJ)sYz#mycF&D=ieMxa1{7 zIpFKJRAN0yC}KAR)8ncee0=1@Azo$=u_oaXS+137MvD4_qkiw;uufYwiZ>cKdwlXY zGrL-8cW-e6wkm$xt8Rl~gl{MD%9IQZiM4V6QH^QemvQnyJXGfOm$nq_k=r=QbjatJp>J%chQ317A#05^;Jg(rgdYF#bYUr?gT8RauT_Vx5M69HE#=8 zTL9l(#MuJ)PJyu;y}+OS+0q?r-&P)v+{NMP`MXLE7cjU0yt{zE1>l{6-k3~OoQ@kb zof+|7-drK7RvGo<{BpcC!Y52OQ%MgYbB7fUDa9Uo6U^t+l3PaXgFQPSRyvV03ok@5 z%Yo1~4_i-0bX^5R+*;2saXj@fR#a`~9wFp(s~?79P*r5p> zA?&3SChOt?!iVp8VG~tG-C#%Qd)q0t zw8c$~JzV|RG#c}TFurfcAN~Ck&iU}$Cuj_q(&8NmNyZ5wa}A}7Us#B51?N+-oJDbB zQ0R@vs3hK5Khd?`5CSnXP>=a;s0?PwZOb;c+?&0|J?Ti6SL?nvke=fc>~RG4n6jJZ z)?{?~y}%7sJQ&O;))2wx9zUVL`b+c276N}MPC!E`N8l9rdp?D5U3gZ(OP@5Xu)PRq z%N&Gz+t^@)+{?~-TO=ApNrWqn|M{jD1{ch^*!X6k(_e3+3b-_6RYrrD`c?(SqX z?QG>~dd{~P%j}O%4^Ii$ckJ?4U(GGeJ(TF$bU8!MZ3bDkoZ##CCAK2<>KYtVO5+U+ zy6%*9jUzdiXO#1oEnvH30gHhvR8xE%QLU$ID6K|SoO`KMTjDHI82O-R1_?tXq1jy2wPe z@!(z=tAE;b4$CAz`B5YvekYQ#byOsJYbm1n`4RV+AV{arp~{#4Hty~8wvNL1CB_-- z(`c-_)%y?uEBO_<>rOuN6!D8Y?kv4ymU`@o4RUK%GSXQ<+NZE|^C?Or>2+Ks3oE(J zbq2|oliB_o+4(5YK~MU4n|5xS!b_$6+b8qjt@ff;eDtO`9#Yh!c2Q)#Z7Zn7z7M`E zz5#3BW5oX^02;J3p70 zzrN%IobzubY8B+Ys(e56UC7hlC8?yYf)W$4O!Qh}W9>~S_soI;L{U4%E7I+{^WE z(;_RqP0T>=N=(ZsTOnrXA~|gx$}gTuGDb{~bR}hh{9T)a)#lpw*xNL5!BGxXo zuAag)4gdoOlc4qmjOBE3wU=>WExY;7=1xGX=}X_b0IpS6V88muHb%)->kb# zZ;<@-!SE#)xuuuAsaGUQGfNFAX*R)CMFM@e{{A;L9JqsE)$_SD1}t(Soe&vR-(G-_m)F7 zXH8&xrtD5 ztv2BpbiIT_vDLy@Kd>{7Lp+AS)sy~)EC4@^&7)YJc{YAwZKM#yvh#M>cPypPGW1eo zX|(XAWLHPslmd|xPRUSA0W^s-47DzRH;cI;oDjz)5H!(`3u{ERm$D@Ph+c|Gn9V1& z27pYC6Vn~3XH7MI%3zsG09MkPOO6;ZAR?Zhl9@@7`=^ILk!R|4D@19E$DIk6jse}6 z&EXHwDkP^&t5C7Fp|?p;r1ose*}u6Z+y&1UwS>Q0X7w&=6<*869)70*{2q2^UNzVF z%oAqp5;bv|aoI~lD=j)VFP505Z_vAsA+s{R`+v}A2@KFh;$36#;jMKq6K#d1Vna61 zB4zc@MtzjGc8FP=B?QgQ@NZth z^{F7{!6Y=;|rPk?wn+oAt3Ko>c~UZ`+JNdzAD18H*GT_|Oiuvp6O5!6f4?xKM_ zcjaNEiVHEjqC=_EWR_a%^hGSp$RZbTf8kIbyD;$pa1XJRb>PW$Oz{l3s^K{5UEx!X z28>`W9p4Fj(#JKX^bg>VR^du8LMXwc9SxLUDH)@UNx=_MtaOENlQL)p>rFoy)}+6( z5Ge%+Dv|@eM_-jJc+QFHv2bom`S5BZ!~wJW(_wx%`1Sf~z2?>D zsfAknVaHJH9@6UO*<0BtT^RF6e8yqH@Z1t{l$3W~!3LL??A=HGN3ZTk@bOcF%84q= zl6JggpSwTxQe*rCo_q9L`Ssz#&&#lw5-bq5v;h$IlRgPylAp=q-4a;2-`%Ur;pcSe zLioWw=AYA}2igaBdH7kA{B3;>sLw%fl;*Kz9`v$HML6opZ+-n{-Pq2ZcV)E3YFtuD zTR;<#K#~m@=^uPH)p%(!_u+jMgtq(f^)|OmEXW;!u@G00J4ywtnC~^sS1a$Z4IH&! zW9Q@7uIM!`*;Db7EoxtSXSb@90!80*Ofy$DggCZ!|Oz87^qU`WIv;`blkG@VrUz^mY|nR2{Zj?4p>L=w+&@IAgyz zc)m!Wv2`&OPb?<+k?7^Ix*|$>QqCsgSsBrwIHyutqMz|*t%~X!ykkzT&ES5Ma>u%S zR>K9;VhN|TT2)gUE}R=Ra`%!we15}46QpPy5;uNHyG|Ah+c?=u0HO@-7~W>^>jGXs zNkK(wjnRe^O^lTF){#=kA|qSH(pxFUWy)~b0$f^p%PqR)>Qa@_!0wR=<7hIcVAq?g zTQ7pL8aN1gLum>cC8eFizHll(EuWT9dwJk&bh8yp@9GnmDi|y%y18 zaSK6Ft^k#@76E^KGf(=cp=fnc4i&!PqCLgpT3E$~)GAk;wg`lwo{M(lPeG~N+fNg? zSqPryo8>nP!P4No%LPdQ51EjTveEBz zEeSGAP39cqh7UatHbvm+CnK!ej5R3Gfo?x0UnP~E!~&GGg~fU%EwW2TRX{9ao%S}$ zOOB4FWoZbOnC<_J-!U)JMSxX1*jl*zm5mFr0o( z%A=T@>tFx)pRcGe%AaW1KPKTfJ{poz;ZzYcmJbZ6yL0wb3vz>Kxwpuaj^LmT^e<&G z1=jrG@N++;QB-}p;UZUYuGpHbSE;C{Ov&-Mk-$O+e1OiAOi4(YCb2nrg+7sxXQG7# zPtrzlU`{z6!E|ARxZw|t+g zONws_rbJX&1v*15ajxGj4*2tvVaSkbfyJYvkx)C70&d6TgWp#oKX+LUKYv+<I%QF03m&N4ae9prBQLDu+q+*7^Z6wNd3S@5c zcZDcV&&idxa9v7ymw}qoDmbWnp2wp&&$TQA0WphX+|irGrErV}UY>7B)iI^8tynLF zl?d~0sbx`VsynDsk4z8dq3HtOsD*C6^=ZlnDxr~I#UEIrX_`#91RB<;a3?>kn0z5% z!yjA)0HoHor^qm~a3z6!rpOEuXC9-9>K6Ew<`qc~S*7>odm>oto~Z z*KfqBhALiU?pxSPx!N%mYNJ%;Sd52S#W>BDld@OHp)~j;wTJH)lk5~hE@f1H-D7U7`-CghR0Z9e(3f6S(95#SFWdbC6Tr%& zawCv zyZ)z>?B_;s@3|Oi0p{VVX8QGhryRcpOUxlNc2%p&lUuWi87_y*JicR??<%7O1+H!o z5InFWG|nRCE%M9Z4Lb(ZM-(5&$LHwLInE|TVnj*hBo%T59Tjb$?#IcjIPrxz`>p5n z(9&*SG^fmtyJEe}NVdFRi_*=!!GGtCee@;AE(vG%8v25Y<3kC^+ZU3k5TSGNmro_K4i+U9mu7d1V%}u8uSwZ>=OLiOPoT_#2 z+jTm_b)I!|ISX{t*{Fqi`4C$&j0NI{uLZTqT2~NmY?%}?<&~wEC3aO~&9a*$uM`=L zh+H(2dXTO*uZnzJWhHfXk$i93TWlURgA#4dv5(rE>3f<)3HuAqdudh%{blT|J%>tE zSXY;=!y@5Rg)qaJtgY1^OX3?_J=|FHU@0qwwvS$gb=9``*fFo#yJTM#1FORB#~!bz ztnkm`!f6d;mb3wsH_|DWlj3+&O;nnc4l5Dog$_aMlpA;179QoH)J2DDmC91B@`}wz z`*Mjz_};rmjJyP1hdABWIP5BzOH8~L)YbOgyG&GvXk#f4pU?{JR6Vv+A%1=hQ?MvO!Kmf7@7bIKHWU=*@bV9dhh+=83c`}IyMUj;H0 z!Kcu(!1IlJi*}H^xi)$Z$uwI`je8!Liw3?TlphLVM~HO{eLk?4Qh`d5+23TE!xl4I zQlN*}|N5Sj*}ASPF}KI@?$S$<`LY8TtyUJJ!|m|o!|~}J){fgn$&6M{@V>%6>)}6U zq0yScgL-lu;l zeQCnXBkP=@^MwAaw-7*kuT4U9RcGHV?o6SxxH}w9MQ5f=0SUe39ICrK5EN=& z3{CJtZdgQe-n4r_3f#GqG%<(<^#7!qG9&lUCSOx5RP$xd?;Su^h-{+jfQa?cC{LG! zR#b_8RkEfTN?`-4J=5P2F0Pk$#WKl+DVlBtvkeIAU%Lh~n!^}RRkxu87|c$?#ejm! z^cC++Ha(BciXtwTFBO7A6si)Wiqb^+0Iia|;TOZX2dBC-5JXbM@X$Xh2?&odDruBZ znvXds*h87RN!_J1fLR(~DeE}uU0GwOuPbmVom;o{?vBD8 zfx^?LA_}93lLn|0O&p*sf?wur-MCSK=%yYvX6F2O@?Ahf13K#$6CSVyMRF=NFiAtK zZ4Cn7n9p^iG$`m~N*OblMhtr+&CMhcB*|osfJLx$qrM&(9A5(|X=zjp+2!(C1X3Gq z?Yx&ov#UC_aUqBQ(BU6$-KT{JA!d5qDs09#+Kh-}cz4saCzvnX_~`rU5{2+%p(!R3 zoSWYIPLJL5C4cXfTw}S?Zx8{Do574$yb?C@T-_A%op10(SA}WGe?z<&{!Q1nB3W{4 z+g`@HG3Ee1kV8;u<2at&QvOoT_l;YL7IH9}=T};^(d-&?J|4|M{9U-;3pC|hC)LcM zi>1SOfpG0j3ua?5bRbQz+_lNZq1Xy%t=W+g{A6NBFXe10r zo-qvBf_MjHlHb(kZCaS;rerR8(Upbh&!+} zf3L}`H20%y7%OP@9z`j}a=8T(rXE|DW3I@ADP0;1=eJCcUYEj9JW^?+Pn6^QNd{dR zdP3h?W>g%fVI}h3$QwvJOZXRH$8Jd!yR^O6Zjb{3ThtlU9+9ly zq~Ro%4mJuA{;u5SjH-~x;6dpNB{MkFCQ9KV-@<%`#hC&gSniW4kUMp0a=#VX5LN8f z1O7Lrf z?4$|uojU5`nH;BL@~!ZEf^>GJd<)NXnZyYl%)-kz_RLVxK?3ldb=+6A0L2V_fvjRW{WxCmDEYhc$G!U zV{>*l*49hVjt^w^#+Kq+yQ2?l!SzZ8RGSXI+?-1Ggu87CrD6T$%MYu<#&DN?f%lU2 z{tAv&x@fA4mC~+r_xK%dnWE9*UNpd8U9s)cSk(+!WC}&6ZPE3|gq5T;HNj&>w~M7@ zj+A}=E|%g(6x9y`9N_Lpwt~~)5}X`DT05O6IF3L;fj`m4ITNj%sy7wHyG1M8`+1p6 zCozzcJ#31gx!D_%NM8(Z&7JjP@Gl;KIiQIOA!$)jRg1I~hg-k1YOG)9=F_k1djpC2 zGS!%B`t*ZXJ^fy<;?dM}$%*uLb$E$yy}~mQe>^+K<4-$37dutMQ>EHut9>%gIEO?L z?8rmnGCj=e7-r_so;X8cKEVHn;Z{G~+R~y?=3*xyr%(X2x8qrFTi&0-`?5v&?1)hR zl~@{Y|IjBx_=NTE1)sQ{Q2GLPz?RIQ`U_`z^2s4~qTej}q}0~{J|r*^#N`jE9OD$% zlDDtnZABMz$=iBAnZV{Avn-B_ffBfUeg&Ts%D9(&&b9S=8Bjl6A5#&Qf*`x|Ar<9< z6--A_9{or1F{uv{7F-D_`ND#?psI!V2VdL4AAXN(-tR`Bqi!F!_M4~s&EKVu-JP9h zPo9K-060B==Kl-VPH=kUj~-M!~KVYvJF@v~=t2zP#$(G;#Z`u)Q254s|Y z-n;Ah|I&+%@Q0_D;bHT%*=`(%=a+8)8A3vcPE)M(aQz@#W3Lwebq*5f?#q|Ezz5N! zoKf!P#{MSUeDShIkHWXG3qWZa%x+M0ev8f{+E2BxHR(yo-OB6P^QYknP@u4J4WxTN z8h5j#KO_w_+}YcG3>{o{8UYL2DMtv>DUGuk^UWSwxus|(=u=%h;{e|6Lic0Q8v>TS zF}4s`>jaO5PJ2|6yG9Z^7Cju&X&Ez9*&4;hxL*(OSOFa8IWX~YcNC*Aa6xWGYAI(; z4a>^pI(t5wI8TNX9^nlA*K|c1e-MWw!3(5GFUPhvA!B;=oyylQ%Ku z1&b$f7LCI5c^A44j%6aqStgu7OMZoUl;KI0F?AI#>k6L*I_9k{^|Mn!ZX&-rog}As zxdb=WoXV-<6bLaS=>-1JLLFK(osLjx!y&d#hO*3fxHH)xzfaS%@d#nI_VYI>@577yYqlX76PfHlO) z0ECNP3^P1~=Br1RmvGNrQ$ETxAi<3a##-!f_KsDxz43(`f;-ueP$6LM7iZTftxCDh znrBZYP)Pn&NZlnR_6libEdPnH{-2CR4%7gQ3;)3nZ*dH9+#`6 z<^dSpq#ppXa>Nb5e?nVbI^mXZ;E2-sM}9=5?=#%ET+W2ws)Mjd-*~;imd@!6dL(yT zTp!<9U%<-m1Kb~4esH%3QOb|?;BXt zSv<{OkqxA0Sfvkjj8NIw+XVQ*J{L4`I1_7G2&0@Ha+ciGtJR84*W49`Hn)il(K5RI z(Wo1v93X^iL4jaQJ|E>e6%~77LX7aV8x`RN;Q|79tXz1Ghzr6L*4!$^=|IQGg`5i1 z9BV77);T2VOck1_Xx`wun?NPFvlrAo*|zFyhGY*4=2F>`;jI};Lr>@AZJ8F zDFfYb&V&wG=_l7opX<$~T_PmhiIHb8>>-Q+H+!_(q0a!x{j40 zLLQDriux$bggwxQWP|_$nGkQku92a*sDYx^BM~={%A@xuo!R&JFp#>+U{hRwvvY|* zr7%OLn%E|86qrHHk}tvafU!;eFDXiUB&+!Tq8Crj4q9(p`whH-W8aY|%?e3Lu#sR56JRlhoYPDg)HD-B z2pMF((@`Yo%H@}p>RhEGg!T)Zyim= z0JmB|B8wS5aRp}%IQkl=w}$I9m2SkFnR?dN0xo4B#&YLLNJqb5rR*%Zh6TG8Z#@s* zPIwgEyb823HuBd9Hy*$1gv%CN4pCJ{EFf8;7RUgM3V|~~^6p|xt`yg>=DwI7CbVL~ z2)5=t8Y0Lx&{z$0U@*fN82vzkYLiKCH19hV;VIKs9!~;YnQ-0heH{hQCWrLW!f>){ zzn{fKC8IoC2iCC;2;Bhce$DbhDsV-)YSFgvCdt{zAa_~;nXyCA;kAuNhmq$A?RYeZ zq*Fze2#Mt&$mWw0=!GV$pcD6NBCy4#3a}b@<&(gX)#)JnWI!F_+7b&ODw@oQA%-PH z3$*7Apn~xfC9er7B|xw!UKp*~M7Qujr1FS2>%lvgZ$g7)8AcmZTRHZkY{yIzjip4b zcIzy|M7Q_RS5;J#W*+6P7=z2}%GL=*s?iP^0~45!$uJ32KDOd-fS{Qsy?Hv%N8CFd z-2|i@a2M`Oaiar&fk}{vAcJ(@3hYi3$|IBLjiO}C{w-zvufvaVJjE@67$Cx3z@O#H zuu%LVQ=dx-C71zmr<=!ktOWV|Zf(;6AIdJyGsbF14)8%oN7zko4Pldhf{0SVS!}a! z!%~@5Vnv5!S5tCudUcz_<`@ZH^JZ3UjeBDG?p9ifL`>wO^dj;Z>Btekkmr6<#av}( z!kj&eIU?Rsi#)5W8ex=T3S|qJvcVg3VvA!Q?m|*r6IRN2>dKi!+I>PO1U{@_B^{aE zZb0W@Rp2EjvW(-Hk%VWF#||5R#m<*#)9L_xHWv0|L`F7zqht)QCBR~o)O78aX&i)`2msTp11|uM>@3l2fu^%#HXYGZlD{&O z&OzYB+zn)Pu8+%KSoRP{nMmE~pe9E@SV4)-ji6rebcj^(8CewV#w6>TRuF*}Ndn6H zr6|s(O6~^q%IGI(K}WF?PlCwxd^WaDVf_V|&*)Yr&!?CAyp86kUQFcbl^$05ig9!|LHWExc zkk^=qc@#)zQ~A}7qmpeuE0cL%AWL4u+HJg3O$ zJQlMH!3UK|`h;bng*&rGY)Q`ffh~}y6KIVLxhNTBBp_O`gQ}m&5y#X)F5=!8Kzxl_ z*bFy;gWlIZgr`DOulVhF%Js zh!>$;s4pFyEbFjzJNzM>f$iu|X%^5qWj&)!<&}~E%(*o|%_3o6&KL<@G#nz7v{_Mkcpem^QPEIP6t##x z(#<7;$R_@d!s~Q2N0a^llwQor1HDQ}x}6`3zLp4eGbMk{=$L8}PNR}i$>bg{m(+_> zD2^UANam#~{p@Wbi%Pq{phZP3;Lg#zD3DdK-=L#AZkNWeCx?nIkfDGWr1tnpHfR6@ ztoVedl8vV*tzbNft_I#4#l-3|wkQ)HloP?WkeA~iS$?uQNKN*6Q+MSz+}El$#-$(=`Xk@&Y%K|tmgXDVt7;9PvI5ff(EQwv3i zJ1n}mINmyt+{gU)ervE8{ydY~iBO9F>*CQ(?@sK+O6JUZ@3AMiGUKXVD18 zGGTfqQj9ol**ZX>g81s1*U39)54e=Zac)Z(f?OkxwIob*PmCTr#%q zgq?X;xkHzsFOrMr9vfJq!Ui!O3poXOImU)_;!Eg?6FaT1m;pS=ANp2KPPT()gPhs= z+T#+1ed_o0(HMHyM81r)o{JSW8@%Ja0Bs67m}0LJ0>;{l!qt>?k%`%H(k zWXk?zWY~f7FC1JlvJpAxafRL^S8%X1f>|EH!e1lMQML>6X-q2~t1Me9&Bxs?ffa-igatn>wbQOry9?1?RJF^cxVDf{K zwBWRkB9^lQ&{rd7GD371UjVIB*Ak9F(s3k?Xu<}vQj1ipUxg^H18K%l78)pFpNiWg zj8bDErMRI$8dQmu9+jj50BB$xUOBWq5q~+`ILA}anVgUkr;&oS$N>h43{R}cfJnq< zAU4+2FiU8p;;SpPc%nqWh>FM?f108hm((ZW^h(VgNd;Y*XkMD(`5pm@I5#8=rVG1Y z+&hv_bSg0llA|b^BNvznFGD7h;5vFv&x&CMW*aJeQGzCqkfE(?u_9ookDXQ*8H5UG zjz!Qo-!yC?$!zS685r#xS|!wOkQD0xKpjLc7yNI4c|=6@5_aBK#*IVNm$*<_6Mth^i7(K+R$0Ihw4+=mmXgCt*@T|^W6bhqe`DB@-f5(hx zZbU<20}1lyl)c1rR*Dv=7g?Tgm$)UzH zkAgz>ydJg&%-6}9LRCP;FMvD%l=ffd{UKTMSVnP_Q+7B9Ac!KviS?y{tfzVp&|DL4 zu&a5TNMNBjt6{s&<9xFgI9N!sFu{=!0dZ$Tf?se_JSq_UNFV`iSv$6rdQ;gn#`(cE znTeopx+v_C8avx~FC)7^(6RHE{XC<02GWWD(~C#ua9t{aUk36I_8oiNmZZIbFu(U%;jL?LWdq9-Se zLV?>Y`cGS)#cevzh=Ns^++bzq!k_6E?|LWnB)35oTuEwnE5~@9^JW}&0_OAGBdxoJ* z$smsa3&Rsy$2gsioOqmIh*2F>&KRkVbYnE}8+71j)(MPYvhKeas;_Rges_lL{;RWae_vuquDaBcZ`4!;|3WLPn zJzIeptB%hSBN-$IpO|O~A%nsRnGj#43CV;PgHjC~E;k(6RIsSsf4u63jKl*QZzHKKG{RM7#i7V@F)Tbl6O# z#$lP!%>UF&1z=;&gk*p*Xaa!+1XGTAE*->ux;4TV8SuXqNn>Jdm|t5RT3w01C0V zo8VuVUI*vqwn2Lb@e&w(g0vk^ii7l5A~Kta7rhqO}p15Y~7OlSZyo zI+W&a-5Cso+bR$gTx7Q z2LoaU#>AMLXlF^$KpsYL*JFhN<@?H+I!ixq8&>GKyv0B$_w9H8vxzX z>>e*?hFeOxTmy@I+`~Bj%GK)05GyO>;Uu3*R-`?Z)ZFds_e9dibWf-?;2F z!;7P4c-}rcY&TBAR!2i(55l+YW-~l{8}1)9+K0^=zSnNz8*W<|AnP;$Z=KQa=07f) zrx)RQvwhOKxPaE)ybl}a=g@fL&2ck4ZoC6%Hvh5TJiiFv9W_sbGi?4{3&zvAXy6B} z)9_upbIPKdJRb2Zp^K zzH40^on2m-!Q-+ih&+?38KCUL6+?u%!6|;=twUG0wK#{QD)$rvekOjm9Bh8v@f= z_uyR%I>!|%E`E(Zfd_W+-vb(*g(r>o9F_fE&;y2P!nS>^0Hm!*2fGL*hPQ8#8reF(n#2V<;1BW z9?Fv89zn(J(e7t;*bAMOz~oF?5ICBce%K}aens^D?~`l& z?|5ncxBOejvzESeAItN{ja#b3eTh26^X{=iLHwtK@?kYud(Yw z3>p&1Dd)=HB(vTX+GM^8Pt#fa%72VOWgr}(lu6xSuzrSmJR7G)lJ9AP)Oq9L=)=X? zhjU;j?+(_!qN){Is^Tlx-e+DtY@c18ubH2nqsGD6JNx^PZ-fDi?S`)AJt%q;#8`mmtMKKMCjqdn<_F+63O3kG?p=mZ z;ikYT44>@mIIjw{=q`+`gGalefr8I7=M(CtY0g%Brw*2TqzQ}LA5>HM0PS!zFG!de zyju@IsAyj_I~QDb{KIJjB!|7=`0Vtsa5H>i-=%33-*s<3p*2n>$#~B8opJPu{+6@y zK+c_;^LXHox@ZYwG<9O8;6&~I&z?Sg`~(_96HYRuNsDq-sCa`prQ_ridSs`HPMT7T zGoFy+;W~!4ysk-+Zed+-v1rRFVO;+QciTr3Xn?+fdT;_D!6U-)f(2{*gMRTq@!6sG z?9e=ep0Sd5^`^{Cd<EmVvvj%yy@nteASgid=%Fcet_oVtNDHgg zJU;#aQa=cTrx%@&u;`eNF2oQ5KD;vSo0C}p&-oskKO|h1PAZUXM^B-Zk!0ZaC@+A_ zR^$HD9M{@d73)+fLCbOar@zR$AU4uA(y$3M?y*e}Rt%7$O(rgy98Z4tG5Z*C9JGRu z_bA5ZE9pOIp6<8bpI=ZiA67?1X><26&ivFlI}#SaMA`P4Q0QLiT@5D2qe$!ik&2=Y zG~{R#M=eW;l$q%DVe{~;!woSi6HSn18Ko(!#oYETRW4?nzZHIENEA&oOm z2mk+wJgdvORQ~$`^kP8Y-=&Yc?>W}* zc^Ry=C~+qorfEOyB01SOXNOWW3NI(gC!&Qd^cGBj4R+$*9Nk#8V677#M%e&svybSV z!>}`r20)DZpnX4T#|Z{Nv^sB2!`-c?&z`>A+uD8dV(Z0butxk5BNF;?L|#BF`-=>E z5J$6lM&fCTm20q;7V|5TIp9l)GN94o=k@TNN&J;Bz7JcE(C>PSv6gd8+K=&Idp&I! zd9tYo5=-`KNd6N%e|DZlCSb81tTiOa-E_za{LyToScLA}V2#B>9Jx7M8&y&%a+uGj z=&#L{wJ8gOiFZ{rtf3j@nr$RxuHLl5rs3GZnll!Zba=AUqFwqnW+sU)0L*uR8IzTnWa1g0b`~!CE)UL2g9( zP4}~8FzNA8{Vbhgpm%Hnj>&lyti8iI-slm3+>WIQR0)iAR2Hb>Pf0$@nVu+R09q3F zt@DfH_DKALg?lhOc7Os*GXRFbgC;Appx9Ch4BMc&^ylL#YJkp^Hf7>iA~!YxQdBAs zHu6z48kleZg%rO?x+CgPYf8O9(AM@e`Bv;7#J)M?fnaR)0z^nubD;#olFS{4P& z^>E9q+YuhdHA=XM47yoccnk}lqy-2Hvm2#T&a=A@)c&VA-0E6(sr=V&HV#gHpYo4) z%70IvmgK*^$B$R?-@oFrm1wc1>6k+^1t|>iCi=g1-z(VX_%^B7L@89`n4)cFGc;&n z@l+E!Z@lZlub^;ihW~Cz)$xFcwM_9YO!WhbgaQ!xd)X{##H{awJ)}h*K0EWv6apJdED0_2gV~XXS8d$PMKLYJwKo2NYiT&3nVo=)g7a;B@xJI84+j_=jesSVA9MWSeps;}IG> zV^Txv0ZJgaYP6#;?hPccnUu^(rg&B&r3TR}0&g8>>tIgkbR1JwrvDVFKC2pgt^S?gUnbE$`M&@-D`Z|DoJ z+%To}O=yr3P)!;g^^A)e*zOq}Sg1x!hh>D%9+3hH9p<-EIg6gyIG|Tsn*p#59;K5b zTD6-r&}_}20BdWs5Met>u99E=JG)MTwX+c&4|f%XFT$hn<+EVz<=*bzPS|cVj+(*R z+t%rE-qW^d2$@7)` z_pi9>Kds-fk?;-OOaHBV32(aF34iO3g1_na1Gf}?c5xJ59=vJnAN>t_T6fHm;g&0n z?!l{_qY(XmfeNcXZGHA(3e;HV{ps0xr_~ASZ&Uyde%$K+9R9d9CGR!_BdPwk9%H z1@OSDbCqNiWQc4Jhi)8surlXCy%nziv;`ymY3nCFaAG~!cMh6x{q^)W8$jt#XI}h> zZ#XSaxn=%-JvgsEkwQ#7rbe`y3+qlxLvD$B_ZxCfI=@FdIk&?j^&4`R<{m8_%806( z@|JmND+6u?UtAB~k(8zsQ=5YJ1u=X?_oA3osDR!vyR@w{uvZMd4okMM6Jk@^d!{{?F0bNprjI zhA^#Zpowwr3clt+y_*Hw^E}(eV}nM7ir$x{_s`D*%86CevlT6E8H0R*p8%9tTqHVu zFb}CB6y|5&%E^?JH8`B48Cw1JjVFRrT1lcbbwR%hH?E@mYLh|i2g)qkDs|N_X`on8 zbE0;AjX*}>(r=PNDi-XS&uWlkN)~ONVv`}A=6cr{7q|J~!BWG85SqZHH)EDFc7b27bH#*At&lbi-{a@IaS`){-O>ul)jGL2i z=!Z*b1t0QcRfJgaAS)t@f-ew76>dD<48Bkt6`oEPFuJ7^Dd_N7aa7VfPuvYn3cg(Q zlrC_O>g$)Ir#R+STE($S^&vK1({Y?ZK^__;RBAtqhiJCW9~OaylFggT!;Yyy&4Lie zDvZ&!nq=q>yhcF~6s5sHC;vrukQgIni`)R@drUU8`$#t*+Iz zx>ncfT3xGab*-+|wYpZ<>RMf^Yjv%z)wQ}-*Xmkbt7~ /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 0000000000000000000000000000000000000000..408dd24dbeb71201eea3e1f1797603b7bdf0f3a5 GIT binary patch literal 41942 zcmb`P37i~doxfW=FvB4rmz>2BGYOf5Q*lBtfdq^uArK;B3`u9EGZ`{7J#^0`gu@e2 z@kG}H)K$b?Ph16cbw%B*#2}!74J_i$Ol*>7G8a8(Lfj<&pYQv=RbACxJrnrbpU>M* zz3=;b@B66gI_5QBOz`{7s}hM*;NeFm64xD)NbEZ~k$5Zm_e{3@96S~Mqwo#z1$Y$P z4UdM0zS-*E1P?<$4IT&I0?&dA;S|^kSHiErS@0z|173(_4XlHg!n@&g_#`|H?uRGA zQ>rcB3Qs_P4V3>k!fEg`unPVXz6m}8&xT#_aQNz}mPbL!oeEzMtDX6IP~lt(75??` zM0h7W0)7LMMTrL>Nl!csm2b~O<-^~h;&U{Sk@-bX@wf(hunEfDry*IKc*yCuLgm*O zJRTl)jt%EbNYWGML786GL2#qU9QEPUMYuTbe8gG$Fq{Jjxg>9`z9J`EM$ zJ0L}o_^z|x3Y8B#pyGeP@k9zq={g@u{wgTB^-$@#8>*f>;Pj8fGthTK#b*+Qt$dmR z75*HkbT5PQXC0J3cS8B|EvNraD1SPj{5b%X?z3hl5~ssUpz`&7P;wuJ=fiJ94?YW( zk1s*xqj# z{#Q`>wB6}nN2Dm?#573JB$h$N|3gsW-UsF1@1fF{hw}FTRJzW-z}jB{WuJn|ulGZx z<6bEFUqi)X2c+sJUUi{0p9ba65~y%8PJg$ve+WwcIVk@QxyY8wWT^1wK-pgpm7gDm z^6&dl@qYp;T|-WP>RW97T?SQOS3;HZC!qZQHdH*eIQ|?1gj@ zi31R?64T$FNE`!ig!2D(sB-!yJP~e&%9k#9IvjI6ZjLRFi{O!%zYltF9aMRI3aWkl z0@9@=x}5&7xi+89gC6D!AYDx2MyUFJ4^(;l7gTyW;AwCVJOdtonf3Q#DDxYj%x`z* z-+)TzW~lOe4l4cycr<+7<+h%j2xVUbmA{umxmyVpZWf*eKLb7ZAXGfJLD?TN&+=3# zcNasYcOg6*W}y82GL-#8&U_1$`+j%|JaoQwcQ#b~-U%;&?}K!KiO)gBV-r;V=b_U3 z+AC~6O@V4ZbD;;dQQ+^e=^S-|F;t zIQ#pc()nYkcJ<#-?YkEq2LBFKuMc~tH9r~3|8t%GQm0=EUx#_p>DM~0hlgN(2Rs{o z3@W}qgr~xvL6yfgI0@#V{4c=Q!u?R?`|5Yu_H#Ov{Q2-qIM10kK()79p#1qRtbz|h zrTf>AAt&(^R6TvoLR-!!!^6 zc0tAWuthd~Q=sBIA1a*dpvt)pD!(^6`@5m)%l%N{{uF)?J_6<6{Ka;jnS@k<#3q=5 zRaYevRJFwIuo^xBm9GO(@j7gYb$jgDUq9sCF|1RX-2E+WLDr zR6aC8)%S0}Bj9Fu0o(@FpB#FPb$PxsC;<= zDm@3F!ke4b{UtCrb(ITotkOodA49H@MLFZAHeQ2yTo)nEP$s$YK^s=f?B)vGb6@D9M^ z;PLOa^=3Mh`BhN9a2 z{sP|yr>wB?PeO(JIe0#N4yv9VeuFKS8IB9#NtoXVRewJU<^Kav;XeoEE)SKzhpx2w zF$*4rei2lEbpuqrS_@U*Z-Vmo18^?97oG|`pvvQKQ0c8&W#@lqK=oVif^UQ^uo`|C zDj$E~^jo3w`z2TdPfOZx7DA=J0V}A;2)sMZ5KQn9@SvW?;@ylB^|#2l|P%|9Qb#q zpR?BH`z`RTn13D8r6-<&SHrU#t-JMbCi)*k$^8{7Jty91!@mSxg1#Qg{62Ug+zc;* ze}hWjx$Ery#0n_=J&wPJm!ltn3jeK5v`u&?d^>y`UJMUww)2{Ka4GtaK;_4?@Xhd; z7Ms4eLB;bHSPdV9lKWpc10J8Y{Rn{55M1giX7;Vk$NoDB=`Ojwh#^=k=~e@*Z__#HS0J_oOWCuMCuB;h;J{}?Kq z|ARB()Hdti^-%eI8$2KW1WtuJq5M6v-PYSVa4z~g;Uf4bTmX+>Z}Vdnl)s;a%J<(o z^Ve*!<#GX(e;c6k?|V??@@IH1Jn?4R-zB_0(@^HWhAOW^Z?W!Y zK&5*nRQ~-dRJwcMVtC=Lw%vXNDj)BKC&ORE6X0`D?Qsao{^;9md$;as>4o&%5jsLijra1Qz` zRD6C4kAsgob~%nhrLXEvo4&K)spw}r{c?B~`gW*%y$34%O>j1R5xyBt|Cp6q3gvzS zRQ$dORZfq>$#58|{+;-7+y2jm@~<8$KkkMX!-t{bI|k>&!#-j2_iCv6@I`3qAyhf- zhNr_RciC{Rgo;NqoB}`T%pZbpLH`_l4?OCVHh&x8>m>)j3jYbtf#-h8=I>3g8vR31 z<E->sY9C&xA+7MNsm~;gRrG_*!@uJPLl!@jm!!^bf)r z@aItSd3XUFg&wT_oQ=-{cnta#@HMa%%Dx>c{$GN}!Uv$z@n2Bo-UBa#ue#gj&pfDj zUJaGbl~C<53qANFsC?fFkAg43!{DUP+wwXN%H3&j4m{tPXW=CDx51;~o$x&P6{z?; z22X=S(1S;P!RF_A@D1n}L)F(CpyGW8RDJv!lz$IGrSlPZFZ^Gq@>u^*#2tPCz84<) zMdm1QHM|Dqpwe^Umuxw$fU2LjLiLyT!!zM;9iNAa$7{cA-JJuEM}I9;JzNLpz&qhN za0|Q$j=-sK>Q`+3EQRkv-vCuV9)ccx3aY$^p~~Tmdu;kw@*R0$+sC@YdRQ}!zm9F2x*>D&tp67nu#-{;Zfc`G1`tTe0dYFf* zH!niP<0Yu{9P`hv+~9HOS3s3p7M=pX3Txmm;3e<{sB$>#8`l1Mcqsby@MQRYSPSok zbKo;j_51j5+Wv3~RQ_BG74Ms&%Jbi#>i=_4<&cMRw->5jR^4aYgQwf}$$cQZT`PETno#0Y^mXvP@Ol~YTfy@l_;dJr)O9HRRy%%xXSxgXQ(vmzBc4)kLVtyQOss~#a?d`t@o*I~b5Q!7Bze@oS*`j14*!p#&d2;1)K$*zOrGC^@_(vh zUq=5qXK)^T0oCO6=faKHp99ri^}7-MrSKl-PmX6js$S($&!Y7EJ<3D98OuB2bksK_ z$nP%H*LXe|^-iAebLRi#D4EOj$L}J{K8N}X&lfxU%N!TO|1wf`+*I3X#_Vk<^#}U> zE9&3T)1@SCf`5W}Y3PqZeI_KUw!GWP3IF2k4)A;? zDv5q2T!_-I%GsaA^Cyi7bqTX!o*zVg5LH0w_c-cG^Ta$F8TBLYb9!MOYKqfuh7UQv zWi)^~1hropej^rUjMU?Es0FBgX>fN9>b0n^qFo2K$lU!p;h~t_2Cs!5Ky~wcJ-orm zY<2YUcK-pM?w&O+T#ZtHrC$~5J*a;{9gC_*eH1?*L}?5-9@W6}EinB1E1J_V|1kU* z>iwwyM7@Z*52fE7*#8vHLj6z%?)O^9CmbJvUqx2GxsG~1m**Sx;C{FI5Ab!^ZG;=( z!_NGTa1m-J>Q>ATL;b+neFnZ0{i(1ALZw6i8`NW{XWR^ov7dN{0pdGtK-k$r`+>;YgP9DUQCvv zPDJhq)G0il0W~IOo!b>Wf0F0L@Vm}zHqW2uc@ykHJ%G~h-I#p@R>SSagto!+y*&Q` z^-Z4NfcigYCmfBMqX&LVvAZ1p0`*~@zX!jC`YcMn4Hk)GvD0r2>SENNQ7LEkA)bH2 z^V{H?;2WL!R~$bEJFshl&qMv%QOi-EMtu+SI@DgCHMSnk^EA{ic^*U^&-3@;mr?qC z+ahrs=K3X3JIs^ai#Qwe&!T2x_6%w{&tFG1@VpFl2kKf>8uibpGf?-VZb3%B|8TsH z=SH62hgu~I_iJ>VjQOQbRz|Pk`3vwHsM~lx3-wmih3J0+{|&VOwH9?ZW=l}|y%kl1 z*#)Slj7cK#Kd>JC7f@r)O!zJ82F%u=^!q02DEBOVE9!7mEoOH+^9SHLs2@7LbvL)G^T2U2pH=dJboUQZPQq8SR$+pxA=WdPH*pjSk zYh0g_+mx5OxwSEq@??8OdsCCQm>_Ds$yxO8P{fw3O}F?4*QC?U-s1M=)v1gVxh|bq z7Z$0Sob{U04UH|eUV>*yd5u}Gy`^q#vZWzaUzMm@C~L2+u{l-mrQ6%Q5TP1YeNiq zKeaYdbzL&k(%8~a>upFS*A*R9Qz*o_k;pd?ABEeVO&NX5#tq4hQ^7gsWmN^<#posIDxr%yb`ivPf6xgDW&cq-pJb`u6 zxL#r79(7q?*@{%wWM~E1wx|=6`nASFQCnjoAI>W8R*!aZn^)7Wzk2;G)nCfHJxD0^ zFWo{dB!e$so2EK>NwuV)EGa2$s6n&|uWfD0a}^<3Pfj*w+cL?vbVfqUCpXnow^M7{ zRs@=K-8wXDGPH`xGo}%S$+GP1gu+}kdB%C?o|~N#(O6-u&No)ndLo!@q&9m^$!wc# zJ2O0Qp)?zkSy`L-69wCpk}VYG`eaih4MshMwP>L}uSvJJ(7+~Vr)0e)u5Q<&t@X~F zoITSt6Dlk1v8gH5K(nApW=M4^Lt8gZwW(fhRbEk$EsZy|r)Vw4N7LG?7c|hIQuR}v zxM|tsrjfTXGU<1DUu^vmA8idRS}M;MFIY+)rpadluY&}UT5o2mt!}1iu0d=}u;~pg zw5in_y~)|>#vqewPOqoIT5oEu@-nHL+Uef1-r~87=Ffij+=a{LTf57XEefJOMWB>) z%G;Q3&zL%DqHl7w)^k#+n^Se|Z7G5=8MVOWKfOR^qwNTlp2a33+S)eS5d0#@di7}& zx#nbB-P-9MZfv*V!dRjRWV4MFbA76%QGKL*D>HWDOV=jr)5ZFm^^)}7N(z0=n#P89 z3Mi1IdJt!0YbuAcxYmyWbuP&BWi9Jk$WNOE>i!jp>*ijwc){W;&+xoO?NrFsG>=qU z&9VjaOfPnZ6}F73wFB{bIMxEUOFT`_ypttr#@ z7R$w$l!g`{!wZA{}6ZLBIJx@Z@dXk%L;(P6uB!ga1ICOVU<*^p_Zf|e#Tu&5Be z>AZq^Z8{gzh@#CTDrMtYDv@Q(QcE(^uWHk?+4-04E$C4vXI(FD^E#8VQ648zR$!vU zx3`#zQJVDj)_S$=d6z9Rxe_VokX?jk`e1{B(@hHC3od>SI z6$6X)qC%|<`w>?!oxRI|N(l{H$5f4|Cl$)T`7v%%olJaf&{&hKuQ#)(`qj;L&f`U+ zTq+X@v|Q9yPCN9h(rCh1s5wFD$YF*#J51Cws@GA?HTDN38M4oWpj4!C z;ilK8GQ}ROGz(n+qejF$vo+J$oTLy;oQgx60?V*UWBnK|C@qvqip%eLDrbf-Q6bsB zb>;N<665DhiBx6pTq_%|>N}B02}bfEbu&u~S8v_ykTpP4dwt3~v*}E`cug~(%6My< zk_}EUmC3MvrRg!j^^)yax3o3ZCEGM}Y)-YUO}m+6L{9C%=3J=Rl}QAt9Z#sVSEwW# zc&03>Bt+{q{U9kyXrQuDG9AG|B`=U%)0kpmX1jnAPlAY)MZ!!W6^^NPm93+>91bM# zAu1A65P@V6o!ERS7pokta7omA<9ipDRgTB_+D1>Bs-La}A$v3|>+Cu&oLqH$%CFK! zXmi}RtG@T5YU3G7W_ zR>=FPP;90LB9ZitAEk(BSuvLScu)~^UIsO@%vaNsDa+NDMOs;4Qz54U`@r+q)Rl`B zM=e`#0tpw{iR|MOZo3HvpfrQOzd^w6hR3#!zw2QaaJI_WRIzxjPtzhao|!(o#4_BE z2QFChCe8H4n1o%dax3MKwHq`2Egfz3g(|QdSPy&wwAeYC4a}_5Mylot;l!xnQ1+a=bNL9dj9Mv91BUfaC~p#12mf|Ym&57Hxmea@ykaBB~dUk(Pj}iGy76B{_uur ziSy=l)D|x`(Dt|;rDnH}lxc6Vd!b2AD6|8YY_dL^vZUR)oyc&TY)P9HBo#er+6nU> zw_9673-xrWfl+HJ!+`;(3(h|*IB;lSA5q43y41>+AY~RvxREc=n^~7RDroV|!W(R6 zN+0Qtv+b>|>5RY0Wv9P(D>BrYNmccRbUPi6>8w-sE z4#h8=a{EYrm5SMp!|nZLQmyH1qg&jWzSm{1U#1bS{5FyGH+$`YPR(2!1t(ic$~A|H zq`V|8v}VmgdFiB-C#zFbJu~Yu=TRolWNt=NZ*7vJsMRU<$ZT=CvKU8TmZx^pyw0S? z7iUOoPPVu;7^exXsk%mb{d%uj=R%X~{la2nQpapD4a?ZXkAv+k$SC(*iCLT@Vn`Z-%UjaMBkKF$cPm5%f7LO z9a|Z~Cb4400|K}46g#Ex?ZPt(-z=C=ghI7@SSrlA_6$qywx*4gPy6AHu~rv(1_dxmsyDKAky-yDXTT}JKd`-L-OYGT^7#VIxuiV>SOEit#Q zE|ul5Anj$__20HO$$nB@9fwzK-n{vX7tEhW=Yo_mn6J}m+h@tSELk7KL^;5jTH#^297dIKNCzt@E2A^snCIv^VGC1wftZs#P1?!m7ffhx`~8VCSMHJG>zCm zVq_wo7VX^*uY4(!(E3qBZP9||y{0sm`!;e`J{;?Szf8;?k=uD+tUx4`V#!CsGIb+7 z@&`Vdaabj-LwI&k*m!SEattd0dz5Bo3`%$)%HbFBWZR3Y3K^c+Jgij{RH}HUO|JLq zlZ@Lf>ZjHC-d>fM*O+W-Zw;Nu&VSF61=q}!LLHI^-yIN+>%LLdCgVJ zmds`WS(SLlRU9wNws>bIv0(As%dcJVZpp3o#eFae`yQ57=PvODzmIx;0~B= z6VO!|xwl8`=ITnZ-?E*Sxh`NTeyVoTq=eBf@vpa7^Jv#;B#ifTjx)}Cn}16pVjdWp z8#_yN+aR&fJhNG8W1m>$s%8+{+=i5I=#sj~RpzLOHFP3on5arDX0y_lsx`XS;2y)` zbYgM3IGLVq1{IYIvtcv2GDR>`LR{i$nxO~ZwOuZm3Oq&m$C^59Yo{TYm_n{fT*Xw# zcUqgcii(y=_|fu0Ba*uvRAQIP)=nxK`Ndu|DcLaeuLe;ggD_~}x-1no3brBY>3TM{ zazq_;K_*>{a77Pl1FyJ-wWM@vFG1UF&|>Hp%*cJ!b&G>Ed)zyT#u6vjq-v~qxTmVc z*e!GXQP|vuDfY(K6t9dWmcC>D!iA=lEPdB}_n=A@1YDa~O10X^SvYOmF9DZ49qg;S z<_?0(9&ckxqq1=_!vU=>d#PSzlJzT14X;XEdobSNRh%5%dvJTrifm*8r%MdxK1XP@ zmGeq=a_P_0O{7#@!95I~mj(0eI&+WBw(F3osS+NyOBjKWw)5C!3^{gw>6_R+v&r>= zNFzHP>X?>glMSibs#WV7TQ^McQuU3Ti-qphxcg_GvG-~?gA0k+*|gj?WFi)}oI`FK zGNo=CoMRUO;-ZUc)ydoHr*a?7wKy9&XSc>%!$m}M*U?^I)9t@>^U9XA)pE0qjh&UP zYq_*I3BPnjtT|=$@;dF=lM~&7GnJAnW3SYI`4{rO#G@t~pJrXUTUnpnn6>&v8m~k8 z>)cJeDo@@mpu@8FFRk?a;0C5_>&-PVImTA8e`P^V(C9Jy+8BJf2*sox9X%;$!xHN(I)hF?Kbrw>9u!`|3y>Ljt#DTMtI&wrspt zjV-P0y%Zy0?#6D^HN!Q!S6JuWuI!=9q!O=HCmGDvr+d2TlnxCXnism;XX?o1%p}im zERIXqH8PJ2nS$yDWSL+fafR*~hJP_mu3+fn3Rsp4TW(rFX89}+5 z!f`Dt{d#vFSJ#Hq86E9vWy0nXX$ahCyD+rn5VG-C!^Ht0aHQH?o^kSaEn9TlS797t zx?H?boVY&S9^7uzc$CgG-a-Ufkg;@BpC$o@1vCAv(Yd>s`eM&iimALt5j$28ie$}( zi=7<=S`BAKqh=ajX!&=xA4-Y2d@dQETo5sWcIv3vof)JF*{q1kb=4tz|GIvLBFKc> zpR|o*MaA;FkWyD0xZCOXC-|?k4fRVlZXw^pa&2iuCXiq!GLznb&~okzbH%zLlWbn$ z8Qrb(=3g;)*}`jYbH=ypDlv@^%Su zyM3QkxO}_k%b1Pvs8NYrdux-91D{T(j_ZJArccaOa8MN)B z%oH30d&s^fd7HdtRMOi8OyZI^>%r)_7*4k-ZIc=QSZrlWTL7|iwS zvYFdzt_j|faGscoLLWz%Briy;F%DcC9UYcUbkw*xUFvo@?}L~qm5A$tvI|w=cr{7Q zd7KI3VMC@>re@k@>u=GTnUghIuI(l!0rl3c8QX0Sq3hwchj2w%TU@qNnq}MHfmD-T zdI*|?>$MohG}^9dXAjC`qYH_eY$IZ7oSj?L`eRdEF!p7u{_fGCp5A@KD|>UJ9esrz zg<%!Gd-ZB}U!iB;u!_CT8`-n3ucyEYgWA{R4RjV(?i(od=g5gl9?4zStK^4$8>=@r zux}tYTznZTH;^C55AE0|$0@I`>&0&6=cFh5x`y(@-opygwwFmyclUMf-aAn63O&8s zbHmPb(@@W@{(ZyVBYXREquUE(rNWzscH~9^@v_&mo-Qb>cIF4Xj=sL!i+SE#+T!i( z$?fdvl`}8jGqP`IVayxN56S7*PkEl@N$FuG+gh@k72j3FF!b%V}4MDha>wD z>(6(dpmk^-pJU%XxC8pNVhjs7#rPA79jg%Uw7~5P=QkD8X3)N*VVnpB^Lw6 zQGU<%kvw+&d2h6Pz$5z#13kT6Ugtn==*4c{=<4!z9+2Zv!W|pfMYy9BFWND?!ygS? z#v@}Rqg{v2oQq$94 z7%cR3DTelyuP1Xu9lg2!m%7QG!pQ!Co%xaOVZHRV#mjFWDeR=S1u@GH=0}G*2D@Y5 z{wnl$?98c7toEMo80n5wt;kzadi|?Eze6)Fnrw@g@9Ws(G#k9Zp+dfAr_(lieqBS> z)a8grOzidyQ4Zb1#dpCX1|~{TCySy^VkDBj#0oFQwtie&`(BuSZK8Uq$%m^HmD>pP7J3Hu4wwq7N?90C zbJ>&c8S0^0nbIv*FuAesjpYVA`|~{mxq;y2F&fAAoithuOj9!Nk13Dx!@NJHI2B(Y z3+s$@$qQuiK+R(`-$!%Isok2|HiLRsH0v784d8Llu$sJ0G!b;oKTn(N@j7?(jtx;s zZ6{W=eSWBO7cIXk@iYwx7sPH`v9*O>G8@bf^>mUOUVpdqY;4%ulN-wQ(){x@dQC!} zCcl~asn@Z=_7?`!>Huu3pkl{tghtbd$>5?p)7M ze*0*y$4c{JT5d4cGn(J-J^aV5Pi&g~^dFwsVyzwtGG*u3KyGy3fI7n7+^&M^7xLu1 zNrh`U-bilP6jQCYNe=o|_PwK>eWv44Uqj7SdY^FR(T!)LxjhHe7u&Hyw#86`*Vmpl z{jcj#J4`Z&|4>iI3x%-(l2z#K>F-d_`(kdO!$sleJM;A1bbUiZ+jrXvBj3x6ow$PN z?K!ZsJJil>NS%8KMCH+67}~veSAM&5vDMW~6<(-Job8`-RHGnXIYw26rku@JD$`!d zWY|;BZMr%9uvSk#wRPLpXSeW@+ml0`gOnXPZtC!8o{*K}t2yo+q!Qa~qYuxGjqV%m z9?cD#K_>hj-1t?B@neeI(p0G)`4`6qyNB|lh5h~cfr3j!P>eYS$+o}E1fTF+>A zwRvl9Do$0ZHtspU(06wC_Y}s4b}-aC0aNVb*pE}+$oL&Yx!pGLxuHGz?R15`J$rW^ zpaTioJsR~_dk6jjK3OkcwAq7Dm$iVm{oOloxq?@QxVG?X+S%S6Yh}%RaW4;ix|C#8#_}CdYH&;jnzfpz8w=yQCVCU z=Po42t#JA~SzCKUW4rp<_9^QX!u?A)!;N_l(@`1fs#i&FS8`X@f+`8dq+swK>=@WvG8C4l zBN&!7gbohv9VI08{(|9DrEP0#>GYZn%7S)Iwee{xg&LP%D?PR(%L0oGk}s!jRdg7e z=M|-kJ^TT;oC;c3Wj8T1rufo&SzeTsS*VYr7+!8qRdnrF6F=+ObqRLhnazw1cCgNL z`y+qMv45ncX2156`f~lxcMND3m~K(8M{D1WT`YF2*&@%g$-4c;e2?4v*|xi*kG*I4 zZMMYxt`bMP%uaUx#a!>u_UAPTu_>+S!gS3C(Jj9s56TPtm3b3W2VP0CRIav!VkQk0 zV;0UFO-sy(Un*_)F%CZeo%~>a=XQStsNiKd_+ow*_Qz*{+tlcajI_}aqcohr$%K_A zkUZ#W7PyF{f*Ss^ilU+~2VIyIeF(?nplex0-~9Mg^l8&T&z^zKF>}B)VjA&uPP&2> zPR?xx=Un#~DJuFBx0`Nyd%vp*cfkiEA2)(UI@A(RItB_oY#*ueb}@}N8lO{M<+a7F z6_^upyruAL42mw58#*v8wdr>0F1H~{{#B4r+(L`r(jZ1luV2LYX^-Y=Vho4q9V8(blHD)1l*Gd#58-%pTIlc@aG#jB(7=*j*-ZV+q$uieh$5;dV!8 zM>D*}55AQ!kznxEgg8OJF_^mHAFbJ3A5T0qKlNvNapL}=PRXuZoM>!BCJ1J*Fgmt} z%2?@;t}Gq>!TGC=LYcszY25i89ev$yP%jhdWWm$J-4e5TQXI|VvcZpExY&ZRzuJ7X z!R-@=a-_pQBej{Pon{+{!Qfn!vt{lWn3HHTM4M|toZMSEdLnx`?fMzpEBMFnRz^q7 zuAea*!0Ha@ly(;E-j4<${{m4BEwi7#Enxso%=YY=2k?>B2s?ZxHEY&N6mTUq z@3v{FY;T6l@~=fijP1=&>r-&iwALH3OKIJ&Q$Nkkl(@tFGGnjWc1$kn+I!&k2Uo{P zFB6%P^0t|0LzqBRM+R|I9Mi}9OU2OEk4{NU%*|~qZMS0J#=im=orbo*pdzwiS1eb1 zQ=_ndK&9z+@cnN~#5gkdI!dIuwx|p|SZS(4Pw=gYgK*@3mcmTIy0klDf*Yl#>F6FX z3CbTZHQmM})@p{gS&h3>1r`0m#FOk+a|vO{T>qoBjIk^8e4($Wmy;)zAC0Zr+(9dT zYl5D@d{iRtmXD2tFA;kY$ck+8FE>=$mkn2*35AOtroVug*h$P(EK=J7A3~d{;oZa7 z2v(3CCw`S&OcXuWq1)-9>&vZ~KQZ!qcwe%=vyWLxi77X@?3Ec?EER`|Qj6mKqOHCU z#TFRa?u*z)=AaRq;v6#)oruiyRMKA4@rDKx8*O$1xk$o=&F$vu6ZOya2GJW^FH6{7 z?+W$zv95D|J@%L4!+bSkv%OksHZ{%NH*Ru;CLR0C=QAF&T-lnJixaH9;k8Ngv+EScFKh90#VefHYjB~~6XZh7U z@kGs*EmQH_9#BO`BLx*c9epgvoxNhc-KPTAhc=4M!W}B9O$0mmgcVFh6l=S6QSPRA z$;u6f$Y$)9I0E6ZK3AajMA?k*x}?M`LI**lIS}P8Z*Iq4-Kf$)5|;GWaiOJP#9?rs zj`1Y$F48BFm3CQEc7QX(dnD#YTD&i0l8uTkDf@Ss4-CY45sqKDcNixkp{xkIs1#^O zJbJPp?%%@E#DOX8P~1yStDU_+Nz;klo*^cTW07NCq&jxko3xrp#QUL0C~$j`+q#cb z&DgMX?=Kow&@wwm`txI2m~zL@MaYk*CX<>6?&B&V5@da7eptMu8Qd1^=YqK|vzoe~ z`-8f!S8GRCa|zTdRN-H6)zq&uv#Ju?f@0T&-o8Bd{mqG&f0ev8@%WZMZ80xVh5L_^ ztIA%rZh>=OlrE01hxB*uaL=KexKpdRtDfu4^&OxLiZ|IA`*ru3tlc?gdJoO=d-J<< zeY#bwiAjG??@$LTl#YHDr@1N)ZVzY$$4;$Qt%d!{pJLo76OK_huIcZZ?y>UiG1H4x z_KPA@f^ws8E}j50r~Uu+pepeT^MZi)7~2jbqx6!)y0C0tLC~ZB3P4rj874E#lKOh+ zNp;%vJjY6f0d9&?8YO2*{z8$Wi7Z-8cN5;h2}+U1JApTqx{Yz1sq^%2qNAC0_l_UgWWP=F#FnR@`om*ex2=3^)6<(C-}<|)+e{S;-Z
ZPtt?$woH_e$~R5vqwC8kX6VQ@`lDiK&%Q0lP}1Qs(-4_C=FJ=Uvbgq&QzQZ$^dZ zM`R>3xNt@5>tc_9Pp|mZGHgj8{);)Gqda9q$OoEgiI?`BsB&{Hx4GrsyO)WZ-T<-} zrAzvKn>p13Q#C1ybnUf?aN&80xcl)z?@X!b6(loHe1t}-8~@>0n?AIdC_>t-Ymy;X zC8I;FsxGCxySrp^XEt=AgJ{V{Wa6>Sk3aK2u6Njm#&i>*#JJ8z3EVMopuc-ML6k+- z-l{YU@qS(vAoHkpH0Taa@jYgg{oN$uaq3Zju4hK@5OnFG@4A!}mtP&-yuQry@`5aJ z5tO$oa`A14@B~b6JD7T2*_vS3sqZt_GWE`vc^Smt)WS0IngaS@GH5$BJG9tCIy$C- zO7mm)DVX5J2Dd1(i!Ntc+`~y&6UyA5R$IYmbrchP7KV8SgC)g4v4yU$yH~10ABUmY zFtCOt-6oRzMogJU_Fc`8NA628SUAoV2s~uEQ`MAJ80gQw6AE| zSK%^@i`#eguk<(3t?33$t5*7(-n?pQKOiGR`&y+HOY3q;!92Tc)mxd72(4kWQLi+W zhRGx-Hq2r?sz}aS6AwSg60d{r%H;cUdscG1#st*7-nWPzYe(4Ny5cK-CM65P@AwhS zeD_AFa;;iXGk<={Ii2d`8dw3pG($V9(46Uo)6U}>I@^SzmfFJZY-Km0dz zO^({#>Qa%=2W61516fHPg+%N(XAVNjesv~J(0@0y7?HRy&qOvl%nM3xg`t(MZkC%j z%Ct>M>m4+sDy_?(h|$qJtUGZll~XK(Lcd4%QycUPCP*=|fzT#a1d(4QSDWl11eMoL zhzeowV`)r&HXjKCT(7~)r(~`1osXyONWuYLp=lg%!sTvj{Eni2afvX zI%KUZUdyc@$vTFUy|6tdjD{6Ns zctg}o=xr4nW!Lffy}CV6bQ3xoa~H>QF=D=aemJ4b%P|3~_4+z?(ZLnJ{Zq8r8CvtX z`2;SitXtLx)6GYI*r;Yp%zSkt*N3UcX;@wl%4*v#?bm?x1q_UX9f9!s%4VO%ttH(Y3qxDjNo11lg}yWt)Ccvi{)_3w z7Eqp1-XQgak;AQ8bkTZZr{U}gd$2wCf;=c%n~nbxgWw>UFBZAzPA@J;%2%l&--1=7 zJ^XYR#Y{a^r2QR+Vn4#3ez@wDJF8Sl?P|i*#{?J9bEMKN+*FJ7wF1Ah3qEZWHP9|t zWbR%H|#XnC}~zYOId`N^{akhI)$)_n2E8ZGCV$Y`Oj%eT`m zu<09f1H0HO*A0>4r;p^=7bv*{5~_?g5MOSzWP3BTbHX^OL5;zW&FQEsd$YwxQKNb| RWSj(Z3*zc7Ke(gU{|CKLK@I=_ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..1b0d71d70621bc3d8c301fc0c488b1cbb2fc8ae9 GIT binary patch literal 40606 zcmbuI37i~doxfXFjtuu5PAfpjBxHspoS6_H7ZAur4nhbqsp+nn^c>woA8EP?B6xBv z3%aZqqAUnr;D$(KT{PDiRK4%- zz3;2?ougiPUxwf3Uy;e23|AkP$!y#&letST{0=%Zleqv+aGVEE;k^zIhi`*Nz(?Vc z@G1BHEIgR^Z^2{XkKyU?PjCvH#Gj3DF`NTG0DIw&U=KW|JCnH>&WF?Ct?*R%I6M(P z=lBzNJnw%s)w+KYoW}blunP{s6JQmd0sjUb0zc~bX?PItUv}@`aPL2K?>~of=MV5e zxId07UWY>2I|0hQ)1bn2HdJ`8gcD&69t!V)ByHvaI2k?$mBe3zO1ED?rO$q6S^YDi z!o2``a08UR*T9qD!|wf4Q0co19tU57^5DVoa)VIu zxecmZJ>cG-hLd>zcc}3E0V4vBAz7Q&12cg`*1u9)0hKlbOpxplv zRJabtarrwHsyr`-GT#hkem9i;4@0HXSKRw=Aw?u}(m9z7S)92H%AFFFzi)wZ?_*H$ zdjZPb7op;H?77zb0x0uqpwg=d6^}cia4;BAkIP=5i+IXA^O}T`! zw;7%UUkgux_d}U~-0_>x2t!xHa>Hq%Iij`@ZaJ1J}CD-1(j~!cKZJVPvQN< zORRerLfKmfDT0{_oCH4r4~JibN5gMHnwZRskRW7ExiphG3a*E8zW|j__ri&A2UNN| z4_^g$IUX?2=Es@vF!Yx~4_*(IA2&ml^AA9^i_g3Fm!Q(=wE0%P57Ja+)af z*;@hSZw{UgZ-E|s2r8VZw@?%_oa{~G;=FdIG%t?{}-U*`x~fqns~X*hgs0$eI1m11Ipb8pvu)VkRp?L z5gq}1udw~}CGbtWUkPb~GXDx`QZffEw*FiKm5x4~0&DP0_#P;KJ_i-Q-Eac@Gwgx~ zU1|IKqoLkUhKIr_Q03)3sQ530vhTb1sxyBJR6HMqDlh*Gm2cmI2g6@LmFt(B{vlUc z_a{Ngo$cNi!UK3;>E72l4#NG=uR`V5jqo7&Zm4?o2vm7_1}a`JK!yK%aDVt;Q2F~S zsQPon5-Wc?JdOABp!BbWs&B(k?z{tb!H1yY{Wzqn%6tZ@oc zvlpQJ{UcQQpRmTJ!Lw;W2RkYizkW5h|WDq0;#( z=)pWxI^O}+UOocVu74J)ynF|$TW`9Ukc^^wNUm;P~pE5dhq>F z;rkbOJp4J7`}<#O!+R)HxIE~=i=oQhMyPZgh7;kvQ0f0cDED80%AY;(2>55H@_zU_ ztA8An{v@dMn+26V3!VO2$Ib8@^y^Ud>oGVNJ_iqn2VZB?@g%5podqYt%c1gZlQVw< z?B)G_sBnD|%HJ2D>8GH=ec*cQ-WgEwn**mqA1ZzChDxu8Vb3cV_rgng|IPK8Odq^p zgDqzzDEW6mg=-sB{5}VdgWrTo$6vq`;Y;v5c>Jrae@o#Q?+th*{29Cyp1+Yc64u}X z_$a&({tPOS>{{tRd8y*O_#+`>2*C+x|bZ^?({zi zRe!(k^#24W@qT*N#%mE&_=n)B@NH1(v;!*syWmOi&rtC?F=ySI1{MERP;x_1<>WS~ z@NI*qz^_8te-X}t2M2b&;9__N?^~ea_bzw>{3w+FUv~VnGw&UsuA_fBoCfQT55vj4 zKM!ZXUqi+B%t6cLjyFQte-K^(zvkW#-faD!3ssJmIV>)MaoA@2`WB`w&z*d>hKYR}9;7*$tIXK2*BC4xS62 zfM>xU!#VKi5&OQ}@g_JI{YT;X@JCSgP9C+q+VPE0>G4nSQuuSIbm=YFc5ndBg5mM+3*A^rOX#Yg(nZC{{Wl{zYLWwzjO3% zu<3J!V;!o#eh@0XegIYO4l3F3dQk1%0w{NCQ0em?xDb8|%Dz{&=Ih`L-fx8-e8Rnd z4JyB0S+Vld;4I#=Q0en`@ErJMcnRFEYV&zMR65-Pr^64z^WZn!`=MLxdmmJM$Dq>b zov;Uf8hY?Wcs@L$X8pY!s(oz0nea&{e}4=WzbQA`_++8{zY|J-2keEvgcra`b(;?B z;IX_v0F{m(g(tvo!sFl`sCv-Vu=zCwDx8-?<$nRn{2s^0;7Pnc3njM;DqRn~$+jmK zLzUMJQ0aO*R5|zvR60BlCI5S<@J!okxg5$~1u7li3l*Oi;B2`6&DOn3;Ay-EQ0~4N zo(|vd%)jLLODMUCud(*#z{_~|;W3hjhrv&{_b)-^^MArVc_N7b@N>q4IMpl>FmR?tR6*{}w7gPPo;Uiy2Vixf)9D z4N&3uFjTsI1jhBv@h z!MmOQ<52N<7OK4e3aT7WdcDn`>es2k+iOgIN7r|%Y0(ivj*1gqG@-?V>crR4CJPnoJKZPbg z@38L8fL-Wc3J-=?L6yI?@NhT)l^$E5+D&jN8uFSzXX-fzk;f7hrHF6<8C;W_hG2|b06%5&%z_&@8Lpt@ZVa0 zS3uSC0z4bu4VAv1gh#+HLZ#QYq1@T;K5IS`%Ds!B(q#oyIn6_b`!1+>ZF77cDxH50 zr^Bwlv+=qB%HBG7DBKDqcL$Wek3#wL9F)7?g^Kqp-)7tMlcCZh3y+3(!sFq4;4$!H z(4-fXzrTVr;H0;^b{U?}`&KCZ?NH(Pq2n*%@w{i=VcX@2Q28+%DxcT8_Xbot-Ve`& zPeY~W51`_4^gAtQLzVN5Q1KjuYQJ6&yW#tx%Jo;F()&N4((#aY+4gT5RDAlO^63t! ze0m#HeSSaef**lOw~xc4;FqA%=etgS4^+JNzu%UVQ=sCt5~`i6K)L%AoCyB~9tXb< zPk_INCSLEh?#zZtzpJ6be;bs)cSEJigYXpiX?QaHE>t{Tg6F_99j8#DW3z7bLtGPm;lCin}~gU;S9P-(Iru0_2X^)yPqPr^^yNAox5^bdfm zP)pIB1N&n#D|z1T-rs=PK`8yshWFaX=3{~i7V>QdB|yuSy&7KXn;o)@_HEW8ah7#hMAyx$0qh0nq7 zpuUHC67?FHq4e8?8gtK|;Q4XX$5G*Lr+c^`nHSyjFwgh6=WX!4yx#yPp`JkHQTn|H z{g0t0qn_p6gH#Jsjvtf&zeT7Gs83^dK5Cvc`Q>@0sW-n1`1=s=55vphKU(cf4bDMT z-1|2j)sDq~6R}f8;~nsDcnlmxsov@L7Sww4#5yth^HAS#?|txEljpuWuWolrj?u7S_M zC!C)2yLdiO5B$`&zMl60wG;LCs0`{J)FUXGk<6P>1yuM`yQ$w-QKz7$q0W^(ent3? z?s+-yW%n$zVbo_)*P?d^JRQ!4v*4kqi+JvX??&nOZPbZ8m&}`8Khon_D4l-@e^cD^ z+t65uQu}s+)4QJM|3v*0>WwJII(vAL_TLFQR^l z>PFp#*&5VqcwPzhI}I*@x1kQ?S$)l)QR-vnqr%^j?%^b47NMp~q4xmlcAozmz6qWP zFNGs0{fLh1-ai0eg}MZFHR>{yem_QCj2c4bGt%Jq*F4XHTj72v z{pP|y*vHH%Jg;!i!WF!$kDKje-_7$>p8pG;2ak06-{O4<&kfXlsH0I^(bMl3RM|W= z{|xZ>N7Uz0`=ivaU5uT(;A+%cc^-lTa0BWisMqlx|9uF(htT*a41c$V4{$DO5@tuk zw>tgv;K$svaJaMkJDxuqbLVy^^C%2ZN4fV+$UNeng(~mAfp^F3{($%IqP~W@2L1mJ ze}wuK>QgZ}UNav;y%Y7XsGCtgL!F7t-=Ic#)^7)DE$ZL&!fz((RLqZeZaoI~L+?0v z2kLa5-wcaz2h{Ii$4lT9yw~BQPVZ{?C-iP`?~>Q=OQ@OX)!{VwO4J)OTWSM=XlnNxeHe9)-#s9w~s zQD{5{!S%vZaw2PsrQx_p*W|J{QXI?| z`n(L!lJfFpuUg1%_6vhSt}D~EM8;kvKN{q`VzuJ=1C^lUP0o4cAX_Zt%Du>}s+S43 zmmMjVks2tLyb_}MLg0=1`9dWq_=RkM-0J#RKq?g~rQ!%FSt)vBrD8U~PAy;A>=lZo zQGdiMSNu|?IySwl8;1soIj$8e-k4u5*NP?Ue%bmMbAD=HrfaQVD&z};eO@i_hnp6< z$rQqzC-8%WNB&mJfq5^~YkqyI;;?>UzD&>xLAK)c*X0?(>gln5n>6zLk&$98$n}!= zp8ZWOPv}`lz6^SU#CS|u)bI8CWs_N9*@#Jd>%E>ENt7EsM7^GZH%f5KW6i4(c>A2U zdCrRpP{Ml8JO#Zpy|=elo-K{NnGhs}_hRfD+Z$}ylQwgmjfiDWiCR#uB(0d(Z#D)B z+JFgsJgK~!JnF?(ucxX%IsI9sKY@316j91wu|O##ffsBpQk*KN!xVq8DYoB-8LWSTbvZ>rDCBRb28yIJEO&J;9;8ABxv8O!q{$5< zZ$o6_@A9tMdL&%5CAev*JX^MS6?K3nqZBzEMTppXX9tz+*`~Tjp)uYTYX$0Lf8Cp0 zo^CWs!Dw*{72Z12v)n5MH&kgJ%igkiOBc<(X5NxDi>%oKzaTGi0iIG)0QfXPyov1JlUKJ3VF4$a;;6XkE2#9WS-jA+f|IP!CQ6)& zLNX^!t6$lSes&~JN;$u?eqjn>-7K#{Uz}bkAT($ipIh{-PgXM*jF4-Tev=Tk$PMI2 zXcraaG#OKLOi$4wHW;YNWryQdrRUsEGit3E)<0QtCNvju=j2Ab04LJH7%J?P->6)~ zbH%!D#L^>bjBM5LS`(pZmKJwo>LQwIbKC@u+wPdW#j(J&-OYS4I<3A%ny%E@NE_Ys zNE@RLk#3r$McSBlh;-a+9Dkkdj*%_}J+)Gv0@@nQ$e@G&rtyl(wP{>TB}!J4q?8S3 zt3;VTPc_L5-?~l9X2)-~wV*|%i;EZ1QecBTPNb~B-XdQun1az7_3Btob$j9br6yGp z`5ZHgB}|%#Ns@T5oz-Sir6ot3kj6_SK#D`@x$Ycr<*n&isuLYbW!#Ola_P)n0(6RK z+&HCZBpvCH2hNRgqv~YRON06vKbJG3uw4JB9V~juAh*gSJZ%@Xh0}IDo79`o7ivt< z+H;t0&UOzvIH-3pR{FI%zV}v7 zuA7D=D(kHo6-jjV-#C!wzcEP3y2#B$LMKW7EP9%|o ziF62VWNPBdts5OO2Nzhls~4}bv90>a@>>1g``MIMnsZPa8lEyU95Ak;yID?#&<3* zs}xUhwL(i8(yO%++7u5>JJc{Mq_(TG6QSw2PK@~_=E{TK zh$d{B)W(At&ixWCPO5;7L~61{j&!Iqk-5pt4r!khN=@`gBoW{7gOm_$%f?n0_bGtR z$*5$uxoTQ6CAr$NL@kRyLIJm=%<59Bi5X$HYnzCth=;*VI&appn_X4Ab4Fmyt|>QbU>G{}_;$G| z>1?4o8kF)`)+z>hDpXR!!;Cg$QSJTsuzxq;-Qd)^CxsB-9xje zGT>8F-AEvECCndbv;@J(B&$Va&8$mN`Qr<&E!IbeDJ@>Ar`5C-rBSzzRH_#2TBy$s zhgRVH5$m$aOX?l9$VA+%Lpr0PnL$#}eN#^u_qf&G9%Mc3il8+Xl-O`!cOtUnvtcpF zI-<1gaA}MsLGmn;a6Mo2Zbn^ZtDz9;#TVGjkUr5Im#brA#ZtJ)rGQ86akDlNtL|E{ zN`qqz1G{rn90=Fk+>~6KDrkCq7#Gvkgj^Iql|&^lBBe4ToF%D+Oc4a^6kuOet{5 z8|G=ksjyCz35{9owHrb`^K1~DY$qvK9rh;W`P9&!fqin)NhwYG*;^=>QIFZrGHE7# z)0=vmeYUdt1J=lFcDlS6M_`VpdNVp~ViStfrH%RpHwR-kVJyhzY4vknxAv7L=fccl zVN%<4DHY3@r1yi>g5S?Pn2DR2``S!ycEK&iVJgR_)GZQ;tV?qzb&A_`#2An3jgjc+ zja}q69lsmSgw0g4LkxAPh4e^KyBun(+p&cqu9GU(+#qlZPpLzS&@4Wp2=$@?Ma);b zhNaBRR!dB^D zs8#(ib9$#{rcGNGu$a&c*tBVxdD(1GX0xE^m8<$&+3d5Pl+ChvRq+-sTDEx6LK+vO zjK(7EZre6{p;i#P*YWFFy0mBE!l{{gb}Aeu6OJ|WaK4|5LZTF4Pc5^+?LBCgW4Cde zZ8MhbpaUT#mhBNdb~-T8b~Awrjo8&^>)1>kUB}U87$$QLgD#lt>TLB)z^>f{zL=hJT&)K07NUDB0VnD$C9<7dQ7%-WMIqi7!Ri(-8+fMCTF%oFTKs4EjWp2>VK+24QG^!Y*`!*ey zPAL#8NwRguc#C}i`ZGJ))`5*=IM~ar2GczfLgOU$tCcE85tK3ts#{k53vD@TDkkof z$kOJK5N~NQM~}Ryuq9tA7R*dRtC0gl09~{GWx7h)R#3Fa8WjT?!BSn3X_srOROw>v zPMM8g`DV+Z@+>-Klev85@--{wGJ)*MT(O+(Wtle5++-Fno3~)~;%m^C#A0`9r*DFL zW&KM_*v;@OeK(nD-D0=FY^#8d+Q`1$VmC)$n(dZtw9IhC*s;d^c2NkNw3(9V{gbY(B^A4whQ&4m!&&0E9&c-Mam)xv89Ib2ZKe&Y2B(0~};DXC>|NH=Q0V zj&3Xz?JFnaSlHP(wwXhZ6L3pM%tizAE~ks0-8s=II@A4gOP;G8(N<_jJ;!80$DR zE({kWRKKxiq8C;c#}%v^na3pzL3M(%O)!$UOlJ?{zZ5H%(e-fztjvKe*D-UH&^qjT zE7#+OZ|X+rK{=bkb}cjgoIB5}W5>mkwsti$VR4B#M0T`X7+Z3PnS`_9W(N>iQfY2a zI61qSwL8wM&<`ZmqN0(1*z_}im>cQf?GoS_s$ zdG#W;ufP|{ngtg-I*4A?oi(*asd%yJ-x;AVE&6h~rGIi>qzKxfqege8lg4K=BPP{V zhV1$6T(1JifIA$tjblW?3Y(BtTQ$yhhV2RNYi~pCk_}tT^|)N6h{#?fScxnZYY469 zyfH_#2TT6w2G6|Rv~ba7^VTd`z13;otfRIGsj00K=5F0*6E-jLLK(9#p44iQtB#FmOFmo;HB%D2h_s{pZ8J%%SamXOwI0TH zq*xqgj%nf6u;acDfAmrmOIoqwh>sc=x>Wa4=##K?2S6@yH;OJO}!OCRoYBuz}d zD;v5ZD^bFv*-9ksI0EB3Vj>vx*|eJsueqQ=3#k-|c0ouEGd9#Hv^_3y(^MagrW>_| z&(Xqtcj(P@cVt2<_@?#NP~ObZqDG`IlZd$%?D4#%php>(CL1$koNjV4)7JRg^YIxA za}GYNd@Qpv_#}Wy4NZq59bJ>KBh*j}hmy9UP*lwrmS&WDH&suo*6VwU=Gsl{zQyG> z&Fzf{JPPe-cxAeAJ4`cKNmm~;@A0?FS^6p6S72D@->3)k#!+z^QoW9t9+Bx+xy80_ z_QYM&{RjEdqK$LXP0E(G_N?#Gldc(v*%I9}W-Mj3)@uQZVL{H?HNCxUGjw3wwizxf z` zS)A*+hBYxZ5BuCmxM%i-GiS}ZuxrKg)jbQeL5x|C7NGmQnX_ll?wN5x&y3mLtQmbX zW}P*Is~iaStPHl~_qhwZPJ|y5twioV_nHd7D=n_H+4a zx#2C%?-BB=F7zkFFbE{&#b1b!Zr|; zdKR(9qoZbh-i7^n2B!A1+pu5Rm}4B;yze$vtZgq2`>GmQZK+Pm1uoUqOo)aU4;Kk>KJbQu9V2-P7~4DzZ;+9}&iXEUp>Acdv3*;% zA-9m$8uxBSNYq?(GTEe@1T&s(LU zNDZwHnVf6HhZ_0=k1=ZhSYL1 z^0!!1bF4;zqx#|1B&N09*O_CUYNU$p;E5R^hIS+8x0$-I%@j#@#z~P4Uv$Y^#?)@;Pg~4Dr$8;BM?xxI($htJD|*44D|#WA)27nZuR7 zP`*~DY}3F}{FO@RN9j{HO`z>SWVV{yeprj{0V+pLhG`&E9ojaXjmFZRekzG+F_Cqi zEu_rt9`hQ0KYL%cG|0XAC0$*n_|Q~Kpz6d|&@R)Y+eTDvvh}3Ajfs}K3aHEtU0-3l z+Asy9G!LV?swGg~*q)~e+fbBn*q~!+mP}l-X3JNtUU}W3k7(Zo?8MH;z&y^axbItN$iiejQ(YY`x->|tn7zR=aYx2)_ySuz*;ZQ}f;faK* zsO@d~IUi)wik%8sH;p*n{nwmaa8T;yO&X!q1&g*skrI$2Q4nl5gf z1d7rjJ^C#{kc;~)7-i}{+t6sqRkqHBAtgwA@u}FUghmFYFtp@R!f+2e<6*;Xsz$=J zb3(U?rKiPTDz>i?4-5M~C2(6{_Tq~iWq3*@NlV5S(|Bc1PYXJl!Zz9*oK(7oL2nI& zX}sDSBWu|R)8nZ0H}9@R^`w|{wOUz9XV+~yD39h&jW2C`4PDn=N0!HyM*3T)4_~RVzK5`$2Ve4YNW%<=+X$<(L?2&RkQk>55HJQ%UCF=3;AgtR)rGY#E+cqS5f4&YcKPWO3i)7+HCliQa0jIZD{a*xT;2^8k6gba7#A`k7w5SdU>| zPG?OWn(j54OIa)rywmEVU{N9{N9AqLzA#YyRRj>ee)tkIP#)% zz|{0rYFgHlFPuuq$8JL>0u$wB)bxi9SGriUsAw~-I+jmM#K=)exFx~8IoB)=`&fwL zGpv2KqG4O;lTF9$W)qLS7dbX6RHR%pI)1#HsT6wFX%;hHvb-$2;UtSGMOd=JnSa8M zP)-|0t|{u2ODUpCzt~{5bGj$&hBfJBibn-~AMG_$Jr=}tN5+awM;iTgcI~%U2gA(N z9{M=zJ#Q6C4oyuBvB6C7H7T1~ zY13?JbBcZ9<}9OGJkrF&mLa+JVJ6ko^I&^x@a(4ml{Dl^zQ`7tHV<2+lKE%+Z56SB zi7LGtFgJtP&pt|(eQGy7HjPfJ8}>H)J_M%YW{CDZ*!QlMs+?9~)ovI4QMfDUf@F$& z*utdj)7e0o!op6yRwJ}d#sUHR5N->V)avne`fR{^{&054?)=!TR0cN1+|ceyIAPH4 zQFE|q-R=(>c1f}6l@1ATfJPVJo0^G@Bt~^Ksx@xOm9iAWMEBZk&D?HWbE>ID%ze1@ zuH0dRjME!gx5vT~19}t(r_0i(`HEcp(tC2}3znQMsX2u*bF@Y%+ z*$rn*Tgr3sPt$WU*_4iAe_5TF_VQeGn2e;Xo0^cg?N6FW|Aq0N^fT&Io3$TBbE1T8E%!BW9t*g zj*?g3U7R^~cZPS`a zx3-@h4aT$7+;eYsPGQYSj?t3lC}IB zaH_dY-FAk-#(ZC;xtEV$W&-9;JS1#J#R&;*Rb{%@n&Vk~C!L;;P?Y&_mI^@8-pd06CGKYM;>*md0xqR8;<;&L5_H#0l4ne2!I1CY< z#N_800T+U~FiZYHNj6q$baaDvxz{e;LtE?EITkB_=%Kq9z5< zj=I`pIevbJ`As#9WKnYZaiP z8B>tjwg4#$t{Fl0IxFw$;eL{hes-5njQqFbhWN;uSX zKUPpe&&Ty8$_D!6IvF15><>1F%314AWIIn7!{amV&}C%VZk=#w$R8@0l4my_Y&iLz z6eBfz#>s9;&;>X0{&t^BO;?yxU2dGAB`R*snmJKs?Yhh7J+f@^vkMm6`{TC0YK-cV zGx`>Q{Sd%#*?b9rL!>mJ!+UCc0-#hZGYp|N>9nZ%0)UzO6UpH`rKWTiHZv_XS;m&}0LRyaqyAA%W;o=x+Z5oIGs%26V9kno_NxF_&0D>3 z;qs;CT1@hga)#qn^R8OGZtXJn0Rf63QPb(?@X~y2Q6MZWo6NKx(b%-z>@P%z7){#} zGY!`q>?u9hf-Wb2S>s?0MF$UjeN&)C%hrD{(Y!kmJ~H7BKXW)z16ft$(0;n%3U@dy zwCJljjRG07!>0v?%N+328D~a(!!{U3m&4bi@h=Xv$+#~LTwh_Fr&OTt15r)mg9GvB ze2_6G@4|&s^TB~Cy;s8vzcipO$!D^s@ouHwYvof)hH1&BsQY2b#W>p1;D)*;6`204 zVr&}re|-3%5GeJ+(S#aNx>{`%M}4hYM&GqE#>^S*;!^~+?V-xJ(vw+}+*x8qZ03yG zRm4r>6j5@=vnkcq0ZIb(j&U41tC@&Oj=>D>(w^aN9}gR5x)(PS+RWWL(8wCj?#}s-zu=_U@LaMFT){dKilBqukp%u0%3CS zSuc(qGD2){++CF@N;+$+*V!h#%4<$cbI`r{y#nh~nv-#-5>oCYwbnP9mlDEpi9L84 z8!)(ZF@u&)hJ@`pt)SY86$1*wscxhkl+9g))&rx+FEfQf^CJ`EUCmVh%13-`X3C3` zai286ZtJALj_)G_H+7dURxsP^iV@s#N%a16y3^qmss4jb*9BT#eB+6?^}n9tG!kM^Wn=8?k7L#Ch@vu!O_6-EY)V;K(QcS{rC1LME z_A?17avV0`NWS?`$HIb^`l*EIzKSY^I}C2e#%AI(ofeV_B^^)L+u3=QJ;85!8k~1G zZfqrVf1__AxFJW;#5O4z$y}GP%1f#xS{3RlV^A~QjfNS-vMJ6}*bBRnMqH;k?1?%a zmcODMXDx7>%VCT%SUNQKTqxT#n+Zo+7PDGRsXl7^;!7S(mIYRa-!Y)z{5P;ttQ>abS&sb40Ecu*oWx5Z@Q zbnF5pFsx6$~GM!S+@EHbDz--aM3HZptWHTG!;ymgh!ejK7!AM{y@U{feS(1atr zNN4X|sp#3vlH*+oiEty=t`?~jB+Xl0h!(Z>Cf1&TO0JfGr4*vLR2aBsiyiLRGYK~T z|7PsV5?Bm#-EEJ${W4uB%c>JqxvfS8*QUkzGO^g&MNK>04xghvv+k*0tM}8J+h}&W z6;8BV!$wJB@q;;%NvLLL#rB)F`QlM-ui2V&wb@e$QVNvy$Twvu)7Epcr=$PZ(V|=b zt0T_XsRP>=M3-fN79Fh&I4u`!n<|kQjPIT5A!>>BkqRE8k5ojK zH26(?rGldo8qhbL#kT!UMKm;$gZf&NgUiu?uq``&rRyWLNDPrFC*w0ni zo52a+%m*vXCE%pC`(y>tXa>(rn9{yk(Jo~_TG6iG>8lkAnN78(cjmhlE)ww%S2(S< zFIV7OJTc9uE2OtxE2jacxO%2#E{bS#XNjbWJ5pqj8(UB_ m^@K)SxA1B6x9jr-CRTAfrmonw%Y4xy=^}d+=Avbr&;JXdwfp}7 literal 0 HcmV?d00001 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 -- 2.40.0