aboutsummaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2024-01-12 15:40:33 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2024-01-12 15:43:55 +0000
commit11715600e626cf6cc4b4f564af97f6ae1e5fb0be (patch)
tree146bf74cdf51ce742620fdc67f8d80cc3f07efa9 /usr.bin
parente762fd81e253d4ae9b9f7d2e65cf448633bbe527 (diff)
Diffstat (limited to 'usr.bin')
-rwxr-xr-xusr.bin/uniq/tests/uniq_test.sh26
-rw-r--r--usr.bin/uniq/uniq.15
-rw-r--r--usr.bin/uniq/uniq.c49
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))