summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2015-07-08 21:06:19 +0000
committerbapt <bapt@FreeBSD.org>2015-07-08 21:06:19 +0000
commit2ba8e41f9e7474b40923e02735dc5f527818594d (patch)
treecafd04b6224298b15beba36ebfb5baa412deee55 /usr.bin
parent6ca1356aa84bbb621e97949e9af5847201a3757e (diff)
downloadFreeBSD-src-2ba8e41f9e7474b40923e02735dc5f527818594d.zip
FreeBSD-src-2ba8e41f9e7474b40923e02735dc5f527818594d.tar.gz
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)
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/calendar/Makefile2
-rw-r--r--usr.bin/calendar/calcpp.c229
-rw-r--r--usr.bin/calendar/calendar.c4
-rw-r--r--usr.bin/calendar/calendar.h4
-rw-r--r--usr.bin/calendar/io.c269
5 files changed, 223 insertions, 285 deletions
diff --git a/usr.bin/calendar/Makefile b/usr.bin/calendar/Makefile
index b347a52..6b7a6f4 100644
--- a/usr.bin/calendar/Makefile
+++ b/usr.bin/calendar/Makefile
@@ -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 \
diff --git a/usr.bin/calendar/calcpp.c b/usr.bin/calendar/calcpp.c
deleted file mode 100644
index 6e3b339..0000000
--- a/usr.bin/calendar/calcpp.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*-
- * Copyright (c) 2013 Diane Bruce
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/* calendar fake cpp does a very limited cpp version */
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <assert.h>
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <langinfo.h>
-#include <locale.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "pathnames.h"
-#include "calendar.h"
-
-#define MAXFPSTACK 50
-static FILE *fpstack[MAXFPSTACK];
-static int curfpi;
-static void pushfp(FILE *fp);
-static FILE *popfp(void);
-static int tokenscpp(char *buf, char *string);
-
-#define T_INVALID -1
-#define T_INCLUDE 0
-#define T_DEFINE 1
-#define T_IFNDEF 2
-#define T_ENDIF 3
-
-#define MAXSYMS 100
-static char *symtable[MAXSYMS];
-static void addsym(const char *name);
-static int findsym(const char *name);
-
-FILE *
-fincludegets(char *buf, int size, FILE *fp)
-{
- char name[MAXPATHLEN];
- FILE *nfp=NULL;
- char *p;
- int ch;
-
- if (fp == NULL)
- return(NULL);
-
- if (fgets(buf, size, fp) == NULL) {
- *buf = '\0';
- fclose(fp);
- fp = popfp();
- return (fp);
- }
- if ((p = strchr(buf, '\n')) != NULL)
- *p = '\0';
- else {
- /* Flush this line */
- while ((ch = fgetc(fp)) != '\n' && ch != EOF);
- if (ch == EOF) {
- *buf = '\0';
- fclose(fp);
- fp = popfp();
- return(fp);
- }
- }
- switch (tokenscpp(buf, name)) {
- case T_INCLUDE:
- *buf = '\0';
- if ((nfp = fopen(name, "r")) != NULL) {
- pushfp(fp);
- fp = nfp;
- }
- break;
- case T_DEFINE:
- addsym(name);
- break;
- case T_IFNDEF:
- if (findsym(name)) {
- fclose(fp);
- fp = popfp();
- *buf = '\0';
- }
- break;
- case T_ENDIF:
- *buf = '\0';
- break;
- default:
- break;
- }
- return (fp);
-}
-
-static int
-tokenscpp(char *buf, char *string)
-{
- char *p;
- char *s;
-
- if ((p = strstr(buf, "#define")) != NULL) {
- p += 8;
- while (isspace((unsigned char)*p))
- p++;
- s = p;
- while(!isspace((unsigned char)*p))
- p++;
- strncpy(string, s, MAXPATHLEN);
- return(T_DEFINE);
- } else if ((p = strstr(buf, "#ifndef")) != NULL) {
- p += 8;
- while (isspace((unsigned char)*p))
- p++;
- s = p;
- while(!isspace((unsigned char)*p))
- p++;
- *p = '\0';
- strncpy(string, s, MAXPATHLEN);
- return(T_IFNDEF);
- } else if ((p = strstr(buf, "#endif")) != NULL) {
- return(T_ENDIF);
- } if ((p = strstr(buf, "#include")) != NULL) {
- p += 8;
- while (isspace((unsigned char)*p))
- p++;
- if (*p == '<') {
- s = p+1;
- if ((p = strchr(s, '>')) != NULL)
- *p = '\0';
- snprintf (string, MAXPATHLEN, "%s/%s",
- _PATH_INCLUDE, s);
- } else if (*p == '(') {
- s = p+1;
- if ((p = strchr(p, '>')) != NULL)
- *p = '\0';
- snprintf (string, MAXPATHLEN, "%s", s);
- }
- return(T_INCLUDE);
- }
- return(T_INVALID);
-}
-
-static void
-pushfp(FILE *fp)
-{
- curfpi++;
- if (curfpi == MAXFPSTACK)
- errx(1, "Max #include reached");
- fpstack[curfpi] = fp;
-}
-
-static
-FILE *popfp(void)
-{
- FILE *tmp;
-
- assert(curfpi >= 0);
- tmp = fpstack[curfpi];
- curfpi--;
- return(tmp);
-}
-
-void
-initcpp(void)
-{
- int i;
-
- for (i=0; i < MAXSYMS; i++)
- symtable[i] = NULL;
- fpstack[0] = NULL;
- curfpi = 0;
-}
-
-
-static void
-addsym(const char *name)
-{
- int i;
-
- if (!findsym(name))
- for (i=0; i < MAXSYMS; i++) {
- if (symtable[i] == NULL) {
- symtable[i] = strdup(name);
- if (symtable[i] == NULL)
- errx(1, "malloc error in addsym");
- return;
- }
- }
- errx(1, "symbol table full\n");
-}
-
-static int
-findsym(const char *name)
-{
- int i;
-
- for (i=0; i < MAXSYMS; i++)
- if (symtable[i] != NULL && strcmp(symtable[i],name) == 0)
- return (1);
- return (0);
-}
diff --git a/usr.bin/calendar/calendar.c b/usr.bin/calendar/calendar.c
index 2a107c2..84d1880 100644
--- a/usr.bin/calendar/calendar.c
+++ b/usr.bin/calendar/calendar.c
@@ -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 */
diff --git a/usr.bin/calendar/calendar.h b/usr.bin/calendar/calendar.h
index 0138fd2..1113c4a 100644
--- a/usr.bin/calendar/calendar.h
+++ b/usr.bin/calendar/calendar.h
@@ -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);
diff --git a/usr.bin/calendar/io.c b/usr.bin/calendar/io.c
index 0f34882..fd030c1 100644
--- a/usr.bin/calendar/io.c
+++ b/usr.bin/calendar/io.c
@@ -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, njunsolstice, ndecsolstice;
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;
- for (l = strlen(buf);
+
+ 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;
+
+ 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);
OpenPOWER on IntegriCloud