-
Notifications
You must be signed in to change notification settings - Fork 127
/
cli.c
198 lines (175 loc) · 9.25 KB
/
cli.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#include "cli.h"
#include "globals.h"
#include "ctr_logging.h"
#include "config.h"
#include "utils.h"
#include <glib.h>
#include <glib-unix.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __linux__
#include <linux/limits.h>
#endif
gboolean opt_version = FALSE;
gboolean opt_terminal = FALSE;
gboolean opt_stdin = FALSE;
gboolean opt_leave_stdin_open = FALSE;
gboolean opt_syslog = FALSE;
gboolean is_cgroup_v2 = FALSE;
char *cgroup2_path = NULL;
char *opt_cid = NULL;
char *opt_cuuid = NULL;
char *opt_name = NULL;
char *opt_runtime_path = NULL;
char *opt_bundle_path = NULL;
char *opt_persist_path = NULL;
char *opt_container_pid_file = NULL;
char *opt_conmon_pid_file = NULL;
gboolean opt_systemd_cgroup = FALSE;
gboolean opt_no_pivot = FALSE;
gboolean opt_attach = FALSE;
char *opt_exec_process_spec = NULL;
gboolean opt_exec = FALSE;
int opt_api_version = 0;
char *opt_restore_path = NULL;
gchar **opt_runtime_opts = NULL;
gchar **opt_runtime_args = NULL;
gchar **opt_log_path = NULL;
char *opt_exit_dir = NULL;
int opt_timeout = 0;
int64_t opt_log_size_max = -1;
int64_t opt_log_global_size_max = -1;
char *opt_socket_path = DEFAULT_SOCKET_PATH;
gboolean opt_no_new_keyring = FALSE;
char *opt_exit_command = NULL;
gchar **opt_exit_args = NULL;
int opt_exit_delay = 0;
gboolean opt_replace_listen_pid = FALSE;
char *opt_log_level = NULL;
char *opt_log_tag = NULL;
gboolean opt_sync = FALSE;
gboolean opt_no_sync_log = FALSE;
char *opt_sdnotify_socket = NULL;
gboolean opt_full_attach_path = FALSE;
char *opt_seccomp_notify_socket = NULL;
char *opt_seccomp_notify_plugins = NULL;
GOptionEntry opt_entries[] = {
{"api-version", 0, 0, G_OPTION_ARG_NONE, &opt_api_version, "Conmon API version to use", NULL},
{"bundle", 'b', 0, G_OPTION_ARG_STRING, &opt_bundle_path, "Location of the OCI Bundle path", NULL},
{"cid", 'c', 0, G_OPTION_ARG_STRING, &opt_cid, "Identification of Container", NULL},
{"conmon-pidfile", 'P', 0, G_OPTION_ARG_STRING, &opt_conmon_pid_file, "PID file for the conmon process", NULL},
{"container-pidfile", 'p', 0, G_OPTION_ARG_STRING, &opt_container_pid_file, "PID file for the initial pid inside of container",
NULL},
{"cuuid", 'u', 0, G_OPTION_ARG_STRING, &opt_cuuid, "Container UUID", NULL},
{"exec", 'e', 0, G_OPTION_ARG_NONE, &opt_exec, "Exec a command into a running container", NULL},
{"exec-attach", 0, 0, G_OPTION_ARG_NONE, &opt_attach, "Attach to an exec session", NULL},
{"exec-process-spec", 0, 0, G_OPTION_ARG_STRING, &opt_exec_process_spec, "Path to the process spec for execution", NULL},
{"exit-command", 0, 0, G_OPTION_ARG_STRING, &opt_exit_command,
"Path to the program to execute when the container terminates its execution", NULL},
{"exit-command-arg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_exit_args,
"Additional arg to pass to the exit command. Can be specified multiple times", NULL},
{"exit-delay", 0, 0, G_OPTION_ARG_INT, &opt_exit_delay, "Delay before invoking the exit command (in seconds)", NULL},
{"exit-dir", 0, 0, G_OPTION_ARG_STRING, &opt_exit_dir, "Path to the directory where exit files are written", NULL},
{"leave-stdin-open", 0, 0, G_OPTION_ARG_NONE, &opt_leave_stdin_open, "Leave stdin open when attached client disconnects", NULL},
{"log-level", 0, 0, G_OPTION_ARG_STRING, &opt_log_level, "Print debug logs based on log level", NULL},
{"log-path", 'l', 0, G_OPTION_ARG_STRING_ARRAY, &opt_log_path, "Log file path", NULL},
{"log-size-max", 0, 0, G_OPTION_ARG_INT64, &opt_log_size_max, "Maximum size of log file", NULL},
{"log-global-size-max", 0, 0, G_OPTION_ARG_INT64, &opt_log_global_size_max, "Maximum size of all log files", NULL},
{"log-tag", 0, 0, G_OPTION_ARG_STRING, &opt_log_tag, "Additional tag to use for logging", NULL},
{"name", 'n', 0, G_OPTION_ARG_STRING, &opt_name, "Container name", NULL},
{"no-new-keyring", 0, 0, G_OPTION_ARG_NONE, &opt_no_new_keyring, "Do not create a new session keyring for the container", NULL},
{"no-pivot", 0, 0, G_OPTION_ARG_NONE, &opt_no_pivot, "Do not use pivot_root", NULL},
{"no-sync-log", 0, 0, G_OPTION_ARG_NONE, &opt_no_sync_log, "Do not manually call sync on logs after container shutdown", NULL},
{"persist-dir", '0', 0, G_OPTION_ARG_STRING, &opt_persist_path,
"Persistent directory for a container that can be used for storing container data", NULL},
{"pidfile", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_container_pid_file, "PID file (DEPRECATED)", NULL},
{"replace-listen-pid", 0, 0, G_OPTION_ARG_NONE, &opt_replace_listen_pid, "Replace listen pid if set for oci-runtime pid", NULL},
{"restore", 0, 0, G_OPTION_ARG_STRING, &opt_restore_path, "Restore a container from a checkpoint", NULL},
{"restore-arg", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, &opt_runtime_opts,
"Additional arg to pass to the restore command. Can be specified multiple times. (DEPRECATED)", NULL},
{"runtime", 'r', 0, G_OPTION_ARG_STRING, &opt_runtime_path, "Path to store runtime data for the container", NULL},
{"runtime-arg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_runtime_args,
"Additional arg to pass to the runtime. Can be specified multiple times", NULL},
{"runtime-opt", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_runtime_opts,
"Additional opts to pass to the restore or exec command. Can be specified multiple times", NULL},
{"sdnotify-socket", 0, 0, G_OPTION_ARG_STRING, &opt_sdnotify_socket, "Path to the host's sd-notify socket to relay messages to",
NULL},
{"socket-dir-path", 0, 0, G_OPTION_ARG_STRING, &opt_socket_path, "Location of container attach sockets", NULL},
{"stdin", 'i', 0, G_OPTION_ARG_NONE, &opt_stdin, "Open up a pipe to pass stdin to the container", NULL},
{"sync", 0, 0, G_OPTION_ARG_NONE, &opt_sync, "Keep the main conmon process as its child by only forking once", NULL},
{"syslog", 0, 0, G_OPTION_ARG_NONE, &opt_syslog, "Log to syslog (use with cgroupfs cgroup manager)", NULL},
{"systemd-cgroup", 's', 0, G_OPTION_ARG_NONE, &opt_systemd_cgroup,
"Enable systemd cgroup manager, rather then use the cgroupfs directly", NULL},
{"terminal", 't', 0, G_OPTION_ARG_NONE, &opt_terminal, "Allocate a pseudo-TTY. The default is false", NULL},
{"timeout", 'T', 0, G_OPTION_ARG_INT, &opt_timeout, "Kill container after specified timeout in seconds.", NULL},
{"version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print the version and exit", NULL},
{"full-attach", 0, 0, G_OPTION_ARG_NONE, &opt_full_attach_path,
"Don't truncate the path to the attach socket. This option causes conmon to ignore --socket-dir-path", NULL},
{"seccomp-notify-socket", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_socket,
"Path to the socket where the seccomp notification fd is received", NULL},
{"seccomp-notify-plugins", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_plugins,
"Plugins to use for managing the seccomp notifications", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL}};
int initialize_cli(int argc, char *argv[])
{
GOptionContext *context = g_option_context_new("- conmon utility");
g_option_context_add_main_entries(context, opt_entries, "conmon");
GError *error = NULL;
if (!g_option_context_parse(context, &argc, &argv, &error)) {
g_printerr("conmon: option parsing failed: %s\n", error->message);
exit(EXIT_FAILURE);
}
g_option_context_free(context);
context = NULL;
if (opt_version) {
g_print("conmon version " VERSION "\ncommit: " GIT_COMMIT "\n");
exit(EXIT_SUCCESS);
}
if (opt_cid == NULL) {
fprintf(stderr, "conmon: Container ID not provided. Use --cid\n");
exit(EXIT_FAILURE);
}
return -1;
}
void process_cli()
{
/* Command line parameters */
set_conmon_logs(opt_log_level, opt_cid, opt_syslog, opt_log_tag);
main_loop = g_main_loop_new(NULL, FALSE);
if (opt_restore_path && opt_exec)
nexit("Cannot use 'exec' and 'restore' at the same time");
if (!opt_exec && opt_attach)
nexit("Attach can only be specified with exec");
if (opt_api_version < 1 && opt_attach)
nexit("Attach can only be specified for a non-legacy exec session");
/* The old exec API did not require opt_cuuid */
if (opt_cuuid == NULL && (!opt_exec || opt_api_version >= 1))
nexit("Container UUID not provided. Use --cuuid");
if (opt_seccomp_notify_plugins == NULL)
opt_seccomp_notify_plugins = getenv("CONMON_SECCOMP_NOTIFY_PLUGINS");
if (opt_runtime_path == NULL)
nexit("Runtime path not provided. Use --runtime");
if (access(opt_runtime_path, X_OK) < 0)
pexitf("Runtime path %s is not valid", opt_runtime_path);
if (opt_exec && opt_exec_process_spec == NULL) {
nexit("Exec process spec path not provided. Use --exec-process-spec");
}
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) == NULL) {
nexit("Failed to get working directory");
}
// opt_bundle_path in exec means we will set up the attach socket
// for the exec session. the legacy version of exec does not need this
// and thus we only override an empty opt_bundle_path when we're not exec
if (opt_bundle_path == NULL && !opt_exec) {
opt_bundle_path = cwd;
}
if (opt_exit_delay < 0) {
nexit("Delay before invoking exit command must be greater than or equal to 0");
}
// we should always override the container pid file if it's empty
// TODO FIXME I removed default_pid_file here. shouldn't opt_container_pid_file be cleaned up?
if (opt_container_pid_file == NULL)
opt_container_pid_file = g_strdup_printf("%s/pidfile-%s", cwd, opt_cid);
configure_log_drivers(opt_log_path, opt_log_size_max, opt_log_global_size_max, opt_cid, opt_name, opt_log_tag);
}