[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.29

1.29    ! xsa         1: /*     $OpenBSD: log.c,v 1.28 2005/12/10 20:27:45 joris 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:  * Returns 0 on success, or -1 on failure.
                     83:  */
                     84: int
                     85: cvs_log_init(u_int dest, u_int flags)
                     86: {
                     87:        int slopt;
                     88:
                     89:        cvs_log_dest = dest;
                     90:        cvs_log_flags = flags;
                     91:
                     92:        /* by default, filter only LP_DEBUG and LP_INFO levels */
1.9       jfb        93:        CVS_LOG_FLTRRST();
                     94:        CVS_LOG_FLTRSET(LP_DEBUG);
                     95:        CVS_LOG_FLTRSET(LP_INFO);
1.1       jfb        96:
1.8       jfb        97:        /* traces are enabled with the -t command-line option */
1.9       jfb        98:        CVS_LOG_FLTRSET(LP_TRACE);
1.8       jfb        99:
1.1       jfb       100:        if (dest & LD_SYSLOG) {
                    101:                slopt = 0;
                    102:
                    103:                if (dest & LD_CONS)
                    104:                        slopt |= LOG_CONS;
                    105:                if (flags & LF_PID)
                    106:                        slopt |= LOG_PID;
                    107:
                    108:                openlog_r(__progname, slopt, LOG_DAEMON, &cvs_sl);
                    109:        }
                    110:
                    111:        return (0);
                    112: }
                    113:
                    114:
                    115: /*
                    116:  * cvs_log_cleanup()
                    117:  *
                    118:  * Cleanup the logging facility.
                    119:  */
                    120: void
                    121: cvs_log_cleanup(void)
                    122: {
1.7       tedu      123:
1.1       jfb       124:        closelog_r(&cvs_sl);
                    125: }
                    126:
                    127:
                    128: /*
                    129:  * cvs_log_filter()
                    130:  *
                    131:  * Apply or remove filters on the logging facility.  The exact operation is
                    132:  * specified by the <how> and <level> arguments.  The <how> arguments tells
                    133:  * how the filters will be affected, and <level> gives the log levels that
                    134:  * will be affected by the change.
                    135:  * Returns 0 on success, or -1 on failure.
                    136:  */
                    137:
                    138: int
                    139: cvs_log_filter(u_int how, u_int level)
                    140: {
                    141:        u_int i;
                    142:
                    143:        if ((level > LP_MAX) && (level != LP_ALL)) {
                    144:                cvs_log(LP_ERR, "invalid log level for filter");
                    145:                return (-1);
                    146:        }
                    147:
                    148:        switch (how) {
                    149:        case LP_FILTER_SET:
                    150:                if (level == LP_ALL)
1.9       jfb       151:                        for (i = 0; i <= LP_MAX; i++)
                    152:                                CVS_LOG_FLTRSET(i);
1.1       jfb       153:                else
1.9       jfb       154:                        CVS_LOG_FLTRSET(level);
1.1       jfb       155:                break;
                    156:        case LP_FILTER_UNSET:
                    157:                if (level == LP_ALL)
1.9       jfb       158:                        CVS_LOG_FLTRRST();
1.1       jfb       159:                else
1.9       jfb       160:                        CVS_LOG_FLTRCLR(level);
1.1       jfb       161:                break;
                    162:        default:
                    163:                return (-1);
                    164:        }
                    165:
                    166:        return (0);
                    167: }
                    168:
                    169:
                    170: /*
                    171:  * cvs_log()
                    172:  *
                    173:  * Log the format-string message
                    174:  * The <fmt> argument should not have a terminating newline, as this is taken
                    175:  * care of by the logging facility.
                    176:  */
                    177: int
                    178: cvs_log(u_int level, const char *fmt, ...)
                    179: {
                    180:        int ret;
                    181:        va_list vap;
                    182:
                    183:        va_start(vap, fmt);
                    184:        ret = cvs_vlog(level, fmt, vap);
                    185:        va_end(vap);
                    186:
                    187:        return (ret);
                    188: }
                    189:
                    190:
                    191: /*
                    192:  * cvs_vlog()
                    193:  *
                    194:  * The <fmt> argument should not have a terminating newline, as this is taken
                    195:  * care of by the logging facility.
                    196:  */
                    197: int
                    198: cvs_vlog(u_int level, const char *fmt, va_list vap)
                    199: {
                    200:        int ecp;
1.25      xsa       201:        char prefix[64], buf[1024], ebuf[255];
1.1       jfb       202:        FILE *out;
1.26      niallo    203: #if !defined(RCSPROG)
1.27      joris     204:        char *cmdname;
1.20      joris     205:        struct cvs_cmd *cmdp;
1.26      niallo    206: #endif
1.1       jfb       207:
1.13      jfb       208:        if (level > LP_MAX)
1.4       jfb       209:                return (-1);
1.1       jfb       210:
                    211:        /* apply any filters */
1.9       jfb       212:        if (CVS_LOG_FLTRGET(level))
1.1       jfb       213:                return (0);
                    214:
                    215:        if (level == LP_ERRNO)
                    216:                ecp = errno;
1.4       jfb       217:        else
                    218:                ecp = 0;
1.1       jfb       219:
1.17      xsa       220:        /* always use the command name in error messages, not aliases */
1.26      niallo    221: #if !defined(RCSPROG)
1.27      joris     222:        if (cvs_command == NULL)
                    223:                cmdname = " ";
                    224:        else {
                    225:                cmdp = cvs_findcmd(cvs_command);
                    226:                cmdname = cmdp->cmd_name;
                    227:        }
1.17      xsa       228:
1.3       jfb       229:        /* The cvs program appends the command name to the program name */
1.8       jfb       230:        if (level == LP_TRACE) {
                    231:                strlcpy(prefix, " -> ", sizeof(prefix));
                    232:                if (cvs_cmdop == CVS_OP_SERVER)
                    233:                        prefix[0] = 'S';
                    234:        } else if (cvs_command != NULL) {
1.4       jfb       235:                if (level == LP_ABORT)
                    236:                        snprintf(prefix, sizeof(prefix), "%s [%s aborted]",
1.27      joris     237:                            __progname, cmdname);
1.4       jfb       238:                else
                    239:                        snprintf(prefix, sizeof(prefix), "%s %s", __progname,
1.27      joris     240:                            cmdname);
1.6       deraadt   241:        } else /* just use the standard strlcpy */
1.26      niallo    242: #endif
1.3       jfb       243:                strlcpy(prefix, __progname, sizeof(prefix));
                    244:
1.8       jfb       245:        if ((cvs_log_flags & LF_PID) && (level != LP_TRACE)) {
1.1       jfb       246:                snprintf(buf, sizeof(buf), "[%d]", (int)getpid());
                    247:                strlcat(prefix, buf, sizeof(prefix));
                    248:        }
                    249:
                    250:        vsnprintf(buf, sizeof(buf), fmt, vap);
                    251:        if (level == LP_ERRNO) {
                    252:                snprintf(ebuf, sizeof(ebuf), ": %s", strerror(errno));
                    253:                strlcat(buf, ebuf, sizeof(buf));
                    254:        }
                    255:
                    256:        if (cvs_log_dest & LD_STD) {
1.24      xsa       257:                if (level < LP_NOTICE)
1.1       jfb       258:                        out = stdout;
                    259:                else
                    260:                        out = stderr;
1.3       jfb       261:
1.26      niallo    262: #if !defined(RCSPROG)
1.3       jfb       263:                if (cvs_cmdop == CVS_OP_SERVER) {
                    264:                        if (out == stdout)
                    265:                                putc('M', out);
1.11      jfb       266:                        else {
                    267:                                out = stdout;
1.3       jfb       268:                                putc('E', out);
1.11      jfb       269:                        }
1.3       jfb       270:                        putc(' ', out);
                    271:                }
1.26      niallo    272: #endif
1.1       jfb       273:
1.8       jfb       274:                fputs(prefix, out);
                    275:                if (level != LP_TRACE)
                    276:                        fputs(": ", out);
                    277:                fputs(buf, out);
                    278:                fputc('\n', out);
1.1       jfb       279:        }
                    280:
                    281:        if (cvs_log_dest & LD_SYSLOG)
                    282:                syslog_r(cvs_slpriomap[level], &cvs_sl, "%s", buf);
                    283:
                    284:        /* preserve it just in case we changed it? */
                    285:        if (level == LP_ERRNO)
                    286:                errno = ecp;
                    287:
                    288:        return (0);
1.2       jfb       289: }
                    290:
                    291:
                    292: /*
                    293:  * cvs_printf()
                    294:  *
1.14      jfb       295:  * Wrapper function around printf() that prepends a 'M' command when
1.2       jfb       296:  * the program is acting as server.
                    297:  */
                    298: int
                    299: cvs_printf(const char *fmt, ...)
                    300: {
                    301:        int ret;
1.26      niallo    302: #if !defined(RCSPROG)
1.14      jfb       303:        char *nstr, *dp, *sp;
1.26      niallo    304: #endif
1.2       jfb       305:        va_list vap;
                    306:
                    307:        va_start(vap, fmt);
1.14      jfb       308:
1.26      niallo    309: #if !defined(RCSPROG)
1.14      jfb       310:        if (cvs_cmdop == CVS_OP_SERVER) {
                    311:                ret = vasprintf(&nstr, fmt, vap);
                    312:                if (ret != -1) {
                    313:                        for (dp = nstr; *dp != '\0';) {
                    314:                                sp = strchr(dp, '\n');
                    315:                                if (sp == NULL)
                    316:                                        for (sp = dp; *sp != '\0'; sp++)
                    317:                                                ;
                    318:
1.21      joris     319:                                if (send_m) {
1.18      joris     320:                                        send_m = 0;
                    321:                                        putc('M', stdout);
                    322:                                        putc(' ', stdout);
                    323:                                }
                    324:
1.14      jfb       325:                                fwrite(dp, sizeof(char), (size_t)(sp - dp),
                    326:                                    stdout);
                    327:
                    328:                                if (*sp != '\n')
                    329:                                        break;
                    330:
                    331:                                putc('\n', stdout);
1.18      joris     332:                                send_m = 1;
1.14      jfb       333:                                dp = sp + 1;
                    334:                        }
1.28      joris     335:                        xfree(nstr);
1.14      jfb       336:                }
                    337:        } else
1.26      niallo    338: #endif
1.14      jfb       339:                ret = vprintf(fmt, vap);
                    340:
1.2       jfb       341:        va_end(vap);
                    342:        return (ret);
1.1       jfb       343: }
1.19      joris     344: void
                    345: cvs_putchar(int c)
                    346: {
1.26      niallo    347: #if !defined(RCSPROG)
1.19      joris     348:        if (cvs_cmdop == CVS_OP_SERVER && send_m) {
                    349:                send_m = 0;
                    350:                putc('M', stdout);
                    351:                putc(' ', stdout);
                    352:        }
1.26      niallo    353: #endif
1.19      joris     354:
                    355:        putc(c, stdout);
                    356:
1.26      niallo    357: #if !defined(RCSPROG)
1.19      joris     358:        if (cvs_cmdop == CVS_OP_SERVER && c == '\n')
                    359:                send_m = 1;
1.26      niallo    360: #endif
1.19      joris     361: }