[BACK]Return to sort.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sort

Annotation of src/usr.bin/sort/sort.c, Revision 1.1

1.1     ! millert     1: /*     $OpenBSD$       */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 1993
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * This code is derived from software contributed to Berkeley by
        !             8:  * Peter McIlroy.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by the University of
        !            21:  *     California, Berkeley and its contributors.
        !            22:  * 4. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  */
        !            38:
        !            39: #ifndef lint
        !            40: static char copyright[] =
        !            41: "@(#) Copyright (c) 1993\n\
        !            42:        The Regents of the University of California.  All rights reserved.\n";
        !            43: #endif /* not lint */
        !            44:
        !            45: #ifndef lint
        !            46: #if 0
        !            47: static char sccsid[] = "@(#)sort.c     8.1 (Berkeley) 6/6/93";
        !            48: #else
        !            49: static char rcsid[] = "$OpenBSD: $";
        !            50: #endif
        !            51: #endif /* not lint */
        !            52:
        !            53: /* Sort sorts a file using an optional user-defined key.
        !            54:  * Sort uses radix sort for internal sorting, and allows
        !            55:  * a choice of merge sort and radix sort for external sorting.
        !            56:  */
        !            57:
        !            58: #include "sort.h"
        !            59: #include "fsort.h"
        !            60: #include "pathnames.h"
        !            61:
        !            62: #include <paths.h>
        !            63: #include <signal.h>
        !            64: #include <stdlib.h>
        !            65: #include <string.h>
        !            66: #include <unistd.h>
        !            67:
        !            68: int REC_D = '\n';
        !            69: u_char d_mask[NBINS];          /* flags for rec_d, field_d, <blank> */
        !            70: /*
        !            71:  * weight tables.  Gweights is one of ascii, Rascii..
        !            72:  * modified to weight rec_d = 0 (or 255)
        !            73:  */
        !            74: extern u_char gweights[NBINS];
        !            75: u_char ascii[NBINS], Rascii[NBINS], RFtable[NBINS], Ftable[NBINS];
        !            76: /*
        !            77:  * masks of ignored characters.  Alltable is 256 ones
        !            78:  */
        !            79: u_char dtable[NBINS], itable[NBINS], alltable[NBINS];
        !            80: int SINGL_FLD = 0, SEP_FLAG = 0, UNIQUE = 0;
        !            81: struct coldesc clist[(ND+1)*2];
        !            82: int ncols = 0;
        !            83: extern struct coldesc clist[(ND+1)*2];
        !            84: extern int ncols;
        !            85:
        !            86: char devstdin[] = _PATH_STDIN;
        !            87: char toutpath[_POSIX_PATH_MAX];
        !            88: char *tmpdir = _PATH_VARTMP;
        !            89:
        !            90: static void cleanup __P((void));
        !            91: static void onsig __P((int));
        !            92: static void usage __P((char *));
        !            93:
        !            94: int
        !            95: main(argc, argv)
        !            96:        int argc;
        !            97:        char *argv[];
        !            98: {
        !            99:        extern int optind;
        !           100:        extern char *optarg;
        !           101:        int (*get)();
        !           102:        int ch, i, stdinflag = 0, tmp = 0;
        !           103:        char cflag = 0, mflag = 0, nflag = 0;
        !           104:        char *outfile, *outpath = 0;
        !           105:        struct field fldtab[ND+2], *ftpos;
        !           106:        union f_handle filelist;
        !           107:        FILE *outfp = NULL;
        !           108:        memset(fldtab, 0, (ND+2)*sizeof(struct field));
        !           109:        memset(d_mask, 0, NBINS);
        !           110:        d_mask[REC_D = '\n'] = REC_D_F;
        !           111:        SINGL_FLD = SEP_FLAG = 0;
        !           112:        d_mask['\t'] = d_mask[' '] = BLANK | FLD_D;
        !           113:        ftpos = fldtab;
        !           114:        fixit(&argc, argv);
        !           115:        if (!issetugid() && (outfile = getenv("TMPDIR")))
        !           116:                tmpdir = outfile;
        !           117:        while ((ch = getopt(argc, argv, "bcdfik:mHno:rR:t:T:uy:")) != -1) {
        !           118:        switch (ch) {
        !           119:                case 'b': fldtab->flags |= BI | BT;
        !           120:                        break;
        !           121:                case 'd':
        !           122:                case 'i':
        !           123:                case 'f':
        !           124:                case 'r': tmp |= optval(ch, 0);
        !           125:                        if (tmp & R && tmp & F)
        !           126:                                fldtab->weights = RFtable;
        !           127:                        else if (tmp & F)
        !           128:                                fldtab->weights = Ftable;
        !           129:                        else if(tmp & R)
        !           130:                                fldtab->weights = Rascii;
        !           131:                        fldtab->flags |= tmp;
        !           132:                        break;
        !           133:                case 'o':
        !           134:                        outpath = optarg;
        !           135:                        break;
        !           136:                case 'n':
        !           137:                        nflag = 1;
        !           138:                        setfield("1n", ++ftpos, fldtab->flags&(~R));
        !           139:                        break;
        !           140:                case 'k':
        !           141:                         setfield(optarg, ++ftpos, fldtab->flags);
        !           142:                        break;
        !           143:                case 't':
        !           144:                        if (SEP_FLAG)
        !           145:                                usage("multiple field delimiters");
        !           146:                        SEP_FLAG = 1;
        !           147:                        d_mask[' '] &= ~FLD_D;
        !           148:                        d_mask['\t'] &= ~FLD_D;
        !           149:                        d_mask[(int)*optarg] |= FLD_D;
        !           150:                        if (d_mask[(int)*optarg] & REC_D_F)
        !           151:                                err(2, "record/field delimiter clash");
        !           152:                        break;
        !           153:                case 'R':
        !           154:                        if (REC_D != '\n')
        !           155:                                usage("multiple record delimiters");
        !           156:                        if ('\n' == (REC_D = *optarg))
        !           157:                                break;
        !           158:                        d_mask['\n'] = d_mask[' '];
        !           159:                        d_mask[REC_D] = REC_D_F;
        !           160:                        break;
        !           161:                case 'T':
        !           162:                        tmpdir = optarg;
        !           163:                        break;
        !           164:                case 'u':
        !           165:                        UNIQUE = 1;
        !           166:                        break;
        !           167:                case 'c':
        !           168:                        cflag = 1;
        !           169:                        break;
        !           170:                case 'm':
        !           171:                        mflag = 1;
        !           172:                        break;
        !           173:                case 'H':
        !           174:                        PANIC = 0;
        !           175:                        break;
        !           176:                case 'y':
        !           177:                        /* accept -y for backwards compat. */
        !           178:                        break;
        !           179:                case '?':
        !           180:                default: usage("");
        !           181:                }
        !           182:        }
        !           183:        if (cflag && argc > optind+1)
        !           184:                errx(2, "too many input files for -c option");
        !           185:        if (argc - 2 > optind && !strcmp(argv[argc-2], "-o")) {
        !           186:                outpath = argv[argc-1];
        !           187:                argc -= 2;
        !           188:        }
        !           189:        if (mflag && argc - optind > (MAXFCT - (16+1))*16)
        !           190:                errx(2, "too many input files for -m option");
        !           191:        for (i = optind; i < argc; i++) {
        !           192:                /* allow one occurrence of /dev/stdin */
        !           193:                if (!strcmp(argv[i], "-") || !strcmp(argv[i], devstdin)) {
        !           194:                        if (stdinflag)
        !           195:                                warnx("ignoring extra \"%s\" in file list",
        !           196:                                    argv[i]);
        !           197:                        else {
        !           198:                                stdinflag = 1;
        !           199:                                argv[i] = devstdin;
        !           200:                        }
        !           201:                } else if ((ch = access(argv[i], R_OK)))
        !           202:                        err(2, "%s", argv[i]);
        !           203:        }
        !           204:        if (!(fldtab->flags & (I|D) || fldtab[1].icol.num)) {
        !           205:                SINGL_FLD = 1;
        !           206:                fldtab[0].icol.num = 1;
        !           207:        } else {
        !           208:                if (!fldtab[1].icol.num) {
        !           209:                        fldtab[0].flags &= ~(BI|BT);
        !           210:                        setfield("1", ++ftpos, fldtab->flags);
        !           211:                }
        !           212:                if (nflag)
        !           213:                        fldtab[1].flags |= fldtab->flags;
        !           214:                fldreset(fldtab);
        !           215:                fldtab[0].flags &= ~F;
        !           216:        }
        !           217:        settables(fldtab[0].flags);
        !           218:        num_init();
        !           219:        fldtab->weights = gweights;
        !           220:        if (optind == argc)
        !           221:                argv[--optind] = devstdin;
        !           222:        filelist.names = argv+optind;
        !           223:        if (SINGL_FLD)
        !           224:                get = makeline;
        !           225:        else
        !           226:                get = makekey;
        !           227:        if (cflag) {
        !           228:                order(filelist, get, fldtab);
        !           229:                /* NOT REACHED */
        !           230:        }
        !           231:        if (!outpath) {
        !           232:                (void)snprintf(toutpath,
        !           233:                    sizeof(toutpath), "%sstdout", _PATH_DEV);
        !           234:                outfile = outpath = toutpath;
        !           235:        } else if (!(ch = access(outpath, 0)) &&
        !           236:            strncmp(_PATH_DEV, outpath, 5)) {
        !           237:                struct sigaction act = {0, SIG_BLOCK, 6};
        !           238:                int sigtable[] = {SIGHUP, SIGINT, SIGPIPE, SIGXCPU, SIGXFSZ,
        !           239:                    SIGVTALRM, SIGPROF, 0};
        !           240:                int outfd;
        !           241:                errno = 0;
        !           242:                if (access(outpath, W_OK))
        !           243:                        err(2, "%s", outpath);
        !           244:                act.sa_handler = onsig;
        !           245:                (void)snprintf(toutpath, sizeof(toutpath), "%sXXXX", outpath);
        !           246:                if ((outfd = mkstemp(toutpath)) < 0 ||
        !           247:                    (outfp = fdopen(outfd, "w")) == 0)
        !           248:                        err(2, toutpath);
        !           249:                outfile = toutpath;
        !           250:                (void)atexit(cleanup);
        !           251:                for (i = 0; sigtable[i]; ++i)   /* always unlink toutpath */
        !           252:                        sigaction(sigtable[i], &act, 0);
        !           253:        } else
        !           254:                outfile = outpath;
        !           255:        if (outfp == NULL && (outfp = fopen(outfile, "w")) == NULL)
        !           256:                err(2, outfile);
        !           257:        if (mflag)
        !           258:                fmerge(-1, filelist, argc-optind, get, outfp, putline, fldtab);
        !           259:        else
        !           260:                fsort(-1, 0, filelist, argc-optind, outfp, fldtab);
        !           261:        if (outfile != outpath) {
        !           262:                if (access(outfile, 0))
        !           263:                        err(2, "%s", outfile);
        !           264:                (void)unlink(outpath);
        !           265:                if (link(outfile, outpath))
        !           266:                        err(2, "cannot link %s: output left in %s",
        !           267:                            outpath, outfile);
        !           268:                (void)unlink(outfile);
        !           269:        }
        !           270:        exit(0);
        !           271: }
        !           272:
        !           273: static void
        !           274: onsig(s)
        !           275:        int s;
        !           276: {
        !           277:        cleanup();
        !           278:        exit(2);                        /* return 2 on error/interrupt */
        !           279: }
        !           280:
        !           281: static void
        !           282: cleanup()
        !           283: {
        !           284:        if (toutpath[0])
        !           285:                (void)unlink(toutpath);
        !           286: }
        !           287:
        !           288: static void
        !           289: usage(msg)
        !           290:        char *msg;
        !           291: {
        !           292:        if (msg)
        !           293:                (void)fprintf(stderr, "sort: %s\n", msg);
        !           294:        (void)fprintf(stderr, "usage: [-o output] [-cmubdfinr] [-t char] ");
        !           295:        (void)fprintf(stderr, "[-T char] [-k keydef] ... [files]\n");
        !           296:        exit(2);
        !           297: }