aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPierre Pfister <ppfister@cisco.com>2017-07-27 22:57:34 -0400
committerPierre Pfister <ppfister@cisco.com>2017-09-05 18:10:40 +0200
commit9a244bb5e4a21835cac51ba7f35095b9c24547e6 (patch)
treead8874c4ee37e1cebc85592982547ad4dd5858fc
parent215961829c4ae5f738ffcd01a8d1afcab13bd0e2 (diff)
Add pidfile cmdline option
Change-Id: Ibaa61b624eb6683b1be6901a7b29f5f73aad27b2 Signed-off-by: Pierre Pfister <ppfister@cisco.com>
-rw-r--r--src/vlib/unix/main.c51
-rw-r--r--src/vlib/unix/unix.h7
-rw-r--r--src/vlib/unix/util.c49
3 files changed, 98 insertions, 9 deletions
diff --git a/src/vlib/unix/main.c b/src/vlib/unix/main.c
index f52316e553b..c90e1331374 100644
--- a/src/vlib/unix/main.c
+++ b/src/vlib/unix/main.c
@@ -317,6 +317,7 @@ unix_config (vlib_main_t * vm, unformat_input_t * input)
unix_main_t *um = &unix_main;
clib_error_t *error = 0;
gid_t gid;
+ int pidfd = -1;
/* Defaults */
um->cli_pager_buffer_limit = UNIX_CLI_DEFAULT_PAGER_LIMIT;
@@ -415,11 +416,38 @@ unix_config (vlib_main_t * vm, unformat_input_t * input)
if (setegid (gid) == -1)
return clib_error_return_unix (0, "setegid");
}
+ else if (unformat (input, "pidfile %s", &um->pidfile))
+ ;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
}
+ if (um->runtime_dir == 0)
+ {
+ uid_t uid = geteuid ();
+ if (uid == 00)
+ um->runtime_dir = format (0, "/run/%s%c",
+ vlib_default_runtime_dir, 0);
+ else
+ um->runtime_dir = format (0, "/run/user/%u/%s%c", uid,
+ vlib_default_runtime_dir, 0);
+ }
+
+ if (um->pidfile)
+ {
+ if ((error = vlib_unix_validate_runtime_file (um,
+ (char *) um->pidfile,
+ &um->pidfile)))
+ return error;
+
+ if (((pidfd = open ((char *) um->pidfile,
+ O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0))
+ {
+ return clib_error_return_unix (0, "open");
+ }
+ }
+
error = setup_signal_handlers (um);
if (error)
return error;
@@ -434,19 +462,21 @@ unix_config (vlib_main_t * vm, unformat_input_t * input)
0) < 0)
clib_error_return (0, "daemon () fails");
}
- um->unix_config_complete = 1;
- if (um->runtime_dir == 0)
+ if (pidfd >= 0)
{
- uid_t uid = geteuid ();
- if (uid == 00)
- um->runtime_dir = format (0, "/run/%s%c",
- vlib_default_runtime_dir, 0);
- else
- um->runtime_dir = format (0, "/run/user/%u/%s%c", uid,
- vlib_default_runtime_dir, 0);
+ u8 *lv = format (0, "%d", getpid ());
+ if (write (pidfd, (char *) lv, vec_len (lv)) != vec_len (lv))
+ {
+ vec_free (lv);
+ close (pidfd);
+ return clib_error_return_unix (0, "write");
+ }
+ vec_free (lv);
+ close (pidfd);
}
+ um->unix_config_complete = 1;
return 0;
}
@@ -475,6 +505,9 @@ unix_config (vlib_main_t * vm, unformat_input_t * input)
* Very useful in situations where folks don't remember or can't be bothered
* to include CLI commands in bug reports.
*
+ * @cfgcmd{pidfile, &lt;filename&gt;}
+ * Writes the pid of the main thread in @c filename.
+ *
* @cfgcmd{full-coredump}
* Ask the Linux kernel to dump all memory-mapped address regions, instead
* of just text+data+bss.
diff --git a/src/vlib/unix/unix.h b/src/vlib/unix/unix.h
index ee1312e3498..97f589447b8 100644
--- a/src/vlib/unix/unix.h
+++ b/src/vlib/unix/unix.h
@@ -106,6 +106,9 @@ typedef struct
/* runtime directory path */
u8 *runtime_dir;
+ /* pidfile filename */
+ u8 *pidfile;
+
/* unix config complete */
volatile int unix_config_complete;
@@ -241,6 +244,10 @@ clib_error_t *foreach_directory_file (char *dir_name,
clib_error_t *vlib_unix_recursive_mkdir (char *path);
+clib_error_t *vlib_unix_validate_runtime_file (unix_main_t * um,
+ const char *path,
+ u8 ** full_path);
+
#endif /* included_unix_unix_h */
/*
diff --git a/src/vlib/unix/util.c b/src/vlib/unix/util.c
index 93aeb99c5d9..312cc9b5a0a 100644
--- a/src/vlib/unix/util.c
+++ b/src/vlib/unix/util.c
@@ -257,6 +257,55 @@ done:
return error;
}
+clib_error_t *
+vlib_unix_validate_runtime_file (unix_main_t * um,
+ const char *path, u8 ** full_path)
+{
+ u8 *fp = 0;
+ char *last_slash = 0;
+
+ if (path[0] == '\0')
+ {
+ return clib_error_return (0, "path is an empty string");
+ }
+ else if (strncmp (path, "../", 3) == 0 || strstr (path, "/../"))
+ {
+ return clib_error_return (0, "'..' not allowed in runtime path");
+ }
+ else if (path[0] == '/')
+ {
+ /* Absolute path. Has to start with runtime directory */
+ if (strncmp ((char *) um->runtime_dir, path,
+ strlen ((char *) um->runtime_dir)))
+ {
+ return clib_error_return (0,
+ "file %s is not in runtime directory %s",
+ path, um->runtime_dir);
+ }
+ fp = format (0, "%s%c", path, '\0');
+ }
+ else
+ {
+ /* Relative path, just append to runtime */
+ fp = format (0, "%s/%s%c", um->runtime_dir, path, '\0');
+ }
+
+ /* We don't want to create a directory out of the last file */
+ if ((last_slash = strrchr ((char *) fp, '/')) != NULL)
+ *last_slash = '\0';
+
+ clib_error_t *error = vlib_unix_recursive_mkdir ((char *) fp);
+
+ if (last_slash != NULL)
+ *last_slash = '/';
+
+ if (error)
+ vec_free (fp);
+
+ *full_path = fp;
+ return error;
+}
+
/*
* fd.io coding-style-patch-verification: ON
*