Makefile, mklink.data, mkso.data, newuser.desc, newuser.rez:

- initial checkin
README:
	- updated installation notes
installit, newuserv.c:
	- deleted (obsolete)
newuser.1:
	- renamed to newuser.8
newuser.c, newuser.8:
	- account home directories are now made in /home rather than /user
	- made all the routines internal to this file to be class 'static'
	- fit sources into GNO base distribution builds
	- added checks for parsing NEWID_FILE
	- added various conchecks to prevent buffer overflow and similar
	  problems
	- ensure the password is at least MIN_PASSWD_LEN characters long
	- don't set the terminal type; that is the responsibility of
	  initd/getty.
	- instead of creating explicit files in the user's home directory,
	  copy every file that is in the SKELETONS directory.
	- account creation is now logged via syslogd
	- added -g flag for selecting non-default group ids
	- check to ensure that the new uid returned by get_next_uid is
	  not already in use; if it is, then log a warning via syslog,
	  skip it, and get another uid
This commit is contained in:
gdr-ftp 1999-02-15 00:22:11 +00:00
parent 5ffbafc1b5
commit 330e74b7e9
11 changed files with 532 additions and 300 deletions

15
usr.sbin/newuser/Makefile Normal file
View File

@ -0,0 +1,15 @@
#
# $Id: Makefile,v 1.1 1999/02/15 00:22:10 gdr-ftp Exp $
#
PROG = newuser
SRCS = newuser.c
LDADD = -lcrypt -lcontrib
DEBUG = 25
OPTIMIZE= 0
CFLAGS += -D__STACK_CHECK__
STACK = 4096 # observed: 940
BINDIR = /usr/sbin
CHAPTER = 8
.INCLUDE: /src/gno/prog.mk

View File

@ -1,7 +1,17 @@
After running the 'install' program, you need to create the files
/var/adm/newuser/newid and /var/adm/newuser/gshrc. The latter is simply
a template gshrc file that all new users will be given. The former is
a file with a single integer (1-5 digits) and *nothing else*. New users
will be assigned the userid found in this file each time newuser is run,
and the userid will be automatically incremented by newuser. So you only
have to set it up once.
$Id: README,v 1.2 1999/02/15 00:22:10 gdr-ftp Exp $
In order to run newuser/newuserv, the following files must exist. They
are installed as part of the GNO base distribution, but you may have to
install them manually if you received newuser/newuserv as a standalone
archive:
/home
A directory. All user home directories will be created in this
directory.
/var/adm/newuser/newid:
A text file containing the next UID that newuser/newuserv
should assign.
/var/adm/newuser/skel:
A directory. All plain files in this directory will be copied
into a user's $HOME directory, when $HOME is created. It is normal
to have a skelton glogin and gshrc in here.

View File

@ -1,9 +0,0 @@
echo "Moving files to appropriate places..."
echo
mv -vi newuser /usr/sbin
mv -vi newuserv /usr/sbin
mv -vi newuser.1 /usr/man/man1/
echo
echo "Make sure the directory /var/adm/newuser exists, and has as"
echo "template 'gshrc' file in it. Also required in that directory"
echo "is the 'newid' file, which holds the next available userid."

View File

@ -0,0 +1,9 @@
# 0
# 1 The first column is the "real" program; the second is what _should_
# 2 be the symlink, but for now is a copy.
# 3 All paths should be relative to the root directory. This list
# 4 should be kept sorted.
# 5
# 6 $Id: mklink.data,v 1.1 1999/02/15 00:22:10 gdr-ftp Exp $
# 7
usr/sbin/newuser usr/sbin/newuserv

View File

@ -0,0 +1,8 @@
# 0
# 1 The first column is the "real" man page; the second is the .so link.
# 2 All paths should be relative to the /usr/man directory. This list
# 3 should be kept sorted.
# 4
# 5 $Id: mkso.data,v 1.1 1999/02/15 00:22:10 gdr-ftp Exp $
# 6
man8/newuser.8 man8/newuserv.8

