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