BSD 4 development
[unix-history] / usr / src / cmd / berknet / sub.c
CommitLineData
442dbcf7
BJ
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 */
23int debugflg = DBV; /* debug flag */
24char local = LOCAL; /* the machine we're on */
25struct userinfo status;
26
27char netcmd[] = NETCMD;
28char resfile[] = RESFILE;
29char senddir[] = SENDDIR;
30char Bsh[] = BINSH;
31
32char 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*/
41passwdent()
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*/
68promptlogin(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
120static 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 */
128FILE *
129mailopen(toaddress, fromaddress, cautious, hopcnt)
130char *toaddress, *fromaddress;
131int 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
190mailclose(ptr)
191FILE *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 */
212gothru(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*/
265harg(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*/
278mexecl(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 */
290mexecv(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 */
304kexecl(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*/
337MchSFromAddr(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 */
370lookup(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 */
380char *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*/
395FMemberSCh(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 */
404char *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*/
432parseparmlist(parmlist)
433 char *parmlist;
434{
435 while(*parmlist && *parmlist != '(')parmlist++;
436}
437
438/* just like strcmp except upper- and lower-case are ignored */
439streql(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 */
454err(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 }