|
|
1.1 root 1: /* $Header: util.c,v 4.3.1.2 85/05/15 14:44:27 lwall Exp $
2: *
3: * $Log: util.c,v $
4: * Revision 4.3.1.2 85/05/15 14:44:27 lwall
5: * Last arg of execl changed from 0 to Nullch [(char*)0].
6: *
7: * Revision 4.3.1.1 85/05/10 11:41:30 lwall
8: * Branch for patches.
9: *
10: * Revision 4.3 85/05/01 11:51:44 lwall
11: * Baseline for release with 4.3bsd.
12: *
13: */
14:
15: #include "EXTERN.h"
16: #include "common.h"
17: #include "final.h"
18: #include "ndir.h"
19: #include "INTERN.h"
20: #include "util.h"
21:
22: void
23: util_init()
24: {
25: ;
26: }
27:
28: /* fork and exec a shell command */
29:
30: int
31: doshell(shl,s)
32: char *s, *shl;
33: {
34: int status, pid, w;
35: register int (*istat)(), (*qstat)();
36: int (*signal())();
37: char *shell;
38:
39: #ifdef SIGTSTP
40: sigset(SIGTSTP,SIG_DFL);
41: sigset(SIGCONT,SIG_DFL);
42: #endif
43: if (shl != Nullch)
44: shell = shl;
45: else if ((shell = getenv("SHELL")) == Nullch || !*shell)
46: shell = PREFSHELL;
47: if ((pid = vfork()) == 0) {
48: if (*s)
49: execl(shell, shell, "-c", s, Nullch);
50: else
51: execl(shell, shell, Nullch, Nullch, Nullch);
52: _exit(127);
53: }
54: #ifndef lint
55: istat = signal(SIGINT, SIG_IGN);
56: qstat = signal(SIGQUIT, SIG_IGN);
57: #else
58: istat = Null(int (*)());
59: qstat = Null(int (*)());
60: #endif lint
61: waiting = TRUE;
62: while ((w = wait(&status)) != pid && w != -1)
63: ;
64: if (w == -1)
65: status = -1;
66: waiting = FALSE;
67: signal(SIGINT, istat);
68: signal(SIGQUIT, qstat);
69: #ifdef SIGTSTP
70: sigset(SIGTSTP,stop_catcher);
71: sigset(SIGCONT,cont_catcher);
72: #endif
73: return status;
74: }
75:
76: static char nomem[] = "rn: out of memory!\n";
77:
78: /* paranoid version of malloc */
79:
80: char *
81: safemalloc(size)
82: MEM_SIZE size;
83: {
84: char *ptr;
85: char *malloc();
86:
87: ptr = malloc(size?size:1); /* malloc(0) is NASTY on our system */
88: if (ptr != Nullch)
89: return ptr;
90: else {
91: fputs(nomem,stdout) FLUSH;
92: sig_catcher(0);
93: }
94: /*NOTREACHED*/
95: }
96:
97: /* paranoid version of realloc */
98:
99: char *
100: saferealloc(where,size)
101: char *where;
102: MEM_SIZE size;
103: {
104: char *ptr;
105: char *realloc();
106:
107: ptr = realloc(where,size?size:1); /* realloc(0) is NASTY on our system */
108: if (ptr != Nullch)
109: return ptr;
110: else {
111: fputs(nomem,stdout) FLUSH;
112: sig_catcher(0);
113: }
114: /*NOTREACHED*/
115: }
116:
117: /* safe version of string copy */
118:
119: char *
120: safecpy(to,from,len)
121: char *to;
122: register char *from;
123: register int len;
124: {
125: register char *dest = to;
126:
127: if (from != Nullch)
128: for (len--; len && (*dest++ = *from++); len--) ;
129: *dest = '\0';
130: return to;
131: }
132:
133: /* safe version of string concatenate, with \n deletion and space padding */
134:
135: char *
136: safecat(to,from,len)
137: char *to;
138: register char *from;
139: register int len;
140: {
141: register char *dest = to;
142:
143: len--; /* leave room for null */
144: if (*dest) {
145: while (len && *dest++) len--;
146: if (len) {
147: len--;
148: *(dest-1) = ' ';
149: }
150: }
151: if (from != Nullch)
152: while (len && (*dest++ = *from++)) len--;
153: if (len)
154: dest--;
155: if (*(dest-1) == '\n')
156: dest--;
157: *dest = '\0';
158: return to;
159: }
160:
161: /* copy a string up to some (non-backslashed) delimiter, if any */
162:
163: char *
164: cpytill(to,from,delim)
165: register char *to, *from;
166: register int delim;
167: {
168: for (; *from; from++,to++) {
169: if (*from == '\\' && from[1] == delim)
170: from++;
171: else if (*from == delim)
172: break;
173: *to = *from;
174: }
175: *to = '\0';
176: return from;
177: }
178:
179: /* return ptr to little string in big string, NULL if not found */
180:
181: char *
182: instr(big, little)
183: char *big, *little;
184:
185: {
186: register char *t, *s, *x;
187:
188: for (t = big; *t; t++) {
189: for (x=t,s=little; *s; x++,s++) {
190: if (!*x)
191: return Nullch;
192: if (*s != *x)
193: break;
194: }
195: if (!*s)
196: return t;
197: }
198: return Nullch;
199: }
200:
201: /* effective access */
202:
203: #ifdef SETUIDGID
204: int
205: eaccess(filename, mod)
206: char *filename;
207: int mod;
208: {
209: int protection, euid;
210:
211: mod &= 7; /* remove extraneous garbage */
212: if (stat(filename, &filestat) < 0)
213: return -1;
214: euid = geteuid();
215: if (euid == ROOTID)
216: return 0;
217: protection = 7 & (filestat.st_mode >>
218: (filestat.st_uid == euid ? 6 :
219: (filestat.st_gid == getegid() ? 3 : 0)
220: ));
221: if ((mod & protection) == mod)
222: return 0;
223: errno = EACCES;
224: return -1;
225: }
226: #endif
227:
228: /*
229: * Get working directory
230: */
231:
232: #ifdef GETWD
233: #define dot "."
234: #define dotdot ".."
235:
236: static char *name;
237:
238: static DIR *dirp;
239: static int off;
240: static struct stat d, dd;
241: static struct direct *dir;
242:
243: char *
244: getwd(np)
245: char *np;
246: {
247: long rdev, rino;
248:
249: *np++ = '/';
250: *np = 0;
251: name = np;
252: off = -1;
253: stat("/", &d);
254: rdev = d.st_dev;
255: rino = d.st_ino;
256: for (;;) {
257: stat(dot, &d);
258: if (d.st_ino==rino && d.st_dev==rdev)
259: goto done;
260: if ((dirp = opendir(dotdot)) == Null(DIR *))
261: prexit("getwd: cannot open ..\n");
262: stat(dotdot, &dd);
263: chdir(dotdot);
264: if(d.st_dev == dd.st_dev) {
265: if(d.st_ino == dd.st_ino)
266: goto done;
267: do
268: if ((dir = readdir(dirp)) == Null(struct direct *))
269: prexit("getwd: read error in ..\n");
270: while (dir->d_ino != d.st_ino);
271: }
272: else do {
273: if ((dir = readdir(dirp)) == Null(struct direct *))
274: prexit("getwd: read error in ..\n");
275: stat(dir->d_name, &dd);
276: } while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
277: cat();
278: closedir(dirp);
279: }
280: done:
281: name--;
282: if (chdir(name) < 0) {
283: printf("getwd: can't cd back to %s\n",name) FLUSH;
284: sig_catcher(0);
285: }
286: return (name);
287: }
288:
289: void
290: cat()
291: {
292: register i, j;
293:
294: i = -1;
295: while (dir->d_name[++i] != 0);
296: if ((off+i+2) > 1024-1)
297: return;
298: for(j=off+1; j>=0; --j)
299: name[j+i+1] = name[j];
300: if (off >= 0)
301: name[i] = '/';
302: off=i+off+1;
303: name[off] = 0;
304: for(--i; i>=0; --i)
305: name[i] = dir->d_name[i];
306: }
307:
308: void
309: prexit(cp)
310: char *cp;
311: {
312: write(2, cp, strlen(cp));
313: sig_catcher(0);
314: }
315: #else
316: char *
317: getwd(np) /* shorter but slower */
318: char *np;
319: {
320: FILE *popen();
321: FILE *pipefp = popen("/bin/pwd","r");
322:
323: if (pipefd == Nullfp) {
324: printf("Can't run /bin/pwd\n") FLUSH;
325: finalize(1);
326: }
327: fgets(np,512,pipefp);
328: np[strlen(np)-1] = '\0'; /* wipe out newline */
329: pclose(pipefp);
330: return np;
331: }
332: #endif
333:
334: /* just like fgets but will make bigger buffer as necessary */
335:
336: char *
337: get_a_line(original_buffer,buffer_length,fp)
338: char *original_buffer;
339: register int buffer_length;
340: FILE *fp;
341: {
342: register int bufix = 0;
343: register int nextch;
344: register char *some_buffer_or_other = original_buffer;
345:
346: do {
347: if (bufix >= buffer_length) {
348: buffer_length *= 2;
349: if (some_buffer_or_other == original_buffer) {
350: /* currently static? */
351: some_buffer_or_other = safemalloc((MEM_SIZE)buffer_length+1);
352: strncpy(some_buffer_or_other,original_buffer,buffer_length/2);
353: /* so we must copy it */
354: }
355: else { /* just grow in place, if possible */
356: some_buffer_or_other = saferealloc(some_buffer_or_other,
357: (MEM_SIZE)buffer_length+1);
358: }
359: }
360: if ((nextch = getc(fp)) == EOF)
361: return Nullch;
362: some_buffer_or_other[bufix++] = (char) nextch;
363: } while (nextch && nextch != '\n');
364: some_buffer_or_other[bufix] = '\0';
365: len_last_line_got = bufix;
366: return some_buffer_or_other;
367: }
368:
369: /* copy a string to a safe spot */
370:
371: char *
372: savestr(str)
373: char *str;
374: {
375: register char *newaddr = safemalloc((MEM_SIZE)(strlen(str)+1));
376:
377: strcpy(newaddr,str);
378: return newaddr;
379: }
380:
381: int
382: makedir(dirname,nametype)
383: register char *dirname;
384: int nametype;
385: {
386: #ifdef MAKEDIR
387: register char *end;
388: register char *s;
389: char tmpbuf[1024];
390: register char *tbptr = tmpbuf+5;
391:
392: for (end = dirname; *end; end++) ; /* find the end */
393: if (nametype == MD_FILE) { /* not to create last component? */
394: for (--end; end != dirname && *end != '/'; --end) ;
395: if (*end != '/')
396: return 0; /* nothing to make */
397: *end = '\0'; /* isolate file name */
398: }
399: strcpy(tmpbuf,"mkdir");
400:
401: s = end;
402: for (;;) {
403: if (stat(dirname,&filestat) >= 0) {
404: /* does this much exist? */
405: *s = '/'; /* mark this as existing */
406: break;
407: }
408: s = rindex(dirname,'/'); /* shorten name */
409: if (!s) /* relative path! */
410: break; /* hope they know what they are doing */
411: *s = '\0'; /* mark as not existing */
412: }
413:
414: for (s=dirname; s <= end; s++) { /* this is grody but efficient */
415: if (!*s) { /* something to make? */
416: sprintf(tbptr," %s",dirname);
417: tbptr += strlen(tbptr); /* make it, sort of */
418: *s = '/'; /* mark it made */
419: }
420: }
421: if (nametype == MD_DIR) /* don't need final slash unless */
422: *end = '\0'; /* a filename follows the dir name */
423:
424: return (tbptr==tmpbuf+5 ? 0 : doshell(sh,tmpbuf));
425: /* exercise our faith */
426: #else
427: sprintf(cmd_buf,"%s %s %d", filexp(DIRMAKER), dirname, nametype);
428: return doshell(sh,cmd_buf);
429: #endif
430: }
431:
432: #ifdef SETENV
433: static bool firstsetenv = TRUE;
434: extern char **environ;
435:
436: void
437: setenv(nam,val)
438: char *nam, *val;
439: {
440: register int i=envix(nam); /* where does it go? */
441:
442: if (!environ[i]) { /* does not exist yet */
443: if (firstsetenv) { /* need we copy environment? */
444: int j;
445: #ifndef lint
446: char **tmpenv = (char**) /* point our wand at memory */
447: safemalloc((MEM_SIZE) (i+2) * sizeof(char*));
448: #else
449: char **tmpenv = Null(char **);
450: #endif lint
451:
452: firstsetenv = FALSE;
453: for (j=0; j<i; j++) /* copy environment */
454: tmpenv[j] = environ[j];
455: environ = tmpenv; /* tell exec where it is now */
456: }
457: #ifndef lint
458: else
459: environ = (char**) saferealloc((char*) environ,
460: (MEM_SIZE) (i+2) * sizeof(char*));
461: /* just expand it a bit */
462: #endif lint
463: environ[i+1] = Nullch; /* make sure it's null terminated */
464: }
465: environ[i] = safemalloc((MEM_SIZE) strlen(nam) + strlen(val) + 2);
466: /* this may or may not be in */
467: /* the old environ structure */
468: sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
469: }
470:
471: int
472: envix(nam)
473: char *nam;
474: {
475: register int i, len = strlen(nam);
476:
477: for (i = 0; environ[i]; i++) {
478: if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
479: break; /* strnEQ must come first to avoid */
480: } /* potential SEGV's */
481: return i;
482: }
483: #endif
484:
485: void
486: notincl(feature)
487: char *feature;
488: {
489: printf("\nNo room for feature \"%s\" on this machine.\n",feature) FLUSH;
490: }
491:
492: char *
493: getval(nam,def)
494: char *nam,*def;
495: {
496: char *val;
497:
498: if ((val = getenv(nam)) == Nullch || !*val)
499: val = def;
500: return val;
501: }
502:
503: /* grow a static string to at least a certain length */
504:
505: void
506: growstr(strptr,curlen,newlen)
507: char **strptr;
508: int *curlen;
509: int newlen;
510: {
511: if (newlen > *curlen) { /* need more room? */
512: if (*curlen)
513: *strptr = saferealloc(*strptr,(MEM_SIZE)newlen);
514: else
515: *strptr = safemalloc((MEM_SIZE)newlen);
516: *curlen = newlen;
517: }
518: }
519:
520: void
521: setdef(buffer,dflt)
522: char *buffer,*dflt;
523: {
524: #ifdef STRICTCR
525: if (*buffer == ' ')
526: #else
527: if (*buffer == ' ' || *buffer == '\n')
528: #endif
529: {
530: if (*dflt == '^' && isupper(dflt[1]))
531: *buffer = Ctl(dflt[1]);
532: else
533: *buffer = *dflt;
534: }
535: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.