|
|
1.1 ! root 1: /* Copyright 1990, AT&T Bell Labs */ ! 2: #include "fsort.h" ! 3: #include <stdlib.h> ! 4: #include <string.h> ! 5: #include <signal.h> ! 6: #include <errno.h> ! 7: #include <sys/types.h> ! 8: #include <sys/stat.h> ! 9: ! 10: #define SIGHUP 1 ! 11: #define SIGINT 2 ! 12: #define SIGQUIT 3 ! 13: #define SIGPIPE 13 ! 14: #define SIGTERM 15 ! 15: ! 16: extern int getpid(void); ! 17: extern int access(char*, int); ! 18: extern int unlink(char*); ! 19: extern int stat(const char*, struct stat *); ! 20: extern int cgets(char*, int, FILE*); ! 21: ! 22: FILE * ! 23: fileopen(char *name, char *mode) ! 24: { ! 25: FILE *f; ! 26: if(strcmp(name,"-") == 0) ! 27: if(strcmp(mode, "r") == 0) ! 28: f = stdin; ! 29: else { ! 30: setbuf(stdout,malloc(BUFSIZ)); ! 31: f = stdout; ! 32: } ! 33: else { ! 34: if(strcmp(mode, "w") == 0 && ! 35: strcmp(name, oname) == 0 && ! 36: overwrite(0)) ! 37: setsigs(SIG_IGN); ! 38: f = fopen(name, mode); ! 39: } ! 40: if(f == 0) ! 41: fatal("can't open", name, 0); ! 42: return f; ! 43: } ! 44: ! 45: void ! 46: fileclose(FILE *f, char *name) ! 47: { ! 48: if(fclose(f)==EOF && name!=0) ! 49: fatal("error on", name, 0); ! 50: } ! 51: ! 52: /* file name strings accumulate as garbage */ ! 53: ! 54: char * ! 55: filename(int number) ! 56: { ! 57: char name[50]; ! 58: char *s; ! 59: int i; ! 60: for(i=0; (s=tname[i])!=0; i++) ! 61: if(access(s, 03) != -1) ! 62: break; ! 63: if(s == 0) ! 64: fatal("no accessible temp directory", "", 0); ! 65: sprintf(name, "%s/stm%.5d.%.4d", s, getpid(), number); ! 66: s = malloc(strlen(name) + 1); ! 67: if(s == 0) ! 68: fatal("out of space", "", 0); ! 69: strcpy(s, name); ! 70: return s; ! 71: } ! 72: ! 73: /* if there is enough room in record r, getline puts ! 74: a line of data there and returns 0; otherwise it ! 75: returns a pointer to a new record. The record ! 76: may be grown in stages; intermediate stages can ! 77: be discarded, but the original cannot. */ ! 78: ! 79: static struct rec * ! 80: newrec(struct rec *r, struct rec *retval) ! 81: { ! 82: int n = (uchar*)r->next - data(r); ! 83: int len = (uchar*)r->next - (uchar*)r; ! 84: struct rec *new = (struct rec*)malloc(len + n); ! 85: if(new == 0) ! 86: fatal("no space for record", "", 0); ! 87: memmove(new, r, len); ! 88: new->next = (struct rec*)((uchar*)new + len + n); ! 89: if(retval) ! 90: free(retval); ! 91: return new; ! 92: } ! 93: ! 94: struct rec* ! 95: getline(struct rec *r, FILE *f) ! 96: { ! 97: int n = 0; ! 98: int m; ! 99: uchar *cp, *dp; ! 100: struct rec *retval = 0; ! 101: ! 102: if(feof(f)) /* in case newline was appended */ ! 103: return ENDFILE; ! 104: for(;;) { /* usually executed once */ ! 105: dp = data(r); ! 106: cp = dp + n; ! 107: m = (uchar*)r->next - cp; ! 108: if(m <= 1) ! 109: retval = r = newrec(r, retval); ! 110: else { ! 111: m = cgets((char*)cp, m, f); ! 112: if(m == 0) { ! 113: if(n == 0) ! 114: return ENDFILE; ! 115: warn("newline appended", "", 0); ! 116: break; ! 117: } ! 118: n += m; ! 119: if(dp[n-1] == '\n') { ! 120: n--; ! 121: break; ! 122: } ! 123: } ! 124: } ! 125: ! 126: r->dlen = n; ! 127: if(n > MAXREC) ! 128: fatal("monster record", "", 0); ! 129: if(!keyed) { ! 130: r->klen = 0; /* hygiene */ ! 131: return retval; ! 132: } ! 133: while((n = fieldcode(data(r),key(r), r->dlen, ! 134: (uchar*)r->next, fields, nfields)) < 0) ! 135: retval = r = newrec(r, retval); /* rare event */ ! 136: if(n > MAXREC) ! 137: fatal("monster key", "", 0); ! 138: r->klen = n; ! 139: return retval; ! 140: } ! 141: ! 142: static char *level = "warning"; ! 143: ! 144: void ! 145: warn(char *m, char *s, int l) ! 146: { ! 147: fprintf(stderr, "sort: %s: %s %.*s\n", ! 148: level, m, l==0?strlen(s):l, s); ! 149: } ! 150: ! 151: void ! 152: fatal(char *m, char *s, int l) ! 153: { ! 154: level = "error"; ! 155: warn(m, s, l); ! 156: if(errno) ! 157: perror(""); ! 158: cleanup(1); ! 159: } ! 160: ! 161: int ! 162: overwrite(int j) ! 163: { ! 164: struct stat sb1, sb2; ! 165: if(strcmp(oname, "-") == 0) ! 166: return 0; ! 167: if(stat(oname, &sb1) == -1) ! 168: return 0; ! 169: for( ; j<nfiles; j++) { ! 170: if(strcmp(files[j], "-") == 0) ! 171: continue; ! 172: if(stat(files[j], &sb2) == -1) ! 173: fatal("cannot locate", files[j], 0); ! 174: if(sb1.st_dev==sb2.st_dev && sb1.st_ino==sb2.st_ino) ! 175: return 1; ! 176: } ! 177: return 0; ! 178: } ! 179: ! 180: static int siglist[] = { SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGTERM }; ! 181: ! 182: void ! 183: setsigs(void(*f)(int)) ! 184: { ! 185: int i; ! 186: for(i=0; i<sizeof(siglist)/sizeof(*siglist); i++) ! 187: if(signal(siglist[i], f) == SIG_IGN) ! 188: signal(siglist[i], SIG_IGN); ! 189: } ! 190: ! 191: void ! 192: cleanup(int i) ! 193: { ! 194: char *name; ! 195: setsigs(SIG_IGN); ! 196: while(--nextfile >= 0) { ! 197: name = filename(nextfile); ! 198: unlink(name); ! 199: free(name); ! 200: } ! 201: exit(i); ! 202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.