|
|
1.1 ! root 1: /* ! 2: * command history ! 3: * ! 4: * only implements in-memory history. ! 5: */ ! 6: ! 7: static char *RCSid = "$Header: history.c,v 3.1 88/11/03 09:16:05 egisin Exp $"; ! 8: ! 9: #include <stddef.h> ! 10: #include <stdio.h> ! 11: #include <string.h> ! 12: #include <errno.h> ! 13: #include <setjmp.h> ! 14: #include "sh.h" ! 15: #include "lex.h" ! 16: ! 17: char **histget(); ! 18: char *histrpl(); ! 19: ! 20: c_fc(wp) ! 21: register char **wp; ! 22: { ! 23: register char *id; ! 24: FILE *f; ! 25: struct temp *tf; ! 26: register char **hp; ! 27: char **hbeg, **hend; ! 28: int lflag = 0, nflag = 0, sflag = 0; ! 29: ! 30: for (wp++; (id = *wp) != NULL && *id == '-' && !sflag; wp++) ! 31: switch (id[1]) { ! 32: case 'l': ! 33: lflag++; ! 34: break; ! 35: case 'n': ! 36: nflag++; ! 37: break; ! 38: case 's': ! 39: sflag++; ! 40: break; ! 41: } ! 42: ! 43: /* fc -s [pat=rep] [cmd], equivalent to Korn's fc -e - [pat=rep] */ ! 44: if (sflag) { ! 45: char *pat = NULL, *rep = NULL; ! 46: ! 47: hp = histptr - 1; ! 48: while ((id = *wp++) != NULL) ! 49: /* todo: multiple substitutions */ ! 50: if ((rep = strchr(id, '=')) != NULL) { ! 51: pat = id; ! 52: *rep++ = '\0'; ! 53: } else ! 54: hp = histget(id); ! 55: ! 56: if (hp == NULL || hp < history) ! 57: errorf("cannot find history\n"); ! 58: if (pat == NULL) ! 59: strcpy(line, *hp); ! 60: else ! 61: histrpl(*hp, pat, rep); ! 62: histsave(line); ! 63: histpush--; ! 64: line[0] = '\0'; ! 65: return 0; ! 66: } ! 67: ! 68: if (*wp != NULL) { ! 69: hbeg = histget(*wp++); /* first */ ! 70: if (*wp != NULL) ! 71: hend = histget(*wp++); /* last */ ! 72: else ! 73: hend = hbeg; ! 74: } else { ! 75: if (lflag) ! 76: hbeg = histptr - 12, hend = histptr; ! 77: else ! 78: hbeg = hend = histptr - 1; ! 79: if (hbeg < history) ! 80: hbeg = history; ! 81: } ! 82: if (hbeg == NULL || hend == NULL) ! 83: errorf("can't find history\n"); ! 84: ! 85: if (lflag) ! 86: f = stdout; ! 87: else { ! 88: nflag++; ! 89: tf = maketemp(ATEMP); ! 90: tf->next = e.temps; e.temps = tf; ! 91: f = fopen(tf->name, "w"); ! 92: if (f == NULL) ! 93: errorf("cannot create temp file %s", tf->name); ! 94: setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ); ! 95: } ! 96: ! 97: for (hp = hbeg; hp <= hend; hp++) { ! 98: if (!nflag) ! 99: fprintf(f, "%3d: ", source->line - (int)(histptr-hp)); ! 100: fprintf(f, "%s\n", *hp); ! 101: } ! 102: ! 103: if (lflag) ! 104: return 0; ! 105: else ! 106: fclose(f); ! 107: ! 108: setstr(local("_"), tf->name); ! 109: command("${FCEDIT:-/bin/ed} $_"); /* edit temp file */ ! 110: ! 111: f = fopen(tf->name, "r"); ! 112: if (f == NULL) ! 113: errorf("cannot open temp file %s\n", tf->name); ! 114: setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ); ! 115: /* we push the editted lines onto the history list */ ! 116: while (fgets(line, sizeof(line), f) != NULL) { ! 117: histsave(line); ! 118: histpush--; ! 119: } ! 120: line[0] = '\0'; ! 121: fclose(f); ! 122: ! 123: return 0; ! 124: } ! 125: ! 126: /* ! 127: * save command in history ! 128: */ ! 129: void ! 130: histsave(cmd) ! 131: char *cmd; ! 132: { ! 133: register char **hp = histptr; ! 134: char *cp; ! 135: ! 136: if (++hp >= history + HISTORY) { /* remove oldest command */ ! 137: afree((Void*)*history, APERM); ! 138: for (hp = history; hp < history + HISTORY - 1; hp++) ! 139: hp[0] = hp[1]; ! 140: } ! 141: *hp = strsave(cmd, APERM); ! 142: if ((cp = strchr(*hp, '\n')) != NULL) ! 143: *cp = '\0'; ! 144: histptr = hp; ! 145: } ! 146: ! 147: /* ! 148: * get pointer to history given pattern ! 149: * pattern is a number or string ! 150: */ ! 151: char ** ! 152: histget(str) ! 153: char *str; ! 154: { ! 155: register char **hp = NULL; ! 156: ! 157: if (*str == '-') ! 158: hp = histptr + getn(str); ! 159: else ! 160: if (digit(*str)) ! 161: hp = histptr + (getn(str) - source->line); ! 162: else ! 163: if (*str == '?') /* unanchored match */ ! 164: for (hp = histptr-1; hp >= history; hp--) ! 165: if (strstr(*hp, str+1) != NULL) ! 166: break; ! 167: else /* anchored match */ ! 168: for (hp = histptr; hp >= history; hp--) ! 169: if (strncmp(*hp, str, strlen(str)) == 0) ! 170: break; ! 171: ! 172: return (history <= hp && hp <= histptr) ? hp : NULL; ! 173: } ! 174: ! 175: char * ! 176: histrpl(s, pat, rep) ! 177: char *s; ! 178: char *pat, *rep; ! 179: { ! 180: char *s1; ! 181: ! 182: if (strlen(s) - strlen(pat) + strlen(rep) >= LINE) ! 183: errorf("substitution too long\n"); ! 184: s1 = strstr(s, pat); ! 185: if (s1 == NULL) ! 186: errorf("substitution failed\n"); ! 187: *s1 = '\0'; ! 188: strcpy(line, s); /* first part */ ! 189: strcat(line, rep); /* replacement */ ! 190: strcat(line, s1 + strlen(pat)); /* last part */ ! 191: return line; ! 192: } ! 193: ! 194: #if 0 ! 195: ! 196: /* History file management routines (by DPK@BRL) */ ! 197: ! 198: void ! 199: hist_init() ! 200: { ! 201: register struct namnod *n; ! 202: int fd; ! 203: ! 204: if (hist_fd >= 0 || (flags&oneflg)) ! 205: return; ! 206: if ((n = findnam(histname)) == (struct namnod *)0 ! 207: || n->namval == (char *)0) ! 208: return; ! 209: if ((fd = open(n->namval, O_RDWR)) >= 0) { ! 210: hist_load(fd); ! 211: (void)fcntl(fd, F_SETFL, O_APPEND); ! 212: } ! 213: hist_fd = fd; ! 214: } ! 215: ! 216: void ! 217: hist_finish() ! 218: { ! 219: if (hist_fd >= 0) ! 220: (void)close(hist_fd); ! 221: hist_fd = -1; ! 222: } ! 223: ! 224: void ! 225: hist_record(buf, len) ! 226: char *buf; ! 227: int len; ! 228: { ! 229: if (hist_fd >= 0) ! 230: (void)write(hist_fd, buf, (unsigned)len); ! 231: } ! 232: ! 233: void ! 234: hist_load(fd) ! 235: int fd; ! 236: { ! 237: extern long lseek(); ! 238: struct stat sb; ! 239: char *x; ! 240: register char *cmdp, *end; ! 241: register int len; ! 242: register int i; ! 243: ! 244: if (fstat(fd, &sb) < 0 || sb.st_size <= 0) ! 245: return; ! 246: if (x = alloc((unsigned)(sb.st_size+1))) { ! 247: (void)lseek(fd, 0L, 0); ! 248: if ((len = read(fd, x, (unsigned)sb.st_size)) <= 0) { ! 249: free((struct blk *)x); ! 250: return; ! 251: } ! 252: x[len] = 0; ! 253: end = x; ! 254: for (;;) { ! 255: while(*end == NL) ! 256: end++; /* Skip NL */ ! 257: if (*end == 0) ! 258: break; ! 259: cmdp = end; ! 260: while(*end && *end != NL) ! 261: end++; /* Goto NL */ ! 262: if (*end == 0) ! 263: break; ! 264: if ((len = (end - cmdp)) < 2) ! 265: continue; ! 266: if (len >= BUFSIZ) ! 267: len = BUFSIZ - 1; /* Protection */ ! 268: i = curhist % NHISTORY; ! 269: if(histbuf[i]) ! 270: free((struct blk *)histbuf[i]); ! 271: histbuf[i] = alloc((unsigned)(len+1)); ! 272: (void)strncpy(histbuf[i], cmdp, len); ! 273: histbuf[i][len] = 0; ! 274: curhist++; ! 275: histpc=curhist; ! 276: } ! 277: free((struct blk *)x); ! 278: } ! 279: return; ! 280: } ! 281: ! 282: #endif ! 283:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.