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 }