1*9981Seric static char sccsid[] = "@(#)sub.c 4.4 (Berkeley) 12/27/82"; 28207Smckusick 38207Smckusick /* 48207Smckusick sub.c 58207Smckusick 68207Smckusick support procedures 78207Smckusick 88207Smckusick the following procedures end up reading the passwd file 98207Smckusick or the passwdf file and are to be avoided. 108207Smckusick 118207Smckusick getpwuid(uid) 128207Smckusick getpwnam(sn) 138207Smckusick PwdCurrent() 148207Smckusick getenv("HOME") maybe if hget, hgethome don't work 158207Smckusick SnFromUid(uid) maybe if hashed passwd stuff doesn't work 168207Smckusick SnCurrent() maybe if getlogin fails calls SnFromUid(uid) 178207Smckusick getpwf() 188207Smckusick passwdent(uid,sn) 198207Smckusick */ 208207Smckusick 218207Smckusick # include "defs.h" 228207Smckusick # include "config.h" 238207Smckusick # include <varargs.h> 248207Smckusick 258207Smckusick /* global variables */ 268207Smckusick int debugflg = DBV; /* debug flag */ 278207Smckusick char local = LOCAL; /* the machine we're on */ 288207Smckusick struct userinfo status; 298207Smckusick 308207Smckusick char netcmd[] = NETCMD; 318207Smckusick char resfile[] = RESFILE; 328207Smckusick char senddir[] = SENDDIR; 338207Smckusick char Bsh[] = BINSH; 348207Smckusick 358207Smckusick char shomedir[100]; 368207Smckusick 378207Smckusick /* 388207Smckusick passwdent() 398207Smckusick 408207Smckusick Read the password file looking for current user's entry. 418207Smckusick Fill in the status structure. 428207Smckusick Has the (dangerous) side effect of giving a value to getenv("HOME"). 438207Smckusick */ 448207Smckusick passwdent() 458207Smckusick { 468207Smckusick register char *u; 478207Smckusick register struct passwd *pwd; 488207Smckusick #ifdef CRN 498207Smckusick register struct gecos *gcos; 508207Smckusick #endif 518207Smckusick pwd = PwdCurrent(); 528207Smckusick if(pwd == NULL){ 538207Smckusick err("Bad uid/username\n"); 548207Smckusick return; 558207Smckusick } 568207Smckusick strcpy(status.localname,pwd->pw_name); 578207Smckusick status.muid = guid(pwd->pw_uid,pwd->pw_gid); 588207Smckusick status.mgid = pwd->pw_gid; 598207Smckusick #ifdef CRN 608207Smckusick if( (gcos=pwgecos( pwd->pw_gecos) ) == NULL ) 618207Smckusick strcpy( status.jobno, MAGICCRN ); 628207Smckusick else { 638207Smckusick if( debugflg ) 648207Smckusick debug( "crn found = %s\n", gcos->gc_crn ); 658207Smckusick if( isalpha( gcos->gc_crn[0] ) || 668207Smckusick isdigit( gcos->gc_crn[0] ) ) 678207Smckusick strcpy( status.jobno, gcos->gc_crn ); 688207Smckusick else 698207Smckusick strcpy( status.jobno, MAGICCRN ); 708207Smckusick } 718207Smckusick #else 728207Smckusick strcpy( status.jobno, "XYZZ" ); 738207Smckusick #endif 748207Smckusick strcpy(status.dir,pwd->pw_dir); 758207Smckusick strcpy(shomedir,pwd->pw_dir); /* side effect */ 768207Smckusick u = pwd->pw_shell; 778207Smckusick if(u[0] == 0 || strcmp(u,"/bin/sbash") == 0)u= Bsh; 788207Smckusick strcpy(status.loginshell,u); 798207Smckusick } 808207Smckusick /* 818207Smckusick promptlogin(mchto) 828207Smckusick 838207Smckusick ask user for login and passwd on mchto. 848207Smckusick make sure status.localname has a value before calling 858207Smckusick this. One way is to call passwdent(). 868207Smckusick */ 878207Smckusick promptlogin(mchto) 888207Smckusick char mchto; 898207Smckusick { 908207Smckusick char buf[BUFSIZ], mch; 918207Smckusick FILE *wf; 928207Smckusick int c; 938207Smckusick if(status.mpasswd[0] == 0 || status.login[0] == 0 || status.force){ 948207Smckusick wf = fopen("/dev/tty","r"); 958207Smckusick if(wf != NULL){ 968207Smckusick if(status.login[0]==0 || status.force){ 978207Smckusick fprintf(stderr,"Name (%s:%s): ",longname(mchto), 988207Smckusick status.localname); 998207Smckusick if(fgets(buf, BUFSIZ, wf) != buf){ 1008207Smckusick perror("fgets"); 1018207Smckusick exit(EX_OSERR); 1028207Smckusick } 1038207Smckusick c = strlen(buf); 1048207Smckusick buf[c > 0 ? c-1 : 0] = 0; 1058207Smckusick if(c > 10){ 1068207Smckusick err("Login name too long.\n"); 1078207Smckusick exit(EX_USAGE); 1088207Smckusick } 1098207Smckusick if(FMemberSCh(buf,' ')){ 1108207Smckusick err("Login names don't have blanks in them.\n"); 1118207Smckusick exit(EX_USAGE); 1128207Smckusick } 1138207Smckusick if(buf[0] == 0)strcpy(buf,status.localname); 1148207Smckusick mch = MchSFromAddr(status.login,buf); 1158207Smckusick if(mch != local && mch != mchto){ 1168207Smckusick err( 1178207Smckusick "Must specify login name on %s machine\n", 1188207Smckusick longname(mchto)); 1198207Smckusick exit(EX_USAGE); 1208207Smckusick } 1218207Smckusick } 1228207Smckusick if(strcmp(status.login,"network") != 0 1238207Smckusick && (status.mpasswd[0]== 0 || status.force)){ 1248207Smckusick sprintf(buf,"Password (%s:%s):", 1258207Smckusick longname(mchto), status.login); 1268207Smckusick strcpy(status.mpasswd,getpass(buf)); 1278207Smckusick } 1288207Smckusick fclose(wf); 1298207Smckusick } 1308207Smckusick } 1318207Smckusick if(status.login[0] == 0) strcpy(status.login,status.localname); 1328207Smckusick if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\""); 1338207Smckusick status.force = 0; 1348207Smckusick } 1358207Smckusick 1368207Smckusick #define tst(a,b) (*mode == 'r'? (b) : (a)) 1378207Smckusick #define RDR 0 1388207Smckusick #define WTR 1 1398207Smckusick static int popen_pid[20]; 1408207Smckusick 1418207Smckusick /* return a file descriptor suitable for writing, send to 1428207Smckusick user toaddress from fromaddress, 1438207Smckusick if cautious != 0 then don't do any forwarding 1448207Smckusick hopcnt is passed thru the mail program. 1458207Smckusick normal value is 0 1468207Smckusick */ 1478207Smckusick FILE * 1488207Smckusick mailopen(toaddress, fromaddress, cautious, hopcnt) 1498207Smckusick char *toaddress, *fromaddress; 1508207Smckusick int cautious, hopcnt; 1518207Smckusick { 1528207Smckusick char cmd[100]; 1538207Smckusick char *mode = "w"; 1548207Smckusick int p[2]; 1558207Smckusick register myside, hisside, pid; 1568207Smckusick char shopcnt[20]; 1578207Smckusick 1588207Smckusick if(pipe(p) < 0) 1598207Smckusick return NULL; 1608207Smckusick myside = tst(p[WTR], p[RDR]); 1618207Smckusick hisside = tst(p[RDR], p[WTR]); 1628207Smckusick while((pid = fork()) == -1)sleep(2); 1638207Smckusick if(pid == 0) { 1648207Smckusick /* myside and hisside reverse roles in child */ 1658207Smckusick close(myside); 1668207Smckusick /* 1678207Smckusick dup2(hisside, tst(0, 1)); 1688207Smckusick */ 1698207Smckusick close(0); 1708207Smckusick dup(hisside); 1718207Smckusick close(hisside); 1728207Smckusick sprintf(shopcnt,"%d",hopcnt); 1738207Smckusick if(fromaddress != NULL){ 1748207Smckusick /* by convention, MAILFWD1 may forward this mail 1758207Smckusick and response messages shouldn't be forwarded */ 1768207Smckusick if(!cautious && !FMemberSCh(toaddress,'/')){ 177*9981Seric # ifdef SENDMAIL 178*9981Seric mexecl("/usr/lib/sendmail", 179*9981Seric "sendmail", "-oee", "-r", fromaddress, 1808207Smckusick "-h",shopcnt, toaddress, 0); 181*9981Seric # endif SENDMAIL 1828207Smckusick mexecl(MAILFWD1, "mail","-r",fromaddress, 1838207Smckusick "-h",shopcnt,toaddress,0); 1848207Smckusick } 1858207Smckusick mexecl(SYSMAIL2, "mail","-d","-r",fromaddress, 1868207Smckusick "-h", shopcnt,toaddress,0); 1878207Smckusick } else { 1888207Smckusick if(!cautious && !FMemberSCh(toaddress,'/')){ 189*9981Seric # ifdef SENDMAIL 190*9981Seric mexecl("/usr/lib/sendmail", 191*9981Seric "sendmail", "-ee", "-h", shopcnt, 1928207Smckusick toaddress, 0); 1938207Smckusick # endif 1948207Smckusick mexecl(MAILFWD1, "mail","-h", shopcnt, 1958207Smckusick toaddress,0); 1968207Smckusick } 1978207Smckusick mexecl(SYSMAIL2, "mail","-d","-h", shopcnt,toaddress,0); 1988207Smckusick } 1998207Smckusick perror(SYSMAIL2); 2008207Smckusick exit(EX_UNAVAILABLE); 2018207Smckusick } 2028207Smckusick if(pid == -1) 2038207Smckusick return NULL; 2048207Smckusick popen_pid[myside] = pid; 2058207Smckusick close(hisside); 2068207Smckusick return(fdopen(myside, mode)); 2078207Smckusick } 2088207Smckusick 2098207Smckusick mailclose(ptr) 2108207Smckusick FILE *ptr; 2118207Smckusick { 2128207Smckusick register f, r, (*hstat)(), (*istat)(), (*qstat)(); 2138207Smckusick int status; 2148207Smckusick 2158207Smckusick f = fileno(ptr); 2168207Smckusick fclose(ptr); 2178207Smckusick istat = signal(SIGINT, SIG_IGN); 2188207Smckusick qstat = signal(SIGQUIT, SIG_IGN); 2198207Smckusick hstat = signal(SIGHUP, SIG_IGN); 2208207Smckusick while((r = wait(&status)) != popen_pid[f] && r != -1) 2218207Smckusick ; 2228207Smckusick if(r == -1) 2238207Smckusick status = -1; 2248207Smckusick signal(SIGINT, istat); 2258207Smckusick signal(SIGQUIT, qstat); 2268207Smckusick signal(SIGHUP, hstat); 2278207Smckusick return(status); 2288207Smckusick } 2298207Smckusick 2308207Smckusick /* 2318207Smckusick ch means 'a'-'z', inx in 0..25 2328207Smckusick ch means '0'-'9', inx in 26..35 2338207Smckusick */ 2348207Smckusick chtoinx(ch) { 2358207Smckusick if('a' <= ch && ch <= 'z') 2368207Smckusick return(ch - 'a'); 2378207Smckusick if('0' <= ch && ch <= '9') 2388207Smckusick return((ch - '0') + 26); 2398207Smckusick err("bad ch"); 2408207Smckusick } 2418207Smckusick 2428207Smckusick /* 2438207Smckusick inx is 0..25 means 'a'-'z' 2448207Smckusick inx is 26..35 means '0'-'9' 2458207Smckusick */ 2468207Smckusick inxtoch(inx) { 2478207Smckusick if(0 <= inx && inx <= 25) 2488207Smckusick return(inx + 'a'); 2498207Smckusick if(26 <= inx && inx <= 35) 2508207Smckusick return('0' + (inx - 26)); 2518207Smckusick err("bad ch"); 2528207Smckusick } 2538207Smckusick 2548207Smckusick /* determine through machine */ 2558207Smckusick gothru(from,to){ 2568207Smckusick register int i; 2578207Smckusick switch(from){ 2588207Smckusick # ifdef RAND 2598207Smckusick case 'a': i = configA[chtoinx(to)]; break; 2608207Smckusick case 'b': i = configB[chtoinx(to)]; break; 2618207Smckusick case 'c': i = configC[chtoinx(to)]; break; 2628207Smckusick # endif 2638207Smckusick # ifdef NOSC 2648207Smckusick case 'a': i = configA[chtoinx(to)]; break; 2658207Smckusick case 'c': i = configC[chtoinx(to)]; break; 2668207Smckusick case 'm': i = configM[chtoinx(to)]; break; 2678207Smckusick # endif 2688207Smckusick # ifdef BERKELEY 2698207Smckusick /* for Berkeley */ 2708207Smckusick case 'a': i = configA[chtoinx(to)]; break; 2718207Smckusick case 'b': i = configB[chtoinx(to)]; break; 2728207Smckusick case 'c': i = configC[chtoinx(to)]; break; 2738207Smckusick case 'd': i = configD[chtoinx(to)]; break; 2748207Smckusick case 'e': i = configE[chtoinx(to)]; break; 2758207Smckusick case 'f': i = configF[chtoinx(to)]; break; 2768207Smckusick case 'g': i = configG[chtoinx(to)]; break; 2778231Smckusick case 'h': i = configH[chtoinx(to)]; break; 2788207Smckusick case 'i': i = configI[chtoinx(to)]; break; 2798207Smckusick case 'j': i = configJ[chtoinx(to)]; break; 2808207Smckusick case 'k': i = configK[chtoinx(to)]; break; 2818207Smckusick case 'l': i = configL[chtoinx(to)]; break; 2828207Smckusick case 'm': i = configM[chtoinx(to)]; break; 2838207Smckusick case 'n': i = configN[chtoinx(to)]; break; 2848207Smckusick case 'o': i = configO[chtoinx(to)]; break; 2858207Smckusick case 'p': i = configP[chtoinx(to)]; break; 2868207Smckusick case 'r': i = configR[chtoinx(to)]; break; 2878207Smckusick case 's': i = configS[chtoinx(to)]; break; 2888207Smckusick case 't': i = configT[chtoinx(to)]; break; 2898231Smckusick case 'u': i = configU[chtoinx(to)]; break; 2908207Smckusick case 'v': i = configV[chtoinx(to)]; break; 2918231Smckusick case 'w': i = configW[chtoinx(to)]; break; 2928207Smckusick case 'x': i = configX[chtoinx(to)]; break; 2938207Smckusick case 'y': i = configY[chtoinx(to)]; break; 2948207Smckusick case 'z': i = configZ[chtoinx(to)]; break; 2958207Smckusick # endif 2968207Smckusick default: i = 0; break; 2978207Smckusick } 2988207Smckusick return(i); 2998207Smckusick } 3008207Smckusick 3018207Smckusick # define NPARMS 20 3028207Smckusick /* prints out commands before executing them */ 3038207Smckusick /*VARARGS0*/ 3048207Smckusick mexecl(va_alist) 3058207Smckusick va_dcl 3068207Smckusick { 3078207Smckusick char *arr[NPARMS], *file, *f; 3088207Smckusick va_list ap; 3098207Smckusick register int i; 3108207Smckusick va_start(ap); 3118207Smckusick file = va_arg(ap, char *); 3128207Smckusick i = 0; 3138207Smckusick while(f = va_arg(ap, char *)){ 3148207Smckusick if(i >= NPARMS){ 3158207Smckusick err("too many args"); 3168207Smckusick arr[NPARMS-1] = NULL; 3178207Smckusick break; 3188207Smckusick } 3198207Smckusick if(debugflg) err("'%s' ",f); 3208207Smckusick arr[i++] = f; 3218207Smckusick } 3228207Smckusick arr[i] = NULL; 3238207Smckusick va_end(ap); 3248207Smckusick if(debugflg) putc('\n',stderr); 3258207Smckusick execv(file, arr); 3268207Smckusick } 3278207Smckusick 3288207Smckusick /* prints out commands before executing them */ 3298207Smckusick mexecv(s,p) 3308207Smckusick register char *s, **p;{ 3318207Smckusick register int i; 3328207Smckusick if(debugflg){ 3338207Smckusick err("'%s' ",s); 3348207Smckusick for(i=0; p[i]; i++)err("'%s' ",p[i]); 3358207Smckusick putc('\n',stderr); 3368207Smckusick } 3378207Smckusick execv(s,p); 3388207Smckusick } 3398207Smckusick 3408207Smckusick /*VARARGS0*/ 3418207Smckusick /* fills in -l - -p from commands like rcp */ 3428207Smckusick /* must be called with at least two arguments */ 3438207Smckusick kexecl(va_alist) 3448207Smckusick va_dcl 3458207Smckusick { 3468207Smckusick char *a[NPARMS], i = 1, *file; 3478207Smckusick va_list ap; 3488207Smckusick va_start(ap); 3498207Smckusick file = va_arg(ap, char *); 3508207Smckusick a[0] = va_arg(ap, char *); 3518207Smckusick if(status.login[0]){ 3528207Smckusick a[i++] = "-l"; 3538207Smckusick a[i++] = status.login; 3548207Smckusick } 3558207Smckusick if(status.mpasswd[0]){ 3568207Smckusick a[i++] = "-p"; 3578207Smckusick a[i++] = status.mpasswd; 3588207Smckusick } 3598207Smckusick if(status.nonotify)a[i++] = "-b"; 3608207Smckusick if(status.force) a[i++] = "-f"; 3618207Smckusick if(status.quiet) a[i++] = "-q"; 3628207Smckusick if(status.nowrite) a[i++] = "-n"; 3638207Smckusick while (a[i++] = va_arg(ap, char *)){ 3648207Smckusick if(i >= NPARMS){ 3658207Smckusick err("too many args"); 3668207Smckusick a[NPARMS-1] = NULL; 3678207Smckusick break; 3688207Smckusick } 3698207Smckusick }; 3708207Smckusick mexecv(file, a); 3718207Smckusick } 3728207Smckusick 3738207Smckusick /* 3748207Smckusick MchSFromAddr(sn,addr) 3758207Smckusick 3768207Smckusick take an address of the form "mach:username" 3778207Smckusick and return mch as the 1 char code of "mach" and 3788207Smckusick in sn put "username". 3798207Smckusick If addr has no colon in it, return mch==local, sn==addr. 3808207Smckusick Return 0 for mch if host unknown. 3818207Smckusick */ 3828207Smckusick MchSFromAddr(sn,addr) 3838207Smckusick char *sn, *addr; 3848207Smckusick { 3858207Smckusick char fcolon = 0, *s, mch, stemp[BUFSIZ]; 3868207Smckusick 3878207Smckusick /* assume addr is a local address */ 3888207Smckusick 3898207Smckusick strcpy(stemp,addr); 3908207Smckusick s = stemp; 3918207Smckusick while(*s){ 3928207Smckusick if(*s == ':'){ 3938207Smckusick fcolon = 1; 3948207Smckusick *s++ = 0; 3958207Smckusick break; 3968207Smckusick } 3978207Smckusick s++; 3988207Smckusick } 3998207Smckusick if(fcolon != 1){ 4008207Smckusick /* sn better be the right size for addr */ 4018207Smckusick mch = local; 4028207Smckusick strcpy(sn,addr); 4038207Smckusick return(mch); 4048207Smckusick } 4058207Smckusick 4068207Smckusick /* addr has a colon in it, s pts to name */ 4078207Smckusick mch = lookup(stemp); 4088207Smckusick strcpy(sn,s); 4098207Smckusick return(mch); 4108207Smckusick } 4118207Smckusick 4128207Smckusick 4138207Smckusick /* returns a single character for machine S */ 4148207Smckusick /* returns 0 for unknown host */ 4158207Smckusick lookup(s) 4168207Smckusick register char *s; { 4178207Smckusick register struct tt *t; 4188207Smckusick if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s); 4198207Smckusick for(t = table; t->bigname; t++) 4208207Smckusick if(streql(s,t->bigname) == 0)return(t->lname); 4218207Smckusick return(0); 4228207Smckusick } 4238207Smckusick 4248207Smckusick /* returns a long name (string) for single character machine c */ 4258207Smckusick char *longname(c) 4268207Smckusick register char c; 4278207Smckusick { 4288207Smckusick register struct tt *t; 4298207Smckusick if(c == 0)return("UNKNOWN"); 4308207Smckusick for(t = table; t->bigname; t++) 4318207Smckusick if(c == t->lname)return(t->bigname); 4328207Smckusick return("UNKNOWN"); 4338207Smckusick } 4348207Smckusick /* 4358207Smckusick FMemberSCh(s,ch) 4368207Smckusick 4378207Smckusick return 1 if ch is a character in string s. 4388207Smckusick 0 otherwise. 4398207Smckusick */ 4408207Smckusick FMemberSCh(s,ch) 4418207Smckusick register char *s, ch; 4428207Smckusick { 4438207Smckusick while(*s)if(*s++ == ch)return(1); 4448207Smckusick return(0); 4458207Smckusick } 4468207Smckusick 4478207Smckusick /* return a static string with the form "X hrs X mins X secs" */ 4488207Smckusick /* t is # of secs */ 4498207Smckusick char *comptime(t) 4508207Smckusick long t; { 4518207Smckusick static char str[30]; 4528207Smckusick char buf[20]; 4538207Smckusick long w; 4548207Smckusick str[0] = 0; 4558207Smckusick w = t/3600L; 4568207Smckusick if(w > 0L){ 4578207Smckusick sprintf(buf,"%ld hr ",w); 4588207Smckusick strcat(str,buf); 4598207Smckusick } 4608207Smckusick t = t % 3600L; 4618207Smckusick w = t/60L; 4628207Smckusick if(w > 0L){ 4638207Smckusick sprintf(buf,"%ld min ",w); 4648207Smckusick strcat(str,buf); 4658207Smckusick } 4668207Smckusick t = t % 60L; 4678207Smckusick sprintf(buf,"%ld sec",t); 4688207Smckusick strcat(str,buf); 4698207Smckusick return(str); 4708207Smckusick } 4718207Smckusick /* 4728207Smckusick parseparmlist(string) 4738207Smckusick 4748207Smckusick parses variable parameter lists in string, 4758207Smckusick as defined in genparmlist in net.c 4768207Smckusick */ 4778207Smckusick parseparmlist(parmlist) 4788207Smckusick char *parmlist; 4798207Smckusick { 4808207Smckusick while(*parmlist && *parmlist != '(')parmlist++; 4818207Smckusick } 4828207Smckusick 4838207Smckusick /* just like strcmp except upper- and lower-case are ignored */ 4848207Smckusick streql(s1,s2) 4858207Smckusick char *s1, *s2; { 4868207Smckusick char a,b; 4878207Smckusick while(*s1 && *s2){ 4888207Smckusick a = isupper(*s1) ? tolower(*s1) : *s1; 4898207Smckusick b = isupper(*s2) ? tolower(*s2) : *s2; 4908207Smckusick if(a < b)return(-1); 4918207Smckusick if(a > b)return(1); 4928207Smckusick s1++, s2++; 4938207Smckusick } 4948207Smckusick if(*s2)return(-1); 4958207Smckusick if(*s1)return(1); 4968207Smckusick return(0); 4978207Smckusick } 4988207Smckusick /* VARARGS0 */ 4998207Smckusick err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) { 5008207Smckusick fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r); 5018207Smckusick } 502