1*10160Seric static char sccsid[] = "@(#)sub.c 4.5 (Berkeley) 01/05/83";
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 */
passwdent()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 */
promptlogin(mchto)878207Smckusick promptlogin(mchto)
888207Smckusick char mchto;
898207Smckusick {
908207Smckusick char buf[BUFSIZ], mch;
918207Smckusick FILE *wf;
928207Smckusick int c;
93*10160Seric if(status.login[0]==0 || status.force){
94*10160Seric buf[0] = 0;
958207Smckusick wf = fopen("/dev/tty","r");
968207Smckusick if(wf != NULL){
97*10160Seric fprintf(stderr,"Name (%s:%s): ",longname(mchto),
98*10160Seric status.localname);
99*10160Seric if(fgets(buf, BUFSIZ, wf) != buf){
100*10160Seric perror("fgets");
101*10160Seric exit(EX_OSERR);
1028207Smckusick }
103*10160Seric c = strlen(buf);
104*10160Seric buf[c > 0 ? c-1 : 0] = 0;
105*10160Seric if(c > 10){
106*10160Seric err("Login name too long.\n");
107*10160Seric exit(EX_USAGE);
1088207Smckusick }
109*10160Seric if(FMemberSCh(buf,' ')){
110*10160Seric err("Login names don't have blanks in them.\n");
111*10160Seric exit(EX_USAGE);
112*10160Seric }
1138207Smckusick fclose(wf);
1148207Smckusick }
115*10160Seric if(buf[0] == 0)strcpy(buf,status.localname);
116*10160Seric mch = MchSFromAddr(status.login,buf);
117*10160Seric if(mch != local && mch != mchto){
118*10160Seric err("Must specify login name on %s machine\n",
119*10160Seric longname(mchto));
120*10160Seric exit(EX_USAGE);
121*10160Seric }
1228207Smckusick }
123*10160Seric if(strcmp(status.login,"network") != 0
124*10160Seric && (status.mpasswd[0]== 0 || status.force)){
125*10160Seric sprintf(buf,"Password (%s:%s):",
126*10160Seric longname(mchto), status.login);
127*10160Seric strcpy(status.mpasswd,getpass(buf));
128*10160Seric }
1298207Smckusick if(status.login[0] == 0) strcpy(status.login,status.localname);
1308207Smckusick if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\"");
1318207Smckusick status.force = 0;
1328207Smckusick }
1338207Smckusick
1348207Smckusick #define tst(a,b) (*mode == 'r'? (b) : (a))
1358207Smckusick #define RDR 0
1368207Smckusick #define WTR 1
1378207Smckusick static int popen_pid[20];
1388207Smckusick
1398207Smckusick /* return a file descriptor suitable for writing, send to
1408207Smckusick user toaddress from fromaddress,
1418207Smckusick if cautious != 0 then don't do any forwarding
1428207Smckusick hopcnt is passed thru the mail program.
1438207Smckusick normal value is 0
1448207Smckusick */
1458207Smckusick FILE *
mailopen(toaddress,fromaddress,cautious,hopcnt)1468207Smckusick mailopen(toaddress, fromaddress, cautious, hopcnt)
1478207Smckusick char *toaddress, *fromaddress;
1488207Smckusick int cautious, hopcnt;
1498207Smckusick {
1508207Smckusick char cmd[100];
1518207Smckusick char *mode = "w";
1528207Smckusick int p[2];
1538207Smckusick register myside, hisside, pid;
1548207Smckusick char shopcnt[20];
1558207Smckusick
1568207Smckusick if(pipe(p) < 0)
1578207Smckusick return NULL;
1588207Smckusick myside = tst(p[WTR], p[RDR]);
1598207Smckusick hisside = tst(p[RDR], p[WTR]);
1608207Smckusick while((pid = fork()) == -1)sleep(2);
1618207Smckusick if(pid == 0) {
1628207Smckusick /* myside and hisside reverse roles in child */
1638207Smckusick close(myside);
1648207Smckusick /*
1658207Smckusick dup2(hisside, tst(0, 1));
1668207Smckusick */
1678207Smckusick close(0);
1688207Smckusick dup(hisside);
1698207Smckusick close(hisside);
1708207Smckusick sprintf(shopcnt,"%d",hopcnt);
1718207Smckusick if(fromaddress != NULL){
1728207Smckusick /* by convention, MAILFWD1 may forward this mail
1738207Smckusick and response messages shouldn't be forwarded */
1748207Smckusick if(!cautious && !FMemberSCh(toaddress,'/')){
1759981Seric # ifdef SENDMAIL
1769981Seric mexecl("/usr/lib/sendmail",
1779981Seric "sendmail", "-oee", "-r", fromaddress,
1788207Smckusick "-h",shopcnt, toaddress, 0);
1799981Seric # endif SENDMAIL
1808207Smckusick mexecl(MAILFWD1, "mail","-r",fromaddress,
1818207Smckusick "-h",shopcnt,toaddress,0);
1828207Smckusick }
1838207Smckusick mexecl(SYSMAIL2, "mail","-d","-r",fromaddress,
1848207Smckusick "-h", shopcnt,toaddress,0);
1858207Smckusick } else {
1868207Smckusick if(!cautious && !FMemberSCh(toaddress,'/')){
1879981Seric # ifdef SENDMAIL
1889981Seric mexecl("/usr/lib/sendmail",
1899981Seric "sendmail", "-ee", "-h", shopcnt,
1908207Smckusick toaddress, 0);
1918207Smckusick # endif
1928207Smckusick mexecl(MAILFWD1, "mail","-h", shopcnt,
1938207Smckusick toaddress,0);
1948207Smckusick }
1958207Smckusick mexecl(SYSMAIL2, "mail","-d","-h", shopcnt,toaddress,0);
1968207Smckusick }
1978207Smckusick perror(SYSMAIL2);
1988207Smckusick exit(EX_UNAVAILABLE);
1998207Smckusick }
2008207Smckusick if(pid == -1)
2018207Smckusick return NULL;
2028207Smckusick popen_pid[myside] = pid;
2038207Smckusick close(hisside);
2048207Smckusick return(fdopen(myside, mode));
2058207Smckusick }
2068207Smckusick
mailclose(ptr)2078207Smckusick mailclose(ptr)
2088207Smckusick FILE *ptr;
2098207Smckusick {
2108207Smckusick register f, r, (*hstat)(), (*istat)(), (*qstat)();
2118207Smckusick int status;
2128207Smckusick
2138207Smckusick f = fileno(ptr);
2148207Smckusick fclose(ptr);
2158207Smckusick istat = signal(SIGINT, SIG_IGN);
2168207Smckusick qstat = signal(SIGQUIT, SIG_IGN);
2178207Smckusick hstat = signal(SIGHUP, SIG_IGN);
2188207Smckusick while((r = wait(&status)) != popen_pid[f] && r != -1)
2198207Smckusick ;
2208207Smckusick if(r == -1)
2218207Smckusick status = -1;
2228207Smckusick signal(SIGINT, istat);
2238207Smckusick signal(SIGQUIT, qstat);
2248207Smckusick signal(SIGHUP, hstat);
2258207Smckusick return(status);
2268207Smckusick }
2278207Smckusick
2288207Smckusick /*
2298207Smckusick ch means 'a'-'z', inx in 0..25
2308207Smckusick ch means '0'-'9', inx in 26..35
2318207Smckusick */
chtoinx(ch)2328207Smckusick chtoinx(ch) {
2338207Smckusick if('a' <= ch && ch <= 'z')
2348207Smckusick return(ch - 'a');
2358207Smckusick if('0' <= ch && ch <= '9')
2368207Smckusick return((ch - '0') + 26);
2378207Smckusick err("bad ch");
2388207Smckusick }
2398207Smckusick
2408207Smckusick /*
2418207Smckusick inx is 0..25 means 'a'-'z'
2428207Smckusick inx is 26..35 means '0'-'9'
2438207Smckusick */
inxtoch(inx)2448207Smckusick inxtoch(inx) {
2458207Smckusick if(0 <= inx && inx <= 25)
2468207Smckusick return(inx + 'a');
2478207Smckusick if(26 <= inx && inx <= 35)
2488207Smckusick return('0' + (inx - 26));
2498207Smckusick err("bad ch");
2508207Smckusick }
2518207Smckusick
2528207Smckusick /* determine through machine */
gothru(from,to)2538207Smckusick gothru(from,to){
2548207Smckusick register int i;
2558207Smckusick switch(from){
2568207Smckusick # ifdef RAND
2578207Smckusick case 'a': i = configA[chtoinx(to)]; break;
2588207Smckusick case 'b': i = configB[chtoinx(to)]; break;
2598207Smckusick case 'c': i = configC[chtoinx(to)]; break;
2608207Smckusick # endif
2618207Smckusick # ifdef NOSC
2628207Smckusick case 'a': i = configA[chtoinx(to)]; break;
2638207Smckusick case 'c': i = configC[chtoinx(to)]; break;
2648207Smckusick case 'm': i = configM[chtoinx(to)]; break;
2658207Smckusick # endif
2668207Smckusick # ifdef BERKELEY
2678207Smckusick /* for Berkeley */
2688207Smckusick case 'a': i = configA[chtoinx(to)]; break;
2698207Smckusick case 'b': i = configB[chtoinx(to)]; break;
2708207Smckusick case 'c': i = configC[chtoinx(to)]; break;
2718207Smckusick case 'd': i = configD[chtoinx(to)]; break;
2728207Smckusick case 'e': i = configE[chtoinx(to)]; break;
2738207Smckusick case 'f': i = configF[chtoinx(to)]; break;
2748207Smckusick case 'g': i = configG[chtoinx(to)]; break;
2758231Smckusick case 'h': i = configH[chtoinx(to)]; break;
2768207Smckusick case 'i': i = configI[chtoinx(to)]; break;
2778207Smckusick case 'j': i = configJ[chtoinx(to)]; break;
2788207Smckusick case 'k': i = configK[chtoinx(to)]; break;
2798207Smckusick case 'l': i = configL[chtoinx(to)]; break;
2808207Smckusick case 'm': i = configM[chtoinx(to)]; break;
2818207Smckusick case 'n': i = configN[chtoinx(to)]; break;
2828207Smckusick case 'o': i = configO[chtoinx(to)]; break;
2838207Smckusick case 'p': i = configP[chtoinx(to)]; break;
2848207Smckusick case 'r': i = configR[chtoinx(to)]; break;
2858207Smckusick case 's': i = configS[chtoinx(to)]; break;
2868207Smckusick case 't': i = configT[chtoinx(to)]; break;
2878231Smckusick case 'u': i = configU[chtoinx(to)]; break;
2888207Smckusick case 'v': i = configV[chtoinx(to)]; break;
2898231Smckusick case 'w': i = configW[chtoinx(to)]; break;
2908207Smckusick case 'x': i = configX[chtoinx(to)]; break;
2918207Smckusick case 'y': i = configY[chtoinx(to)]; break;
2928207Smckusick case 'z': i = configZ[chtoinx(to)]; break;
2938207Smckusick # endif
2948207Smckusick default: i = 0; break;
2958207Smckusick }
2968207Smckusick return(i);
2978207Smckusick }
2988207Smckusick
2998207Smckusick # define NPARMS 20
3008207Smckusick /* prints out commands before executing them */
3018207Smckusick /*VARARGS0*/
mexecl(va_alist)3028207Smckusick mexecl(va_alist)
3038207Smckusick va_dcl
3048207Smckusick {
3058207Smckusick char *arr[NPARMS], *file, *f;
3068207Smckusick va_list ap;
3078207Smckusick register int i;
3088207Smckusick va_start(ap);
3098207Smckusick file = va_arg(ap, char *);
3108207Smckusick i = 0;
3118207Smckusick while(f = va_arg(ap, char *)){
3128207Smckusick if(i >= NPARMS){
3138207Smckusick err("too many args");
3148207Smckusick arr[NPARMS-1] = NULL;
3158207Smckusick break;
3168207Smckusick }
3178207Smckusick if(debugflg) err("'%s' ",f);
3188207Smckusick arr[i++] = f;
3198207Smckusick }
3208207Smckusick arr[i] = NULL;
3218207Smckusick va_end(ap);
3228207Smckusick if(debugflg) putc('\n',stderr);
3238207Smckusick execv(file, arr);
3248207Smckusick }
3258207Smckusick
3268207Smckusick /* prints out commands before executing them */
mexecv(s,p)3278207Smckusick mexecv(s,p)
3288207Smckusick register char *s, **p;{
3298207Smckusick register int i;
3308207Smckusick if(debugflg){
3318207Smckusick err("'%s' ",s);
3328207Smckusick for(i=0; p[i]; i++)err("'%s' ",p[i]);
3338207Smckusick putc('\n',stderr);
3348207Smckusick }
3358207Smckusick execv(s,p);
3368207Smckusick }
3378207Smckusick
3388207Smckusick /*VARARGS0*/
3398207Smckusick /* fills in -l - -p from commands like rcp */
3408207Smckusick /* must be called with at least two arguments */
kexecl(va_alist)3418207Smckusick kexecl(va_alist)
3428207Smckusick va_dcl
3438207Smckusick {
3448207Smckusick char *a[NPARMS], i = 1, *file;
3458207Smckusick va_list ap;
3468207Smckusick va_start(ap);
3478207Smckusick file = va_arg(ap, char *);
3488207Smckusick a[0] = va_arg(ap, char *);
3498207Smckusick if(status.login[0]){
3508207Smckusick a[i++] = "-l";
3518207Smckusick a[i++] = status.login;
3528207Smckusick }
3538207Smckusick if(status.mpasswd[0]){
3548207Smckusick a[i++] = "-p";
3558207Smckusick a[i++] = status.mpasswd;
3568207Smckusick }
3578207Smckusick if(status.nonotify)a[i++] = "-b";
3588207Smckusick if(status.force) a[i++] = "-f";
3598207Smckusick if(status.quiet) a[i++] = "-q";
3608207Smckusick if(status.nowrite) a[i++] = "-n";
3618207Smckusick while (a[i++] = va_arg(ap, char *)){
3628207Smckusick if(i >= NPARMS){
3638207Smckusick err("too many args");
3648207Smckusick a[NPARMS-1] = NULL;
3658207Smckusick break;
3668207Smckusick }
3678207Smckusick };
3688207Smckusick mexecv(file, a);
3698207Smckusick }
3708207Smckusick
3718207Smckusick /*
3728207Smckusick MchSFromAddr(sn,addr)
3738207Smckusick
3748207Smckusick take an address of the form "mach:username"
3758207Smckusick and return mch as the 1 char code of "mach" and
3768207Smckusick in sn put "username".
3778207Smckusick If addr has no colon in it, return mch==local, sn==addr.
3788207Smckusick Return 0 for mch if host unknown.
3798207Smckusick */
MchSFromAddr(sn,addr)3808207Smckusick MchSFromAddr(sn,addr)
3818207Smckusick char *sn, *addr;
3828207Smckusick {
3838207Smckusick char fcolon = 0, *s, mch, stemp[BUFSIZ];
3848207Smckusick
3858207Smckusick /* assume addr is a local address */
3868207Smckusick
3878207Smckusick strcpy(stemp,addr);
3888207Smckusick s = stemp;
3898207Smckusick while(*s){
3908207Smckusick if(*s == ':'){
3918207Smckusick fcolon = 1;
3928207Smckusick *s++ = 0;
3938207Smckusick break;
3948207Smckusick }
3958207Smckusick s++;
3968207Smckusick }
3978207Smckusick if(fcolon != 1){
3988207Smckusick /* sn better be the right size for addr */
3998207Smckusick mch = local;
4008207Smckusick strcpy(sn,addr);
4018207Smckusick return(mch);
4028207Smckusick }
4038207Smckusick
4048207Smckusick /* addr has a colon in it, s pts to name */
4058207Smckusick mch = lookup(stemp);
4068207Smckusick strcpy(sn,s);
4078207Smckusick return(mch);
4088207Smckusick }
4098207Smckusick
4108207Smckusick
4118207Smckusick /* returns a single character for machine S */
4128207Smckusick /* returns 0 for unknown host */
lookup(s)4138207Smckusick lookup(s)
4148207Smckusick register char *s; {
4158207Smckusick register struct tt *t;
4168207Smckusick if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s);
4178207Smckusick for(t = table; t->bigname; t++)
4188207Smckusick if(streql(s,t->bigname) == 0)return(t->lname);
4198207Smckusick return(0);
4208207Smckusick }
4218207Smckusick
4228207Smckusick /* returns a long name (string) for single character machine c */
longname(c)4238207Smckusick char *longname(c)
4248207Smckusick register char c;
4258207Smckusick {
4268207Smckusick register struct tt *t;
4278207Smckusick if(c == 0)return("UNKNOWN");
4288207Smckusick for(t = table; t->bigname; t++)
4298207Smckusick if(c == t->lname)return(t->bigname);
4308207Smckusick return("UNKNOWN");
4318207Smckusick }
4328207Smckusick /*
4338207Smckusick FMemberSCh(s,ch)
4348207Smckusick
4358207Smckusick return 1 if ch is a character in string s.
4368207Smckusick 0 otherwise.
4378207Smckusick */
FMemberSCh(s,ch)4388207Smckusick FMemberSCh(s,ch)
4398207Smckusick register char *s, ch;
4408207Smckusick {
4418207Smckusick while(*s)if(*s++ == ch)return(1);
4428207Smckusick return(0);
4438207Smckusick }
4448207Smckusick
4458207Smckusick /* return a static string with the form "X hrs X mins X secs" */
4468207Smckusick /* t is # of secs */
comptime(t)4478207Smckusick char *comptime(t)
4488207Smckusick long t; {
4498207Smckusick static char str[30];
4508207Smckusick char buf[20];
4518207Smckusick long w;
4528207Smckusick str[0] = 0;
4538207Smckusick w = t/3600L;
4548207Smckusick if(w > 0L){
4558207Smckusick sprintf(buf,"%ld hr ",w);
4568207Smckusick strcat(str,buf);
4578207Smckusick }
4588207Smckusick t = t % 3600L;
4598207Smckusick w = t/60L;
4608207Smckusick if(w > 0L){
4618207Smckusick sprintf(buf,"%ld min ",w);
4628207Smckusick strcat(str,buf);
4638207Smckusick }
4648207Smckusick t = t % 60L;
4658207Smckusick sprintf(buf,"%ld sec",t);
4668207Smckusick strcat(str,buf);
4678207Smckusick return(str);
4688207Smckusick }
4698207Smckusick /*
4708207Smckusick parseparmlist(string)
4718207Smckusick
4728207Smckusick parses variable parameter lists in string,
4738207Smckusick as defined in genparmlist in net.c
4748207Smckusick */
parseparmlist(parmlist)4758207Smckusick parseparmlist(parmlist)
4768207Smckusick char *parmlist;
4778207Smckusick {
4788207Smckusick while(*parmlist && *parmlist != '(')parmlist++;
4798207Smckusick }
4808207Smckusick
4818207Smckusick /* just like strcmp except upper- and lower-case are ignored */
streql(s1,s2)4828207Smckusick streql(s1,s2)
4838207Smckusick char *s1, *s2; {
4848207Smckusick char a,b;
4858207Smckusick while(*s1 && *s2){
4868207Smckusick a = isupper(*s1) ? tolower(*s1) : *s1;
4878207Smckusick b = isupper(*s2) ? tolower(*s2) : *s2;
4888207Smckusick if(a < b)return(-1);
4898207Smckusick if(a > b)return(1);
4908207Smckusick s1++, s2++;
4918207Smckusick }
4928207Smckusick if(*s2)return(-1);
4938207Smckusick if(*s1)return(1);
4948207Smckusick return(0);
4958207Smckusick }
4968207Smckusick /* VARARGS0 */
err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r)4978207Smckusick err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) {
4988207Smckusick fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
4998207Smckusick }
500