[net.sources] Automatic account/password entry program

root@sbcs.UUCP (SBCS Systems Staff) (11/21/83)

	System Administrators: Ever get tired of creating accounts manually?
I do not know if anything like this exists, but, here goes.

	The following routines will give you a quick and easy way to generate
Unix accounts -  both the entry in /etc/passwd, and the creation and chowning
of new home directories.  This was developed on 4.1bsd.  Please inform me of
any bugs, refinements, ...     
						Lory Molesky




	The following script will extract README, pwentry.8 pwentry.c,
pwsort.c, and pwmakedir.  

echo x = README
cat >README <<'!Funky!Stuff!'
The script pwmakedir relies on a /usr/skel/.login and
/usr/skel/.cshrc.

Remove those ::0:0:: type markers from /etc/passwd before
using pwentry.
!Funky!Stuff!
echo x = makefile
cat >makefile <<'!Funky!Stuff!'
BIN=/usr/bin
ETC=/etc
all: pwentry.c
	cc -O -o pwentry pwentry.c
	cc -O -o pwsort pwsort.c

install: 
	cp pwentry.8 /usr/man/man8/pwentry.8
	cp pwentry $(BIN)/pwentry
	cp pwmakedir $(BIN)/pwmakedir
	chmod 4110 $(BIN)/pwentry
	chmod 4110 $(BIN)/pwmakedir
	cp /dev/null $(ETC)/tempfile
	chmod 755 $(ETC)/tempfile
!Funky!Stuff!
echo x = pwentry.8
cat >pwentry.8 <<'!Funky!Stuff!'
.TH PWENTRY l
.UC 4
.SH NAME
pwentry, pwmakedir \- automatic account generator
.SH SYNOPSIS
.B /usr/bin/pwentry
[ -uUID -d -g ]
.PP
.SH DESCRIPTION
.I Pwmakedir
invoke an automated account entry program.  The system administrator
is prompted to enter four fields of information for the new user,
login name, full name, home directory, and group number.  From this 
information, an entry is inserted in 
.I /etc/passwd,
.I /etc/group,
and the users home directory with the appropriate dot files is created.
.PP
The following optional arguments are accepted:
.PP
.TP 8
.B -d   
Do not call
.I pwmakedir
to make the users home directory.
.PP
.TP 8
.B -gGID
Use GID as the group number for all entries.
.PP
.TP 8
.B -hDIR
Use DIR as the home directory for all entries.
.PP
.TP 8
.B -n   
Do not enter the user in the 
.I /etc/group 
file.
.PP
.TP 8
.B -uUID
The following user id is used to start the search in
.I /etc/passwd.
.PP
These routines rely on a free of marker
.I /etc/passwd 
file.  Upon completion of
.I pwentry,
the 
.I /etc/passwd
file will be sorted on the UID field.
The head of the home directory must exist, or
.I pwmakedir
will fail.  (if /uh/graphics/joe is the homedir, /uh/graphics must
exist previous to
.I pwmakedir's
invocation).
.I Pwentry
will not allow duplicate UID's or duplicate login names.
.PP
.I Pwentry
will loop, asking for another login name, until the string
.I exit
is entered.  The passwd file is then merged with the entries, and
pwmakedir is involed.  The 
.B -uUID
option is particularly useful if it is desired to arrange the
.I /etc/passwd
file in some home directory style order.
For example,
.PP
pwentry -u300 -g19 -h/uh/graphics
.PP
will prompt for login name and full name only, using the first UID >= 300.
.SH FILES
/etc/passwd	password file.
.br
/etc/group	group file.
.br
/etc/tempfile	stores user entries before merging with passwd.
.br
.SH AUTHOR
Lory Molesky
.SH BUGS
The search of the password file is slow if the UID supplied has
many sequential entries after it.  If the 
.I /etc/passwd
file has the ::0:0::: markers before it is sorted, these will be
placed in the first lines of
.I /etc/passwd
confusing the UNIX file system.
.br
!Funky!Stuff!
echo x = pwentry.c
cat >pwentry.c <<'!Funky!Stuff!'
/*	pwentry.c			Lory Molesky (root!sbcs)

	Automatic account generator.  

	options:	
	-uUID	use this as the lower bound uid to start search.
	-d	Do not call the shell file to make the users directory.
	-n	Do not enter users in /etc/group file
	-gGID	Use this number as the group id for all entries
	-hDIR	Use this directory as the home directory for all entries.


*/
	

#include <stdio.h>
#include <pwd.h>
#define max_count 40	/* max entries per invocation */

