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 * ==========================================================================
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__)
45 #if !HAVE_SETPROCTITLE
46 #if (defined __linux || defined __APPLE__) && defined __GNUC__
53 /* title space available */
56 /* pointer to original nul character within base */
65 #define SPT_MIN(a, b) (((a) < (b))? (a) : (b))
68 static inline size_t spt_min(size_t a
, size_t b
) {
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) {
83 extern char **environ
;
86 if (!(tmp
= malloc(sizeof *tmp
)))
94 } /* spt_clearenv() */
97 static int spt_copyenv(char *oldenv
[]) {
98 extern char **environ
;
102 if (environ
!= oldenv
)
105 if ((error
= spt_clearenv()))
108 for (i
= 0; oldenv
[i
]; i
++) {
109 if (!(eq
= strchr(oldenv
[i
], '=')))
113 error
= (0 != setenv(oldenv
[i
], eq
+ 1, 1))? errno
: 0;
125 } /* spt_copyenv() */
128 static int spt_copyargs(int argc
, char *argv
[]) {
132 for (i
= 1; i
< argc
|| (i
>= argc
&& argv
[i
]); i
++) {
136 if (!(tmp
= strdup(argv
[i
])))
143 } /* spt_copyargs() */
145 void spt_init(int argc
, char *argv
[], char *envp
[]) {
146 char *base
, *end
, *nul
, *tmp
;
149 if (!(base
= argv
[0]))
152 nul
= &base
[strlen(base
)];
155 for (i
= 0; i
< argc
|| (i
>= argc
&& argv
[i
]); i
++) {
156 if (!argv
[i
] || argv
[i
] < end
)
159 end
= argv
[i
] + strlen(argv
[i
]) + 1;
162 for (i
= 0; envp
[i
]; i
++) {
166 end
= envp
[i
] + strlen(envp
[i
]) + 1;
169 if (!(SPT
.arg0
= strdup(argv
[0])))
173 if (!(tmp
= strdup(program_invocation_name
)))
176 program_invocation_name
= tmp
;
178 if (!(tmp
= strdup(program_invocation_short_name
)))
181 program_invocation_short_name
= tmp
;
183 if (!(tmp
= strdup(getprogname())))
190 if ((error
= spt_copyenv(envp
)))
193 if ((error
= spt_copyargs(argc
, argv
)))
209 #define SPT_MAXTITLE 255
212 void setproctitle(const char *fmt
, ...) {
213 char buf
[SPT_MAXTITLE
+ 1]; /* use buffer in case argv[0] is passed */
223 len
= vsnprintf(buf
, sizeof buf
, fmt
, ap
);
226 len
= snprintf(buf
, sizeof buf
, "%s", SPT
.arg0
);
230 { error
= errno
; goto error
; }
233 memset(SPT
.base
, 0, SPT
.end
- SPT
.base
);
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
];
245 } else if (nul
== SPT
.nul
&& &nul
[1] < SPT
.end
) {
253 } /* setproctitle() */
256 #endif /* __linux || __APPLE__ */
257 #endif /* !HAVE_SETPROCTITLE */