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