"Fossies" - the Fresh Open Source Software Archive

Member "dhcpcd-9.4.1/compat/setproctitle.c" (22 Oct 2021, 6941 Bytes) of package /linux/misc/dhcpcd-9.4.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "setproctitle.c": 9.3.0_vs_9.3.1.

    1 /*
    2  * Copyright © 2010 William Ahern
    3  * Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
    4  *
    5  * Permission is hereby granted, free of charge, to any person obtaining a
    6  * copy of this software and associated documentation files (the
    7  * "Software"), to deal in the Software without restriction, including
    8  * without limitation the rights to use, copy, modify, merge, publish,
    9  * distribute, sublicense, and/or sell copies of the Software, and to permit
   10  * persons to whom the Software is furnished to do so, subject to the
   11  * following conditions:
   12  *
   13  * The above copyright notice and this permission notice shall be included
   14  * in all copies or substantial portions of the Software.
   15  *
   16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
   19  * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
   20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
   21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
   22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
   23  */
   24 
   25 #include <errno.h>
   26 #include <stddef.h>
   27 #include <stdarg.h>
   28 #include <stdbool.h>
   29 #include <stdlib.h>
   30 #include <stdio.h>
   31 #include <err.h>
   32 #include <unistd.h>
   33 #include <string.h>
   34 //#include "local-link.h"
   35 
   36 #include "config.h"
   37 
   38 static struct {
   39     /* Original value. */
   40     char *arg0;
   41 
   42     /* Title space available. */
   43     char *base, *end;
   44 
   45      /* Pointer to original nul character within base. */
   46     char *nul;
   47 
   48     bool warned;
   49     bool reset;
   50     int error;
   51 
   52     /* Our copy of args and environment to free. */
   53     int argc;
   54     char **argv;
   55     char **tmp_environ;
   56 } SPT;
   57 
   58 
   59 static inline size_t
   60 spt_min(size_t a, size_t b)
   61 {
   62     return a < b ? a : b;
   63 }
   64 
   65 /*
   66  * For discussion on the portability of the various methods, see
   67  * https://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
   68  */
   69 static int
   70 spt_clearenv(void)
   71 {
   72 #ifdef HAVE_CLEARENV
   73     return clearenv();
   74 #else
   75     SPT.tmp_environ = malloc(sizeof(*SPT.tmp_environ));
   76     if (SPT.tmp_environ == NULL)
   77         return errno;
   78 
   79     SPT.tmp_environ[0] = NULL;
   80     environ = SPT.tmp_environ;
   81 
   82     return 0;
   83 #endif
   84 }
   85 
   86 static int
   87 spt_copyenv(int envc, char *envp[])
   88 {
   89     char **envcopy;
   90     char *eq;
   91     size_t envsize;
   92     int i, error;
   93 
   94     if (environ != envp)
   95         return 0;
   96 
   97     /* Make a copy of the old environ array of pointers, in case
   98      * clearenv() or setenv() is implemented to free the internal
   99      * environ array, because we will need to access the old environ
  100      * contents to make the new copy. */
  101     envsize = (size_t)(envc + 1) * sizeof(char *);
  102     envcopy = malloc(envsize);
  103     if (envcopy == NULL)
  104         return errno;
  105     memcpy(envcopy, envp, envsize);
  106 
  107     error = spt_clearenv();
  108     if (error) {
  109         environ = envp;
  110         free(envcopy);
  111         return error;
  112     }
  113 
  114     for (i = 0; envcopy[i]; i++) {
  115         eq = strchr(envcopy[i], '=');
  116         if (eq == NULL)
  117             continue;
  118 
  119         *eq = '\0';
  120         if (setenv(envcopy[i], eq + 1, 1) < 0)
  121             error = errno;
  122         *eq = '=';
  123 
  124         if (error) {
  125 #ifdef HAVE_CLEARENV
  126             /* Because the old environ might not be available
  127              * anymore we will make do with the shallow copy. */
  128             environ = envcopy;
  129 #else
  130             environ = envp;
  131             free(envcopy);
  132 #endif
  133             return error;
  134         }
  135     }
  136 
  137     /* Dispose of the shallow copy, now that we've finished transfering
  138      * the old environment. */
  139     free(envcopy);
  140 
  141     return 0;
  142 }
  143 
  144 static int
  145 spt_copyargs(int argc, char *argv[])
  146 {
  147     char *tmp;
  148     int i;
  149 
  150     for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
  151         if (argv[i] == NULL)
  152             continue;
  153 
  154         tmp = strdup(argv[i]);
  155         if (tmp == NULL)
  156             return errno;
  157 
  158         argv[i] = tmp;
  159     }
  160 
  161     return 0;
  162 }
  163 
  164 void
  165 setproctitle_init(int argc, char *argv[], char *envp[])
  166 {
  167     char *base, *end, *nul, *tmp;
  168     int i, envc, error;
  169 
  170     /* Try to make sure we got called with main() arguments. */
  171     if (argc < 0)
  172         return;
  173 
  174     base = argv[0];
  175     if (base == NULL)
  176         return;
  177 
  178     nul = &base[strlen(base)];
  179     end = nul + 1;
  180 
  181     for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
  182         if (argv[i] == NULL || argv[i] != end)
  183             continue;
  184 
  185         end = argv[i] + strlen(argv[i]) + 1;
  186     }
  187 
  188     for (i = 0; envp[i]; i++) {
  189         if (envp[i] != end)
  190             continue;
  191 
  192         end = envp[i] + strlen(envp[i]) + 1;
  193     }
  194     envc = i;
  195 
  196     SPT.arg0 = strdup(argv[0]);
  197     if (SPT.arg0 == NULL) {
  198         SPT.error = errno;
  199         return;
  200     }
  201 
  202     tmp = strdup(getprogname());
  203     if (tmp == NULL) {
  204         SPT.error = errno;
  205         return;
  206     }
  207     setprogname(tmp);
  208 
  209     error = spt_copyenv(envc, envp);
  210     if (error) {
  211         SPT.error = error;
  212         return;
  213     }
  214 
  215     error = spt_copyargs(argc, argv);
  216     if (error) {
  217         SPT.error = error;
  218         return;
  219     }
  220 
  221     SPT.argc = argc;
  222     SPT.argv = argv;
  223 
  224     SPT.nul  = nul;
  225     SPT.base = base;
  226     SPT.end  = end;
  227 }
  228 
  229 void
  230 setproctitle_fini(void)
  231 {
  232     int i;
  233 
  234     free(SPT.arg0);
  235     SPT.arg0 = NULL;
  236 
  237     for (i = 1; i < SPT.argc; i++) {
  238         if (SPT.argv[i] != NULL)
  239             free(SPT.argv[i]);
  240     }
  241     SPT.argc = 0;
  242 
  243     free(SPT.tmp_environ);
  244     SPT.tmp_environ = NULL;
  245 }
  246 
  247 #ifndef SPT_MAXTITLE
  248 #define SPT_MAXTITLE 255
  249 #endif
  250 
  251 __printflike(1, 2) static void
  252 setproctitle_impl(const char *fmt, ...)
  253 {
  254     /* Use buffer in case argv[0] is passed. */
  255     char buf[SPT_MAXTITLE + 1];
  256     va_list ap;
  257     char *nul;
  258     int l;
  259     size_t len, base_len;
  260 
  261     if (SPT.base == NULL) {
  262         if (!SPT.warned) {
  263             warnx("setproctitle not initialized, please either call "
  264                   "setproctitle_init() or link against libbsd-ctor.");
  265             SPT.warned = true;
  266         }
  267         return;
  268     }
  269 
  270     if (fmt) {
  271         if (fmt[0] == '-') {
  272             /* Skip program name prefix. */
  273             fmt++;
  274             len = 0;
  275         } else {
  276             /* Print program name heading for grep. */
  277             l = snprintf(buf, sizeof(buf), "%s: ", getprogname());
  278             if (l <= 0)
  279                 return;
  280             len = (size_t)l;
  281         }
  282 
  283         va_start(ap, fmt);
  284         l = vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
  285         va_end(ap);
  286     } else {
  287         len = 0;
  288         l = snprintf(buf, sizeof(buf), "%s", SPT.arg0);
  289     }
  290 
  291     if (l <= 0) {
  292         SPT.error = errno;
  293         return;
  294     }
  295     len += (size_t)l;
  296 
  297     base_len = (size_t)(SPT.end - SPT.base);
  298     if (!SPT.reset) {
  299         memset(SPT.base, 0, base_len);
  300         SPT.reset = true;
  301     } else {
  302         memset(SPT.base, 0, spt_min(sizeof(buf), base_len));
  303     }
  304 
  305     len = spt_min(len, spt_min(sizeof(buf), base_len) - 1);
  306     memcpy(SPT.base, buf, len);
  307     nul = &SPT.base[len];
  308 
  309     if (nul < SPT.nul) {
  310         *SPT.nul = '.';
  311     } else if (nul == SPT.nul && &nul[1] < SPT.end) {
  312         *SPT.nul = ' ';
  313         *++nul = '\0';
  314     }
  315 }
  316 libbsd_symver_default(setproctitle, setproctitle_impl, LIBBSD_0.5);
  317 
  318 /* The original function introduced in 0.2 was a stub, it only got implemented
  319  * in 0.5, make the implementation available in the old version as an alias
  320  * for code linking against that version, and change the default to use the
  321  * new version, so that new code depends on the implemented version. */
  322 #ifdef HAVE_TYPEOF
  323 extern __typeof__(setproctitle_impl)
  324 setproctitle_stub
  325     __attribute__((__alias__("setproctitle_impl")));
  326 #else
  327 void
  328 setproctitle_stub(const char *fmt, ...)
  329     __attribute__((__alias__("setproctitle_impl")));
  330 #endif
  331 libbsd_symver_variant(setproctitle, setproctitle_stub, LIBBSD_0.2);