svn commit: r285291 - stable/10/usr.bin/calendar
Baptiste Daroussin
bapt at FreeBSD.org
Wed Jul 8 21:06:22 UTC 2015
Author: bapt
Date: Wed Jul 8 21:06:19 2015
New Revision: 285291
URL: https://svnweb.freebsd.org/changeset/base/285291
Log:
MFC: r279597 (and 259152,259219 as dependency)
Make calendar(1) usable again. rework the calendar parser so that it is
compatible with documented format:
Support includes surrounded by '"' or '<' '>'
Print warnings about bad syntax
Correctly navigate through include directories to find calendar files
Correctly support multiple includes
While here:
MFC: 262011 (by eadler)
calendar(1): don't segfault in invalid input
When the user supplies an invalid number of days provide a useful error message
instead of segfaulting.
Approved by: re (gjb)
Deleted:
stable/10/usr.bin/calendar/calcpp.c
Modified:
stable/10/usr.bin/calendar/Makefile
stable/10/usr.bin/calendar/calendar.c
stable/10/usr.bin/calendar/calendar.h
stable/10/usr.bin/calendar/io.c
Directory Properties:
stable/10/ (props changed)
Modified: stable/10/usr.bin/calendar/Makefile
==============================================================================
--- stable/10/usr.bin/calendar/Makefile Wed Jul 8 19:26:36 2015 (r285290)
+++ stable/10/usr.bin/calendar/Makefile Wed Jul 8 21:06:19 2015 (r285291)
@@ -5,7 +5,7 @@
PROG= calendar
SRCS= calendar.c locale.c events.c dates.c parsedata.c io.c day.c \
- ostern.c paskha.c pom.c sunpos.c calcpp.c
+ ostern.c paskha.c pom.c sunpos.c
DPADD= ${LIBM}
LDADD= -lm
INTER= de_AT.ISO_8859-15 de_DE.ISO8859-1 fr_FR.ISO8859-1 \
Modified: stable/10/usr.bin/calendar/calendar.c
==============================================================================
--- stable/10/usr.bin/calendar/calendar.c Wed Jul 8 19:26:36 2015 (r285290)
+++ stable/10/usr.bin/calendar/calendar.c Wed Jul 8 21:06:19 2015 (r285291)
@@ -96,10 +96,14 @@ main(int argc, char *argv[])
case 'A': /* days after current date */
f_dayAfter = atoi(optarg);
+ if (f_dayAfter < 0)
+ errx(1, "number of days must be positive");
break;
case 'B': /* days before current date */
f_dayBefore = atoi(optarg);
+ if (f_dayBefore < 0)
+ errx(1, "number of days must be positive");
break;
case 'D': /* debug output of sun and moon info */
Modified: stable/10/usr.bin/calendar/calendar.h
==============================================================================
--- stable/10/usr.bin/calendar/calendar.h Wed Jul 8 19:26:36 2015 (r285290)
+++ stable/10/usr.bin/calendar/calendar.h Wed Jul 8 21:06:19 2015 (r285291)
@@ -168,10 +168,6 @@ void closecal(FILE *);
FILE *opencalin(void);
FILE *opencalout(void);
-/* calcpp.c */
-void initcpp(void);
-FILE *fincludegets(char *buf, int size, FILE *fp);
-
/* ostern.c / paskha.c */
int paskha(int);
int easter(int);
Modified: stable/10/usr.bin/calendar/io.c
==============================================================================
--- stable/10/usr.bin/calendar/io.c Wed Jul 8 19:26:36 2015 (r285290)
+++ stable/10/usr.bin/calendar/io.c Wed Jul 8 21:06:19 2015 (r285291)
@@ -51,14 +51,23 @@ __FBSDID("$FreeBSD$");
#include <langinfo.h>
#include <locale.h>
#include <pwd.h>
+#include <stdbool.h>
+#define _WITH_GETLINE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stringlist.h>
#include <unistd.h>
#include "pathnames.h"
#include "calendar.h"
+enum {
+ T_OK = 0,
+ T_ERR,
+ T_PROCESS,
+};
+
const char *calendarFile = "calendar"; /* default calendar file */
static const char *calendarHomes[] = {".calendar", _PATH_INCLUDE}; /* HOME */
static const char *calendarNoMail = "nomail";/* don't sent mail if file exist */
@@ -68,6 +77,147 @@ static char path[MAXPATHLEN];
struct fixs neaster, npaskha, ncny, nfullmoon, nnewmoon;
struct fixs nmarequinox, nsepequinox, njunsolstice, ndecsolstice;
+static int cal_parse(FILE *in, FILE *out);
+
+static StringList *definitions = NULL;
+static struct event *events[MAXCOUNT];
+static char *extradata[MAXCOUNT];
+
+static void
+trimlr(char **buf)
+{
+ char *walk = *buf;
+
+ while (isspace(*walk))
+ walk++;
+ while (isspace(walk[strlen(walk) -1]))
+ walk[strlen(walk) -1] = '\0';
+
+ *buf = walk;
+}
+
+static FILE *
+cal_fopen(const char *file)
+{
+ FILE *fp;
+ char *home = getenv("HOME");
+ unsigned int i;
+
+ if (home == NULL || *home == '\0') {
+ warnx("Cannot get home directory");
+ return (NULL);
+ }
+
+ if (chdir(home) != 0) {
+ warnx("Cannot enter home directory");
+ return (NULL);
+ }
+
+ for (i = 0; i < sizeof(calendarHomes)/sizeof(calendarHomes[0]) ; i++) {
+ if (chdir(calendarHomes[i]) != 0)
+ continue;
+
+ if ((fp = fopen(file, "r")) != NULL)
+ return (fp);
+ }
+
+ warnx("can't open calendar file \"%s\"", file);
+
+ return (NULL);
+}
+
+static int
+token(char *line, FILE *out, bool *skip)
+{
+ char *walk, c, a;
+
+ if (strncmp(line, "endif", 5) == 0) {
+ *skip = false;
+ return (T_OK);
+ }
+
+ if (*skip)
+ return (T_OK);
+
+ if (strncmp(line, "include", 7) == 0) {
+ walk = line + 7;
+
+ trimlr(&walk);
+
+ if (*walk == '\0') {
+ warnx("Expecting arguments after #include");
+ return (T_ERR);
+ }
+
+ if (*walk != '<' && *walk != '\"') {
+ warnx("Excecting '<' or '\"' after #include");
+ return (T_ERR);
+ }
+
+ a = *walk;
+ walk++;
+ c = walk[strlen(walk) - 1];
+
+ switch(c) {
+ case '>':
+ if (a != '<') {
+ warnx("Unterminated include expecting '\"'");
+ return (T_ERR);
+ }
+ break;
+ case '\"':
+ if (a != '\"') {
+ warnx("Unterminated include expecting '>'");
+ return (T_ERR);
+ }
+ break;
+ default:
+ warnx("Unterminated include expecting '%c'",
+ a == '<' ? '>' : '\"' );
+ return (T_ERR);
+ }
+ walk[strlen(walk) - 1] = '\0';
+
+ if (cal_parse(cal_fopen(walk), out))
+ return (T_ERR);
+
+ return (T_OK);
+ }
+
+ if (strncmp(line, "define", 6) == 0) {
+ if (definitions == NULL)
+ definitions = sl_init();
+ walk = line + 6;
+ trimlr(&walk);
+
+ if (*walk == '\0') {
+ warnx("Expecting arguments after #define");
+ return (T_ERR);
+ }
+
+ sl_add(definitions, strdup(walk));
+ return (T_OK);
+ }
+
+ if (strncmp(line, "ifndef", 6) == 0) {
+ walk = line + 6;
+ trimlr(&walk);
+
+ if (*walk == '\0') {
+ warnx("Expecting arguments after #ifndef");
+ return (T_ERR);
+ }
+
+ if (definitions != NULL && sl_find(definitions, walk) != NULL)
+ *skip = true;
+
+ return (T_OK);
+ }
+
+ return (T_PROCESS);
+
+}
+
#define REPLACE(string, slen, struct_) \
if (strncasecmp(buf, (string), (slen)) == 0 && buf[(slen)]) { \
if (struct_.name != NULL) \
@@ -77,30 +227,25 @@ struct fixs nmarequinox, nsepequinox, nj
struct_.len = strlen(buf + (slen)); \
continue; \
}
-void
-cal(void)
+static int
+cal_parse(FILE *in, FILE *out)
{
- char *pp, p;
- FILE *fpin;
- FILE *fpout;
- int l;
- int count, i;
+ char *line = NULL;
+ char *buf;
+ size_t linecap = 0;
+ ssize_t linelen;
+ ssize_t l;
+ static int d_first = -1;
+ static int count = 0;
+ int i;
int month[MAXCOUNT];
int day[MAXCOUNT];
int year[MAXCOUNT];
- char **extradata; /* strings of 20 length */
- int flags;
- static int d_first = -1;
- char buf[2048 + 1];
- struct event *events[MAXCOUNT];
- struct tm tm;
+ bool skip = false;
char dbuf[80];
-
- initcpp();
- extradata = (char **)calloc(MAXCOUNT, sizeof(char *));
- for (i = 0; i < MAXCOUNT; i++) {
- extradata[i] = (char *)calloc(1, 20);
- }
+ char *pp, p;
+ struct tm tm;
+ int flags;
/* Unused */
tm.tm_sec = 0;
@@ -108,20 +253,32 @@ cal(void)
tm.tm_hour = 0;
tm.tm_wday = 0;
- count = 0;
- if ((fpin = opencalin()) == NULL) {
- free(extradata);
- return;
- }
- if ((fpout = opencalout()) == NULL) {
- fclose(fpin);
- free(extradata);
- return;
- }
- while ((fpin = fincludegets(buf, sizeof(buf), fpin)) != NULL) {
- if (*buf == '\0')
+ if (in == NULL)
+ return (1);
+
+ while ((linelen = getline(&line, &linecap, in)) > 0) {
+ if (linelen == 0)
+ continue;
+
+ if (*line == '#') {
+ switch (token(line+1, out, &skip)) {
+ case T_ERR:
+ free(line);
+ return (1);
+ case T_OK:
+ continue;
+ case T_PROCESS:
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (skip)
continue;
- for (l = strlen(buf);
+
+ buf = line;
+ for (l = linelen;
l > 0 && isspace((unsigned char)buf[l - 1]);
l--)
;
@@ -208,16 +365,41 @@ cal(void)
}
}
+ free(line);
+ fclose(in);
+
+ return (0);
+}
+
+void
+cal(void)
+{
+ FILE *fpin;
+ FILE *fpout;
+ int i;
+
+ for (i = 0; i < MAXCOUNT; i++)
+ extradata[i] = (char *)calloc(1, 20);
+
+
+ if ((fpin = opencalin()) == NULL)
+ return;
+
+ if ((fpout = opencalout()) == NULL) {
+ fclose(fpin);
+ return;
+ }
+
+ if (cal_parse(fpin, fpout))
+ return;
+
event_print_all(fpout);
closecal(fpout);
- free(extradata);
}
FILE *
opencalin(void)
{
- size_t i;
- int found;
struct stat sbuf;
FILE *fpin;
@@ -231,22 +413,7 @@ opencalin(void)
if ((fpin = fopen(calendarFile, "r")) == NULL)
return (NULL);
} else {
- char *home = getenv("HOME");
- if (home == NULL || *home == '\0')
- errx(1, "cannot get home directory");
- if (chdir(home) != 0)
- errx(1, "cannot enter home directory");
- for (found = i = 0; i < sizeof(calendarHomes) /
- sizeof(calendarHomes[0]); i++)
- if (chdir(calendarHomes[i]) == 0 &&
- (fpin = fopen(calendarFile, "r")) != NULL) {
- found = 1;
- break;
- }
- if (!found)
- errx(1,
- "can't open calendar file \"%s\": %s (%d)",
- calendarFile, strerror(errno), errno);
+ fpin = cal_fopen(calendarFile);
}
}
return (fpin);
More information about the svn-src-stable-10
mailing list