Example #1
0
void
__vsyslog_chk(int pri, int flag, const char *fmt, va_list ap)
{
    struct tm now_tm;
    time_t now;
    int fd;
    FILE *f;
    char *buf = 0;
    size_t bufsize = 0;
    size_t msgoff;
#ifndef NO_SIGPIPE
    struct sigaction action, oldaction;
    int sigpipe;
#endif
    int saved_errno = errno;
    char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];

#define	INTERNALLOG	LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
    /* Check for invalid bits. */
    if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
        syslog(INTERNALLOG,
               "syslog: unknown facility/priority: %x", pri);
        pri &= LOG_PRIMASK|LOG_FACMASK;
    }

    /* Check priority against setlogmask values. */
    if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
        return;

    /* Set default facility if none specified. */
    if ((pri & LOG_FACMASK) == 0)
        pri |= LogFacility;

    /* Build the message in a memory-buffer stream.  */
    f = __open_memstream (&buf, &bufsize);
    if (f == NULL)
    {
        /* We cannot get a stream.  There is not much we can do but
           emitting an error messages.  */
        char numbuf[3 * sizeof (pid_t)];
        char *nump;
        char *endp = __stpcpy (failbuf, "out of memory [");
        pid_t pid = __getpid ();

        nump = numbuf + sizeof (numbuf);
        /* The PID can never be zero.  */
        do
            *--nump = '0' + pid % 10;
        while ((pid /= 10) != 0);

        endp = __mempcpy (endp, nump, (numbuf + sizeof (numbuf)) - nump);
        *endp++ = ']';
        *endp = '\0';
        buf = failbuf;
        bufsize = endp - failbuf;
        msgoff = 0;
    }
    else
    {
        __fsetlocking (f, FSETLOCKING_BYCALLER);
        fprintf (f, "<%d>", pri);
        (void) time (&now);
        f->_IO_write_ptr += __strftime_l (f->_IO_write_ptr,
                                          f->_IO_write_end
                                          - f->_IO_write_ptr,
                                          "%h %e %T ",
                                          __localtime_r (&now, &now_tm),
                                          _nl_C_locobj_ptr);
        msgoff = ftell (f);
        if (LogTag == NULL)
            LogTag = __progname;
        if (LogTag != NULL)
            __fputs_unlocked (LogTag, f);
        if (LogStat & LOG_PID)
            fprintf (f, "[%d]", (int) __getpid ());
        if (LogTag != NULL)
        {
            putc_unlocked (':', f);
            putc_unlocked (' ', f);
        }

        /* Restore errno for %m format.  */
        __set_errno (saved_errno);

        /* We have the header.  Print the user's format into the
               buffer.  */
        if (flag == -1)
            vfprintf (f, fmt, ap);
        else
            __vfprintf_chk (f, flag, fmt, ap);

        /* Close the memory stream; this will finalize the data
           into a malloc'd buffer in BUF.  */
        fclose (f);
    }

    /* Output to stderr if requested. */
    if (LogStat & LOG_PERROR) {
        struct iovec iov[2];
        struct iovec *v = iov;

        v->iov_base = buf + msgoff;
        v->iov_len = bufsize - msgoff;
        /* Append a newline if necessary.  */
        if (buf[bufsize - 1] != '\n')
        {
            ++v;
            v->iov_base = (char *) "\n";
            v->iov_len = 1;
        }

        __libc_cleanup_push (free, buf == failbuf ? NULL : buf);

        /* writev is a cancellation point.  */
        (void)__writev(STDERR_FILENO, iov, v - iov + 1);

        __libc_cleanup_pop (0);
    }

    /* Prepare for multiple users.  We have to take care: open and
       write are cancellation points.  */
    struct cleanup_arg clarg;
    clarg.buf = buf;
    clarg.oldaction = NULL;
    __libc_cleanup_push (cancel_handler, &clarg);
    __libc_lock_lock (syslog_lock);

#ifndef NO_SIGPIPE
    /* Prepare for a broken connection.  */
    memset (&action, 0, sizeof (action));
    action.sa_handler = sigpipe_handler;
    sigemptyset (&action.sa_mask);
    sigpipe = __sigaction (SIGPIPE, &action, &oldaction);
    if (sigpipe == 0)
        clarg.oldaction = &oldaction;
#endif

    /* Get connected, output the message to the local logger. */
    if (!connected)
        openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);

    /* If we have a SOCK_STREAM connection, also send ASCII NUL as
       a record terminator.  */
    if (LogType == SOCK_STREAM)
        ++bufsize;

    if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
    {
        if (connected)
        {
            /* Try to reopen the syslog connection.  Maybe it went
               down.  */
            closelog_internal ();
            openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
        }

        if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
        {
            closelog_internal ();	/* attempt re-open next time */
            /*
             * Output the message to the console; don't worry
             * about blocking, if console blocks everything will.
             * Make sure the error reported is the one from the
             * syslogd failure.
             */
            if (LogStat & LOG_CONS &&
                    (fd = __open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY, 0)) >= 0)
            {
                __dprintf (fd, "%s\r\n", buf + msgoff);
                (void)__close(fd);
            }
        }
    }

