diff --git a/Makefile b/Makefile index ac22896..ef960d9 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,15 @@ override CFLAGS += -DWITH_PTHREAD_NP endif +WITH_SETPROCTITLE ?= 1 +ifneq ($(call optbool,$(WITH_SETPROCTITLE)),) +ifeq ($(shell uname -s | tr A-Z a-z),linux) +_LIBS += -lbsd +endif +override CFLAGS += -DWITH_SETPROCTITLE +endif + + # ===== all: $(PROG) diff --git a/README.md b/README.md index 645da9b..b1aa4bf 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ If you're going to live-stream from your backyard webcam and need to control it, ----- # Building -You'll need ```make```, ```gcc```, ```libevent``` with ```pthreads``` support, ```libjpeg8```/```libjpeg-turbo``` and ```libuuid```. +You'll need ```make```, ```gcc```, ```libevent``` with ```pthreads``` support, ```libjpeg8```/```libjpeg-turbo```, ```libuuid``` and ```libbsd``` (only for Linux). On Raspberry Pi you can build the program with OpenMAX IL. To do this pass option ```WITH_OMX=1``` to ```make```. To enable GPIO support install [wiringPi](http://wiringpi.com) and pass option ```WITH_GPIO=1```. If the compiler reports about a missing function ```pthread_get_name_np()``` (or similar), add option ```WITH_PTHREAD_NP=0``` (it's enabled by default). diff --git a/README.ru.md b/README.ru.md index d55ab6d..207d432 100644 --- a/README.ru.md +++ b/README.ru.md @@ -30,7 +30,7 @@ ----- # Сборка -Для сборки вам понадобятся ```make```, ```gcc```, ```libevent``` с поддержкой ```pthreads```, ```libjpeg8```/```libjpeg-turbo``` и ```libuuid```. +Для сборки вам понадобятся ```make```, ```gcc```, ```libevent``` с поддержкой ```pthreads```, ```libjpeg8```/```libjpeg-turbo```, ```libuuid``` и ```libbsd``` (только для Linux). На Raspberry Pi программу можно собрать с поддержкой OpenMAX IL. Для этого передайте ```make``` параметр ```WITH_OMX=1```. Для включения сборки с поддержкой GPIO установите [wiringPi](http://wiringpi.com) и добавьте параметр ```WITH_GPIO=1```. Если при сборке компилятор ругается на отсутствие функции ```pthread_get_name_np()``` или другой подобной, добавьте параметр ```WITH_PTHREAD_NP=0``` (по умолчанию он включен). diff --git a/pkg/arch/PKGBUILD b/pkg/arch/PKGBUILD index 1ea5dac..d50c44c 100644 --- a/pkg/arch/PKGBUILD +++ b/pkg/arch/PKGBUILD @@ -9,7 +9,7 @@ pkgdesc="Lightweight and fast MJPG-HTTP streamer" url="https://github.com/pikvm/ustreamer" license=(GPL) arch=(i686 x86_64 armv6h armv7h) -depends=(libjpeg libevent libutil-linux) +depends=(libjpeg libevent libutil-linux libbsd) # optional: raspberrypi-firmware for OMX encoder # optional: wiringpi for GPIO support makedepends=(gcc make) diff --git a/pkg/gentoo/ustreamer-9999.ebuild b/pkg/gentoo/ustreamer-9999.ebuild index b9ca6e6..8d8ef90 100644 --- a/pkg/gentoo/ustreamer-9999.ebuild +++ b/pkg/gentoo/ustreamer-9999.ebuild @@ -18,6 +18,7 @@ DEPEND=" >=dev-libs/libevent-2.1.8 >=media-libs/libjpeg-turbo-1.5.3 >=sys-apps/util-linux-2.33 + >=dev-libs/libbsd-0.9.1 " RDEPEND="${DEPEND}" BDEPEND="" diff --git a/pkg/openwrt/Makefile b/pkg/openwrt/Makefile index 8b5784e..56958d8 100644 --- a/pkg/openwrt/Makefile +++ b/pkg/openwrt/Makefile @@ -25,7 +25,7 @@ define Package/ustreamer SECTION:=multimedia CATEGORY:=Multimedia TITLE:=uStreamer - DEPENDS:=+libpthread +libjpeg +libv4l +libuuid +libevent2 +libevent2-core +libevent2-extra +libevent2-pthreads + DEPENDS:=+libpthread +libjpeg +libv4l +libuuid +libbsd +libevent2 +libevent2-core +libevent2-extra +libevent2-pthreads URL:=https://github.com/pikvm/ustreamer endef diff --git a/src/options.c b/src/options.c index 7430a9c..b52e16f 100644 --- a/src/options.c +++ b/src/options.c @@ -111,6 +111,9 @@ enum _OPT_VALUES { #ifdef HAS_PDEATHSIG _O_EXIT_ON_PARENT_DEATH, #endif +#ifdef WITH_SETPROCTITLE + _O_PROCESS_NAME_PREFIX, +#endif _O_LOG_LEVEL, _O_PERF, @@ -179,6 +182,9 @@ static const struct option _LONG_OPTS[] = { #ifdef HAS_PDEATHSIG {"exit-on-parent-death", no_argument, NULL, _O_EXIT_ON_PARENT_DEATH}, #endif +#ifdef WITH_SETPROCTITLE + {"process-name-prefix", required_argument, NULL, _O_PROCESS_NAME_PREFIX}, +#endif {"log-level", required_argument, NULL, _O_LOG_LEVEL}, {"perf", no_argument, NULL, _O_PERF}, @@ -261,6 +267,9 @@ int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t int short_index; int opt_index; char short_opts[1024] = {0}; +# ifdef WITH_SETPROCTITLE + char *process_name_prefix = NULL; +# endif for (short_index = 0, opt_index = 0; _LONG_OPTS[opt_index].name != NULL; ++opt_index) { if (isalpha(_LONG_OPTS[opt_index].val)) { @@ -344,6 +353,9 @@ int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t }; break; # endif +# ifdef WITH_SETPROCTITLE + case _O_PROCESS_NAME_PREFIX: OPT_SET(process_name_prefix, optarg); +# endif case _O_LOG_LEVEL: OPT_NUMBER("--log-level", log_level, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, 0); case _O_PERF: OPT_SET(log_level, LOG_LEVEL_PERF); @@ -360,6 +372,12 @@ int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t } } +# ifdef WITH_SETPROCTITLE + if (process_name_prefix != NULL) { + process_set_name_prefix(argc, argv, process_name_prefix); + } +# endif + # undef OPT_CTL_AUTO # undef OPT_CTL # undef OPT_PARSE @@ -446,6 +464,15 @@ static void _version(bool nl) { # endif # ifdef WITH_GPIO printf(" + GPIO"); +# endif +# ifdef WITH_PTHREAD_NP + printf(" + PThreadNP"); +# endif +# ifdef WITH_SETPROCTITLE + printf(" + SetProcTitle"); +# endif +# ifdef HAS_PDEATHSIG + printf(" + PDeathSig"); # endif if (nl) { putchar('\n'); @@ -548,10 +575,16 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s printf(" --gpio-workers-busy-at ── Set 1 on (pin + N) while worker with number N has a job.\n"); printf(" The worker's numbering starts from 0. Default: disabled\n\n"); #endif -#ifdef HAS_PDEATHSIG +#if (defined(HAS_PDEATHSIG) || defined(WITH_SETPROCTITLE)) printf("Process options:\n"); printf("════════════════\n"); - printf(" --exit-on-parent-death ─ Exit the program if the parent process is dead. Default: disabled.\n\n"); +#endif +#ifdef HAS_PDEATHSIG + printf(" --exit-on-parent-death ─────── Exit the program if the parent process is dead. Default: disabled.\n\n"); +#endif +#ifdef WITH_SETPROCTITLE + printf(" --process-name-prefix ── Set process name prefix which will be displayed in the process list\n"); + printf(" like ': ustreamer --blah-blah-blah'. Default: disabled.\n\n"); #endif printf("Logging options:\n"); printf("════════════════\n"); diff --git a/src/process.h b/src/process.h index e8b89fe..05a66cc 100644 --- a/src/process.h +++ b/src/process.h @@ -31,19 +31,46 @@ # endif #endif + #ifdef HAS_PDEATHSIG # include # include - +#endif +#ifdef WITH_SETPROCTITLE +# include +# include +# if defined(__linux__) +# include +# include +# elif (defined(__FreeBSD__) || defined(__DragonFly__)) +# include +# include +# elif (defined(__NetBSD__) || defined(__OpenBSD__)) // setproctitle() placed in stdlib.h +# else +# error setproctitle() not implemented, you can disable it using WITH_SETPROCTITLE=0 +# endif +#endif +#ifdef HAS_PDEATHSIG # if defined(__linux__) # include # elif defined(__FreeBSD__) # include # endif - +#endif +#ifdef WITH_SETPROCTITLE +# include "tools.h" +#endif +#ifdef HAS_PDEATHSIG # include "logging.h" +#endif +#ifdef WITH_SETPROCTITLE +extern char **environ; +#endif + + +#ifdef HAS_PDEATHSIG INLINE int process_track_parent_death(void) { int signum = SIGTERM; # if defined(__linux__) @@ -65,5 +92,39 @@ INLINE int process_track_parent_death(void) { return 0; } +#endif -#endif // HAS_PDEATHSIG +#ifdef WITH_SETPROCTITLE +# pragma GCC diagnostic ignored "-Wunused-parameter" +# pragma GCC diagnostic push +INLINE void process_set_name_prefix(int argc, char *argv[], const char *prefix) { +# pragma GCC diagnostic pop + + char *cmdline = NULL; + size_t allocated = 2048; + size_t used = 0; + size_t arg_len = 0; + + A_REALLOC(cmdline, allocated); + cmdline[0] = '\0'; + + for (int index = 0; index < argc; ++index) { + arg_len = strlen(argv[index]); + if (used + arg_len + 16 >= allocated) { + allocated += arg_len + 2048; + A_REALLOC(cmdline, allocated); + } + + strcat(cmdline, " "); + strcat(cmdline, argv[index]); + used = strlen(cmdline); // Не считаем вручную, так надежнее + } + +# ifdef __linux__ + setproctitle_init(argc, argv, environ); +# endif + setproctitle("-%s:%s", prefix, cmdline); + + free(cmdline); +} +#endif