main(argc, argv)
int argc;
char *argv[];
{
	FILE *fopen(), *fp;
	char name[max_count][12],home[max_count][40];
	char firstname[20],lastname[20],shell[20],homename[35],newdir[55],groupie[70];
	char uid_s[5],gid_s[5],c,*x;
	int i,j,debug,uid,count,makedir,entgroup,home_ask,group_ask;
	int gid[max_count];
	
	debug = 0;
	uid = 1000;
	count = 0;
	home_ask = 1;
	group_ask = 1;
	makedir = 1;
	entgroup =1;
	for (i=1; i<argc; i++)
	{
		if (argv[i][0] == '-')
		{
			c = argv[i][1];
			switch(c)
			{
			case 'u':
				j=0;
				while ((uid_s[j] = argv[i][j+2]) != '\0') j++;
				uid = atoi(uid_s);
				break;

			case 'd':
				makedir = 0;
				break;

			case 'n':
				entgroup = 0;
				break;

			case 'g':
				group_ask = 0;
				j=0;
				while ((gid_s[j] = argv[i][j+2]) != '\0') j++;
				gid[0] = atoi(gid_s);
				break;

			case 'h':
				home_ask = 0;
				j=0;
				while ((home[0][j] = argv[i][j+2]) != '\0') j++;
				home[0][j] = '\0';
				break;

			default : 
				printf("*** illegal option ***\n");
				exit();
			}
		}
	}

	if ((fp = fopen("/etc/tempfile","w")) == NULL) {
		printf("File tempfile does not exist\n");
		exit();
	}

	printf("Automatic passwd entry program.\n");
	sprintf(shell, "/bin/csh");
	sprintf(name[count], "nothing");

	/* Loop until user enters the name 'exit' on the first prompt */

	while (strcmp(name[count],"exit") != 0) {
		if (count == (max_count - 1)) {
			printf("*** Maximum number of names reached, exiting ***\n");
			sprintf(name[count],"exit");
		}
newname:	if (count < (max_count - 1)) {
			printf("\nLogin name:\t\t");
			scanf("%s",name[count]);
		}
		if (strcmp(name[count],"exit") != 0) {

			if (strlen(name[count]) > 8) {
				printf("*** Login name limited to eight chararacters ***\n");
				goto newname;
			}

			if ((strcmp(name[count],"?") == 0) || (strcmp(name[count],"help") == 0)) {
				printf("*** Enter exit to finish ***");
				goto newname;
			}
			if ((x = (char *) getpwnam(name[count])) != NULL)
			{ 
				printf("*** Duplicate login name ***\n");
				goto newname;
			}
		
			printf("full name:\t\t");
			c = getchar();
			i = 0;
			while ((c = getchar()) != '\n') {
				firstname[i++] = c;
			}
			firstname[i] = '\0';

			if (home_ask) {
				printf("home directory:\t\t");
				scanf("%s",home[count]);
			}
			else strcpy(home[count],home[0]);
			sprintf(homename, "%s/%s",home[count],name[count]);

			if (group_ask) {
				printf("groupid:\t\t");
				scanf("%d",&gid[count]);
			}
			else gid[count] = gid[0];
		
			while ((x = (char *) getpwuid(uid)) != NULL) uid++;
			if (debug) printf("uid is :%d",uid);

			fprintf(fp,"%s::%d:%d:%s %s:%s:%s\n",name[count],uid,gid[count],firstname,lastname,homename,shell);

			count++;
			uid++;	/* to allow multiple entries per invocation */
		}
	}

	fclose(fp);
	system("cp /etc/passwd /etc/passwd.OLD");
	system("sort -t: +2n /etc/tempfile -o /etc/tempfile");
	if (debug) system("cat /etc/tempfile");
	system("sort -t: +2n /etc/tempfile /etc/passwd -o /etc/passwd");
	printf("sorted, merged tempfile\n");
	/* pwmakedir is a shell script to make the new users home directory,
	/* with correct ownership, .login and .cshrc	*/
	if (makedir) {
		for (j=0; j<count; j++)
		{
			sprintf(newdir, "pwmakedir %s %s",home[j],name[j]);
			system(newdir);
			if (entgroup) {
				system("cp /etc/group /etc/group.OLD");
				sprintf(groupie,"sed s/%d:/%d:%s,/ /etc/group > /etc/group.old",gid[j],gid[j],name[j]);
				system(groupie);
				system("mv /etc/group.old /etc/group");
			}
		}
	}

}
!Funky!Stuff!
echo x = pwsort.c
cat >pwsort.c <<'!Funky!Stuff!'

/* Not too useful, but instructive. */
main()
{

system("sort -m /etc/tempfile /etc/passwd -o /etc/passwd");
system("sort -t: +2n /etc/passwd -o /etc/passwd");

}
!Funky!Stuff!
echo x=pwmakedir
cat >pwmakedir <<'!Funky!Stuff!'
# arg1 - home trail
# arg2 - user name
cd $1
mkdir $2
chown $2 $2
cd $2
cp /usr/skel/.login .
cp /usr/skel/.cshrc .
chown $2 .login
chown $2 .cshrc
echo 'processed' $2 'to' $1
!Funky!Stuff!