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!