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