|
|
1.1 ! root 1: #include <stdio.h> ! 2: #include <ctype.h> ! 3: #include <signal.h> ! 4: #include <sys/types.h> ! 5: #include <sys/stat.h> ! 6: ! 7: #define N 16 ! 8: #define C 20 ! 9: #define NF 10 ! 10: ! 11: /* ! 12: * Memory administration ! 13: * ! 14: * Using a lot of memory is great when sorting a lot of data. ! 15: * Using a megabyte to sort the output of `who' loses big. ! 16: * MAXMEM, MINMEM and DEFMEM define the absolute maximum, ! 17: * minimum and default memory requirements. Administrators ! 18: * can override any or all of these via defines at compile time. ! 19: * Users can override the amount allocated (within the limits ! 20: * of MAXMEM and MINMEM) on the command line. ! 21: */ ! 22: ! 23: #ifndef MAXMEM ! 24: #define MAXMEM 1048576 /* Megabyte maximum */ ! 25: #endif ! 26: ! 27: #ifndef MINMEM ! 28: #define MINMEM 16384 /* 16K minimum */ ! 29: #endif ! 30: ! 31: #ifndef DEFMEM ! 32: #define DEFMEM 131072 /* Same as old sort */ ! 33: #endif ! 34: ! 35: ! 36: #define ASC 0 ! 37: #define NUM 1 ! 38: #define MON 2 ! 39: ! 40: #define blank(c) ((c)==' ' || (c)=='\t') ! 41: FILE *is, *os; ! 42: char *dirtry[] = {"/usr/tmp", "/tmp", NULL}; ! 43: char **dirs; ! 44: char file1[30]; ! 45: char *file = file1; ! 46: char *filep; ! 47: int nfiles; ! 48: int *lspace; ! 49: unsigned alloc,tryfor; ! 50: char bufin[BUFSIZ], bufout[BUFSIZ]; /* Use setbuf's to avoid malloc calls. ! 51: ** Malloc seems to develope heartburn ! 52: ** when brk returns storage. ! 53: */ ! 54: int maxrec; ! 55: int cmp(), cmpa(); ! 56: int (*compare)() = cmpa; ! 57: char *eol(); ! 58: int term(); ! 59: int mflg; ! 60: int mphase; ! 61: int nway; ! 62: int cflg; ! 63: int uflg; ! 64: char *outfil; ! 65: int unsafeout; /*kludge to assure -m -o works*/ ! 66: char tabchar; ! 67: int eargc; ! 68: char **eargv; ! 69: ! 70: char zero[256]; ! 71: ! 72: char fold[256] = { ! 73: 0200,0201,0202,0203,0204,0205,0206,0207, ! 74: 0210,0211,0212,0213,0214,0215,0216,0217, ! 75: 0220,0221,0222,0223,0224,0225,0226,0227, ! 76: 0230,0231,0232,0233,0234,0235,0236,0237, ! 77: 0240,0241,0242,0243,0244,0245,0246,0247, ! 78: 0250,0251,0252,0253,0254,0255,0256,0257, ! 79: 0260,0261,0262,0263,0264,0265,0266,0267, ! 80: 0270,0271,0272,0273,0274,0275,0276,0277, ! 81: 0300,0301,0302,0303,0304,0305,0306,0307, ! 82: 0310,0311,0312,0313,0314,0315,0316,0317, ! 83: 0320,0321,0322,0323,0324,0325,0326,0327, ! 84: 0330,0331,0332,0333,0334,0335,0336,0337, ! 85: 0340,0341,0342,0343,0344,0345,0346,0347, ! 86: 0350,0351,0352,0353,0354,0355,0356,0357, ! 87: 0360,0361,0362,0363,0364,0365,0366,0367, ! 88: 0370,0371,0372,0373,0374,0375,0376,0377, ! 89: 0000,0001,0002,0003,0004,0005,0006,0007, ! 90: 0010,0011,0012,0013,0014,0015,0016,0017, ! 91: 0020,0021,0022,0023,0024,0025,0026,0027, ! 92: 0030,0031,0032,0033,0034,0035,0036,0037, ! 93: 0040,0041,0042,0043,0044,0045,0046,0047, ! 94: 0050,0051,0052,0053,0054,0055,0056,0057, ! 95: 0060,0061,0062,0063,0064,0065,0066,0067, ! 96: 0070,0071,0072,0073,0074,0075,0076,0077, ! 97: 0100,0101,0102,0103,0104,0105,0106,0107, ! 98: 0110,0111,0112,0113,0114,0115,0116,0117, ! 99: 0120,0121,0122,0123,0124,0125,0126,0127, ! 100: 0130,0131,0132,0133,0134,0134,0136,0137, ! 101: 0140,0101,0102,0103,0104,0105,0106,0107, ! 102: 0110,0111,0112,0113,0114,0115,0116,0117, ! 103: 0120,0121,0122,0123,0124,0125,0126,0127, ! 104: 0130,0131,0132,0173,0174,0175,0176,0177 ! 105: }; ! 106: char nofold[256] = { ! 107: 0200,0201,0202,0203,0204,0205,0206,0207, ! 108: 0210,0211,0212,0213,0214,0215,0216,0217, ! 109: 0220,0221,0222,0223,0224,0225,0226,0227, ! 110: 0230,0231,0232,0233,0234,0235,0236,0237, ! 111: 0240,0241,0242,0243,0244,0245,0246,0247, ! 112: 0250,0251,0252,0253,0254,0255,0256,0257, ! 113: 0260,0261,0262,0263,0264,0265,0266,0267, ! 114: 0270,0271,0272,0273,0274,0275,0276,0277, ! 115: 0300,0301,0302,0303,0304,0305,0306,0307, ! 116: 0310,0311,0312,0313,0314,0315,0316,0317, ! 117: 0320,0321,0322,0323,0324,0325,0326,0327, ! 118: 0330,0331,0332,0333,0334,0335,0336,0337, ! 119: 0340,0341,0342,0343,0344,0345,0346,0347, ! 120: 0350,0351,0352,0353,0354,0355,0356,0357, ! 121: 0360,0361,0362,0363,0364,0365,0366,0367, ! 122: 0370,0371,0372,0373,0374,0375,0376,0377, ! 123: 0000,0001,0002,0003,0004,0005,0006,0007, ! 124: 0010,0011,0012,0013,0014,0015,0016,0017, ! 125: 0020,0021,0022,0023,0024,0025,0026,0027, ! 126: 0030,0031,0032,0033,0034,0035,0036,0037, ! 127: 0040,0041,0042,0043,0044,0045,0046,0047, ! 128: 0050,0051,0052,0053,0054,0055,0056,0057, ! 129: 0060,0061,0062,0063,0064,0065,0066,0067, ! 130: 0070,0071,0072,0073,0074,0075,0076,0077, ! 131: 0100,0101,0102,0103,0104,0105,0106,0107, ! 132: 0110,0111,0112,0113,0114,0115,0116,0117, ! 133: 0120,0121,0122,0123,0124,0125,0126,0127, ! 134: 0130,0131,0132,0133,0134,0135,0136,0137, ! 135: 0140,0141,0142,0143,0144,0145,0146,0147, ! 136: 0150,0151,0152,0153,0154,0155,0156,0157, ! 137: 0160,0161,0162,0163,0164,0165,0166,0167, ! 138: 0170,0171,0172,0173,0174,0175,0176,0177 ! 139: }; ! 140: ! 141: char nonprint[256] = { ! 142: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 143: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 144: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 145: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 146: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 147: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 148: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 149: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 150: 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, ! 151: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 152: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 153: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 154: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 155: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 156: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 157: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 ! 158: }; ! 159: ! 160: char dict[256] = { ! 161: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 162: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 163: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 164: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 165: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 166: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 167: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 168: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 169: 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1, ! 170: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 171: 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, ! 172: 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, ! 173: 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 174: 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, ! 175: 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ! 176: 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1 ! 177: }; ! 178: ! 179: struct field { ! 180: char *code; ! 181: char *ignore; ! 182: int fcmp; ! 183: int rflg; ! 184: int bflg[2]; ! 185: int m[2]; ! 186: int n[2]; ! 187: } fields[NF]; ! 188: struct field proto = { ! 189: nofold+128, ! 190: zero+128, ! 191: ASC, ! 192: 1, ! 193: 0,0, ! 194: 0,-1, ! 195: 0,0 ! 196: }; ! 197: int nfields; ! 198: int error = 1; ! 199: char *setfil(); ! 200: ! 201: main(argc, argv) ! 202: char **argv; ! 203: { ! 204: register a; ! 205: char *arg; ! 206: struct field *p, *q; ! 207: int i; ! 208: long incr; ! 209: char *sbrk(); ! 210: char *sp; ! 211: ! 212: copyproto(); ! 213: eargv = argv; ! 214: tryfor = DEFMEM; ! 215: while (--argc > 0) { ! 216: if(**++argv == '-') for(arg = *argv;;) { ! 217: switch(*++arg) { ! 218: case '\0': ! 219: if(arg[-1] == '-') ! 220: eargv[eargc++] = "-"; ! 221: break; ! 222: ! 223: case 'o': ! 224: if(--argc > 0) ! 225: outfil = *++argv; ! 226: continue; ! 227: ! 228: case 'T': ! 229: if (--argc > 0) ! 230: dirtry[0] = *++argv; ! 231: continue; ! 232: ! 233: default: ! 234: field(++*argv,nfields>0); ! 235: break; ! 236: } ! 237: break; ! 238: } else if (**argv == '+') { ! 239: if(++nfields>=NF) { ! 240: diag("too many keys",""); ! 241: exit(1); ! 242: } ! 243: copyproto(); ! 244: field(++*argv,0); ! 245: } else ! 246: eargv[eargc++] = *argv; ! 247: } ! 248: q = &fields[0]; ! 249: for(a=1; a<=nfields; a++) { ! 250: p = &fields[a]; ! 251: if(p->code != proto.code) continue; ! 252: if(p->ignore != proto.ignore) continue; ! 253: if(p->fcmp != proto.fcmp) continue; ! 254: if(p->rflg != proto.rflg) continue; ! 255: if(p->bflg[0] != proto.bflg[0]) continue; ! 256: if(p->bflg[1] != proto.bflg[1]) continue; ! 257: p->code = q->code; ! 258: p->ignore = q->ignore; ! 259: p->fcmp = q->fcmp; ! 260: p->rflg = q->rflg; ! 261: p->bflg[0] = p->bflg[1] = q->bflg[0]; ! 262: } ! 263: if(eargc == 0) ! 264: eargv[eargc++] = "-"; ! 265: if(cflg && eargc>1) { ! 266: diag("can check only 1 file",""); ! 267: exit(1); ! 268: } ! 269: ! 270: safeoutfil(); ! 271: ! 272: sp = sbrk(0); ! 273: lspace = (int *) sp; ! 274: if (!mflg && !cflg) { ! 275: if (tryfor < MINMEM) tryfor = MINMEM; ! 276: else if (tryfor > MAXMEM) tryfor = MAXMEM; ! 277: for (incr=tryfor; (sp + incr) <= sp; incr >>= 1); ! 278: do { ! 279: if ((long)alloc+incr <= tryfor && brk(sp+incr) == 0) { ! 280: sp += incr; ! 281: alloc += incr; ! 282: } ! 283: } while ( ( incr >>= 1 ) >= 512L ); ! 284: alloc -= 512; /* for recursion? */ ! 285: if ( brk((char *) lspace + alloc) != 0) { ! 286: diag("allocation error before sort", ""); ! 287: exit(1); ! 288: } ! 289: } ! 290: ! 291: a = -1; ! 292: for(dirs=dirtry; *dirs; dirs++) { ! 293: (void) sprintf(filep=file1, "%s/stm%.5uaa", *dirs, getpid()); ! 294: while (*filep) ! 295: filep++; ! 296: filep -= 2; ! 297: if ( (a=creat(file, 0600)) >=0) ! 298: break; ! 299: } ! 300: if(a < 0) { ! 301: diag("can't locate temp",""); ! 302: exit(1); ! 303: } ! 304: (void) close(a); ! 305: (void) unlink(file); ! 306: if (signal(SIGHUP, SIG_IGN) != SIG_IGN) ! 307: (void) signal(SIGHUP, term); ! 308: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 309: (void) signal(SIGINT, term); ! 310: (void) signal(SIGPIPE,term); ! 311: if (signal(SIGTERM, SIG_IGN) != SIG_IGN) ! 312: (void) signal(SIGTERM,term); ! 313: nfiles = eargc; ! 314: if(!mflg && !cflg) { ! 315: sort(); ! 316: if (ferror(stdin)) ! 317: rderror("stdin"); ! 318: (void) fclose(stdin); ! 319: } ! 320: ! 321: mphase = 1; ! 322: if (maxrec == 0) maxrec = 512; ! 323: alloc = (N + 1) * maxrec + N * BUFSIZ; ! 324: for (nway = N; nway >= 2; --nway) { ! 325: if (brk((char *)lspace + alloc) == 0) break; ! 326: alloc -= maxrec + BUFSIZ; ! 327: } ! 328: if (nway < 2) { ! 329: diag("allocation error before merge", ""); ! 330: term(); ! 331: } ! 332: ! 333: if (cflg) checksort(); ! 334: ! 335: a = mflg || cflg ? 0 : eargc; ! 336: if ((i = nfiles - a) > nway) { /* Do leftovers early */ ! 337: if ((i %= (nway - 1)) == 0) ! 338: i = nway - 1; ! 339: if (i != 1) { ! 340: newfile(); ! 341: (void) setbuf(os, bufout); ! 342: merge(a,a+i); ! 343: a += i; ! 344: } ! 345: } ! 346: for(; a+nway<nfiles || unsafeout&&a<eargc; a=i) { ! 347: i = a+nway; ! 348: if(i>=nfiles) ! 349: i = nfiles; ! 350: newfile(); ! 351: (void) setbuf(os, bufout); ! 352: merge(a, i); ! 353: } ! 354: if(a != nfiles) { ! 355: oldfile(); ! 356: (void) setbuf(os, bufout); ! 357: merge(a, nfiles); ! 358: } ! 359: error = 0; ! 360: term(); ! 361: } ! 362: ! 363: sort() ! 364: { ! 365: register char *cp; ! 366: register c; ! 367: register char **lp; ! 368: char *keep, *ekeep, *ep, **tp; ! 369: int done, i; ! 370: char *f; ! 371: ! 372: /* ! 373: ** Records are read in from the front of the buffer area. ! 374: ** Pointers to the records are allocated from the back of the buffer. ! 375: ** If a partially read record exhausts the buffer, it is saved and ! 376: ** then copied to the start of the buffer for processing with the ! 377: ** next coreload. ! 378: */ ! 379: done = 0; ! 380: keep = 0; ! 381: i = 0; ! 382: c = EOF; ! 383: ep = (char *) lspace + alloc; ! 384: do { ! 385: lp = (char **)ep - 1; ! 386: cp = (char *) lspace; ! 387: if (keep != 0) { /* part of record from previous coreload */ ! 388: *lp-- = cp; ! 389: for(; keep < ekeep; *cp++ = *keep++); ! 390: } ! 391: while (cp < (char *) lp) { ! 392: if (keep == 0) *lp-- = cp; ! 393: while (cp + 1 < (char *) lp && c != '\n') { ! 394: if(c != EOF) { ! 395: *cp++ = c; ! 396: c = getc(is); ! 397: continue; ! 398: } else if(is) { ! 399: if(ferror(is)) ! 400: rderror(f); ! 401: (void) fclose(is); ! 402: } ! 403: if(i < eargc) { ! 404: if((f = setfil(i++)) == 0) ! 405: is = stdin; ! 406: else if((is = fopen(f, "r")) == NULL) ! 407: cant(f); ! 408: (void) setbuf(is, bufin); ! 409: c = getc(is); ! 410: } else ! 411: break; ! 412: } ! 413: if (c == '\n') { ! 414: *cp++ = '\n'; ! 415: keep = 0; ! 416: } ! 417: else if (c != EOF) { /* save partial record */ ! 418: lp++; ! 419: if (keep != 0) { ! 420: diag("whopper record won't fit", ""); ! 421: term(); ! 422: } ! 423: keep = *lp; ! 424: ekeep = cp; ! 425: break; ! 426: } ! 427: if(c == EOF) { ! 428: if(ferror(is)) ! 429: rderror(f); ! 430: done++; ! 431: lp++; ! 432: break; ! 433: } ! 434: c = getc(is); ! 435: } ! 436: lp++; ! 437: qsort(lp, (char **) ep); ! 438: if(done == 0 || nfiles != eargc) ! 439: newfile(); ! 440: else ! 441: oldfile(); ! 442: (void) setbuf(os, bufout); ! 443: tp = (char **) ep; ! 444: while(tp > lp) { ! 445: cp = *--tp; ! 446: if(*cp) { ! 447: do ! 448: putc(*cp, os); ! 449: while(*cp++ != '\n'); ! 450: } ! 451: } ! 452: if (ferror(os)) ! 453: wterror("sorting"); ! 454: (void) fclose(os); ! 455: } while(done == 0); ! 456: } ! 457: ! 458: char *heap[N]; ! 459: int lowkid = 0; /* ! 460: ** Index of lesser subtree of heap, if known. ! 461: ** Useful if records are mostly ordered, with long runs of ! 462: ** records being written from the same input file before ! 463: ** the heap is really restructured. ! 464: */ ! 465: ! 466: ! 467: # define EXC(a, b) t = a; a = b; b = t ! 468: ! 469: merge(a, b) ! 470: { ! 471: FILE *tfile[N]; ! 472: char *buffer = (char *) lspace; ! 473: register int nf; /* number of merge files */ ! 474: register int i; ! 475: int j; ! 476: register char *cp; ! 477: char *t, *f; ! 478: char *save,*iobuf; ! 479: ! 480: save = (char *) lspace + (nway * maxrec); ! 481: iobuf = save + maxrec; ! 482: for (nf=0, i=a; i < b; i++) { ! 483: f = setfil(i); ! 484: if (f == 0) ! 485: tfile[nf] = stdin; ! 486: else if ((tfile[nf] = fopen(f, "r")) == NULL) ! 487: cant(f); ! 488: heap[nf] = buffer + (nf * maxrec); ! 489: (void) setbuf(tfile[nf],iobuf); ! 490: iobuf += BUFSIZ; ! 491: if (rline(tfile[nf], heap[nf])==0) ! 492: nf++; ! 493: else { ! 494: if(ferror(tfile[nf])) ! 495: rderror(f); ! 496: (void) fclose(tfile[nf]); ! 497: } ! 498: } ! 499: ! 500: qsort(heap, (heap + nf)); ! 501: ! 502: for (i=0, j=nf-1; i < j ; i++, --j ) { /* qsort is backwards */ ! 503: EXC(heap[i], heap[j]); ! 504: } ! 505: lowkid = 1; ! 506: ! 507: while (nf > 0) { ! 508: cp = heap[0]; ! 509: do ! 510: putc(*cp, os); ! 511: while (*cp++ != '\n'); ! 512: ! 513: if (uflg) { ! 514: t = save; ! 515: cp = heap[0]; ! 516: do ! 517: *t++ = *cp; ! 518: while (*cp++ != '\n'); ! 519: } ! 520: ! 521: /* Get another record and reheap. Bypass repeats if uflg. */ ! 522: ! 523: do { ! 524: i = (heap[0] - buffer) / maxrec; ! 525: if (rline(tfile[i], heap[0])) { ! 526: if (ferror(tfile[i])) ! 527: rderror(setfil(i+a)); ! 528: (void) fclose(tfile[i]); ! 529: if (--nf <= 0) break; ! 530: heap[0] = heap[nf]; ! 531: if (nf < 3) lowkid = 0; ! 532: } ! 533: reheap(nf); ! 534: } while (uflg && (*compare)(heap[0], save) == 0 ); ! 535: } ! 536: for (i=a; i < b; i++) { ! 537: if (i >= eargc) ! 538: (void) unlink(setfil(i)); ! 539: } ! 540: if (ferror(os)) ! 541: wterror("merging"); ! 542: (void) fclose(os); ! 543: } ! 544: ! 545: ! 546: reheap(ind) ! 547: register int ind; ! 548: { ! 549: register int i, j; ! 550: char *t; ! 551: ! 552: --ind; /* last legitimate index */ ! 553: for (i=0; (j = 2*i + 1) <= ind; i = j) { ! 554: if (lowkid != 0) ! 555: j = lowkid; ! 556: else if ( (j < ind) && (*compare)(heap[j],heap[j+1]) <= 0 ) ! 557: j++; ! 558: if ( (*compare)(heap[i], heap[j]) >= 0 ) { ! 559: if (i == 0) lowkid = j; ! 560: return; ! 561: } ! 562: EXC(heap[i], heap[j]); ! 563: lowkid = 0; ! 564: } ! 565: return; ! 566: } ! 567: rline(iop, s) ! 568: FILE *iop; ! 569: register char *s; ! 570: { ! 571: register char *ce; ! 572: register int c; ! 573: ! 574: ce = s + maxrec; ! 575: do { ! 576: c = getc(iop); ! 577: if (c == EOF) ! 578: return(1); ! 579: if (s >= ce) ! 580: --s; ! 581: *s++ = c; ! 582: } while (c != '\n'); ! 583: return(0); ! 584: } ! 585: ! 586: ! 587: checksort() ! 588: { ! 589: char *f; ! 590: char *s[2]; ! 591: register int i, j, r; ! 592: ! 593: f = setfil(0); ! 594: if (f == 0) ! 595: is = stdin; ! 596: else if ((is = fopen(f, "r")) == NULL) ! 597: cant(f); ! 598: (void) setbuf(is, bufin); ! 599: ! 600: i = 0; j = 1; ! 601: s[0] = (char *) lspace; ! 602: s[1] = s[0] + maxrec; ! 603: if ( rline(is, s[0]) ) { ! 604: if (ferror(is)) { ! 605: rderror(f); ! 606: } ! 607: (void) fclose(is); ! 608: exit(0); ! 609: } ! 610: while ( !rline(is, s[j]) ) { ! 611: r = (*compare)(s[i], s[j]); ! 612: if (r < 0) ! 613: disorder("disorder: ", s[j]); ! 614: if (r == 0 && uflg) ! 615: disorder("non-unique: ", s[j]); ! 616: r = i; i = j; j = r; ! 617: } ! 618: if (ferror(is)) ! 619: rderror(f); ! 620: (void) fclose(is); ! 621: exit(0); ! 622: } ! 623: ! 624: ! 625: disorder(s,t) ! 626: char *s, *t; ! 627: { ! 628: register char *u; ! 629: for(u=t; *u!='\n';u++) ; ! 630: *u = 0; ! 631: diag(s,t); ! 632: term(); ! 633: } ! 634: ! 635: newfile() ! 636: { ! 637: register char *f; ! 638: ! 639: f = setfil(nfiles); ! 640: if((os=fopen(f, "w")) == NULL) { ! 641: diag("can't create ",f); ! 642: term(); ! 643: } ! 644: nfiles++; ! 645: } ! 646: ! 647: char * ! 648: setfil(i) ! 649: { ! 650: ! 651: if(i < eargc) ! 652: if(eargv[i][0] == '-' && eargv[i][1] == '\0') ! 653: return(0); ! 654: else ! 655: return(eargv[i]); ! 656: i -= eargc; ! 657: filep[0] = i/26 + 'a'; ! 658: filep[1] = i%26 + 'a'; ! 659: return(file); ! 660: } ! 661: ! 662: oldfile() ! 663: { ! 664: ! 665: if(outfil) { ! 666: if((os=fopen(outfil, "w")) == NULL) { ! 667: diag("can't create ",outfil); ! 668: term(); ! 669: } ! 670: } else ! 671: os = stdout; ! 672: } ! 673: ! 674: safeoutfil() ! 675: { ! 676: register int i; ! 677: struct stat ostat,istat; ! 678: ! 679: if(!mflg||outfil==0) ! 680: return; ! 681: if(stat(outfil,&ostat)==-1) ! 682: return; ! 683: if ((i = eargc - N) < 0) i = 0; /*-N is suff., not nec. */ ! 684: for (; i < eargc; i++) { ! 685: if(stat(eargv[i],&istat)==-1) ! 686: continue; ! 687: if(ostat.st_dev==istat.st_dev&& ! 688: ostat.st_ino==istat.st_ino) ! 689: unsafeout++; ! 690: } ! 691: } ! 692: ! 693: cant(f) ! 694: char *f; ! 695: { ! 696: ! 697: diag("can't open ",f); ! 698: term(); ! 699: } ! 700: ! 701: diag(s,t) ! 702: char *s, *t; ! 703: { ! 704: (void) fputs("sort: ",stderr); ! 705: (void) fputs(s,stderr); ! 706: (void) fputs(t,stderr); ! 707: (void) fputs("\n",stderr); ! 708: } ! 709: ! 710: term() ! 711: { ! 712: register i; ! 713: ! 714: (void) signal(SIGINT, SIG_IGN); ! 715: (void) signal(SIGHUP, SIG_IGN); ! 716: (void) signal(SIGTERM, SIG_IGN); ! 717: if(nfiles == eargc) ! 718: nfiles++; ! 719: for(i=eargc; i<=nfiles; i++) { /*<= in case of interrupt*/ ! 720: (void) unlink(setfil(i)); /*with nfiles not updated*/ ! 721: } ! 722: exit(error); ! 723: } ! 724: ! 725: cmp(i, j) ! 726: char *i, *j; ! 727: { ! 728: register char *pa, *pb; ! 729: char *skip(); ! 730: char *code, *ignore; ! 731: int a, b; ! 732: int k; ! 733: char *la, *lb; ! 734: register int sa; ! 735: int sb; ! 736: char *ipa, *ipb, *jpa, *jpb; ! 737: struct field *fp; ! 738: ! 739: for(k = nfields>0; k<=nfields; k++) { ! 740: fp = &fields[k]; ! 741: pa = i; ! 742: pb = j; ! 743: if(k) { ! 744: la = skip(pa, fp, 1); ! 745: pa = skip(pa, fp, 0); ! 746: lb = skip(pb, fp, 1); ! 747: pb = skip(pb, fp, 0); ! 748: } else { ! 749: la = eol(pa); ! 750: lb = eol(pb); ! 751: } ! 752: if(fp->fcmp==NUM) { ! 753: sa = sb = fp->rflg; ! 754: while(blank(*pa)) ! 755: pa++; ! 756: while(blank(*pb)) ! 757: pb++; ! 758: if(*pa == '-') { ! 759: pa++; ! 760: sa = -sa; ! 761: } ! 762: if(*pb == '-') { ! 763: pb++; ! 764: sb = -sb; ! 765: } ! 766: for(ipa = pa; ipa<la&&isdigit(*ipa); ipa++) ; ! 767: for(ipb = pb; ipb<lb&&isdigit(*ipb); ipb++) ; ! 768: jpa = ipa; ! 769: jpb = ipb; ! 770: a = 0; ! 771: if(sa==sb) ! 772: while(ipa > pa && ipb > pb) ! 773: if(b = *--ipb - *--ipa) ! 774: a = b; ! 775: while(ipa > pa) ! 776: if(*--ipa != '0') ! 777: return(-sa); ! 778: while(ipb > pb) ! 779: if(*--ipb != '0') ! 780: return(sb); ! 781: if(a) return(a*sa); ! 782: if(*(pa=jpa) == '.') ! 783: pa++; ! 784: if(*(pb=jpb) == '.') ! 785: pb++; ! 786: if(sa==sb) ! 787: while(pa<la && isdigit(*pa) ! 788: && pb<lb && isdigit(*pb)) ! 789: if(a = *pb++ - *pa++) ! 790: return(a*sa); ! 791: while(pa<la && isdigit(*pa)) ! 792: if(*pa++ != '0') ! 793: return(-sa); ! 794: while(pb<lb && isdigit(*pb)) ! 795: if(*pb++ != '0') ! 796: return(sb); ! 797: continue; ! 798: } else if(fp->fcmp==MON) { ! 799: sa = fp->rflg*(month(pb)-month(pa)); ! 800: if(sa) ! 801: return(sa); ! 802: else ! 803: continue; ! 804: } ! 805: code = fp->code; ! 806: ignore = fp->ignore; ! 807: loop: ! 808: while(ignore[*pa]) ! 809: pa++; ! 810: while(ignore[*pb]) ! 811: pb++; ! 812: if(pa>=la || *pa=='\n') ! 813: if(pb<lb && *pb!='\n') ! 814: return(fp->rflg); ! 815: else continue; ! 816: if(pb>=lb || *pb=='\n') ! 817: return(-fp->rflg); ! 818: if((sa = code[*pb++]-code[*pa++]) == 0) ! 819: goto loop; ! 820: return(sa*fp->rflg); ! 821: } ! 822: if(uflg) ! 823: return(0); ! 824: return(cmpa(i, j)); ! 825: } ! 826: ! 827: cmpa(pa, pb) ! 828: register char *pa, *pb; ! 829: { ! 830: while(*pa == *pb++) ! 831: if(*pa++ == '\n') ! 832: return(0); ! 833: return( ! 834: *pa == '\n' ? fields[0].rflg: ! 835: *--pb == '\n' ?-fields[0].rflg: ! 836: *pb > *pa ? fields[0].rflg: ! 837: -fields[0].rflg ! 838: ); ! 839: } ! 840: ! 841: char * ! 842: skip(pp, fp, j) ! 843: struct field *fp; ! 844: char *pp; ! 845: { ! 846: register i; ! 847: register char *p; ! 848: ! 849: p = pp; ! 850: if( (i=fp->m[j]) < 0) ! 851: return(eol(p)); ! 852: while(i-- > 0) { ! 853: if(tabchar != 0) { ! 854: while(*p != tabchar) ! 855: if(*p != '\n') ! 856: p++; ! 857: else goto ret; ! 858: p++; ! 859: } else { ! 860: while(blank(*p)) ! 861: p++; ! 862: while(!blank(*p)) ! 863: if(*p != '\n') ! 864: p++; ! 865: else goto ret; ! 866: } ! 867: } ! 868: if(fp->bflg[j]) ! 869: while(blank(*p)) ! 870: p++; ! 871: i = fp->n[j]; ! 872: if(i==0 && j!=0 && fp->m[j]>0 && p[-1]==tabchar) ! 873: p--; ! 874: while((i-- > 0) && (*p != '\n')) ! 875: p++; ! 876: ret: ! 877: return(p); ! 878: } ! 879: ! 880: char * ! 881: eol(p) ! 882: register char *p; ! 883: { ! 884: while(*p != '\n') p++; ! 885: return(p); ! 886: } ! 887: ! 888: copyproto() ! 889: { ! 890: register i; ! 891: register int *p, *q; ! 892: ! 893: p = (int *)&proto; ! 894: q = (int *)&fields[nfields]; ! 895: for(i=0; i<sizeof(proto)/sizeof(*p); i++) ! 896: *q++ = *p++; ! 897: } ! 898: ! 899: field(s,k) ! 900: char *s; ! 901: { ! 902: register struct field *p; ! 903: register d; ! 904: p = &fields[nfields]; ! 905: d = 0; ! 906: for(; *s!=0; s++) { ! 907: switch(*s) { ! 908: case '\0': ! 909: return; ! 910: ! 911: case 'b': ! 912: p->bflg[k]++; ! 913: break; ! 914: ! 915: case 'd': ! 916: p->ignore = dict+128; ! 917: break; ! 918: ! 919: case 'f': ! 920: p->code = fold+128; ! 921: break; ! 922: case 'i': ! 923: p->ignore = nonprint+128; ! 924: break; ! 925: ! 926: case 'c': ! 927: cflg = 1; ! 928: continue; ! 929: ! 930: case 'm': ! 931: mflg = 1; ! 932: continue; ! 933: ! 934: case 'M': ! 935: p->fcmp = MON; ! 936: break; ! 937: ! 938: case 'n': ! 939: p->fcmp = NUM; ! 940: break; ! 941: case 't': ! 942: tabchar = *++s; ! 943: if(tabchar == 0) s--; ! 944: continue; ! 945: ! 946: case 'r': ! 947: p->rflg = -1; ! 948: continue; ! 949: case 'u': ! 950: uflg = 1; ! 951: continue; ! 952: ! 953: case 'y': ! 954: if ( *++s ) tryfor = number(&s); ! 955: else { ! 956: --s; ! 957: tryfor = MAXMEM; ! 958: } ! 959: continue; ! 960: ! 961: case 'z': ! 962: if ( *++s ) ! 963: maxrec = number(&s); ! 964: else --s; ! 965: continue; ! 966: ! 967: case '.': ! 968: if(p->m[k] == -1) /* -m.n with m missing */ ! 969: p->m[k] = 0; ! 970: d = &fields[0].n[0]-&fields[0].m[0]; ! 971: if (*++s == '\0') { ! 972: --s; ! 973: p->m[k+d] = 0; ! 974: continue; ! 975: } ! 976: ! 977: default: ! 978: p->m[k+d] = number(&s); ! 979: } ! 980: compare = cmp; ! 981: } ! 982: } ! 983: ! 984: number(ppa) ! 985: char **ppa; ! 986: { ! 987: int n; ! 988: register char *pa; ! 989: pa = *ppa; ! 990: n = 0; ! 991: while(isdigit(*pa)) { ! 992: n = n*10 + *pa - '0'; ! 993: *ppa = pa++; ! 994: } ! 995: return(n); ! 996: } ! 997: ! 998: #define qsexc(p,q) t= *p;*p= *q;*q=t ! 999: #define qstexc(p,q,r) t= *p;*p= *r;*r= *q;*q=t ! 1000: ! 1001: qsort(a,l) ! 1002: char **a, **l; ! 1003: { ! 1004: register char **i, **j; ! 1005: char **k; ! 1006: char **lp, **hp; ! 1007: int c; ! 1008: char *t; ! 1009: unsigned n; ! 1010: ! 1011: ! 1012: start: ! 1013: if((n=l-a) <= 1) ! 1014: return; ! 1015: ! 1016: n /= 2; ! 1017: hp = lp = a+n; ! 1018: i = a; ! 1019: j = l-1; ! 1020: ! 1021: ! 1022: for(;;) { ! 1023: if(i < lp) { ! 1024: if((c = (*compare)(*i, *lp)) == 0) { ! 1025: --lp; ! 1026: qsexc(i, lp); ! 1027: continue; ! 1028: } ! 1029: if(c < 0) { ! 1030: ++i; ! 1031: continue; ! 1032: } ! 1033: } ! 1034: ! 1035: loop: ! 1036: if(j > hp) { ! 1037: if((c = (*compare)(*hp, *j)) == 0) { ! 1038: ++hp; ! 1039: qsexc(hp, j); ! 1040: goto loop; ! 1041: } ! 1042: if(c > 0) { ! 1043: if(i == lp) { ! 1044: ++hp; ! 1045: qstexc(i, hp, j); ! 1046: i = ++lp; ! 1047: goto loop; ! 1048: } ! 1049: qsexc(i, j); ! 1050: --j; ! 1051: ++i; ! 1052: continue; ! 1053: } ! 1054: --j; ! 1055: goto loop; ! 1056: } ! 1057: ! 1058: ! 1059: if(i == lp) { ! 1060: if(uflg&&!mphase) ! 1061: for(k=lp+1; k<=hp;) **k++ = '\0'; ! 1062: if(lp-a >= l-hp) { ! 1063: qsort(hp+1, l); ! 1064: l = lp; ! 1065: } else { ! 1066: qsort(a, lp); ! 1067: a = hp+1; ! 1068: } ! 1069: goto start; ! 1070: } ! 1071: ! 1072: ! 1073: --lp; ! 1074: qstexc(j, lp, i); ! 1075: j = --hp; ! 1076: } ! 1077: } ! 1078: ! 1079: char * months[] = { ! 1080: "jan", ! 1081: "feb", ! 1082: "mar", ! 1083: "apr", ! 1084: "may", ! 1085: "jun", ! 1086: "jul", ! 1087: "aug", ! 1088: "sep", ! 1089: "oct", ! 1090: "nov", ! 1091: "dec" ! 1092: }; ! 1093: month(s) ! 1094: char *s; ! 1095: { ! 1096: register char *t, *u; ! 1097: register i; ! 1098: char *f = fold + 128; ! 1099: ! 1100: while(blank(*s)) ! 1101: s++; ! 1102: for(i=0; i<sizeof(months)/sizeof(*months); i++) { ! 1103: for(t=s,u=months[i]; f[*t++]==f[*u++]; ) ! 1104: if(*u==0) ! 1105: return(i); ! 1106: } ! 1107: return(-1); ! 1108: } ! 1109: ! 1110: ! 1111: rderror(s) ! 1112: char *s; ! 1113: { ! 1114: diag("read error on ", s == 0 ? "stdin" : s); ! 1115: term(); ! 1116: } ! 1117: ! 1118: wterror(s) ! 1119: char *s; ! 1120: { ! 1121: diag("write error while ", s); ! 1122: term(); ! 1123: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.