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