[BACK]Return to log.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/log.c, Revision 1.34

1.34    ! xsa         1: /*     $OpenBSD: log.c,v 1.33 2006/04/14 02:45:35 deraadt Exp $        */
1.1       jfb         2: /*
1.2       jfb         3:  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.1       jfb         4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  *
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. The name of the author may not be used to endorse or promote products
                     13:  *    derived from this software without specific prior written permission.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     16:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     17:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     18:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     19:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
                     26:
1.29      xsa        27: #include "includes.h"
1.1       jfb        28:
1.16      xsa        29: #include "cvs.h"
1.1       jfb        30: #include "log.h"
                     31:
                     32: extern char *__progname;
                     33:
1.3       jfb        34:
1.2       jfb        35: #ifdef unused
1.13      jfb        36: static char *cvs_log_levels[LP_MAX + 1] = {
1.1       jfb        37:        "debug",
                     38:        "info",
                     39:        "notice",
                     40:        "warning",
                     41:        "error",
                     42:        "alert",
1.4       jfb        43:        "error",
                     44:        "abort",
1.13      jfb        45:        "trace",
1.1       jfb        46: };
1.2       jfb        47: #endif
1.1       jfb        48:
1.13      jfb        49: static int cvs_slpriomap[LP_MAX + 1] = {
1.1       jfb        50:        LOG_DEBUG,
1.24      xsa        51:        LOG_INFO,
1.23      xsa        52:        LOG_NOTICE,
1.1       jfb        53:        LOG_WARNING,
                     54:        LOG_ERR,
                     55:        LOG_ALERT,
                     56:        LOG_ERR,
1.4       jfb        57:        LOG_ERR,
1.13      jfb        58:        LOG_DEBUG,
1.1       jfb        59: };
                     60:
1.26      niallo     61: #if !defined(RCSPROG)
1.19      joris      62: static int send_m = 1;
1.26      niallo     63: #endif
1.1       jfb        64: static u_int cvs_log_dest = LD_STD;
                     65: static u_int cvs_log_flags = 0;
                     66:
1.10      jfb        67: static struct syslog_data cvs_sl = SYSLOG_DATA_INIT;
1.1       jfb        68:
1.9       jfb        69: /* filter manipulation macros */
1.22      xsa        70: #define CVS_LOG_FLTRRST()      (cvs_log_filters = 0)
                     71: #define CVS_LOG_FLTRSET(l)     (cvs_log_filters |= (1 << l))
                     72: #define CVS_LOG_FLTRGET(l)     (cvs_log_filters & (1 << l))
                     73: #define CVS_LOG_FLTRCLR(l)     (cvs_log_filters &= ~(1 << l))
1.1       jfb        74:
1.9       jfb        75: static u_int cvs_log_filters;
1.1       jfb        76:
                     77:
                     78: /*
                     79:  * cvs_log_init()
                     80:  *
                     81:  * Initialize the logging facility of the server.
                     82:  */
