calendar: correct the search order for files

Include files that don't begin with a '/' are documented to search the
current directory, then /usr/share/calendar.  This hasn't been accurate
for years, since e061f95e7b ("Rework calendar(1) parser") rewrote a
lot of this.

Stash off the cwd before we do any chdir()ing around and use that to
honor the same order we'll follow for the -f flag.  This may result in
an extra lookup that will fail for the initial calendar file, but I
don't think it's worth the complexity to avoid it.

While we're here, fix the documentation to just reference the order
described in FILES so that we only need to keep it up to date in one
place.

Reviewed by:	bapt
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D42278
This commit is contained in:
Kyle Evans 2023-12-17 23:53:03 -06:00
parent 7aa375dcc6
commit 0a82cd4f10
2 changed files with 34 additions and 4 deletions

View file

@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd July 31, 2022
.Dd December 17, 2023
.Dt CALENDAR 1
.Os
.Sh NAME
@ -213,9 +213,8 @@ succeeding lines.
.Pp
If the shared file is not referenced by a full pathname,
.Nm
searches in the current (or home) directory first, and then in the
directory
.Pa /usr/share/calendar .
searches in the same order of precedence described in
.Sx FILES .
.Pp
Blank lines and text protected by the C comment syntax
.Ql /* ... */

View file

@ -35,6 +35,7 @@
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libutil.h>
#include <locale.h>
#include <pwd.h>
@ -102,9 +103,11 @@ trimlr(char **buf)
static FILE *
cal_fopen(const char *file)
{
static int cwdfd = -1;
FILE *fp;
char *home = getenv("HOME");
unsigned int i;
int fd;
struct stat sb;
static bool warned = false;
static char calendarhome[MAXPATHLEN];
@ -114,6 +117,34 @@ cal_fopen(const char *file)
return (NULL);
}
/*
* On -a runs, we would have done a chdir() earlier on, but we also
* shouldn't have used the initial cwd anyways lest we bring
* unpredictable behavior upon us.
*/
if (!doall && cwdfd == -1) {
cwdfd = open(".", O_DIRECTORY | O_PATH);
if (cwdfd == -1)
err(1, "open(cwd)");
}
/*
* Check $PWD first as documented.
*/
if (cwdfd != -1) {
if ((fd = openat(cwdfd, file, O_RDONLY)) != -1) {
if ((fp = fdopen(fd, "r")) == NULL)
err(1, "fdopen(%s)", file);
cal_home = NULL;
cal_dir = NULL;
cal_file = file;
return (fp);
} else if (errno != ENOENT && errno != ENAMETOOLONG) {
err(1, "open(%s)", file);
}
}
if (chdir(home) != 0) {
warnx("Cannot enter home directory \"%s\"", home);
return (NULL);