cmogstored 1.8.1 - use default system stack size
[cmogstored.git] / nostd / setproctitle.c
blob73ecadb90bba7f10bf38d17a49d15e17e25d89ea
1 /* ==========================================================================
2 * setproctitle.c - Linux/Darwin setproctitle.
3 * --------------------------------------------------------------------------
4 * Copyright (C) 2010 William Ahern
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to permit
11 * persons to whom the Software is furnished to do so, subject to the
12 * following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
20 * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 * USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * ==========================================================================
26 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE
28 #endif
30 #include <stddef.h> /* NULL size_t */
31 #include <stdarg.h> /* va_list va_start va_end */
32 #include <stdlib.h> /* malloc(3) setenv(3) clearenv(3) setproctitle(3) getprogname(3) */
33 #include <stdio.h> /* vsnprintf(3) snprintf(3) */
35 #include <string.h> /* strlen(3) strchr(3) strdup(3) memset(3) memcpy(3) */
37 #include <errno.h> /* errno program_invocation_name program_invocation_short_name */
40 #if !defined(HAVE_SETPROCTITLE)
41 #define HAVE_SETPROCTITLE (defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)
42 #endif
45 #if !HAVE_SETPROCTITLE
46 #if (defined __linux || defined __APPLE__) && defined __GNUC__
49 static struct {
50 /* original value */
51 const char *arg0;
53 /* title space available */
54 char *base, *end;
56 /* pointer to original nul character within base */
57 char *nul;
59 _Bool reset;
60 int error;
61 } SPT;
64 #ifndef SPT_MIN
65 #define SPT_MIN(a, b) (((a) < (b))? (a) : (b))
66 #endif
68 static inline size_t spt_min(size_t a, size_t b) {
69 return SPT_MIN(a, b);
70 } /* spt_min() */
74 * For discussion on the portability of the various methods, see
75 * http://lists.freebsd.org/pipermail/freebsd-stable/2008-June/043136.html
77 static int spt_clearenv(void) {
78 #if __GLIBC__
79 clearenv();
81 return 0;
82 #else
83 extern char **environ;
84 char **tmp;
86 if (!(tmp = malloc(sizeof *tmp)))
87 return errno;
89 tmp[0] = NULL;
90 environ = tmp;
92 return 0;
93 #endif
94 } /* spt_clearenv() */
97 static int spt_copyenv(char *oldenv[]) {
98 extern char **environ;
99 char *eq;
100 int i, error;
102 if (environ != oldenv)
103 return 0;
105 if ((error = spt_clearenv()))
106 goto error;
108 for (i = 0; oldenv[i]; i++) {
109 if (!(eq = strchr(oldenv[i], '=')))
110 continue;
112 *eq = '\0';
113 error = (0 != setenv(oldenv[i], eq + 1, 1))? errno : 0;
114 *eq = '=';
116 if (error)
117 goto error;
120 return 0;
121 error:
122 environ = oldenv;
124 return error;
125 } /* spt_copyenv() */
128 static int spt_copyargs(int argc, char *argv[]) {
129 char *tmp;
130 int i;
132 for (i = 1; i < argc || (i >= argc && argv[i]); i++) {
133 if (!argv[i])
134 continue;
136 if (!(tmp = strdup(argv[i])))
137 return errno;
139 argv[i] = tmp;
142 return 0;
143 } /* spt_copyargs() */
145 void spt_init(int argc, char *argv[], char *envp[]) {
146 char *base, *end, *nul, *tmp;
147 int i, error;
149 if (!(base = argv[0]))
150 return;
152 nul = &base[strlen(base)];
153 end = nul + 1;
155 for (i = 0; i < argc || (i >= argc && argv[i]); i++) {
156 if (!argv[i] || argv[i] < end)
157 continue;
159 end = argv[i] + strlen(argv[i]) + 1;
162 for (i = 0; envp[i]; i++) {
163 if (envp[i] < end)
164 continue;
166 end = envp[i] + strlen(envp[i]) + 1;
169 if (!(SPT.arg0 = strdup(argv[0])))
170 goto syerr;
172 #if __GLIBC__
173 if (!(tmp = strdup(program_invocation_name)))
174 goto syerr;
176 program_invocation_name = tmp;
178 if (!(tmp = strdup(program_invocation_short_name)))
179 goto syerr;
181 program_invocation_short_name = tmp;
182 #elif __APPLE__
183 if (!(tmp = strdup(getprogname())))
184 goto syerr;
186 setprogname(tmp);
187 #endif
190 if ((error = spt_copyenv(envp)))
191 goto error;
193 if ((error = spt_copyargs(argc, argv)))
194 goto error;
196 SPT.nul = nul;
197 SPT.base = base;
198 SPT.end = end;
200 return;
201 syerr:
202 error = errno;
203 error:
204 SPT.error = error;
205 } /* spt_init() */
208 #ifndef SPT_MAXTITLE
209 #define SPT_MAXTITLE 255
210 #endif
212 void setproctitle(const char *fmt, ...) {
213 char buf[SPT_MAXTITLE + 1]; /* use buffer in case argv[0] is passed */
214 va_list ap;
215 char *nul;
216 int len, error;
218 if (!SPT.base)
219 return;
221 if (fmt) {
222 va_start(ap, fmt);
223 len = vsnprintf(buf, sizeof buf, fmt, ap);
224 va_end(ap);
225 } else {
226 len = snprintf(buf, sizeof buf, "%s", SPT.arg0);
229 if (len <= 0)
230 { error = errno; goto error; }
232 if (!SPT.reset) {
233 memset(SPT.base, 0, SPT.end - SPT.base);
234 SPT.reset = 1;
235 } else {
236 memset(SPT.base, 0, spt_min(sizeof buf, SPT.end - SPT.base));
239 len = spt_min(len, spt_min(sizeof buf, SPT.end - SPT.base) - 1);
240 memcpy(SPT.base, buf, len);
241 nul = &SPT.base[len];
243 if (nul < SPT.nul) {
244 *SPT.nul = '.';
245 } else if (nul == SPT.nul && &nul[1] < SPT.end) {
246 *SPT.nul = ' ';
247 *++nul = '\0';
250 return;
251 error:
252 SPT.error = error;
253 } /* setproctitle() */
256 #endif /* __linux || __APPLE__ */
257 #endif /* !HAVE_SETPROCTITLE */