|
|
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: int debugflg = DBV; /* debug flag */
23: char local = LOCAL; /* the machine we're on */
24:
25: char netcmd[] = NETCMD;
26: char resfile[] = RESFILE;
27: char senddir[] = SENDDIR;
28: char Bsh[] = BINSH;
29:
30: char shomedir[BUFSIZ];
31:
32: /*
33: passwdent()
34:
35: Read the password file looking for current user's entry.
36: Fill in the status structure.
37: Has the (dangerous) side effect of giving a value to getenv("HOME").
38: */
39: passwdent()
40: {
41: register char *u;
42: register struct passwd *pwd;
43: pwd = PwdCurrent();
44: if(pwd == NULL){
45: err("Bad uid/username\n");
46: return;
47: }
48: strcpy(status.localname,pwd->pw_name);
49: status.muid = guid(pwd->pw_uid,pwd->pw_gid);
50: status.mgid = pwd->pw_gid;
51: if(isdigit(pwd->pw_gecos[0]))status.jobno = atoi(pwd->pw_gecos);
52: else status.jobno = 32767;
53: strcpy(status.dir,pwd->pw_dir);
54: strcpy(shomedir,pwd->pw_dir); /* side effect */
55: u = pwd->pw_shell;
56: if(u[0] == 0)u= Bsh;
57: strcpy(status.loginshell,u);
58: }
59: /*
60: promptlogin(mchto)
61:
62: ask user for login and passwd on mchto.
63: make sure status.localname has a value before calling
64: this. One way is to call passwdent(), another is to
65: strcpy(status.localname,SnCurrent()).
66: */
67: promptlogin(mchto)
68: char mchto;
69: {
70: char buf[BUFSIZ], mch;
71: FILE *wf;
72: int c;
73: if(status.mpasswd[0] == 0 || status.login[0] == 0 || status.force){
74: wf = fopen("/dev/tty","r");
75: if(wf != NULL){
76: if(status.login[0]==0 || status.force){
77: printf("Name (%s:%s): ",longname(mchto),
78: status.localname);
79: if(fgets(buf, BUFSIZ, wf) != buf){
80: perror("fgets");
81: exit(1);
82: }
83: c = strlen(buf);
84: buf[c > 0 ? c-1 : 0] = 0;
85: if(c > 10){
86: err("Login name too long.\n");
87: exit(1);
88: }
89: if(FMemberSCh(buf,' ')){
90: err("Login names don't have blanks in them.\n");
91: exit(1);
92: }
93: if(buf[0] == 0)strcpy(buf,status.localname);
94: mch = MchSFromAddr(status.login,buf);
95: if(mch != local && mch != mchto){
96: err(
97: "Must specify login name on %s machine\n",
98: longname(mchto));
99: exit(1);
100: }
101: }
102: if(strcmp(status.login,"network") != 0
103: && (status.mpasswd[0]== 0 || status.force)){
104: sprintf(buf,"Password (%s:%s):",
105: longname(mchto), status.login);
106: strcpy(status.mpasswd,getpass(buf));
107: }
108: fclose(wf);
109: }
110: }
111: if(status.login[0] == 0) strcpy(status.login,status.localname);
112: if(status.mpasswd[0] == 0)strcpy(status.mpasswd,"\"\"");
113: status.force = 0;
114: }
115:
116: /* determine through machine */
117: gothru(from,to){
118: register int i;
119: switch(from){
120: case 'a': i = configA[to-'a']; break;
121: case 'b': i = configB[to-'a']; break;
122: case 'c': i = configC[to-'a']; break;
123: case 'd': i = configD[to-'a']; break;
124: case 'e': i = configE[to-'a']; break;
125: case 'f': i = configF[to-'a']; break;
126: case 'i': i = configI[to-'a']; break;
127: case 'j': i = configJ[to-'a']; break;
128: case 'm': i = configM[to-'a']; break;
129: case 'o': i = configO[to-'a']; break;
130: case 'q': i = configQ[to-'a']; break;
131: case 's': i = configS[to-'a']; break;
132: case 'v': i = configV[to-'a']; break;
133: case 'y': i = configY[to-'a']; break;
134: case 'z': i = configZ[to-'a']; break;
135: default: i = 0; break;
136: }
137: return(i);
138: }
139: /*
140: harg(string,pargc,pargv)
141:
142: A curious procedure which takes a pointer to an argc, and a
143: pointer to an argv, and parses them so that the
144: argument following the flag is copied into string.
145: pargv[0] must be the flag argument.
146: handles both
147: -my
148: and
149: -m y
150: for the net command.
151: */
152: harg(ans,pargc,pargv)
153: char *ans,*pargc,***pargv;{
154: if((*pargv)[0][2]) /* no space */
155: strcpy(ans,(*pargv)[0] + 2);
156: else { /* space, get next arg */
157: strcpy(ans,(*pargv)[1]);
158: (*pargc)--;
159: (*pargv)++;
160: }
161: }
162:
163: /* prints out commands before executing them */
164: /*VARARGS0*/
165: mexecl(s)
166: char *s;{
167: int *p = (int *)&s;
168: register int i;
169: if(debugflg){
170: for(i=0; p[i]; i++)err("%s ",p[i]);
171: putc('\n',stderr);
172: }
173: 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],
174: p[12],p[13],p[14],p[15],0);
175: perror(p[0]);
176: }
177: /* prints out commands before executing them */
178: mexecv(s,p)
179: register char *s, **p;{
180: register int i;
181: if(debugflg){
182: err("%s ",s);
183: for(i=0; p[i]; i++)err("%s ",p[i]);
184: putc('\n',stderr);
185: }
186: execv(s,p);
187: perror(s);
188: }
189:
190: /*VARARGS0*/
191: /* fills in -l - -p from commands like rcp */
192: /* must be called with at least two arguments */
193: kexecl(s)
194: char *s; {
195: char *a[20], i = 2, j = 2;
196: char **p = (char **)&s;
197: a[0] = p[0];
198: a[1] = p[1];
199: if(status.login[0]){
200: a[i++] = "-l";
201: a[i++] = status.login;
202: }
203: if(status.mpasswd[0]){
204: a[i++] = "-p";
205: a[i++] = status.mpasswd;
206: }
207: if(status.nonotify)a[i++] = "-b";
208: if(status.force) a[i++] = "-f";
209: if(status.quiet) a[i++] = "-q";
210: if(status.nowrite) a[i++] = "-n";
211: while(p[j])a[i++] = p[j++];
212: a[i] = 0;
213: 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],
214: a[12],a[13],a[14],a[15],0);
215: }
216:
217: /*
218: MchSFromAddr(sn,addr)
219:
220: take an address of the form "mach:username"
221: and return mch as the 1 char code of "mach" and
222: in sn put "username".
223: If addr has no colon in it, return mch==local, sn==addr.
224: */
225: MchSFromAddr(sn,addr)
226: char *sn, *addr;
227: {
228: char fcolon = 0, *s, mch, stemp[BUFSIZ];
229:
230: /* assume addr is a local address */
231:
232: strcpy(stemp,addr);
233: s = stemp;
234: while(*s){
235: if(*s == ':'){
236: fcolon = 1;
237: *s++ = 0;
238: break;
239: }
240: s++;
241: }
242: if(fcolon != 1){
243: /* sn better be the right size for addr */
244: mch = local;
245: strcpy(sn,addr);
246: return(mch);
247: }
248:
249: /* addr has a colon in it, s pts to name */
250: mch = lookup(stemp);
251: strcpy(sn,s);
252: return(mch);
253: }
254:
255:
256: /* returns a single character for machine S */
257: lookup(s)
258: register char *s; {
259: register struct tt *t;
260: if(strlen(s) == 1)return(isupper(*s) ? tolower(*s) : *s);
261: for(t = table; t->bigname; t++)
262: if(streql(s,t->bigname) == 0)return(t->lname);
263: return(0);
264: }
265:
266: /* returns a long name (string) for single character machine c */
267: char *longname(c)
268: register char c;
269: {
270: register struct tt *t;
271: if(c == 0)return("UNKNOWN");
272: for(t = table; t->bigname; t++)
273: if(c == t->lname)return(t->bigname);
274: return("UNKNOWN");
275: }
276: /*VARARGS0*/
277: debug(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t)
278: char *s; {
279: if(debugflg){
280: printf(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,t);
281: putchar('\n');
282: }
283: }
284:
285: /*
286: FMemberSCh(s,ch)
287:
288: return 1 if ch is a character in string s.
289: 0 otherwise.
290: */
291: FMemberSCh(s,ch)
292: register char *s, ch;
293: {
294: while(*s)if(*s++ == ch)return(1);
295: return(0);
296: }
297:
298: /* return a static string with the form "X hrs X mins X secs" */
299: /* t is # of secs */
300: char *comptime(t)
301: long t; {
302: static char str[30];
303: char buf[20];
304: long w;
305: str[0] = 0;
306: w = t/3600L;
307: if(w > 0L){
308: sprintf(buf,"%ld hr ",w);
309: strcat(str,buf);
310: }
311: t = t % 3600L;
312: w = t/60L;
313: if(w > 0L){
314: sprintf(buf,"%ld min ",w);
315: strcat(str,buf);
316: }
317: t = t % 60L;
318: sprintf(buf,"%ld sec",t);
319: strcat(str,buf);
320: return(str);
321: }
322: /*
323: parseparmlist(string)
324:
325: parses variable parameter lists in string,
326: as defined in genparmlist in net.c
327: */
328: parseparmlist(parmlist)
329: char *parmlist;
330: {
331: while(*parmlist && *parmlist != '(')parmlist++;
332: }
333:
334: /*
335: PwdCurrent()
336:
337: Read the password file and return pwd to
338: entry for current user.
339: Return NULL if error.
340:
341: This code is a little screwed up because of the conventions
342: regarding the state of the utmp file after someone su's--
343: either to root or to another person.
344: The final decision was to return getpwuid(getuid) if
345: the machine has one login name per userid,
346: and if there are multiple login names per userid, to
347: search the passwd file for the getlogin() name and return
348: the passwd file entry for that.
349: If there is no utmp entry, just use the userid.
350: This means that people who su on machine with multiple
351: user-id's will get the passwd entry for the account recorded
352: in the utmp file, not their current userid.
353: */
354: struct passwd *
355: PwdCurrent()
356: {
357: register struct passwd *pwd;
358: register char *sn;
359:
360: # ifdef MULTNAMS
361: sn = getlogin();
362: if(sn != NULL && sn[0] != 0 && sn[0] != ' '){
363: pwd = getpwnam(sn);
364: if(pwd != NULL)return(pwd);
365: }
366: # endif
367:
368: return(getpwuid(uidmask(getuid())));
369: }
370: /*
371: SnCurrent()
372:
373: Return the name of the current user.
374: If not in the /etc/utmp file, will read the passwd file.
375: Returns NULL if error.
376: Note that detached processes on V7 have getlogin() return
377: a pointer to a null string, not NULL.
378: */
379: char *SnCurrent()
380: {
381: static char snBuf[NS];
382: register char *sn;
383:
384: sn = getlogin();
385: if(sn == NULL || sn[0] == 0 || sn[0] == ' ')
386: sn = SnFromUid(getuid());
387: if(sn != NULL){
388: strcpy(snBuf,sn);
389: sn = snBuf;
390: }
391: return(sn);
392: }
393: /* just like strcmp except upper- and lower-case are ignored */
394: streql(s1,s2)
395: char *s1, *s2; {
396: char a,b;
397: while(*s1 && *s2){
398: a = isupper(*s1) ? tolower(*s1) : *s1;
399: b = isupper(*s2) ? tolower(*s2) : *s2;
400: if(a < b)return(-1);
401: if(a > b)return(1);
402: s1++, s2++;
403: }
404: if(*s2)return(-1);
405: if(*s1)return(1);
406: return(0);
407: }
408: /* VARARGS0 */
409: err(s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r) {
410: fprintf(stderr,s,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r);
411: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.