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