View File

@ -1,52 +0,0 @@
.TH NEWUSER 8
.SH NAME
.nf
newuser - add a new user to the system
newuserv - add a new user to the system, subject to validation
.fi
.LP
.SH DESCRIPTION
This is
.B newuser
for GNO/ME. Its basic intent is
to let people add themselves to the system without requiring the system
administrator to do it all manually.
.LP
.B newuser
will ask for real name, account name, terminal type and password (verifying
the password once) and then create the directory /user/(account name) and
copy a template
.B gshrc
into that directory. Then it will add the user to
.B /etc/passwd
and exit.
.PP
If the
.B -v
(verify) flag is selected, everything is done as normal, except
that the new entry is appended to
.B /var/adm/newuser/newusers
instead of being appended to
.BR /etc/passwd ". "
.LP
.SH FILES
.nf
.BR /var/adm/newuser/newid " -- This file holds the next available"
userID. newuser will increment it as necessary.
.BR /var/adm/newuser/gshrc " -- This is the 'template' gshrc file"
that all new users will get. In addition to this, newuser will append
'set' commands to set $home and $user.
.BR /etc/passwd " -- Not required if you use -v. But what's the point"
in newuser if you don't have it? :)
.BR /user/ " -- Has to exist. This is where the user's home directories"
go.
.fi
.LP
.B newuser
will time out after 60 seconds of operation.
.LP
.SH AUTHOR
.nf
James Brookes
jamesb@cscihp.ecst.csuchico.edu
.fi

View File

@ -1,52 +1,88 @@
.TH NEWUSER 8
.TH NEWUSER 8 "14 February 1999" GNO "System Administration"
.SH NAME
.nf
newuser - add a new user to the system
newuserv - add a new user to the system, subject to validation
.fi
.LP
.BR newuser ,
.BR newuserv
\- add a new user to the system
.SH SYNOPSIS
.BR newuser
[
.BR -v
] [
.B -g
.I gid
]
.br
.BR newuserv
[
.BR -v
] [
.B -g
.I gid
]
.SH DESCRIPTION
This is
This manual page documents
.B newuser
for GNO/ME. Its basic intent is
and
.B newuserv
version 1.2 for GNO. Its basic intent is
to let people add themselves to the system without requiring the system
administrator to do it all manually.
.LP
.B newuser
will ask for real name, account name, terminal type and password (verifying
the password once) and then create the directory /user/(account name) and
copy a template
.B gshrc
into that directory. Then it will add the user to
will ask for a real name, account name, terminal type and password (verifying
the password once) and then create the directory \fB/home/\fIaccount_name\fR.
.BR newuser
will also copy all the regular files from the
.BR /var/adm/newuser/skel
directory into the \fB/home/\fIaccount_name\fR directory.
It will not recurse.
Finally, it will add the appropriate entry to
.B /etc/passwd
and exit.
and then exit.
.PP
If the
.B -v
(verify) flag is selected, everything is done as normal, except
that the new entry is appended to
.B /var/adm/newuser/newusers
(verify) flag is selected, or if invoked as
.BR newuserv ,
everything is done as normal, except that the new entry is appended to
.B /var/adm/newuser/pending
instead of being appended to
.BR /etc/passwd ". "
.BR /etc/passwd .
.LP
.SH FILES
.nf
.BR /var/adm/newuser/newid " -- This file holds the next available"
userID. newuser will increment it as necessary.
.BR /var/adm/newuser/gshrc " -- This is the 'template' gshrc file"
that all new users will get. In addition to this, newuser will append
'set' commands to set $home and $user.
.BR /etc/passwd " -- Not required if you use -v. But what's the point"
in newuser if you don't have it? :)
.BR /user/ " -- Has to exist. This is where the user's home directories"
go.
.fi
Accounts are normally created with group ID 100. The
.B -g
flag overrides this group ID.
.LP
Both
.BR newuser
and
.BR newuserv
will log created accounts via
.BR syslogd (8)
using the auth.info facility.
.LP
.B newuser
will time out after 60 seconds of operation.
.LP
.SH FILES
.IP \fB/home\fR
The directory where new user home directories will be placed.
.IP \fB/var/adm/newuser/newid\fR
The text file containing the next available user ID. It must consist
of exactly one line, containing only a decimal number.
.BR newuser
will update this file as required.
.IP \fB/var/adm/newuser/pending\fR
This file contains all of the
.BR /etc/passwd
entries that are waiting for approval before activation.
.IP \fB/var/adm/newuser/skel\fR
All regular files in this directory will be copied to the newly created
home directory.
.SH BUGS
.BR newuser
should create a lock file in
.BR /var/locks
to ensure that a race condition with multiple instantiations is avoided.
They are currently possible.
.SH AUTHOR
.nf
James Brookes
jamesb@cscihp.ecst.csuchico.edu
.fi
James Brookes. Maintained by Devin Reade.

