1124208Sdes/* Based on conf.c from UCB sendmail 8.8.8 */
2124208Sdes
398937Sdes/*
4124208Sdes * Copyright 2003 Damien Miller
5124208Sdes * Copyright (c) 1983, 1995-1997 Eric P. Allman
6124208Sdes * Copyright (c) 1988, 1993
7124208Sdes *	The Regents of the University of California.  All rights reserved.
898937Sdes *
9124208Sdes * Redistribution and use in source and binary forms, with or without
10124208Sdes * modification, are permitted provided that the following conditions
11124208Sdes * are met:
12124208Sdes * 1. Redistributions of source code must retain the above copyright
13124208Sdes *    notice, this list of conditions and the following disclaimer.
14124208Sdes * 2. Redistributions in binary form must reproduce the above copyright
15124208Sdes *    notice, this list of conditions and the following disclaimer in the
16124208Sdes *    documentation and/or other materials provided with the distribution.
17124208Sdes * 3. Neither the name of the University nor the names of its contributors
18124208Sdes *    may be used to endorse or promote products derived from this software
19124208Sdes *    without specific prior written permission.
2098937Sdes *
21124208Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22124208Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23124208Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24124208Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25124208Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26124208Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27124208Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28124208Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29124208Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30124208Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31124208Sdes * SUCH DAMAGE.
3298937Sdes */
3398937Sdes
3498937Sdes#include "includes.h"
3598937Sdes
3698937Sdes#ifndef HAVE_SETPROCTITLE
3798937Sdes
38162852Sdes#include <stdarg.h>
39162852Sdes#include <stdlib.h>
40113908Sdes#include <unistd.h>
41113908Sdes#ifdef HAVE_SYS_PSTAT_H
42124208Sdes#include <sys/pstat.h>
43113908Sdes#endif
44162852Sdes#include <string.h>
4598937Sdes
46181111Sdes#include <vis.h>
47181111Sdes
48124208Sdes#define SPT_NONE	0	/* don't use it at all */
49126274Sdes#define SPT_PSTAT	1	/* use pstat(PSTAT_SETCMD, ...) */
50126274Sdes#define SPT_REUSEARGV	2	/* cover argv with title information */
51113908Sdes
52124208Sdes#ifndef SPT_TYPE
53124208Sdes# define SPT_TYPE	SPT_NONE
5498937Sdes#endif
5598937Sdes
56124208Sdes#ifndef SPT_PADCHAR
57124208Sdes# define SPT_PADCHAR	'\0'
58113908Sdes#endif
5998937Sdes
60124208Sdes#if SPT_TYPE == SPT_REUSEARGV
61124208Sdesstatic char *argv_start = NULL;
62124208Sdesstatic size_t argv_env_len = 0;
63113908Sdes#endif
64113908Sdes
65124208Sdes#endif /* HAVE_SETPROCTITLE */
66113908Sdes
6798937Sdesvoid
68124208Sdescompat_init_setproctitle(int argc, char *argv[])
6998937Sdes{
70263970Sdes#if !defined(HAVE_SETPROCTITLE) && \
71263970Sdes    defined(SPT_TYPE) && SPT_TYPE == SPT_REUSEARGV
72124208Sdes	extern char **environ;
73124208Sdes	char *lastargv = NULL;
74124208Sdes	char **envp = environ;
75124208Sdes	int i;
7698937Sdes
77113908Sdes	/*
78124208Sdes	 * NB: This assumes that argv has already been copied out of the
79124208Sdes	 * way. This is true for sshd, but may not be true for other
80124208Sdes	 * programs. Beware.
81113908Sdes	 */
82113908Sdes
83124208Sdes	if (argc == 0 || argv[0] == NULL)
84124208Sdes		return;
85113908Sdes
86124208Sdes	/* Fail if we can't allocate room for the new environment */
87124208Sdes	for (i = 0; envp[i] != NULL; i++)
88124208Sdes		;
89162852Sdes	if ((environ = calloc(i + 1, sizeof(*environ))) == NULL) {
90124208Sdes		environ = envp;	/* put it back */
91124208Sdes		return;
92124208Sdes	}
93124208Sdes
94113908Sdes	/*
95124208Sdes	 * Find the last argv string or environment variable within
96124208Sdes	 * our process memory area.
97113908Sdes	 */
98124208Sdes	for (i = 0; i < argc; i++) {
99124208Sdes		if (lastargv == NULL || lastargv + 1 == argv[i])
100124208Sdes			lastargv = argv[i] + strlen(argv[i]);
101113908Sdes	}
102124208Sdes	for (i = 0; envp[i] != NULL; i++) {
103124208Sdes		if (lastargv + 1 == envp[i])
104124208Sdes			lastargv = envp[i] + strlen(envp[i]);
105124208Sdes	}
10698937Sdes
107124208Sdes	argv[1] = NULL;
108124208Sdes	argv_start = argv[0];
109124208Sdes	argv_env_len = lastargv - argv[0] - 1;
11098937Sdes
111124208Sdes	/*
112124208Sdes	 * Copy environment
113124208Sdes	 * XXX - will truncate env on strdup fail
114124208Sdes	 */
115124208Sdes	for (i = 0; envp[i] != NULL; i++)
116124208Sdes		environ[i] = strdup(envp[i]);
117124208Sdes	environ[i] = NULL;
118124208Sdes#endif /* SPT_REUSEARGV */
11998937Sdes}
120113908Sdes
121124208Sdes#ifndef HAVE_SETPROCTITLE
122113908Sdesvoid
123124208Sdessetproctitle(const char *fmt, ...)
124113908Sdes{
125124208Sdes#if SPT_TYPE != SPT_NONE
126124208Sdes	va_list ap;
127181111Sdes	char buf[1024], ptitle[1024];
128124208Sdes	size_t len;
129263970Sdes	int r;
130124208Sdes	extern char *__progname;
131124208Sdes#if SPT_TYPE == SPT_PSTAT
132124208Sdes	union pstun pst;
133113908Sdes#endif
134113908Sdes
135124208Sdes#if SPT_TYPE == SPT_REUSEARGV
136124208Sdes	if (argv_env_len <= 0)
137124208Sdes		return;
138124208Sdes#endif
139113908Sdes
140124208Sdes	strlcpy(buf, __progname, sizeof(buf));
141113908Sdes
142263970Sdes	r = -1;
143124208Sdes	va_start(ap, fmt);
144124208Sdes	if (fmt != NULL) {
145124208Sdes		len = strlcat(buf, ": ", sizeof(buf));
146124208Sdes		if (len < sizeof(buf))
147263970Sdes			r = vsnprintf(buf + len, sizeof(buf) - len , fmt, ap);
148113908Sdes	}
149124208Sdes	va_end(ap);
150263970Sdes	if (r == -1 || (size_t)r >= sizeof(buf) - len)
151263970Sdes		return;
152181111Sdes	strnvis(ptitle, buf, sizeof(ptitle),
153181111Sdes	    VIS_CSTYLE|VIS_NL|VIS_TAB|VIS_OCTAL);
154113908Sdes
155124208Sdes#if SPT_TYPE == SPT_PSTAT
156181111Sdes	pst.pst_command = ptitle;
157181111Sdes	pstat(PSTAT_SETCMD, pst, strlen(ptitle), 0, 0);
158124208Sdes#elif SPT_TYPE == SPT_REUSEARGV
159124208Sdes/*	debug("setproctitle: copy \"%s\" into len %d",
160124208Sdes	    buf, argv_env_len); */
161181111Sdes	len = strlcpy(argv_start, ptitle, argv_env_len);
162124208Sdes	for(; len < argv_env_len; len++)
163124208Sdes		argv_start[len] = SPT_PADCHAR;
164124208Sdes#endif
165113908Sdes
166124208Sdes#endif /* SPT_NONE */
167113908Sdes}
168113908Sdes
169124208Sdes#endif /* HAVE_SETPROCTITLE */
170