diff options
| author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2024-01-12 15:40:33 +0000 |
|---|---|---|
| committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2024-01-12 15:43:55 +0000 |
| commit | 11715600e626cf6cc4b4f564af97f6ae1e5fb0be (patch) | |
| tree | 146bf74cdf51ce742620fdc67f8d80cc3f07efa9 /usr.bin | |
| parent | e762fd81e253d4ae9b9f7d2e65cf448633bbe527 (diff) | |
Diffstat (limited to 'usr.bin')
| -rwxr-xr-x | usr.bin/uniq/tests/uniq_test.sh | 26 | ||||
| -rw-r--r-- | usr.bin/uniq/uniq.1 | 5 | ||||
| -rw-r--r-- | usr.bin/uniq/uniq.c | 49 |
3 files changed, 59 insertions, 21 deletions
diff --git a/usr.bin/uniq/tests/uniq_test.sh b/usr.bin/uniq/tests/uniq_test.sh index ddd9ec9881dd..8dc2015734f6 100755 --- a/usr.bin/uniq/tests/uniq_test.sh +++ b/usr.bin/uniq/tests/uniq_test.sh @@ -133,6 +133,30 @@ count_unique_body() { atf_check_uniq --count --unique } +atf_test_case interactive +interactive_head() { + atf_set descr "test interactive use" +} +interactive_body() { + sh -c 'yes | stdbuf -oL uniq >actual' & + pid=$! + sleep 1 + kill $! + atf_check -o inline:"y\n" cat actual +} + +atf_test_case interactive_repeated +interactive_repeated_head() { + atf_set descr "test interactive use with -d" +} +interactive_repeated_body() { + sh -c 'yes | stdbuf -oL uniq -d >actual' & + pid=$! + sleep 1 + kill $! + atf_check -o inline:"y\n" cat actual +} + atf_init_test_cases() { atf_add_test_case basic @@ -146,4 +170,6 @@ atf_init_test_cases() atf_add_test_case skip_chars atf_add_test_case unique atf_add_test_case count_unique + atf_add_test_case interactive + atf_add_test_case interactive_repeated } diff --git a/usr.bin/uniq/uniq.1 b/usr.bin/uniq/uniq.1 index e01c84328575..30dee856d772 100644 --- a/usr.bin/uniq/uniq.1 +++ b/usr.bin/uniq/uniq.1 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd June 7, 2020 +.Dd January 12, 2024 .Dt UNIQ 1 .Os .Sh NAME @@ -72,6 +72,9 @@ Precede each output line with the count of the number of times the line occurred in the input, followed by a single space. .It Fl d , Fl -repeated Output a single copy of each line that is repeated in the input. +Ignored if +.Fl D +is also specified. .It Fl D , Fl -all-repeated Op Ar septype Output all lines that are repeated (like .Fl d , diff --git a/usr.bin/uniq/uniq.c b/usr.bin/uniq/uniq.c index 55766f7e987e..0bc9b2b86af3 100644 --- a/usr.bin/uniq/uniq.c +++ b/usr.bin/uniq/uniq.c @@ -42,6 +42,7 @@ #include <limits.h> #include <locale.h> #include <nl_types.h> +#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -51,14 +52,9 @@ #include <wchar.h> #include <wctype.h> -static int Dflag, cflag, dflag, uflag, iflag; -static int numchars, numfields, repeats; - -/* Dflag values */ -#define DF_NONE 0 -#define DF_NOSEP 1 -#define DF_PRESEP 2 -#define DF_POSTSEP 3 +static enum { DF_NONE, DF_NOSEP, DF_PRESEP, DF_POSTSEP } Dflag; +static bool cflag, dflag, uflag, iflag; +static long long numchars, numfields, repeats; static const struct option long_opts[] = { @@ -88,7 +84,7 @@ main (int argc, char *argv[]) int ch, comp; size_t prevbuflen, thisbuflen, b1; char *prevline, *thisline, *p; - const char *ifn, *errstr;; + const char *errstr, *ifn; cap_rights_t rights; (void) setlocale(LC_ALL, ""); @@ -108,13 +104,13 @@ main (int argc, char *argv[]) usage(); break; case 'c': - cflag = 1; + cflag = true; break; case 'd': - dflag = 1; + dflag = true; break; case 'i': - iflag = 1; + iflag = true; break; case 'f': numfields = strtonum(optarg, 0, INT_MAX, &errstr); @@ -127,7 +123,7 @@ main (int argc, char *argv[]) errx(1, "character skip value is %s: %s", errstr, optarg); break; case 'u': - uflag = 1; + uflag = true; break; case '?': default: @@ -140,6 +136,9 @@ main (int argc, char *argv[]) if (argc > 2) usage(); + if (Dflag && dflag) + dflag = false; + ifp = stdin; ifn = "stdin"; ofp = stdout; @@ -180,6 +179,8 @@ main (int argc, char *argv[]) err(1, "%s", ifn); exit(0); } + if (!cflag && !Dflag && !dflag && !uflag) + show(ofp, prevline); tprev = convert(prevline); tthis = NULL; @@ -199,7 +200,11 @@ main (int argc, char *argv[]) /* If different, print; set previous to new value. */ if (Dflag == DF_POSTSEP && repeats > 0) fputc('\n', ofp); - if (!Dflag) + if (!cflag && !Dflag && !dflag && !uflag) + show(ofp, thisline); + else if (!Dflag && + (!dflag || (cflag && repeats > 0)) && + (!uflag || repeats == 0)) show(ofp, prevline); p = prevline; b1 = prevbuflen; @@ -220,13 +225,20 @@ main (int argc, char *argv[]) show(ofp, prevline); } show(ofp, thisline); + } else if (dflag && !cflag) { + if (repeats == 0) + show(ofp, prevline); } ++repeats; } } if (ferror(ifp)) err(1, "%s", ifn); - if (!Dflag) + if (!cflag && !Dflag && !dflag && !uflag) + /* already printed */ ; + else if (!Dflag && + (!dflag || (cflag && repeats > 0)) && + (!uflag || repeats == 0)) show(ofp, prevline); exit(0); } @@ -291,11 +303,8 @@ inlcmp(const char *s1, const char *s2) static void show(FILE *ofp, const char *str) { - - if ((!Dflag && dflag && repeats == 0) || (uflag && repeats > 0)) - return; if (cflag) - (void)fprintf(ofp, "%4d %s", repeats + 1, str); + (void)fprintf(ofp, "%4lld %s", repeats + 1, str); else (void)fprintf(ofp, "%s", str); } @@ -303,7 +312,7 @@ show(FILE *ofp, const char *str) static wchar_t * skip(wchar_t *str) { - int nchars, nfields; + long long nchars, nfields; for (nfields = 0; *str != L'\0' && nfields++ != numfields; ) { while (iswblank(*str)) |