View File

@ -1,85 +1,114 @@
/* */
/* newuser - add a new user to the system, v1.1 -- James Brookes */
/* */
/* Changes from 1.0 */
/* */
/* * Removed code to add "set $home/$user" stuff to new user's gshrc */
/* file, per request of Phil Vandry. */
/* * Added restriction that the new password entered must be greater */
/* than four characters. */
/* * Newuser will now try multiple times to open up the /etc/passwd */
/* file, just as passwd itself does. */
/* */
/* Some code borrowed from Eric Shepard's passwd source. */
/* */
/* files: /var/adm/newuser/newid */
/* /var/adm/newuser/newusers */
/* /var/adm/newuser/gshrc */
/* /user/ */
/* */
/*#pragma optimize -1 */
#pragma stacksize 512
/*
* newuser - add a new user to the system -- James Brookes
*
* $Id: newuser.c,v 1.3 1999/02/15 00:22:11 gdr-ftp Exp $
*
* Changes for version 1.2 (Modifications by Devin Reade)
* - account home directories are now made in /home rather than /user
* - made all the routines internal to this file to be class 'static'
* - fit sources into GNO base distribution builds
* - added checks for parsing NEWID_FILE
* - added various conchecks to prevent buffer overflow and similar
* problems
* - ensure the password is at least MIN_PASSWD_LEN characters long
* - don't set the terminal type; that is the responsibility of
* initd/getty.
* - instead of creating explicit files in the user's home directory,
* copy every file that is in the SKELETONS directory.
* - account creation is now logged via syslogd
* - added -g flag for selecting non-default group ids
* - check to ensure that the new uid returned by get_next_uid is
* not already in use; if it is, then log a warning via syslog,
* skip it, and get another uid
*
* Changes for version 1.1
*
* * Removed code to add "set $home/$user" stuff to new user's gshrc
* file, per request of Phil Vandry.
* * Added restriction that the new password entered must be greater
* than four characters.
* * Newuser will now try multiple times to open up the /etc/passwd
* file, just as passwd itself does.
*
* Original version 1.0:
* * Some code borrowed from Eric Shepard's passwd source.
*
* files: /var/adm/newuser/newid
* /var/adm/newuser/newusers
* /var/adm/newuser/gshrc
* /user/
*/
#include <sys/stat.h>
#include <limits.h>
#include <paths.h>
#include <errno.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <sgtty.h>
#include <gno/gno.h>
#include <pwd.h>
#include <unistd.h>
#include <syslog.h>
#include <err.h>
#include <dirent.h>
#include <gno/gno.h>
#include <gno/contrib.h>
#pragma lint -1
#define HOME "/home"
#define NEWID_FILE "/var/adm/newuser/newid" /* next ID to assign */
#define NEWUSERS_FILE "/var/adm/newuser/pending" /* addtions "on hold */
#define SKELETONS "/var/adm/newuser/skel" /* files to copy */
#define DEFAULT_SHELL _PATH_GSHELL /* default shell */
char *getpass(char *prompt);
char *crypt(char *key, char *salt);
void time_out(void);
void makesalt(char *salt, long seed);
int get_next_uid(void);
void getpassword(char *password, char *salt, char *passstring);
int bad_name(char *acct_name);
void myfgets(char *string, int maxchar, FILE *FilePtr);
FILE *smartopen(char *file, char *mode);
#define NEWID_FILE "/var/adm/newuser/newid"
#define NEWUSERS_FILE "/var/adm/newuser/newusers"
#define NEWGSHRC_FILE "/var/adm/newuser/gshrc"
#define DEFAULT_GID 2 /* default group ID assigned to new user */
#define ACCT_NAME_LEN 8 /* max # of chars in account name */
#define REAL_NAME_LEN 30 /* max # of chars in real name */
#define TERM_TYPE_LEN 8 /* max # of chars in terminal type */
#define MAX_TRIES 3 /* max # of trials for opening passwd file */
#define MIN_PASSWD_LEN 5 /* minimum length of cleartext password */
#define DEFAULT_GID 100 /* default group ID assigned to new user */
#define ACCT_NAME_LEN 32 /* max # of chars in account name, +1 */
/* We later truncate the account name to */
/* to no more than 8 chars. */
#define REAL_NAME_LEN 31 /* max # of chars in real name, +1 */
#define CRYPT_PASS_LEN 14 /* max # of chars in encrypted passwd +1 */
#define MAX_TRIES 3 /* max # of trials for opening passwd file */
#ifndef FALSE
#define FALSE 0
#define TRUE 1
#endif
static char acct_name[ACCT_NAME_LEN+1],
buffer[80],
name[REAL_NAME_LEN+1],
pass1[14], pass2[14],
salt[3],
scratch[256],
term_type[TERM_TYPE_LEN+1];
static void time_out(void);
static void makesalt(char *salt, long seed);
static uid_t get_next_uid(void);
static int getpassword(char *, int, char *, char *);
static int bad_name(char *acct_name);
static void mygets(char *string, int maxchar);
static FILE * smartopen(char *file, char *mode);
static char acct_name[ACCT_NAME_LEN];
static char name[REAL_NAME_LEN];
static char pass1[CRYPT_PASS_LEN];
static char pass2[CRYPT_PASS_LEN];
static char salt[3];
static char newhome[PATH_MAX];
static unsigned char salttab[] = /* table of chars for salt */
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
void time_out(void)
{
printf("\nnewuser timed out after 60 seconds.\n");
exit(1);
}
#pragma databank 1
static void
time_out(void)
{
printf("\nnewuser timed out after 60 seconds.\n");
exit(1);
}
#pragma databank 0
/* Borrowed from Eric's passwd.cc */
void
static void
makesalt(char *salt, long seed)
{
int num = 2;
@ -89,14 +118,27 @@ makesalt(char *salt, long seed)
}
}
int
/*
* get_next_uid()
*
* Return the next available user id from NEWID_FILE, and update the
* NEWID_FILE under the assumption that the returned id will be assigned
* in /etc/passwd. Abort on any errors.
*/
static uid_t
get_next_uid(void)
{
FILE *FPtr;
int uid;
uid_t uid;
FPtr = fopen(NEWID_FILE,"r+");
fscanf(FPtr,"%d\n",&uid);
if ((FPtr = fopen(NEWID_FILE,"r+")) == NULL) {
err(1, "failed to id file %s", NEWID_FILE);
/*NOTREACHED*/
}
if (fscanf(FPtr,"%d\n",&uid) != 1) {
errx(1, "scan of %s failed", NEWID_FILE);
}
rewind(FPtr);
fprintf(FPtr,"%d\n",uid+1);
fclose(FPtr);
@ -104,56 +146,120 @@ get_next_uid(void)
return(uid);
}
void
getpassword(char *password, char *salt, char *passstring)
/*
* getpassword
* prompt for a password with <passstrings>. put the encrypted
* password into <password>, aborting if it's length is greater
* than <passwdlen>-1. Return the length of the plaintext password.
*/
static int
getpassword(char *password, int passwdlen, char *salt, char *passstring)
{
char *pass, *passcode;
int length_clear, length_crypt, quit_now;
pass = getpass(passstring);
passcode = crypt(pass,salt);
if (*pass == '\0') { /* ^D */
quit_now = 1;
} else {
quit_now = 0;
length_clear = strlen(pass);
passcode = crypt(pass,salt);
}
/* zero out the cleartext password */
for (length_crypt=0; length_crypt<_PASSWORD_LEN; length_crypt++) {
if (pass[length_crypt] == '\0') {
break;
}
pass[length_crypt] = '\0';
}
/* password not given? */
if (quit_now) {
errx(1, "aborted");
}
if (length_crypt > passwdlen-1) {
errx(1,
"internal error: encrypted password length (%d) > buffer length (%d)",
length_crypt+1, passwdlen);
/*NOTREACHED*/
}
strcpy(password,passcode);
return length_clear;
}
int
/*
* bad_name()
*
* return nonzero if <acct_name> is unsuitable as an account name. It must
* be between 2 and 8 characters long, start with a lower case letter, and
* contain only lower case letters or digits.
*/
static int
bad_name(char *acct_name)
{
if (!isalpha(*acct_name++))
int len;
len = strlen(acct_name);
if ((len < 2) || (len > 8) || !islower(*acct_name)) {
return(TRUE);
}
len = 1;
acct_name++;
while (*acct_name != '\0')
if (!isalnum(*acct_name++))
while (*acct_name != '\0') {
len++;
if ((len > 8) || (!islower(*acct_name) && !isdigit(*acct_name))) {
return(TRUE);
}
acct_name++;
}
/* it's a good account name */
return(FALSE);
}
void
myfgets(char *string, int maxchar, FILE *FilePtr)
static void
mygets(char *string, int maxchar)
{
int last_char;
char *tmp_buf;
tmp_buf = (char *) malloc (256);
maxchar++;
fgets(tmp_buf,maxchar,FilePtr);
if (*tmp_buf == 0x00) /* ^D */
exit(1);
last_char = strlen(tmp_buf)-1;
/* remove terminating \n if necessary */
if ((tmp_buf[last_char] == '\n') || (tmp_buf[last_char] == '\r'))
tmp_buf[last_char] = '\0';
strcpy(string,tmp_buf);
fflush(stdin);
free(tmp_buf);
int len;
fgets(string, maxchar, stdin);
fflush(stdin);
if (*string == 0x00) { /* ^D */
goto fail;
}
len = strlen(string);
if (len == 0) {
goto fail;
}
/* remove terminating \n if necessary */
if ((string[len-1] == '\r') || (string[len-1] == '\n')) {
string[len-1] = '\0';
len--;
}
/* check for empty string */
if ((len == 0)) {
goto fail;
}
return;
fail:
errx(1, "aborted");
/*NOTREACHED*/
}
/* try multiple times to open /etc/passwd file */
FILE *
static FILE *
smartopen(char *file, char *mode)
{
FILE *FOutPtr;
@ -171,15 +277,54 @@ smartopen(char *file, char *mode)
return(FOutPtr);
}
static void
usage (void)
{
printf("Usage: newuser [-v] [-g gid]\n");
printf(" newuserv [-v] [-g gid]\n");
exit(1);
}
int
main (int argc, char **argv)
{
int validate, uid;
FILE *FInPtr, *FOutPtr;
int validate, ch;
uid_t uid;
gid_t gid;
FILE *FOutPtr;
DIR *dirp;
struct dirent *entp;
struct sgttyb *s;
s = (struct sgttyb *) malloc (sizeof(struct sgttyb));
char *srcfile;
__REPORT_STACK();
/* check usage */
gid = DEFAULT_GID;
validate = (strcmp(basename(argv[0]), "newuserv") == 0) ? TRUE : FALSE;
while ((ch = getopt(argc, argv, "vg:")) != EOF) {
switch(ch) {
case 'g':
if ((gid = atoi(optarg)) == 0) {
gid = DEFAULT_GID;
}
break;
case 'v':
validate = TRUE;
break;
default:
usage();
}
}
if (argc - optind > 0) {
usage();
}
/* set up for system logging */
openlog(basename(argv[0]), LOG_PID | LOG_NDELAY, LOG_AUTH | LOG_INFO);
/* set up signal handlers */
signal(SIGINT,SIG_IGN);
signal(SIGHUP,SIG_IGN);
signal(SIGQUIT,SIG_IGN);
@ -187,40 +332,34 @@ main (int argc, char **argv)
signal(SIGALRM,time_out);
/* Set proper erase character */
s = malloc (sizeof(struct sgttyb));
gtty(STDIN_FILENO,s);
s->sg_erase = 0x7f;
stty(STDIN_FILENO,s);
free(s);
validate = FALSE;
if (argc == 2 && !strcmp(argv[1],"-v"))
validate = TRUE;
else if (argc == 1);
else
exit(1);
/* Make sure all required files exist before going any further */
if ((FInPtr = fopen(NEWID_FILE,"r+")) == NULL) {
fprintf(stderr,"unable to open %s; exiting.\n",NEWID_FILE);
exit(1);
if (access(NEWID_FILE, R_OK | W_OK) != 0) {
errx(1, "no read/write access for %s", NEWID_FILE);
}
if (access(HOME, R_OK | W_OK | X_OK) != 0) {
errx(1, "no read/write/execute access for %s", HOME);
}
if (access(SKELETONS, R_OK | X_OK) != 0) {
errx(1, "no read/execute access for %s", SKELETONS);
}
fclose(FInPtr);
if ((FInPtr = fopen(NEWGSHRC_FILE,"r+")) == NULL) {
fprintf(stderr,"unable to open %s; exiting.\n",NEWGSHRC_FILE);
exit(1);
printf("\n\tYou have requested a new account. You will be required\n");
printf("\tto enter the account information, after which ");
if (validate) {
printf("your account\n\tWill be placed on hold until it is verified\n");
} else {
printf("you will be\n\table to log into the system\n");
}
fclose(FInPtr);
/* Get information */
printf("\nReal Name: ");
myfgets(name,REAL_NAME_LEN,stdin);
/* Get the user's "Real Name" for the GECOS field */
printf("\nReal Name: ");
mygets(name, REAL_NAME_LEN);
/* Get login name. If the login name is duplicate, prompt for */
/* a new login name. If the login name would call for the */
@ -232,91 +371,142 @@ main (int argc, char **argv)
while(1) {
printf("Login Name: ");
myfgets(acct_name,ACCT_NAME_LEN,stdin);
printf("\n\n(login name: '%s')\n\n",acct_name);
if (getpwnam(acct_name) != NULL) {
printf("Duplicate username: please choose another.\n");
} else if (bad_name(acct_name)) {
printf("\n** Invalid username: please choose a name comprised of\n");
printf(" alphanumeric characters which starts with an alphabetic\n");
printf(" character.\n");
mygets(acct_name, ACCT_NAME_LEN);
#if 0
printf("\n\n(login name: '%s')\n\n", acct_name);
#endif
if (bad_name(acct_name)) {
puts("\nInvalid login name. Login names must be between 2 and 8");
puts("characters long, must start with a lower case letter, and");
puts("must consist of only digits and lower case letters.\n");
} else if (getpwnam(acct_name) != NULL) {
printf("The login name \"%s\" is already in use.\n", acct_name);
printf("Please choose another.\n");
} else {
break;
#if 0
/* bad_name ensures that strlen(acct_name) < 8 */
if (sizeof(HOME) + strlen(acct_name) > PATH_MAX) {
/* what are the chances? */
err(1, "buffer overflow at line %d", __LINE__);
}
#endif
sprintf(newhome, "%s/%s", HOME, acct_name);
if (access(newhome, X_OK) == 0) {
printf("The login name \"%s\" has already been requested by someone else\n",
acct_name);
printf("Please choose another.\n");
} else {
break;
}
}
}
printf("Terminal Type: ");
myfgets(term_type,TERM_TYPE_LEN,stdin);
/* Get password of > 4 chars, with verification */
/* close the file descriptor we have open on /etc/passswd */
endpwent();
/* Get password of >= MIN_PASSWD_LEN chars, with verification */
makesalt(salt, rand());
while(1) {
getpassword(pass1,salt,"Password: ");
getpassword(pass2,salt,"Verify: ");
if (!strcmp(pass1,pass2) && (strlen(pass1) > 4)) {
if (getpassword(pass1, CRYPT_PASS_LEN, salt, "Password: ")
< MIN_PASSWD_LEN) {
printf("The password must be at least %d characters long.\nTry again.\n",
MIN_PASSWD_LEN);
continue;
}
getpassword(pass2, CRYPT_PASS_LEN, salt,"Verify: ");
if (strcmp(pass1,pass2) == 0) {
break;
} else {
printf("*** Failed verification.\n");
printf("Passwords don't match. Try again.\n");
}
}
uid = get_next_uid(); /* get and update next free ID# */
/* make home directory */
sprintf(scratch,"mkdir -s /user/%s",acct_name);
exec("/bin/mkdir",scratch);
sleep(2);
/* and copy default gshrc to it */
sprintf(scratch,"/user/%s/gshrc",acct_name);
FOutPtr = fopen(scratch,"w");
FInPtr = fopen(NEWGSHRC_FILE,"r");
while(fgets(buffer,80,FInPtr) != NULL) {
fputs(buffer,FOutPtr);
/*
* Get the next free uid and update the NEWID_FILE. When we return from
* this routine, we are now past the point of no return; if we fail
* anything, then we have used up a user id.
*/
while(1) {
uid = get_next_uid();
if (getpwuid(uid) == NULL) {
break;
} else {
syslog(LOG_WARNING, "uid %d is already in use; skipping", uid);
}
}
fclose(FInPtr);
/* update default gshrc to have correct $home, $user, and $term */
/* Phil asked that this be removed, so... :) */
#if 0
fprintf(FOutPtr,"set home=/user/%s\n",acct_name);
fprintf(FOutPtr,"set user=%s\n",acct_name);
#endif
fprintf(FOutPtr,"set term=%s\n",term_type);
/*
* make the home directory
*/
if (mkdir(newhome) != 0) {
err(1, "failed to create directory %s", newhome);
}
#if 0
fprintf(FOutPtr,"export home user term\n");
#else
fprintf(FOutPtr,"export term\n");
#endif
fclose(FOutPtr);
/*
* Copy each of the files in SKELETONS into the user's home directory.
* Initially change directory into SKELETONS so that we can use partial
* pathnames when copying the files into $HOME.
*/
putchar('\n');
if (chdir(SKELETONS) != 0) {
err(1, "couldn't change directory into %s", SKELETONS);
/*NOTREACHED*/
}
if ((dirp = opendir(SKELETONS)) == NULL) {
err(1, "read of directory %d failed", SKELETONS);
}
while ((entp = readdir(dirp)) != NULL) {
/* only copy regular files, and don't recurse through subdirectories */
if (entp->d_type == DT_DIR) {
continue;
}
/* skip entries for current and parent directories */
srcfile = entp->d_name;
if (((srcfile[0]=='.') && (srcfile[1]=='\0')) ||
((srcfile[0]=='.') && (srcfile[1]=='.') && (srcfile[2]=='\0'))) {
continue;
}
/* do the copy */
srcfile = LC_CopyFile(srcfile, newhome, LC_COPY_DATA | LC_COPY_REZ);
if (srcfile == NULL) {
err(1, "couldn't copy %s", entp->d_name);
} else {
printf("creating %s\n", srcfile);
}
}
closedir(dirp);
/* Save the password information away. */
if (!validate) { /* no validation, so append new entry to /etc/passwd */
FOutPtr = smartopen("/etc/passwd","a");
FOutPtr = smartopen(_PATH_PASSWD, "a");
if (FOutPtr == NULL) {
fprintf(stderr,"Trouble opening /etc/passwd file.\nExiting\n");
exit(1);
err(1, "couldn't open %s", _PATH_PASSWD);
}
fprintf(FOutPtr,"%s:%s:%d:%d:%s:/user/%s:/bin/gsh\n",acct_name,pass1,
uid,DEFAULT_GID,name,acct_name);
fprintf(FOutPtr, "%s:%s:%d:%d:%s:%s/%s:%s\n",
acct_name, pass1, uid, gid, name, HOME, acct_name, DEFAULT_SHELL);
fclose(FOutPtr);
syslog(LOG_INFO, "created account %s", acct_name);
printf("You may now log in.\n");
} else { /* validation selected -- so append new entry to NEWUSERS_FILE */
FOutPtr = fopen(NEWUSERS_FILE,"a");
fprintf(FOutPtr,"%s:%s:%d:0:%s:/user/%s:/bin/gsh\n",acct_name,pass1,
uid,name,acct_name);
if ((FOutPtr = fopen(NEWUSERS_FILE, "a")) == NULL) {
err(1, "couldn't open %s", NEWUSERS_FILE);
}
fprintf(FOutPtr,"%s:%s:%d:%d:%s:%s/%s:%s\n",
acct_name, pass1, uid, gid, name, HOME, acct_name, DEFAULT_SHELL);
fclose(FOutPtr);
printf("Try back in 24 hours.\n");
syslog(LOG_INFO, "created account %s pending validation", acct_name);
printf("\nYour account will be available after the system administrator");
printf("has had a\nchance to review it.\n");
}
closelog();
exit(0);
return 0;
}

View File

@ -0,0 +1,23 @@
Name: newuser
Version: 1.2
Shell: GNO
Author: James Brookes. Maintained by Devin Reade.
Contact: gdr@trenco.gno.org
Where: /usr/sbin
FTP: ftp.gno.org
Create a home directory in /home with a template $HOME/gshrc and $HOME/glogin
for a new user, and add the user's entry into the /etc/passwd file for
immediate access. See also newuserv.
Name: newuserv
Version: 1.2
Shell: GNO
Author: James Brookes. Maintained by Devin Reade.
Contact: gdr@trenco.gno.org
Where: /usr/sbin
FTP: ftp.gno.org
Create a home directory in /home with a template $HOME/gshrc and $HOME/glogin
for a new user, and add the user's entry into the /var/adm/newuser/newusers
file for validation by the system operator. See also newuserv.

View File

@ -0,0 +1,18 @@
/*
* $Id: newuser.rez,v 1.1 1999/02/15 00:22:11 gdr-ftp Exp $
*/
#include "Types.Rez"
#include "builddate.rez"
resource rVersion (0x1, purgeable3, nocrossbank) {
{ 1, 2, 0, /* version */
release, /* development|alpha|beta|final|release */
0 /* non-final release number */
},
verUS,
"newuser/newuserv",
"create new accounts\n"
BUILD_DATE
};

View File

@ -1,16 +0,0 @@
#pragma optimize -1
#pragma stacksize 256
/* */
/* newverify.c - a simple program to launch newuser with the -v option */
/* */
#include<stdio.h>
#include<stdlib.h>
#include<gno/gno.h>
int main(int argc, char **argv)
{
execve("/usr/sbin/newuser","newuser -v");
}