import gsm0502_calc_paging_group() from openbsc
[osmocom-bb.git] / src / logging.c
index 2c24f2f..3c9dc03 100644 (file)
@@ -143,29 +143,19 @@ static void _output(struct log_target *target, unsigned int subsys,
                    unsigned int level, char *file, int line, int cont,
                    const char *format, va_list ap)
 {
-       char col[30];
-       char sub[30];
-       char tim[30];
        char buf[4096];
-       char final[4096];
-
-       /* prepare the data */
-       col[0] = '\0';
-       sub[0] = '\0';
-       tim[0] = '\0';
-       buf[0] = '\0';
+       int ret, len = 0, offset = 0, rem = sizeof(buf);
 
        /* are we using color */
        if (target->use_color) {
                const char *c = color(subsys);
                if (c) {
-                       snprintf(col, sizeof(col), "%s", color(subsys));
-                       col[sizeof(col)-1] = '\0';
+                       ret = snprintf(buf + offset, rem, "%s", color(subsys));
+                       if (ret < 0)
+                               goto err;
+                       OSMO_SNPRINTF_RET(ret, rem, offset, len);
                }
        }
-       vsnprintf(buf, sizeof(buf), format, ap);
-       buf[sizeof(buf)-1] = '\0';
-
        if (!cont) {
                if (target->print_timestamp) {
                        char *timestr;
@@ -173,17 +163,30 @@ static void _output(struct log_target *target, unsigned int subsys,
                        tm = time(NULL);
                        timestr = ctime(&tm);
                        timestr[strlen(timestr)-1] = '\0';
-                       snprintf(tim, sizeof(tim), "%s ", timestr);
-                       tim[sizeof(tim)-1] = '\0';
+                       ret = snprintf(buf + offset, rem, "%s ", timestr);
+                       if (ret < 0)
+                               goto err;
+                       OSMO_SNPRINTF_RET(ret, rem, offset, len);
                }
-               snprintf(sub, sizeof(sub), "<%4.4x> %s:%d ", subsys, file, line);
-               sub[sizeof(sub)-1] = '\0';
+               ret = snprintf(buf + offset, rem, "<%4.4x> %s:%d ",
+                               subsys, file, line);
+               if (ret < 0)
+                       goto err;
+               OSMO_SNPRINTF_RET(ret, rem, offset, len);
        }
+       ret = vsnprintf(buf + offset, rem, format, ap);
+       if (ret < 0)
+               goto err;
+       OSMO_SNPRINTF_RET(ret, rem, offset, len);
 
-       snprintf(final, sizeof(final), "%s%s%s%s%s", col, tim, sub, buf,
-                target->use_color ? "\033[0;m" : "");
-       final[sizeof(final)-1] = '\0';
-       target->output(target, level, final);
+       ret = snprintf(buf + offset, rem, "%s",
+                       target->use_color ? "\033[0;m" : "");
+       if (ret < 0)
+               goto err;
+       OSMO_SNPRINTF_RET(ret, rem, offset, len);
+err:
+       buf[sizeof(buf)-1] = '\0';
+       target->output(target, level, buf);
 }
 
 
@@ -195,6 +198,7 @@ static void _logp(unsigned int subsys, int level, char *file, int line,
        llist_for_each_entry(tar, &osmo_log_target_list, entry) {
                struct log_category *category;
                int output = 0;
+               va_list bp;
 
                category = &tar->categories[subsys];
                /* subsystem is not supposed to be logged */
@@ -218,19 +222,15 @@ static void _logp(unsigned int subsys, int level, char *file, int line,
                else if (osmo_log_info->filter_fn)
                        output = osmo_log_info->filter_fn(&log_context,
                                                       tar);
+               if (!output)
+                       continue;
 
-               if (output) {
-                       /* FIXME: copying the va_list is an ugly
-                        * workaround against a bug hidden somewhere in
-                        * _output.  If we do not copy here, the first
-                        * call to _output() will corrupt the va_list
-                        * contents, and any further _output() calls
-                        * with the same va_list will segfault */
-                       va_list bp;
-                       va_copy(bp, ap);
-                       _output(tar, subsys, level, file, line, cont, format, bp);
-                       va_end(bp);
-               }
+               /* According to the manpage, vsnprintf leaves the value of ap
+                * in undefined state. Since _output uses vsnprintf and it may
+                * be called several times, we have to pass a copy of ap. */
+               va_copy(bp, ap);
+               _output(tar, subsys, level, file, line, cont, format, ap);
+               va_end(bp);
        }
 }
 
@@ -448,11 +448,11 @@ const char *log_vty_command_string(const struct log_info *info)
                size += strlen(loglevel_strs[i].str) + 1;
 
        rem = size;
-       str = talloc_zero_size(NULL, size);
+       str = talloc_zero_size(tall_log_ctx, size);
        if (!str)
                return NULL;
 
-       ret = snprintf(str + offset, rem, "logging level (");
+       ret = snprintf(str + offset, rem, "logging level (all|");
        if (ret < 0)
                goto err;
        OSMO_SNPRINTF_RET(ret, rem, offset, len);
@@ -499,6 +499,7 @@ const char *log_vty_command_string(const struct log_info *info)
                goto err;
        OSMO_SNPRINTF_RET(ret, rem, offset, len);
 err:
+       str[size-1] = '\0';
        return str;
 }
 
@@ -517,8 +518,9 @@ const char *log_vty_command_description(const struct log_info *info)
        for (i = 0; i < LOGLEVEL_DEFS; i++)
                size += strlen(loglevel_descriptions[i]) + 1;
 
+       size += strlen("Global setting for all subsystems") + 1;
        rem = size;
-       str = talloc_zero_size(NULL, size);
+       str = talloc_zero_size(tall_log_ctx, size);
        if (!str)
                return NULL;
 
@@ -528,6 +530,12 @@ const char *log_vty_command_description(const struct log_info *info)
                goto err;
        OSMO_SNPRINTF_RET(ret, rem, offset, len);
 
+       ret = snprintf(str + offset, rem,
+                       "Global setting for all subsystems\n");
+       if (ret < 0)
+               goto err;
+       OSMO_SNPRINTF_RET(ret, rem, offset, len);
+
        for (i = 0; i < info->num_cat; i++) {
                ret = snprintf(str + offset, rem, "%s\n",
                                info->cat[i].description);
@@ -543,6 +551,7 @@ const char *log_vty_command_description(const struct log_info *info)
                OSMO_SNPRINTF_RET(ret, rem, offset, len);
        }
 err:
+       str[size-1] = '\0';
        return str;
 }