/* * A program to examine the classes a user is in, pick the class with * the largest disc limits and install said user in said class, adjusting * said users limits in the process. * Flags are: * -w mail user of the change * -l always adjust limits * -f force adjustment of important limits (ie disc, proc) * * This program: * checks to see the user is not logged on, * works out if a change is necessary, * moves directories using ln or copy * adjust passwd entry if less than possible * warns of people who are over supposed maximum limits. * * NOTE: The password entry templates are COMPILED IN (quick but nasty) * and so new class templates must be added with care..... * * All data comes from the compiled-in templates. * * Useful for end-of-session cleanups, and giving people what they * deserve........ tee hee....... * * Peter Ivanov, June 1979. * */ /* include all the inclusions...... */ #include <wtmp.h> #include <local-system> #include <passwd.h> #include <lnode.h> #include <stdio.h> /* global data */ #define PROMPT(x) if(prompt) prints(1, x) #define LOGNAME 100 #define DIREC 100 struct data { char *da_class; struct pwent da_dpw; } data[CMASKSIZE*16] { /* the compiled-in templates */ # include <classincludes.h> }; struct pwent upw; struct pwent *dp; struct lnode lnod; char logname[LOGNAME]; char direc[DIREC]; char buf[250]; char *oldirec; int prompt, lflag, wflag, fflag; char stopf; main(argc, argv) int argc; char *argv[]; { register int eh; register int size; extern stop(); signal(2,stop); signal(3,stop); while (argc-- > 1) { if(**++argv == '-') { while(*++*argv) switch(**argv) { case 'l': lflag++; break; case 'w': wflag++; break; case 'f': fflag++; break; default: error("Usage: adjust [-lwf]\n"); } } else { error("Usage: adjust [-lwf]\n"); } } /* args are now set up */ if(ttyn(0) != 'x') prompt ++; /* prompts set up */ while (!stopf) { PROMPT("login name: "); if(gets(logname)) { upw.pw_strings[LNAME] = logname; size = getpwuid(&upw, buf, sizeof buf); if (size == sizeof buf) { error("string buffer too small\n"); } if(size > 0) { /* there is an entry */ /* see is the user is logged in, via lnode */ lnod.l_uid = upw.pw_uid; if(limits(&lnod, L_OTHLIM) < 0) { /* all ok */ if(eh = adjust()) { if((eh == 1) && (updtpwent(&upw) != 1)) error("updtpwent failed\n"); if((eh == 2) && (chngpwent(&upw) != 1)) error("chngpwent failed\n"); if(wflag) mail(); } } else { /* dont touch, cos he is logged in */ prints(1,logname); prints(1," is presently logged in\n"); } } else { /* there is no entry */ prints(1, logname); prints(1, " no such login name\n"); } } else { prints(2,"adjust: end\n"); exit(0); } } } mvit() { register int cpid; register char *c, *sl; int status; char od[DIREC], nd[DIREC]; if(cpid = fork()) { /* parent */ if(cpid == -1) { error(" cannot fork copy\n"); } /* await the completeion if mails are to be done */ if(wflag) { while(wait(&status) >= 0); } } else { /* child */ /* bloody copy chucks away empty directories if used like this...... */ /* execl("/bin/copy", "adjust.copy", "-m", "-s", "-o", "-r", oldirec, direc, 0);*/ /* use links to move the directory, as long as on same disc */ strcpy(od, oldirec); strcpy(nd, direc); strcat(od,"/.."); for(c=nd,sl=0; *c; c++) { if(*c == '/') sl=c; } /* now sl should be null or point to the '/' to be zapped */ if(sl == 0) error(" cant make new pathname/..\n"); *sl = '\0'; /* suck it and see */ if(link(oldirec,direc)<0) error(" cant relink directory\n"); /* now we know that links are possible so do em */ if(unlink(od) < 0) prints(2," cant unlink ..\n"); if(link(nd, od) < 0) prints(2,"cant link ..\n"); if(unlink(oldirec) < 0) prints(2,"cant unlink oldirec\n"); /* and that is all */ exit(0); } } error(s1) char *s1; { prints(2,"adjust: "); prints(2, s1); exit(1); } adjust() { register int i; register int j; register int firstclass; int candobetter, inaclass; /* * Set tpw structure to contain the class with largest disc limit. * If the disc limits is larger and not dlfag, warn but do not alter. * Make global "dp" a pointer to the template in core. * Return 0 for no change needed, 1 for updtpwent, 2 for chngpwent. */ firstclass = 0; inaclass = 0; candobetter = 0; for(i=0; i < (CMASKSIZE*16); i++) if((upw.pw_cmask[i/16]) & ( 0100000 >> (i%16))) { firstclass = i; inaclass++; break; } dp = &data[firstclass].da_dpw; /* now dp should point to a valid class if any */ for(i=firstclass; i< (CMASKSIZE*16); i++) { if(data[i].da_dpw.pw_cmask[i/16] & upw.pw_cmask[i/16]) if(data[i].da_dpw.pw_dlimit > dp->pw_dlimit) dp = &data[i].da_dpw; } if(dp->pw_dlimit > upw.pw_dlimit) candobetter++; /* * now dp should point to the best possible class, if any. * now have a number of possible actions: * if(dflag) force adjustment of limits * if(candobetter) adjust limits and directory * including case where (oldirec != direc) */ /* now the new directory string - and save the old one */ strcpy(direc, dp->pw_strings[DIRPATH]); oldirec = upw.pw_strings[DIRPATH]; strcat(direc, logname); upw.pw_strings[DIRPATH] = direc; /* must he be moved ?? */ if(strcmp(direc,oldirec) != 0) candobetter++; /* now he is in a class or he is not in a class */ if(inaclass) { /* adjust his limits? */ if(candobetter || lflag) { prints(2,"\n"); prints(2,logname); prints(2,": adjusting limits\n"); if(fflag) { /* force adjustment */ upw.pw_dlimit = dp->pw_dlimit; upw.pw_doverflw = dp->pw_doverflw; upw.pw_plimit = dp->pw_plimit; upw.pw_tmask = dp->pw_tmask; upw.pw_shares = dp->pw_shares; upw.pw_flags = dp->pw_flags; } else { /* check them all */ if(upw.pw_dlimit > dp->pw_dlimit) warn("dlimit"); else upw.pw_dlimit = dp->pw_dlimit; if(upw.pw_doverflw > dp->pw_doverflw) warn("doverflw"); else upw.pw_doverflw = dp->pw_doverflw; if(upw.pw_plimit > dp->pw_plimit) warn("plimit"); else upw.pw_plimit = dp->pw_plimit; if(upw.pw_tmask > dp->pw_tmask) warn("tmask"); else upw.pw_tmask = dp->pw_tmask; if(upw.pw_shares > dp->pw_shares) warn("shares"); else upw.pw_shares = dp->pw_shares; } upw.pw_flags = dp->pw_flags; upw.pw_climit = dp->pw_climit; upw.pw_pages = dp->pw_pages; # ifdef TERMBOOK upw.pw_tblim = dp->pw_tblim; upw.pw_tbrate = dp->pw_tbrate; # endif TERMBOOK if(candobetter == 0) return(1); /* now have to move the directory */ mvit(); return(2); } else return(0); } /* and here he is not in any class and so should not have been looked at */ prints(2,logname); prints(2," has no classes\n"); return(0); /* and thats the lot */ } stop() { signal(2,1); signal(3,1); stopf++; } mail() { int fd; if(fork()) return(0); close(0); open("/usr/lib/pwe/adjust.mail", 0); execl("/bin/mail", "adjust.mail", logname, 0); error("Cannot exec mail\n"); } warn(s) char *s; { prints(1,logname); prints(1,": present "); prints(1,s); prints(1," limit too large\n"); }