189 lines
3.4 KiB
C
189 lines
3.4 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)chsh.c 1.1 92/07/30 SMI"; /* from UCB 4.7 07/10/83 */
|
|
#endif
|
|
|
|
/*
|
|
* chsh
|
|
*/
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <pwd.h>
|
|
#include <sys/file.h>
|
|
#include <sys/time.h>
|
|
#include <sys/resource.h>
|
|
|
|
char PASSWD[] = "/etc/passwd";
|
|
char temp[] = "/etc/ptmp";
|
|
struct passwd *pwd;
|
|
struct passwd *getpwent();
|
|
int endpwent();
|
|
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);
|
|
(void) umask(0);
|
|
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);
|
|
}
|
|
|
|
static char EMPTY[] = "";
|
|
static FILE *pwf = NULL;
|
|
static char line[BUFSIZ+1];
|
|
static struct passwd passwd;
|
|
|
|
setpwent()
|
|
{
|
|
if( pwf == NULL )
|
|
pwf = fopen( PASSWD, "r" );
|
|
else
|
|
rewind( pwf );
|
|
}
|
|
|
|
endpwent()
|
|
{
|
|
if( pwf != NULL ){
|
|
fclose( pwf );
|
|
pwf = NULL;
|
|
}
|
|
}
|
|
|
|
static char *
|
|
pwskip(p)
|
|
register char *p;
|
|
{
|
|
while( *p && *p != ':' && *p != '\n' )
|
|
++p;
|
|
if( *p ) *p++ = 0;
|
|
return(p);
|
|
}
|
|
|
|
struct passwd *
|
|
getpwent()
|
|
{
|
|
register char *p;
|
|
|
|
if (pwf == NULL) {
|
|
if( (pwf = fopen( PASSWD, "r" )) == NULL )
|
|
return(0);
|
|
}
|
|
p = fgets(line, BUFSIZ, pwf);
|
|
if (p==NULL)
|
|
return(0);
|
|
passwd.pw_name = p;
|
|
p = pwskip(p);
|
|
passwd.pw_passwd = p;
|
|
p = pwskip(p);
|
|
passwd.pw_uid = atoi(p);
|
|
p = pwskip(p);
|
|
passwd.pw_gid = atoi(p);
|
|
passwd.pw_quota = 0;
|
|
passwd.pw_comment = EMPTY;
|
|
p = pwskip(p);
|
|
passwd.pw_gecos = p;
|
|
p = pwskip(p);
|
|
passwd.pw_dir = p;
|
|
p = pwskip(p);
|
|
passwd.pw_shell = p;
|
|
while(*p && *p != '\n') p++;
|
|
*p = '\0';
|
|
return(&passwd);
|
|
}
|