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