github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/nsenter/log.c (about)

     1  #define _GNU_SOURCE
     2  #include <stdarg.h>
     3  #include <stdio.h>
     4  #include <stdlib.h>
     5  #include <string.h>
     6  #include <unistd.h>
     7  
     8  #include "log.h"
     9  #include "getenv.h"
    10  
    11  static const char *level_str[] = { "panic", "fatal", "error", "warning", "info", "debug", "trace" };
    12  
    13  int logfd = -1;
    14  static int loglevel = DEBUG;
    15  
    16  extern char *escape_json_string(char *str);
    17  void setup_logpipe(void)
    18  {
    19  	int i;
    20  
    21  	i = getenv_int("_LIBCONTAINER_LOGPIPE");
    22  	if (i < 0) {
    23  		/* We are not runc init, or log pipe was not provided. */
    24  		return;
    25  	}
    26  	logfd = i;
    27  
    28  	i = getenv_int("_LIBCONTAINER_LOGLEVEL");
    29  	if (i < 0)
    30  		return;
    31  	loglevel = i;
    32  }
    33  
    34  /* Defined in nsexec.c */
    35  extern int current_stage;
    36  
    37  void write_log(int level, const char *format, ...)
    38  {
    39  	char *message = NULL, *stage = NULL, *json = NULL;
    40  	va_list args;
    41  	int ret;
    42  
    43  	if (logfd < 0 || level > loglevel)
    44  		goto out;
    45  
    46  	va_start(args, format);
    47  	ret = vasprintf(&message, format, args);
    48  	va_end(args);
    49  	if (ret < 0) {
    50  		message = NULL;
    51  		goto out;
    52  	}
    53  
    54  	message = escape_json_string(message);
    55  
    56  	if (current_stage < 0) {
    57  		stage = strdup("nsexec");
    58  		if (stage == NULL)
    59  			goto out;
    60  	} else {
    61  		ret = asprintf(&stage, "nsexec-%d", current_stage);
    62  		if (ret < 0) {
    63  			stage = NULL;
    64  			goto out;
    65  		}
    66  	}
    67  	ret = asprintf(&json, "{\"level\":\"%s\", \"msg\": \"%s[%d]: %s\"}\n",
    68  		       level_str[level], stage, getpid(), message);
    69  	if (ret < 0) {
    70  		json = NULL;
    71  		goto out;
    72  	}
    73  
    74  	/* This logging is on a best-effort basis. In case of a short or failed
    75  	 * write there is nothing we can do, so just ignore write() errors.
    76  	 */
    77  	ssize_t __attribute__((unused)) __res = write(logfd, json, ret);
    78  
    79  out:
    80  	free(message);
    81  	free(stage);
    82  	free(json);
    83  }