opnsense-src/sys/contrib/openzfs/lib/libzutil/os/linux/zutil_setproctitle.c
Martin Matuska 15f0b8c309 zfs: merge openzfs/zfs@9cd71c860 (master)
Notable upstream pull request merges:
  #13805 Configure zed's diagnosis engine with vdev properties
  #14110 zfs list: Allow more fields in ZFS_ITER_SIMPLE mode
  #14121 Batch enqueue/dequeue for bqueue
  #14123 arc_read()/arc_access() refactoring and cleanup
  #14159 Bypass metaslab throttle for removal allocations
  #14243 Implement uncached prefetch
  #14251 Cache dbuf_hash() calculation
  #14253 Allow reciever to override encryption property in case of replication
  #14254 Restrict visibility of per-dataset kstats inside FreeBSD jails
  #14255 Zero end of embedded block buffer in dump_write_embedded()
  #14263 Cleanups identified by CodeQL and Coverity
  #14264 Miscellaneous fixes
  #14272 Change ZEVENT_POOL_GUID to ZEVENT_POOL to display pool names
  #14287 FreeBSD: Remove stray debug printf
  #14288 Colorize zfs diff output
  #14289 deadlock between spa_errlog_lock and dp_config_rwlock
  #14291 FreeBSD: Fix potential boot panic with bad label
  #14292 Add tunable to allow changing micro ZAP's max size
  #14293 Turn default_bs and default_ibs into ZFS_MODULE_PARAMs
  #14295 zed: add hotplug support for spare vdevs
  #14304 Activate filesystem features only in syncing context
  #14311 zpool: do guid-based comparison in is_vdev_cb()
  #14317 Pack zrlock_t by 8 bytes
  #14320 Update arc_summary and arcstat outputs
  #14328 FreeBSD: catch up to 1400077
  #14376 Use setproctitle to report progress of zfs send
  #14340 Remove some dead ARC code
  #14358 Wait for txg sync if the last DRR_FREEOBJECTS might result in a hole
  #14360 libzpool: fix ddi_strtoull to update nptr
  #14364 Fix unprotected zfs_znode_dmu_fini
  #14379 zfs_receive_one: Check for the more likely error first
  #14380 Cleanup of dead code suggested by Clang Static Analyzer
  #14397 Avoid passing an uninitialized index to dsl_prop_known_index
  #14404 Fix reading uninitialized variable in receive_read
  #14407 free_blocks(): Fix reports from 2016 PVS Studio FreeBSD report
  #14418 Introduce minimal ZIL block commit delay
  #14422 x86 assembly: fix .size placement and replace .align with .balign

Obtained from:	OpenZFS
OpenZFS commit:	9cd71c8604
2023-01-25 19:50:29 +01:00

299 lines
6 KiB
C