#ifndef NO_SIGPIPE
    if (sigpipe == 0)
        __sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);
#endif

    /* End of critical section.  */
    __libc_cleanup_pop (0);
    __libc_lock_unlock (syslog_lock);

    if (buf != failbuf)
        free (buf);
}
Example #2
0
const char* __strftime_fmt_1(char (*s)[100],
                             size_t* l,
                             int f,
                             const struct tm* tm,
                             locale_t loc) {
  nl_item item;
  long long val;
  const char* fmt = "-";
  int width = 2;

  switch (f) {
    case 'a':
      if (tm->tm_wday > 6U)
        goto string;
      item = ABDAY_1 + tm->tm_wday;
      goto nl_strcat;
    case 'A':
      if (tm->tm_wday > 6U)
        goto string;
      item = DAY_1 + tm->tm_wday;
      goto nl_strcat;
    case 'h':
    case 'b':
      if (tm->tm_mon > 11U)
        goto string;
      item = ABMON_1 + tm->tm_mon;
      goto nl_strcat;
    case 'B':
      if (tm->tm_mon > 11U)
        goto string;
      item = MON_1 + tm->tm_mon;
      goto nl_strcat;
    case 'c':
      item = D_T_FMT;
      goto nl_strftime;
    case 'C':
      val = (1900LL + tm->tm_year) / 100;
      goto number;
    case 'd':
      val = tm->tm_mday;
      goto number;
    case 'D':
      fmt = "%m/%d/%y";
      goto recu_strftime;
    case 'e':
      *l = snprintf(*s, sizeof *s, "%2d", tm->tm_mday);
      return *s;
    case 'F':
      fmt = "%Y-%m-%d";
      goto recu_strftime;
    case 'g':
    case 'G':
      val = tm->tm_year + 1900LL;
      if (tm->tm_yday < 3 && week_num(tm) != 1)
        val--;
      else if (tm->tm_yday > 360 && week_num(tm) == 1)
        val++;
      if (f == 'g')
        val %= 100;
      else
        width = 4;
      goto number;
    case 'H':
      val = tm->tm_hour;
      goto number;
    case 'I':
      val = tm->tm_hour;
      if (!val)
        val = 12;
      else if (val > 12)
        val -= 12;
      goto number;
    case 'j':
      val = tm->tm_yday + 1;
      width = 3;
      goto number;
    case 'm':
      val = tm->tm_mon + 1;
      goto number;
    case 'M':
      val = tm->tm_min;
      goto number;
    case 'n':
      *l = 1;
      return "\n";
    case 'p':
      item = tm->tm_hour >= 12 ? PM_STR : AM_STR;
      goto nl_strcat;
    case 'r':
      item = T_FMT_AMPM;
      goto nl_strftime;
    case 'R':
      fmt = "%H:%M";
      goto recu_strftime;
    case 's':
      val = __tm_to_secs(tm) - tm->__tm_gmtoff;
      width = 1;
      goto number;
    case 'S':
      val = tm->tm_sec;
      goto number;
    case 't':
      *l = 1;
      return "\t";
    case 'T':
      fmt = "%H:%M:%S";
      goto recu_strftime;
    case 'u':
      val = tm->tm_wday ? tm->tm_wday : 7;
      width = 1;
      goto number;
    case 'U':
      val = (tm->tm_yday + 7U - tm->tm_wday) / 7;
      goto number;
    case 'W':
      val = (tm->tm_yday + 7U - (tm->tm_wday + 6U) % 7) / 7;
      goto number;
    case 'V':
      val = week_num(tm);
      goto number;
    case 'w':
      val = tm->tm_wday;
      width = 1;
      goto number;
    case 'x':
      item = D_FMT;
      goto nl_strftime;
    case 'X':
      item = T_FMT;
      goto nl_strftime;
    case 'y':
      val = tm->tm_year % 100;
      goto number;
    case 'Y':
      val = tm->tm_year + 1900LL;
      if (val >= 10000) {
        *l = snprintf(*s, sizeof *s, "+%lld", val);
        return *s;
      }
      width = 4;
      goto number;
    case 'z':
      if (tm->tm_isdst < 0) {
        *l = 0;
        return "";
      }
      *l = snprintf(*s, sizeof *s, "%+.2d%.2d", (tm->__tm_gmtoff) / 3600,
                    abs(tm->__tm_gmtoff % 3600) / 60);
      return *s;
    case 'Z':
      if (tm->tm_isdst < 0) {
        *l = 0;
        return "";
      }
      fmt = __tm_to_tzname(tm);
      goto string;
    case '%':
      *l = 1;
      return "%";
    default:
      return 0;
  }
number:
  *l = snprintf(*s, sizeof *s, "%0*lld", width, val);
  return *s;
nl_strcat:
  fmt = __nl_langinfo_l(item, loc);
string:
  *l = strlen(fmt);
  return fmt;
nl_strftime:
  fmt = __nl_langinfo_l(item, loc);
recu_strftime:
  *l = __strftime_l(*s, sizeof *s, fmt, tm, loc);
  if (!*l)
    return 0;
  return *s;
}