extsmail-2.0004075500017500001750000000000001243070540200125715ustar00ltrattltrattextsmail-2.0/CREDITS010064400017500001750000000005101243070540200136610ustar00ltrattltratt================================================================================ extsmail credits ================================================================================ I thank the following people for their role in extsmail's development (in alphabetical order): Geerd-Dietger "Didi" Hoffmann Olivier Girondelextsmail-2.0/Config.h.in010064400017500001750000000051321243070540200146310ustar00ltrattltratt/* Config.h.in. Generated from configure.ac by autoheader. */ /* Define if your platform has the inotify family of functions. */ #undef HAVE_INOTIFY /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define if your platform has the kqueue family of functions. */ #undef HAVE_KQUEUE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define if your platform has the strtonum function. */ #undef HAVE_STRTONUM /* Define to 1 if you have the header file. */ #undef HAVE_SYS_INOTIFY_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define if lex/flex has yylex_destroy */ #undef HAVE_YYLEX_DESTROY /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE extsmail-2.0/HISTORY010064400017500001750000000066141243070540200137400ustar00ltrattltratt============================================================================ extsmail history ============================================================================ extsmail 2.0 (2014-11-12) * Reload configuration file when SIGHUP is received. * Added -t option to check a configuration file without running extsmaild. * Be more careful to free all file handles. extsmail 1.9 (2014-06-20) * Fix bug which could temporarily cause undue CPU to be consumed when a large file send was cut off in the middle. This didn't prevent mail being sent correctly in the end, but was ugly. extsmail 1.8 (2014-05-29) * Fix bug which caused extsmaild to consume larger amounts of CPU than strictly necessary (a normal user should now be able to run extsmaild for several days before exceeding 1 second of CPU usage). * Fix reporting of sent mail on Linux (which previously sent mail correctly, but incorrectly reported failure even when the send was successful). * Various fixes to make OS packager's lives easier. * Significant code reorganisation to improve readability. extsmail 1.7 (2014-03-12) * Several minor bug fixes spotted by static analysis tools (including memory leaks). * More robust handling of corrupt message files. extsmail 1.6 (2012-11-17) * Time out stalled sendmail processes. If a sendmail process hasn't read or written any data for 60 seconds, it is killed and later retried. This stops a stalled sendmail from perpetually blocking extsmail. Although rare, this could happen e.g. when an interface went down while an SSH session was open. extsmail 1.5 (2012-07-09) * Ensure that all messages which can be sent are sent. Some messages may temporarily be unsendable (e.g. because of size) and shouldn't hold up others. * Use exponential backoff when retrying. Quite often, a send failure is just a brief blip, so retry quickly, and as retries fail, increase the length of time until the next retry. * Add user-configurable notifications for successful / unsuccessful sends. Allows users to easily be notified (e.g. via xosd) if mail has been sent and, if not, how long it has been since everything was sent. * Various portability improvements. * Improvements to batch mode to bring it in line with daemon mode. extsmail 1.4 (2011-06-18) * Minor bug fixes. * Documentation fixes. extsmail 1.3 (2010-05-30) * OS X compile fixes. * Fix overly-restrictive configuration permissions check. * Recover gracefully from some errors that were previously fatal. extsmail 1.2 (2009-09-24) * Fix build error when using bison. * Minor documentation fixes. extsmail 1.1 (2009-04-29) * Fix two frees of possibly uninitialised pointers. extsmail 1.0 (2009-01-05) * extsmaild's modes are now specified via the "-m " switch. In particular the behaviour of the "-d" switch is now obtained with "-m daemon". * More intelligent detection of whether a previous instance of extsmaild is running or not. * Systematically use syslog. * Fix possible race condition between extsmail and extsmaild. * Correctly handle SIGPIPE. extsmail 0.3 (2008-12-11) * Make Linux support on a par with BSD (using inotify). * Minor error handling / reporting changes. extsmail 0.2 (2008-11-20) * Adds 'timeout' feature to externals. * Fixes bug where exec'd externals first parameter was not correctly set. extsmail 0.1 (2008-11-11) * First public release. extsmail-2.0/INSTALL010064400017500001750000000007051243070540200137000ustar00ltrattltratt================================================================================ extsmail installation ================================================================================ extsmail follows the standard UNIX installation sequence: $ ./configure $ make $ make install Please note that if, and only if, you are building from the git repository you will first need to execute make -f Makefile.bootstrap to build the configure script. extsmail-2.0/Makefile.in010064400017500001750000000037751243070540200147260ustar00ltrattltrattCC=@CC@ CFLAGS=@CFLAGS@ LIBS=@LIBS@ LDFLAGS=@LDFLAGS@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ bindir = @bindir@ mandir = @mandir@ INSTALL = @INSTALL@ all: extsmail extsmaild EXTSMAIL_OBJS = conf_parser.tab.o conf_tokenizer.o extsmail.o common.o extsmail: ${EXTSMAIL_OBJS} ${CC} -o extsmail ${EXTSMAIL_OBJS} ${LDFLAGS} EXTSMAILD_OBJS = conf_parser.tab.o conf_tokenizer.o externals_parser.tab.o \ externals_tokenizer.o extsmaild.o common.o @COMPAT_STRTONUM@ extsmaild: ${EXTSMAILD_OBJS} ${CC} -o extsmaild ${EXTSMAILD_OBJS} ${LDFLAGS} conf_parser.tab.c: conf_parser.y yacc -p yyc -d -b conf_parser conf_parser.y conf_tokenizer.c: conf_tokenizer.l lex -Pyyc -oconf_tokenizer.c conf_tokenizer.l externals_parser.tab.c: externals_parser.y yacc -p yye -d -b externals_parser externals_parser.y externals_tokenizer.c: externals_tokenizer.l lex -Pyye -oexternals_tokenizer.c externals_tokenizer.l install: all install -d ${DESTDIR}${bindir} install -c -m 555 extsmail ${DESTDIR}${bindir} install -c -m 555 extsmaild ${DESTDIR}${bindir} install -d ${DESTDIR}${mandir}/man1 install -d ${DESTDIR}${mandir}/man5 install -c -m 444 extsmail.1 ${DESTDIR}${mandir}/man1/extsmail.1 install -c -m 444 extsmail.conf.5 \ ${DESTDIR}${mandir}/man5/extsmail.conf.5 install -c -m 444 extsmail.externals.5 \ ${DESTDIR}${mandir}/man5/extsmail.externals.5 install -c -m 444 extsmaild.1 ${DESTDIR}${mandir}/man1/extsmaild.1 clean: rm -f extsmail extsmaild ${EXTSMAIL_OBJS} ${EXTSMAILD_OBJS} \ conf_parser.tab.[ch] externals_parser.tab.[ch] conf_tokenizer.c \ externals_tokenizer.c distclean: clean rm -rf configure Makefile Config.h Config.h.in autom4te.cache config.log \ config.status distrib: ${MAKE} distclean ${MAKE} -f Makefile.bootstrap @read v?'extsmail version: '; mkdir extsmail-$$v; \ cp -r `ls | grep -E -v "(autom4te.cache)|(Makefile.bootstrap)|(extsmail-$$v)"` extsmail-$$v; \ tar cfz extsmail-$$v.tar.gz extsmail-$$v; rm -rf extsmail-$$v extsmail-2.0/README010064400017500001750000000012711243070540200135260ustar00ltrattltratt================================================================================ extsmail ================================================================================ extsmail enables the robust sending of e-mail to external commands. In effect extsmail masquerades as the standard UNIX sendmail program, reading messages, and later trying to send them by user-defined commands. A typical use of extsmail is to allow users who regularly move between different networks and / or find themselves regularly offline, to ensure that their e-mail is sent reliably via ssh to external servers. More information about extsmail can be found at its webpage: http://tratt.net/laurie/src/extsmail/ extsmail-2.0/common.c010064400017500001750000000206151243070540200143050ustar00ltrattltratt// Copyright (C)2008 Laurence Tratt http://tratt.net/laurie/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. #include "Config.h" #include #include #include #include #include #include #include #include #include #include #include "conf.h" #include "common.h" #include "conf_parser.tab.h" static const char *CONF_PATHS[] = {"~/.extsmail/conf", "/etc/extsmail/conf", NULL}; #define HOME_PFX "~/" static int try_conf_path(const char *); static bool check_dir(const char *); //////////////////////////////////////////////////////////////////////////////// // Configuration related // extern int yycparse(void); #if HAVE_YYLEX_DESTROY extern void yyclex_destroy(void); #endif extern FILE *yycin; Conf *conf = NULL; // Global variable needed for Yacc. Sigh. // // Read the configuration file. // Conf *read_conf() { conf = malloc(sizeof(Conf)); if (conf == NULL) errx(1, "read_conf: unable to allocate memory"); conf->spool_dir = NULL; conf->notify_failure_interval = 0; conf->notify_failure_cmd = NULL; conf->notify_success_cmd = NULL; int i; for (i = 0; CONF_PATHS[i] != NULL; i += 1) { int rtn = try_conf_path(CONF_PATHS[i]); if (rtn == 0) break; else if (rtn == -1) exit(1); } if (CONF_PATHS[i] == NULL) err(1, "Can't find a valid configuration file"); return conf; } // // Free configuration // void free_conf(Conf *conf) { free(conf->spool_dir); free(conf); } // // Attempts to read a configuration file at 'path'; returns 0 on success, 1 if a // file is not found and -1 if an error occurred. // static int try_conf_path(const char *path) { char *cnd_path = expand_path(path); if (cnd_path == NULL) { return -1; } yycin = fopen(cnd_path, "rt"); free(cnd_path); if (yycin == NULL) { if (errno == ENOENT) return 1; return -1; } if (yycparse() != 0) { fclose(yycin); return -1; } fclose(yycin); #if HAVE_YYLEX_DESTROY yyclex_destroy(); #endif return 0; } // // Check that the spool dir is correctly setup, returning true if so and false // if problems are found. // bool check_spool_dir(Conf *conf) { if (conf->spool_dir == NULL) { warnx("spool_dir not defined"); return false; } if (!check_dir(conf->spool_dir)) return false; char *mdp; // spool path if (asprintf(&mdp, "%s%s%s", conf->spool_dir, DIR_SEP, MSGS_DIR) == -1) errx(1, "check_spool_dir: asprintf: unable to allocate memory"); if (!check_dir(mdp)) { free(mdp); return false; } free(mdp); return true; } static bool check_dir(const char *path) { struct stat sd_st; if (stat(path, &sd_st) == -1) { if (errno == ENOENT) { // If the directory does not exist, we try and create it. if (mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { warn("%s", path); return false; } // There's no need to go through the rest of the checks; since // mk_dir was successful, spool_dir now exists as a directory with // the correct permissions. return true; } else { warn("%s", path); return false; } } // 'path' must be a directory. if (!S_ISDIR(sd_st.st_mode)) { warnx("%s: Exists and is not a directory", path); return false; } // 'path' must have owner only having rwx access. if ((sd_st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXG)) != (S_IRUSR | S_IWUSR | S_IXUSR)) { warnx("%s: Incorrect permissions (should be %.o)", path, S_IRUSR | S_IWUSR | S_IXUSR); return false; } return true; } //////////////////////////////////////////////////////////////////////////////// // Misc // // // Reads a malloc'd NULL-terminated line from 'fd', stripping any newlines // from the end. // // Upon error NULL is returned. // char *fdrdline(int fd) { # define TMPBUFLEN 128 char tmpbuf[TMPBUFLEN]; char *line = NULL; size_t line_len = 0; size_t line_alloc = 0; while (1) { ssize_t nr = read(fd, &tmpbuf, TMPBUFLEN); if (nr == 0) break; else if (nr == -1) { if (line != NULL) { free(line); return NULL; } } off_t i; for (i = 0; i < nr; i++) { if (tmpbuf[i] == '\n' || tmpbuf[i] == '\r') break; } if (line == NULL) { line_alloc = i + 1; line = malloc(line_alloc); if (line == NULL) errx(1, "fdrdline: malloc"); } else if (line_alloc < line_len + i + 1) { line = realloc(line, line_len + i + 1); if (line == NULL) errx(1, "fdrdline: realloc"); } memcpy(line + line_len, tmpbuf, i); line_len += i; if (i < nr) { if (lseek(fd, 1 -(nr - i), SEEK_CUR) == -1) { free(line); return NULL; } break; } } // If we didn't read in any data, then we hit EOF. The user is expected to // have detected that condition, so we return NULL. if (line == NULL) return NULL; line[line_len] = 0; return line; } // // Performs tilde expansion on 'path'. This returns a malloc'd object with the // new path in (regardless of whether expansion occurred or not) unless an error // occurred in which case NULL is returned. // char *expand_path(const char *path) { char *exp_path; // If path begins with "~/", we expand that to the users home directory. if (strncmp(path, HOME_PFX, strlen(HOME_PFX)) == 0) { struct passwd *pw_ent = getpwuid(geteuid()); if (pw_ent == NULL) return NULL; if (asprintf(&exp_path, "%s%s%s", pw_ent->pw_dir, DIR_SEP, path + strlen(HOME_PFX)) == -1) errx(1, "expand_path: asprintf: unable to allocate memory"); } else if (asprintf(&exp_path, "%s", path) == -1) errx(1, "expand_path: asprintf: unable to allocate memory"); return exp_path; } char *mk_str(char *str) { char *buf = malloc(strlen(str) + 1); if (buf == NULL) errx(1, "mk_str: malloc"); memmove(buf, str, strlen(str) + 1); return buf; } char *str_replace(const char *str, const char *old, const char *new) { size_t new_size = 0, i = 0; while (i < strlen(str)) { if (i < strlen(str) - strlen(old) && memcmp(str + i, old, strlen(old)) == 0) { i += strlen(old); new_size += strlen(new); } else { new_size += 1; i += 1; } } char *new_str = malloc(new_size + 1); if (new_str == NULL) errx(1, "str_replace: malloc"); i = 0; size_t j = 0; while (i < strlen(str)) { if (i < strlen(str) - strlen(old) && memcmp(str + i, old, strlen(old)) == 0) { memmove(new_str + j, new, strlen(new)); i += strlen(old); j += strlen(new); } else new_str[j++] = str[i++]; } new_str[new_size] = 0; return new_str; } extsmail-2.0/common.h010064400017500001750000000026141243070540200143110ustar00ltrattltratt// Copyright (C)2008 Laurence Tratt http://tratt.net/laurie/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. #define DIR_SEP "/" #define MSGS_DIR "msgs" #define VERSION1_ID "v1" Conf *read_conf(); void free_conf(Conf *); bool check_spool_dir(Conf *); char *fdrdline(int); char *expand_path(const char *); char *mk_str(char *); char *str_replace(const char *, const char *, const char *); extsmail-2.0/compat004075500017500001750000000000001243070540200140545ustar00ltrattltrattextsmail-2.0/compat/strtonum.c010064400017500001750000000033501243070540200161700ustar00ltrattltratt/* $OpenBSD: strtonum.c,v 1.7 2013/04/17 18:40:58 tedu Exp $ */ /* * Copyright (c) 2004 Ted Unangst and Todd Miller * All rights reserved. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #define INVALID 1 #define TOOSMALL 2 #define TOOLARGE 3 long long strtonum(const char *numstr, long long minval, long long maxval, const char **errstrp) { long long ll = 0; int error = 0; char *ep; struct errval { const char *errstr; int err; } ev[4] = { { NULL, 0 }, { "invalid", EINVAL }, { "too small", ERANGE }, { "too large", ERANGE }, }; ev[0].err = errno; errno = 0; if (minval > maxval) { error = INVALID; } else { ll = strtoll(numstr, &ep, 10); if (numstr == ep || *ep != '\0') error = INVALID; else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) error = TOOSMALL; else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) error = TOOLARGE; } if (errstrp != NULL) *errstrp = ev[error].errstr; errno = ev[error].err; if (error) ll = 0; return (ll); } extsmail-2.0/compat/strtonum.h010064400017500001750000000001621243070540200161730ustar00ltrattltrattlong long strtonum(const char *nptr, long long minval, long long maxval, const char **errstr); extsmail-2.0/conf.h010064400017500001750000000036171243070540200137520ustar00ltrattltratt// Copyright (C)2008 Laurence Tratt http://tratt.net/laurie/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. typedef enum {BATCH_MODE, DAEMON_MODE} Mode; typedef struct { char *spool_dir; Mode mode; time_t notify_failure_interval; // How many seconds should mail not be sent // before notify_cmd should be executed. If // set to 0, means that notify_cmd sholud // never be executed. const char *notify_failure_cmd; // The command to be executed by system(3) // when notify_failure_interval seconds have // elapsed since a successful send cycle. const char *notify_success_cmd; // The command to be executed by system(3) // when message(s) are successfully sent } Conf; extsmail-2.0/conf_parser.y010064400017500001750000000062161243070540200153450ustar00ltrattltratt%{ // Copyright (C)2008 Laurence Tratt http://tratt.net/laurie/ // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. #include "Config.h" #include #include #include #include #include #include #include "conf.h" extern int yyclex(void); void yycerror(const char *); extern Conf *conf; char *expand_path(const char *); bool set_entry(const char *, const char *); void warn_var(const char *); %} %union { const char *str; time_t time; } %token TASSIGN %token TID %token TSTRING %token TTIME %% start : defns ; defns : defn defns | defn ; defn : TID TASSIGN TSTRING { if (strcmp($1, "spool_dir") == 0) { conf->spool_dir = expand_path($3); if (conf->spool_dir == NULL) { warnx("Unable to expand path '%s'", $3); YYABORT; } free((void *) $3); } else if (strcmp($1, "notify_failure_cmd") == 0) { conf->notify_failure_cmd = $3; } else if (strcmp($1, "notify_success_cmd") == 0) { conf->notify_success_cmd = $3; } else { warn_var($1); free((void *) $3); YYABORT; } free((void *) $1); } | TID TASSIGN TTIME { if (strcmp($1, "notify_failure_interval") == 0) { conf->notify_failure_interval = $