|
|
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.