18a16b7a1SPedro F. Giffuni /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 40da30e9aSPeter Wemm * Copyright (c) 1989, 1993 50da30e9aSPeter Wemm * The Regents of the University of California. All rights reserved. 60da30e9aSPeter Wemm * 70da30e9aSPeter Wemm * This code is derived from software contributed to Berkeley by 80da30e9aSPeter Wemm * Case Larsen. 90da30e9aSPeter Wemm * 100da30e9aSPeter Wemm * Redistribution and use in source and binary forms, with or without 110da30e9aSPeter Wemm * modification, are permitted provided that the following conditions 120da30e9aSPeter Wemm * are met: 130da30e9aSPeter Wemm * 1. Redistributions of source code must retain the above copyright 140da30e9aSPeter Wemm * notice, this list of conditions and the following disclaimer. 150da30e9aSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 160da30e9aSPeter Wemm * notice, this list of conditions and the following disclaimer in the 170da30e9aSPeter Wemm * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 190da30e9aSPeter Wemm * may be used to endorse or promote products derived from this software 200da30e9aSPeter Wemm * without specific prior written permission. 210da30e9aSPeter Wemm * 220da30e9aSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 230da30e9aSPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 240da30e9aSPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 250da30e9aSPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 260da30e9aSPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 270da30e9aSPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 280da30e9aSPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 290da30e9aSPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 300da30e9aSPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 310da30e9aSPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 320da30e9aSPeter Wemm * SUCH DAMAGE. 330da30e9aSPeter Wemm */ 340da30e9aSPeter Wemm 35b881b8beSRobert Watson #include <sys/capsicum.h> 36de89bd6bSPawel Jakub Dawidek 377672a014SMariusz Zaborski #include <capsicum_helpers.h> 380da30e9aSPeter Wemm #include <ctype.h> 39213915d4SPhilippe Charnier #include <err.h> 40de89bd6bSPawel Jakub Dawidek #include <errno.h> 41a597327bSKyle Evans #include <getopt.h> 42c02e5894SAndrey A. Chernov #include <limits.h> 430c312497SAndrey A. Chernov #include <locale.h> 44de89bd6bSPawel Jakub Dawidek #include <nl_types.h> 4511715600SDag-Erling Smørgrav #include <stdbool.h> 46a8092021SJaakko Heinonen #include <stdint.h> 47213915d4SPhilippe Charnier #include <stdio.h> 480da30e9aSPeter Wemm #include <stdlib.h> 490da30e9aSPeter Wemm #include <string.h> 50de89bd6bSPawel Jakub Dawidek #include <termios.h> 510da30e9aSPeter Wemm #include <unistd.h> 523fead394STim J. Robbins #include <wchar.h> 533fead394STim J. Robbins #include <wctype.h> 540da30e9aSPeter Wemm 5511715600SDag-Erling Smørgrav static enum { DF_NONE, DF_NOSEP, DF_PRESEP, DF_POSTSEP } Dflag; 5611715600SDag-Erling Smørgrav static bool cflag, dflag, uflag, iflag; 5711715600SDag-Erling Smørgrav static long long numchars, numfields, repeats; 58d9371717SIan Lepore 59a597327bSKyle Evans static const struct option long_opts[] = 60a597327bSKyle Evans { 61d9371717SIan Lepore {"all-repeated",optional_argument, NULL, 'D'}, 62a597327bSKyle Evans {"count", no_argument, NULL, 'c'}, 63a597327bSKyle Evans {"repeated", no_argument, NULL, 'd'}, 64a597327bSKyle Evans {"skip-fields", required_argument, NULL, 'f'}, 65a597327bSKyle Evans {"ignore-case", no_argument, NULL, 'i'}, 66a597327bSKyle Evans {"skip-chars", required_argument, NULL, 's'}, 67a597327bSKyle Evans {"unique", no_argument, NULL, 'u'}, 68a597327bSKyle Evans {NULL, no_argument, NULL, 0} 69a597327bSKyle Evans }; 70a597327bSKyle Evans 717f3cfdffSEd Schouten static FILE *file(const char *, const char *); 727f3cfdffSEd Schouten static wchar_t *convert(const char *); 737f3cfdffSEd Schouten static int inlcmp(const char *, const char *); 747f3cfdffSEd Schouten static void show(FILE *, const char *); 757f3cfdffSEd Schouten static wchar_t *skip(wchar_t *); 767f3cfdffSEd Schouten static void obsolete(char *[]); 773f330d7dSWarner Losh static void usage(void); 78c02e5894SAndrey A. Chernov 790da30e9aSPeter Wemm int 80f4ac32deSDavid Malone main (int argc, char *argv[]) 810da30e9aSPeter Wemm { 825eaad26eSAndrey A. Chernov wchar_t *tprev, *tthis; 830da30e9aSPeter Wemm FILE *ifp, *ofp; 84d4c2dafaSAndrey A. Chernov int ch, comp; 855eaad26eSAndrey A. Chernov size_t prevbuflen, thisbuflen, b1; 86d4c2dafaSAndrey A. Chernov char *prevline, *thisline, *p; 87899837e8SDag-Erling Smørgrav const char *errstr, *ifn, *ofn; 88de89bd6bSPawel Jakub Dawidek cap_rights_t rights; 890da30e9aSPeter Wemm 90b285e268SAndrey A. Chernov (void) setlocale(LC_ALL, ""); 910c312497SAndrey A. Chernov 920da30e9aSPeter Wemm obsolete(argv); 93d9371717SIan Lepore while ((ch = getopt_long(argc, argv, "+D::cdif:s:u", long_opts, 94a597327bSKyle Evans NULL)) != -1) 950da30e9aSPeter Wemm switch (ch) { 96d9371717SIan Lepore case 'D': 97d9371717SIan Lepore if (optarg == NULL || strcasecmp(optarg, "none") == 0) 98d9371717SIan Lepore Dflag = DF_NOSEP; 99d9371717SIan Lepore else if (strcasecmp(optarg, "prepend") == 0) 100d9371717SIan Lepore Dflag = DF_PRESEP; 101d9371717SIan Lepore else if (strcasecmp(optarg, "separate") == 0) 102d9371717SIan Lepore Dflag = DF_POSTSEP; 103d9371717SIan Lepore else 104d9371717SIan Lepore usage(); 105d9371717SIan Lepore break; 1060da30e9aSPeter Wemm case 'c': 10711715600SDag-Erling Smørgrav cflag = true; 1080da30e9aSPeter Wemm break; 1090da30e9aSPeter Wemm case 'd': 11011715600SDag-Erling Smørgrav dflag = true; 1110da30e9aSPeter Wemm break; 1122ca7dc15SJoerg Wunsch case 'i': 11311715600SDag-Erling Smørgrav iflag = true; 1142ca7dc15SJoerg Wunsch break; 1150da30e9aSPeter Wemm case 'f': 116e052829eSDaniel Tameling numfields = strtonum(optarg, 0, INT_MAX, &errstr); 117e052829eSDaniel Tameling if (errstr) 118e052829eSDaniel Tameling errx(1, "field skip value is %s: %s", errstr, optarg); 1190da30e9aSPeter Wemm break; 1200da30e9aSPeter Wemm case 's': 121e052829eSDaniel Tameling numchars = strtonum(optarg, 0, INT_MAX, &errstr); 122e052829eSDaniel Tameling if (errstr != NULL) 123e052829eSDaniel Tameling errx(1, "character skip value is %s: %s", errstr, optarg); 1240da30e9aSPeter Wemm break; 1250da30e9aSPeter Wemm case 'u': 12611715600SDag-Erling Smørgrav uflag = true; 1270da30e9aSPeter Wemm break; 1280da30e9aSPeter Wemm case '?': 1290da30e9aSPeter Wemm default: 1300da30e9aSPeter Wemm usage(); 1310da30e9aSPeter Wemm } 1320da30e9aSPeter Wemm 133fc630325STim J. Robbins argc -= optind; 1340da30e9aSPeter Wemm argv += optind; 1350da30e9aSPeter Wemm 13638b1ff46STim J. Robbins if (argc > 2) 13738b1ff46STim J. Robbins usage(); 13838b1ff46STim J. Robbins 13911715600SDag-Erling Smørgrav if (Dflag && dflag) 14011715600SDag-Erling Smørgrav dflag = false; 14111715600SDag-Erling Smørgrav 1420da30e9aSPeter Wemm ifp = stdin; 1433fead394STim J. Robbins ifn = "stdin"; 1440da30e9aSPeter Wemm ofp = stdout; 145899837e8SDag-Erling Smørgrav ofn = "stdout"; 14638b1ff46STim J. Robbins if (argc > 0 && strcmp(argv[0], "-") != 0) 1473fead394STim J. Robbins ifp = file(ifn = argv[0], "r"); 1487008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_FSTAT, CAP_READ); 149377421dfSMariusz Zaborski if (caph_rights_limit(fileno(ifp), &rights) < 0) 150de89bd6bSPawel Jakub Dawidek err(1, "unable to limit rights for %s", ifn); 1517008be5bSPawel Jakub Dawidek cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE); 15238b1ff46STim J. Robbins if (argc > 1) 153899837e8SDag-Erling Smørgrav ofp = file(ofn = argv[1], "w"); 154de89bd6bSPawel Jakub Dawidek else 1557008be5bSPawel Jakub Dawidek cap_rights_set(&rights, CAP_IOCTL); 156377421dfSMariusz Zaborski if (caph_rights_limit(fileno(ofp), &rights) < 0) { 157de89bd6bSPawel Jakub Dawidek err(1, "unable to limit rights for %s", 158de89bd6bSPawel Jakub Dawidek argc > 1 ? argv[1] : "stdout"); 159de89bd6bSPawel Jakub Dawidek } 1607008be5bSPawel Jakub Dawidek if (cap_rights_is_set(&rights, CAP_IOCTL)) { 161de89bd6bSPawel Jakub Dawidek unsigned long cmd; 162de89bd6bSPawel Jakub Dawidek 163de89bd6bSPawel Jakub Dawidek cmd = TIOCGETA; /* required by isatty(3) in printf(3) */ 164de89bd6bSPawel Jakub Dawidek 165377421dfSMariusz Zaborski if (caph_ioctls_limit(fileno(ofp), &cmd, 1) < 0) { 166de89bd6bSPawel Jakub Dawidek err(1, "unable to limit ioctls for %s", 167de89bd6bSPawel Jakub Dawidek argc > 1 ? argv[1] : "stdout"); 168de89bd6bSPawel Jakub Dawidek } 169de89bd6bSPawel Jakub Dawidek } 170de89bd6bSPawel Jakub Dawidek 171a3552326SMariusz Zaborski caph_cache_catpages(); 1727672a014SMariusz Zaborski if (caph_enter() < 0) 173de89bd6bSPawel Jakub Dawidek err(1, "unable to enter capability mode"); 1740da30e9aSPeter Wemm 1755eaad26eSAndrey A. Chernov prevbuflen = thisbuflen = 0; 1765eaad26eSAndrey A. Chernov prevline = thisline = NULL; 1770da30e9aSPeter Wemm 1785eaad26eSAndrey A. Chernov if (getline(&prevline, &prevbuflen, ifp) < 0) { 17926cfaf71SJuli Mallett if (ferror(ifp)) 18036c5e18dSJuli Mallett err(1, "%s", ifn); 1810da30e9aSPeter Wemm exit(0); 1823fead394STim J. Robbins } 18311715600SDag-Erling Smørgrav if (!cflag && !Dflag && !dflag && !uflag) 18411715600SDag-Erling Smørgrav show(ofp, prevline); 1855eaad26eSAndrey A. Chernov tprev = convert(prevline); 186d4c2dafaSAndrey A. Chernov 1875eaad26eSAndrey A. Chernov tthis = NULL; 1885eaad26eSAndrey A. Chernov while (getline(&thisline, &thisbuflen, ifp) >= 0) { 1895eaad26eSAndrey A. Chernov if (tthis != NULL) 1905eaad26eSAndrey A. Chernov free(tthis); 1915eaad26eSAndrey A. Chernov tthis = convert(thisline); 1920da30e9aSPeter Wemm 193d4c2dafaSAndrey A. Chernov if (tthis == NULL && tprev == NULL) 1945eaad26eSAndrey A. Chernov comp = inlcmp(thisline, prevline); 195d4c2dafaSAndrey A. Chernov else if (tthis == NULL || tprev == NULL) 196d4c2dafaSAndrey A. Chernov comp = 1; 1972ca7dc15SJoerg Wunsch else 198d4c2dafaSAndrey A. Chernov comp = wcscoll(tthis, tprev); 1992ca7dc15SJoerg Wunsch 2002ca7dc15SJoerg Wunsch if (comp) { 201d4c2dafaSAndrey A. Chernov /* If different, print; set previous to new value. */ 202d9371717SIan Lepore if (Dflag == DF_POSTSEP && repeats > 0) 203d9371717SIan Lepore fputc('\n', ofp); 20411715600SDag-Erling Smørgrav if (!cflag && !Dflag && !dflag && !uflag) 20511715600SDag-Erling Smørgrav show(ofp, thisline); 20611715600SDag-Erling Smørgrav else if (!Dflag && 20711715600SDag-Erling Smørgrav (!dflag || (cflag && repeats > 0)) && 20811715600SDag-Erling Smørgrav (!uflag || repeats == 0)) 2090da30e9aSPeter Wemm show(ofp, prevline); 210d4c2dafaSAndrey A. Chernov p = prevline; 2115eaad26eSAndrey A. Chernov b1 = prevbuflen; 2120da30e9aSPeter Wemm prevline = thisline; 2135eaad26eSAndrey A. Chernov prevbuflen = thisbuflen; 2145eaad26eSAndrey A. Chernov if (tprev != NULL) 2155eaad26eSAndrey A. Chernov free(tprev); 216d4c2dafaSAndrey A. Chernov tprev = tthis; 217d4c2dafaSAndrey A. Chernov thisline = p; 2185eaad26eSAndrey A. Chernov thisbuflen = b1; 2195eaad26eSAndrey A. Chernov tthis = NULL; 2200da30e9aSPeter Wemm repeats = 0; 221d9371717SIan Lepore } else { 222d9371717SIan Lepore if (Dflag) { 223d9371717SIan Lepore if (repeats == 0) { 224d9371717SIan Lepore if (Dflag == DF_PRESEP) 225d9371717SIan Lepore fputc('\n', ofp); 226d9371717SIan Lepore show(ofp, prevline); 227d9371717SIan Lepore } 22811715600SDag-Erling Smørgrav } else if (dflag && !cflag) { 22911715600SDag-Erling Smørgrav if (repeats == 0) 23011715600SDag-Erling Smørgrav show(ofp, prevline); 231d9371717SIan Lepore } 2320da30e9aSPeter Wemm ++repeats; 233*c3f8900eSDag-Erling Smørgrav if (Dflag) 234*c3f8900eSDag-Erling Smørgrav show(ofp, thisline); 2350da30e9aSPeter Wemm } 236d9371717SIan Lepore } 2373fead394STim J. Robbins if (ferror(ifp)) 23836c5e18dSJuli Mallett err(1, "%s", ifn); 23911715600SDag-Erling Smørgrav if (!cflag && !Dflag && !dflag && !uflag) 24011715600SDag-Erling Smørgrav /* already printed */ ; 24111715600SDag-Erling Smørgrav else if (!Dflag && 24211715600SDag-Erling Smørgrav (!dflag || (cflag && repeats > 0)) && 24311715600SDag-Erling Smørgrav (!uflag || repeats == 0)) 2440da30e9aSPeter Wemm show(ofp, prevline); 245899837e8SDag-Erling Smørgrav if (fflush(ofp) != 0) 246899837e8SDag-Erling Smørgrav err(1, "%s", ofn); 2470da30e9aSPeter Wemm exit(0); 2480da30e9aSPeter Wemm } 2490da30e9aSPeter Wemm 2507f3cfdffSEd Schouten static wchar_t * 2515eaad26eSAndrey A. Chernov convert(const char *str) 252d4c2dafaSAndrey A. Chernov { 253d4c2dafaSAndrey A. Chernov size_t n; 2545eaad26eSAndrey A. Chernov wchar_t *buf, *ret, *p; 255d4c2dafaSAndrey A. Chernov 2565eaad26eSAndrey A. Chernov if ((n = mbstowcs(NULL, str, 0)) == (size_t)-1) 2575eaad26eSAndrey A. Chernov return (NULL); 258d2796d06SAndrey A. Chernov if (SIZE_MAX / sizeof(*buf) < n + 1) 259d2796d06SAndrey A. Chernov errx(1, "conversion buffer length overflow"); 2605eaad26eSAndrey A. Chernov if ((buf = malloc((n + 1) * sizeof(*buf))) == NULL) 2615eaad26eSAndrey A. Chernov err(1, "malloc"); 2625eaad26eSAndrey A. Chernov if (mbstowcs(buf, str, n + 1) != n) 2635eaad26eSAndrey A. Chernov errx(1, "internal mbstowcs() error"); 2645eaad26eSAndrey A. Chernov /* The last line may not end with \n. */ 2655eaad26eSAndrey A. Chernov if (n > 0 && buf[n - 1] == L'\n') 2665eaad26eSAndrey A. Chernov buf[n - 1] = L'\0'; 2675eaad26eSAndrey A. Chernov 268d4c2dafaSAndrey A. Chernov /* If requested get the chosen fields + character offsets. */ 2695eaad26eSAndrey A. Chernov if (numfields || numchars) { 2705eaad26eSAndrey A. Chernov if ((ret = wcsdup(skip(buf))) == NULL) 2715eaad26eSAndrey A. Chernov err(1, "wcsdup"); 2725eaad26eSAndrey A. Chernov free(buf); 2735eaad26eSAndrey A. Chernov } else 274d4c2dafaSAndrey A. Chernov ret = buf; 2755eaad26eSAndrey A. Chernov 276d4c2dafaSAndrey A. Chernov if (iflag) { 277d4c2dafaSAndrey A. Chernov for (p = ret; *p != L'\0'; p++) 278d4c2dafaSAndrey A. Chernov *p = towlower(*p); 279d4c2dafaSAndrey A. Chernov } 280d4c2dafaSAndrey A. Chernov 281d4c2dafaSAndrey A. Chernov return (ret); 282d4c2dafaSAndrey A. Chernov } 283d4c2dafaSAndrey A. Chernov 2847f3cfdffSEd Schouten static int 2855eaad26eSAndrey A. Chernov inlcmp(const char *s1, const char *s2) 2865eaad26eSAndrey A. Chernov { 2875eaad26eSAndrey A. Chernov int c1, c2; 2885eaad26eSAndrey A. Chernov 2895eaad26eSAndrey A. Chernov while (*s1 == *s2++) 2905eaad26eSAndrey A. Chernov if (*s1++ == '\0') 2915eaad26eSAndrey A. Chernov return (0); 2925eaad26eSAndrey A. Chernov c1 = (unsigned char)*s1; 2935eaad26eSAndrey A. Chernov c2 = (unsigned char)*(s2 - 1); 2945eaad26eSAndrey A. Chernov /* The last line may not end with \n. */ 2955eaad26eSAndrey A. Chernov if (c1 == '\n') 2965eaad26eSAndrey A. Chernov c1 = '\0'; 2975eaad26eSAndrey A. Chernov if (c2 == '\n') 2985eaad26eSAndrey A. Chernov c2 = '\0'; 2995eaad26eSAndrey A. Chernov return (c1 - c2); 3005eaad26eSAndrey A. Chernov } 3015eaad26eSAndrey A. Chernov 3020da30e9aSPeter Wemm /* 3030da30e9aSPeter Wemm * show -- 3040da30e9aSPeter Wemm * Output a line depending on the flags and number of repetitions 3050da30e9aSPeter Wemm * of the line. 3060da30e9aSPeter Wemm */ 3077f3cfdffSEd Schouten static void 308d4c2dafaSAndrey A. Chernov show(FILE *ofp, const char *str) 3090da30e9aSPeter Wemm { 3100cd82603STim J. Robbins if (cflag) 31111715600SDag-Erling Smørgrav (void)fprintf(ofp, "%4lld %s", repeats + 1, str); 312a520574dSEd Maste else 3135eaad26eSAndrey A. Chernov (void)fprintf(ofp, "%s", str); 3140da30e9aSPeter Wemm } 3150da30e9aSPeter Wemm 3167f3cfdffSEd Schouten static wchar_t * 3173fead394STim J. Robbins skip(wchar_t *str) 3180da30e9aSPeter Wemm { 31911715600SDag-Erling Smørgrav long long nchars, nfields; 3200da30e9aSPeter Wemm 321d4c2dafaSAndrey A. Chernov for (nfields = 0; *str != L'\0' && nfields++ != numfields; ) { 3223fead394STim J. Robbins while (iswblank(*str)) 323382ac430STim J. Robbins str++; 324d4c2dafaSAndrey A. Chernov while (*str != L'\0' && !iswblank(*str)) 325382ac430STim J. Robbins str++; 3260da30e9aSPeter Wemm } 327d4c2dafaSAndrey A. Chernov for (nchars = numchars; nchars-- && *str != L'\0'; ++str) 328d4c2dafaSAndrey A. Chernov ; 3290da30e9aSPeter Wemm return(str); 3300da30e9aSPeter Wemm } 3310da30e9aSPeter Wemm 3327f3cfdffSEd Schouten static FILE * 333f4ac32deSDavid Malone file(const char *name, const char *mode) 3340da30e9aSPeter Wemm { 3350da30e9aSPeter Wemm FILE *fp; 3360da30e9aSPeter Wemm 3370da30e9aSPeter Wemm if ((fp = fopen(name, mode)) == NULL) 338213915d4SPhilippe Charnier err(1, "%s", name); 3390da30e9aSPeter Wemm return(fp); 3400da30e9aSPeter Wemm } 3410da30e9aSPeter Wemm 3427f3cfdffSEd Schouten static void 343f4ac32deSDavid Malone obsolete(char *argv[]) 3440da30e9aSPeter Wemm { 345e2ec8ee0SDag-Erling Smørgrav char *ap, *p; 3460da30e9aSPeter Wemm 347213915d4SPhilippe Charnier while ((ap = *++argv)) { 3480da30e9aSPeter Wemm /* Return if "--" or not an option of any form. */ 3490da30e9aSPeter Wemm if (ap[0] != '-') { 3500da30e9aSPeter Wemm if (ap[0] != '+') 3510da30e9aSPeter Wemm return; 352e2ec8ee0SDag-Erling Smørgrav } else if (ap[1] == '-') { 3530da30e9aSPeter Wemm return; 354e2ec8ee0SDag-Erling Smørgrav } 3550c312497SAndrey A. Chernov if (!isdigit((unsigned char)ap[1])) 3560da30e9aSPeter Wemm continue; 3570da30e9aSPeter Wemm /* 3580da30e9aSPeter Wemm * Digit signifies an old-style option. Malloc space for dash, 3590da30e9aSPeter Wemm * new option and argument. 3600da30e9aSPeter Wemm */ 361e2ec8ee0SDag-Erling Smørgrav if (asprintf(&p, "-%c%s", ap[0] == '+' ? 's' : 'f', ap + 1) < 0) 3627dd4ac68STim J. Robbins err(1, "malloc"); 363e2ec8ee0SDag-Erling Smørgrav *argv = p; 3640da30e9aSPeter Wemm } 3650da30e9aSPeter Wemm } 3660da30e9aSPeter Wemm 367213915d4SPhilippe Charnier static void 368f4ac32deSDavid Malone usage(void) 3690da30e9aSPeter Wemm { 370b93791f5SDag-Erling Smørgrav (void)fprintf(stderr, "usage: uniq [-cdiu] [-D[septype]] " 371b93791f5SDag-Erling Smørgrav "[-f fields] [-s chars] [input [output]]\n"); 3720da30e9aSPeter Wemm exit(1); 3730da30e9aSPeter Wemm } 374