make it all work....
[unix-history] / usr / src / old / berknet / sub.c
CommitLineData
0c4520bd 1static char sccsid[] = "@(#)sub.c 4.4 (Berkeley) %G%";
2a56de55
KM
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"
2a56de55 23# include <varargs.h>
2a56de55
KM
24
25/* global variables */
26int debugflg = DBV; /* debug flag */
27char local = LOCAL; /* the machine we're on */
28struct userinfo status;
29
30char netcmd[] = NETCMD;
31char resfile[] = RESFILE;
32char senddir[] = SENDDIR;
33char Bsh[] = BINSH;
34
35char 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*/
44passwdent()
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*/
87promptlogin(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
139static 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 */
147FILE *
148mailopen(toaddress, fromaddress, cautious, hopcnt)
149char *toaddress, *fromaddress;
150int 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
209mailclose(ptr)
210FILE *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*/
234chtoinx(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*/
246inxtoch(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 */
255gothru(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;
0b4e7efb 277 case 'h': i = configH[chtoinx(to)]; break;
2a56de55
KM
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;
2a56de55
KM
286 case 'r': i = configR[chtoinx(to)]; break;
287 case 's': i = configS[chtoinx(to)]; break;
288 case 't': i = configT[chtoinx(to)]; break;
0b4e7efb 289 case 'u': i = configU[chtoinx(to)]; break;
2a56de55 290 case 'v': i = configV[chtoinx(to)]; break;
0b4e7efb 291 case 'w': i = configW[chtoinx(to)]; break;
2a56de55
KM
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*/
304mexecl(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 */
329mexecv(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 */
343kexecl(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*/
382MchSFromAddr(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 */
415lookup(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 */
425char *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*/
440FMemberSCh(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 */
449char *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*/
477parseparmlist(parmlist)
478 char *parmlist;
479{
480 while(*parmlist && *parmlist != '(')parmlist++;
481}
482
483/* just like strcmp except upper- and lower-case are ignored */
484streql(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 */
499err(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 }