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