1 /*
2  * Originally taken by Andy Igoshin <ai@vsu.ru> from
3  * Sendmail 8.8.8 by Eric Allman <eric@sendmail.org>.
4  * Edited a bit by Dima Maloff for Binkd/0.9.3
5  */
6 /*
7  * $Id: setpttl.c,v 2.3 2003/12/02 13:02:27 gul Exp $
8  *
9  * Revision history:
10  * $Log: setpttl.c,v $
11  * Revision 2.3  2003/12/02 13:02:27  gul
12  * Use own snprintf() instead of sprintf() if no HAVE_SNPRINTF
13  *
14  * Revision 2.2  2003/02/28 20:39:09  gul
15  * Code cleanup:
16  * change "()" to "(void)" in function declarations;
17  * change C++-style comments to C-style
18  *
19  * Revision 2.1  2001/10/27 08:31:30  gul
20  * minor fix
21  *
22  * Revision 2.0  2001/01/10 12:12:40  gul
23  * Binkd is under CVS again
24  *
25  *
26  */
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <stdarg.h>
31 #include <string.h>
32 
33 /*
34  * First -- map autoconf's values to sendmail's
35  */
36 #ifdef HAVE_SETPROCTITLE /* We have built-in setproctitle() */
37   #define SPT_TYPE SPT_BUILTIN
38 #endif
39 
40 /*
41  * (xalloc.c) allocate memory or log error
42  */
43 extern void *xalloc (size_t size);
44 extern void *xstrdup (const char *str);
45 
46 
47 #define MAXLINE	2048
48 #define SPACELEFT(buf, ptr)     (sizeof buf - ((ptr) - buf))
49 
50 
51 /*
52 **  SETPROCTITLE -- set process title for ps
53 **
54 **	Parameters:
55 **		fmt -- a printf style format string.
56 **		a, b, c -- possible parameters to fmt.
57 **
58 **	Returns:
59 **		none.
60 **
61 **	Side Effects:
62 **		Clobbers argv of our main procedure so ps(1) will
63 **		display the title.
64 */
65 
66 #define SPT_NONE	0	/* don't use it at all */
67 #define SPT_REUSEARGV	1	/* cover argv with title information */
68 #define SPT_BUILTIN	2	/* use libc builtin */
69 #define SPT_PSTAT	3	/* use pstat(PSTAT_SETCMD, ...) */
70 #define SPT_PSSTRINGS	4	/* use PS_STRINGS->... */
71 #define SPT_SYSMIPS	5	/* use sysmips() supported by NEWS-OS 6 */
72 #define SPT_SCO		6	/* write kernel u. area */
73 #define SPT_CHANGEARGV	7	/* write our own strings into argv[] */
74 
75 #ifndef SPT_TYPE
76 # define SPT_TYPE	SPT_REUSEARGV
77 #endif
78 
79 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
80 
81 # if SPT_TYPE == SPT_PSTAT
82 #  include <sys/pstat.h>
83 # endif
84 # if SPT_TYPE == SPT_PSSTRINGS
85 #  include <machine/vmparam.h>
86 #  include <sys/exec.h>
87 #  ifndef PS_STRINGS	/* hmmmm....  apparently not available after all */
88 #   undef SPT_TYPE
89 #   define SPT_TYPE	SPT_REUSEARGV
90 #  else
91 #   ifndef NKPDE			/* FreeBSD 2.0 */
92 #    define NKPDE 63
93 typedef unsigned int	*pt_entry_t;
94 #   endif
95 #  endif
96 # endif
97 
98 # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
99 #  define SETPROC_STATIC	static
100 # else
101 #  define SETPROC_STATIC
102 # endif
103 
104 # if SPT_TYPE == SPT_SYSMIPS
105 #  include <sys/sysmips.h>
106 #  include <sys/sysnews.h>
107 # endif
108 
109 # if SPT_TYPE == SPT_SCO
110 #  include <sys/immu.h>
111 #  include <sys/dir.h>
112 #  include <sys/user.h>
113 #  include <sys/fs/s5param.h>
114 #  if PSARGSZ > MAXLINE
115 #   define SPT_BUFSIZE	PSARGSZ
116 #  endif
117 # endif
118 
119 # ifndef SPT_PADCHAR
120 /*#  define SPT_PADCHAR	' ' */
121 #  define SPT_PADCHAR	'\0'
122 # endif
123 
124 # ifndef SPT_BUFSIZE
125 #  define SPT_BUFSIZE	MAXLINE
126 # endif
127 
128 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
129 
130 /*
131 **  Pointers for setproctitle.
132 **	This allows "ps" listings to give more useful information.
133 */
134 
135 char		**Argv = NULL;		/* pointer to argument vector */
136 char		*LastArgv = NULL;	/* end of argv */
137 
138 void
initsetproctitle(argc,argv,envp)139 initsetproctitle(argc, argv, envp)
140 	int argc;
141 	char **argv;
142 	char **envp;
143 {
144 	register int i, envpsize = 0;
145 	extern char **environ;
146 
147 	/*
148 	**  Move the environment so setproctitle can use the space at
149 	**  the top of memory.
150 	*/
151 
152 	for (i = 0; envp[i] != NULL; i++)
153 		envpsize += strlen(envp[i]) + 1;
154 	environ = (char **) xalloc(sizeof (char *) * (i + 1));
155 	for (i = 0; envp[i] != NULL; i++)
156 		environ[i] = xstrdup(envp[i]);
157 	environ[i] = NULL;
158 
159 	/*
160 	**  Save start and extent of argv for setproctitle.
161 	*/
162 
163 	Argv = argv;
164 
165 	/*
166 	**  Find the last environment variable within sendmail's
167 	**  process memory area.
168 	*/
169 	while (i > 0 && (envp[i - 1] < argv[0] ||
170 			 envp[i - 1] > (argv[argc - 1] +
171 					strlen(argv[argc - 1]) + 1 + envpsize)))
172 		i--;
173 
174 	if (i > 0)
175 		LastArgv = envp[i - 1] + strlen(envp[i - 1]);
176 	else
177 		LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
178 }
179 
180 #if SPT_TYPE != SPT_BUILTIN
181 
182 
setproctitle(const char * fmt,...)183 void setproctitle(const char *fmt, ...)
184 {
185 # if SPT_TYPE != SPT_NONE
186 	register char *p;
187 	register int i;
188 	SETPROC_STATIC char buf[SPT_BUFSIZE];
189 	va_list ap;
190 #  if SPT_TYPE == SPT_PSTAT
191 	union pstun pst;
192 #  endif
193 #  if SPT_TYPE == SPT_SCO
194 	off_t seek_off;
195 	static int kmem = -1;
196 	static int kmempid = -1;
197 	struct user u;
198 #  endif
199 
200 	p = buf;
201 
202 	/* print sendmail: heading for grep */
203 	(void) strcpy(p, "binkd: ");
204 	p += strlen(p);
205 
206 	/* print the argument string */
207 	va_start(ap, fmt);
208 	(void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
209 	va_end(ap);
210 
211 	i = strlen(buf);
212 
213 #  if SPT_TYPE == SPT_PSTAT
214 	pst.pst_command = buf;
215 	pstat(PSTAT_SETCMD, pst, i, 0, 0);
216 #  endif
217 #  if SPT_TYPE == SPT_PSSTRINGS
218 	PS_STRINGS->ps_nargvstr = 1;
219 	PS_STRINGS->ps_argvstr = buf;
220 #  endif
221 #  if SPT_TYPE == SPT_SYSMIPS
222 	sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
223 #  endif
224 #  if SPT_TYPE == SPT_SCO
225 	if (kmem < 0 || kmempid != getpid())
226 	{
227 		if (kmem >= 0)
228 			close(kmem);
229 		kmem = open(_PATH_KMEM, O_RDWR, 0);
230 		if (kmem < 0)
231 			return;
232 		(void) fcntl(kmem, F_SETFD, 1);
233 		kmempid = getpid();
234 	}
235 	buf[PSARGSZ - 1] = '\0';
236 	seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
237 	if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
238 		(void) write(kmem, buf, PSARGSZ);
239 #  endif
240 #  if SPT_TYPE == SPT_REUSEARGV
241 	if (LastArgv == NULL)
242 		return;
243 
244 	if (i > LastArgv - Argv[0] - 2)
245 	{
246 		i = LastArgv - Argv[0] - 2;
247 		buf[i] = '\0';
248 	}
249 	(void) strcpy(Argv[0], buf);
250 	p = &Argv[0][i];
251 	while (p < LastArgv)
252 		*p++ = SPT_PADCHAR;
253 	Argv[1] = NULL;
254 #  endif
255 #  if SPT_TYPE == SPT_CHANGEARGV
256 	Argv[0] = buf;
257 	Argv[1] = 0;
258 #  endif
259 # endif /* SPT_TYPE != SPT_NONE */
260 }
261 
262 #endif /* SPT_TYPE != SPT_BUILTIN */
263