diff --git a/src/log_proxy.c b/src/log_proxy.c index 09bfe67..74fbbed 100644 --- a/src/log_proxy.c +++ b/src/log_proxy.c @@ -109,7 +109,7 @@ static void every_second(int sig) { // another program rotated our log file // => let's reinit the output channel destroy_output_channel(); - init_output_channel(log_file, use_locks, TRUE); + init_output_channel(log_file, use_locks, TRUE, chmod_str, chown_str, chgrp_str); unlock_control_file(fd); if (sig > 0) { // if sig<0, this is the final call before program end @@ -144,7 +144,7 @@ static void every_second(int sig) { } if (rotate_res == TRUE) { destroy_output_channel(); - init_output_channel(log_file, use_locks, TRUE); + init_output_channel(log_file, use_locks, TRUE, chmod_str, chown_str, chgrp_str); } } unlock_control_file(fd); @@ -170,7 +170,7 @@ void init_or_reinit_output_channel(const gchar *lg_file, gboolean us_locks) { exit(2); } destroy_output_channel(); - init_output_channel(lg_file, us_locks, FALSE); + init_output_channel(lg_file, us_locks, FALSE, chmod_str, chown_str, chgrp_str); unlock_control_file(lock_fd); } diff --git a/src/options.h b/src/options.h index 8448583..f28748f 100644 --- a/src/options.h +++ b/src/options.h @@ -11,6 +11,9 @@ static glong rotation_size = -1; static glong rotation_time = -1; static gchar *rotation_suffix = NULL; static gchar *log_directory = NULL; +static gchar *chmod_str = NULL; +static gchar *chown_str = NULL; +static gchar *chgrp_str = NULL; static gint rotated_files = -1; static gboolean rm_fifo_at_exit = FALSE; static gchar *fifo = NULL; @@ -86,7 +89,10 @@ static GOptionEntry entries[] = { { "rotated-files", 'n', 0, G_OPTION_ARG_INT, &rotated_files, "maximum number of rotated files to keep including main one (0 => no cleaning, default: content of environment variable LOGPROXY_ROTATED_FILES or 5)", NULL }, { "use-locks", 'm', 0, G_OPTION_ARG_NONE, &use_locks, "use locks to append to main log file (useful if several process writes to the same file)", NULL }, { "fifo", 'f', 0, G_OPTION_ARG_STRING, &fifo, "if set, read lines on this fifo instead of stdin", NULL }, - { "rm-fifo-at-exit", 'r', 0, G_OPTION_ARG_NONE, &rm_fifo_at_exit, "if set, drop fifo at then end of the program (you have to use --fifo option of course)", NULL } + { "rm-fifo-at-exit", 'r', 0, G_OPTION_ARG_NONE, &rm_fifo_at_exit, "if set, drop fifo at then end of the program (you have to use --fifo option of course)", NULL }, + { "chmod", 'c', 0, G_OPTION_ARG_STRING, &chmod_str, "if set, chmod the logfile to this octal value (0700 for example)", NULL }, + { "chown", 'o', 0, G_OPTION_ARG_STRING, &chown_str, "if set, try (if you don't have sufficient privileges, it will fail silently) to change the owner of the logfile to the given user value", NULL }, + { "chgrp", 'g', 0, G_OPTION_ARG_STRING, &chgrp_str, "if set, try (if you don't have sufficient privileges, it will fail silently) to change the group of the logfile to the given group value", NULL } }; #endif /* OPTIONS_H_ */ diff --git a/src/out.c b/src/out.c index 592e4e9..cf70b0f 100644 --- a/src/out.c +++ b/src/out.c @@ -30,7 +30,7 @@ void destroy_output_channel() { g_free(_log_file); } -void init_output_channel(const gchar *log_file, gboolean use_locks, gboolean force_control_file) { +void init_output_channel(const gchar *log_file, gboolean use_locks, gboolean force_control_file, const gchar *chmod_str, const gchar *chown_str, const gchar *chgrp_str) { _log_file = g_strdup(log_file); _use_locks = use_locks; create_empty(_log_file); @@ -52,6 +52,21 @@ void init_output_channel(const gchar *log_file, gboolean use_locks, gboolean for GError *error = NULL; while (TRUE) { _out_channel = g_io_channel_new_file(_log_file, "a", &error); + if (chmod_str != NULL) { + mode_t chmod_mode_t = strtol(chmod_str, NULL, 8); + chmod(_log_file, chmod_mode_t); + } + uid_t uid = -1; + gid_t gid = -1; + if (chown_str != NULL) { + uid = user_id_from_name(chown_str); + } + if (chgrp_str != NULL) { + gid = group_id_from_name(chgrp_str); + } + if ((uid > 0) || (gid > 0)) { + chown(_log_file, uid, gid); + } if (error != NULL) { g_warning("error during open output channel: %s => waiting 1s and try again...", error->message); g_error_free(error); diff --git a/src/out.h b/src/out.h index 93e7b3e..0a803e8 100644 --- a/src/out.h +++ b/src/out.h @@ -3,7 +3,7 @@ #include -void init_output_channel(const gchar *log_file, gboolean use_locks, gboolean force_control_file); +void init_output_channel(const gchar *log_file, gboolean use_locks, gboolean force_control_file, const gchar *chmod_str, const gchar *chown_str, const gchar *chgrp_str); void destroy_output_channel(); gboolean write_output_channel(GString *buffer); glong get_output_channel_age(); diff --git a/src/util.c b/src/util.c index 323c55e..0189441 100644 --- a/src/util.c +++ b/src/util.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include "util.h" static GRand *__rand = NULL; @@ -173,3 +176,41 @@ gboolean create_empty(const gchar *file_path) { } return TRUE; } + +uid_t user_id_from_name(const gchar *name) { + struct passwd *pwd; + uid_t u; + char *endptr; + if (name == NULL || *name == '\0') { + return -1; + } + u = strtol(name, &endptr, 10); + if (*endptr == '\0') { + // allow a numeric string + return u; + } + pwd = getpwnam(name); + if (pwd == NULL) { + return -1; + } + return pwd->pw_uid; +} + +gid_t group_id_from_name(const gchar *name) { + struct group *grp; + gid_t g; + char *endptr; + if (name == NULL || *name == '\0') { + return -1; + } + g = strtol(name, &endptr, 10); + if (*endptr == '\0') { + // allow a numeric string + return g; + } + grp = getgrnam(name); + if (grp == NULL) { + return -1; + } + return grp->gr_gid; +} diff --git a/src/util.h b/src/util.h index ded1c68..0310eb4 100644 --- a/src/util.h +++ b/src/util.h @@ -2,6 +2,7 @@ #define UTIL_H_ #include +#include glong get_file_size(const gchar *file_path); glong get_current_timestamp(); @@ -11,5 +12,7 @@ glong get_file_inode(const gchar *file_path); glong get_fd_inode(int fd); gboolean create_empty(const gchar *file_path); gchar *compute_file_path(const gchar *directory, const gchar *file_name); +uid_t user_id_from_name(const gchar *name); +gid_t group_id_from_name(const gchar *name); #endif /* UTIL_H_ */