Path: seismo!harvard!think!mit-eddie!genrad!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: chsh chfn for SV Message-ID: <1349@panda.UUCP> Date: 27 Jan 86 15:24:58 GMT Sender: jpn@panda.UUCP Lines: 127 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 #include #include #include #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 */