xref: /csrg-svn/old/berknet/sub.c (revision 8231)
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