summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--Makefile.in2
-rw-r--r--action.c65
-rwxr-xr-xconfigure20
-rw-r--r--configure.ac2
-rw-r--r--doc/manual.html2
-rw-r--r--doc/rsyslog_pgsql.html4
-rwxr-xr-xltmain.sh4
-rw-r--r--plugins/immark/immark.c1
-rw-r--r--runtime/msg.c14
-rw-r--r--runtime/queue.c9
-rw-r--r--tools/pmrfc3164.c2
-rwxr-xr-xylwrap222
13 files changed, 313 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index 74fc007..de4e4b5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,14 @@
---------------------------------------------------------------------------
+Version 5.8.5 [V5-stable] (rgerhards/al), 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
+- bugfix: mark message processing did not work correctly
+- bugfix: potential hang condition during tag emulation
+- bugfix: too-early string termination during tag emulation
+- bugfix: The NUL-Byte for the syslogtag was not copied in MsgDup (msg.c)
+- bugfix: fixed incorrect state handling for Discard Action (transactions)
+ Note: This caused all messages in a batch to be set to COMMITTED,
+ even if they were discarded.
+---------------------------------------------------------------------------
Version 5.8.4 [V5-stable] (al), 2011-08-10
- bugfix: potential misadressing in property replacer
- bugfix: memcpy overflow can occur in allowed sender checkig
@@ -861,11 +871,13 @@ Version 4.7.0 [v4-devel] (rgerhards), 2010-04-14
Thanks for varmojfekoj for pointing me at this bug.
- imported changes from 4.5.6 and below
---------------------------------------------------------------------------
-Version 4.6.8 [v4-stable] (rgerhards), 2011-??-??
+Version 4.6.8 [v4-stable] (rgerhards), 2011-09-01
+- bugfix/security: off-by-two bug in legacy syslog parser, CVE-2011-3200
- bugfix: potential misadressing in property replacer
-- bugfix: memcpy overflow can occur in allowed sender checkig
+- bugfix: memcpy overflow can occur in allowed sender checking
if a name is resolved to IPv4-mapped-on-IPv6 address
Found by Ismail Dönmez at suse
+- bugfix: The NUL-Byte for the syslogtag was not copied in MsgDup (msg.c)
---------------------------------------------------------------------------
Version 4.6.7 [v4-stable] (rgerhards), 2011-07-11
- added support for the ":omusrmsg:" syntax in configuring user messages
diff --git a/Makefile.in b/Makefile.in
index b0cfd26..08dbad5 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -82,7 +82,7 @@ DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
$(top_srcdir)/configure AUTHORS COPYING COPYING.LESSER \
ChangeLog INSTALL NEWS compile config.guess config.sub depcomp \
- install-sh ltmain.sh missing
+ install-sh ltmain.sh missing ylwrap
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/atomic_operations.m4 \
$(top_srcdir)/m4/atomic_operations_64bit.m4 \
diff --git a/action.c b/action.c
index 54a05fc..951b472 100644
--- a/action.c
+++ b/action.c
@@ -960,7 +960,7 @@ tryDoAction(action_t *pAction, batch_t *pBatch, int *pnElem)
i = pBatch->iDoneUpTo; /* all messages below that index are processed */
iElemProcessed = 0;
iCommittedUpTo = i;
-dbgprintf("XXXXX: tryDoAction %p, pnElem %d, nElem %d\n", pAction, *pnElem, pBatch->nElem);
+dbgprintf("XXXXX: tryDoAction %p, pnElem %d, nElem %d\n", pAction, *pnElem, pBatch->nElem);
while(iElemProcessed <= *pnElem && i < pBatch->nElem) {
if(*(pBatch->pbShutdownImmediate))
ABORT_FINALIZE(RS_RET_FORCE_TERM);
@@ -980,13 +980,17 @@ dbgprintf("XXXXX: tryDoAction %p, pnElem %d, nElem %d\n", pAction, *pnElem,
/* mark messages as committed */
while(iCommittedUpTo <= i) {
pBatch->pElem[iCommittedUpTo].bPrevWasSuspended = 0; /* we had success! */
- pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
+ batchSetElemState(pBatch, iCommittedUpTo, BATCH_STATE_COMM);
+ ++iCommittedUpTo;
+ //pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
}
} else if(localRet == RS_RET_PREVIOUS_COMMITTED) {
/* mark messages as committed */
while(iCommittedUpTo < i) {
pBatch->pElem[iCommittedUpTo].bPrevWasSuspended = 0; /* we had success! */
- pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
+ batchSetElemState(pBatch, iCommittedUpTo, BATCH_STATE_COMM);
+ ++iCommittedUpTo;
+ //pBatch->pElem[iCommittedUpTo++].state = BATCH_STATE_COMM;
}
pBatch->pElem[i].state = BATCH_STATE_SUB;
} else if(localRet == RS_RET_DEFER_COMMIT) {
@@ -1011,6 +1015,15 @@ finalize_it:
RETiRet;
}
+/* debug aid */
+static void displayBatchState(batch_t *pBatch)
+{
+ int i;
+ for(i = 0 ; i < pBatch->nElem ; ++i) {
+ dbgprintf("XXXXX: displayBatchState2 %p[%d]: %d\n", pBatch, i, pBatch->pElem[i].state);
+ }
+}
+
/* submit a batch for actual action processing.
* The first nElem elements are processed. This function calls itself
@@ -1468,7 +1481,6 @@ doSubmitToActionQNotAllMarkBatch(action_t *pAction, batch_t *pBatch)
time_t now = 0;
time_t lastAct;
int i;
- int bProcessMarkMsgs = 0;
int bModifiedFilter;
sbool FilterSave[1024];
sbool *pFilterSave;
@@ -1482,33 +1494,32 @@ doSubmitToActionQNotAllMarkBatch(action_t *pAction, batch_t *pBatch)
bModifiedFilter = 0;
for(i = 0 ; i < batchNumMsgs(pBatch) ; ++i) {
+ if(!pBatch->pElem[i].bFilterOK)
+ continue;
pFilterSave[i] = pBatch->pElem[i].bFilterOK;
- if(((msg_t*)(pBatch->pElem[i].pUsrp))->msgFlags & MARK) {
- /* check if we need to write or not */
- if(now == 0) {
- now = datetime.GetTime(NULL); /* good time call - the only one done */
- /* CAS loop, we write back a bit early, but that's OK... */
- /* we use reception time, not dequeue time - this is considered more appropriate and
- * also faster ;) -- rgerhards, 2008-09-17 */
- do {
- lastAct = pAction->f_time;
- if((now - lastAct) < MarkInterval / 2) {
- DBGPRINTF("action was recently called, ignoring mark message\n");
- bProcessMarkMsgs = 0;
- } else {
- bProcessMarkMsgs = 1;
- }
- } while(ATOMIC_CAS_time_t(&pAction->f_time, lastAct,
- ((msg_t*)(pBatch->pElem[i].pUsrp))->ttGenTime, &pAction->mutCAS) == 0);
- }
- if(bProcessMarkMsgs) {
- pBatch->pElem[i].bFilterOK = 0;
- bModifiedFilter = 1;
+ if(now == 0) {
+ now = datetime.GetTime(NULL); /* good time call - the only one done */
+ }
+ /* CAS loop, we write back a bit early, but that's OK... */
+ /* we use reception time, not dequeue time - this is considered more appropriate and
+ * also faster ;) -- rgerhards, 2008-09-17 */
+ do {
+ lastAct = pAction->f_time;
+ if(((msg_t*)(pBatch->pElem[i].pUsrp))->msgFlags & MARK) {
+ if((now - lastAct) < MarkInterval / 2) {
+ pBatch->pElem[i].bFilterOK = 0;
+ bModifiedFilter = 1;
+ DBGPRINTF("action was recently called, ignoring mark message\n");
+ break; /* do not update timestamp for non-written mark messages */
+ }
}
+ } while(ATOMIC_CAS_time_t(&pAction->f_time, lastAct,
+ ((msg_t*)(pBatch->pElem[i].pUsrp))->ttGenTime, &pAction->mutCAS) == 0);
+ if(pBatch->pElem[i].bFilterOK) {
+ DBGPRINTF("Called action(NotAllMark), processing batch[%d] via '%s'\n",
+ i, module.GetStateName(pAction->pMod));
}
}
-
- DBGPRINTF("Called action(NotAllMark), logging to %s\n", module.GetStateName(pAction->pMod));
iRet = doSubmitToActionQBatch(pAction, pBatch);
diff --git a/configure b/configure
index a0912ec..8806340 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.67 for rsyslog 5.8.4.
+# Generated by GNU Autoconf 2.67 for rsyslog 5.8.5.
#
# Report bugs to <rsyslog@lists.adiscon.com>.
#
@@ -701,8 +701,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='rsyslog'
PACKAGE_TARNAME='rsyslog'
-PACKAGE_VERSION='5.8.4'
-PACKAGE_STRING='rsyslog 5.8.4'
+PACKAGE_VERSION='5.8.5'
+PACKAGE_STRING='rsyslog 5.8.5'
PACKAGE_BUGREPORT='rsyslog@lists.adiscon.com'
PACKAGE_URL=''
@@ -1616,7 +1616,7 @@ if test "$ac_init_help" = "long"; then
# 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 rsyslog 5.8.4 to adapt to many kinds of systems.
+\`configure' configures rsyslog 5.8.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1686,7 +1686,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of rsyslog 5.8.4:";;
+ short | recursive ) echo "Configuration of rsyslog 5.8.5:";;
esac
cat <<\_ACEOF
@@ -1861,7 +1861,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-rsyslog configure 5.8.4
+rsyslog configure 5.8.5
generated by GNU Autoconf 2.67
Copyright (C) 2010 Free Software Foundation, Inc.
@@ -2440,7 +2440,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by rsyslog $as_me 5.8.4, which was
+It was created by rsyslog $as_me 5.8.5, which was
generated by GNU Autoconf 2.67. Invocation command line was
$ $0 $@
@@ -3255,7 +3255,7 @@ fi
# Define the identity of the package.
PACKAGE='rsyslog'
- VERSION='5.8.4'
+ VERSION='5.8.5'
cat >>confdefs.h <<_ACEOF
@@ -17211,7 +17211,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by rsyslog $as_me 5.8.4, which was
+This file was extended by rsyslog $as_me 5.8.5, which was
generated by GNU Autoconf 2.67. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -17277,7 +17277,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-rsyslog config.status 5.8.4
+rsyslog config.status 5.8.5
configured by $0, generated by GNU Autoconf 2.67,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 2706ec0..8ee2424 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[5.8.4],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[5.8.5],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
diff --git a/doc/manual.html b/doc/manual.html
index a2c4122..7952099 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ rsyslog support</a> available directly from the source!</p>
<p><b>Please visit the <a href="http://www.rsyslog.com/sponsors">rsyslog sponsor's page</a>
to honor the project sponsors or become one yourself!</b> We are very grateful for any help towards the
project goals.</p>
-<p><b>This documentation is for version 5.8.4 (v5-stable branch) of rsyslog.</b>
+<p><b>This documentation is for version 5.8.5 (v5-stable branch) of rsyslog.</b>
Visit the <i><a href="http://www.rsyslog.com/status">rsyslog status page</a></i></b>
to obtain current version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/rsyslog_pgsql.html b/doc/rsyslog_pgsql.html
index dcb9dc3..21516ec 100644
--- a/doc/rsyslog_pgsql.html
+++ b/doc/rsyslog_pgsql.html
@@ -30,7 +30,7 @@
-->
</STYLE>
</HEAD>
-<BODY LANG="de-DE" DIR="LTR">
+<BODY>
<H1 CLASS="western"><SPAN LANG="en-US">Writing </SPAN>syslog messages
to MySQL, PostgreSQL or any other supported Database</H1>
<P CLASS="western"><FONT SIZE=2><I>Written by </I></FONT><A HREF="http://www.adiscon.com/en/people/rainer-gerhards.php"><FONT SIZE=2><I>Rainer
@@ -333,4 +333,4 @@ Gerhards</A>, Marc Schiffbauer and <A HREF="http://www.adiscon.com/en/">Adiscon<
<P CLASS="western"><BR><BR>
</P>
</BODY>
-</HTML> \ No newline at end of file
+</HTML>
diff --git a/ltmain.sh b/ltmain.sh
index d88da2c..fa4b1e1 100755
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -65,7 +65,7 @@
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2
+# $progname: (GNU libtool) 2.2.6b Debian-2.2.6b-2ubuntu3
# automake: $automake_version
# autoconf: $autoconf_version
#
@@ -73,7 +73,7 @@
PROGRAM=ltmain.sh
PACKAGE=libtool
-VERSION="2.2.6b Debian-2.2.6b-2"
+VERSION="2.2.6b Debian-2.2.6b-2ubuntu3"
TIMESTAMP=""
package_revision=1.3017
diff --git a/plugins/immark/immark.c b/plugins/immark/immark.c
index 6410003..baac13a 100644
--- a/plugins/immark/immark.c
+++ b/plugins/immark/immark.c
@@ -87,6 +87,7 @@ CODESTARTrunInput
if(glbl.GetGlobalInputTermState() == 1)
break; /* terminate input! */
+ dbgprintf("immark: injecting mark message\n");
logmsgInternal(NO_ERRCODE, LOG_INFO, (uchar*)"-- MARK --", MARK);
}
ENDrunInput
diff --git a/runtime/msg.c b/runtime/msg.c
index cc7b463..f1de813 100644
--- a/runtime/msg.c
+++ b/runtime/msg.c
@@ -967,7 +967,7 @@ msg_t* MsgDup(msg_t* pOld)
*/
if(pOld->iLenTAG > 0) {
if(pOld->iLenTAG < CONF_TAG_BUFSIZE) {
- memcpy(pNew->TAG.szBuf, pOld->TAG.szBuf, pOld->iLenTAG);
+ memcpy(pNew->TAG.szBuf, pOld->TAG.szBuf, pOld->iLenTAG + 1);
} else {
if((pNew->TAG.pszTAG = srUtilStrDup(pOld->TAG.pszTAG, pOld->iLenTAG)) == NULL) {
msgDestruct(&pNew);
@@ -1661,6 +1661,8 @@ void MsgSetTAG(msg_t *pMsg, uchar* pszBuf, size_t lenBuf)
uchar *pBuf;
assert(pMsg != NULL);
+dbgprintf("MsgSetTAG in: len %d, pszBuf: %s\n", lenBuf, pszBuf);
+
freeTAG(pMsg);
pMsg->iLenTAG = lenBuf;
@@ -1679,6 +1681,8 @@ void MsgSetTAG(msg_t *pMsg, uchar* pszBuf, size_t lenBuf)
memcpy(pBuf, pszBuf, pMsg->iLenTAG);
pBuf[pMsg->iLenTAG] = '\0'; /* this also works with truncation! */
+
+dbgprintf("MsgSetTAG exit: pMsg->iLenTAG %d, pMsg->TAG.szBuf: %s\n", pMsg->iLenTAG, pMsg->TAG.szBuf);
}
@@ -1697,8 +1701,11 @@ static inline void tryEmulateTAG(msg_t *pM, sbool bLockMutex)
if(bLockMutex == LOCK_MUTEX)
MsgLock(pM);
- if(pM->iLenTAG > 0)
+ if(pM->iLenTAG > 0) {
+ if(bLockMutex == LOCK_MUTEX)
+ MsgUnlock(pM);
return; /* done, no need to emulate */
+ }
if(getProtocolVersion(pM) == 1) {
if(!strcmp(getPROCID(pM, MUTEX_ALREADY_LOCKED), "-")) {
@@ -1708,7 +1715,7 @@ static inline void tryEmulateTAG(msg_t *pM, sbool bLockMutex)
/* now we can try to emulate */
lenTAG = snprintf((char*)bufTAG, CONF_TAG_MAXSIZE, "%s[%s]",
getAPPNAME(pM, MUTEX_ALREADY_LOCKED), getPROCID(pM, MUTEX_ALREADY_LOCKED));
- bufTAG[32] = '\0'; /* just to make sure... */
+ bufTAG[sizeof(bufTAG)-1] = '\0'; /* just to make sure... */
MsgSetTAG(pM, bufTAG, lenTAG);
}
}
@@ -1734,6 +1741,7 @@ getTAG(msg_t *pM, uchar **ppBuf, int *piLen)
*piLen = pM->iLenTAG;
}
}
+dbgprintf("getTAG: len %d, buf '%s'\n", *piLen, *ppBuf);
}
diff --git a/runtime/queue.c b/runtime/queue.c
index 00eb76c..9012abe 100644
--- a/runtime/queue.c
+++ b/runtime/queue.c
@@ -88,6 +88,15 @@ static rsRetVal qqueueMultiEnqObjDirect(qqueue_t *pThis, multi_submit_t *pMultiS
#define QUEUE_CHECKPOINT 1
#define QUEUE_NO_CHECKPOINT 0
+/* debug aid */
+static void displayBatchState(batch_t *pBatch)
+{
+ int i;
+ for(i = 0 ; i < pBatch->nElem ; ++i) {
+ dbgprintf("XXXXX: displayBatchState %p[%d]: %d\n", pBatch, i, pBatch->pElem[i].state);
+ }
+}
+
/***********************************************************************
* we need a private data structure, the "to-delete" list. As C does
* not provide any partly private data structures, we implement this
diff --git a/tools/pmrfc3164.c b/tools/pmrfc3164.c
index 635ca98..6d2d22b 100644
--- a/tools/pmrfc3164.c
+++ b/tools/pmrfc3164.c
@@ -177,7 +177,7 @@ CODESTARTparse
* outputs so that only 32 characters max are used by default.
*/
i = 0;
- while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE) {
+ while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE - 2) {
bufParseTAG[i++] = *p2parse++;
--lenMsg;
}
diff --git a/ylwrap b/ylwrap
new file mode 100755
index 0000000..84d5634
--- /dev/null
+++ b/ylwrap
@@ -0,0 +1,222 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
+# 2007, 2009 Free Software Foundation, Inc.
+#
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program 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, or (at your option)
+# any later version.
+#
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case "$1" in
+ '')
+ echo "$0: No files given. Try \`$0 --help' for more information." 1>&2
+ exit 1
+ ;;
+ --basedir)
+ basedir=$2
+ shift 2
+ ;;
+ -h|--h*)
+ cat <<\EOF
+Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+
+Wrapper for lex/yacc invocations, renaming files as desired.
+
+ INPUT is the input file
+ OUTPUT is one file PROG generates
+ DESIRED is the file we actually want instead of OUTPUT
+ PROGRAM is program to run
+ ARGS are passed to PROG
+
+Any number of OUTPUT,DESIRED pairs may be used.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v|--v*)
+ echo "ylwrap $scriptversion"
+ exit $?
+ ;;
+esac
+
+
+# The input.
+input="$1"
+shift
+case "$input" in
+ [\\/]* | ?:[\\/]*)
+ # Absolute path; do nothing.
+ ;;
+ *)
+ # Relative path. Make it absolute.
+ input="`pwd`/$input"
+ ;;
+esac
+
+pairlist=
+while test "$#" -ne 0; do
+ if test "$1" = "--"; then
+ shift
+ break
+ fi
+ pairlist="$pairlist $1"
+ shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+ [\\/]* | ?:[\\/]*) ;;
+ *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines. But that might take us over the 14-char limit.
+dirname=ylwrap$$
+trap "cd '`pwd`'; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+case $# in
+ 0) "$prog" "$input" ;;
+ *) "$prog" "$@" "$input" ;;
+esac
+ret=$?
+
+if test $ret -eq 0; then
+ set X $pairlist
+ shift
+ first=yes
+ # Since DOS filename conventions don't allow two dots,
+ # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+ # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+ y_tab_nodot="no"
+ if test -f y_tab.c || test -f y_tab.h; then
+ y_tab_nodot="yes"
+ fi
+
+ # The directory holding the input.
+ input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+ # Quote $INPUT_DIR so we can use it in a regexp.
+ # FIXME: really we should care about more than `.' and `\'.
+ input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
+
+ while test "$#" -ne 0; do
+ from="$1"
+ # Handle y_tab.c and y_tab.h output by DOS
+ if test $y_tab_nodot = "yes"; then
+ if test $from = "y.tab.c"; then
+ from="y_tab.c"
+ else
+ if test $from = "y.tab.h"; then
+ from="y_tab.h"
+ fi
+ fi
+ fi
+ if test -f "$from"; then
+ # If $2 is an absolute path name, then just use that,
+ # otherwise prepend `../'.
+ case "$2" in
+ [\\/]* | ?:[\\/]*) target="$2";;
+ *) target="../$2";;
+ esac
+
+ # We do not want to overwrite a header file if it hasn't
+ # changed. This avoid useless recompilations. However the
+ # parser itself (the first file) should always be updated,
+ # because it is the destination of the .y.c rule in the
+ # Makefile. Divert the output of all other files to a temporary
+ # file so we can compare them to existing versions.
+ if test $first = no; then
+ realtarget="$target"
+ target="tmp-`echo $target | sed s/.*[\\/]//g`"
+ fi
+ # Edit out `#line' or `#' directives.
+ #
+ # We don't want the resulting debug information to point at
+ # an absolute srcdir; it is better for it to just mention the
+ # .y file with no path.
+ #
+ # We want to use the real output file name, not yy.lex.c for
+ # instance.
+ #
+ # We want the include guards to be adjusted too.
+ FROM=`echo "$from" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+ TARGET=`echo "$2" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+
+ sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
+ -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
+
+ # Check whether header files must be updated.
+ if test $first = no; then
+ if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
+ echo "$2" is unchanged
+ rm -f "$target"
+ else
+ echo updating "$2"
+ mv -f "$target" "$realtarget"
+ fi
+ fi
+ else
+ # A missing file is only an error for the first file. This
+ # is a blatant hack to let us support using "yacc -d". If -d
+ # is not specified, we don't want an error when the header
+ # file is "missing".
+ if test $first = yes; then
+ ret=1
+ fi
+ fi
+ shift
+ shift
+ first=no
+ done
+else
+ ret=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End: