static char
*sccsid
= "@(#)chsh.sh 4.9 (Berkeley) %G%";
#include <sys/resource.h>
char temp
[] = "/etc/ptmp";
char passwd
[] = "/etc/passwd";
struct passwd
*getpwent
();
if (argc
< 2 || argc
> 3) {
printf("Usage: chsh user [ /bin/csh ]\n");
"/bin/\0 12345678901234567890123456789", argv
[2]);
if (strcmp
(argv
[2], "/bin/csh") &&
strcmp
(argv
[2], "/bin/oldcsh") &&
strcmp
(argv
[2], "/bin/newcsh") &&
strcmp
(argv
[2], "/usr/new/csh") &&
/* and
, for cretins who can
't read the manual */
strcmp(argv[2], "/bin/sh") &&
"Only /bin/csh may be specified\n"
if (access(argv[2], 1) < 0) {
printf("%s is not available\n", argv[2]);
if (u != 0 && ((pwd = getpwnam(argv[1])) == NULL || u != pwd->pw_uid)) {
printf("Permission denied.\n");
signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
if ((fd = open(temp, O_CREAT|O_EXCL|O_RDWR, 0644)) < 0) {
printf("Temporary file busy -- try again\n");
if ((tf = fdopen(fd, "w")) == NULL) {
printf("Absurd fdopen failure - seek help\n");
if ((dp = ndbmopen(passwd, O_RDWR, 0644)) == NULL) {
fprintf(stderr, "Warning: dbminit failed: ");
} else if (flock(dp->db_dirf, LOCK_EX) < 0) {
perror("Warning: lock failed");
* Copy passwd to temp, replacing matching lines
while ((pwd = getpwent()) != NULL) {
if (strcmp(pwd->pw_name, argv[1]) == 0) {
if (u != 0 && u != pwd->pw_uid) {
printf("Permission denied.\n");
if (strcmp(pwd->pw_shell, "/bin/sh") == 0)
fprintf(tf, "%s:%s:%d:%d:%s:%s:%s\n"
if (rename(temp, passwd) < 0) {
fprintf(stderr, "chsh: "), perror("rename");
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
* Replace the password entry in the dbm data base with pwd.
#define COMPACT(e) tp = pwd->pw_/**/e; while (*cp++ = *tp++);
*(int *)cp = pwd->pw_uid; cp += sizeof (int);
*(int *)cp = pwd->pw_gid; cp += sizeof (int);
*(int *)cp = pwd->pw_quota; cp += sizeof (int);
content.dsize = cp - buf;
key.dsize = strlen(pwd->pw_name);
dbmstore(dp, key, content, DB_REPLACE);
key.dptr = (char *)&pwd->pw_uid;
key.dsize = sizeof (int);
dbmstore(dp, key, content, DB_REPLACE);