1 /*
2  * setproctitle()-related routines in this file are derived from Sendmail
3  * 8.13.5 which is:
4  *
5  * Copyright (c) 1998-2005 Sendmail, Inc. and its suppliers.
6  *      All rights reserved.
7  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
8  * Copyright (c) 1988, 1993
9  *      The Regents of the University of California.  All rights reserved.
10  *
11  * By using this file, you agree to the terms and conditions set
12  * forth in the LICENSE file which can be found at the top level of
13  * the sendmail distribution.
14  *
15  */
16 
17 #include "pmacct.h"
18 
19 /*
20  *  SETPROCTITLE -- set process title for ps
21 */
22 
23 #define SPT_NONE	0	/* don't use it at all */
24 #define SPT_REUSEARGV	1	/* cover argv with title information */
25 #define SPT_BUILTIN	2	/* use libc builtin */
26 #define SPT_PSTAT	3	/* use pstat(PSTAT_SETCMD, ...) */
27 
28 #include "setproctitle.h"
29 
30 #define MAXLINE (2*LONGLONGSRVBUFLEN)
31 #define SPACELEFT(x) (sizeof(x)-strlen(x))
32 
33 #if defined PROGNAME && SPT_TYPE == SPT_REUSEARGV
34 extern char *__progname;
35 #endif
36 
37 char pmacctd_globstr[] = "pmacctd\0";
38 char nfacctd_globstr[] = "nfacctd\0";
39 char sfacctd_globstr[] = "sfacctd\0";
40 char uacctd_globstr[] = "uacctd\0";
41 char pmtele_globstr[] = "pmtelemetryd\0";
42 char pmbgpd_globstr[] = "pmbgpd\0";
43 char pmbmpd_globstr[] = "pmbmpd\0";
44 
45 /*
46  * NEWSTR -- Create a copy of a C string
47  */
48 
spt_newstr(s)49 char *spt_newstr(s)
50 const char *s;
51 {
52   size_t l;
53   char *n;
54 
55   l = strlen(s);
56   n = malloc(l + 1);
57   strlcpy(n, s, l + 1);
58 
59   return n;
60 }
61 
62 #ifndef SPT_TYPE
63 #  define SPT_TYPE	SPT_NONE
64 #endif /* ! SPT_TYPE */
65 
66 
67 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
68 
69 #if SPT_TYPE == SPT_PSTAT
70 #  include <sys/pstat.h>
71 #endif /* SPT_TYPE == SPT_PSTAT */
72 
73 #ifndef SPT_PADCHAR
74 #  define SPT_PADCHAR	' '
75 #endif /* ! SPT_PADCHAR */
76 
77 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
78 
79 #ifndef SPT_BUFSIZE
80 #  define SPT_BUFSIZE	MAXLINE
81 #endif /* ! SPT_BUFSIZE */
82 
83 /*
84  *  Pointers for setproctitle.
85  *	This allows "ps" listings to give more useful information.
86  */
87 
88 static char	**Argv = NULL;		/* pointer to argument vector */
89 static char	*LastArgv = NULL;	/* end of argv */
90 
91 void
initsetproctitle(argc,argv,envp)92 initsetproctitle(argc, argv, envp)
93 	int argc;
94 	char **argv;
95 	char **envp;
96 {
97 	register int i;
98 	extern char **environ;
99 
100 	/*
101 	**  Move the environment so setproctitle can use the space at
102 	**  the top of memory.
103 	*/
104 
105 	if (envp != NULL)
106 	{
107 		for (i = 0; envp[i] != NULL; i++)
108 			continue;
109 		environ = (char **) malloc(sizeof (char *) * (i + 1));
110 		for (i = 0; envp[i] != NULL; i++)
111 			environ[i] = spt_newstr(envp[i]);
112 		environ[i] = NULL;
113 	}
114 
115 	/*
116 	**  Save start and extent of argv for setproctitle.
117 	*/
118 
119 	Argv = argv;
120 
121 	/*
122 	**  Determine how much space we can use for setproctitle.
123 	**  Use all contiguous argv and envp pointers starting at argv[0]
124 	*/
125 
126 	for (i = 0; i < argc; i++)
127 	{
128 		if (i == 0 || LastArgv + 1 == argv[i])
129 			LastArgv = argv[i] + strlen(argv[i]);
130 	}
131 	for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++)
132 	{
133 		if (LastArgv + 1 == envp[i])
134 			LastArgv = envp[i] + strlen(envp[i]);
135 	}
136 
137 #if defined PROGNAME && SPT_TYPE == SPT_REUSEARGV
138 	if (config.uacctd_group) __progname = uacctd_globstr; /* XXX: hack */
139 	else if (config.acct_type == ACCT_PM) __progname = pmacctd_globstr;
140 	else if (config.acct_type == ACCT_NF) __progname = nfacctd_globstr;
141 	else if (config.acct_type == ACCT_SF) __progname = sfacctd_globstr;
142 	else if (config.acct_type == ACCT_PMTELE) __progname = pmtele_globstr;
143 	else if (config.acct_type == ACCT_PMBGP) __progname = pmbgpd_globstr;
144 	else if (config.acct_type == ACCT_PMBMP) __progname = pmbmpd_globstr;
145 #endif
146 }
147 
148 #if SPT_TYPE != SPT_BUILTIN
149 
150 /*VARARGS1*/
151 static void
152 # ifdef __STDC__
setproctitle(const char * fmt,...)153 setproctitle(const char *fmt, ...)
154 # else /* __STDC__ */
155 setproctitle(fmt, va_alist)
156 	const char *fmt;
157 	va_dcl
158 # endif /* __STDC__ */
159 {
160 # if SPT_TYPE != SPT_NONE
161 	register int i;
162 	register char *p;
163 	char buf[SPT_BUFSIZE];
164 	va_list ap;
165 #  if SPT_TYPE == SPT_PSTAT
166 	union pstun pst;
167 #  endif /* SPT_TYPE == SPT_PSTAT */
168 
169 	memset(buf, 0, SPT_BUFSIZE);
170 	p = buf;
171 	va_start(ap, fmt);
172 	vsnprintf(p, SPACELEFT(buf), fmt, ap);
173 	va_end(ap);
174 
175 	i = (int) strlen(buf);
176 	if (i < 0) return;
177 
178 #  if SPT_TYPE == SPT_PSTAT
179 	pst.pst_command = buf;
180 	pstat(PSTAT_SETCMD, pst, i, 0, 0);
181 #  endif /* SPT_TYPE == SPT_PSTAT */
182 #  if SPT_TYPE == SPT_REUSEARGV
183 	if (LastArgv == NULL)
184 		return;
185 
186 	if (i > (LastArgv - Argv[0]) - 2)
187 	{
188 		i = (LastArgv - Argv[0]) - 2;
189 		buf[i] = '\0';
190 	}
191 	(void) strlcpy(Argv[0], buf, i + 1);
192 	p = &Argv[0][i];
193 	while (p < LastArgv)
194 		*p++ = SPT_PADCHAR;
195 	Argv[1] = NULL;
196 #  endif /* SPT_TYPE == SPT_REUSEARGV */
197 # endif /* SPT_TYPE != SPT_NONE */
198 }
199 
200 #endif /* SPT_TYPE != SPT_BUILTIN */
201 /*
202  *  PM_SETPROCTITLE -- set process task and set process title for ps
203  */
204 
205 /*VARARGS2*/
206 void
207 #ifdef __STDC__
pm_setproctitle(const char * fmt,...)208 pm_setproctitle(const char *fmt, ...)
209 #else /* __STDC__ */
210 pm_setproctitle(fmt, va_alist)
211   const char *fmt;
212   va_dcl
213 #endif /* __STDC__ */
214 {
215   char buf[SPT_BUFSIZE];
216   char prefix[16];
217   va_list ap;
218 
219   memset(prefix, 0, sizeof(prefix));
220   memset(buf, 0, sizeof(buf));
221 
222   if (config.uacctd_group) strcpy(prefix, uacctd_globstr); /* XXX: hack */
223   else if (config.acct_type == ACCT_PM) strcpy(prefix, pmacctd_globstr);
224   else if (config.acct_type == ACCT_NF) strcpy(prefix, nfacctd_globstr);
225   else if (config.acct_type == ACCT_SF) strcpy(prefix, sfacctd_globstr);
226   else if (config.acct_type == ACCT_PMTELE) strcpy(prefix, pmtele_globstr);
227   else if (config.acct_type == ACCT_PMBGP) strcpy(prefix, pmbgpd_globstr);
228   else if (config.acct_type == ACCT_PMBMP) strcpy(prefix, pmbmpd_globstr);
229 
230   va_start(ap, fmt);
231   vsnprintf(buf, sizeof(buf), fmt, ap);
232   va_end(ap);
233 
234 #if SPT_TYPE != SPT_BUILTIN
235   setproctitle("%s: %s", prefix, buf);
236 #else
237   setproctitle("%s", buf);
238 #endif
239 }
240 
241