/* -*-c-*-
*
- * $Id: conf.c,v 1.8 2001/02/03 20:33:26 mdw Exp $
- *
* Configuration parsing
*
* (c) 1999 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
- * This file is part of the `fw' port forwarder.
+ * This file is part of the `fwd' port forwarder.
*
- * `fw' is free software; you can redistribute it and/or modify
+ * `fwd' is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
- * `fw' is distributed in the hope that it will be useful,
+ *
+ * `fwd' is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
- * along with `fw'; if not, write to the Free Software Foundation,
+ * along with `fwd'; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-/*----- Revision history --------------------------------------------------*
- *
- * $Log: conf.c,v $
- * Revision 1.8 2001/02/03 20:33:26 mdw
- * Fix flags to be unsigned.
- *
- * Revision 1.7 2000/08/01 17:58:10 mdw
- * Fix subtleties with <ctype.h> functions.
- *
- * Revision 1.6 2000/02/12 18:13:20 mdw
- * Terminate tables of sources and targets.
- *
- * Revision 1.5 1999/10/22 22:46:44 mdw
- * Improve documentation for conf_enum.
- *
- * Revision 1.4 1999/10/15 21:12:36 mdw
- * Remove redundant debugging code.
- *
- * Revision 1.3 1999/08/19 18:32:48 mdw
- * Improve lexical analysis. In particular, `chmod' patterns don't have to
- * be quoted any more.
- *
- * Revision 1.2 1999/07/26 23:28:39 mdw
- * Major reconstruction work for new design.
- *
- * Revision 1.1.1.1 1999/07/01 08:56:23 mdw
- * Initial revision.
- *
- */
-
-/*----- Header files ------------------------------------------------------*/
-
-#include "config.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <mLib/dstr.h>
-#include <mLib/quis.h>
-#include <mLib/report.h>
-
-#include "conf.h"
-#include "scan.h"
-#include "source.h"
-#include "target.h"
-
-#include "exec.h"
-#include "file.h"
-#include "socket.h"
-
-/*----- Source and target tables ------------------------------------------*/
-
-static source_ops *sources[] =
- { &xsource_ops, &fsource_ops, &ssource_ops, 0 };
-static target_ops *targets[] =
- { &xtarget_ops, &ftarget_ops, &starget_ops, 0 };
-
-static const char *notword = 0;
-static const char *notdelim = 0;
+#include "fwd.h"
/*----- Main code ---------------------------------------------------------*/
-/* --- @undelim@ --- *
+/* --- @conf_undelim@ --- *
*
- * Arguments: @const char *d, dd@ = pointer to characters to escape
+ * Arguments: @scanner *sc@ = pointer to scanner definition
+ * @const char *d, *dd@ = pointer to characters to escape
*
* Returns: ---
*
* second list will always be allowed to continue a word.
*/
-void undelim(const char *d, const char *dd) { notword = d; notdelim = dd; }
+void conf_undelim(scanner *sc, const char *d, const char *dd)
+{
+ sc->wbegin = d;
+ sc->wcont = dd;
+}
/* --- @token@ --- *
*
if (sc->head->tok) {
dstr_puts(&sc->d, sc->head->tok);
- free(sc->head->tok);
+ xfree(sc->head->tok);
sc->head->tok = 0;
sc->t = sc->head->t;
goto done;
/* --- Various self-delimiting characters --- */
case SELFDELIM:
- if (!notword || strchr(notword, ch) == 0) {
+ if (!sc->wbegin || strchr(sc->wbegin, ch) == 0) {
dstr_putc(&sc->d, ch);
dstr_putz(&sc->d);
sc->t = ch;
q = !q;
break;
case SELFDELIM:
- if (q || (notdelim && strchr(notdelim, ch)))
+ if (q || (sc->wcont && strchr(sc->wcont, ch)))
goto insert;
goto word;
default:
* to pushing a new scanner source.
*/
-static void pushback(scanner *sc)
+void pushback(scanner *sc)
{
sc->head->tok = xstrdup(sc->d.buf);
sc->head->t = sc->t;
if (sc->t == '[') {
token(sc);
- f |= f_bra;
+ f |= f_bra | f_ok;
}
/* --- Do the main reading sequence --- */
#undef f_bra
}
-/* --- @conf_parse@ --- *
+/* --- @conf_fname@ --- *
*
- * Arguments: @scanner *sc@ = pointer to scanner definition
+ * Arguments: @scanner *sc@ = pointer to scanner
+ * @dstr *d@ = pointer to dynamic string for output
*
* Returns: ---
*
- * Use: Parses a configuration file from the scanner.
+ * Use: Reads a file name from the input and stores it in @d@.
*/
-void conf_parse(scanner *sc)
+void conf_fname(scanner *sc, dstr *d)
{
- token(sc);
-
- for (;;) {
- if (sc->t == CTOK_EOF)
- break;
- if (sc->t != CTOK_WORD)
- error(sc, "parse error, keyword expected");
-
- /* --- Handle a forwarding request --- */
-
- if (strcmp(sc->d.buf, "forward") == 0 ||
- strcmp(sc->d.buf, "fw") == 0 ||
- strcmp(sc->d.buf, "from") == 0) {
- source *s;
- target *t;
-
- token(sc);
-
- /* --- Read a source description --- */
-
- {
- source_ops **sops;
-
- /* --- Try to find a source type which understands --- */
-
- s = 0;
- for (sops = sources; *sops; sops++) {
- if ((s = (*sops)->read(sc)) != 0)
- goto found_source;
- }
- error(sc, "unknown source name `%s'", sc->d.buf);
-
- /* --- Read any source-specific options --- */
-
- found_source:
- if (sc->t == '{') {
- token(sc);
- while (sc->t == CTOK_WORD) {
- if (!s->ops->option || !s->ops->option(s, sc)) {
- error(sc, "unknown %s source option `%s'",
- s->ops->name, sc->d.buf);
- }
- if (sc->t == ';')
- token(sc);
- }
- if (sc->t != '}')
- error(sc, "parse error, missing `}'");
- token(sc);
- }
- }
-
- /* --- Read a destination description --- */
-
- if (sc->t == CTOK_WORD && (strcmp(sc->d.buf, "to") == 0 ||
- strcmp(sc->d.buf, "->") == 0))
- token(sc);
-
- {
- target_ops **tops;
-
- /* --- Try to find a target which understands --- */
-
- t = 0;
- for (tops = targets; *tops; tops++) {
- if ((t = (*tops)->read(sc)) != 0)
- goto found_target;
- }
- error(sc, "unknown target name `%s'", sc->d.buf);
-
- /* --- Read any target-specific options --- */
-
- found_target:
- if (sc->t == '{') {
- token(sc);
- while (sc->t == CTOK_WORD) {
- if (!t->ops->option || !t->ops->option(t, sc)) {
- error(sc, "unknown %s target option `%s'",
- t->ops->name, sc->d.buf);
- }
- if (sc->t == ';')
- token(sc);
- }
- if (sc->t != '}')
- error(sc, "parse error, `}' expected");
- token(sc);
- }
- }
-
- /* --- Combine the source and target --- */
-
- s->ops->attach(s, sc, t);
- }
-
- /* --- Include configuration from a file --- *
- *
- * Slightly tricky. Scan the optional semicolon from the including
- * stream, not the included one.
- */
-
- else if (strcmp(sc->d.buf, "include") == 0) {
- FILE *fp;
- dstr d = DSTR_INIT;
-
- token(sc);
- conf_name(sc, '/', &d);
- if ((fp = fopen(d.buf, "r")) == 0)
- error(sc, "can't include `%s': %s", d.buf, strerror(errno));
- if (sc->t == ';')
- token(sc);
- pushback(sc);
- scan_push(sc, scan_file(fp, xstrdup(d.buf), SCF_FREENAME));
- token(sc);
- dstr_destroy(&d);
- continue; /* Don't parse a trailing `;' */
- }
-
- /* --- Other configuration is handled elsewhere --- */
-
- else {
-
- /* --- First try among the sources --- */
-
- {
- source_ops **sops;
-
- for (sops = sources; *sops; sops++) {
- if ((*sops)->option && (*sops)->option(0, sc))
- goto found_option;
- }
- }
-
- /* --- Then try among the targets --- */
-
- {
- target_ops **tops;
-
- for (tops = targets; *tops; tops++) {
- if ((*tops)->option && (*tops)->option(0, sc))
- goto found_option;
- }
- }
-
- /* --- Nobody wants the option --- */
-
- error(sc, "unknown global option or prefix `%s'", sc->d.buf);
-
- found_option:;
- }
-
- if (sc->t == ';')
- token(sc);
- }
+ const char fnchars[] = ".-+";
+ conf_undelim(sc, fnchars, fnchars);
+ conf_name(sc, '/', d);
+ conf_undelim(sc, 0, 0);
}
/*----- That's all, folks -------------------------------------------------*/