xref: /original-bsd/old/berknet/sub.c (revision c35f7ea3)
1 static char sccsid[] = "@(#)sub.c	4.3	(Berkeley)	10/03/82";
2 
3 /*
4 	sub.c
5 
6 	support procedures
7 
8 	the following procedures end up reading the passwd file
9 	or the passwdf file and are to be avoided.
10 
11 	getpwuid(uid)
12 	getpwnam(sn)
13 	PwdCurrent()
14 	getenv("HOME")		maybe if hget, hgethome don't work
15 	SnFromUid(uid)		maybe if hashed passwd stuff doesn't work
16 	SnCurrent()		maybe if getlogin fails calls SnFromUid(uid)
17 	getpwf()
18 	passwdent(uid,sn)
19 */
20 
21 # include "defs.h"
22 # include "config.h"
23 # include <varargs.h>
24 
25 /* global variables */
26 int debugflg = DBV;	/* debug flag */
27 char local = LOCAL;	/* the machine we're on */
28 struct userinfo status;
29 
30 char netcmd[]  =	NETCMD;
31 char resfile[] = 	RESFILE;
32 char senddir[] =	SENDDIR;
33 char Bsh[] =		BINSH;
34 
35 char shomedir[100];
36 
37 /*
38 	passwdent()
39 
40 	Read the password file looking for current user's entry.
41 	Fill in the status structure.
42 	Has the (dangerous) side effect of giving a value to getenv("HOME").
43 */
44 passwdent()
45 {
46 	register char *u;
47 	register struct passwd *pwd;
48 #ifdef CRN
49 	register struct gecos *gcos;
50 #endif
51 	pwd = PwdCurrent();
52 	if(pwd == NULL){
53 		err("Bad uid/username\n");
54 		return;
55 	}
56 	strcpy(status.localname,pwd->pw_name);
57 	status.muid = guid(pwd->pw_uid,pwd->pw_gid);
58 	status.mgid = pwd->pw_gid;
59 #ifdef CRN
60 	if( (gcos=pwgecos( pwd->pw_gecos) ) == NULL )
61 		strcpy( status.jobno, MAGICCRN );
62 	else {
63 		if( debugflg )
64 			debug( "crn found = %s\n", gcos->gc_crn );
65 		if( isalpha( gcos->gc_crn[0] ) ||
66 			isdigit( gcos->gc_crn[0] ) )
67 			strcpy( status.jobno, gcos->gc_crn );
68 		else
69 			strcpy( status.jobno, MAGICCRN );
70 	}
71 #else
72 	strcpy( status.jobno, "XYZZ" );
73 #endif
74 	strcpy(status.dir,pwd->pw_dir);
75 	strcpy(shomedir,pwd->pw_dir);		/* side effect */
76 	u = pwd->pw_shell;
77 	if(u[0] == 0 || strcmp(u,"/bin/sbash") == 0)u= Bsh;
78 	strcpy(status.loginshell,u);
79 	}
80 /*
81 	promptlogin(mchto)
82 
83 	ask user for login and passwd on mchto.
84 	make sure status.localname has a value before calling
85 	this.  One way is to call passwdent().
86 */
87 promptlogin(mchto)
88 	char mchto;
89 {
90 	char buf[BUFSIZ], mch;
91 	FILE *wf;
92 	int c;
93 	if(status.mpasswd[0] == 0 || status.login[0] == 0 || status.force){
94 		wf = fopen("/dev/tty","r");
95 		if(wf != NULL){
96 			if(status.login[0]==0 || status.force){
97 				fprintf(stderr,"Name (%s:%s): ",longname(mchto),
98 					status.localname);
99 				if(fgets(buf, BUFSIZ, wf) != buf){
100 					perror("fgets");
101 					exit(EX_OSERR);
102 					}
103 				c = strlen(buf);
104 				buf[c > 0 ? c-1 : 0] = 0;
105 				if(c > 10){
106 					err("Login name too long.\n");
107 					exit(EX_USAGE);
108 					}
109 				if(FMemberSCh(buf,' ')){
110 					err("Login names don't have blanks in them.\n");
111 					exit(EX_USAGE);
112 					}
113 				if(buf[0] == 0)strcpy(buf,status.localname);
114 				mch = MchSFromAddr(status.login,buf);
115 				if(mch != local && mch != mchto){
116 					err(
117 				"Must specify login name on %s machine\n",
118 						longname(mchto));
119 					exit(EX_USAGE);
120 				}
121 			}
122 			if(strcmp(status.login,"network") != 0
123 				&& (status.mpasswd[0]== 0 || status.force)){
124 				sprintf(buf,"Password (%s:%s):",
125 					longname(mchto), status.login);
126 				strcpy(status.mpasswd,getpass(buf));
127 				}
128 			fclose(wf);
129 			}
130 		}
131 	if(status.login[0] == 0) strcpy(status.login,status.localname);
132 	if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\"");
133 	status.force = 0;
134 	}
135 
136 #define	tst(a,b)	(*mode == 'r'? (b) : (a))
137 #define	RDR	0
138 #define	WTR	1
139 static	int	popen_pid[20];
140 
141 /* return a file descriptor suitable for writing, send to
142   user toaddress from fromaddress,
143   if cautious != 0 then don't do any forwarding
144   hopcnt is passed thru the mail program.
145 	  normal value is 0
146   */
147 FILE *
148 mailopen(toaddress, fromaddress, cautious, hopcnt)
149 char *toaddress, *fromaddress;
150 int cautious, hopcnt;
151 {
152 	char	cmd[100];
153 	char	*mode = "w";
154 	int p[2];
155 	register myside, hisside, pid;
156 	char shopcnt[20];
157 
158 	if(pipe(p) < 0)
159 		return NULL;
160 	myside = tst(p[WTR], p[RDR]);
161 	hisside = tst(p[RDR], p[WTR]);
162 	while((pid = fork()) == -1)sleep(2);
163 	if(pid == 0) {
164 		/* myside and hisside reverse roles in child */
165 		close(myside);
166 		/*
167 		dup2(hisside, tst(0, 1));
168 		*/
169 		close(0);
170 		dup(hisside);
171 		close(hisside);
172 		sprintf(shopcnt,"%d",hopcnt);
173 		if(fromaddress != NULL){
174 			/* by convention, MAILFWD1 may forward this mail
175 			   and response messages shouldn't be forwarded */
176 			if(!cautious && !FMemberSCh(toaddress,'/')){
177 # ifdef DELIVERM
178 				mexecl("/etc/delivermail",
179 					"delivermail", "-ee", "-r", fromaddress,
180 					"-h",shopcnt, toaddress, 0);
181 # endif
182 				mexecl(MAILFWD1, "mail","-r",fromaddress,
183 					"-h",shopcnt,toaddress,0);
184 			}
185 			mexecl(SYSMAIL2, "mail","-d","-r",fromaddress,
186 				"-h", shopcnt,toaddress,0);
187 		} else {
188 			if(!cautious && !FMemberSCh(toaddress,'/')){
189 # ifdef DELIVERM
190 				mexecl("/etc/delivermail",
191 					"delivermail", "-ee", "-h", shopcnt,
192 					toaddress, 0);
193 # endif
194 				mexecl(MAILFWD1, "mail","-h", shopcnt,
195 					toaddress,0);
196 			}
197 			mexecl(SYSMAIL2, "mail","-d","-h", shopcnt,toaddress,0);
198 		}
199 		perror(SYSMAIL2);
200 		exit(EX_UNAVAILABLE);
201 	}
202 	if(pid == -1)
203 		return NULL;
204 	popen_pid[myside] = pid;
205 	close(hisside);
206 	return(fdopen(myside, mode));
207 }
208 
209 mailclose(ptr)
210 FILE *ptr;
211 {
212 	register f, r, (*hstat)(), (*istat)(), (*qstat)();
213 	int status;
214 
215 	f = fileno(ptr);
216 	fclose(ptr);
217 	istat = signal(SIGINT, SIG_IGN);
218 	qstat = signal(SIGQUIT, SIG_IGN);
219 	hstat = signal(SIGHUP, SIG_IGN);
220 	while((r = wait(&status)) != popen_pid[f] && r != -1)
221 		;
222 	if(r == -1)
223 		status = -1;
224 	signal(SIGINT, istat);
225 	signal(SIGQUIT, qstat);
226 	signal(SIGHUP, hstat);
227 	return(status);
228 }
229 
230 /*
231 	ch means 'a'-'z', inx in 0..25
232 	ch means '0'-'9', inx in 26..35
233 */
234 chtoinx(ch) {
235 	if('a' <= ch && ch <= 'z')
236 		return(ch - 'a');
237 	if('0' <= ch && ch <= '9')
238 		return((ch - '0') + 26);
239 	err("bad ch");
240 }
241 
242 /*
243 	inx is 0..25 means 'a'-'z'
244 	inx is 26..35 means '0'-'9'
245 */
246 inxtoch(inx) {
247 	if(0 <= inx && inx <= 25)
248 		return(inx + 'a');
249 	if(26 <= inx && inx <= 35)
250 		return('0' + (inx - 26));
251 	err("bad ch");
252 }
253 
254 /* determine through machine */
255 gothru(from,to){
256 	register int i;
257 	switch(from){
258 # ifdef RAND
259 	case 'a':	i = configA[chtoinx(to)]; break;
260 	case 'b':	i = configB[chtoinx(to)]; break;
261 	case 'c':	i = configC[chtoinx(to)]; break;
262 # endif
263 # ifdef NOSC
264 	case 'a':	i = configA[chtoinx(to)]; break;
265 	case 'c':	i = configC[chtoinx(to)]; break;
266 	case 'm':	i = configM[chtoinx(to)]; break;
267 # endif
268 # ifdef BERKELEY
269 	/* for Berkeley */
270 	case 'a':	i = configA[chtoinx(to)]; break;
271 	case 'b':	i = configB[chtoinx(to)]; break;
272 	case 'c':	i = configC[chtoinx(to)]; break;
273 	case 'd':	i = configD[chtoinx(to)]; break;
274 	case 'e':	i = configE[chtoinx(to)]; break;
275 	case 'f':	i = configF[chtoinx(to)]; break;
276 	case 'g':	i = configG[chtoinx(to)]; break;
277 	case 'h':	i = configH[chtoinx(to)]; break;
278 	case 'i':	i = configI[chtoinx(to)]; break;
279 	case 'j':	i = configJ[chtoinx(to)]; break;
280 	case 'k':	i = configK[chtoinx(to)]; break;
281 	case 'l':	i = configL[chtoinx(to)]; break;
282 	case 'm':	i = configM[chtoinx(to)]; break;
283 	case 'n':	i = configN[chtoinx(to)]; break;
284 	case 'o':	i = configO[chtoinx(to)]; break;
285 	case 'p':	i = configP[chtoinx(to)]; break;
286 	case 'r':	i = configR[chtoinx(to)]; break;
287 	case 's':	i = configS[chtoinx(to)]; break;
288 	case 't':	i = configT[chtoinx(to)]; break;
289 	case 'u':	i = configU[chtoinx(to)]; break;
290 	case 'v':	i = configV[chtoinx(to)]; break;
291 	case 'w':	i = configW[chtoinx(to)]; break;
292 	case 'x':	i = configX[chtoinx(to)]; break;
293 	case 'y':	i = configY[chtoinx(to)]; break;
294 	case 'z':	i = configZ[chtoinx(to)]; break;
295 # endif
296 	default:	i = 0; break;
297 	}
298 	return(i);
299 	}
300 
301 # define NPARMS 20
302 /* prints out commands before executing them */
303 /*VARARGS0*/
304 mexecl(va_alist)
305   	va_dcl
306 {
307 	char *arr[NPARMS], *file, *f;
308 	va_list ap;
309 	register int i;
310 	va_start(ap);
311 	file = va_arg(ap, char *);
312 	i = 0;
313 	while(f = va_arg(ap, char *)){
314 		if(i >= NPARMS){
315 			err("too many args");
316 			arr[NPARMS-1] = NULL;
317 			break;
318 			}
319 		if(debugflg) err("'%s' ",f);
320 		arr[i++] = f;
321 		}
322 	arr[i] = NULL;
323 	va_end(ap);
324 	if(debugflg) putc('\n',stderr);
325 	execv(file, arr);
326 	}
327 
328 /* prints out commands before executing them */
329 mexecv(s,p)
330   register char *s, **p;{
331 	register int i;
332 	if(debugflg){
333 		err("'%s' ",s);
334 		for(i=0; p[i]; i++)err("'%s' ",p[i]);
335 		putc('\n',stderr);
336 		}
337 	execv(s,p);
338 	}
339 
340 /*VARARGS0*/
341 /* fills in -l - -p from commands like rcp */
342 /* must be called with at least two arguments */
343 kexecl(va_alist)
344   va_dcl
345 {
346 	char *a[NPARMS], i = 1, *file;
347 	va_list ap;
348 	va_start(ap);
349 	file = va_arg(ap, char *);
350 	a[0] = va_arg(ap, char *);
351 	if(status.login[0]){
352 		a[i++] = "-l";
353 		a[i++] = status.login;
354 		}
355 	if(status.mpasswd[0]){
356 		a[i++] = "-p";
357 		a[i++] = status.mpasswd;
358 		}
359 	if(status.nonotify)a[i++] = "-b";
360 	if(status.force)   a[i++] = "-f";
361 	if(status.quiet)   a[i++] = "-q";
362 	if(status.nowrite) a[i++] = "-n";
363 	while (a[i++] = va_arg(ap, char *)){
364 		if(i >= NPARMS){
365 			err("too many args");
366 			a[NPARMS-1] = NULL;
367 			break;
368 			}
369 		};
370 	mexecv(file, a);
371 	}
372 
373 /*
374 	MchSFromAddr(sn,addr)
375 
376 	take an address of the form "mach:username"
377 	and return mch as the 1 char code of "mach" and
378 	in sn put "username".
379 	If addr has no colon in it, return mch==local, sn==addr.
380 	Return 0 for mch if host unknown.
381 */
382 MchSFromAddr(sn,addr)
383 	char *sn, *addr;
384 {
385 	char fcolon = 0, *s, mch, stemp[BUFSIZ];
386 
387 	/* assume addr is a local address */
388 
389 	strcpy(stemp,addr);
390 	s = stemp;
391 	while(*s){
392 		if(*s == ':'){
393 			fcolon = 1;
394 			*s++ = 0;
395 			break;
396 		}
397 		s++;
398 	}
399 	if(fcolon != 1){
400 		/* sn better be the right size for addr */
401 		mch = local;
402 		strcpy(sn,addr);
403 		return(mch);
404 	}
405 
406 	/* addr has a colon in it, s pts to name */
407 	mch = lookup(stemp);
408 	strcpy(sn,s);
409 	return(mch);
410 }
411 
412 
413 /* returns a single character for machine S */
414 /* returns 0 for unknown host */
415 lookup(s)
416   register char *s; {
417 	register struct tt *t;
418 	if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s);
419 	for(t = table; t->bigname; t++)
420 		if(streql(s,t->bigname) == 0)return(t->lname);
421 	return(0);
422 	}
423 
424 /* returns a long name (string) for single character machine c */
425 char *longname(c)
426   register char c;
427 	{
428 	register struct tt *t;
429 	if(c == 0)return("UNKNOWN");
430 	for(t = table; t->bigname; t++)
431 		if(c == t->lname)return(t->bigname);
432 	return("UNKNOWN");
433 	}
434 /*
435 	FMemberSCh(s,ch)
436 
437 	return 1 if ch is a character in string s.
438 	0 otherwise.
439 */
440 FMemberSCh(s,ch)
441 	register char *s, ch;
442 {
443 	while(*s)if(*s++ == ch)return(1);
444 	return(0);
445 }
446 
447 /* return a static string with the form "X hrs X mins X secs" */
448 /* t is # of secs */
449 char *comptime(t)
450   long t; {
451 	static char str[30];
452 	char buf[20];
453 	long w;
454 	str[0] = 0;
455 	w = t/3600L;
456 	if(w > 0L){
457 		sprintf(buf,"%ld hr ",w);
458 		strcat(str,buf);
459 		}
460 	t = t % 3600L;
461 	w = t/60L;
462 	if(w > 0L){
463 		sprintf(buf,"%ld min ",w);
464 		strcat(str,buf);
465 		}
466 	t = t % 60L;
467 	sprintf(buf,"%ld sec",t);
468 	strcat(str,buf);
469 	return(str);
470 	}
471 /*
472 	parseparmlist(string)
473 
474 	parses variable parameter lists in string,
475 	as defined in genparmlist in net.c
476 */
477 parseparmlist(parmlist)
478 	char *parmlist;
479 {
480 	while(*parmlist && *parmlist != '(')parmlist++;
481 }
482 
483 /* just like strcmp except upper- and lower-case are ignored */
484 streql(s1,s2)
485   char *s1, *s2; {
486 	char a,b;
487 	while(*s1 && *s2){
488 		a = isupper(*s1) ? tolower(*s1) : *s1;
489 		b = isupper(*s2) ? tolower(*s2) : *s2;
490 		if(a < b)return(-1);
491 		if(a > b)return(1);
492 		s1++, s2++;
493 		}
494 	if(*s2)return(-1);
495 	if(*s1)return(1);
496 	return(0);
497 	}
498 /* VARARGS0 */
499 err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) {
500 	fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
501 	}
502