]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/gen/setproctitle.c
Update opencsd to 0.14.2
[FreeBSD/FreeBSD.git] / lib / libc / gen / setproctitle.c
1 /*
2  * Copyright (c) 1995 Peter Wemm <peter@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, is permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice immediately at the beginning of the file, without modification,
10  *    this list of conditions, and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Absolutely no warranty of function or purpose is made by the author
15  *    Peter Wemm.
16  */
17
18 #include <sys/cdefs.h>
19 __FBSDID("$FreeBSD$");
20
21 #include "namespace.h"
22 #include <sys/param.h>
23 #include <sys/elf_common.h>
24 #include <sys/exec.h>
25 #include <sys/sysctl.h>
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include "un-namespace.h"
32
33 #include "libc_private.h"
34
35 /*
36  * Older FreeBSD 2.0, 2.1 and 2.2 had different ps_strings structures and
37  * in different locations.
38  * 1: old_ps_strings at the very top of the stack.
39  * 2: old_ps_strings at SPARE_USRSPACE below the top of the stack.
40  * 3: ps_strings at the very top of the stack.
41  * We only support a kernel providing #3 style ps_strings.
42  *
43  * For historical purposes, a definition of the old ps_strings structure
44  * and location is preserved below:
45 struct old_ps_strings {
46         char    *old_ps_argvstr;
47         int     old_ps_nargvstr;
48         char    *old_ps_envstr;
49         int     old_ps_nenvstr;
50 };
51 #define OLD_PS_STRINGS ((struct old_ps_strings *) \
52         (USRSTACK - SPARE_USRSPACE - sizeof(struct old_ps_strings)))
53  */
54
55 #include <stdarg.h>
56
57 #define SPT_BUFSIZE 2048        /* from other parts of sendmail */
58
59 static char *
60 setproctitle_internal(const char *fmt, va_list ap)
61 {
62         static struct ps_strings *ps_strings;
63         static char *buf = NULL;
64         static char *obuf = NULL;
65         static char **oargv, *kbuf;
66         static int oargc = -1;
67         static char *nargv[2] = { NULL, NULL };
68         char **nargvp;
69         int nargc;
70         int i;
71         size_t len;
72         unsigned long ul_ps_strings;
73
74         if (buf == NULL) {
75                 buf = malloc(SPT_BUFSIZE);
76                 if (buf == NULL)
77                         return (NULL);
78                 nargv[0] = buf;
79         }
80
81         if (obuf == NULL ) {
82                 obuf = malloc(SPT_BUFSIZE);
83                 if (obuf == NULL)
84                         return (NULL);
85                 *obuf = '\0';
86         }
87
88         if (fmt) {
89                 buf[SPT_BUFSIZE - 1] = '\0';
90
91                 if (fmt[0] == '-') {
92                         /* skip program name prefix */
93                         fmt++;
94                         len = 0;
95                 } else {
96                         /* print program name heading for grep */
97                         (void)snprintf(buf, SPT_BUFSIZE, "%s: ", _getprogname());
98                         len = strlen(buf);
99                 }
100
101                 /* print the argument string */
102                 (void)vsnprintf(buf + len, SPT_BUFSIZE - len, fmt, ap);
103
104                 nargvp = nargv;
105                 nargc = 1;
106                 kbuf = buf;
107         } else if (*obuf != '\0') {
108                 /* Idea from NetBSD - reset the title on fmt == NULL */
109                 nargvp = oargv;
110                 nargc = oargc;
111                 kbuf = obuf;
112         } else
113                 /* Nothing to restore */
114                 return (NULL);
115
116         if (ps_strings == NULL)
117                 (void)_elf_aux_info(AT_PS_STRINGS, &ps_strings,
118                     sizeof(ps_strings));
119
120         if (ps_strings == NULL) {
121                 len = sizeof(ul_ps_strings);
122                 if (sysctlbyname("kern.ps_strings", &ul_ps_strings, &len, NULL,
123                     0) == -1)
124                         return (NULL);
125                 ps_strings = (struct ps_strings *)ul_ps_strings;
126         }
127
128         if (ps_strings == NULL)
129                 return (NULL);
130
131         /*
132          * PS_STRINGS points to zeroed memory on a style #2 kernel.
133          * Should not happen.
134          */
135         if (ps_strings->ps_argvstr == NULL)
136                 return (NULL);
137
138         /* style #3 */
139         if (oargc == -1) {
140                 /* Record our original args */
141                 oargc = ps_strings->ps_nargvstr;
142                 oargv = ps_strings->ps_argvstr;
143                 for (i = len = 0; i < oargc; i++) {
144                         /*
145                          * The program may have scribbled into its
146                          * argv array, e.g., to remove some arguments.
147                          * If that has happened, break out before
148                          * trying to call strlen on a NULL pointer.
149                          */
150                         if (oargv[i] == NULL) {
151                                 oargc = i;
152                                 break;
153                         }
154                         snprintf(obuf + len, SPT_BUFSIZE - len, "%s%s",
155                             len != 0 ? " " : "", oargv[i]);
156                         if (len != 0)
157                                 len++;
158                         len += strlen(oargv[i]);
159                         if (len >= SPT_BUFSIZE)
160                                 break;
161                 }
162         }
163         ps_strings->ps_nargvstr = nargc;
164         ps_strings->ps_argvstr = nargvp;
165
166         return (nargvp[0]);
167 }
168
169 static int fast_update = 0;
170
171 void
172 setproctitle_fast(const char *fmt, ...)
173 {
174         va_list ap;
175         char *buf;
176         int oid[4];
177
178         va_start(ap, fmt);
179         buf = setproctitle_internal(fmt, ap);
180         va_end(ap);
181
182         if (buf && !fast_update) {
183                 /* Tell the kernel to start looking in user-space */
184                 oid[0] = CTL_KERN;
185                 oid[1] = KERN_PROC;
186                 oid[2] = KERN_PROC_ARGS;
187                 oid[3] = getpid();
188                 sysctl(oid, 4, 0, 0, "", 0);
189                 fast_update = 1;
190         }
191 }
192
193 void
194 setproctitle(const char *fmt, ...)
195 {
196         va_list ap;
197         char *buf;
198         int oid[4];
199
200         va_start(ap, fmt);
201         buf = setproctitle_internal(fmt, ap);
202         va_end(ap);
203
204         if (buf != NULL) {
205                 /* Set the title into the kernel cached command line */
206                 oid[0] = CTL_KERN;
207                 oid[1] = KERN_PROC;
208                 oid[2] = KERN_PROC_ARGS;
209                 oid[3] = getpid();
210                 sysctl(oid, 4, 0, 0, buf, strlen(buf) + 1);
211                 fast_update = 0;
212         }
213 }