* Copyright (c) 1993 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* %sccs.include.redist.c%
"@(#) Copyright (c) 1993 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)sort.c 5.1 (Berkeley) %G%";
/* Sort sorts a file using an optional user-defined key.
* Sort uses radix sort for internal sorting, and allows
* a choice of merge sort and radix sort for external sorting.
u_char d_mask
[NBINS
]; /* flags for rec_d, field_d, <blank> */
* weight tables. Gweights is one of ascii, Rascii..
* modified to weight rec_d = 0 (or 255)
extern u_char gweights
[NBINS
];
u_char ascii
[NBINS
], Rascii
[NBINS
], RFtable
[NBINS
], Ftable
[NBINS
];
* masks of ignored characters. Alltable is 256 ones
u_char dtable
[NBINS
], itable
[NBINS
], alltable
[NBINS
];
int SINGL_FLD
= 0, SEP_FLAG
= 0, UNIQUE
= 0;
struct coldesc clist
[(ND
+1)*2];
extern struct coldesc clist
[(ND
+1)*2];
char devstdin
[] = _PATH_STDIN
;
char toutpath
[_POSIX_PATH_MAX
];
static void cleanup
__P((void));
static void onsig
__P((int));
static void usage
__P((char *));
int ch
, i
, stdinflag
= 0, tmp
= 0;
char cflag
= 0, mflag
= 0, nflag
= 0;
char *outfile
, *outpath
= 0;
struct field fldtab
[ND
+2], *ftpos
;
memset(fldtab
, 0, (ND
+2)*sizeof(struct field
));
memset(d_mask
, 0, NBINS
);
d_mask
[REC_D
= '\n'] = REC_D_F
;
SINGL_FLD
= SEP_FLAG
= 0;
d_mask
['\t'] = d_mask
[' '] = BLANK
| FLD_D
;
while ((ch
= getopt(argc
, argv
, "bcdfik:mHno:rt:T:ux")) != EOF
) {
case 'b': fldtab
->flags
|= BI
| BT
;
case 'r': tmp
|= optval(ch
, 0);
fldtab
->weights
= RFtable
;
fldtab
->weights
= Ftable
;
fldtab
->weights
= Rascii
;
setfield("1n", ++ftpos
, fldtab
->flags
&(~R
));
setfield(optarg
, ++ftpos
, fldtab
->flags
);
usage("multiple field delimiters");
d_mask
[*optarg
] |= FLD_D
;
if (d_mask
[*optarg
] & REC_D_F
)
err(2, "record/field delimiter clash");
usage("multiple record delimiters");
if ('\n' == (REC_D
= *optarg
))
d_mask
['\n'] = d_mask
[' '];
if (cflag
&& argc
> optind
+1)
errx(2, "too many input files for -c option");
if (argc
- 2 > optind
&& !strcmp(argv
[argc
-2], "-o")) {
if (mflag
&& argc
- optind
> (MAXFCT
- (16+1))*16)
errx(2, "too many input files for -m option");
for (i
= optind
; i
< argc
; i
++) {
/* allow one occurrence of /dev/stdin */
if (!strcmp(argv
[i
], "-") || !strcmp(argv
[i
], devstdin
)) {
warnx("ignoring extra \"%s\" in file list",
} else if (ch
= access(argv
[i
], R_OK
))
if (!(fldtab
->flags
& (I
|D
) || fldtab
[1].icol
.num
)) {
if (!fldtab
[1].icol
.num
) {
fldtab
[0].flags
&= ~(BI
|BT
);
setfield("1", ++ftpos
, fldtab
->flags
);
fldtab
[1].flags
|= fldtab
->flags
;
settables(fldtab
[0].flags
);
fldtab
->weights
= gweights
;
argv
[--optind
] = devstdin
;
filelist
.names
= argv
+optind
;
order(filelist
, get
, fldtab
);
sizeof(toutpath
), "%sstdout", _PATH_DEV
);
outfile
= outpath
= toutpath
;
} else if (!(ch
= access(outpath
, 0)) &&
strncmp(_PATH_DEV
, outpath
, 5)) {
struct sigaction act
= {0, SIG_BLOCK
, 6};
int sigtable
[] = {SIGHUP
, SIGINT
, SIGPIPE
, SIGXCPU
, SIGXFSZ
,
if (access(outpath
, W_OK
))
act
.sa_handler
= cleanup
;
(void)snprintf(toutpath
, sizeof(toutpath
), "%sXXXX", outpath
);
outfile
= mktemp(toutpath
);
for (i
= 0; sigtable
[i
]; ++i
) /* always unlink toutpath */
sigaction(sigtable
[i
], &act
, 0);
} else outfile
= outpath
;
if (!(outfd
= fopen(outfile
, "w")))
fmerge(-1, filelist
, argc
-optind
, get
, outfd
, putline
, fldtab
);
fsort(-1, 0, filelist
, argc
-optind
, outfd
, fldtab
);
if (outfile
!= outpath
) {
if (link(outfile
, outpath
))
err(2, "cannot link %s: output left in %s",
exit(2); /* return 2 on error/interrupt */
(void)fprintf(stderr
, "sort: %s\n", msg
);
(void)fprintf(stderr
, "usage: [-o output] [-cmubdfinr] [-t char] ");
(void)fprintf(stderr
, "[-T char] [-k keydef] ... [files]\n");