ctags: Support writing to stdout instead of a file.

* Understand "-" to mean stdout as per convention.
* Check that the output is a regular file and ignore -u if not, otherwise we might try to rm /dev/stdout.
* As a bonus, if -u was specified but the output file does not exist, proceed as if -u had not been specified instead of erroring out.

MFC after:	1 week
Sponsored by:	Klara, Inc.
Reviewed by:	cracauer, debdrup
Differential Revision:	https://reviews.freebsd.org/D40237
This commit is contained in:
Dag-Erling Smørgrav 2023-05-25 11:55:56 +00:00
parent 4bf44dd73b
commit 430d064ba5
2 changed files with 35 additions and 6 deletions

View file

@ -28,7 +28,7 @@
.\" @(#)ctags.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
.Dd June 6, 1993
.Dd May 23, 2023
.Dt CTAGS 1
.Os
.Sh NAME
@ -93,16 +93,26 @@ Place the tag descriptions in a file called
.Ar tagsfile .
The default behaviour is to place them in a file called
.Pa tags .
If
.Ar tagsfile
is
.Dq - ,
the tags will be written to standard output instead.
.It Fl u
Update the specified files in the
.Pa tags
file, that is, all
references to them are deleted, and the new values are appended to the
file.
(Beware: this option is implemented in a way which is rather
This is ignored if the tags file does not exist or is not a regular
file (e.g.
.Fl f Ns -
was used to write to standard output).
.Pp
Beware: this option is implemented in a way which is rather
slow; it is usually faster to simply rebuild the
.Pa tags
file.)
file.
.It Fl v
An index of the form expected by
.Xr vgrind 1

View file

@ -42,11 +42,14 @@ static char sccsid[] = "@(#)ctags.c 8.4 (Berkeley) 2/7/95";
#endif
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/wait.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <locale.h>
#include <regex.h>
@ -143,6 +146,9 @@ main(int argc, char **argv)
if (!argc)
usage();
if (strcmp(outfile, "-") == 0)
outfile = "/dev/stdout";
if (!xflag)
setlocale(LC_COLLATE, "C");
@ -164,11 +170,23 @@ main(int argc, char **argv)
put_entries(head);
else {
if (uflag) {
struct stat sb;
FILE *oldf;
regex_t *regx;
if ((oldf = fopen(outfile, "r")) == NULL)
if ((oldf = fopen(outfile, "r")) == NULL) {
if (errno == ENOENT) {
uflag = 0;
goto udone;
}
err(1, "opening %s", outfile);
}
if (fstat(fileno(oldf), &sb) != 0 ||
!S_ISREG(sb.st_mode)) {
fclose(oldf);
uflag = 0;
goto udone;
}
if (unlink(outfile))
err(1, "unlinking %s", outfile);
if ((outf = fopen(outfile, "w")) == NULL)
@ -198,6 +216,7 @@ main(int argc, char **argv)
fclose(outf);
++aflag;
}
udone:
if (!(outf = fopen(outfile, aflag ? "a" : "w")))
err(1, "%s", outfile);
put_entries(head);