diff options
Diffstat (limited to 'examples/redis-unstable/src/setproctitle.c')
| -rw-r--r-- | examples/redis-unstable/src/setproctitle.c | 331 |
1 files changed, 0 insertions, 331 deletions
diff --git a/examples/redis-unstable/src/setproctitle.c b/examples/redis-unstable/src/setproctitle.c deleted file mode 100644 index cc31845..0000000 --- a/examples/redis-unstable/src/setproctitle.c +++ /dev/null | |||
| @@ -1,331 +0,0 @@ | |||
| 1 | /* ========================================================================== | ||
| 2 | * setproctitle.c - Linux/Darwin setproctitle. | ||
| 3 | * -------------------------------------------------------------------------- | ||
| 4 | * Copyright (C) 2010 William Ahern | ||
| 5 | * Copyright (C) 2013-current Redis Ltd. | ||
| 6 | * Copyright (C) 2013 Stam He | ||
| 7 | * | ||
| 8 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 9 | * copy of this software and associated documentation files (the | ||
| 10 | * "Software"), to deal in the Software without restriction, including | ||
| 11 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 12 | * distribute, sublicense, and/or sell copies of the Software, and to permit | ||
| 13 | * persons to whom the Software is furnished to do so, subject to the | ||
| 14 | * following conditions: | ||
| 15 | * | ||
| 16 | * The above copyright notice and this permission notice shall be included | ||
| 17 | * in all copies or substantial portions of the Software. | ||
| 18 | * | ||
| 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
| 20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN | ||
| 22 | * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
| 23 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 24 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 25 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 26 | * ========================================================================== | ||
| 27 | */ | ||
| 28 | #ifndef _GNU_SOURCE | ||
| 29 | #define _GNU_SOURCE | ||
| 30 | #endif | ||
| 31 | |||
| 32 | #include <stddef.h> /* NULL size_t */ | ||
| 33 | #include <stdarg.h> /* va_list va_start va_end */ | ||
| 34 | #include <stdlib.h> /* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */ | ||
| 35 | #include <stdio.h> /* vsnprintf(3) snprintf(3) */ | ||
| 36 | |||
| 37 | #include <string.h> /* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */ | ||
| 38 | |||
| 39 | #include <errno.h> /* errno program_invocation_name program_invocation_short_name */ | ||
| 40 | |||
| 41 | #if !defined(HAVE_SETPROCTITLE) | ||
| 42 | #if (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__ || defined __DragonFly__) | ||
| 43 | #define HAVE_SETPROCTITLE 1 | ||
| 44 | #else | ||
| 45 | #define HAVE_SETPROCTITLE 0 | ||
| 46 | #endif | ||
| 47 | #endif | ||
| 48 | |||
| 49 | |||
| 50 | #if !HAVE_SETPROCTITLE | ||
| 51 | #if (defined __linux || defined __APPLE__) | ||
| 52 | |||
| 53 | #ifdef __GLIBC__ | ||
| 54 | #define HAVE_CLEARENV | ||
| 55 | #endif | ||
| 56 | |||
| 57 | extern char **environ; | ||
| 58 | |||
| 59 | static struct { | ||
| 60 | /* original value */ | ||
| 61 | const char *arg0; | ||
| 62 | |||
| 63 | /* title space available */ | ||
| 64 | char *base, *end; | ||
| 65 | |||
| 66 | /* pointer to original nul character within base */ | ||
| 67 | char *nul; | ||
| 68 | |||
| 69 | _Bool reset; | ||
| 70 | int error; | ||
| 71 | } SPT; | ||
| 72 | |||
| 73 | |||
| 74 | #ifndef SPT_MIN | ||
| 75 | #define SPT_MIN(a, b) (((a) < (b))? (a) : (b)) | ||
| 76 | #endif | ||
| 77 | |||
| 78 | static inline size_t spt_min(size_t a, size_t b) { | ||
| 79 | return SPT_MIN(a, b); | ||
| 80 | } /* spt_min() */ | ||
| 81 | |||
| 82 | |||
| 83 | /* | ||
| 84 | * For discussion on the portability of the various methods, see | ||
| 85 | * http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html | ||
| 86 | */ | ||
| 87 | int spt_clearenv(void) { | ||
| 88 | #ifdef HAVE_CLEARENV | ||
| 89 | return clearenv(); | ||
| 90 | #else | ||
| 91 | extern char **environ; | ||
| 92 | static char **tmp; | ||
| 93 | |||
| 94 | if (!(tmp = malloc(sizeof *tmp))) | ||
| 95 | return errno; | ||
| 96 | |||
| 97 | tmp[0] = NULL; | ||
| 98 | environ = tmp; | ||
| 99 | |||
| 100 | return 0; | ||
| 101 | #endif | ||
| 102 | } /* spt_clearenv() */ | ||
| 103 | |||
| 104 | |||
| 105 | static int spt_copyenv(int envc, char *oldenv[]) { | ||
| 106 | extern char **environ; | ||
| 107 | char **envcopy = NULL; | ||
| 108 | char *eq; | ||
| 109 | int i, error; | ||
| 110 | int envsize; | ||
| 111 | |||
| 112 | if (environ != oldenv) | ||
| 113 | return 0; | ||
| 114 | |||
| 115 | /* Copy environ into envcopy before clearing it. Shallow copy is | ||
| 116 | * enough as clearenv() only clears the environ array. | ||
| 117 | */ | ||
| 118 | envsize = (envc + 1) * sizeof(char *); | ||
| 119 | envcopy = malloc(envsize); | ||
| 120 | if (!envcopy) | ||
| 121 | return ENOMEM; | ||
| 122 | memcpy(envcopy, oldenv, envsize); | ||
| 123 | |||
| 124 | /* Note that the state after clearenv() failure is undefined, but we'll | ||
| 125 | * just assume an error means it was left unchanged. | ||
| 126 | */ | ||
| 127 | if ((error = spt_clearenv())) { | ||
| 128 | environ = oldenv; | ||
| 129 | free(envcopy); | ||
| 130 | return error; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* Set environ from envcopy */ | ||
| 134 | for (i = 0; envcopy[i]; i++) { | ||
| 135 | if (!(eq = strchr(envcopy[i], '='))) | ||
| 136 | continue; | ||
| 137 | |||
| 138 | *eq = '\0'; | ||
| 139 | error = (0 != setenv(envcopy[i], eq + 1, 1))? errno : 0; | ||
| 140 | *eq = '='; | ||
| 141 | |||
| 142 | /* On error, do our best to restore state */ | ||
| 143 | if (error) { | ||
| 144 | #ifdef HAVE_CLEARENV | ||
| 145 | /* We don't assume it is safe to free environ, so we | ||
| 146 | * may leak it. As clearenv() was shallow using envcopy | ||
| 147 | * here is safe. | ||
| 148 | */ | ||
| 149 | environ = envcopy; | ||
| 150 | #else | ||
| 151 | free(envcopy); | ||
| 152 | free(environ); /* Safe to free, we have just alloc'd it */ | ||
| 153 | environ = oldenv; | ||
| 154 | #endif | ||
| 155 | return error; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | free(envcopy); | ||
| 160 | return 0; | ||
| 161 | } /* spt_copyenv() */ | ||
| 162 | |||
| 163 | |||
| 164 | static int spt_copyargs(int argc, char *argv[]) { | ||
| 165 | char *tmp; | ||
| 166 | int i; | ||
| 167 | |||
| 168 | for (i = 1; i < argc || (i >= argc && argv[i]); i++) { | ||
| 169 | if (!argv[i]) | ||
| 170 | continue; | ||
| 171 | |||
| 172 | if (!(tmp = strdup(argv[i]))) | ||
| 173 | return errno; | ||
| 174 | |||
| 175 | argv[i] = tmp; | ||
| 176 | } | ||
| 177 | |||
| 178 | return 0; | ||
| 179 | } /* spt_copyargs() */ | ||
| 180 | |||
| 181 | /* Initialize and populate SPT to allow a future setproctitle() | ||
| 182 | * call. | ||
| 183 | * | ||
| 184 | * As setproctitle() basically needs to overwrite argv[0], we're | ||
| 185 | * trying to determine what is the largest contiguous block | ||
| 186 | * starting at argv[0] we can use for this purpose. | ||
| 187 | * | ||
| 188 | * As this range will overwrite some or all of the argv and environ | ||
| 189 | * strings, a deep copy of these two arrays is performed. | ||
| 190 | */ | ||
| 191 | void spt_init(int argc, char *argv[]) { | ||
| 192 | char **envp = environ; | ||
| 193 | char *base, *end, *nul, *tmp; | ||
| 194 | int i, error, envc; | ||
| 195 | |||
| 196 | if (!(base = argv[0])) | ||
| 197 | return; | ||
| 198 | |||
| 199 | /* We start with end pointing at the end of argv[0] */ | ||
| 200 | nul = &base[strlen(base)]; | ||
| 201 | end = nul + 1; | ||
| 202 | |||
| 203 | /* Attempt to extend end as far as we can, while making sure | ||
| 204 | * that the range between base and end is only allocated to | ||
| 205 | * argv, or anything that immediately follows argv (presumably | ||
| 206 | * envp). | ||
| 207 | */ | ||
| 208 | for (i = 0; i < argc || (i >= argc && argv[i]); i++) { | ||
| 209 | if (!argv[i] || argv[i] < end) | ||
| 210 | continue; | ||
| 211 | |||
| 212 | if (end >= argv[i] && end <= argv[i] + strlen(argv[i])) | ||
| 213 | end = argv[i] + strlen(argv[i]) + 1; | ||
| 214 | } | ||
| 215 | |||
| 216 | /* In case the envp array was not an immediate extension to argv, | ||
| 217 | * scan it explicitly. | ||
| 218 | */ | ||
| 219 | for (i = 0; envp[i]; i++) { | ||
| 220 | if (envp[i] < end) | ||
| 221 | continue; | ||
| 222 | |||
| 223 | if (end >= envp[i] && end <= envp[i] + strlen(envp[i])) | ||
| 224 | end = envp[i] + strlen(envp[i]) + 1; | ||
| 225 | } | ||
| 226 | envc = i; | ||
| 227 | |||
| 228 | /* We're going to deep copy argv[], but argv[0] will still point to | ||
| 229 | * the old memory for the purpose of updating the title so we need | ||
| 230 | * to keep the original value elsewhere. | ||
| 231 | */ | ||
| 232 | if (!(SPT.arg0 = strdup(argv[0]))) | ||
| 233 | goto syerr; | ||
| 234 | |||
| 235 | #if __linux__ | ||
| 236 | if (!(tmp = strdup(program_invocation_name))) | ||
| 237 | goto syerr; | ||
| 238 | |||
| 239 | program_invocation_name = tmp; | ||
| 240 | |||
| 241 | if (!(tmp = strdup(program_invocation_short_name))) | ||
| 242 | goto syerr; | ||
| 243 | |||
| 244 | program_invocation_short_name = tmp; | ||
| 245 | #elif __APPLE__ | ||
| 246 | if (!(tmp = strdup(getprogname()))) | ||
| 247 | goto syerr; | ||
| 248 | |||
| 249 | setprogname(tmp); | ||
| 250 | #endif | ||
| 251 | |||
| 252 | /* Now make a full deep copy of the environment and argv[] */ | ||
| 253 | if ((error = spt_copyenv(envc, envp))) | ||
| 254 | goto error; | ||
| 255 | |||
| 256 | if ((error = spt_copyargs(argc, argv))) | ||
| 257 | goto error; | ||
| 258 | |||
| 259 | SPT.nul = nul; | ||
| 260 | SPT.base = base; | ||
| 261 | SPT.end = end; | ||
| 262 | |||
| 263 | return; | ||
| 264 | syerr: | ||
| 265 | error = errno; | ||
| 266 | error: | ||
| 267 | SPT.error = error; | ||
| 268 | } /* spt_init() */ | ||
| 269 | |||
| 270 | |||
| 271 | #ifndef SPT_MAXTITLE | ||
| 272 | #define SPT_MAXTITLE 255 | ||
| 273 | #endif | ||
| 274 | |||
| 275 | void setproctitle(const char *fmt, ...) { | ||
| 276 | char buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */ | ||
| 277 | va_list ap; | ||
| 278 | char *nul; | ||
| 279 | int len, error; | ||
| 280 | |||
| 281 | if (!SPT.base) | ||
| 282 | return; | ||
| 283 | |||
| 284 | if (fmt) { | ||
| 285 | va_start(ap, fmt); | ||
| 286 | len = vsnprintf(buf, sizeof buf, fmt, ap); | ||
| 287 | va_end(ap); | ||
| 288 | } else { | ||
| 289 | len = snprintf(buf, sizeof buf, "%s", SPT.arg0); | ||
| 290 | } | ||
| 291 | |||
| 292 | if (len <= 0) | ||
| 293 | { error = errno; goto error; } | ||
| 294 | |||
| 295 | if (!SPT.reset) { | ||
| 296 | memset(SPT.base, 0, SPT.end - SPT.base); | ||
| 297 | SPT.reset = 1; | ||
| 298 | } else { | ||
| 299 | memset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base)); | ||
| 300 | } | ||
| 301 | |||
| 302 | len = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1); | ||
| 303 | memcpy(SPT.base, buf, len); | ||
| 304 | nul = &SPT.base[len]; | ||
| 305 | |||
| 306 | if (nul < SPT.nul) { | ||
| 307 | *SPT.nul = '.'; | ||
| 308 | } else if (nul == SPT.nul && &nul[1] < SPT.end) { | ||
| 309 | *SPT.nul = ' '; | ||
| 310 | *++nul = '\0'; | ||
| 311 | } | ||
| 312 | |||
| 313 | return; | ||
| 314 | error: | ||
| 315 | SPT.error = error; | ||
| 316 | } /* setproctitle() */ | ||
| 317 | |||
| 318 | |||
| 319 | #endif /* __linux || __APPLE__ */ | ||
| 320 | #endif /* !HAVE_SETPROCTITLE */ | ||
| 321 | |||
| 322 | #ifdef SETPROCTITLE_TEST_MAIN | ||
| 323 | int main(int argc, char *argv[]) { | ||
| 324 | spt_init(argc, argv); | ||
| 325 | |||
| 326 | printf("SPT.arg0: [%p] '%s'\n", SPT.arg0, SPT.arg0); | ||
| 327 | printf("SPT.base: [%p] '%s'\n", SPT.base, SPT.base); | ||
| 328 | printf("SPT.end: [%p] (%d bytes after base)'\n", SPT.end, (int) (SPT.end - SPT.base)); | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | #endif | ||
