Logo Search packages:      
Sourcecode: wdm version File versions  Download package

loghelpers.c

/*
 * wdm - WINGs display manager
 * Copyright (C) 2003, 2004 Alexey Voinov <voins@voins.program.ru>
 *
 * 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 of the License, 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * loghelpers.c: helper functions for intecepting messages in stderr
 *               and redirecting them to standard logging functions.
 */
#include <wdmlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <dm.h>
#include <signal.h>

/*
 * I hate global variables. But I don't know other way to pass information to 
 * signal handler... :(
 */
static pid_t childpid = 0;

/*
 * Function that treats buffer as set of lines separated with '\n'
 * These lines will be directed to WDMLogMessage function with
 * specified message level. n is a number of actual characters in buffer.
 *
 * Returned value is pointer to string that is left unterminated with '\n'
 */
char *
WDMLogMessages(int level, char *buffer, int n)
{
      char *tmpmsg, *pos;

      while((pos = memchr(buffer, '\n', n)) != NULL)
      {
            tmpmsg = wmalloc(pos - buffer + 2);
            strncpy(tmpmsg, buffer, pos - buffer + 1);
            tmpmsg[pos - buffer + 1] = '\0';
            WDMLogMessage(level, "%s", tmpmsg);
            wfree(tmpmsg);

            n -= pos - buffer + 1;
            buffer = pos + 1;
      }

      return buffer;
}

void
WDMBufferedLogMessages(int level, char *buffer, int n)
{
      static char *old = NULL;
      static size_t oldn = 0;

      char *rest;

      old = wrealloc(old, oldn + n);
      memcpy(old + oldn, buffer, n);
      oldn += n;

      rest = WDMLogMessages(level, old, oldn);

      oldn -= rest - old;
      memmove(old, rest, oldn);
}

int
WDMRedirectFileToLog(int level, pid_t pid, int fd)
{
      fd_set set;
      int status;
      struct timeval tv;
      char buf[1024];
      int n;

      WDMDebug("logger started\n");
      while(waitpid(pid, &status, WNOHANG) == 0)
      {
            FD_ZERO(&set);
            FD_SET(fd, &set);
            tv.tv_sec = 1;
            tv.tv_usec = 0;
            if(select(fd + 1, &set, NULL, NULL, &tv) > 0)
            {
                  n = read(fd, buf, sizeof(buf));
                  if(n == -1)
                        WDMError("error reading form pipe(stderr)\n");

                  WDMBufferedLogMessages(level, buf, n);
            }
      }
      WDMBufferedLogMessages(level, "\n", 1);
      WDMDebug("logger stopped\n");

      return WEXITSTATUS(status);
}

void WDMRedirectSignals(int n)
{
      kill(childpid, n);
#ifdef SIGNALS_RESET_WHEN_CAUGHT
      Signal(n, WDMRedirectSignals);
#endif
}

void
WDMRedirectStderr(int level)
{
      int errpipe[2];
      int exitstatus;

      if(pipe(errpipe) == -1)
            WDMError("cannot create pipe. "
                        "all stderr messages will go to stderr\n");

      childpid = fork();
      if(childpid == -1)
      {
            WDMError("fork failed. "
                        "all stderr messages will go to stderr\n");
            close(errpipe[0]);
            close(errpipe[1]);
      }
      else if(childpid != 0)
      {
            /* parent, will read all messages from stderr and
             * redirect it to log */
            Signal(SIGTERM, WDMRedirectSignals);
            Signal(SIGINT, WDMRedirectSignals);
            Signal(SIGHUP, WDMRedirectSignals);
            close(errpipe[1]);
            exitstatus = WDMRedirectFileToLog(WDM_LEVEL_ERROR,
                                          childpid, errpipe[0]);
            close(errpipe[0]);
            exit(exitstatus);
      }

      /* child, will close read end of pipe and dup2
       * write end of pipe to stderr */
      close(errpipe[0]);
      RegisterCloseOnFork(errpipe[1]);
      dup2(errpipe[1], 2);
}


Generated by  Doxygen 1.6.0   Back to index