1.30      xsa        83: void
1.1       jfb        84: cvs_log_init(u_int dest, u_int flags)
                     85: {
                     86:        int slopt;
                     87:
                     88:        cvs_log_dest = dest;
                     89:        cvs_log_flags = flags;
                     90:
                     91:        /* by default, filter only LP_DEBUG and LP_INFO levels */
1.9       jfb        92:        CVS_LOG_FLTRRST();
                     93:        CVS_LOG_FLTRSET(LP_DEBUG);
                     94:        CVS_LOG_FLTRSET(LP_INFO);
1.1       jfb        95:
1.8       jfb        96:        /* traces are enabled with the -t command-line option */
1.9       jfb        97:        CVS_LOG_FLTRSET(LP_TRACE);
1.8       jfb        98:
1.1       jfb        99:        if (dest & LD_SYSLOG) {
                    100:                slopt = 0;
                    101:
                    102:                if (dest & LD_CONS)
                    103:                        slopt |= LOG_CONS;
                    104:                if (flags & LF_PID)
                    105:                        slopt |= LOG_PID;
                    106:
                    107:                openlog_r(__progname, slopt, LOG_DAEMON, &cvs_sl);
                    108:        }
                    109: }
                    110:
                    111:
                    112: /*
                    113:  * cvs_log_cleanup()
                    114:  *
                    115:  * Cleanup the logging facility.
                    116:  */
                    117: void
                    118: cvs_log_cleanup(void)
                    119: {
1.7       tedu      120:
1.1       jfb       121:        closelog_r(&cvs_sl);
                    122: }
                    123:
                    124:
                    125: /*
                    126:  * cvs_log_filter()
                    127:  *
                    128:  * Apply or remove filters on the logging facility.  The exact operation is
                    129:  * specified by the <how> and <level> arguments.  The <how> arguments tells
                    130:  * how the filters will be affected, and <level> gives the log levels that
                    131:  * will be affected by the change.
                    132:  * Returns 0 on success, or -1 on failure.
                    133:  */
                    134:
                    135: int
                    136: cvs_log_filter(u_int how, u_int level)
                    137: {
                    138:        u_int i;
                    139:
1.33      deraadt   140:        if (level > LP_MAX && level != LP_ALL) {
1.1       jfb       141:                cvs_log(LP_ERR, "invalid log level for filter");
                    142:                return (-1);
                    143:        }
                    144:
                    145:        switch (how) {
                    146:        case LP_FILTER_SET:
                    147:                if (level == LP_ALL)
1.9       jfb       148:                        for (i = 0; i <= LP_MAX; i++)
                    149:                                CVS_LOG_FLTRSET(i);
1.1       jfb       150:                else
1.9       jfb       151:                        CVS_LOG_FLTRSET(level);
1.1       jfb       152:                break;
                    153:        case LP_FILTER_UNSET:
                    154:                if (level == LP_ALL)
1.9       jfb       155:                        CVS_LOG_FLTRRST();
1.1       jfb       156:                else
1.9       jfb       157:                        CVS_LOG_FLTRCLR(level);
1.1       jfb       158:                break;
                    159:        default:
                    160:                return (-1);
                    161:        }
                    162:
                    163:        return (0);
                    164: }
                    165:
                    166:
                    167: /*
                    168:  * cvs_log()
                    169:  *
                    170:  * Log the format-string message
                    171:  * The <fmt> argument should not have a terminating newline, as this is taken
                    172:  * care of by the logging facility.
                    173:  */
1.34    ! xsa       174: void
1.1       jfb       175: cvs_log(u_int level, const char *fmt, ...)
                    176: {
                    177:        va_list vap;
                    178:
                    179:        va_start(vap, fmt);
1.34    ! xsa       180:        cvs_vlog(level, fmt, vap);
1.1       jfb       181:        va_end(vap);
                    182: }
                    183:
                    184:
                    185: /*
                    186:  * cvs_vlog()
                    187:  *
                    188:  * The <fmt> argument should not have a terminating newline, as this is taken
                    189:  * care of by the logging facility.
                    190:  */
