/*
** mts.c -- definitions for the mail transport system
**
** This code is Copyright (c) 2002, by the authors of nmh.  See the
** COPYRIGHT file in the root directory of the nmh distribution for
** complete copyright information.
*/

#include <h/mh.h>   /* for snprintf() */
#include <h/utils.h>
#include <ctype.h>
#include <stdio.h>
#include <pwd.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

/*
** static prototypes
*/
static void getuserinfo(void);

/* Cache the username and fullname of the user */
static char username[BUFSIZ];
static char fullname[BUFSIZ];


/*
** Get the fully qualified name of the local host.
*/
char *
LocalName(void)
{
	static char buffer[BUFSIZ] = "";
	struct addrinfo hints, *res;

	/* check if we have cached the local name */
	if (buffer[0])
		return buffer;

	memset(buffer, 0, sizeof(buffer));
	/* first get our local name */
	gethostname(buffer, sizeof(buffer) - 1);

	/* now fully qualify our name */
	memset(&hints, 0, sizeof(hints));
	hints.ai_flags = AI_CANONNAME;
	hints.ai_family = PF_UNSPEC;
	if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
		strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
		freeaddrinfo(res);
	}

	return buffer;
}


/*
** Get the username of current user
*/
char *
getusername(void)
{
	if (username[0] == '\0')
		getuserinfo();

	return username;
}


/*
** Get full name of current user (typically from GECOS
** field of password file).
*/
char *
getfullname(void)
{
	if (username[0] == '\0')
		getuserinfo();

	return fullname;
}


/*
** Find the user's username and full name, and cache them.
*/
static void
getuserinfo(void)
{
	unsigned char *cp;
	char *np;
	struct passwd *pw;
	int needquotes = 0;
	char tmp[BUFSIZ];
	char *tp;

	if (!(pw = getpwuid(getuid())) || !pw->pw_name || !*pw->pw_name) {
		strncpy(username, "unknown", sizeof(username));
		snprintf(fullname, sizeof(fullname),
				"The Unknown User-ID (%d)", (int)getuid());
		return;
	}

	np = pw->pw_gecos;

	/*
	** Get the user's real name from the GECOS field.  Stop once
	** we hit a ',', which some OSes use to separate other 'finger'
	** information in the GECOS field, like phone number.
	*/
	for (cp = tmp; *np != '\0' && *np != ',';) {
		*cp++ = *np++;
	}
	*cp = '\0';
	strncpy(username, pw->pw_name, sizeof(username));

	/*
	** The $SIGNATURE environment variable overrides the GECOS field's
	** idea of your real name.
	*/
	if ((cp = getenv("SIGNATURE")) && *cp)
		strncpy(tmp, cp, sizeof(tmp));

	/* quote the fullname as needed */
	needquotes = 0;
	for (tp=tmp; *tp; tp++) {
		switch (*tp) {
		case '(': case ')': case '<': case '>': case '[': case ']':
		case ':': case ';': case '@': case '\\': case ',': case '.':
		case '"':  /* cf. RFC 5322 */
			break;  /* ... the switch */
		default:
			continue;  /* ... the loop */
		}
		/* we've found a special char */
		needquotes = 1;
		break;
	}
	cp=fullname;
	if (needquotes) {
		*cp++ = '"';
	}
	for (tp=tmp; *tp; *cp++=*tp++) {
		if (*tp == '"') {
			*cp++ = '\\';  /* prepend backslash */
		}
	}
	if (needquotes) {
		*cp++ = '"';
	}
	*cp = '\0';

	return;
}
