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: }