must rm before ln
[unix-history] / usr / src / usr.bin / passwd / chsh.sh
#ifndef lint
static char *sccsid = "@(#)chsh.sh 4.5 (Berkeley) %G%";
#endif
/*
* chsh
*/
#include <stdio.h>
#include <signal.h>
#include <pwd.h>
#include <sys/file.h>
#include <time.h>
#include <resource.h>
char passwd[] = "/etc/passwd";
char temp[] = "/etc/ptmp";
struct passwd *pwd;
struct passwd *getpwent();
int endpwent();
char *crypt();
char *getpass();
char *strcat();
char buf[BUFSIZ];
main(argc, argv)
register char *argv[];
{
register int u, fd;
register FILE *tf;
if (argc < 2 || argc > 3) {
printf("Usage: chsh user [ /bin/csh ]\n");
exit(1);
}
if (argc == 2)
argv[2] = "";
else {
if (argv[2][0] != '/')
argv[2] = strcat(
"/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") &&
getuid()) {
printf(
"Only /bin/csh may be specified\n"
);
exit(1);
}
if (access(argv[2], 1) < 0) {
printf("%s is not available\n", argv[2]);
exit(1);
}
}
unlimit(RLIMIT_CPU);
unlimit(RLIMIT_FSIZE);
while ((pwd=getpwent()) != NULL) {
if (strcmp(pwd->pw_name, argv[1]) == 0) {
u = getuid();
if (u!=0 && u != pwd->pw_uid) {
printf("Permission denied.\n");
exit(1);
}
break;
}
}
endpwent();
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
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");
exit(1);
}
if ((tf=fdopen(fd, "w")) == NULL) {
printf("Absurd fdopen failure - seek help\n");
goto out;
}
/*
* Copy passwd to temp, replacing matching lines
* with new shell.
*/
while ((pwd=getpwent()) != NULL) {
if (strcmp(pwd->pw_name, argv[1]) == 0) {
u = getuid();
if (u != 0 && u != pwd->pw_uid) {
printf("Permission denied.\n");
goto out;
}
pwd->pw_shell = argv[2];
}
if (strcmp(pwd->pw_shell, "/bin/sh") == 0)
pwd->pw_shell = "";
fprintf(tf, "%s:%s:%d:%d:%s:%s:%s\n"
, pwd->pw_name
, pwd->pw_passwd
, pwd->pw_uid
, pwd->pw_gid
, pwd->pw_gecos
, pwd->pw_dir
, pwd->pw_shell
);
}
endpwent();
if (rename(temp, passwd) < 0) {
fprintf(stderr, "chsh: "); perror("rename");
out:
unlink(temp);
exit(1);
}
fclose(tf);
exit(0);
}
unlimit(lim)
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
setrlimit(lim, &rlim);
}