# /* * This program maintains and updates the passwd file * under the AUSAM system. The command has the following format. * * pwedit [-m] [-u] [-k] [-n] [-x] [-c] [-pstring] [-tstring] [filename] * * where -k allows keyword specifications in the input * -n causes encryption of passwords to be suspended * -x causes extraction of all files onto standard output * -m causes initial directory creation on adds * -u allows uids not in the default range to be specified * -c causes comments to appear in password entry listings * from -x option and editor temporarys... * -pstring the string is to be used as the alternate password * file name * -tstring specifies a string to be used as a template filename * that is "/usr/lib/pwetplts/string" * filename specifies a file from which entries are to be taken * for operation in non-interactive mode * * Commands which may be given are; add, delete, update, * change, look and default. * * * Graham fix 29/11/78 * octal numbers in updates are recognised by a leading * '0' and are also printed by pwedit thus. * */ #include <local-system> #include <passwd.h> #include <class.h> /* some nice little defines to make life easier */ #define PWETMPS "/tmp/" /* where tmp files are kept */ #define PWETPLTS "/usr/lib/pwe/tplts/" /* where the templates are */ #define PWEDFLTS "/usr/lib/pwe/dflts/" /* where the defaults are */ #define PWETDFLT "default" /* the default name */ #define SSIZE 100 /* name string lengths */ /* some handles on difficult to hold things */ struct { unsigned hiword; unsigned loword; }; struct { char lobyte; char hibyte; }; /* now the global data */ /* flags */ int tflag, nflag, xflag, cflag, fflag, mflag, uflag; int sigstop; int status; /* status used for waits */ int owuid; /* the caller's uid */ /* filename arrays */ char tname[SSIZE], dname[SSIZE], ename[SSIZE], fname[SSIZE]; /* temp file templates for editor */ char *edtemp "pweaXXXXX"; /* the global last character */ char nextc; char c; /* global passwd entry */ struct pwent pe; /* global default entry */ struct pwent de; /* putc and getc buffers */ struct iobuf { int fildes; int count; char *cnext; char buff[512]; } sibuf; struct iobuf sobuf { 1, 0, 0, 512*0 }; struct iobuf *ibuf, *obuf; /* some definitions */ #define ITEMKEY 1 /* a keyword item */ #define ITEMNUM 2 /* a number item, may be byte,int or long */ #define ITEMSTR 3 /* string item */ #define ITEMBIT 4 /* a bit string */ #define ITEMNL 5 /* an empty line */ #define ITEMTERM 6 /* a terminal group spec in {}'s */ /* definition of ITEMKEY command codes for internal use */ #define ADDCOM 0 /* add command */ #define DELCOM 1 /* delete command */ #define CHNGCOM 2 /* change command */ #define UPDTCOM 3 /* update command */ #define LOOKCOM 4 /* lookat command */ /* string to code matching */ char *commands[] { "add", /* ADDCOM */ "delete", /* DELCOM */ "change", /* CHNGCOM */ "update", /* UPDTCOM */ "look", /* LOOKCOM */ 0 }; /* some handles to hang on to things by */ long pnum; /* the global read number */ int pcom; /* type of command, +ve if known, -ve if not */ int scom; /* a place to keep it safe */ int pclass[CMASKSIZE]; /* the present read class mask bits string */ char *pstr; /* the global read string */ main(argc, argv) int argc; char *argv[]; { extern catsig(); register int i; /* initialise io */ ibuf = &sibuf; obuf = &sobuf; #ifdef DEBUG printf("main\n"); fflush(obuf); #endif DEBUG owuid = getuid(); /* get args and stuff */ getargs(argc, argv); /* initialise defaults etc */ initialise(); /* * now have serveral possibilities. * extraction mode, file input mode, or interaction. */ if(xflag) xtract(); else { /* initialise nasty signals */ for(i = 1; i < 4; i++) signal(i, 1); for(i = 14; i <= 16; i++) signal(i, catsig); if(fflag) readfile(); else interact(); } } getargs(ac, av) int ac; char **av; { /* things with a '-' are flags, without is a filename */ #ifdef DEBUG printf("getargs\n"); fflush(obuf); #endif DEBUG while(--ac) { if(**++av == '-') { switch(av[0][1]) { case 't': settname(*av+2); tflag++; break; case 'p': setpname(*av+2); break; case 'm': mflag++; break; case 'u': uflag++; break; case 'n': nflag++; break; case 'x': xflag++; break; case 'c': cflag++; break; default: error(1, *av); break; } } else { setfname(*av); fflag++; } } #ifdef DEBUG printf("tflag=%d,nflag=%d,xflag=%d\n", tflag, nflag, xflag); fflush(obuf); printf("tname->%s<-,dname->%s<-,fname->%s<-\n", tname, dname, fname); fflush(obuf); #endif DEBUG } initialise() { /* * set default file names if necessary, open template and default files * and initialise default pwent. */ #ifdef DEBUG printf("initialise\n"); fflush(obuf); #endif DEBUG if(!tflag) { strcpy(tname, PWETPLTS); strcat(tname, PWETDFLT); strcpy(dname, PWEDFLTS); strcat(dname, PWETDFLT); } getdefault(); } settname(s) char *s; { /* make up the filenames for templates and defaults */ #ifdef DEBUG printf("settname\n"); fflush(obuf); #endif DEBUG strcpy(tname, PWETPLTS); strcat(tname, s); strcpy(dname, PWEDFLTS); strcat(dname, s); } setpname(s) char *s; { /* set the default password file name */ #ifdef DEBUG printf("setpname\n"); fflush(obuf); #endif DEBUG pwfile(s); } setfname(s) char *s; { /* set input file name */ #ifdef DEBUG printf("setfname\n"); fflush(obuf); #endif DEBUG strcpy(fname, s); } xtract() { /* explode whole passwd file onto SO with adds for each entry */ register struct iobuf *rsbuf; register int i; #ifdef DEBUG printf("xtract\n"); fflush(obuf); #endif DEBUG /* save old output */ rsbuf = obuf; fflush(obuf); obuf = &sobuf; /* output */ for(i = 0; i < PWTABSIZE; i++) { pe.pw_uid = i; if(getpwlog(&pe, 0, 0) < 0) continue; /* real entry, output it */ if(getpw(0, &pe) < 0) continue; putpe("add", &pe, 1); } /* restore old SO */ fflush(obuf); obuf = rsbuf; } interact() { /* * it interacts with the cretins */ register int ri, rf; struct iobuf *ribuf, *robuf; char cc; #ifdef DEBUG printf("interact\n"); fflush(obuf); #endif DEBUG while(1) { /* major loop */ if(sigstop) break; rf = 0; if( owuid == 0) { do { putchar('>'); fflush(obuf); } while(((ri = getitem()) != ITEMKEY) && (ri != 0)); if(ri == 0) break; scom = pcom; } else scom = LOOKCOM; if(scom != ADDCOM) { /* only need uid and lname if not an add command */ printf("lname: "); fflush(obuf); if((ri = getitem()) == 0) break; if(ri == ITEMSTR) { pe.pw_strings[LNAME] = pstr; rf =| 02; } if( rf == 0 || scom == DELCOM) { printf("uid: "); fflush(obuf); if((ri = getitem()) == 0) break; if(ri == ITEMNUM) { /* got a number, not just nothing */ if(!bcheck(2)) { error(15, 0); continue; } pe.pw_uid = pnum.loword; rf =| 01; } } } /* now have command and other data, just use it */ if(scom == DELCOM) { /* delete command, must have both uid and lname */ if((rf&03) != 03) { error(17, 0); } else { if(delpwent(&pe) < 1) error(9, 0); } } else { /* for add command or flags 01|02 must go on */ if((scom == ADDCOM) || (rf&03)) { fflush(obuf); robuf = obuf; strcpy(ename, PWETMPS); strcat(ename, edtemp); mktemp(ename); obuf = copen(ename, 0600); if(scom == ADDCOM) { /* for an add must copy over template */ ribuf = ibuf; ibuf = copen(tname, 0); while((cc = getc(ibuf)) != -1) putc(cc, obuf); cclose(ibuf); ibuf = ribuf; } else { /* must be change or update */ if(rf&01) { if(getpw(0, &pe) < 0) rf =| 04; } else { if(getpw(1, &pe) < 0) rf =| 04; } /* free up the interactive login name */ if(!(rf&04)) putpe(commands[scom], &pe, 1); } /* finished with obuf */ fflush(obuf); cclose(obuf); obuf = robuf; if(!(rf&04)) { /* return input absorbed into buffer */ seek(ibuf->fildes, -(ibuf->count), 1); ibuf->count = 0; /* now spawn an elfic ed */ if(fork()) { /* parent */ wait(&status); } else { /* child */ if(execl("/bin/em", "pwede", "-e", ename, 0) < 0) { error(16, 0); } } /* now have returned so validate results */ if(scom != LOOKCOM) { ribuf = ibuf; ibuf = copen(ename, 0); if(getpe(&pe) < 0) { error(5, 1); rf =| 04; } else if(putpw(&pe) < 0) error(6, 1); cclose(ibuf); ibuf = ribuf; } } unlink(ename); } } } } putpe(rs, rpe, ff) register char *rs; register struct pwent *rpe; int ff; { /* * Output the pwent struct at *rpe with the string at *rs as the * first line of output. Uses printf calling putchar calling putc * an ff of 1 causes freeing of string area after output */ register int i; #ifdef DEBUG printf("putpe\n"); fflush(obuf); #endif DEBUG /* command out */ printf("%s\n", rs); /* now all other entries */ if(cflag) { printf("%d /* uid */\n", rpe->pw_uid); } else { printf("%d\n", rpe->pw_uid); } if(cflag) { printf("%d /* shares */\n", rpe->pw_shares); } else { printf("%d\n", rpe->pw_shares); } if(cflag) { printf("%ld /* usage */\n", rpe->pw_usage); } else { printf("%ld\n", rpe->pw_usage); } printclass(rpe); printterms(rpe); if(cflag) { printf("0%o /* flags */\n", rpe->pw_flags); /* Graham fix */ } else { printf("0%o\n", rpe->pw_flags); /* Graham fix */ } if(cflag) { printf("%d /* dlimit */\n", rpe->pw_dlimit); } else { printf("%d\n", rpe->pw_dlimit); } if(cflag) { printf("%d /* doverflw */\n", rpe->pw_doverflw); } else { printf("%d\n", rpe->pw_doverflw); } if(cflag) { printf("%d /* plimit */\n", rpe->pw_plimit); } else { printf("%d\n", rpe->pw_plimit); } if(cflag) { printf("%d /* climit */\n", rpe->pw_climit); } else { printf("%d\n", rpe->pw_climit); } if(rpe->pw_pword[0] == 0) printf("\"\"\n"); else { printf("\"%c%c%c%c%c%c%c%c\"\n", rpe->pw_pword[0], rpe->pw_pword[1], rpe->pw_pword[2], rpe->pw_pword[3], rpe->pw_pword[4], rpe->pw_pword[5], rpe->pw_pword[6], rpe->pw_pword[7]); } if(cflag) { printf("%ld /* contime */\n", rpe->pw_contime); } else { printf("%ld\n", rpe->pw_contime); } if(cflag) { printf("%ld /* cputime */\n", rpe->pw_cputime); } else { printf("%ld\n", rpe->pw_cputime); } if(cflag) { printf("%ld /* extime */\n", rpe->pw_extime); } else { printf("%ld\n", rpe->pw_extime); } if(cflag) { printf("%d /* warn */\n", rpe->pw_warn); } else { printf("%d\n", rpe->pw_warn); } if(cflag) { printf("%d /* pages */\n", rpe->pw_pages); } else { printf("%d\n", rpe->pw_pages); } #ifdef TERMBOOK if(cflag) { printf("%d /* tblim */\n", rpe->pw_tblim & 0377); } else { printf("%d\n", rpe->pw_tblim & 0377); } if(cflag) { printf("%d /* tbrate */\n", rpe->pw_tbrate); } else { printf("%d\n", rpe->pw_tbrate); } #endif TERMBOOK for(i = 0; i < PWSLENCNT; i++) if(rpe->pw_strings[i] != 0) { printf("\"%s\"\n", rpe->pw_strings[i]); } else { error(2, i); } if(ff) { free(rpe->pw_strings[0]); for(i = 0; i < PWSLENCNT; i++) rpe->pw_strings[i] = 0; } } getpw(ct, rpe) int ct; register struct pwent *rpe; { /* * using call type, ct, gets an entry into *rpe. cts are: * 0 by uid * 1 by login name */ register int rsum, ri; char *as, *ss; #ifdef DEBUG printf("getpw\n"); fflush(obuf); #endif DEBUG /* first determine the string sizes */ ss = rpe->pw_strings[0]; switch(ct) { case 0: /* by uid */ if(getpwlog(rpe, 0, 0) < 0) { error(12, 0); return(-1); } break; case 1: /* by login name */ if(getpwuid(rpe, 0, 0) < 0) { error(13, 0); return(-1); } break; } for(ri = 0, rsum = 0; ri < PWSLENCNT; ri++) { rsum =+ rpe->pw_strings[ri]; } if((as = alloc(rsum)) < 0) { error(14, 0); return(-1); } switch(ct) { case 0: /* by uid we get it */ if(getpwlog(rpe, as, rsum) != rsum) { error(12, 0); return(-1); } break; case 1: /* by login name */ rpe->pw_strings[0] = ss; if(getpwuid(rpe, as, rsum) != rsum) { error(13, 0); return(-1); } break; } } putpw(rpe) register struct pwent *rep; { /* * add change or update a passwd file entry using the stuff in *rep */ register int ri; #ifdef DEBUG printf("putpw\n"); fflush(obuf); #endif DEBUG switch(scom) { case 0: /* add */ /* enforce the bounds limits for this site */ if(!uflag) rpe->pw_uid = UIDLB; if(addpwent(rpe) < 0) error(8, rpe->pw_strings[LNAME]); else /* make directories etc if needed */ if(mflag) mkit(); break; case 2: /* change */ if(chngpwent(rpe) < 0) error(10, 0); break; case 3: /* update */ if(updtpwent(rpe) < 0) error(11, 0); break; } for(ri = 0; ri < PWSLENCNT; ri++) { free(rpe->pw_strings[ri]); rpe->pw_strings[ri] = 0; } } struct iobuf *copen(s, m) char *s; int m; { /* * open (or if m>0 creat) a file with name "*s" and make * associated buffer area for getc and putc. */ register int rfd; register struct iobuf *rsbuf; #ifdef DEBUG printf("copen of %s\n", s); fflush(obuf); #endif DEBUG if(m > 0) { /* creat the file */ if((rfd = creat(s, m)) < 0) { error(3, s); } } else { /* open only */ if((rfd = open(s, 0)) < 0) { error(0, s); } } if((rsbuf = alloc(sizeof sobuf)) < 0) error(4, s); rsbuf->fildes = rfd; rsbuf->count = 0; rsbuf->cnext = 0; return(rsbuf); } readfile() { /* * opens file called "*fname" and decodes input to form * new and modified passwd entries. Sets up input buffers also. */ register struct iobuf *rsbuf; register int ri, rn; /* save old input buffer */ #ifdef DEBUG printf("readfile\n"); fflush(obuf); #endif DEBUG rsbuf = ibuf; /* open and use the new stuff */ ibuf = copen(fname, 0); rn = 0; while(++rn) { if(sigstop) break; if((ri = getpe(&pe)) < 0) { error(5, rn); break; } if(putpw(&pe) < 0) error(6, rn); if(ri == 0) break; } /* flush and restore to exit */ fflush(obuf); cclose(ibuf); ibuf = rsbuf; } getdefault() { /* * open files etc and read defaults into "&de". * Note that defaults of zero force entries to be requested for them */ register struct iobuf *rsbuf; #ifdef DEBUG printf("getdefault\n"); fflush(obuf); #endif DEBUG rsbuf = ibuf; ibuf = copen(dname, 0); if(getpe(&de) < 0) error(5, 0); cclose(ibuf); ibuf = rsbuf; } getpe(rpe) register struct pwent *rpe; { /* * reads and validates the entry from "ibuf" into "*rpe". */ register char *rpw; register int rn; #ifdef DEBUG printf("getpe\n"); fflush(obuf); #endif DEBUG /* get command */ if(getitem() != ITEMKEY) return(-1); if((scom = pcom) < 0) return(-1); /* get uid */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(2)) return(-1); rpe->pw_uid = pnum.loword; /* get shares */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(2)) return(-1); rpe->pw_shares = pnum.loword; /* get usage */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(4)) return(-1); rpe->pw_usage = pnum; /* read class mask bit string */ if(getitem() != ITEMBIT) return(-1); for(rn = 0; rn < CMASKSIZE; rn++) rpe->pw_cmask[rn] = pclass[rn]; /* read terminal groups string */ if(getitem() != ITEMTERM) return(-1); rpe->pw_tmask = pnum.loword; /* get flags */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(2)) return(-1); rpe->pw_flags = pnum.loword; /* get dlimit */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(2)) return(-1); rpe->pw_dlimit = pnum.loword; /* get doverflw */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(2)) return(-1); rpe->pw_doverflw = pnum.loword; /* get plimit */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(1)) return(-1); rpe->pw_plimit = pnum.loword.lobyte; /* get climit */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(1)) return(-1); rpe->pw_climit = pnum.loword.lobyte; /* get passwd */ if(getitem() != ITEMSTR) return(-1); if(*pstr == 0) { /* null passwd */ for(rn = 0; rn < 8; rn++) rpe->pw_pword[rn] = 0; } else if((scom != ADDCOM) || (nflag)) { /* no encryption */ for(rn = 0; rn < 8; rn++) rpe->pw_pword[rn] = pstr[rn]; } else { /* encrypt */ rpw = crypt(pstr); for(rn = 0; rn < 8; rn++) rpe->pw_pword[rn] = rpw[rn]; } /* get contime */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(4)) return(-1); rpe->pw_contime = pnum; /* get cputime */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(4)) return(-1); rpe->pw_cputime = pnum; /* get extime */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(4)) return(-1); rpe->pw_extime = pnum; /* get warn */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(1)) return(-1); rpe->pw_warn = pnum.loword.lobyte; /* get pages */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(1)) return(-1); rpe->pw_pages = pnum.loword.lobyte; #ifdef TERMBOOK /* get tblim */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(1)) return(-1); rpe->pw_tblim = pnum.loword.lobyte; /* get tbrate */ if(getitem() != ITEMNUM) return(-1); if(!bcheck(1)) return(-1); rpe->pw_tbrate = pnum.loword.lobyte; #endif TERMBOOK /* finally get strings */ for(rn = 0; rn < PWSLENCNT; rn++) { if(getitem() != ITEMSTR) return(-1); if(rpe->pw_strings[rn] != 0) { free(rpe->pw_strings[rn]); } rpe->pw_strings[rn] = pstr; pstr = 0; } } getitem() { /* * returns a number corresponding to the type of item read. * return values are define previously. Returns the negative of the * normal return for an error item. Returns 0 for eof. */ register int finished; register int rv; register int ri; #ifdef DEBUG printf("getitem\n"); fflush(obuf); #endif DEBUG finished = 0; c = getc(ibuf); while(!finished) { if(c == -1) return(0); if((c <= 'z') && (c >= 'a')) { /* a keyword */ rv = ITEMKEY; nextc = c; pstr = getstring(pstr, 0); for(ri = 0; (strcmp(commands[ri], pstr) != 0); ri++) { if(commands[ri] == '\0') { ri = -1; break; } } pcom = ri; finished = 1; } else if((c <= '9') && (c >= '0')) { /* a number of some form */ rv = ITEMNUM; if(c == '0') /* Graham fix,we're not interested in null's! */ { if(getnum(8) < 0) rv =* -1; } else { if(getnum(10) < 0) rv =* -1; } finished = 1; } else switch(c) { case '"': /* a string */ rv = ITEMSTR; pstr = getstring(pstr, 1); finished = 1; break; case '/': /* a comment */ flushline(); break; case '`': /* a bit string */ rv = ITEMBIT; if(getclass() < 0) rv =* -1; finished = 1; break; case '{': /* a terminal group spec */ rv = ITEMTERM; if(getterms() < 0) rv = -rv; finished = 1; break; case '\n': /* a null line */ rv = ITEMNL; finished = 1; break; default: /* read another char and do again */ c = getc(ibuf); break; } } flushline(); return(rv); } getnum(rbase) register int rbase; { /* * get a number terminated by a blank in base rbase */ char cc; #ifdef DEBUG printf("getnum\n"); fflush(obuf); #endif DEBUG pnum = 0; while(((cc = c-'0') >= 0) && (cc < rbase)) { pnum = (pnum*rbase)+cc; c = getc(ibuf); } return(0); } printclass(rpe) register struct pwent *rpe; { /* * prints the bitwise representation of the pw_cmask */ register int rn, ri; #ifdef DEBUG printf("printclass\n"); fflush(obuf); #endif DEBUG putc('`', obuf); for(rn = 0; rn < CMASKSIZE; rn++) { /* int by int */ for(ri = 0; ri < 16; ri++) { /* bit by bit */ if(((rpe->pw_cmask[rn]<<ri)&0100000) == 0) putc('0', obuf); else putc('1', obuf); } } putc('`', obuf); putc('\n', obuf); } printterms(rpe) register struct pwent *rpe; { /* * prints the groupwise representation of pw_tmask */ register rn, ri; #ifdef DEBUG printf("printterms\n"); fflush(obuf); #endif DEBUG rn = rpe->pw_tmask; putc('{', obuf); for(ri = 0; ri < 16; ri++) { if(rn&01) { putc('a'+ri, obuf); } rn =>> 1; } putc('}', obuf); putc('\n', obuf); } getclass() { /* read class mask into pclass */ register int ri, rn; #ifdef DEBUG printf("getclass\n"); fflush(obuf); #endif DEBUG for(rn = 0; rn < CMASKSIZE; rn++) pclass[rn] = 0; for(rn = 0; rn < CMASKSIZE; rn++) { for(ri = 16; --ri >= 0; ) { c = getc(ibuf); if((c == '0') || (c == '1')) { if(c == '0') pclass[rn] =& ~(1<<ri); else pclass[rn] =| (1<<ri); } else return(-1); } } return(0); } getterms() { /* * return terminal mask in pnum.loword */ register rc, ri; #ifdef DEBUG printf("getterms\n"); fflush(obuf); #endif DEBUG ri = 0; while((rc = getc(ibuf)) != -1 && rc != '\n') { if(rc == '}') { pnum.loword = ri; return 0; } if(rc >= 'a' && rc <= 'p') /* only valid groups so far */ { ri = ri^(1<<(rc-'a')); } else if(rc == '!') ri = ~ri; else return -1; } return -1; } flushline() { /* flushes ibuf until a '\n' or eof are reached */ #ifdef DEBUG printf("flushline\n"); fflush(obuf); #endif DEBUG while((c != '\n') && (c != -1)) { c = getc(ibuf); } } bcheck(ri) register int ri; { /* * checks to see if the global long pnum has a number small enough * to fit in "ri" bytes. */ #ifdef DEBUG printf("bcheck\n"); fflush(obuf); #endif DEBUG return(1); } cclose(rsbuf) register struct iobuf *rsbuf; { /* * close the file * and free the buffer area */ #ifdef DEBUG printf("cclose\n"); fflush(obuf); #endif DEBUG close(rsbuf->fildes); free(rsbuf); } char readc(tm) int tm; { /* * reads characters from the ibuf file one by one. * returns characters, '\0' for EOF or end of string * specified by value of tm. */ #ifdef DEBUG printf("readc\n"); fflush(obuf); #endif DEBUG if(nextc) { c = nextc; nextc = 0; } else c = getc(ibuf); if(c == '\\') { c = getc(ibuf); return(c); } if(c == -1) return('\0'); if(tm) { /* terminate with '"' */ if(c == '"') return('\0'); } else { /* terminate with ' ' or '\n' */ if((c == ' ') || (c == '\n')) return('\0'); } return(c); } char *getstring(ptr, tm) char *ptr; int tm; { /* * read a string from the input source specified by present ibuf. * free the area pointed to by ptr (if non-zero). return a pointer * to a newly alloced string. * tm specifies the termination method, as in 1 for a """ terminator * and 0 for normal ones like " ", "\n" etc */ register char *string; register s, slen, finished; #ifdef DEBUG printf("getstring\n"); fflush(obuf); #endif DEBUG s = 0; finished = 0; if(ptr) { free(ptr); ptr = 0; } string = alloc(slen = SSIZE); while(!finished) { while(s < slen) { if((string[s++] = readc(tm)) <= 0) { finished = 1; break; } } if(finished) string = expand(string, s, slen); else string = expand(string, slen, slen =+ SSIZE); } return(string); } char *expand(old, initial, final) register char *old; { /* * modifies size of area pointed to by "old" from "initial" to "final" * and returns "new" pointer */ register char *new; register int i; #ifdef DEBUG printf("expand\n"); fflush(obuf); #endif DEBUG new = alloc(final); for(i = 0; i < initial; i++) { new[i] = old[i]; } free(old); return(new); } error(ri, rp) register int ri; register unsigned *rp; { /* error output and actions */ register struct iobuf *rsbuf; rsbuf = obuf; obuf = &sobuf; printf("pwedit: "); switch(ri) { case 0: printf("cannot open file %s\n", rp); fflush(obuf); exit(0); break; case 1: printf("unknown argument %s\n", rp); break; case 2: printf("not used at present\n"); fflush(obuf); exit(0); break; case 3: printf("cannot creat file %s\n", rp); fflush(obuf); exit(0); break; case 4: printf("cannot alloc buffer area for file %s\n", rp); fflush(obuf); exit(0); break; case 5: printf("error in input file at item %d\n", rp); break; case 6: printf("error writing passwd file at item %d\n", rp); fflush(obuf); exit(0); break; case 7: printf("invalid character is %c\n", *rp); fflush(obuf); exit(0); break; case 8: printf("passwd add error login name %s\n", rp); break; case 9: printf("passwd delete error\n"); break; case 10: printf("passwd change error\n"); break; case 11: printf("passwd update error\n"); break; case 12: printf("passwd getpwlog error\n"); break; case 13: printf("passwd getpwuid error\n"); break; case 14: printf("cannot alloc string area\n"); fflush(obuf); exit(0); break; case 15: printf("uid too large\n"); break; case 16: printf("editor execl failed\n"); fflush(obuf); exit(0); break; case 17: printf("not enough data for interactive action requested\n"); break; case 18: printf("cannot fork mkdir\n"); break; case 19: printf("cannot exec mkdir for %s\n", rp); fflush(obuf); exit(0); case 20: printf("mkdir failed for %s\n", rp); break; case 21: printf("chown failed for %s\n", rp); break; default: printf("spurious error call\n"); fflush(obuf); exit(0); break; } fflush(obuf); obuf = rsbuf; } putchar(ac) char ac; { putc(ac, obuf); } catsig() { register int i; for(i = 14; i <= 16; i++) signal(i, 1); sigstop++; } mkit() { register int cpid; if(cpid = fork()) { /* parent */ if(cpid == -1) { error(18, 0); } else { wait(&status); if(status&0177400) error(20, pe.pw_strings[DIRPATH]); else { if(chown(pe.pw_strings[DIRPATH], pe.pw_uid) < 0) error(21, pe.pw_strings[DIRPATH]); } } } else { /* child */ execl("/bin/mkdir", "mkdir", pe.pw_strings[DIRPATH], 0); error(19, 1); } }