Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ser2net for openSUSE:Factory checked 
in at 2022-01-27 23:16:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ser2net (Old)
 and      /work/SRC/openSUSE:Factory/.ser2net.new.1898 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ser2net"

Thu Jan 27 23:16:51 2022 rev:20 rq:949347 version:4.3.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/ser2net/ser2net.changes  2021-12-12 
00:58:04.434603510 +0100
+++ /work/SRC/openSUSE:Factory/.ser2net.new.1898/ser2net.changes        
2022-01-27 23:18:24.926377708 +0100
@@ -1,0 +2,9 @@
+Sun Jan 23 15:53:49 UTC 2022 - Martin Hauke <[email protected]>
+
+- ser2net 4.3.5:
+  * Yet another quick release. gcc-11 and the new sctp library
+    threw some curve balls, so those needed to be handled.
+    No functional changes, just compile and bug fixes related to
+    the new compiler and library.
+
+-------------------------------------------------------------------

Old:
----
  ser2net-4.3.4.tar.gz

New:
----
  ser2net-4.3.5.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ser2net.spec ++++++
--- /var/tmp/diff_new_pack.TlQpE9/_old  2022-01-27 23:18:25.790371739 +0100
+++ /var/tmp/diff_new_pack.TlQpE9/_new  2022-01-27 23:18:25.798371684 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package ser2net
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           ser2net
-Version:        4.3.4
+Version:        4.3.5
 Release:        0
 Summary:        Serial port to network proxy
 License:        GPL-2.0-or-later

++++++ ser2net-4.3.4.tar.gz -> ser2net-4.3.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/addsysattrs.c 
new/ser2net-4.3.5/addsysattrs.c
--- old/ser2net-4.3.4/addsysattrs.c     2020-10-28 19:50:59.000000000 +0100
+++ new/ser2net-4.3.5/addsysattrs.c     2022-01-17 18:59:00.000000000 +0100
@@ -25,6 +25,8 @@
  *  release a modified version which carries forward this exception.
  */
 
+#include <gensio/gensio.h>
+
 #ifdef linux
 
 #include <sys/types.h>
@@ -35,7 +37,6 @@
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
-#include <gensio/gensio.h>
 #include <gensio/argvutils.h>
 #include "ser2net.h"
 #include "port.h"
@@ -50,9 +51,12 @@
 
     s = strstr(devname, ",serialdev");
     if (s) {
+       s++;
        s = strchr(s, ',');
        if (s)
            s++;
+       while (isspace(*s))
+           s++;
     } else {
        s = strstr(devname, "/dev/");
     }
@@ -62,6 +66,8 @@
            *len = e - s;
        else
            *len = strlen(s);
+       while (*len > 0 && isspace(s[(*len) - 1]))
+           (*len)--;
     }
 
     return s;
@@ -118,7 +124,6 @@
 {
     int rv;
     char *p, *s;
-    unsigned int len;
 
     rv = gensio_argv_sappend(so, txt, args, argc, "devicetype=serialusb");
     if (rv < 0)
@@ -126,27 +131,26 @@
                  "Device %s: Unable add txt devicetype for %s\n",
                  portname, gensio_err_to_str(rv));
 
-    /* Search backwards three directory levels, the name should match. */
+    /*
+     * Search backwards to the device.  Depending on the specific
+     * device, there should be various levels of directories named
+     * "tty" or "ttyxxxx".  Like "tty/ttyACM0" or
+     * "ttyUSB0/tty/ttyUSB0".
+     */
     s = p = strrchr(path, '/');
