From nobody Fri Jan 12 15:44:28 2024 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4TBQnn1nYRz573cj; Fri, 12 Jan 2024 15:44:29 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4TBQnm6dXyz4M7s; Fri, 12 Jan 2024 15:44:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1705074268; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=yUyiqK9yK3XHn+NsSvDnziCfC4n/Dwh3jm0+1O1kSTM=; b=LrspZmOSLoFjuwCcAEOz7uTsYRYq779kUfS55BDqvO04jcPl0tZpxaljhKhmzxkVOiY+k+ 0rsFEmTZuVRKVaXkfRt1g+C96TD9evRyFUh1aGB/fKoL68jpAiwRN5xGtsDRY/TqGCESjw WHw0Zhc0Pa2p6X+AVbvSKx/H4JBNDYQESiTlc+73eR/YOcK/RVAK5t2f3ecldCPaDTFdXT zTS10Dn865uOg1Z0w8l17otQH39Coldsy75sO1dokWh+ckXElPhP1OXpayUY7zCLjUdD0B 575Z6goEPLE5GvBWCMyVN6Dk4cwEdAB3SNX8VtVZkpaKJQp4DcSPoMAanNObWg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1705074268; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=yUyiqK9yK3XHn+NsSvDnziCfC4n/Dwh3jm0+1O1kSTM=; b=fQf0SRkIF9lu9YHc9lLgZvn2UUXGnNBi8S2Pcu5z3+KRw80a9pjt2L/QP9o0yAkcukPlQV jSGWVTJ6WqtcjoA2ueNsJnsWnJy+QG1NsWCaetQNc4LRlR2wgzCmhn4MyRO40PqDi5p0Zw rnid++7JVje+nWBiRwla9dH2xyjZebniGp/URYzY9JCXlRR4CmL5uQuvlCndr5sJBF2ryw +PJnitMS3SpganJU2L0bWi+wpvJjCCKdyxzVLFctGcYE/g6egfqL/54ekcHRoSJdLmt4Jh KSeiC+h7Dj1fCuzqMelXQ5JkhYe07/bGvrQFw2HutF8PumfbBADxNXQt1VJncQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1705074269; a=rsa-sha256; cv=none; b=mh9Ex9ULHFK93Rjy2Xi3xI6HESHz2gpwc/QVz3LpGdtQS0wo/h6YmE4RYQ7KwwJL0XNsqE XGDuZ8Iq1DIXhugUO42ui0OEMzAOhLPTyue3Psbi8JJoF3RdjJWXFhZmxbTxUtLZ7W/ElR xWJDqdBEu4u7ijUHEggOZ5xJFuJQhz7rpTCC1M31VNirV2hb91BieztGTaY4F0P5Fg3x1F clQaANLf0YoS4G+jHc42JPwTzt7u+yo9xgpNBbwQbhAm9X37MHR544DhDDcjY3uuALDui1 uklHPAdOdPg629AZZBvo+aehSvk97R1aVayr+nxNX+5Jdxfx1GTWxRwqngutlw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4TBQnm5kpCz170n; Fri, 12 Jan 2024 15:44:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 40CFiSxK076636; Fri, 12 Jan 2024 15:44:28 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 40CFiSAe076633; Fri, 12 Jan 2024 15:44:28 GMT (envelope-from git) Date: Fri, 12 Jan 2024 15:44:28 GMT Message-Id: <202401121544.40CFiSAe076633@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Dag-Erling =?utf-8?Q?Sm=C3=B8rgrav?= Subject: git: 11715600e626 - main - uniq: Fix interactive use. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: des X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 11715600e626cf6cc4b4f564af97f6ae1e5fb0be Auto-Submitted: auto-generated The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=11715600e626cf6cc4b4f564af97f6ae1e5fb0be commit 11715600e626cf6cc4b4f564af97f6ae1e5fb0be Author: Dag-Erling Smørgrav AuthorDate: 2024-01-12 15:40:33 +0000 Commit: Dag-Erling Smørgrav CommitDate: 2024-01-12 15:43:55 +0000 uniq: Fix interactive use. Output a line as soon as it is possible to determine that it will have to be output. For the basic case, this means output each line as it is read unless it is identical to the previous one. For the -d case, it means output the first instance as soon as the second is read, unless the -c option was also given. The -D and -u cases were already fine. Add test cases for interactive use with no options and with -d. Explicitly ignore -d when -D is also specified. MFC after: 1 week Sponsored by: Klara, Inc. Reviewed by: rew, kevans Differential Revision: https://reviews.freebsd.org/D43382 --- usr.bin/uniq/tests/uniq_test.sh | 26 ++++++++++++++++++++++ usr.bin/uniq/uniq.1 | 5 ++++- 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 #include #include +#include #include #include #include @@ -51,14 +52,9 @@ #include #include -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))