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