-    if (p && p > path) {
-       p--;
-       while (p > path && *p != '/')
-           p--;
-    }
-    if (p && p > path) {
+    while (p && p > path && strncmp(p + 1, "tty", 3) == 0) {
        s = p;
        p--;
        while (p > path && *p != '/')
            p--;
     }
-    len = strlen(devstr);
-    if (!p || (s - p - 1 != len) || strncmp(p + 1, devstr, len)) {
+    if (!p) {
        eout->out(eout,
                  "Device %s: usb path is not valid: %s\n",
                  portname, path);
        return;
     }
-    *p = '\0';
+    *s = '\0';
 
     add_attr(eout, portname, path, "bInterfaceNumber", txt, args, argc);
     add_attr(eout, portname, path, "interface", txt, args, argc);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/configure new/ser2net-4.3.5/configure
--- old/ser2net-4.3.4/configure 2021-10-06 03:37:05.000000000 +0200
+++ new/ser2net-4.3.5/configure 2022-01-18 01:24:28.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for ser2net 4.3.4.
+# Generated by GNU Autoconf 2.69 for ser2net 4.3.5.
 #
 # Report bugs to <[email protected]>.
 #
@@ -590,8 +590,8 @@
 # Identity of this package.
 PACKAGE_NAME='ser2net'
 PACKAGE_TARNAME='ser2net'
-PACKAGE_VERSION='4.3.4'
-PACKAGE_STRING='ser2net 4.3.4'
+PACKAGE_VERSION='4.3.5'
+PACKAGE_STRING='ser2net 4.3.5'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1339,7 +1339,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures ser2net 4.3.4 to adapt to many kinds of systems.
+\`configure' configures ser2net 4.3.5 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1410,7 +1410,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of ser2net 4.3.4:";;
+     short | recursive ) echo "Configuration of ser2net 4.3.5:";;
    esac
   cat <<\_ACEOF
 
@@ -1530,7 +1530,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-ser2net configure 4.3.4
+ser2net configure 4.3.5
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1899,7 +1899,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by ser2net $as_me 4.3.4, which was
+It was created by ser2net $as_me 4.3.5, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2762,7 +2762,7 @@
 
 # Define the identity of the package.
  PACKAGE='ser2net'
- VERSION='4.3.4'
+ VERSION='4.3.5'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -13054,6 +13054,29 @@
 
 fi
 
+for ac_header in wordexp.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "wordexp.h" "ac_cv_header_wordexp_h" 
"$ac_includes_default"
+if test "x$ac_cv_header_wordexp_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_WORDEXP_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in wordexp
+do :
+  ac_fn_c_check_func "$LINENO" "wordexp" "ac_cv_func_wordexp"
+if test "x$ac_cv_func_wordexp" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_WORDEXP 1
+_ACEOF
+
+fi
+done
+
 
 
 
@@ -13979,7 +14002,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by ser2net $as_me 4.3.4, which was
+This file was extended by ser2net $as_me 4.3.5, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14036,7 +14059,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-ser2net config.status 4.3.4
+ser2net config.status 4.3.5
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/configure.ac 
new/ser2net-4.3.5/configure.ac
--- old/ser2net-4.3.4/configure.ac      2021-10-06 03:35:39.000000000 +0200
+++ new/ser2net-4.3.5/configure.ac      2022-01-18 01:21:26.000000000 +0100
@@ -1,4 +1,4 @@
-AC_INIT([ser2net], [4.3.4], [[email protected]])
+AC_INIT([ser2net], [4.3.5], [[email protected]])
 AM_INIT_AUTOMAKE([-Wall])
 AC_PROG_CC
 AM_PROG_AR
@@ -47,6 +47,8 @@
 AC_CONFIG_MACRO_DIR([m4])
 AC_STDC_HEADERS
 AC_CHECK_LIB(nsl,main)
+AC_CHECK_HEADERS([wordexp.h])
+AC_CHECK_FUNCS(wordexp)
 
 PKG_CHECK_MODULES(GENSIO, libgensio, [LIBS=$GENSIO_LIBS],
    [AC_CHECK_HEADER(gensio/gensio.h, [],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/port.c new/ser2net-4.3.5/port.c
--- old/ser2net-4.3.4/port.c    2021-08-23 07:10:38.000000000 +0200
+++ new/ser2net-4.3.5/port.c    2022-01-17 18:59:00.000000000 +0100
@@ -1170,7 +1170,8 @@
                                handle_port_child_event, new_port,
                                &new_port->accepter);
     if (err) {
-       eout->out(eout, "Invalid port name/number: %s", gensio_err_to_str(err));
+       eout->out(eout, "Invalid accepter port name/number '%s': %s",
+                 new_port->accstr, gensio_err_to_str(err));
        return -1;
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/readconfig.h 
new/ser2net-4.3.5/readconfig.h
--- old/ser2net-4.3.4/readconfig.h      2020-10-27 02:49:45.000000000 +0100
+++ new/ser2net-4.3.5/readconfig.h      2022-01-17 18:59:00.000000000 +0100
@@ -37,7 +37,7 @@
 /* Read the specified configuration file and call the routine to
    create the ports. */
 int readconfig(FILE *instream);
-int yaml_readconfig(FILE *f, char **config_lines,
+int yaml_readconfig(FILE *f, char *filename, char **config_lines,
                    unsigned int num_config_lines,
                    struct absout *errout);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/ser2net.c new/ser2net-4.3.5/ser2net.c
--- old/ser2net-4.3.4/ser2net.c 2021-02-05 17:25:32.000000000 +0100
+++ new/ser2net-4.3.5/ser2net.c 2022-01-17 18:59:00.000000000 +0100
@@ -167,7 +167,7 @@
 }
 
 static FILE *
-fopen_config_file(bool *is_yaml)
+fopen_config_file(bool *is_yaml, char **rfilename)
 {
     FILE *instream = fopen(config_file, "r");
 
@@ -183,8 +183,10 @@
                   " '%s': %m", config_file, old_config_file);
            return NULL;
        }
+       *rfilename = old_config_file;
        *is_yaml = false;
     } else {
+       *rfilename = config_file;
        *is_yaml = str_endswith(config_file, ".yaml");
     }
 
@@ -210,20 +212,21 @@
 
     if (config_file) {
        FILE *instream = NULL;
+       char *filename;
        bool is_yaml;
 
        syslog(LOG_INFO, "Got %s, re-reading configuration", reqtype);
        readconfig_init();
 
-       instream = fopen_config_file(&is_yaml);
+       instream = fopen_config_file(&is_yaml, &filename);
        if (!instream)
            goto out;
 
        if (!admin_port_from_cmdline)
            controller_shutdown();
        if (is_yaml)
-           rv = yaml_readconfig(instream, config_lines, num_config_lines,
-                                eout);
+           rv = yaml_readconfig(instream, filename,
+                                config_lines, num_config_lines, eout);
        else
            rv = readconfig(instream);
        fclose(instream);
@@ -718,6 +721,7 @@
     int print_when_ready = 0;
     FILE *instream = NULL;
     enum { CONFIG_NONE, CONFIG_YAML, CONFIG_OLD } config_type = CONFIG_NONE;
+    char *filename;
 
     gensio_set_progname("ser2net");
 
@@ -940,8 +944,9 @@
        if (strcmp(config_file, "-") == 0) {
            instream = stdin;
            is_yaml = true;
+           filename = "<stdin>";
        } else {
-           instream = fopen_config_file(&is_yaml);
+           instream = fopen_config_file(&is_yaml, &filename);
            if (!instream)
                exit(1);
        }
@@ -960,13 +965,16 @@
            }
            config_type = CONFIG_OLD;
        }
+    } else {
+       filename = "<cmdline>";
     }
 
     if (config_type == CONFIG_YAML || instream)        {
        int rv;
 
        if (config_type == CONFIG_YAML)
-           rv = yaml_readconfig(instream, config_lines, num_config_lines,
+           rv = yaml_readconfig(instream, filename,
+                                config_lines, num_config_lines,
                                 &stderr_absout);
        else
            rv = readconfig(instream);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/ser2net.yaml 
new/ser2net-4.3.5/ser2net.yaml
--- old/ser2net-4.3.4/ser2net.yaml      2020-10-27 02:49:45.000000000 +0100
+++ new/ser2net-4.3.5/ser2net.yaml      2022-01-17 18:59:00.000000000 +0100
@@ -11,6 +11,13 @@
 # error doesn't happen.
 define: &confver 1.0
 
+# # You can include other files from here, only at the main level.
+# # These must be full yaml files, but are included in context at
+# # this point, with all the defines, connection names, etc.
+# # This can let you have individual connections in individual
+# # files to ease management.  globs are accepted.
+# include: /etc/ser2net/ser2net/*.yaml
+
 # # Just a basic serial port  The con0 is the name of the connection,
 # # each connection must be given a unique name.  The accepter is the
 # # information about how to receive connections, in this case it is
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/ser2net.yaml.5 
new/ser2net-4.3.5/ser2net.yaml.5
--- old/ser2net-4.3.4/ser2net.yaml.5    2021-06-03 21:54:11.000000000 +0200
+++ new/ser2net-4.3.5/ser2net.yaml.5    2022-01-17 18:59:00.000000000 +0100
@@ -40,11 +40,23 @@
 you are not sure, like:
 .IP
 define: &aliasname "alias text"
+.br
 banner: "My banner *(aliasname) is here"
 .PP
 
 If you for some reason need "*(" in your text, use "*(*" for that.
 
+.SH INCLUDING OTHER FILES
+A YAML file may include another file at the main level, with:
+.IP
+include: <filename>
+.PP
+This filename can include globs, and all referenced files are
+included.  These must be full yaml files, but are included in context
+at this point, with all the defines, connection names, etc.  This can
+let you have individual connections in individual files to ease
+management.
+
 .SH USING EXTERNAL FILES
 You may want to store passwords and such in external files for better
 security.  Putting "*{filename}" in a YAML scalar will put the file's
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/tests/ipmisimdaemon.py 
new/ser2net-4.3.5/tests/ipmisimdaemon.py
--- old/ser2net-4.3.4/tests/ipmisimdaemon.py    2021-01-22 21:45:55.000000000 
+0100
+++ new/ser2net-4.3.5/tests/ipmisimdaemon.py    2022-01-17 18:59:00.000000000 
+0100
@@ -11,6 +11,8 @@
 import signal
 import time
 
+ipmisol_port = 9002
+
 default_ipmisim_emu = """
 mc_setbmc 0x20\n
 \n
@@ -26,7 +28,7 @@
 set_working_mc 0x20\n
 \n
   startlan 1\n
-    addr localhost 9001\n
+    addr localhost %d\n
 \n
     # Maximum privilege limit on the channel.\n
     priv_limit admin\n
@@ -53,7 +55,7 @@
   #    # valid name      passw  priv-lim max-sess allowed-auths (ignored)\n
   user 1 true  ""        "test" user     10       none md2 md5 straight\n
   user 2 true  "ipmiusr" "test" admin    10       none md2 md5 straight\n
-"""
+""" % (ipmisol_port)
 
 class IPMISimDaemon:
     """Create an IPMI Sim daemon instance and start it up
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/tests/test_rfc2217.py 
new/ser2net-4.3.5/tests/test_rfc2217.py
--- old/ser2net-4.3.4/tests/test_rfc2217.py     2021-02-02 05:04:45.000000000 
+0100
+++ new/ser2net-4.3.5/tests/test_rfc2217.py     2022-01-17 18:59:00.000000000 
+0100
@@ -169,8 +169,6 @@
     def op(self, io1, io2):
         sio1 = io1.cast_to_sergensio()
         sio1.sg_flowcontrol_s(gensio.SERGENSIO_FLOWCONTROL_XON_XOFF)
-        if utils.gensio_version_ge("2.3.0-rc1"):
-            return termioschk.dup_base_termios(iflags=termios.IXON)
         return termioschk.dup_base_termios(iflags=termios.IXON | termios.IXOFF)
 
 termioschk.test_ser2net_termios("xon/xoff rfc2217 settings",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/tests/test_tty_base.py 
new/ser2net-4.3.5/tests/test_tty_base.py
--- old/ser2net-4.3.4/tests/test_tty_base.py    2021-02-02 05:01:53.000000000 
+0100
+++ new/ser2net-4.3.5/tests/test_tty_base.py    2022-01-17 18:59:00.000000000 
+0100
@@ -118,10 +118,7 @@
 
 class xonhandler:
     def op(self, io1, io2):
-        if utils.gensio_version_ge("2.3.0-rc1"):
-            return termioschk.dup_base_termios(iflags=termios.IXON)
         return termioschk.dup_base_termios(iflags=(termios.IXON |
-                                                   termios.IXANY |
                                                    termios.IXOFF))
 
 termioschk.test_ser2net_termios("xon/xoff termios settings",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/tests/test_xfer_basic_ipmisol.py 
new/ser2net-4.3.5/tests/test_xfer_basic_ipmisol.py
--- old/ser2net-4.3.4/tests/test_xfer_basic_ipmisol.py  2021-06-03 
21:54:00.000000000 +0200
+++ new/ser2net-4.3.5/tests/test_xfer_basic_ipmisol.py  2022-01-17 
18:59:00.000000000 +0100
@@ -11,7 +11,7 @@
 test_transfer("basic ipmisol", "This is a test!",
               ("connection: &con",
                "  accepter: tcp,3023",
-               "  connector: ipmisol,lan -U ipmiusr -P test -p 9001 
localhost,9600"),
+               "  connector: ipmisol,lan -U ipmiusr -P test -p %d 
localhost,9600" % ipmisimdaemon.ipmisol_port),
               "tcp,localhost,3023",
               "serialdev,/dev/ttyPipeA0,9600N81")
 
@@ -26,7 +26,7 @@
 test_write_drain("basic tcp", "This is a write drain test!",
               ("connection: &con",
                "  accepter: tcp,3023",
-               "  connector: ipmisol,lan -U ipmiusr -P test -p 9001 
localhost,9600"),
+               "  connector: ipmisol,lan -U ipmiusr -P test -p %d 
localhost,9600" % ipmisimdaemon.ipmisol_port),
                  "tcp,localhost,3023",
                  "serialdev,/dev/ttyPipeA0,9600N81,LOCAL",
                  switch_delay = 0.25)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/tests/test_xfer_large_ipmisol.py 
new/ser2net-4.3.5/tests/test_xfer_large_ipmisol.py
--- old/ser2net-4.3.4/tests/test_xfer_large_ipmisol.py  2020-10-27 
02:49:45.000000000 +0100
+++ new/ser2net-4.3.5/tests/test_xfer_large_ipmisol.py  2022-01-17 
18:59:00.000000000 +0100
@@ -14,6 +14,6 @@
 test_transfer("basic ipmisol", rb,
               ("connection: &con",
                "  accepter: tcp,3023",
-               "  connector: ipmisol,lan -U ipmiusr -P test -p 9001 
localhost,115200"),
+               "  connector: ipmisol,lan -U ipmiusr -P test -p %d 
localhost,115200" % (ipmisimdaemon.ipmisol_port)),
               "tcp,localhost,3023",
               "serialdev,/dev/ttyPipeA0,115200N81", timeout=150000)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/tests/test_xfer_small_ipmisol.py 
new/ser2net-4.3.5/tests/test_xfer_small_ipmisol.py
--- old/ser2net-4.3.4/tests/test_xfer_small_ipmisol.py  2020-12-05 
04:21:02.000000000 +0100
+++ new/ser2net-4.3.5/tests/test_xfer_small_ipmisol.py  2022-01-17 
18:59:00.000000000 +0100
@@ -14,6 +14,6 @@
 test_transfer("basic ipmisol", rb,
               ("connection: &con",
                "  accepter: tcp,3023",
-               "  connector: ipmisol,lan -U ipmiusr -P test -p 9001 
localhost,9600"),
+               "  connector: ipmisol,lan -U ipmiusr -P test -p %d 
localhost,9600" % (ipmisimdaemon.ipmisol_port)),
               "tcp,localhost,3023",
               "serialdev,/dev/ttyPipeA0,9600N81", timeout=5000)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ser2net-4.3.4/yamlconf.c new/ser2net-4.3.5/yamlconf.c
--- old/ser2net-4.3.4/yamlconf.c        2020-10-27 02:49:45.000000000 +0100
+++ new/ser2net-4.3.5/yamlconf.c        2022-01-17 18:59:00.000000000 +0100
@@ -34,6 +34,12 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
+#if defined(HAVE_WORDEXP) && defined(HAVE_WORDEXP_H)
+#define DO_WORDEXP
+#endif
+#ifdef DO_WORDEXP
+#include <wordexp.h>
+#endif
 #include <gensio/gensio.h>
 #include <gensio/argvutils.h>
 #include "ser2net.h"
@@ -56,6 +62,7 @@
     MAIN_LEVEL,
 
     IN_DEFINE,
+    IN_INCLUDE,
 
     /*
      * We have read the type of the main mapping (connection, led, etc)
@@ -157,6 +164,39 @@
     };
 };
 
+/*
+ * Used for processing include directives, stores the glob output and
+ * information about the previous file so we can go back.
+ */
+struct yaml_read_file {
+#ifdef DO_WORDEXP
+    wordexp_t files;
+    bool files_set;
+    int curr_file;
+#endif
+
+    bool closeme;
+    yaml_parser_t parser;
+    yaml_event_t e;
+    char *filename;
+    FILE *f;
+
+    struct yaml_read_file *prev_f;
+};
+
+struct yaml_read_handler_data {
+    struct yaml_read_file *f;
+    char **config_lines;
+    unsigned int num_config_lines;
+    unsigned int curr;
+    unsigned int pos;
+    char in_quote;
+    bool in_escape;
+    unsigned int include_depth;
+    struct yconf *y;
+    struct absout *errout;
+};
+
 struct yconf {
     enum ystate state;
 
@@ -188,42 +228,66 @@
 
     struct yfile *files;
 
-    yaml_parser_t parser;
-    yaml_event_t e;
-    struct absout *errout;
+    struct yaml_read_handler_data *d;
     struct absout sub_errout;
 };
 
 static int
-errout(struct yconf *y, const char *str, ...)
+yaml_verrout_d_f(struct yaml_read_handler_data *d,
+                struct yaml_read_file *f,
+                const char *str, va_list ap)
 {
-    va_list ap;
     char buf[1024];
 
-    va_start(ap, str);
     vsnprintf(buf, sizeof(buf), str, ap);
-    va_end(ap);
-    y->errout->out(y->errout, "%s on line %lu column %lu", buf,
-                  (unsigned long) y->e.start_mark.line,
-                  (unsigned long) y->e.start_mark.column);
+    d->errout->out(d->errout, "%s:%lu(column %lu): %s",
+                  f->filename,
+                  (unsigned long) f->e.start_mark.line,
+                  (unsigned long) f->e.start_mark.column,
+                  buf);
     return 0;
 }
 
 static int
+yaml_errout(struct yconf *y, const char *str, ...)
+{
+    va_list ap;
+    int rv;
+
+    va_start(ap, str);
+    rv = yaml_verrout_d_f(y->d, y->d->f, str, ap);
+    va_end(ap);
+    return rv;
+}
+
+static int
 sub_errout(struct absout *e, const char *str, ...)
 {
     struct yconf *y = e->data;
     va_list ap;
-    char buf[1024];
+    int rv;
 
     va_start(ap, str);
-    vsnprintf(buf, sizeof(buf), str, ap);
+    rv = yaml_verrout_d_f(y->d, y->d->f, str, ap);
     va_end(ap);
-    y->errout->out(y->errout, "%s on line %lu column %lu", buf,
-                  (unsigned long) y->e.start_mark.line,
-                  (unsigned long) y->e.start_mark.column);
-    return 0;
+    return rv;
+}
+
+#ifdef DO_WORDEXP
+static int
+yaml_errout_d_f(struct yaml_read_handler_data *d,
+               struct yaml_read_file *f,
+               const char *str, ...)
+{
+    va_list ap;
+    int rv;
+
+    va_start(ap, str);
+    rv = yaml_verrout_d_f(d, f, str, ap);
+    va_end(ap);
+    return rv;
 }
+#endif
 
 static void
 dofree(char **val)
@@ -290,13 +354,13 @@
 
     name = strdup(iname);
     if (!name) {
-       errout(y, "Out of memory allocating alias name");
+       yaml_errout(y, "Out of memory allocating alias name");
        return -1;
     }
     value = strdup(ivalue);
     if (!value) {
        free(name);
-       errout(y, "Out of memory allocating alias value");
+       yaml_errout(y, "Out of memory allocating alias value");
        return -1;
     }
 
@@ -309,7 +373,7 @@
        if (!a) {
            free(name);
            free(value);
-           errout(y, "Out of memory allocating alias");
+           yaml_errout(y, "Out of memory allocating alias");
            return -1;
        }
        a->next = y->aliases;
@@ -321,6 +385,128 @@
     return 0;
 }
 
+static void
+cleanup_yaml_read_file(struct yaml_read_handler_data *d)
+{
+    struct yaml_read_file *old_f = d->f;
+
+    d->f = d->f->prev_f;
+    yaml_parser_delete(&old_f->parser);
+    if (old_f->closeme) {
+       if (old_f->f)
+           fclose(old_f->f);
+#ifdef DO_WORDEXP
+       if (old_f->files_set)
+           wordfree(&old_f->files);
+#endif
+       free(old_f);
+       d->include_depth--;
+    }
+}
+
+static bool
+another_yaml_file_pending(struct yaml_read_handler_data *d)
+{
+#ifdef DO_WORDEXP
+    struct yaml_read_file *f = d->f;
+
+    return f->curr_file < f->files.we_wordc;
+#else
+    return false;
+#endif
+}
+
+static int yaml_read_handler(void *data, unsigned char *buffer, size_t size,
+                            size_t *size_read);
+
+/*
+ * Returns 0 if it successfully opened a file, 1 if not.
+ */
+static int
+next_yaml_read_file(struct yaml_read_handler_data *d)
+{
+#ifdef DO_WORDEXP
+    struct yaml_read_file *f = d->f;
+
+ retry:
+    f->filename = f->files.we_wordv[f->curr_file++];
+    f->f = fopen(f->filename, "r");
+    if (!f->f) {
+       yaml_errout_d_f(d, f->prev_f,
+                       "Unable to open file %s, skipping\n", f->filename);
+       if (f->curr_file < f->files.we_wordc)
+           goto retry;
+       return 1;
+    }
+    yaml_parser_initialize(&f->parser);
+    yaml_parser_set_input(&f->parser, yaml_read_handler, d);
+    d->y->state = BEGIN_DOC;
+    return 0;
+#else
+    return 1;
+#endif
+}
+
+static int
+do_include(struct yconf *y, const char *ivalue)
+{
+#ifdef DO_WORDEXP
+    struct yaml_read_file *f;
+    int rv;
+
+    if (y->d->include_depth > 100) {
+       yaml_errout(y, "Too many nested includes, you probably have a"
+                   " circular include\n");
+       return -1;
+    }
+
+    f = calloc(1, sizeof(*f));
+    if (!f) {
+       yaml_errout(y, "Out of memory allocating include info");
+       return -1;
+    }
+
+    rv = wordexp(ivalue, &f->files, WRDE_NOCMD);
+    switch (rv) {
+    case 0:
+       break;
+
+    case WRDE_BADCHAR:
+       yaml_errout(y, "Bad character in include directive");
+       return -1;
+
+    case WRDE_CMDSUB:
+       yaml_errout(y, "Command substitution not allowed in include directive");
+       return -1;
+
+    case WRDE_NOSPACE:
+       yaml_errout(y, "Out of memory processing include directive");
+       return -1;
+
+    case WRDE_SYNTAX:
+       yaml_errout(y, "Syntax error in include directive");
+       return -1;
+
+    case WRDE_BADVAL:
+    default:
+       yaml_errout(y, "Unknown error in include directive");
+       return -1;
+    }
+
+    f->closeme = true;
+    f->files_set = true;
+    f->prev_f = y->d->f;
+    y->d->f = f;
+    y->d->include_depth++;
+    if (next_yaml_read_file(y->d))
+       cleanup_yaml_read_file(y->d);
+    return 0;
+#else
+    yaml_errout(y, "Include is not supported on this system");
+    return -1;
+#endif
+}
+
 static struct yfile *
 lookup_filename_len(struct yconf *y, const char *filename, unsigned int len)
 {
@@ -336,38 +522,38 @@
 
     name = strndup(filename, len);
     if (!name) {
-       errout(y, "Out of memory allocating alias name");
+       yaml_errout(y, "Out of memory allocating alias name");
        return NULL;
     }
 
     infd = open(name, O_RDONLY);
     if (infd == -1) {
-       errout(y, "Error opening %s: %s", name, strerror(errno));
+       yaml_errout(y, "Error opening %s: %s", name, strerror(errno));
        goto out_err;
     }
 
     rv = fstat(infd, &stat);
     if (rv == -1) {
-       errout(y, "Error stat-ing %s: %s", name, strerror(errno));
+       yaml_errout(y, "Error stat-ing %s: %s", name, strerror(errno));
        goto out_err;
     }
 
     value = malloc(stat.st_size + 1);
     if (!value) {
-       errout(y, "Error allocating memory for file %s", name);
+       yaml_errout(y, "Error allocating memory for file %s", name);
        goto out_err;
     }
 
     rv = read(infd, value, stat.st_size);
     if (rv == -1) {
-       errout(y, "Error reading %s: %s", name, strerror(errno));
+       yaml_errout(y, "Error reading %s: %s", name, strerror(errno));
        goto out_err;
     }
     value[stat.st_size] = '\0';
 
     f = malloc(sizeof(*f));
     if (!f) {
-       errout(y, "Error allocating memory for file struct %s", name);
+       yaml_errout(y, "Error allocating memory for file struct %s", name);
        goto out_err;
     }
     close(infd);
@@ -398,7 +584,8 @@
        char **new_options = malloc(sizeof(char *) * new_len);
 
        if (!new_options) {
-           errout(y, "Out of memory allocating option array for %s", place);
+           yaml_errout(y, "Out of memory allocating option array for %s",
+                       place);
            return -1;
        }
        memcpy(new_options, y->options, sizeof(char *) * y->options_len);
@@ -417,8 +604,8 @@
            s = strdup(name);
        }
        if (!s) {
-           errout(y, "Out of memory allocating option %s for %s",
-                  option, place);
+           yaml_errout(y, "Out of memory allocating option %s for %s",
+                       option, place);
            return -1;
        }
        y->options[y->curr_option] = s;
@@ -437,8 +624,8 @@
        char **new_connections = malloc(sizeof(char *) * new_len);
 
        if (!new_connections) {
-           errout(y, "Out of memory allocating connection array for %s",
-                  place);
+           yaml_errout(y, "Out of memory allocating connection array for %s",
+                       place);
            return -1;
        }
        memcpy(new_connections, y->connections,
@@ -451,8 +638,8 @@
     if (connection) {
        y->connections[y->curr_connection] = strdup(connection);
        if (!y->connections[y->curr_connection]) {
-           errout(y, "Out of memory allocating connection %s for %s",
-                  connection, place);
+           yaml_errout(y, "Out of memory allocating connection %s for %s",
+                       connection, place);
            return -1;
        }
     } else {
@@ -591,6 +778,7 @@
 
 static struct scalar_next_state sc_main[] = {
     { "define", IN_DEFINE },
+    { "include", IN_INCLUDE },
     { "default", IN_MAIN_NAME, WHICH_INFO_MAP, .map_info = &sc_default_map },
     { "delete_default", IN_MAIN_NAME, WHICH_INFO_MAP,
       .map_info = &sc_deldefault_map },
@@ -607,16 +795,16 @@
        struct yconf *y)
 {
     if (!ival || strlen(ival) == 0) {
-       errout(y, "Empty %s %s not permitted", mapname, keyname);
+       yaml_errout(y, "Empty %s %s not permitted", mapname, keyname);
        return -1;
     }  
     if (*oval) {
-       errout(y, "%s %s already set in connection", mapname, keyname);
+       yaml_errout(y, "%s %s already set in connection", mapname, keyname);
        return -1;
     }
     *oval = strdup(ival);
     if (!*oval) {
-       errout(y, "Unable to allocate %s %s", mapname, keyname);
+       yaml_errout(y, "Unable to allocate %s %s", mapname, keyname);
        return -1;
     }
     return 0;
@@ -695,12 +883,12 @@
                len += 2;
                state = 0;
            } else if (!*s) {
-               errout(y, "Missing ')' for alias at '%s'", start - 2);
+               yaml_errout(y, "Missing ')' for alias at '%s'", start - 2);
                goto out_err;
            } else if (*s == ')') {
                struct alias *a = lookup_alias_len(y, start, s - start);
                if (!a) {
-                   errout(y, "unknown alias at '%s'", start - 2);
+                   yaml_errout(y, "unknown alias at '%s'", start - 2);
                    goto out_err;
                }
                alen = strlen(a->value);
@@ -722,7 +910,7 @@
                len += 2;
                state = 0;
            } else if (!*s) {
-               errout(y, "Missing '}' for filename at '%s'", start - 2);
+               yaml_errout(y, "Missing '}' for filename at '%s'", start - 2);
                goto out_err;
            } else if (*s == '}') {
                struct yfile *f = lookup_filename_len(y, start, s - start);
@@ -741,7 +929,7 @@
     if (!out) {
        out = malloc(len + 1);
        if (!out) {
-           errout(y, "Out of memory processing string '%s'", iscalar);
+           yaml_errout(y, "Out of memory processing string '%s'", iscalar);
            return NULL;
        }
        rv = out;
@@ -772,7 +960,7 @@
     case MAIN_LEVEL:
        scalar_next_state(y, sc_main, scalar);
        if (y->state == PARSE_ERR) {
-           errout(y, "Invalid token at the main level: %s\n", scalar);
+           yaml_errout(y, "Invalid token at the main level: %s\n", scalar);
            goto out_err;
        }
        break;
@@ -780,7 +968,7 @@
     case IN_DEFINE:
        anchor_allowed = true;
        if (!anchor)
-           errout(y, "No anchor for define, define ignored\n");
+           yaml_errout(y, "No anchor for define, define ignored\n");
        else {
            if (add_alias(y, anchor, scalar))
                goto out_err;
@@ -788,11 +976,17 @@
        y->state = MAIN_LEVEL;
        break;
 
+    case IN_INCLUDE:
+       if (do_include(y, scalar))
+           goto out_err;
+       /* do_include conditionally moves us to BEGIN_DOC. */
+       break;
+
     case IN_MAIN_MAP:
        scalar_next_state(y, y->map_info->states, scalar);
        if (y->state == PARSE_ERR) {
-           errout(y, "Invalid token in the %s: %s",
-                     y->map_info->name, scalar);
+           yaml_errout(y, "Invalid token in the %s: %s",
+                       y->map_info->name, scalar);
            goto out_err;
        }
        break;
@@ -807,7 +1001,7 @@
     case IN_CONNSPEC_TIMEOUT:
        y->timeout = strtoul(scalar, &end, 0);
        if (end == scalar || *end != '\0') {
-           errout(y, "Invalid number in connection timeout");
+           yaml_errout(y, "Invalid number in connection timeout");
            goto out_err;
        }
        y->state = IN_MAIN_MAP;
@@ -819,7 +1013,7 @@
        } else if (strcasecmp(scalar, "off") == 0) {
            y->enable = false;
        } else {
-           errout(y, "enable must be 'on' or 'off'");
+           yaml_errout(y, "enable must be 'on' or 'off'");
            goto out_err;
        }
        y->state = IN_MAIN_MAP;
@@ -845,12 +1039,12 @@
        break;
 
     default:
-       errout(y, "Unexpected scalar value");
+       yaml_errout(y, "Unexpected scalar value");
        goto out_err;
     }
 
     if (anchor && !anchor_allowed)
-       errout(y, "Anchor on non-scalar ignored\n");
+       yaml_errout(y, "Anchor on non-scalar ignored\n");
 
     free(scalar);
     return 0;
@@ -869,7 +1063,7 @@
        break;
 
     default:
-       errout(y, "Unexpected sequence start: %d", y->state);
+       yaml_errout(y, "Unexpected sequence start: %d", y->state);
        return -1;
     }
 
@@ -885,7 +1079,7 @@
        break;
 
     default:
-       errout(y, "Unexpected sequence end: %d", y->state);
+       yaml_errout(y, "Unexpected sequence end: %d", y->state);
        return -1;
     }
 
@@ -902,15 +1096,15 @@
 
     case IN_MAIN_NAME:
        if (y->map_info->needs_anchor) {
-           char *anchor = (char *) y->e.data.mapping_start.anchor;
+           char *anchor = (char *) y->d->f->e.data.mapping_start.anchor;
 
            if (!anchor) {
-               errout(y, "Main mapping requires an anchor for the name");
+               yaml_errout(y, "Main mapping requires an anchor for the name");
                return -1;
            }
            y->name = strdup(anchor);
            if (!y->name) {
-               errout(y, "Out of memory allocating name");
+               yaml_errout(y, "Out of memory allocating name");
                return -1;
            }
            if (add_alias(y, anchor, anchor))
@@ -924,7 +1118,7 @@
        break;
 
     default:
-       errout(y, "Unexpected mapping start: %d", y->state);
+       yaml_errout(y, "Unexpected mapping start: %d", y->state);
        return -1;
     }
 
@@ -946,14 +1140,14 @@
        switch (y->map_info->map_type) {
        case MAIN_MAP_DEFAULT:
            if (!y->name) {
-               errout(y, "No name given in default");
+               yaml_errout(y, "No name given in default");
                return -1;
            }
            err = gensio_set_default(so, y->class, y->name, y->value, 0);
            if (err) {
-               errout(y, "Unable to set default name %s:%s:%s: %s",
-                         y->class ? y->class : "",
-                         y->name, y->value, gensio_err_to_str(err));
+               yaml_errout(y, "Unable to set default name %s:%s:%s: %s",
+                           y->class ? y->class : "",
+                           y->name, y->value, gensio_err_to_str(err));
                return -1;
            }
            y->state = MAIN_LEVEL;
@@ -962,18 +1156,18 @@
 
        case MAIN_MAP_DELDEFAULT:
            if (!y->name) {
-               errout(y, "No name given in delete_default");
+               yaml_errout(y, "No name given in delete_default");
                return -1;
            }
            if (!y->class) {
-               errout(y, "No class given in delete_default");
+               yaml_errout(y, "No class given in delete_default");
                return -1;
            }
            err = gensio_del_default(so, y->class, y->name, false);
            if (err) {
-               errout(y, "Unable to set default name %s:%s:%s: %s",
-                         y->class ? y->class : "",
-                         y->name, y->value, gensio_err_to_str(err));
+               yaml_errout(y, "Unable to set default name %s:%s:%s: %s",
+                           y->class ? y->class : "",
+                           y->name, y->value, gensio_err_to_str(err));
                return -1;
            }
            y->state = MAIN_LEVEL;
@@ -982,15 +1176,15 @@
 
        case MAIN_MAP_CONNECTION:
            if (!y->name) {
-               errout(y, "No name given in connection");
+               yaml_errout(y, "No name given in connection");
                return -1;
            }
            if (!y->accepter) {
-               errout(y, "No accepter given in connection");
+               yaml_errout(y, "No accepter given in connection");
                return -1;
            }
            if (!y->connector) {
-               errout(y, "No connector given in connection");
+               yaml_errout(y, "No connector given in connection");
                return -1;
            }
            /* NULL terminate the options. */
@@ -1005,15 +1199,15 @@
        
        case MAIN_MAP_ROTATOR:
            if (!y->name) {
-               errout(y, "No name given in rotator");
+               yaml_errout(y, "No name given in rotator");
                return -1;
            }
            if (!y->accepter) {
-               errout(y, "No accepter given in rotator");
+               yaml_errout(y, "No accepter given in rotator");
                return -1;
            }
            if (y->curr_connection == 0) {
-               errout(y, "No connections given in rotator");
+               yaml_errout(y, "No connections given in rotator");
                return -1;
            }
            /* NULL terminate the connections. */
@@ -1022,14 +1216,15 @@
            err = gensio_argv_copy(so, (const char **) y->connections,
                                   &argc, &argv);
            if (err) {
-               errout(y, "Unable to allocate rotator connections");
+               yaml_errout(y, "Unable to allocate rotator connections");
                return -1;
            }
            /* NULL terminate the options. */
            if (add_option(y, NULL, NULL, "rotator"))
                return -1;
            err = add_rotator(&y->sub_errout, y->name, y->accepter, argc, argv,
-                             (const char **) y->options, y->e.start_mark.line);
+                             (const char **) y->options,
+                             y->d->f->e.start_mark.line);
            if (err)
                gensio_argv_free(so, argv);
            y->state = MAIN_LEVEL;
@@ -1038,25 +1233,26 @@
 
        case MAIN_MAP_LED:
            if (!y->name) {
-               errout(y, "No name given in led");
+               yaml_errout(y, "No name given in led");
                return -1;
            }
            if (!y->driver) {
-               errout(y, "No driver given in led");
+               yaml_errout(y, "No driver given in led");
                return -1;
            }
            /* NULL terminate the options. */
            if (add_option(y, NULL, NULL, "led"))
                return -1;
            err = add_led(y->name, y->driver,
-                         (const char **) y->options, y->e.start_mark.line);
+                         (const char **) y->options,
+                         y->d->f->e.start_mark.line);
            y->state = MAIN_LEVEL;
            yconf_cleanup_main(y);
            break;
 
        case MAIN_MAP_ADMIN:
            if (!y->accepter) {
-               errout(y, "No accepter given in admin");
+               yaml_errout(y, "No accepter given in admin");
                return -1;
            }
            /* NULL terminate the options. */
@@ -1075,23 +1271,13 @@
        break;
 
     default:
-       errout(y, "Unexpected mapping end: %d", y->state);
+       yaml_errout(y, "Unexpected mapping end: %d", y->state);
        return -1;
     }
 
     return 0;
 }
 
-struct yaml_read_handler_data {
-    FILE *f;
-    char **config_lines;
-    unsigned int num_config_lines;
-    unsigned int curr;
-    unsigned int pos;
-    char in_quote;
-    bool in_escape;
-};
-
 /*
  * Copy characters from input to buffer, up to either buffer_size or
  * input_size.  Upon return buffer_size and input_size are updated to
@@ -1158,23 +1344,27 @@
 
     *size_read = 0;
 
-    if (d->f) {
-       *size_read = fread(buffer, 1, size, d->f);
+    if (d->f->f) {
+       *size_read = fread(buffer, 1, size, d->f->f);
        if (*size_read < size) {
-           if (ferror(d->f)) {
-               syslog(LOG_ERR, "Error reading input file: %m");
+           if (ferror(d->f->f)) {
+               yaml_errout(d->y, "Error reading input file: %s",
+                           strerror(errno));
                return 0;
            }
            /* End of file */
-           d->f = NULL;
            size -= *size_read;
            buffer += *size_read;
-       } else {
-           return 1;
+
+           /*
+            * End of file handling in the main routine will move to
+            * the next file as necessary.
+            */
        }
+       return 1;
     }
 
-    while (d->curr < d->num_config_lines && size > 1) {
+    while (d->curr < d->num_config_lines) {
        unsigned int len = strlen(d->config_lines[d->curr]);
 
        size--; /* leave space for the terminating newline. */
@@ -1185,7 +1375,7 @@
            if (!process_buffer(d, buffer, &output_processed,
                                d->config_lines[d->curr] + d->pos,
                                &input_processed)) {
-               syslog(LOG_ERR, "Invalid yaml config string");
+               yaml_errout(d->y, "Invalid yaml config string");
                return 0;
            }
            size -= output_processed;
@@ -1210,13 +1400,15 @@
 }
 
 int
-yaml_readconfig(FILE *f, char **config_lines, unsigned int num_config_lines,
+yaml_readconfig(FILE *file, char *filename,
+               char **config_lines, unsigned int num_config_lines,
                struct absout *errout)
 {
     bool done = false;
     struct yconf y;
     int err = 0;
     struct yaml_read_handler_data d;
+    struct yaml_read_file f;
 
     memset(&y, 0, sizeof(y));
     y.enable = true;
@@ -1234,29 +1426,31 @@
     }
     y.connections_len = 10;
     y.state = BEGIN_DOC;
-    y.errout = errout;
     y.sub_errout.out = sub_errout;
     y.sub_errout.data = &y;
-
-    yaml_parser_initialize(&y.parser);
+    y.d = &d;
 
     memset(&d, 0, sizeof(d));
-    d.f = f;
+    d.errout = errout;
     d.config_lines = config_lines;
     d.num_config_lines = num_config_lines;
-    yaml_parser_set_input(&y.parser, yaml_read_handler, &d);
+    d.f = &f;
+    d.y = &y;
+
+    memset(&f, 0, sizeof(f));
+    f.filename = filename;
+    f.f = file;
+    yaml_parser_initialize(&f.parser);
+    yaml_parser_set_input(&f.parser, yaml_read_handler, &d);
 
     while (!done && !err) {
-       if (!yaml_parser_parse(&y.parser, &y.e)) {
-           errout->out(errout, "yaml parsing error at line %lu column %lu: %s",
-                  (unsigned long) y.parser.problem_mark.line,
-                  (unsigned long) y.parser.problem_mark.column,
-                  y.parser.problem);
+       if (!yaml_parser_parse(&y.d->f->parser, &y.d->f->e)) {
+           yaml_errout(&y, y.d->f->parser.problem);
            err = EINVAL;
            break;
        }
 
-       switch (y.e.type) {
+       switch (y.d->f->e.type) {
        case YAML_NO_EVENT:
        case YAML_STREAM_START_EVENT:
        case YAML_DOCUMENT_START_EVENT:
@@ -1265,7 +1459,7 @@
 
        case YAML_STREAM_END_EVENT:
            if (y.state != END_DOC) {
-               errout->out(errout, "yaml file ended in invalid state: %d",
+               yaml_errout(&y, "yaml file ended in invalid state: %d",
                            y.state);
                err = EINVAL;
            }
@@ -1278,10 +1472,10 @@
            printf("YAML_ALIAS_EVENT\n");
            printf(" anc: '%s'\n", y.e.data.alias.anchor);
 #endif
-           a = lookup_alias(&y, (char *) y.e.data.alias.anchor);
+           a = lookup_alias(&y, (char *) y.d->f->e.data.alias.anchor);
            if (!a) {
-               errout->out(errout, "Unable to find alias '%s'",
-                           y.e.data.alias.anchor);
+               yaml_errout(&y, "Unable to find alias '%s'",
+                           y.d->f->e.data.alias.anchor);
                err = EINVAL;
            } else {
                if (yhandle_scalar(&y, NULL, a->value))
@@ -1297,8 +1491,8 @@
            printf(" tag: '%s'\n", y.e.data.scalar.tag);
            printf(" val: '%s'\n", y.e.data.scalar.value);
 #endif
-           if (yhandle_scalar(&y, (char *) y.e.data.scalar.anchor,
-                              (char *) y.e.data.scalar.value))
+           if (yhandle_scalar(&y, (char *) y.d->f->e.data.scalar.anchor,
+                              (char *) y.d->f->e.data.scalar.value))
                err = EINVAL;
            break;
 
@@ -1339,10 +1533,25 @@
            break;
        }
 
-       yaml_event_delete(&y.e);
+       yaml_event_delete(&y.d->f->e);
+
+       if (done) {
+       continue_clean:
+           while (d.f && !another_yaml_file_pending(&d))
+               /* Done with this include directive. */
+               cleanup_yaml_read_file(&d);
+           if (d.f) {
+               done = false;
+               yaml_parser_delete(&d.f->parser);
+               fclose(d.f->f);
+               if (next_yaml_read_file(&d))
+                   goto continue_clean;
+           }
+       }
     }
 
-    yaml_parser_delete(&y.parser);
+    while (d.f)
+       cleanup_yaml_read_file(&d);
 
     yconf_cleanup_main(&y);
     free(y.options);

Reply via email to