Warning, file /frameworks/kinit/src/kdeinit/proctitle.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* Based on setproctitle.c from OpenSSH 6.6p1 */
0002 /*
0003     SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
0004     SPDX-FileCopyrightText: 2003 Damien Miller
0005     SPDX-FileCopyrightText: 1983, 1995-1997 Eric P. Allman
0006     SPDX-FileCopyrightText: 1988, 1993 The Regents of the University of California.  All rights reserved.
0007 
0008     SPDX-License-Identifier: BSD-3-Clause
0009 */
0010 
0011 #include "proctitle.h"
0012 #include <config-kdeinit.h>
0013 
0014 #define PT_NONE         0    /* don't use it at all */
0015 #define PT_PSTAT        1    /* use pstat(PSTAT_SETCMD, ...) */
0016 #define PT_REUSEARGV    2    /* cover argv with title information */
0017 #define PT_SETPROCTITLE 3    /* forward onto the native setproctitle */
0018 
0019 #include <stdarg.h>
0020 #include <stdio.h>
0021 #include <stdlib.h>
0022 #include <sys/types.h>
0023 #include <unistd.h>
0024 #include <string.h>
0025 
0026 #if HAVE_SETPROCTITLE
0027 #  define PT_TYPE    PT_SETPROCTITLE
0028    // process title should get prepended automagically
0029 #  define ADD_PROCTITLE 0
0030 #elif HAVE_SYS_PSTAT_H && HAVE_PSTAT
0031 #  include <sys/pstat.h>
0032 #  define PT_TYPE    PT_PSTAT
0033 #elif CAN_CLOBBER_ARGV
0034 #  define PT_TYPE    PT_REUSEARGV
0035 #endif
0036 
0037 #ifndef PT_TYPE
0038 #  define PT_TYPE    PT_NONE
0039 #endif
0040 #ifndef ADD_PROCTITLE
0041 #  define ADD_PROCTITLE 1
0042 #endif
0043 
0044 #if PT_TYPE == PT_REUSEARGV
0045 static char *argv_start = nullptr;
0046 static size_t argv_env_len = 0;
0047 #endif
0048 
0049 #if HAVE___PROGNAME
0050 extern char *__progname;
0051 #else
0052 char *__progname;
0053 #endif
0054 
0055 void
0056 proctitle_init(int argc, char *argv[])
0057 {
0058 #if HAVE___PROGNAME
0059     // progname may be a reference to argv[0]
0060     __progname = strdup(__progname);
0061 #else
0062     if (argc == 0 || argv[0] == NULL) {
0063         __progname = "unknown";    /* XXX */
0064     } else {
0065         char *p = strrchr(argv[0], '/');
0066         if (p == NULL)
0067             p = argv[0];
0068         else
0069             p++;
0070 
0071         __progname = strdup(p);
0072     }
0073 #endif
0074 
0075 #if PT_TYPE == PT_REUSEARGV
0076     if (argc == 0 || argv[0] == nullptr)
0077         return;
0078 
0079     extern char **environ;
0080     char *lastargv = nullptr;
0081     char **envp = environ;
0082     int i;
0083 
0084     /*
0085      * NB: This assumes that argv has already been copied out of the
0086      * way. This is true for kdeinit, but may not be true for other
0087      * programs. Beware.
0088      */
0089 
0090     /* Fail if we can't allocate room for the new environment */
0091     for (i = 0; envp[i] != nullptr; i++)
0092         ;
0093     if ((environ = (char**)calloc(i + 1, sizeof(*environ))) == nullptr) {
0094         environ = envp;    /* put it back */
0095         return;
0096     }
0097 
0098     /*
0099      * Find the last argv string or environment variable within
0100      * our process memory area.
0101      */
0102     for (i = 0; i < argc; i++) {
0103         if (lastargv == nullptr || lastargv + 1 == argv[i])
0104             lastargv = argv[i] + strlen(argv[i]);
0105     }
0106     for (i = 0; envp[i] != nullptr; i++) {
0107         if (lastargv + 1 == envp[i])
0108             lastargv = envp[i] + strlen(envp[i]);
0109     }
0110 
0111     argv[1] = nullptr;
0112     argv_start = argv[0];
0113     argv_env_len = lastargv - argv[0] - 1;
0114 
0115     /*
0116      * Copy environment
0117      * XXX - will truncate env on strdup fail
0118      */
0119     for (i = 0; envp[i] != nullptr; i++)
0120         environ[i] = strdup(envp[i]);
0121     environ[i] = nullptr;
0122 #endif /* PT_REUSEARGV */
0123 }
0124 
0125 void
0126 proctitle_set(const char *fmt, ...)
0127 {
0128 #if PT_TYPE != PT_NONE
0129 #if PT_TYPE == PT_REUSEARGV
0130     if (argv_env_len <= 0)
0131         return;
0132 #endif
0133 
0134     bool skip_proctitle = false;
0135     if (fmt != nullptr && fmt[0] == '-') {
0136         skip_proctitle = true;
0137         ++fmt;
0138     }
0139     char ptitle[1024];
0140     memset(ptitle, '\0', sizeof(ptitle));
0141     size_t len = 0;
0142 
0143 #if ADD_PROCTITLE
0144     if (!skip_proctitle) {
0145         strncpy(ptitle, __progname, sizeof(ptitle)-1);
0146         len = strlen(ptitle);
0147         if (fmt != nullptr && sizeof(ptitle) - len > 2) {
0148             strcpy(ptitle + len, ": ");
0149             len += 2;
0150         }
0151     }
0152 #endif
0153 
0154     if (fmt != nullptr) {
0155         int r = -1;
0156         if (len < sizeof(ptitle) - 1) {
0157             va_list ap;
0158             va_start(ap, fmt);
0159             r = vsnprintf(ptitle + len, sizeof(ptitle) - len , fmt, ap);
0160             va_end(ap);
0161         }
0162         if (r == -1 || (size_t)r >= sizeof(ptitle) - len)
0163             return;
0164     }
0165 
0166 #if PT_TYPE == PT_PSTAT
0167     union pstun pst;
0168     pst.pst_command = ptitle;
0169     pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
0170 #elif PT_TYPE == PT_REUSEARGV
0171     strncpy(argv_start, ptitle, argv_env_len);
0172     argv_start[argv_env_len-1] = '\0';
0173 #elif PT_TYPE == PT_SETPROCTITLE
0174     if (fmt == NULL) {
0175         setproctitle(NULL);
0176 #if defined(__FreeBSD__)
0177     } else if (skip_proctitle) {
0178         // setproctitle on FreeBSD allows skipping the process title
0179         setproctitle("-%s", ptitle);
0180 #endif
0181     } else {
0182         setproctitle("%s", ptitle);
0183     }
0184 #endif
0185 
0186 #endif /* !PT_NONE */
0187 }