Add spl's around queue manipulation
[unix-history] / usr / src / usr.bin / passwd / chsh.sh
CommitLineData
9f52e30a 1#ifndef lint
01eaadf6 2static char *sccsid = "@(#)chsh.sh 4.9 (Berkeley) %G%";
9f52e30a
SL
3#endif
4
854c8e85
BJ
5/*
6 * chsh
7 */
8#include <stdio.h>
9#include <signal.h>
10#include <pwd.h>
01eaadf6 11#include <ndbm.h>
9f52e30a 12#include <sys/file.h>
840fc587
SL
13#include <sys/time.h>
14#include <sys/resource.h>
854c8e85 15
a7da04e0 16char temp[] = "/etc/ptmp";
854c8e85 17char passwd[] = "/etc/passwd";
854c8e85
BJ
18struct passwd *pwd;
19struct passwd *getpwent();
20int endpwent();
21char *crypt();
22char *getpass();
9f52e30a 23char *strcat();
854c8e85
BJ
24char buf[BUFSIZ];
25
26main(argc, argv)
9f52e30a 27register char *argv[];
854c8e85 28{
9f52e30a
SL
29 register int u, fd;
30 register FILE *tf;
01eaadf6 31 DBM *dp;
854c8e85 32
9f52e30a 33 if (argc < 2 || argc > 3) {
1f096eb2 34 printf("Usage: chsh user [ /bin/csh ]\n");
9f52e30a 35 exit(1);
854c8e85
BJ
36 }
37 if (argc == 2)
38 argv[2] = "";
9f52e30a
SL
39 else {
40 if (argv[2][0] != '/')
41 argv[2] = strcat(
42 "/bin/\0 12345678901234567890123456789", argv[2]);
43 if (strcmp(argv[2], "/bin/csh") &&
44 strcmp(argv[2], "/bin/oldcsh") &&
45 strcmp(argv[2], "/bin/newcsh") &&
46 strcmp(argv[2], "/usr/new/csh") &&
47 /* and, for cretins who can't read the manual */
48 strcmp(argv[2], "/bin/sh") &&
49 getuid()) {
50 printf(
51 "Only /bin/csh may be specified\n"
52 );
78ffcf9e
BJ
53 exit(1);
54 }
9f52e30a
SL
55 if (access(argv[2], 1) < 0) {
56 printf("%s is not available\n", argv[2]);
57 exit(1);
58 }
59 }
60 unlimit(RLIMIT_CPU);
61 unlimit(RLIMIT_FSIZE);
a7da04e0
RC
62 u = getuid();
63 if (u != 0 && ((pwd = getpwnam(argv[1])) == NULL || u != pwd->pw_uid)) {
64 printf("Permission denied.\n");
65 exit(1);
9f52e30a 66 }
854c8e85 67
9f52e30a
SL
68 signal(SIGHUP, SIG_IGN);
69 signal(SIGINT, SIG_IGN);
70 signal(SIGQUIT, SIG_IGN);
71 signal(SIGTSTP, SIG_IGN);
fb8f0ff2 72 (void) umask(0);
9f52e30a 73 if ((fd = open(temp, O_CREAT|O_EXCL|O_RDWR, 0644)) < 0) {
854c8e85 74 printf("Temporary file busy -- try again\n");
9f52e30a 75 exit(1);
854c8e85 76 }
01eaadf6 77 if ((tf = fdopen(fd, "w")) == NULL) {
9f52e30a
SL
78 printf("Absurd fdopen failure - seek help\n");
79 goto out;
854c8e85 80 }
01eaadf6
RC
81 if ((dp = ndbmopen(passwd, O_RDWR, 0644)) == NULL) {
82 fprintf(stderr, "Warning: dbminit failed: ");
83 perror(passwd);
84 } else if (flock(dp->db_dirf, LOCK_EX) < 0) {
85 perror("Warning: lock failed");
86 ndbmclose(dp);
87 dp = NULL;
88 }
9f52e30a
SL
89 /*
90 * Copy passwd to temp, replacing matching lines
91 * with new shell.
92 */
01eaadf6 93 while ((pwd = getpwent()) != NULL) {
9f52e30a 94 if (strcmp(pwd->pw_name, argv[1]) == 0) {
9f52e30a 95 if (u != 0 && u != pwd->pw_uid) {
854c8e85
BJ
96 printf("Permission denied.\n");
97 goto out;
98 }
99 pwd->pw_shell = argv[2];
01eaadf6 100 replace(dp, pwd);
854c8e85 101 }
9f52e30a
SL
102 if (strcmp(pwd->pw_shell, "/bin/sh") == 0)
103 pwd->pw_shell = "";
104 fprintf(tf, "%s:%s:%d:%d:%s:%s:%s\n"
105 , pwd->pw_name
106 , pwd->pw_passwd
107 , pwd->pw_uid
108 , pwd->pw_gid
109 , pwd->pw_gecos
110 , pwd->pw_dir
111 , pwd->pw_shell
112 );
854c8e85
BJ
113 }
114 endpwent();
01eaadf6
RC
115 (void) fclose(tf);
116 ndbmclose(dp);
117 if (rename(temp, passwd) < 0) {
a7da04e0 118 fprintf(stderr, "chsh: "), perror("rename");
01eaadf6
RC
119 out:
120 (void) unlink(temp);
121 exit(1);
122 }
123 exit(0);
9f52e30a 124}
854c8e85 125
9f52e30a
SL
126unlimit(lim)
127{
128 struct rlimit rlim;
854c8e85 129
9f52e30a
SL
130 rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
131 setrlimit(lim, &rlim);
854c8e85 132}
a7da04e0 133
01eaadf6
RC
134/*
135 * Replace the password entry in the dbm data base with pwd.
136 */
137replace(dp, pwd)
138 DBM *dp;
139 struct passwd *pwd;
a7da04e0 140{
01eaadf6
RC
141 datum key, content;
142 register char *cp, *tp;
143 char buf[BUFSIZ];
a7da04e0 144
01eaadf6
RC
145 if (dp == NULL)
146 return;
147
148 cp = buf;
149#define COMPACT(e) tp = pwd->pw_/**/e; while (*cp++ = *tp++);
150 COMPACT(name);
151 COMPACT(passwd);
152 *(int *)cp = pwd->pw_uid; cp += sizeof (int);
153 *(int *)cp = pwd->pw_gid; cp += sizeof (int);
154 *(int *)cp = pwd->pw_quota; cp += sizeof (int);
155 COMPACT(comment);
156 COMPACT(gecos);
157 COMPACT(dir);
158 COMPACT(shell);
159 content.dptr = buf;
160 content.dsize = cp - buf;
161 key.dptr = pwd->pw_name;
162 key.dsize = strlen(pwd->pw_name);
163 dbmstore(dp, key, content, DB_REPLACE);
164 key.dptr = (char *)&pwd->pw_uid;
165 key.dsize = sizeof (int);
166 dbmstore(dp, key, content, DB_REPLACE);
a7da04e0 167}