/*
 * $Id: 51a55013fe5ebbe030576a680577fa145ca463c6 $
 *
 * This file is part of nsmtp.
 *
 * Copyright (c) 2007, 2008 Niklas Olmes <niklas@noxa.de>
 *                          http://www.nevm.de/nsmtp/
 *                          NEVM-RIPE
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */

#include "proctitle.h"

#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)

void
initproctitle(int argc __attribute__((unused)), char **argv __attribute__((unused)))
{
	;
}

#elif defined(__linux__)

/*
 * from util-linux-ng-2.13.1.1, license GPLv2
 *      ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

#ifndef SPT_BUFSIZE
#define SPT_BUFSIZE     2048
#endif

extern char **environ;

static char progname[128] = "";
static char **argv0;
static int argv_lth;

void
initproctitle(int argc, char **argv)
{
	int i;
	char **envp = environ;

	if (*progname == '\0')
		(void)snprintf(progname, sizeof(progname), "%s", argv[0]);

	/*
	 * Move the environment so we can reuse the memory.
	 * (Code borrowed from sendmail.)
	 * WARNING: ugly assumptions on memory layout here
	 */
	for (i = 0; envp[i] != NULL; i++)
		continue;
	environ = malloc(sizeof(char *) * (i + 1));
	if (environ == NULL)
		return;
	for (i = 0; envp[i] != NULL; i++)
		if ((environ[i] = strdup(envp[i])) == NULL)
			return;
	environ[i] = NULL;

	argv0 = argv;
	if (i > 0)
		argv_lth = envp[i-1] + strlen(envp[i-1]) - argv0[0];
	else
		argv_lth = argv0[argc-1] + strlen(argv0[argc-1]) - argv0[0];
}

void
setproctitle(const char *fmt, ...)
{
	char buf[SPT_BUFSIZE];
	va_list ap;
	int i, offset;

	if (!argv0)
		return;

	if (fmt == NULL) {
		(void)snprintf(buf, sizeof(buf), "%s", progname);
	} else {
		(void)snprintf(buf, sizeof(buf), "%s: ", progname);
		offset = strlen(buf);

		va_start(ap, fmt);
		(void)vsnprintf(buf + offset, sizeof(buf) - offset, fmt, ap);
		va_end(ap);
	}

	i = strlen(buf);
	if (i > argv_lth - 2) {
		i = argv_lth - 2;
		buf[i] = '\0';
	}
	(void)memset(argv0[0], '\0', argv_lth); /* clear the memory area */
	(void)strncpy(argv0[0], buf, i);
	argv0[1] = NULL;
}

void
setprogname(const char *name)
{

	(void)snprintf(progname, sizeof(progname), "%s", name);
}

const char *
getprogname(void)
{

	return progname;
}

#else

static char progname[128] = "";

void
initproctitle(int argc __attribute__((unused)), char **argv __attribute__((unused)))
{
	;
}

void
setproctitle(const char *fmt __attribute__((unused)))
{
	;
}

void
setprogname(const char *name)
{

	(void)snprintf(progname, sizeof(progname), "%s", name);
}

const char *
getprogname(void)
{

	return progname;
}

#endif
