#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # chpass.1 # Makefile # chpass.c # chpass.h # field.c # pathnames.h # util.c # This archive created: Thu Jan 10 09:00:12 1991 # By: John F Haugh II (River Parishes Programming, Austin TX) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'chpass.1'" '(5439 characters)' if test -f 'chpass.1' then echo shar: "will not over-write existing file 'chpass.1'" else sed 's/^X//' << \SHAR_EOF > 'chpass.1' X.\" Copyright (c) 1988, 1990 The Regents of the University of California. X.\" All rights reserved. X.\" X.\" Redistribution and use in source and binary forms are permitted provided X.\" that: (1) source distributions retain this entire copyright notice and X.\" comment, and (2) distributions including binaries display the following X.\" acknowledgement: ``This product includes software developed by the X.\" University of California, Berkeley and its contributors'' in the X.\" documentation or other materials provided with the distribution and in X.\" all advertising materials mentioning features or use of this software. X.\" Neither the name of the University nor the names of its contributors may X.\" be used to endorse or promote products derived from this software without X.\" specific prior written permission. X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X.\" X.\" @(#)chpass.1 5.9 (Berkeley) 7/24/90 X.\" X.Dd July 24, 1990 X.Dt CHPASS 1 X.Os BSD 4.4 X.Sh NAME X.Nm chpass X.Nd add or change user database information X.Sh SYNOPSIS Xchpass X.Op Fl a Ar list X.Op Fl s Ar shell X.Op user X.Sh DESCRIPTION X.Nm Chpass Xallows editing of the user database information associated Xwith X.Ar user Xor, by default, the current user. XThe information is formatted and supplied to an editor for changes. X.Pp XOnly the information that the user is allowed to change is displayed. X.Pp XThe options are as follows: X.Tw Ds X.Tp Fl a XThe super-user is allowed to directly supply a user database Xentry, in the format specified by X.Xr passwd 5 , Xas an argument. XThis argument must be a colon (``:'') separated list of all the Xuser database fields, although they may be empty. X.Tp Fl s XThe X.Fl s Xoption attempts to change the user's shell to X.Ar newsh . X.Tp X.Pp XPossible display items are as follows: X.Pp X.Dw Home\ Directory: X.Dp Login: Xuser's login name X.Dp Password: Xuser's encrypted password X.Dp Uid: Xuser's id X.Dp Gid: Xuser's login group id X.Dp Change: Xpassword change time X.Dp Expire: Xaccount expiration time X.Dp Class: Xuser's general classification X.Dp Home Directory: Xuser's home directory X.Dp Shell: Xuser's login shell X.Dp Full Name: Xuser's real name X.Dp Location: Xuser's normal location X.Dp Home Phone: Xuser's home phone X.Dp Office Phone: Xuser's office phone X.Dp X.Pp XThe X.Ar login Xfield is the user name used to access the computer account. X.Pp XThe X.Ar password Xfield contains the encrypted form of the user's password. X.Pp XThe X.Ar uid Xfield is the number associated with the X.Ar login Xfield. XBoth of these fields should be unique across the system (and often Xacross a group of systems) as they control file access. X.Pp XWhile it is possible to have multiple entries with identical login names Xand/or identical user id's, it is usually a mistake to do so. Routines Xthat manipulate these files will often return only one of the multiple Xentries, and that one by random selection. X.Pp XThe X.Ar group Xfield is the group that the user will be placed in at login. XSince this system supports multiple groups (see X.Xr groups 1 ) Xthis field currently has little special meaning. XThis field may be filled in with either a number or a group name (see X.Xr group 5 ) . X.Pp XThe X.Ar change Xfield is the date by which the password must be changed. X.Pp XThe X.Ar expire Xfield is the date on which the account expires. X.Pp XBoth the X.Ar change Xand X.Ar expire Xfields should be entered in the form ``month day year'' where X.Ar month Xis the month name (the first three characters are sufficient), X.Ar day Xis the day of the month, and X.Ar year Xis the year. X.bp XThe X.Ar class Xfield is currently unused. In the near future it will be a key to Xa X.Xr termcap 5 Xstyle database of user attributes. X.Pp XThe user's X.Ar home directory Xis the full UNIX path name where the user Xwill be placed at login. X.Pp XThe X.Ar shell Xfield is the command interpreter the user prefers. XIf the X.Ar shell Xfield is empty, the Bourne shell, X.Pa /bin/sh , Xis assumed. XWhen altering a login shell, and not the super-user, the user Xmay not change from a non-standard shell or to a non-standard Xshell. XNon-standard is defined as a shell not found in X.Pa /etc/shells . X.Pp XThe last four fields are for storing the user's X.Ar full name , office location , Xand X.Ar home Xand X.Ar work telephone Xnumbers. X.Pp XOnce the information has been verified, X.Nm chpass Xuses X.Xr mkpasswd 8 Xto update the user database. This is run in the background, and, Xat very large sites could take several minutes. Until this update Xis completed, the password file is unavailable for other updates Xand the new information will not be available to programs. X.Sh ENVIRONMENT XThe X.Xr vi 1 Xeditor will be used unless the environment variable EDITOR is set to Xan alternate editor. XWhen the editor terminates, the information is re-read and used to Xupdate the user database itself. XOnly the user, or the super-user, may edit the information associated Xwith the user. X.Sh FILES X.Dw /etc/master.passwd X.Di L X.Dp Pa /etc/master.passwd XThe user database X.Dp Pa /etc/shells XThe list of approved shells X.Dp X.Sh SEE ALSO X.Xr login 1 , X.Xr finger 1 , X.Xr getusershell 3 , X.Xr passwd 5 , X.Xr mkpasswd 8 , X.Xr vipw 8 X.Pp XRobert Morris and Ken Thompson, X.Ar UNIX Password security X.Sh HISTORY XFirst release 4.3 Reno BSD. X.Sh BUGS XUser information should (and eventually will) be stored elsewhere. SHAR_EOF if test 5439 -ne "`wc -c < 'chpass.1'`" then echo shar: "error transmitting 'chpass.1'" '(should have been 5439 characters)' fi fi echo shar: "extracting 'Makefile'" '(302 characters)' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# @(#)Makefile 5.3 (Berkeley) 5/11/90 X XPROG= chpass XSRCS= chpass.c field.c util.c XBINOWN= root XBINMODE=4555 XLINKS= ${BINDIR}/chpass ${BINDIR}/chfn ${BINDIR}/chpass ${BINDIR}/chsh XMLINKS= chpass.1 chfn.1 chpass.1 chsh.1 XCFLAGS= -g X Xall: $(PROG) X X$(PROG): $(SRCS:.c=.o) X cc $(CFLAGS) -o $@ $(SRCS:.c=.o) SHAR_EOF if test 302 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 302 characters)' fi fi echo shar: "extracting 'chpass.c'" '(11797 characters)' if test -f 'chpass.c' then echo shar: "will not over-write existing file 'chpass.c'" else sed 's/^X//' << \SHAR_EOF > 'chpass.c' X/*- X * Copyright (c) 1988 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted provided X * that: (1) source distributions retain this entire copyright notice and X * comment, and (2) distributions including binaries display the following X * acknowledgement: ``This product includes software developed by the X * University of California, Berkeley and its contributors'' in the X * documentation or other materials provided with the distribution and in X * all advertising materials mentioning features or use of this software. X * Neither the name of the University nor the names of its contributors may X * be used to endorse or promote products derived from this software without X * specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X/* X * Modified 1/10/91, John F Haugh II X * X * Made changes needed to get chpass to run on System V. X */ X X#ifndef lint Xchar copyright[] = X"@(#) Copyright (c) 1988 The Regents of the University of California.\n\ X All rights reserved.\n"; X#endif /* not lint */ X X#ifndef lint Xstatic char sccsid[] = "@(#)chpass.c 5.15 (Berkeley) 6/29/90"; X#endif /* not lint */ X X#include <sys/types.h> X#include <sys/param.h> X#include <sys/file.h> X#include <sys/stat.h> X#include <sys/signal.h> X#include <fcntl.h> X#include <time.h> X#include <pwd.h> X#include <errno.h> X#include <stdio.h> X#include <ctype.h> X#include <string.h> X#include "chpass.h" X#include "pathnames.h" X Xchar e1[] = ": "; Xchar e2[] = ":,"; X Xint p_gecos(), p_gid(), p_hdir(); Xint p_login(), p_passwd(), p_shell(), p_uid(); X Xstruct entry list[] = { X { "Login", p_login, 1, 5, e1, }, X { "Password", p_passwd, 1, 8, e1, }, X { "Uid", p_uid, 1, 3, e1, }, X { "Gid", p_gid, 1, 3, e1, }, X#define E_NAME 4 X { "Full Name", p_gecos, 0, 9, e2, }, X#define E_BPHONE 5 X { "Office Phone", p_gecos, 0, 12, e2, }, X#define E_HPHONE 6 X { "Home Phone", p_gecos, 0, 10, e2, }, X#define E_LOCATE 7 X { "Location", p_gecos, 0, 8, e2, }, X { "Home directory", p_hdir, 1, 14, e1, }, X#define E_SHELL 9 X { "Shell", p_shell, 0, 5, e1, }, X { NULL, 0, }, X}; X Xuid_t uid; X Xstruct flock lock = { F_WRLCK, 0, 0, 0, 0, 0 }; Xextern char *sys_errlist[]; X Xmain(argc, argv) X int argc; X char **argv; X{ X extern int errno, optind; X extern char *optarg; X register char *p; X struct passwd lpw, *pw; X FILE *temp_fp; X int aflag, ch, fd; X char *fend, *newsh, *passwd, *temp, *tend; X char from[BUFSIZ], to[BUFSIZ]; X char *getusershell(); X X uid = getuid(); X aflag = 0; X newsh = NULL; X while ((ch = getopt(argc, argv, "a:s:")) != EOF) X switch(ch) { X case 'a': X if (uid) X baduser(); X loadpw(optarg, pw = &lpw); X aflag = 1; X break; X case 's': X newsh = optarg; X /* protect p_field -- it thinks NULL is /bin/sh */ X if (!*newsh) X usage(); X break; X case '?': X default: X usage(); X } X argc -= optind; X argv += optind; X X if (!aflag) X switch(argc) { X case 0: X if (!(pw = getpwuid(uid))) { X (void)fprintf(stderr, X "chpass: unknown user: uid %u\n", uid); X exit(1); X } X break; X case 1: X if (!(pw = getpwnam(*argv))) { X (void)fprintf(stderr, X "chpass: unknown user %s.\n", *argv); X exit(1); X } X if (uid && uid != pw->pw_uid) X baduser(); X break; X default: X usage(); X } X X (void)signal(SIGHUP, SIG_IGN); X (void)signal(SIGINT, SIG_IGN); X (void)signal(SIGQUIT, SIG_IGN); X X (void)ulimit(2, (1L<<20)); X (void)umask(0); X X temp = _PATH_PTMP; X if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0) { X if (errno == EEXIST) { X (void)fprintf(stderr, X "chpass: password file busy -- try again later.\n"); X exit(1); X } X (void)fprintf(stderr, "chpass: %s: %s; ", X temp, sys_errlist[errno]); X goto bad; X } X if (!(temp_fp = fdopen(fd, "w"))) { X (void)fprintf(stderr, "chpass: can't write %s; ", temp); X goto bad; X } X X if (newsh) { X if (p_shell(newsh, pw, (struct entry *)NULL)) X goto bad; X } X else if (!aflag && !info(pw)) X goto bad; X X /* root should have a 0 uid and a reasonable shell */ X if (!strcmp(pw->pw_name, "root")) { X if (pw->pw_uid) { X (void)fprintf(stderr, "chpass: root uid should be 0."); X exit(1); X } X setusershell(); X for (;;) X if (!(p = getusershell())) { X (void)fprintf(stderr, X "chpass: warning, unknown root shell."); X break; X } X else if (!strcmp(pw->pw_shell, p)) X break; X } X X passwd = _PATH_PASSWD; X if (!freopen(passwd, "r", stdin)) { X (void)fprintf(stderr, "chpass: can't read %s; ", passwd); X goto bad; X } X if (!copy(pw, temp_fp)) X goto bad; X X (void)fclose(temp_fp); X (void)fclose(stdin); X X switch(fork()) { X case 0: X break; X case -1: X (void)fprintf(stderr, "chpass: can't fork; "); X goto bad; X /* NOTREACHED */ X default: X exit(0); X /* NOTREACHED */ X } X X if (makedb(temp)) { X (void)fprintf(stderr, "chpass: mkpasswd failed; "); Xbad: (void)fprintf(stderr, "%s unchanged.\n", _PATH_PASSWD); X (void)unlink(temp); X exit(1); X } X X /* X * possible race; have to rename four files, and someone could slip X * in between them. LOCK_EX and rename the ``passwd.dir'' file first X * so that getpwent(3) can't slip in; the lock should never fail and X * it's unclear what to do if it does. Rename ``ptmp'' last so that X * passwd/vipw/chpass can't slip in. X */ X (void)nice(-19); X fend = strcpy(from, temp) + strlen(temp); X tend = strcpy(to, _PATH_PASSWD) + strlen(_PATH_PASSWD); X memcpy(fend, ".dir", 5); X memcpy(tend, ".dir", 5); X if ((fd = open(from, O_RDONLY, 0)) >= 0) X fcntl (fd, F_SETLK, &lock); X X /* here we go... */ X (void)rename(from, to); X memcpy(fend, ".pag", 5); X memcpy(tend, ".pag", 5); X (void)rename(from, to); X memcpy(fend, ".orig", 6); X (void)rename(from, _PATH_PASSWD); X (void)rename(temp, passwd); X /* done! */ X exit(0); X} X Xrename (from, to) Xchar *from; Xchar *to; X{ X struct stat s1, s2; X X if (stat (from, &s1)) X return -1; X X if (stat (to, &s2)) { X if (link (from, to)) X return -1; X X return unlink(from); X } X if (s1.st_dev != s2.st_dev) { X errno = EXDEV; X return -1; X } X if (unlink (to)) X return -1; X X if (link (from, to)) X return -1; X X return unlink (from); X} X Xinfo(pw) X struct passwd *pw; X{ X struct stat begin, end; X FILE *fp; X int fd, rval; X char *tfile; X X tfile = _PATH_TMP; X if ((fd = open(mktemp(tfile), O_RDWR|O_CREAT, 0600)) == -1 X || !(fp = fdopen(fd, "w+"))) { X (void)fprintf(stderr, "chpass: no temporary file"); X return(0); X } X X /* X * if print doesn't print out a shell field, make it restricted. X * Not particularly pretty, but print is the routine that checks X * to see if the user can change their shell. X */ X if (!print(fp, pw)) X list[E_SHELL].restricted = 1; X (void)fflush(fp); X X /* X * give the file to the real user; setuid permissions X * are discarded in edit() X */ X (void)chown(tfile, getuid(), getgid()); X X for (rval = 0;;) { X (void)fstat(fd, &begin); X if (edit(tfile)) { X (void)fprintf(stderr, "chpass: edit failed; "); X break; X } X (void)fstat(fd, &end); X if (begin.st_mtime == end.st_mtime) { X (void)fprintf(stderr, "chpass: no changes made; "); X break; X } X (void)rewind(fp); X if (check(fp, pw)) { X rval = 1; X break; X } X (void)fflush(stderr); X if (prompt()) X break; X } X (void)fclose(fp); X (void)unlink(tfile); X return(rval); X} X Xcheck(fp, pw) X FILE *fp; X struct passwd *pw; X{ X register struct entry *ep; X register char *p; X static char buf[1024]; X X while (fgets(buf, sizeof(buf), fp)) { X if (!buf[0] || buf[0] == '#') X continue; X if (!(p = strchr(buf, '\n'))) { X (void)fprintf(stderr, "chpass: line too long.\n"); X return(0); X } X *p = '\0'; X for (ep = list;; ++ep) { X if (!ep->prompt) { X (void)fprintf(stderr, X "chpass: unrecognized field.\n"); X return(0); X } X if (!strncmp(buf, ep->prompt, ep->len)) { Xprintf ("found %s\n", buf); X if (ep->restricted && uid) { X (void)fprintf(stderr, X "chpass: you may not change the %s field.\n", X ep->prompt); X return(0); X } X if (!(p = strchr(buf, ':'))) { X (void)fprintf(stderr, X "chpass: line corrupted.\n"); X return(0); X } X while (isspace(*++p)); X if (ep->except && strpbrk(p, ep->except)) { X (void)fprintf(stderr, X "chpass: illegal character in the \"%s\" field.\n", X ep->prompt); X return(0); X } X if ((*ep->func)(p, pw, ep)) X return(0); X break; X } X } X } X /* X * special checks... X * X * there has to be a limit on the size of the gecos fields, X * otherwise getpwent(3) can choke. X * ``if I swallow anything evil, put your fingers down my throat...'' X * -- The Who X */ X if (strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) + X strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) X > 512) { X (void)fprintf(stderr, "chpass: gecos field too large.\n"); X exit(1); X } X (void)sprintf(pw->pw_gecos = buf, "%s,%s,%s,%s", X list[E_NAME].save, list[E_LOCATE].save, list[E_BPHONE].save, X list[E_HPHONE].save); X return(1); X} X Xcopy(pw, fp) X struct passwd *pw; X FILE *fp; X{ X register int done; X register char *p; X char buf[1024]; X X for (done = 0; fgets(buf, sizeof(buf), stdin);) { X /* skip lines that are too big */ X if (!strchr(buf, '\n')) { X (void)fprintf(stderr, "chpass: line too long; "); X return(0); X } X if (done) { X (void)fprintf(fp, "%s", buf); X continue; X } X if (!(p = strchr(buf, ':'))) { X (void)fprintf(stderr, "chpass: corrupted entry; "); X return(0); X } X *p = '\0'; X if (strcmp(buf, pw->pw_name)) { X *p = ':'; X (void)fprintf(fp, "%s", buf); X continue; X } X (void)fprintf(fp, "%s:%s:%d:%d:%s:%s:%s\n", X pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, X pw->pw_gecos, pw->pw_dir, pw->pw_shell); X done = 1; X } X if (!done) X (void)fprintf(fp, "%s:%s:%d:%d:%s:%s:%s\n", X pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, X pw->pw_gecos, pw->pw_dir, pw->pw_shell); X return(1); X} X Xmakedb(file) X char *file; X{ X int status, pid, w; X X if (!(pid = fork())) { X execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL); X (void)fprintf(stderr, "chpass: can't find \"mkpasswd\".\n"); X _exit(127); X } X while ((w = wait(&status)) != pid && w != -1); X return(w == -1 || status); X} X Xedit(file) X char *file; X{ X int status, pid, w; X char *p, *editor, *getenv(); X X if (editor = getenv("EDITOR")) { X if (p = strrchr(editor, '/')) X ++p; X else X p = editor; X } X else X p = editor = "vi"; X if (!(pid = fork())) { X (void)setgid(getgid()); X (void)setuid(getuid()); X execlp(editor, p, file, NULL); X (void)fprintf(stderr, "chpass: can't find \"%s\".\n", editor); X _exit(127); X } X while ((w = wait(&status)) != pid && w != -1); X return(w == -1 || status); X} X Xloadpw(arg, pw) X char *arg; X register struct passwd *pw; X{ X register char *cp; X char *bp = arg; X long atol(); X char *strtok(); X X pw->pw_name = strtok(bp, ":"); X pw->pw_passwd = strtok((char *) 0, ":"); X if (!(cp = strtok((char *) 0, ":"))) X goto bad; X pw->pw_uid = atoi(cp); X if (!(cp = strtok((char *) 0, ":"))) X goto bad; X pw->pw_gid = atoi(cp); X pw->pw_gecos = strtok((char *) 0, ":"); X pw->pw_dir = strtok((char *) 0, ":"); X pw->pw_shell = strtok((char *) 0, ":"); X if (!pw->pw_shell || strtok((char *) 0, ":")) { Xbad: (void)fprintf(stderr, "chpass: bad password list.\n"); X exit(1); X } X} X Xprompt() X{ X register int c; X X for (;;) { X (void)printf("re-edit the password file? [y]: "); X (void)fflush(stdout); X c = getchar(); X if (c != EOF && c != (int)'\n') X while (getchar() != (int)'\n'); X return(c == (int)'n'); X } X /* NOTREACHED */ X} X Xbaduser() X{ X (void)fprintf(stderr, "chpass: %s\n", sys_errlist[EACCES]); X exit(1); X} X Xusage() X{ X (void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [user]\n"); X exit(1); X} SHAR_EOF if test 11797 -ne "`wc -c < 'chpass.c'`" then echo shar: "error transmitting 'chpass.c'" '(should have been 11797 characters)' fi fi echo shar: "extracting 'chpass.h'" '(1156 characters)' if test -f 'chpass.h' then echo shar: "will not over-write existing file 'chpass.h'" else sed 's/^X//' << \SHAR_EOF > 'chpass.h' X/* X * Copyright (c) 1988 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: ``This product includes software X * developed by the University of California, Berkeley and its contributors'' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * @(#)chpass.h 5.2 (Berkeley) 6/1/90 X */ X Xstruct entry { X char *prompt; X int (*func)(), restricted, len; X char *except, *save; X}; X Xextern uid_t uid; SHAR_EOF if test 1156 -ne "`wc -c < 'chpass.h'`" then echo shar: "error transmitting 'chpass.h'" '(should have been 1156 characters)' fi fi echo shar: "extracting 'field.c'" '(4654 characters)' if test -f 'field.c' then echo shar: "will not over-write existing file 'field.c'" else sed 's/^X//' << \SHAR_EOF > 'field.c' X/* X * Copyright (c) 1988 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: ``This product includes software X * developed by the University of California, Berkeley and its contributors'' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X/* X * Modified 1/10/91, John F Haugh II X * X * Made changes needed to get chpass to run on System V. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#)field.c 5.12 (Berkeley) 6/1/90"; X#endif /* not lint */ X X#include <sys/types.h> X#include <sys/param.h> X#include <pwd.h> X#include <grp.h> X#include <string.h> X#include <stdio.h> X#include <ctype.h> X#include "chpass.h" X#include "pathnames.h" X X#ifndef USHRT_MAX X#define USHRT_MAX (0xffff) X#endif X X/* ARGSUSED */ Xp_login(p, pw, ep) X char *p; X struct passwd *pw; X struct entry *ep; X{ X if (!*p) { X (void)fprintf(stderr, "chpass: empty login field.\n"); X return(1); X } X if (*p == '-') { X (void)fprintf(stderr, X "chpass: login names may not begin with a hyphen.\n"); X return(1); X } X if (!(pw->pw_name = strdup(p))) { X (void)fprintf(stderr, "chpass: can't save entry.\n"); X return(1); X } X if (strchr(p, '.')) X (void)fprintf(stderr, X "chpass: \'.\' is dangerous in a login name.\n"); X for (; *p; ++p) X if (isupper(*p)) { X (void)fprintf(stderr, X "chpass: upper-case letters are dangerous in a login name.\n"); X break; X } X return(0); X} X X/* ARGSUSED */ Xp_passwd(p, pw, ep) X char *p; X struct passwd *pw; X struct entry *ep; X{ X if (!*p) X pw->pw_passwd = ""; /* "NOLOGIN"; */ X else if (!(pw->pw_passwd = strdup(p))) { X (void)fprintf(stderr, "chpass: can't save password entry.\n"); X return(1); X } X X return(0); X} X X/* ARGSUSED */ Xp_uid(p, pw, ep) X register char *p; X struct passwd *pw; X struct entry *ep; X{ X int id; X X if (!*p) { X (void)fprintf(stderr, "chpass: empty uid field.\n"); X return(1); X } X if (!isdigit(*p)) { X (void)fprintf(stderr, "chpass: illegal uid.\n"); X return(1); X } X id = atoi(p); X if ((unsigned int)id > USHRT_MAX) { X (void)fprintf(stderr, "chpass: %d > max uid value (%d).\n", X id, USHRT_MAX); X return(1); X } X pw->pw_uid = id; X return(0); X} X X/* ARGSUSED */ Xp_gid(p, pw, ep) X register char *p; X struct passwd *pw; X struct entry *ep; X{ X struct group *gr; X int id; X X if (!*p) { X (void)fprintf(stderr, "chpass: empty gid field.\n"); X return(1); X } X if (!isdigit(*p)) { X if (!(gr = getgrnam(p))) { X (void)fprintf(stderr, X "chpass: unknown group %s.\n", p); X return(1); X } X pw->pw_gid = gr->gr_gid; X return(0); X } X id = atoi(p); X if ((unsigned int)id > USHRT_MAX) { X (void)fprintf(stderr, "chpass: %d > max gid value (%d).\n", X id, USHRT_MAX); X return(1); X } X pw->pw_gid = id; X return(0); X} X X/* ARGSUSED */ Xp_gecos(p, pw, ep) X char *p; X struct passwd *pw; X struct entry *ep; X{ Xprintf ("adding %s to %s\n", p, ep->prompt); X if (!*p) X ep->save = ""; X else if (!(ep->save = strdup(p))) { X (void)fprintf(stderr, "chpass: can't save entry.\n"); X return(1); X } X return(0); X} X X/* ARGSUSED */ Xp_hdir(p, pw, ep) X char *p; X struct passwd *pw; X struct entry *ep; X{ X if (!*p) { X (void)fprintf(stderr, "chpass: empty home directory field.\n"); X return(1); X } X if (!(pw->pw_dir = strdup(p))) { X (void)fprintf(stderr, "chpass: can't save entry.\n"); X return(1); X } X return(0); X} X X/* ARGSUSED */ Xp_shell(p, pw, ep) X register char *p; X struct passwd *pw; X struct entry *ep; X{ X char *t, *ok_shell(); X X if (!*p) { X pw->pw_shell = _PATH_BSHELL; X return(0); X } X /* only admin can change from or to "restricted" shells */ X if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) { X (void)fprintf(stderr, X "chpass: %s: current shell non-standard.\n", pw->pw_shell); X return(1); X } X if (!(t = ok_shell(p))) { X if (uid) { X (void)fprintf(stderr, X "chpass: %s: non-standard shell.\n", p); X return(1); X } X } X else X p = t; X if (!(pw->pw_shell = strdup(p))) { X (void)fprintf(stderr, "chpass: can't save entry.\n"); X return(1); X } X return(0); X} SHAR_EOF if test 4654 -ne "`wc -c < 'field.c'`" then echo shar: "error transmitting 'field.c'" '(should have been 4654 characters)' fi fi echo shar: "extracting 'pathnames.h'" '(1367 characters)' if test -f 'pathnames.h' then echo shar: "will not over-write existing file 'pathnames.h'" else sed 's/^X//' << \SHAR_EOF > 'pathnames.h' X/* X * Copyright (c) 1989 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: ``This product includes software X * developed by the University of California, Berkeley and its contributors'' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X * X * @(#)pathnames.h 5.3 (Berkeley) 6/1/90 X */ X X/* X * Modified 1/10/91, John F Haugh II X * X * Made changes needed to get chpass to run on System V. X */ X X#define _PATH_TMP "/tmp/passwd.XXXXXX" X#define _PATH_PTMP "/etc/ptmp" X#define _PATH_PASSWD "/etc/passwd" X#define _PATH_MKPASSWD "/etc/mkpasswd" X#define _PATH_BSHELL "/bin/sh" X#define _PATH_SHELLS "/etc/shells" SHAR_EOF if test 1367 -ne "`wc -c < 'pathnames.h'`" then echo shar: "error transmitting 'pathnames.h'" '(should have been 1367 characters)' fi fi echo shar: "extracting 'util.c'" '(3810 characters)' if test -f 'util.c' then echo shar: "will not over-write existing file 'util.c'" else sed 's/^X//' << \SHAR_EOF > 'util.c' X/*- X * Copyright (c) 1988 The Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted provided X * that: (1) source distributions retain this entire copyright notice and X * comment, and (2) distributions including binaries display the following X * acknowledgement: ``This product includes software developed by the X * University of California, Berkeley and its contributors'' in the X * documentation or other materials provided with the distribution and in X * all advertising materials mentioning features or use of this software. X * Neither the name of the University nor the names of its contributors may X * be used to endorse or promote products derived from this software without X * specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X/* X * Modified 1/10/91, John F Haugh II X * X * Made changes needed to get chpass to run on System V. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#)util.c 5.13 (Berkeley) 6/29/90"; X#endif /* not lint */ X X#include <sys/types.h> X#include <time.h> X#include <pwd.h> X#include <stdio.h> X#include <string.h> X#include <ctype.h> X#include "chpass.h" X#include "pathnames.h" X Xstatic int dmsize[] = X { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; Xstatic char *months[] = X { "January", "February", "March", "April", "May", "June", X "July", "August", "September", "October", "November", X "December", NULL }; X X#define TM_YEAR_BASE (1900) X#define EPOCH_YEAR (1969) X#define DAYSPERLYEAR (366) X#define DAYSPERNYEAR (365) X#define HOURSPERDAY (24) X#define MINSPERHOUR (60) X#define SECSPERMIN (60) X Xstatic FILE *shell_fp; X Xint Xsetusershell () X{ X if (shell_fp) { X rewind (shell_fp); X return 0; X } X return (shell_fp = fopen (_PATH_SHELLS, "r")) == 0 ? -1:0; X} X Xchar * Xgetusershell () X{ X static char shell[BUFSIZ]; X char *cp; X X if (! shell_fp) X return 0; X X if (fgets (shell, sizeof shell, shell_fp) == 0) X return 0; X X if (cp = strrchr (shell, '\n')) X *cp = '\0'; X X return shell; X} X X/* X * print -- X * print out the file for the user to edit; strange side-effect: X * return if the user is allowed to modify their shell. X */ Xprint(fp, pw) X FILE *fp; X struct passwd *pw; X{ X register char *p; X int shellval; X char *bp; X char *getusershell(), *ok_shell(), *ttoa(); X X shellval = 1; X (void)fprintf(fp, "#Changing user database information for %s.\n", X pw->pw_name); X if (!uid) { X (void)fprintf(fp, "Login: %s\n", pw->pw_name); X (void)fprintf(fp, "Password: %s\n", pw->pw_passwd); X (void)fprintf(fp, "Uid [#]: %d\n", pw->pw_uid); X (void)fprintf(fp, "Gid [# or name]: %d\n", pw->pw_gid); X (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir); X (void)fprintf(fp, "Shell: %s\n", X *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); X } X /* only admin can change "restricted" shells */ X else if (ok_shell(pw->pw_shell)) X (void)fprintf(fp, "Shell: %s\n", X *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); X else X shellval = 0; X bp = pw->pw_gecos; X p = strtok(bp, ","); X (void)fprintf(fp, "Full Name: %s\n", p ? p : ""); X p = strtok((char *) 0, ","); X (void)fprintf(fp, "Location: %s\n", p ? p : ""); X p = strtok((char *) 0, ","); X (void)fprintf(fp, "Office Phone: %s\n", p ? p : ""); X p = strtok((char *) 0, ","); X (void)fprintf(fp, "Home Phone: %s\n", p ? p : ""); X return(shellval); X} X Xchar * Xok_shell(name) X register char *name; X{ X register char *p, *sh; X char *getusershell(); X X setusershell(); X while (sh = getusershell()) { X if (!strcmp(name, sh)) X return(name); X /* allow just shell name, but use "real" path */ X if ((p = strrchr(sh, '/')) && !strcmp(name, p + 1)) X return(sh); X } X return(NULL); X} SHAR_EOF if test 3810 -ne "`wc -c < 'util.c'`" then echo shar: "error transmitting 'util.c'" '(should have been 3810 characters)' fi fi exit 0 # End of shell archive