/*
* Copyright © 2013 Guillem Jover <guillem@hadrons.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <unistd.h>
#include <string.h>
#include <sys/param.h>
#include <libzutil.h>
static struct {
/* Original value. */
const char *arg0;
/* Title space available. */
char *base, *end;
/* Pointer to original nul character within base. */
char *nul;
boolean_t warned;
boolean_t reset;
int error;
} SPT;
#define LIBBSD_IS_PATHNAME_SEPARATOR(c) ((c) == '/')
#define SPT_MAXTITLE 255
extern const char *__progname;
static const char *
getprogname(void)
{
return (__progname);
}
static void
setprogname(const char *progname)
{
size_t i;
for (i = strlen(progname); i > 0; i--) {
if (LIBBSD_IS_PATHNAME_SEPARATOR(progname[i - 1])) {
__progname = progname + i;
return;
}
}
__progname = progname;
}
static inline size_t
spt_min(size_t a, size_t b)
{
return ((a < b) ? a : b);
}
/*
* For discussion on the portability of the various methods, see
* https://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
*/
static int
spt_clearenv(void)
{
char **tmp;
tmp = malloc(sizeof (*tmp));
if (tmp == NULL)
return (errno);
tmp[0] = NULL;
environ = tmp;
return (0);
}
static int
spt_copyenv(int envc, char *envp[])
{
char **envcopy;
char *eq;
int envsize;
int i, error;
if (environ != envp)
return (0);
/*
* Make a copy of the old environ array of pointers, in case
* clearenv() or setenv() is implemented to free the internal
* environ array, because we will need to access the old environ
* contents to make the new copy.
*/
envsize = (envc + 1) * sizeof (char *);
envcopy = malloc(envsize);
if (envcopy == NULL)
return (errno);
memcpy(envcopy, envp, envsize);
error = spt_clearenv();
if (error) {
environ = envp;
free(envcopy);
return (error);
}
for (i = 0; envcopy[i]; i++) {
eq = strchr(envcopy[i], '=');
if (eq == NULL)
continue;
*eq = '\0';
if (setenv(envcopy[i], eq + 1, 1) < 0)
error = errno;
*eq = '=';
if (error) {
environ = envp;
free(envcopy);
return (error);
}
}
/*
* Dispose of the shallow copy, now that we've finished transfering
* the old environment.
*/
free(envcopy);
return (0);
}
static int
spt_copyargs(int argc, char *argv[])
{
char *tmp;
int i;
for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
if (argv[i] == NULL)
continue;
tmp = strdup(argv[i]);
if (tmp == NULL)
return (errno);
argv[i] = tmp;
}
return (0);
}
void
zfs_setproctitle_init(int argc, char *argv[], char *envp[])
{
char *base, *end, *nul, *tmp;
int i, envc, error;
/* Try to make sure we got called with main() arguments. */
if (argc < 0)
return;
base = argv[0];
if (base == NULL)
return;
nul = base + strlen(base);
end = nul + 1;
for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
if (argv[i] == NULL || argv[i] != end)
continue;
end = argv[i] + strlen(argv[i]) + 1;
}
for (i = 0; envp[i]; i++) {
if (envp[i] != end)
continue;
end = envp[i] + strlen(envp[i]) + 1;
}
envc = i;
SPT.arg0 = strdup(argv[0]);
if (SPT.arg0 == NULL) {
SPT.error = errno;
return;
}
tmp = strdup(getprogname());
if (tmp == NULL) {
SPT.error = errno;
return;
}
setprogname(tmp);
error = spt_copyenv(envc, envp);
if (error) {
SPT.error = error;
return;
}
error = spt_copyargs(argc, argv);
if (error) {
SPT.error = error;
return;
}
SPT.nul = nul;
SPT.base = base;
SPT.end = end;
}
void
zfs_setproctitle(const char *fmt, ...)
{
/* Use buffer in case argv[0] is passed. */
char buf[SPT_MAXTITLE + 1];
va_list ap;
char *nul;
int len;
if (SPT.base == NULL) {
if (!SPT.warned) {
warnx("setproctitle not initialized, please"
"call zfs_setproctitle_init()");
SPT.warned = B_TRUE;
}
return;
}
if (fmt) {
if (fmt[0] == '-') {
/* Skip program name prefix. */
fmt++;
len = 0;
} else {
/* Print program name heading for grep. */
snprintf(buf, sizeof (buf), "%s: ", getprogname());
len = strlen(buf);
}
va_start(ap, fmt);
len += vsnprintf(buf + len, sizeof (buf) - len, fmt, ap);
va_end(ap);
} else {
len = snprintf(buf, sizeof (buf), "%s", SPT.arg0);
}
if (len <= 0) {
SPT.error = errno;
return;
}
if (!SPT.reset) {
memset(SPT.base, 0, SPT.end - SPT.base);
SPT.reset = B_TRUE;
} else {
memset(SPT.base, 0, spt_min(sizeof (buf), SPT.end - SPT.base));
}
len = spt_min(len, spt_min(sizeof (buf), SPT.end - SPT.base) - 1);
memcpy(SPT.base, buf, len);
nul = SPT.base + len;
if (nul < SPT.nul) {
*SPT.nul = '.';
} else if (nul == SPT.nul && nul + 1 < SPT.end) {
*SPT.nul = ' ';
*++nul = '\0';
}
}