|
|
1.1 root 1: static char sccsid[] = "@(#)sub.c 4.5 (Berkeley) 1/5/83";
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.login[0]==0 || status.force){
94: buf[0] = 0;
95: wf = fopen("/dev/tty","r");
96: if(wf != NULL){
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: fclose(wf);
114: }
115: if(buf[0] == 0)strcpy(buf,status.localname);
116: mch = MchSFromAddr(status.login,buf);
117: if(mch != local && mch != mchto){
118: err("Must specify login name on %s machine\n",
119: longname(mchto));
120: exit(EX_USAGE);
121: }
122: }
123: if(strcmp(status.login,"network") != 0
124: && (status.mpasswd[0]== 0 || status.force)){
125: sprintf(buf,"Password (%s:%s):",
126: longname(mchto), status.login);
127: strcpy(status.mpasswd,getpass(buf));
128: }
129: if(status.login[0] == 0) strcpy(status.login,status.localname);
130: if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\"");
131: status.force = 0;
132: }
133:
134: #define tst(a,b) (*mode == 'r'? (b) : (a))
135: #define RDR 0
136: #define WTR 1
137: static int popen_pid[20];
138:
139: /* return a file descriptor suitable for writing, send to
140: user toaddress from fromaddress,
141: if cautious != 0 then don't do any forwarding
142: hopcnt is passed thru the mail program.
143: normal value is 0
144: */
145: FILE *
146: mailopen(toaddress, fromaddress, cautious, hopcnt)
147: char *toaddress, *fromaddress;
148: int cautious, hopcnt;
149: {
150: char cmd[100];
151: char *mode = "w";
152: int p[2];
153: register myside, hisside, pid;
154: char shopcnt[20];
155:
156: if(pipe(p) < 0)
157: return NULL;
158: myside = tst(p[WTR], p[RDR]);
159: hisside = tst(p[RDR], p[WTR]);
160: while((pid = fork()) == -1)sleep(2);
161: if(pid == 0) {
162: /* myside and hisside reverse roles in child */
163: close(myside);
164: /*
165: dup2(hisside, tst(0, 1));
166: */
167: close(0);
168: dup(hisside);
169: close(hisside);
170: sprintf(shopcnt,"%d",hopcnt);
171: if(fromaddress != NULL){
172: /* by convention, MAILFWD1 may forward this mail
173: and response messages shouldn't be forwarded */
174: if(!cautious && !FMemberSCh(toaddress,'/')){
175: # ifdef SENDMAIL
176: mexecl("/usr/lib/sendmail",
177: "sendmail", "-oee", "-r", fromaddress,
178: "-h",shopcnt, toaddress, 0);
179: # endif SENDMAIL
180: mexecl(MAILFWD1, "mail","-r",fromaddress,
181: "-h",shopcnt,toaddress,0);
182: }
183: mexecl(SYSMAIL2, "mail","-d","-r",fromaddress,
184: "-h", shopcnt,toaddress,0);
185: } else {
186: if(!cautious && !FMemberSCh(toaddress,'/')){
187: # ifdef SENDMAIL
188: mexecl("/usr/lib/sendmail",
189: "sendmail", "-ee", "-h", shopcnt,
190: toaddress, 0);
191: # endif
192: mexecl(MAILFWD1, "mail","-h", shopcnt,
193: toaddress,0);
194: }
195: mexecl(SYSMAIL2, "mail","-d","-h", shopcnt,toaddress,0);
196: }
197: perror(SYSMAIL2);
198: exit(EX_UNAVAILABLE);
199: }
200: if(pid == -1)
201: return NULL;
202: popen_pid[myside] = pid;
203: close(hisside);
204: return(fdopen(myside, mode));
205: }
206:
207: mailclose(ptr)
208: FILE *ptr;
209: {
210: register f, r, (*hstat)(), (*istat)(), (*qstat)();
211: int status;
212:
213: f = fileno(ptr);
214: fclose(ptr);
215: istat = signal(SIGINT, SIG_IGN);
216: qstat = signal(SIGQUIT, SIG_IGN);
217: hstat = signal(SIGHUP, SIG_IGN);
218: while((r = wait(&status)) != popen_pid[f] && r != -1)
219: ;
220: if(r == -1)
221: status = -1;
222: signal(SIGINT, istat);
223: signal(SIGQUIT, qstat);
224: signal(SIGHUP, hstat);
225: return(status);
226: }
227:
228: /*
229: ch means 'a'-'z', inx in 0..25
230: ch means '0'-'9', inx in 26..35
231: */
232: chtoinx(ch) {
233: if('a' <= ch && ch <= 'z')
234: return(ch - 'a');
235: if('0' <= ch && ch <= '9')
236: return((ch - '0') + 26);
237: err("bad ch");
238: }
239:
240: /*
241: inx is 0..25 means 'a'-'z'
242: inx is 26..35 means '0'-'9'
243: */
244: inxtoch(inx) {
245: if(0 <= inx && inx <= 25)
246: return(inx + 'a');
247: if(26 <= inx && inx <= 35)
248: return('0' + (inx - 26));
249: err("bad ch");
250: }
251:
252: /* determine through machine */
253: gothru(from,to){
254: register int i;
255: switch(from){
256: # ifdef RAND
257: case 'a': i = configA[chtoinx(to)]; break;
258: case 'b': i = configB[chtoinx(to)]; break;
259: case 'c': i = configC[chtoinx(to)]; break;
260: # endif
261: # ifdef NOSC
262: case 'a': i = configA[chtoinx(to)]; break;
263: case 'c': i = configC[chtoinx(to)]; break;
264: case 'm': i = configM[chtoinx(to)]; break;
265: # endif
266: # ifdef BERKELEY
267: /* for Berkeley */
268: case 'a': i = configA[chtoinx(to)]; break;
269: case 'b': i = configB[chtoinx(to)]; break;
270: case 'c': i = configC[chtoinx(to)]; break;
271: case 'd': i = configD[chtoinx(to)]; break;
272: case 'e': i = configE[chtoinx(to)]; break;
273: case 'f': i = configF[chtoinx(to)]; break;
274: case 'g': i = configG[chtoinx(to)]; break;
275: case 'h': i = configH[chtoinx(to)]; break;
276: case 'i': i = configI[chtoinx(to)]; break;
277: case 'j': i = configJ[chtoinx(to)]; break;
278: case 'k': i = configK[chtoinx(to)]; break;
279: case 'l': i = configL[chtoinx(to)]; break;
280: case 'm': i = configM[chtoinx(to)]; break;
281: case 'n': i = configN[chtoinx(to)]; break;
282: case 'o': i = configO[chtoinx(to)]; break;
283: case 'p': i = configP[chtoinx(to)]; break;
284: case 'r': i = configR[chtoinx(to)]; break;
285: case 's': i = configS[chtoinx(to)]; break;
286: case 't': i = configT[chtoinx(to)]; break;
287: case 'u': i = configU[chtoinx(to)]; break;
288: case 'v': i = configV[chtoinx(to)]; break;
289: case 'w': i = configW[chtoinx(to)]; break;
290: case 'x': i = configX[chtoinx(to)]; break;
291: case 'y': i = configY[chtoinx(to)]; break;
292: case 'z': i = configZ[chtoinx(to)]; break;
293: # endif
294: default: i = 0; break;
295: }
296: return(i);
297: }
298:
299: # define NPARMS 20
300: /* prints out commands before executing them */
301: /*VARARGS0*/
302: mexecl(va_alist)
303: va_dcl
304: {
305: char *arr[NPARMS], *file, *f;
306: va_list ap;
307: register int i;
308: va_start(ap);
309: file = va_arg(ap, char *);
310: i = 0;
311: while(f = va_arg(ap, char *)){
312: if(i >= NPARMS){
313: err("too many args");
314: arr[NPARMS-1] = NULL;
315: break;
316: }
317: if(debugflg) err("'%s' ",f);
318: arr[i++] = f;
319: }
320: arr[i] = NULL;
321: va_end(ap);
322: if(debugflg) putc('\n',stderr);
323: execv(file, arr);
324: }
325:
326: /* prints out commands before executing them */
327: mexecv(s,p)
328: register char *s, **p;{
329: register int i;
330: if(debugflg){
331: err("'%s' ",s);
332: for(i=0; p[i]; i++)err("'%s' ",p[i]);
333: putc('\n',stderr);
334: }
335: execv(s,p);
336: }
337:
338: /*VARARGS0*/
339: /* fills in -l - -p from commands like rcp */
340: /* must be called with at least two arguments */
341: kexecl(va_alist)
342: va_dcl
343: {
344: char *a[NPARMS], i = 1, *file;
345: va_list ap;
346: va_start(ap);
347: file = va_arg(ap, char *);
348: a[0] = va_arg(ap, char *);
349: if(status.login[0]){
350: a[i++] = "-l";
351: a[i++] = status.login;
352: }
353: if(status.mpasswd[0]){
354: a[i++] = "-p";
355: a[i++] = status.mpasswd;
356: }
357: if(status.nonotify)a[i++] = "-b";
358: if(status.force) a[i++] = "-f";
359: if(status.quiet) a[i++] = "-q";
360: if(status.nowrite) a[i++] = "-n";
361: while (a[i++] = va_arg(ap, char *)){
362: if(i >= NPARMS){
363: err("too many args");
364: a[NPARMS-1] = NULL;
365: break;
366: }
367: };
368: mexecv(file, a);
369: }
370:
371: /*
372: MchSFromAddr(sn,addr)
373:
374: take an address of the form "mach:username"
375: and return mch as the 1 char code of "mach" and
376: in sn put "username".
377: If addr has no colon in it, return mch==local, sn==addr.
378: Return 0 for mch if host unknown.
379: */
380: MchSFromAddr(sn,addr)
381: char *sn, *addr;
382: {
383: char fcolon = 0, *s, mch, stemp[BUFSIZ];
384:
385: /* assume addr is a local address */
386:
387: strcpy(stemp,addr);
388: s = stemp;
389: while(*s){
390: if(*s == ':'){
391: fcolon = 1;
392: *s++ = 0;
393: break;
394: }
395: s++;
396: }
397: if(fcolon != 1){
398: /* sn better be the right size for addr */
399: mch = local;
400: strcpy(sn,addr);
401: return(mch);
402: }
403:
404: /* addr has a colon in it, s pts to name */
405: mch = lookup(stemp);
406: strcpy(sn,s);
407: return(mch);
408: }
409:
410:
411: /* returns a single character for machine S */
412: /* returns 0 for unknown host */
413: lookup(s)
414: register char *s; {
415: register struct tt *t;
416: if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s);
417: for(t = table; t->bigname; t++)
418: if(streql(s,t->bigname) == 0)return(t->lname);
419: return(0);
420: }
421:
422: /* returns a long name (string) for single character machine c */
423: char *longname(c)
424: register char c;
425: {
426: register struct tt *t;
427: if(c == 0)return("UNKNOWN");
428: for(t = table; t->bigname; t++)
429: if(c == t->lname)return(t->bigname);
430: return("UNKNOWN");
431: }
432: /*
433: FMemberSCh(s,ch)
434:
435: return 1 if ch is a character in string s.
436: 0 otherwise.
437: */
438: FMemberSCh(s,ch)
439: register char *s, ch;
440: {
441: while(*s)if(*s++ == ch)return(1);
442: return(0);
443: }
444:
445: /* return a static string with the form "X hrs X mins X secs" */
446: /* t is # of secs */
447: char *comptime(t)
448: long t; {
449: static char str[30];
450: char buf[20];
451: long w;
452: str[0] = 0;
453: w = t/3600L;
454: if(w > 0L){
455: sprintf(buf,"%ld hr ",w);
456: strcat(str,buf);
457: }
458: t = t % 3600L;
459: w = t/60L;
460: if(w > 0L){
461: sprintf(buf,"%ld min ",w);
462: strcat(str,buf);
463: }
464: t = t % 60L;
465: sprintf(buf,"%ld sec",t);
466: strcat(str,buf);
467: return(str);
468: }
469: /*
470: parseparmlist(string)
471:
472: parses variable parameter lists in string,
473: as defined in genparmlist in net.c
474: */
475: parseparmlist(parmlist)
476: char *parmlist;
477: {
478: while(*parmlist && *parmlist != '(')parmlist++;
479: }
480:
481: /* just like strcmp except upper- and lower-case are ignored */
482: streql(s1,s2)
483: char *s1, *s2; {
484: char a,b;
485: while(*s1 && *s2){
486: a = isupper(*s1) ? tolower(*s1) : *s1;
487: b = isupper(*s2) ? tolower(*s2) : *s2;
488: if(a < b)return(-1);
489: if(a > b)return(1);
490: s1++, s2++;
491: }
492: if(*s2)return(-1);
493: if(*s1)return(1);
494: return(0);
495: }
496: /* VARARGS0 */
497: err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) {
498: fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
499: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.