home *** CD-ROM | disk | FTP | other *** search
- Subject: chsh chfn for SV
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 98
- Submitted by: decvax!cwruecmp!rexago1!rich (K. Richard Magill)
-
- I got tired of editting passwd files so...
-
- This is tested & running on a 3b2/300 SV.2.2. It uses a lot of library
- routines that probably don't exist outside SV. (sorry).
-
- ----hack & slash here----
- /*
- * I AM NOT A SHELL ARCHIVE!
- *
- * This file is chsh.c and contains a public domain version
- * of chsh/chfn intended for SV. Calling sequence is
- *
- * chfn user new_name
- * or chsh user new_shell
- *
- * A null name means a null name. A null shell means /bin/sh.
- * Your old passwd file is stored in /etc/passwd~. Protections
- * and passwd requests work like su. To install use:
- *
- * make chsh
- * chmod 4555 chsh
- * ln chsh /usr/lbin (or some such)
- * ln chsh /usr/lbin/chfn
- *
- * AAAAnyway, you get the idea.
- *
- * K. Richard Magill, 26-jan-86.
- * Last Mod 26-jan-86, rich.
- */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <pwd.h>
-
- #define WATCH(x) if(x){perror(argv[0]);return(-1);}
-
- char *PASSWD = "/etc/passwd";
- char *BACKUP = "/etc/passwd~";
- char *TEMP = "/tmp/chshXXXXXX";
-
- void endpwent(), perror();
- char *crypt(), *getpass(), *mktemp();
- struct passwd *getpwent(), *getpwnam(), *fgetpwent();
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- register int i;
- register struct passwd *p;
- FILE *fin, *fout;
- int target_id;
- struct stat stat_buf;
-
- if (argc < 2 || argc > 3) {
- (void) fprintf(stderr, "usage: %s login shell\n", argv[0]);
- return(-1);
- } /* if usage error */
-
- /* is this person real? */
-
- if ((p = getpwnam(argv[1])) == NULL) {
- (void) fprintf(stderr, "%s: don't know %s\n",
- argv[0], argv[1]);
- return(-1);
- } /* if person isn't real */
-
- /* do we have permission to do this? */
- target_id = p->pw_uid;
-
- if ((i = getuid()) != 0 && i != target_id) {
- char salt[3];
-
- salt[0] = p->pw_passwd[0];
- salt[1] = p->pw_passwd[1];
- salt[3] = '\0';
-
- if (*p->pw_passwd != '\0'
- && strncmp(crypt(getpass("Password: "), salt),
- p->pw_passwd, 8)) {
- (void) fprintf(stderr, "Sorry.\n");
- return(-1);
- } /* passwd didn't match */
- } /* check for permission */
-
- /* set up files */
-
- endpwent(); /* close passwd file */
-
- WATCH((fin = fopen(PASSWD, "r")) == NULL);
- WATCH((fout = fopen(mktemp(TEMP), "w")) == NULL);
-
- while ((p = fgetpwent(fin)) != NULL) {
- if (p->pw_uid == target_id) {
- if (strcmp(argv[0], "chsh")) {
- p->pw_gecos = argv[2];
- } else {
- p->pw_shell = argv[2] == NULL ? "/bin/sh"
- : argv[2];
- }
- } /* if this is entry to be changed */
-
- WATCH(putpwent(p, fout));
- } /* while not eof (we couldn't recognize an error) */
-
- /* close files */
- WATCH(fclose(fin) || fclose(fout));
-
- /* remove old backup if it exists */
- WATCH(!stat(BACKUP, &stat_buf) && unlink(BACKUP));
-
- /* make current passwd file backup */
- WATCH(link(PASSWD, BACKUP) || unlink(PASSWD));
-
- /* make new file passwd */
- WATCH(link(TEMP, PASSWD) || unlink(TEMP));
-
- /* must have succeeded */
- return(0);
- } /* main */
-
-
- /* EOF */
-
-
-