USG_PG3/usr/source/sccscmds/admin.c
#include "../sccshead/sfile.h"
#include "../sccshead/statbuf.h"
#include "../sccshead/sint.h"
# include "../sccshead/had.h"
int num_files;
char had[26];
# define MINR 1
# define MAXR 9999
# define DESCSIZE 100
# define PERSONSIZE 14
# define TYPESIZE 10
char admin_____[] "~|^`admin.c: 3.6";
int irel, ceil, floor, numlocks, numulocks, rdef, fexists, didargs;
int lock[5], unlock[5];
char *desc, *person, *type, *ifile;
/* aulist is the list of users to be added to Hulist,
* eulist is the list of users to be erased from Hulist.
*/
char aulist[32]; /* initialized to zero */
char eulist[32] { 0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
0377, 0377, 0377, 0377, 0377, 0377, 0377, 0377,
};
struct Ibufr pbuf;
main(argc,argv)
int argc;
char *argv[];
{
register int j;
register char *p;
char c;
int testmore, testklt;
int i;
int uid, mask, k;
extern admin();
opnl(&pbuf,"/etc/passwd");
testklt = 1;
for(j=1; j<argc; j++)
if(argv[j][0] == '-' && (c=argv[j][1])) {
p = &argv[j][2];
testmore = 0;
switch (c) {
case 'd':
desc = p;
if (size(desc) > DESCSIZE)
fatal("description too large (471)");
break;
case 'p':
person = p;
if (size(person) > PERSONSIZE)
fatal("person too large (472)");
break;
case 't':
type = p;
if (size(type) > TYPESIZE)
fatal("type too large (473)");
break;
case 'i':
ifile = p;
break;
case 'r':
if ((irel = patoi(p)) == -1)
fatal("bad r argument (454)");
if ((irel < MINR) || (irel > MAXR))
fatal("bad r argument (455)");
break;
case 'c':
if ((ceil = patoi(p)) == -1)
fatal("bad ceiling (450)");
if ((ceil < MINR) || (ceil > MAXR))
fatal("bad ceiling (451)");
break;
case 'f':
if ((floor = patoi(p)) == -1)
fatal("bad floor (452)");
if ((floor < MINR) || (floor > MAXR))
fatal("bad floor (453)");
break;
case 'l':
testklt = 0;
if (numlocks >= 5)
fatal("too many locks (456)");
if ((i = patoi(p)) == -1)
fatal("bad lock (457)");
if ((i < MINR) || (i > MAXR))
fatal ("bad lock (458)");
chkr(i);
lock[numlocks++] = i;
break;
case 'u':
testklt = 0;
if (numulocks >= 5)
fatal("too many unlocks (459)");
if ((i = patoi(p)) == -1)
fatal("bad unlock (460)");
if ((i < MINR) || (i > MAXR))
fatal("bad unlock (461)");
chkr(i);
unlock[numulocks++] = i;
break;
case 'a':
testklt = 0;
uid = getluid(p);
mask = 1;
for (k=uid&7; k; k--) mask =<< 1;
aulist[uid>>3] =| mask;
break;
case 'e':
testklt = 0;
if ((uid = patoi(p))== -1) uid = getluid(p);
mask = 1;
for (k=uid&7; k; k--) mask =<< 1;
eulist[uid>>3] =& ~mask;
break;
case 'y':
if ((rdef = patoi(p)) == -1)
fatal("bad y argument (462)");
if ((rdef<MINR || rdef>MAXR) && rdef!=0)
fatal("bad y argument (463)");
break;
case 'z':
case 'n':
testmore++;
break;
default:
fatal("unknown key letter (69)");
}
if (testmore) {
testmore = 0;
if (*p)
fatal(stringf(
"value after %c arg (232)",c));
}
if (had[c - 'a']++ && testklt++)
fatal("key letter twice (464)");
argv[j] = 0;
}
else num_files++;
if(num_files == 0)
fatal("missing file arg (49)");
setsig(fatal,fatal,fatal);
for (j=1; j<argc; j++)
if (p=argv[j])
do_file(p,admin);
exit(0);
}
/* `Main' routine.
* Note that keyletter args are only processed once.
*/
admin(afile)
char *afile;
{
register struct Header *hdr;
register int i, k;
int fd, rel, ohash, nhash;
int chkunlk[5];
char *cp;
struct Reltab rt;
struct Deltab dt;
struct Control ctl;
struct Ibufr ibuf;
struct Obufr obuf;
struct Header ahdr;
extern char *fatal_file;
extern nfiles;
hdr = &ahdr;
if (!same(sname(afile),"s.",2))
fatal("not an SCCS file (301)");
fexists = exists(afile);
if (HADI && nfiles > 0)
fatal("more than one file (465)");
if (HADI) HADN = 1;
if (HADN && fexists)
fatal("file exists (466)");
if (!HADN && !fexists)
fatal("file does not exist (467)");
if (fexists) {
chmod(afile,fexists|(IREAD|IWRITE));
fd = xopen(afile,2);
chmod(afile,fexists);
seek(fd,2,0);
if (read(fd,hdr,sizeof(*hdr))!=sizeof(*hdr))
fatal("read error (468)");
ohash = hash(hdr,&hdr->Hash);
if (hdr->Hash==0) HADZ = 1;
}
else {
crtr(&obuf,afile,0444);
hdr->Hmagicno = MAGICNO;
}
if (HADD) copy(desc,hdr->Hdesc);
if (HADP) copy(person,hdr->Hpers);
if (HADT) copy(type,hdr->Htype);
if (HADC) hdr->Hceil = ceil;
if (HADF) hdr->Hfloor = floor;
if (HADU) {
for (k=0; k<numulocks; k++) {
chkunlk[k] = unlock[k];
for (i=0; i<5; i++)
if (hdr->Hsw[i]==unlock[k])
hdr->Hsw[i] = chkunlk[k] = 0;
}
for (k=0; k<numulocks; k++) if (chkunlk[k])
msg2(stringf("[%s]: Release %d wasn't locked (469)\n",
fatal_file,chkunlk[k]));
for (k=0; k<5; k++)
if (hdr->Hsw[k]==0)
for (i=k+1; i<5; i++)
if (hdr->Hsw[k] = hdr->Hsw[i]) {
hdr->Hsw[i] = 0;
break;
}
}
if (HADL) {
for (k=0; k<5; k++)
if (hdr->Hsw[k]==0) break;
for (i=0; i<numlocks; i++) {
if (k==5)
fatal("too many locks (470)");
hdr->Hsw[k++] = lock[i];
}
}
if (HADA)
for (i=0; i<32; i++) hdr->Hulist[i] =| aulist[i];
if (HADE)
for (i=0; i<32; i++) hdr->Hulist[i] =& eulist[i];
if (HADY) hdr->Hrdef = rdef;
if (fexists) {
nhash = hash(hdr,&hdr->Hash);
hdr->Hash =+ nhash-ohash;
if (HADZ) hdr->Hash = 0;
seek(fd,2,0);
if (write(fd,hdr,sizeof(*hdr))!=sizeof(*hdr))
fatal("write error (474)");
close(fd);
return;
}
/* Thie following is really a large else clause
* to complement the `if (fexists)' above.
* I.e., we get here if the file did not exist.
*/
putr(&obuf,hdr,sizeof(*hdr));
if (HADI) {
if (HADR) rel = rt.Rrel = irel;
else rel = rt.Rrel = 1;
rt.Rlevs = 1;
putr(&obuf,&rt,sizeof(rt));
}
rt.Rrel = rt.Rlevs = 0;
putr(&obuf,&rt,sizeof(rt));
dt.Dtype = 'D';
dt.Dfill = ' ';
time(&dt.Ddatetime);
if ((cp=getlnam())==0)
fatal("Who are you? (75)");
copy(cp,dt.Dpgmr);
dt.Dhist[0] = '\0';
if (HADI) {
dt.Drel = rel;
dt.Dlev = 1;
putr(&obuf,&dt,sizeof(dt)-(sizeof(dt.Dhist)-1));
}
dt.Drel = dt.Dlev = 0;
putr(&obuf,&dt,sizeof(dt)-(sizeof(dt.Dhist)-1));
if (HADI) {
ctl.Crel = rel;
ctl.Clev = 1;
ctl.Cctl = INS;
putr(&obuf,&ctl,SIZEOFCONTROL);
if (*ifile) opnl(&ibuf,ifile);
else opnl(&ibuf,0,0);
for (k = 1; getl(&ibuf) != 1; k++) {
cp = ibuf.Irecptr;
i = ibuf.Ilen - 1;
cp[i] = 0;
if (ctlrec(cp,i))
fatal(stringf("illegal data on line %d (312)",
k));
putr(&obuf,cp,i);
}
close(ibuf.Ifildes);
ctl.Cctl = END;
putr(&obuf,&ctl,SIZEOFCONTROL);
}
ctl.Crel = ctl.Clev = 0;
ctl.Cctl = END;
putr(&obuf,&ctl,SIZEOFCONTROL);
flshr(&obuf,HADZ);
close(obuf.Ofildes);
}
/* This is really a typo check (if you type the same release
* number twice this routine catches it).
*/
chkr(r)
{
register int i;
for (i=0; i<numlocks; i++)
if (r==lock[i])
fatal(stringf("release %d twice (475)",r));
for (i=0; i<numulocks; i++)
if (r==unlock[i])
fatal(stringf("release %d twice (476)",r));
}
/* Computes the integer sum of memory in the interval [ip1,ip2).
*/
hash(ip1,ip2)
int *ip1,*ip2;
{
register int *rip, sum;
sum = 0;
for (rip=ip1; rip<ip2; rip++) sum =+ *rip;
return(sum);
}
/* Returns the numerical user ID of the argument string (s).
*/
getluid(s)
char *s;
{
register char *p;
register int i,uid;
seek(pbuf.Ifildes,0,0);
opnl(&pbuf,0,pbuf.Ifildes);
i = size(s) - 1;
while ((p=getl(&pbuf))!=1) {
if (p[i]==':') {
p[i] = '\0';
if (!equal(p,s)) continue;
for (p= &p[i+1]; *p++ !=':'; );
uid = 0;
for (; *p!=':'; p++) uid = uid*10+(*p-'0');
return(uid);
}
}
fatal(stringf("%s not in passwd file (477)",s));
}