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