From 9dddd0075ef84fd75afd8eef05e2ccbafb6a88e0 Mon Sep 17 00:00:00 2001 From: Devaev Maxim Date: Thu, 6 Dec 2018 21:55:28 +0300 Subject: [PATCH] unix socket perms; strtol() error handling --- src/http.c | 7 ++++++- src/http.h | 3 +++ src/main.c | 38 ++++++++++++++++++++++++-------------- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/http.c b/src/http.c index 0cb102b..71481a5 100644 --- a/src/http.c +++ b/src/http.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -153,7 +154,7 @@ int http_server_listen(struct http_server_t *server) { unix_addr.sun_path[107] = '\0'; unix_addr.sun_family = AF_UNIX; - if (server->unix_path && server->unix_rm && unlink(server->unix_path) < 0) { + if (server->unix_rm && unlink(server->unix_path) < 0) { if (errno != ENOENT) { LOG_PERROR("Can't remove old UNIX socket '%s'", server->unix_path); return -1; @@ -163,6 +164,10 @@ int http_server_listen(struct http_server_t *server) { LOG_PERROR("Can't bind HTTP to UNIX socket '%s'", server->unix_path); return -1; } + if (server->unix_mode && chmod(server->unix_path, server->unix_mode) < 0) { + LOG_PERROR("Can't set permissions %o to UNIX socket '%s'", server->unix_mode, server->unix_path); + return -1; + } if (listen(server->run->unix_fd, 128) < 0) { LOG_PERROR("Can't listen UNIX socket '%s'", server->unix_path); return -1; diff --git a/src/http.h b/src/http.h index 50d8d19..8b23f3e 100644 --- a/src/http.h +++ b/src/http.h @@ -21,6 +21,8 @@ #include +#include + #include #include #include @@ -80,6 +82,7 @@ struct http_server_t { unsigned port; char *unix_path; bool unix_rm; + mode_t unix_mode; unsigned drop_same_frames; unsigned fake_width; unsigned fake_height; diff --git a/src/main.c b/src/main.c index b67f0b7..4351a6b 100644 --- a/src/main.c +++ b/src/main.c @@ -40,7 +40,7 @@ #include "http.h" -static const char _short_opts[] = "d:i:x:y:f:a:z:tn:w:q:c:s:p:u:er:h"; +static const char _short_opts[] = "d:i:x:y:f:a:z:tn:w:q:c:s:p:u:ro:e:h"; static const struct option _long_opts[] = { {"device", required_argument, NULL, 'd'}, {"input", required_argument, NULL, 'i'}, @@ -62,8 +62,9 @@ static const struct option _long_opts[] = { {"host", required_argument, NULL, 's'}, {"port", required_argument, NULL, 'p'}, {"unix", required_argument, NULL, 'u'}, - {"unix-rm", no_argument, NULL, 'e'}, - {"drop-same-frames", required_argument, NULL, 'r'}, + {"unix-rm", no_argument, NULL, 'r'}, + {"unix-mode", required_argument, NULL, 'o'}, + {"drop-same-frames", required_argument, NULL, 'e'}, {"fake-width", required_argument, NULL, 2001}, {"fake-height", required_argument, NULL, 2002}, {"server-timeout", required_argument, NULL, 2003}, @@ -114,7 +115,7 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s printf(" Default: %d (number of CPU cores + 1)\n\n", dev->n_buffers); printf(" -w|--workers -- The number of compressing threads. Default: %d (== --buffers).\n\n", dev->n_workers); printf(" -q|--quality -- Set quality of JPEG encoding from 1 to 100 (best). Default: %d.\n\n", encoder->quality); - printf(" --encoder -- Use specified encoder. It may affects to workers number.\n"); + printf(" -c|--encoder -- Use specified encoder. It may affects to workers number.\n"); printf(" -- Available: %s; default: CPU.\n\n", ENCODER_TYPES_STR); printf(" --device-timeout -- Timeout for device querying. Default: %d\n\n", dev->timeout); printf(" --device-persistent -- Don't re-initialize device on timeout. Default: disabled.\n\n"); @@ -122,11 +123,12 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s printf(" after a timeout. Default: %d\n\n", dev->error_delay); printf("HTTP server options:\n"); printf("--------------------\n"); - printf(" --host
-- Listen on Hostname or IP. Default: %s\n\n", server->host); - printf(" --port -- Bind to this TCP port. Default: %d\n\n", server->port); - printf(" --unix -- Bind to UNIX domain socket. Default: disabled\n\n"); - printf(" --unix-rm -- Try to remove old UNIX socket file before binding. Default: disabled\n\n"); - printf(" --drop-same-frames -- Don't send same frames to clients, but no more than specified number.\n"); + printf(" -s|--host
-- Listen on Hostname or IP. Default: %s\n\n", server->host); + printf(" -p|--port -- Bind to this TCP port. Default: %d\n\n", server->port); + printf(" -u|--unix -- Bind to UNIX domain socket. Default: disabled\n\n"); + printf(" -r|--unix-rm -- Try to remove old UNIX socket file before binding. Default: disabled\n\n"); + printf(" -o|--unix-mode -- Set UNIX socket file permissions (like 777). Default: disabled\n\n"); + printf(" -e|--drop-same-frames -- Don't send same frames to clients, but no more than specified number.\n"); printf(" It can significantly reduce the outgoing traffic, but will increase\n"); printf(" the CPU loading. Don't use this option with analog signal sources\n"); printf(" or webcams, it's useless. Default: disabled.\n\n"); @@ -150,9 +152,9 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e { _dest = _value; break; } # define OPT_UNSIGNED(_dest, _name, _min, _max) \ - { errno = 0; int _tmp = strtol(optarg, NULL, 0); \ - if (errno || _tmp < _min || _tmp > _max) \ - { printf("Invalid value for '%s=%u'; min=%u; max=%u\n", _name, _tmp, _min, _max); return -1; } \ + { errno = 0; char *_end = NULL; int _tmp = strtol(optarg, &_end, 0); \ + if (errno || *_end || _tmp < _min || _tmp > _max) \ + { printf("Invalid value for '%s=%s'; min=%u; max=%u\n", _name, optarg, _min, _max); return -1; } \ _dest = _tmp; break; } # define OPT_PARSE(_dest, _func, _invalid, _name) \ @@ -160,6 +162,12 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e { printf("Unknown " _name ": %s\n", optarg); return -1; } \ break; } +# define OPT_CHMOD(_dest, _name) \ + { errno = 0; char *_end = NULL; int _tmp = strtol(optarg, &_end, 8); \ + if (errno || *_end) \ + { printf("Invalid value for '%s=%s'\n", _name, optarg); return -1; } \ + _dest = _tmp; break; } + int index; int ch; @@ -189,8 +197,9 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e case 's': OPT_SET(server->host, optarg); case 'p': OPT_UNSIGNED(server->port, "--port", 1, 65535); case 'u': OPT_SET(server->unix_path, optarg); - case 'e': OPT_SET(server->unix_rm, true); - case 'r': OPT_UNSIGNED(server->drop_same_frames, "--drop-same-frames", 0, 30); + case 'r': OPT_SET(server->unix_rm, true); + case 'o': OPT_CHMOD(server->unix_mode, "--unix-mode"); + case 'e': OPT_UNSIGNED(server->drop_same_frames, "--drop-same-frames", 0, 30); case 2001: OPT_UNSIGNED(server->fake_width, "--fake-width", 0, 1920); case 2002: OPT_UNSIGNED(server->fake_height, "--fake-height", 0, 1200); case 2003: OPT_UNSIGNED(server->timeout, "--server-timeout", 1, 60); @@ -206,6 +215,7 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e } } +# undef OPT_CHMOD # undef OPT_PARSE # undef OPT_UNSIGNED # undef OPT_SET