Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162636963
D56505.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D56505.diff
View Options
diff --git a/usr.bin/ident/Makefile b/usr.bin/ident/Makefile
--- a/usr.bin/ident/Makefile
+++ b/usr.bin/ident/Makefile
@@ -2,6 +2,12 @@
PROG= ident
+.if ${MK_CASPER} != "no"
+LIBADD+= casper
+LIBADD+= cap_fileargs
+CFLAGS+= -DWITH_CASPER
+.endif
+
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/usr.bin/ident/ident.1 b/usr.bin/ident/ident.1
--- a/usr.bin/ident/ident.1
+++ b/usr.bin/ident/ident.1
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd July 25, 2015
+.Dd April 18, 2026
.Dt IDENT 1
.Os
.Sh NAME
@@ -52,15 +52,18 @@
.Pp
These options are supported:
.Bl -tag -width "XXX"
-.It Fl q
+.It Fl q , Fl -quiet
Quiet mode: suppress warnings if no pattern found.
-.It Fl V
+.It Fl V , Fl -version
Do nothing, added for compatibility with GNU ident.
.El
.Sh EXIT STATUS
.Ex -std ident
.Sh AUTHORS
+.An -nosplit
This version of the
.Nm
utility was written by
-.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org .
+.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org
+and
+.An Dag-Erling Sm\(/orrgav Aq Mt des@FreeBSD.org .
diff --git a/usr.bin/ident/ident.c b/usr.bin/ident/ident.c
--- a/usr.bin/ident/ident.c
+++ b/usr.bin/ident/ident.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2026 Dag-Erling Smørgrav <des@FreeBSD.org>
* Copyright (c) 2015-2021 Baptiste Daroussin <bapt@FreeBSD.org>
* Copyright (c) 2015 Xin LI <delphij@FreeBSD.org>
*
@@ -24,20 +25,24 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/capsicum.h>
#include <sys/types.h>
+#include <sys/capsicum.h>
#include <sys/sbuf.h>
#include <capsicum_helpers.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <getopt.h>
+#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <xlocale.h>
+
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
typedef enum {
/* state condition to transit to next state */
@@ -56,20 +61,20 @@
bool hasid = false;
bool subversion = false;
analyzer_states state = INIT;
- FILE* buffp;
+ FILE *buffp;
char *buf;
size_t sz;
- locale_t l;
- l = newlocale(LC_ALL_MASK, "C", NULL);
sz = 0;
buf = NULL;
- buffp = open_memstream(&buf, &sz);
- if (buffp == NULL)
- err(EXIT_FAILURE, "open_memstream()");
+ if ((buffp = open_memstream(&buf, &sz)) == NULL)
+ goto bufferr;
- if (name != NULL)
+ if (name != NULL) {
printf("%s:\n", name);
+ if (fflush(stdout) == EOF)
+ err(EXIT_FAILURE, "stdout");
+ }
while ((c = fgetc(fp)) != EOF) {
switch (state) {
@@ -83,13 +88,14 @@
}
break;
case DELIM_SEEN:
- if (isalpha_l(c, l)) {
+ if (isalpha(c)) {
/* Transit to KEYWORD if we see letter */
if (buf != NULL)
memset(buf, 0, sz);
- rewind(buffp);
- fputc('$', buffp);
- fputc(c, buffp);
+ if (fseek(buffp, 0, SEEK_SET) != 0 ||
+ fputc('$', buffp) == EOF ||
+ fputc(c, buffp) == EOF)
+ goto bufferr;
state = KEYWORD;
continue;
@@ -102,9 +108,10 @@
}
break;
case KEYWORD:
- fputc(c, buffp);
+ if (fputc(c, buffp) == EOF)
+ goto bufferr;
- if (isalpha_l(c, l)) {
+ if (isalpha(c)) {
/*
* Stay in KEYWORD if additional letter is seen
*/
@@ -132,7 +139,8 @@
break;
case PUNC_SEEN:
case PUNC_SEEN_SVN:
- fputc(c, buffp);
+ if (fputc(c, buffp) == EOF)
+ goto bufferr;
switch (c) {
case ':':
@@ -166,13 +174,15 @@
}
break;
case TEXT:
- fputc(c, buffp);
+ if (fputc(c, buffp) == EOF)
+ goto bufferr;
- if (iscntrl_l(c, l)) {
+ if (iscntrl(c)) {
/* Control characters are not allowed in this state */
state = INIT;
} else if (c == '$') {
- fflush(buffp);
+ if (fflush(buffp) == EOF)
+ goto bufferr;
/*
* valid ident should end with a space.
*
@@ -182,9 +192,11 @@
* subversion mode. No length check is enforced
* because GNU RCS ident(1) does not do it either.
*/
- c = buf[strlen(buf) -2 ];
+ c = buf[strlen(buf) - 2];
if (c == ' ' || (subversion && c == '#')) {
printf(" %s\n", buf);
+ if (fflush(stdout) == EOF)
+ err(EXIT_FAILURE, "stdout");
hasid = true;
}
state = INIT;
@@ -193,32 +205,49 @@
break;
}
}
- fclose(buffp);
+ if (fclose(buffp) == EOF)
+ goto bufferr;
free(buf);
- freelocale(l);
if (!hasid) {
- if (!quiet)
+ if (!quiet) {
fprintf(stderr, "%s warning: no id keywords in %s\n",
getprogname(), name ? name : "standard input");
-
+ }
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
+bufferr:
+ err(EXIT_FAILURE, "buffer");
}
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-q] [-V] [file...]", getprogname());
+ exit(EXIT_FAILURE);
+}
+
+static struct option longopts[] = {
+ { "quiet", no_argument, NULL, 'q' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+};
+
int
main(int argc, char **argv)
{
+ fileargs_t *fa;
+ cap_rights_t rights;
bool quiet = false;
- int ch, i, *fds, fd;
- int ret = EXIT_SUCCESS;
- size_t nfds;
+ int i, opt, ret;
FILE *fp;
- while ((ch = getopt(argc, argv, "qV")) != -1) {
- switch (ch) {
+ setlocale(LC_CTYPE, "C");
+
+ while ((opt = getopt_long(argc, argv, "+qV", longopts, NULL)) != -1) {
+ switch (opt) {
case 'q':
quiet = true;
break;
@@ -226,61 +255,36 @@
/* Do nothing, compat with GNU rcs's ident */
return (EXIT_SUCCESS);
default:
- errx(EXIT_FAILURE, "usage: %s [-q] [-V] [file...]",
- getprogname());
+ usage();
}
}
argc -= optind;
argv += optind;
- if (caph_limit_stdio() < 0)
- err(EXIT_FAILURE, "unable to limit stdio");
+ cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL);
+ fa = fileargs_init(argc, argv, O_RDONLY, 0, &rights, FA_OPEN);
+ if (fa == NULL)
+ err(EXIT_FAILURE, "Unable to initialize casper");
+ caph_cache_catpages();
+ if (caph_limit_stdio() != 0)
+ err(EXIT_FAILURE, "Unable to limit stdio");
+ if (caph_enter_casper() != 0)
+ err(EXIT_FAILURE, "Unable to enter capability mode");
if (argc == 0) {
- nfds = 1;
- fds = malloc(sizeof(*fds));
- if (fds == NULL)
- err(EXIT_FAILURE, "unable to allocate fds array");
- fds[0] = STDIN_FILENO;
+ ret = scan(stdin, NULL, quiet);
} else {
- nfds = argc;
- fds = malloc(sizeof(*fds) * nfds);
- if (fds == NULL)
- err(EXIT_FAILURE, "unable to allocate fds array");
-
+ ret = EXIT_SUCCESS;
for (i = 0; i < argc; i++) {
- fds[i] = fd = open(argv[i], O_RDONLY);
- if (fd < 0) {
- warn("%s", argv[i]);
+ if ((fp = fileargs_fopen(fa, argv[i], "r")) == NULL)
+ err(EXIT_FAILURE, "%s", argv[i]);
+ if (scan(fp, argv[i], quiet) != EXIT_SUCCESS)
ret = EXIT_FAILURE;
- continue;
- }
- if (caph_limit_stream(fd, CAPH_READ) < 0)
- err(EXIT_FAILURE,
- "unable to limit fcntls/rights for %s",
- argv[i]);
- }
- }
-
- /* Enter Capsicum sandbox. */
- if (caph_enter() < 0)
- err(EXIT_FAILURE, "unable to enter capability mode");
-
- for (i = 0; i < (int)nfds; i++) {
- if (fds[i] < 0)
- continue;
-
- fp = fdopen(fds[i], "r");
- if (fp == NULL) {
- warn("%s", argv[i]);
- ret = EXIT_FAILURE;
- continue;
+ (void)fclose(fp);
}
- if (scan(fp, argc == 0 ? NULL : argv[i], quiet) != EXIT_SUCCESS)
- ret = EXIT_FAILURE;
- fclose(fp);
}
+ fileargs_free(fa);
return (ret);
}
diff --git a/usr.bin/ident/tests/ident_test.sh b/usr.bin/ident/tests/ident_test.sh
--- a/usr.bin/ident/tests/ident_test.sh
+++ b/usr.bin/ident/tests/ident_test.sh
@@ -1,15 +1,89 @@
+#
+# Copyright (c) 2026 Dag-Erling Smørgrav <des@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
-atf_test_case ident
-ident_body() {
- atf_check -o file:$(atf_get_srcdir)/test.out \
- ident < $(atf_get_srcdir)/test.in
- atf_check -o match:'Foo.*' -s exit:1 \
- -e inline:"ident warning: no id keywords in $(atf_get_srcdir)/testnoid\n" \
- ident $(atf_get_srcdir)/test.in $(atf_get_srcdir)/testnoid
- atf_check -o match:'Foo.*' -s exit:1 \
- ident -q $(atf_get_srcdir)/test.in $(atf_get_srcdir)/testnoid
+atf_test_case stdin
+stdin_head()
+{
+ atf_set "descr" "Read from stdin"
+}
+stdin_body()
+{
+ local dir=$(atf_get_srcdir)
+ atf_check -o file:"${dir}/test.out" \
+ ident < "${dir}/test.in"
+}
+
+atf_test_case file
+file_head()
+{
+ atf_set "descr" "Read from a file"
+}
+file_body()
+{
+ local dir=$(atf_get_srcdir)
+ echo "${dir}/test.in:" >out
+ cat "${dir}/test.out" >>out
+ atf_check -o file:out ident "${dir}/test.in"
+}
+
+atf_test_case noid
+noid_head()
+{
+ atf_set "descr" "No id keywords in input"
+}
+noid_body()
+{
+ local dir=$(atf_get_srcdir)
+ atf_check \
+ -s exit:1 \
+ -o inline:"${dir}/testnoid:\n" \
+ -e inline:"ident warning: no id keywords in ${dir}/testnoid\n" \
+ ident "${dir}/testnoid"
+}
+
+atf_test_case multi
+multi_head()
+{
+ atf_set "descr" "Multiple inputs"
+}
+multi_body()
+{
+ local dir=$(atf_get_srcdir)
+ echo "${dir}/test.in:" >out
+ cat "${dir}/test.out" >>out
+ echo "${dir}/testnoid:" >>out
+ atf_check \
+ -s exit:1 \
+ -o file:out \
+ -e inline:"ident warning: no id keywords in ${dir}/testnoid\n" \
+ ident "${file}"
}
+
+atf_test_case stdout
+stdout_head()
+{
+ atf_set "descr" "Failure to write to stdout"
+}
+stdout_body()
+{
+ local dir=$(atf_get_srcdir)
+ (
+ trap "" PIPE
+ sleep 1
+ ident "${dir}"/test.in 2>stderr
+ echo $? >result
+ ) | true
+ atf_check -o inline:"1\n" cat result
+ atf_check -o match:"stdout" cat stderr
+}
+
atf_init_test_cases()
{
- atf_add_test_case ident
+ atf_add_test_case stdin
+ atf_add_test_case file
+ atf_add_test_case noid
+ atf_add_test_case stdout
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 16, 7:18 AM (58 m, 2 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35129084
Default Alt Text
D56505.diff (9 KB)
Attached To
Mode
D56505: ident: Clean up
Attached
Detach File
Event Timeline
Log In to Comment