1.34    ! xsa       191: void
1.1       jfb       192: cvs_vlog(u_int level, const char *fmt, va_list vap)
                    193: {
                    194:        int ecp;
1.25      xsa       195:        char prefix[64], buf[1024], ebuf[255];
1.1       jfb       196:        FILE *out;
1.26      niallo    197: #if !defined(RCSPROG)
1.27      joris     198:        char *cmdname;
1.20      joris     199:        struct cvs_cmd *cmdp;
1.26      niallo    200: #endif
1.1       jfb       201:
1.13      jfb       202:        if (level > LP_MAX)
1.34    ! xsa       203:                fatal("cvs_vlog failed");
1.1       jfb       204:
                    205:        /* apply any filters */
1.9       jfb       206:        if (CVS_LOG_FLTRGET(level))
1.34    ! xsa       207:                return;
1.1       jfb       208:
                    209:        if (level == LP_ERRNO)
                    210:                ecp = errno;
1.4       jfb       211:        else
                    212:                ecp = 0;
1.1       jfb       213:
1.17      xsa       214:        /* always use the command name in error messages, not aliases */
1.26      niallo    215: #if !defined(RCSPROG)
1.27      joris     216:        if (cvs_command == NULL)
                    217:                cmdname = " ";
                    218:        else {
                    219:                cmdp = cvs_findcmd(cvs_command);
                    220:                cmdname = cmdp->cmd_name;
                    221:        }
1.17      xsa       222:
1.3       jfb       223:        /* The cvs program appends the command name to the program name */
1.8       jfb       224:        if (level == LP_TRACE) {
                    225:                strlcpy(prefix, " -> ", sizeof(prefix));
                    226:                if (cvs_cmdop == CVS_OP_SERVER)
                    227:                        prefix[0] = 'S';
                    228:        } else if (cvs_command != NULL) {
1.4       jfb       229:                if (level == LP_ABORT)
                    230:                        snprintf(prefix, sizeof(prefix), "%s [%s aborted]",
1.27      joris     231:                            __progname, cmdname);
1.4       jfb       232:                else
                    233:                        snprintf(prefix, sizeof(prefix), "%s %s", __progname,
1.27      joris     234:                            cmdname);
1.6       deraadt   235:        } else /* just use the standard strlcpy */
1.26      niallo    236: #endif
1.3       jfb       237:                strlcpy(prefix, __progname, sizeof(prefix));
                    238:
1.33      deraadt   239:        if ((cvs_log_flags & LF_PID) && level != LP_TRACE) {
1.1       jfb       240:                snprintf(buf, sizeof(buf), "[%d]", (int)getpid());
                    241:                strlcat(prefix, buf, sizeof(prefix));
                    242:        }
                    243:
                    244:        vsnprintf(buf, sizeof(buf), fmt, vap);
                    245:        if (level == LP_ERRNO) {
                    246:                snprintf(ebuf, sizeof(ebuf), ": %s", strerror(errno));
                    247:                strlcat(buf, ebuf, sizeof(buf));
                    248:        }
                    249:
                    250:        if (cvs_log_dest & LD_STD) {
1.24      xsa       251:                if (level < LP_NOTICE)
1.1       jfb       252:                        out = stdout;
                    253:                else
                    254:                        out = stderr;
1.3       jfb       255:
1.26      niallo    256: #if !defined(RCSPROG)
1.3       jfb       257:                if (cvs_cmdop == CVS_OP_SERVER) {
                    258:                        if (out == stdout)
                    259:                                putc('M', out);
1.11      jfb       260:                        else {
                    261:                                out = stdout;
1.3       jfb       262:                                putc('E', out);
1.11      jfb       263:                        }
1.3       jfb       264:                        putc(' ', out);
                    265:                }
1.26      niallo    266: #endif
1.1       jfb       267:
1.8       jfb       268:                fputs(prefix, out);
                    269:                if (level != LP_TRACE)
                    270:                        fputs(": ", out);
                    271:                fputs(buf, out);
                    272:                fputc('\n', out);
1.1       jfb       273:        }
                    274:
                    275:        if (cvs_log_dest & LD_SYSLOG)
                    276:                syslog_r(cvs_slpriomap[level], &cvs_sl, "%s", buf);
                    277:
                    278:        /* preserve it just in case we changed it? */
                    279:        if (level == LP_ERRNO)
                    280:                errno = ecp;
1.2       jfb       281: }
                    282:
                    283:
                    284: /*
                    285:  * cvs_printf()
                    286:  *
1.14      jfb       287:  * Wrapper function around printf() that prepends a 'M' command when
1.2       jfb       288:  * the program is acting as server.
                    289:  */
                    290: int
                    291: cvs_printf(const char *fmt, ...)
                    292: {
                    293:        int ret;
1.26      niallo    294: #if !defined(RCSPROG)
1.14      jfb       295:        char *nstr, *dp, *sp;
1.26      niallo    296: #endif
1.2       jfb       297:        va_list vap;
                    298:
                    299:        va_start(vap, fmt);
1.14      jfb       300:
1.26      niallo    301: #if !defined(RCSPROG)
1.14      jfb       302:        if (cvs_cmdop == CVS_OP_SERVER) {
                    303:                ret = vasprintf(&nstr, fmt, vap);
1.32      ray       304:                if (ret == -1)
                    305:                        fatal("cvs_printf: %s", strerror(errno));
                    306:                for (dp = nstr; *dp != '\0';) {
                    307:                        sp = strchr(dp, '\n');
                    308:                        if (sp == NULL)
                    309:                                for (sp = dp; *sp != '\0'; sp++)
                    310:                                        ;
                    311:
                    312:                        if (send_m) {
                    313:                                send_m = 0;
                    314:                                putc('M', stdout);
                    315:                                putc(' ', stdout);
1.14      jfb       316:                        }
1.32      ray       317:
                    318:                        fwrite(dp, sizeof(char), (size_t)(sp - dp), stdout);
                    319:
                    320:                        if (*sp != '\n')
                    321:                                break;
                    322:
                    323:                        putc('\n', stdout);
                    324:                        send_m = 1;
                    325:                        dp = sp + 1;
1.14      jfb       326:                }
1.32      ray       327:                xfree(nstr);
1.14      jfb       328:        } else
1.26      niallo    329: #endif
1.14      jfb       330:                ret = vprintf(fmt, vap);
                    331:
1.2       jfb       332:        va_end(vap);
                    333:        return (ret);
1.19      joris     334: }