home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume13
/
autoadd
< prev
next >
Wrap
Text File
|
1988-01-31
|
26KB
|
987 lines
Subject: v13i043: Program to add users to system
Newsgroups: comp.sources.unix
Sender: sources
Approved: rsalz@uunet.UU.NET
Submitted-by: jim nelson <ecsgate!ecsvax!nelson>
Posting-number: Volume 13, Issue 43
Archive-name: autoadd
Autoadd reads lines from an input file, creates required lines in
/etc/passwd, calls mkdir(1) to create required directories, creates
.profile files, etc. It's designed for educational environments.
# To unbundle, sh this file
echo MANIFEST 1>&2
sed -e 's/^X//' >MANIFEST <<'End'
XMANIFEST
XREADME
Xautoadd.8
XMakefile
Xautoadd.h
Xexample
Xausr
Xkusr
Xalready.c
Xecpw.c
Xexists.c
Xinitfiles.c
Xkindex.c
Xmain.c
Xparse.c
Xquit.c
Xtryagain.c
End
echo README 1>&2
sed -e 's/^X//' >README <<'End'
XAutoadd is yours for the taking. If you like it, use it.
XIf not, trash it. I wrote it just for fun, and because I
Xneeded it. It's hereby put in the public domain; no
Xcopyright, no send-me-money, no nothing.
X
XAutoadd is a batch adduser program. It's in C, with one
Xcall to the "system()" (to mkdir) (why reinvent TWO wheels?)
X(Oh yeah, I think I also sytem("cp ....") just from sheer
Xlaziness).
X
XI'd have to admit to a little hubris, though, in titling the
Xman page with a ".8" suffix instead of ".1". Feel free to
Xmove it to ".1" if you see fit.
X
XI have included my own /etc/ausr and /etc/kusr (Bourne) shell
Xscripts just for comparison with the autoadd.c program. Throw
Xthem away quickly if you have your own favorite (which most
Xeverybody should, I guess.).
X
XNB: this is one of those "Oh, he wants me to run this as root?"
Xprograms. Well, the source is not very long; and it's intended
Xto be totally readable to the most casual of observers, so
Xuse if you like, but
X
X#include <standard.disclaimer>
X
XSee mostly the autoadd.h comments and #defines, but also take
Xa look at initfiles.c .
X--- jhn
X
XOh yeah, all these sources should be looked at with tab stops
Xset at four. They were created using vi with autoindent and
Xtabstops at four. Stops of eight will make some of the lines run
Xoff the screen. Alternatively, run them thru sed and change
Xall \t to four blanks (which I did not do, in the interest of
Xkeeping the byte count down).
X--- jhn
End
echo autoadd.8 1>&2
sed -e 's/^X//' >autoadd.8 <<'End'
X.ig
X @(#)autoadd.8
X..
X.TH AUTOADD 8
X.UC 4
X.SH NAME
Xautoadd \- add class rosters to system
X.SH SYNOPSIS
X.B autoadd
X[
Xfilename
X]
X.SH DESCRIPTION
X.I Autoadd
Xreads lines from an input file, creates required lines in
X/etc/passwd, calls mkdir(1) to create required directories,
Xcreates .profile files, etc.,
Xto add a batch of users to the system. Optionally, it will
Xappend to the /etc/accesstab file for use with "access".
XSupplied in source form. See comments and tunable parameters
Xin autoadd.h for more info.
X.PP
XNo command line parameters are provided; this program will
Xbe used rarely (twice or thrice per semester, typically) and
Xcan be configured by #defines in the source.
X.PP
XKeywords are:
X.TP
X.B prof: professor
X.TP
X.B group: group
X.TP
X.B alias: for a mailrc
X.TP
X.B disk: partition
X.TP
X.B passwd: password
X.TP
X.B firstprog: last line of profile
X.PP
XOther input lines are of the form:
X.TP
X.B lastname i i
X.PP
XThe /etc/passwd file is read to determine the largest user number
Xthere, and the new people are assigned user numbers from there up.
X.SH FILES
X.ta 2i
X/etc/passwd password file
X.br
X/etc/accesstab (optional) for professor:student lines
X.br
X./mailrc alias list for sending to professor
X.SH AUTHOR
XJim Nelson, UNC-Wilmington (nelson@ecsvax.uucp) 919-395-3300
X.SH BUGS
X Must be run as root.
End
echo Makefile 1>&2
sed -e 's/^X//' >Makefile <<'End'
XCFLAGS=
XLDFLAGS=-s
XLINTFLAGS=-hbx
X
XSOURCES= main.c parse.c kindex.c exists.c \
X ecpw.c quit.c initfiles.c already.c tryagain.c
X
XOBJS= main.o parse.o kindex.o exists.o \
X ecpw.o quit.o initfiles.o already.o tryagain.o
X
Xautoadd: $(OBJS) autoadd.h
X cc $(LDFLAGS) -o autoadd $(OBJS)
X
Xmain.o initfiles.o tryagain.o parse.o: autoadd.h
X
Xautoadd.shar: MANIFEST README autoadd.8 Makefile autoadd.h example \
X ausr kusr $(SOURCES)
X shar MANIFEST README autoadd.8 Makefile autoadd.h example \
X ausr kusr $(SOURCES) >autoadd.shar
X
Xlint: $(SOURCES) autoadd.h
X lint $(LINTFLAGS) autoadd.h $(SOURCES)
End
echo autoadd.h 1>&2
sed -e 's/^X//' >autoadd.h <<'End'
X/*
X"autoadd" -- a batch account-setter-upper. for adding whole class
Xrosters to unix machines.
Xby: j. nelson, univ. nc-wilmington, dept. math. sciences,
Xwilmington nc 28403, 919-395-3300.
X
XThe idea here is to allow a student assistant or other partially
Xtrusted assistant to enter the class roster, and then in one
Xswell-foop, add all those folks to the system. This can be either
Xpermitted to the assistant or reserved to the sysop, but requires
Xthat the program be run as root (at least it does on my machines).
X
XAn input file consists of a few "keyword" lines, followed by the
Xclass roster in "lastname fi mi" form.
X
XKeywords :
X"prof:ssss" professor for "accesstab" file
X this is for that neat program that came down the
X wire a while back that allows someone to access
X another directory by effectively "becoming" them.
X If not using, comment out the following line: */
X#define ACCESS
X/*
X"disk:/sssss" parent directory, e.g. /usr3, /stoonts, etc.
X"firstprog:ssss" this will be the last line of .profile
X"shell:xxxxx" shell; 0 means no entry */
X#define PROFILE "/.profile" /*will have parentdir prepended*/
X#define LOGIN "/.login"
X#define STDPROFILE "/etc/stdprofile"
X/*
X"alias:sssss" for manually moving into the prof's .mailrc file
X"group:nnn" group
X"passwd:xxxxxx" password (will be same for all these users, but salt
X is randomly selected)
X"password:xxxx" (same as passwd)
X special case: 1 means use username as password.
X
XAny line containing one of the keywords is processed for the keyword
Xvalue. Null lines, blank lines, and lines beginning with # are ignored.
XOther lines are presumed to be name-lines of the form
Xlastname f m
Xthat is, lastname firstinitial middleinitial
Xseparated by blanks.
XThe lastname may be of any length, but will be truncated to ML (default
Xis 7) chars before applying any of the algorithms. fi and mi should
Xbe only single characters, but the parser will accept any number,
Xand will truncate them to single chars.
XAlso accepts usernames of the form abc, where abc is the person's
Xfi mi li, as some system admins like to use, e.g. I would be
X"jhn" (James H Nelson), and "Joe Bob College" would be "jbc".
XThe program assumes that "jhn" is the lastname, and forces fi
Xand mi to be '1' for purposes of the algorithm.
XThe algorithm first tries lastname, then filastname, then
Xlastnamefi, then filastnamemi, etc., etc., finally resorting to
Xprepending digits to usernames if all else fails (this is guaranteed
Xto work unless you have a huge number of users (!)). The exact
Xalgorithm is clear from reading the code in tryagain().
XSee alse the example file.
X*/
X
X#include <stdio.h>
X
X
X/* these next includes probably will not work everywhere */
X/* they DO work on SysVr2 (3b2/300) and a BSD4.1-derived
Xknockoff (lmc -- GENIX on a nsc16032) */
X#include <string.h> /*maybe strings.h ???*/
X#include <sys/types.h> /*maybe don't need sys ??? */
X#include <sys/stat.h> /* ditto */
X#include <errno.h> /*only for ENOENT*/ /*if fails, forget it! */
X
X/* next three are individually tunable parameters */
X#define MAXNU 1300 /*max number of entries in /etc/passwd */
X#define ROOT 0 /* just in case your root is not uid==0 (?weird?) */
X#define ML 7 /*maximum length of a login-name.*/
X/* 7 is a nice length, 'cause tabs work better, but this can be
X anything within reason */
X
X#define null '\0' /*just for ease of typing*/ /* not same as NULL */
X
Xextern void exit(); /* for lint */
X
X#ifdef MAIN /*so only see once; main.c will define MAIN,
Xbut nobody else will*/
X
X/* some of the following might need to be lengthened if sysop
Xallows ridiculously long login names */
X
Xint euid;
X/* euid = geteuid(); */ /*to see if we're dangerous */
X/*this will be done very early in main() */
X/* Autoadd does slightly different things depending on whether
X user is root or not, e.g. /etc/passwd vs. ./passwd , etc.
X Examine the code carefully before running at all, and then re-
X examine it before running as root. This is not a disk-polisher or
X one of those other nasties, (DO NOT take my word for it, look at
X the code!) but it does have to run as root to be
X effective (not necessarily setuid root, just "effective uid"
X of root), 'cause it must append to /etc/passwd and create
X directories in /"disk". (unless you let just anybody do those
X things!)
X*/
X/* some defaults:*/
X#define GROUP "100" /*why not?*/
X#define DISK "/usr4" /*our current place to stash stoonts*/
X#define SHELL "0" /* 0 means Bourne shell */
X#define ALIAS "csc101" /*we don't have a csc101, so why not?*/
X#define FIRSTPROG "0" /* default no startup program */
X#define PROFESSOR "nelson" /* make "0" (with quotes) for none*/
X#define PASSWD "0" /*no default password*/
X#define DISLIST "./mailrc" /*filename of where to put alias list*/
X/*notice that several of the variables default if the first
X(i.e. zeroth) character of a string is the character '0' , but the
Xabove defines must be in double-qoutes, not single-quotes, becuz
Xthey're used in strcpy() statements.
XA couple of other things: GROUP must be a string, not an integer;
Xthe leading / is optional on DISK (it'll be forced if omitted);
XI don't have ksh, so the only way to make it the default is to
Xhack on the source; be sure the look at ecpw.c closely if worried
Xabout passwords.
X*/
X
X/* Global variables: */
Xchar *user[MAXNU],*malloc(); /* we have only about 120, but ...*/
Xchar ecptex[20]; /* large enuff to hold an encrypted password*/
Xchar infile[100]; /*the input filename ... 30 should be plenty*/
Xchar line[142],lastname[50],fi[2],mi[2];
Xchar profname[30],diskname[20],groupname[20],passwordname[20],
X username[40],aliasname[40],firstprog[40],parentdir[40];
Xchar dislist[60],passwd[60],proffile[60] ;
X#endif /*MAIN*/
End
echo example 1>&2
sed -e 's/^X//' >example <<'End'
X# fortran77
Xgroup:195
Xalias:csc111
Xprof:herbst
Xdisk:usr
Xpassword:beginner
X# force them into the menu-shell as the last line
X# of their .profile
Xfirstprog:/usr/uncw/msh
X
Xnelson brain dead
Xmr
Xmmr
Xal-anon muhammad mustafa
Xshell:/bin/csh
Xpodgornowitz a a
Xpodgornowitz a b
X#next person should be only one who has password same as login
Xpasswd:1
Xpodgornowitz b a
Xpasswd:0
X
X# intro comp sci II section 1
Xprof:knuth
Xdisk:/usr1
X#i think this is the unit of albanian currency ?
Xpasswd:zlotny
Xgroup:177
Xfirstprog:0
Xalias:csc12201
Xshell:0
Xcampus big man on
Xcretin a a
Xcretin a b
X# just to see if this works
Xshell:/bin/ksh
Xcretin b a
Xshell:/bin/csh
Xcretin b b
X# go back to Bourne shell
Xshell:0
Xcretin b b
Xjhn
Xcollege suzy coed
Xbch
X#
X# operating systems
Xprof:ast
Xalias:csc342
Xpasswd:Wachtwoord
Xgroup:178
Xdisk:usr3
Xfirstprog:0
X
Xcretin a a
Xcretin a b
Xcretin b a
Xcollege jim bob
Xcretin b b
Xbch
X
X# programming languages
Xprof:dmr
Xpasswd:0
Xalias:csc334
Xdisk:/usr2
Xgroup:179
Xfirstprog:0
X
Xcretin a a
Xfrn
Xcretin a b
Xcollege joe bob
Xcretina b a
Xcretinal b a
Xcretinally terminal hazeltine
Xcretin b b
End
echo ausr 1>&2
sed -e 's/^X//' >ausr <<'End'
XP#I'm not sure how to shar shell scripts, so I just arbitrarily
XP#put a capital letter in column 1. sed should snarf it fine.
XP#!/bin/sh
XP#adduser shell script ... bypasses most of the
XP# agony the sysadm (SysVr2) route makes you go through
XP#jhn 06jan87
XPcase `uname` in
XP 3b2b)
XP echo "puttem where? 2,3,or 4 [default is /usr] \c"
XP read blonk
XP case $blonk in
XP 2) scrod=2;;
XP 3) scrod=3;;
XP 4) scrod=4;;
XP "") scrod="";;
XP *) echo "valid responses are <cr>, 2, 3, or 4. Bye...";
XP exit;;
XP esac ;;
XP 3b2a) scrod="";;
XPesac #end case uname
XPscrod=usr${scrod}
XPecho "putting them in /$scrod
XP please wait ... looking for next avail userno"
XP
XPgroup=100
XPnextuser=`/usr/bin/awk -F: '$3+0>num+0 {num=$3+0}
XPEND {print 1+num}' /etc/passwd `
XP#nextuser=`expr $nextuser + 1`
XPecho next available userno is $nextuser
XP
XPwhile : ; do
XPecho "enter fullname \c"
XPread fullname
XPcase $fullname in
XP "") echo "null user fullname not allowed"; exit 1;;
XPesac
XP
XPecho "enter loginname \c"
XPread login
XPcase $login in
XP "") echo "null user name not allowed"; exit 1;;
XPesac
XPecho "enter usernumber [$nextuser] \c"
XPread user
XPcase $user in
XP "") user=$nextuser;echo "using $user";;
XPesac
XPnextuser=`expr $user + 1`
XPloop=true
XPwhile :
XPdo
XP echo "enter group (? for cat /etc/group) [$group] \c"
XP read xroup
XP case $xroup in
XP \?) cat /etc/group;;
XP "") break;;
XP *) group=$xroup;break;;
XP esac
XPdone
XPcase $group in
XP "") echo null group not allowed ... bye; exit 1;;
XPesac
XP
XP/usr/bin/awk -F: '$1=='\"$login\"' || $3=='\"$user\"' {print}' /etc/passwd\
XP >/tmp/au$$
XPalready=""
XPif test -s /tmp/au$$
XPthen
XP /bin/cat /tmp/au$$
XP echo "login=$login or user=$user in use ..."
XP rm -f /tmp/au$$
XP already=1
XPfi
XPif test -d /${scrod}/$login
XPthen
XP echo "/${scrod}/$login already exists ... !"
XP rm -f /tmp/au$$
XP already=1
XPfi
XP
XP
XPcase $already in
XP "")
XP /bin/mkdir /${scrod}/$login
XP echo "$login::$user:$group:$fullname:/${scrod}/$login:"
XP echo "ok? [y] \c"
XP read doit
XP case $doit in
XP n) /bin/rmdir /${scrod}/$login; exit 1;;
XP esac
XP /bin/chmod u+w /etc/passwd
XP echo "$login::$user:$group:$fullname:/${scrod}/$login:">>/etc/passwd
XP sync
XP /bin/chmod u+w /etc/passwd
XP tail -2 /etc/passwd
XP /bin/chown $user /${scrod}/$login
XP /bin/chgrp $group /${scrod}/$login
XP /bin/chmod 755 /${scrod}/$login
XP /bin/cp /etc/stdprofile /${scrod}/$login/.profile
XP /bin/chown $user /${scrod}/$login/.profile
XP /bin/chgrp sys /${scrod}/$login/.profile
XP /bin/chmod gu+w /${scrod}/$login/.profile
XP case $umsk in
XP "") echo "enter umask [22]: \c"
XP read umsk
XP case $umsk in
XP "") umsk=22;;
XP esac
XP ;;
XP esac
XP echo "umask $umsk">>/${scrod}/$login/.profile
XP echo "menu-shell initially? [n]: \c"
XP read yesno
XP case $yesno in
XP y) echo "/usr/uncw/msh" >> /${scrod}/$login/.profile;;
XP *) echo "menu-shell not selected";;
XP esac
XP echo "give him a password? [y]: \c"
XP read yesno
XP case $yesno in
XP y|"") /bin/passwd $login;;
XP *) echo "no password set for $login";;
XP esac
XP rm -f /tmp/au$$
XP echo "put password aging in effect? [y]: \c"
XP read yesno
XP case $yesno in
XP y|"") /etc/agepw $login;;
XP n) echo password aging not set for $login;;
XP esac
XP;;
XPesac #end of case $already==""
XPcase $god in
XP "") echo "enter godname []: \c"
XP read god;;
XP *) ;;
XPesac
XPcase $god in
XP "") ;;
XP *) echo "$god:$login">>/etc/accesstab
XP ;;
XPesac
XPecho '***** done *****
XP
XP want to add another user? [y] \c'
XPread domore
XPcase $domore in
XP n) exit;;
XPesac
XPdone
XP
End
echo kusr 1>&2
sed -e 's/^X//' >kusr <<'End'
XPcase $1 in
XP "") echo "usage: /etc/kusr username"; exit 1;;
XPesac
XPx=`/usr/bin/awk -F: '$1=='\"$1\"' {print $6}' /etc/passwd `
XPcase $x in
XP/|/etc|/bin|/usr/bin|/usr/uncw|/lib|/usr/lib|/usr/spool ) \
XP echo "rm -r $x would be considered antisocial behavior";exit 1;;
XP "") echo no such user...bye; exit 1;;
XP /usr* ) ;;
XP *) echo "wtf?? x=$x"; exit 1;;
XPesac
XP
XP#echo "about to rm -r $x ok [y] \c"
XP#read ans
XPans=y
XPcase $ans in
XP "") rm -r $x;;
XP n) exit;;
XP y) rm -r $x;;
XP *) echo "invalid response ... $x not removed";exit;;
XPesac
XP#grep -v $1 /etc/passwd > /tmp/kusr$$
XP/usr/bin/awk -F: '$1!='\"$1\"' {print }' /etc/passwd >/tmp/kusr$$
XP#diff /etc/passwd /tmp/kusr$$
XP#echo "ok? [y] \c"
XP#read ans
XPans=y
XPcase $ans in
XP n) exit;;
XP ""|y)
XP /bin/rm -f /usr/mail/$1;
XP cp /tmp/kusr$$ /etc/passwd ;
XP /bin/rm /tmp/kusr$$;;
XP *) echo "invalid response interpreted as \"no\" ";exit;;
XPesac
End
echo already.c 1>&2
sed -e 's/^X//' >already.c <<'End'
X
X#ifndef NULL
X#include <stdio.h>
X#endif
Xalready(p)
Xchar *p;
X{
X int i;
X extern char *user[];
X i=0;
X /*printf("in already, looking for ...%s...",p);*/
X while(user[i]!=NULL){
X if(strcmp(p,user[i])==0){/*printf("found at %d...",i);*/
X return 1;}
X i++;
X }
X /*printf("not found, i=%d...",i);*/
X return 0;
X}
End
echo ecpw.c 1>&2
sed -e 's/^X//' >ecpw.c <<'End'
X
Xchar salts[63]= /*must be 63 to leave room for the null*/
X"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
X/*1234567890123456789012345678901234567890123456789012345678901*/
X/*0000000001111111111222222222233333333334444444444555555555566*/
X/* don't use / or . because one manual says one thing, and the other
X manual says another thing. stick with letters and digits for salt.
X*/
X
Xecpw(pwd)
Xchar *pwd;
X{
X /*side effect: modifies ecptex*/
X extern char ecptex[];
X void extern exit();
X char *result,*crypt();
X char salt[3];
X salt[0]=salts[rand()%62];
X salt[1]=salts[rand()%62];
X salt[2]='\0';
X
X result=crypt(pwd,salt);
X (void) strcpy(ecptex,result);
X}
End
echo exists.c 1>&2
sed -e 's/^X//' >exists.c <<'End'
X
X#ifndef ENOENT
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X#endif
Xexists(filename)
Xchar *filename;
X{
X extern int errno;
X struct stat buf;
X if(stat(filename,&buf)== -1 && errno==ENOENT)return 0;
X return 1;
X}
End
echo initfiles.c 1>&2
sed -e 's/^X//' >initfiles.c <<'End'
X#include "autoadd.h"
Xinitfiles()
X{
X extern int euid;
X extern char passwd[], proffile[];
X if(euid==ROOT){
X strcpy(passwd,"/etc/passwd");
X strcpy(proffile,"/etc/accesstab");}
X else{
X strcpy(passwd,"passwd");
X strcpy(proffile,"accesstab");}
X}
End
echo kindex.c 1>&2
sed -e 's/^X//' >kindex.c <<'End'
Xkindex(s,t)
Xchar s[],t[];
X{
X extern void exit();
X/* slightly beefed up version of "index" from the middle
Xof p. 67 K&R */
X int c,i,j,k;
X c=s[0];
X if(c==0){i=puts("in kindex ... dummy, s[0] is zero");j=i;
X puts(t);
X if(i==j)exit(1);}
X c=t[0];
X if(c==0){i=puts("in kindex ... dummy, t[0] is zero");j=i;
X puts(s);
X if(j==i)exit(1);}
X for(i=0;s[i] !='\0'; i++){
X for(j=i,k=0;t[k] !='\0' && s[j]==t[k];j++,k++)
X ;
X if(t[k]=='\0')return (i);
X }
X return(-1);
X}
X
End
echo main.c 1>&2
sed -e 's/^X//' >main.c <<'End'
X#define MAIN
X#include "autoadd.h"
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X char systemline[100],profilename[100],directory[100],shellname[100];
X char answer[9];
X int i,j,k,how,nextu,unum,maxunum,groupnumber,firstalias,cshell;
X extern int geteuid();
X FILE *fp1,*fp2,*fp3,*fp4,*fopen();
X long time();
X void srand(); /*to make lint shut up*/
X
X/*some executable initializations:*/
X euid=geteuid(); /*should be first executable stmt*/
X initfiles(); /*executably set sensitive filenames*/
X strcpy(groupname,GROUP); /*100 our default group*/
X strcpy(diskname,DISK); /* /usr our default disk*/
X strcpy(shellname,SHELL);
X strcpy(aliasname,ALIAS);
X strcpy(firstprog,FIRSTPROG);
X strcpy(profname,PROFESSOR);
X strcpy(passwordname,PASSWD);
X strcpy(dislist,DISLIST);
X firstalias=cshell=0;
X for(i=0;i<MAXNU;++i)user[i]=NULL;
X srand((unsigned int)time(0L));
X
X/*open the password file in read mode to see who's already there */
X fp1=fopen("/etc/passwd","r");
X if(fp1==NULL)quit("/etc/passwd");
X j=0;
X maxunum= -1;
X while(fgets(line,120,fp1)==line){
X i=kindex(line,":");
X line[i]='\0';
X k=i+1;
X while(line[k]!=':')k++;
X sscanf(&line[k+1],"%d",&unum);
X if(unum>maxunum)maxunum=unum;
X user[j]=malloc((unsigned)i+1);
X strcpy(user[j],line);
X j++;
X }
X nextu=j;
X if(fclose(fp1)<0)quit("/etc/passwd");
X/* thru reading /etc/passwd */
X if(argc>=2)
X strcpy(infile,argv[1]);
X else{
X printf("input filename:");
X scanf("%s",infile);
X }
X/* open the input file in read mode */
X fp1=fopen(infile,"r");
X if(fp1==NULL)quit(infile);
X/* open /etc/passwd in append mode */
X fp2=fopen(passwd,"a");
X if(fp2==NULL)quit(passwd);
X#ifdef ACCESS
X/* open /etc/accesstab in append mode */
X fp3=fopen(proffile,"a");
X if(fp3==NULL)quit(proffile);
X#endif
X profname[0]=null;
X/* open mailrc in append mode */
X fp4=fopen(dislist,"a");
X if(fp4==NULL)quit(dislist);
X/* process input file */
X while(fgets(line,120,fp1)==line){
X if(*line==' ' || *line=='#' || *line=='\n' || *line==null)
X continue;
X for(i=0;line[i];i++)if(line[i]<' '){
X line[i]='\0';
X break;
X }
X#ifdef ACCESS
X if((i=kindex(line,"prof:"))>=0){
X strcpy(profname,&line[i+strlen("prof:")]);
X }
X else
X#endif
X
X if((i=kindex(line,"disk:"))>=0){
X strcpy(diskname,&line[i+strlen("disk:")]);
X if(diskname[0]!='/'){
X strcpy(diskname,"/");
X strcat(diskname,&line[i+strlen("disk:")]);}
X if(euid!=ROOT){
X strcpy(parentdir,".");
X strcat(parentdir,diskname);}
X else
X strcpy(parentdir,diskname);
X if(!exists(parentdir)){
X /*if not root, don't bother asking, just do it */
X if(euid==ROOT){
X printf(
X "%s doesn't seem to exist, shall I mkdir it?(y/n): "
X ,parentdir);
X scanf("%s",answer);
X if(kindex(answer,"y")!=0)quit(parentdir);
X }
X /*else{*/
X strcpy(systemline,"mkdir ");
X strcat(systemline,parentdir);
X system(systemline);
X if(!exists(parentdir))quit(parentdir);
X /*}*/
X }
X }
X
X else if((i=kindex(line,"firstprog:"))>=0){
X strcpy(firstprog,&line[i+strlen("firstprog:")]);
X }
X else if((i=kindex(line,"alias:"))>=0){
X strcpy(aliasname,&line[i+strlen("alias:")]);
X if(aliasname[0]!='0'){
X fprintf(fp4,
X firstalias?"\nalias %s ":"alias %s ",aliasname);
X firstalias=1;
X }
X }
X
X
X else if((i=kindex(line,"group:"))>=0){
X strcpy(groupname,&line[i+strlen("group:")]);
X sscanf(groupname,"%d",&groupnumber);
X }
X
X else if((i=kindex(line,"shell:"))>=0){
X strcpy(shellname,&line[i+strlen("shell:")]);
X if(kindex(shellname,"csh")>0)cshell=1;else cshell=0;
X }
X
X else if((i=kindex(line,"passwd:"))>=0){
X strcpy(passwordname,&line[i+strlen("passwd:")]);
X }
X
X else if((i=kindex(line,"password:"))>=0){
X strcpy(passwordname,&line[i+strlen("password:")]);
X }
X else{
X if(kindex(line,":")>=0){
X printf("IGNORED:%s\n",line);continue;}
X parse();
X strcpy(username,lastname);
X how=0;
Xfor(;;){
X strcpy(directory,parentdir);
X strcat(directory,"/");
X strcat(directory,username);
X if(exists(directory) || already(username))
X {
X tryagain(how);
X username[ML]=null;
X how++;
X }
X else
X break;
X}
X strcpy(systemline,"mkdir ");
X strcat(systemline,directory);
X system(systemline);
X if(!exists(directory))quit(directory);/*failed*/
X
X
X user[nextu]=malloc((unsigned)strlen(username)+1);
X strcpy(user[nextu],username);
X nextu++;
X
X if(passwordname[0]=='0' || passwordname[0]==null)
X ecptex[0]=null;
X else if (passwordname[0] == '1')
X ecpw(username);
X else
X ecpw(passwordname);
X
X fprintf(fp2,"%s:%s:%d:%s:%s:%s/%s:%s\n"
X ,username,ecptex,++maxunum,groupname,line,
X diskname,username,shellname[0]!='0'?shellname:"");
X if(aliasname[0]!='0')
X fprintf(fp4,"\\\n%s ",username);/*for dislist*/
X
X unum=maxunum;
X#ifdef ACCESS
X if(*profname&&*profname!='0')
X fprintf(fp3,"%s:%s\n",profname,username);
X#endif
X
X strcpy(profilename,directory);
X strcat(profilename,cshell?LOGIN:PROFILE);
X if(!exists(profilename)){
X strcpy(systemline,"cp ");
X strcat(systemline,STDPROFILE /*"/etc/stdprofile "*/);
X strcat(systemline," "); /*just in case*/
X strcat(systemline,profilename);
X system(systemline);
X if(firstprog[0]!='0'){
X strcpy(systemline,"echo ");
X strcat(systemline,firstprog);
X strcat(systemline," >> ");
X strcat(systemline,profilename);
X system(systemline);
X }
X }
X if(euid==ROOT){
X /*do the chowns only if running as root (effective uid)*/
X if(chown(directory,unum,groupnumber)<0)quit(directory);
X if(chown(profilename,unum,3 /*3=="sys"*/)<0)
X quit(profilename);
X }
X
X
X }
X } /*end of file on input file */
X if(firstalias)
X fprintf(fp4,"\n");/*close out the last line of dislist*/
X return 0; /* lint */
X}
End
echo parse.c 1>&2
sed -e 's/^X//' >parse.c <<'End'
X
X
X
X#include "autoadd.h"
Xparse()
X{
X int i=0;
X int j;
X extern char lastname[],fi[],mi[],line[];
X lastname[0]=mi[0]=fi[0]='1';
X lastname[ML]=fi[1]=mi[1]=null;
X j=strlen(line);
X while(line[i]==' ' && i<j)i++;
X while(line[i] && line[i]!=' ' && i<ML && i<j)
X {lastname[i]=line[i];i++;}
X lastname[i]=lastname[ML]='\0';
X if(i>=j)return;
X while(line[i]!=' ' && i<j)i++;
X while(line[i]==' ' && i<j)i++;
X if(i>=j)return;
X fi[0]=line[i++];
X fi[1]='\0';
X if(i>=j)return;
X while(line[i]!=' ' && i<j)i++;
X while(line[i]==' ' && i<j)i++;
X if(line[i])mi[0]=line[i];
X mi[1]='\0';
X}
X
End
echo quit.c 1>&2
sed -e 's/^X//' >quit.c <<'End'
Xquit(p)
Xchar *p;
X{
X extern void exit();
X puts(
X"******* something went wrong here that I can't figure out********"
X );
X puts(p);
X puts("I'm outta here...");
X exit(1);
X}
End
echo tryagain.c 1>&2
sed -e 's/^X//' >tryagain.c <<'End'
X#include "autoadd.h"
Xtryagain(how)
X{
X extern char fi[],lastname[],mi[],username[];
X char temp[49];
Xswitch(how){
Xcase 0:
X strcpy(temp,fi);
X strcat(temp,lastname);
X break;
Xcase 1:
X strncpy(temp,lastname,ML-1);
X temp[ML-1]='\0';
X strcat(temp,fi);
X break;
Xcase 2:
X strncpy(temp,lastname,ML-2);
X temp[ML-2]='\0';
X strcat(temp,fi);
X strcat(temp,mi);
X break;
Xcase 3:
X strcpy(temp,fi);
X strcat(temp,mi);
X strcat(temp,lastname);
X break;
Xcase 4:
X strcpy(temp,fi);
X strncat(temp,lastname,ML-2);
X temp[ML-1]='\0';
X strcat(temp,mi);
X break;
Xdefault:
X sprintf(temp,"%d%s",how>4?how-4+1:how /*this 4 is dangerous*/
X ,lastname);
X break;
X}
X/* temp[ML]='\0';*/ /* let main do it!*/
X strcpy(username,temp);
X}
End