1/*++
2/* NAME
3/*	fullname 3
4/* SUMMARY
5/*	lookup personal name of invoking user
6/* SYNOPSIS
7/*	#include <fullname.h>
8/*
9/*	const char *fullname()
10/* DESCRIPTION
11/*	fullname() looks up the personal name of the invoking user.
12/*	The result is volatile. Make a copy if it is to be used for
13/*	an appreciable amount of time.
14/*
15/*	On UNIX systems, fullname() first tries to use the NAME environment
16/*	variable, provided that the environment can be trusted.
17/*	If that fails, fullname() extracts the username from the GECOS
18/*	field of the user's password-file entry, replacing any occurrence
19/*	of "&" by the login name, first letter capitalized.
20/*
21/*	A null result means that no full name information was found.
22/* SEE ALSO
23/*	safe_getenv(3) safe getenv() interface
24/* LICENSE
25/* .ad
26/* .fi
27/*	The Secure Mailer license must be distributed with this software.
28/* AUTHOR(S)
29/*	Wietse Venema
30/*	IBM T.J. Watson Research
31/*	P.O. Box 704
32/*	Yorktown Heights, NY 10598, USA
33/*--*/
34
35/* System library. */
36
37#include <sys_defs.h>
38#include <unistd.h>
39#include <pwd.h>
40#include <ctype.h>
41#include <stdlib.h>
42#include <string.h>
43
44/* Utility library. */
45
46#include "vstring.h"
47#include "safe.h"
48#include "fullname.h"
49
50/* fullname - get name of user */
51
52const char *fullname(void)
53{
54    static VSTRING *result;
55    char   *cp;
56    int     ch;
57    uid_t   uid;
58    struct passwd *pwd;
59
60    if (result == 0)
61	result = vstring_alloc(10);
62
63    /*
64     * Try the environment.
65     */
66    if ((cp = safe_getenv("NAME")) != 0)
67	return (vstring_str(vstring_strcpy(result, cp)));
68
69    /*
70     * Try the password file database.
71     */
72    uid = getuid();
73    if ((pwd = getpwuid(uid)) == 0)
74	return (0);
75
76    /*
77     * Replace all `&' characters by the login name of this user, first
78     * letter capitalized. Although the full name comes from the protected
79     * password file, the actual data is specified by the user so we should
80     * not trust its sanity.
81     */
82    VSTRING_RESET(result);
83    for (cp = pwd->pw_gecos; (ch = *(unsigned char *) cp) != 0; cp++) {
84	if (ch == ',' || ch == ';' || ch == '%')
85	    break;
86	if (ch == '&') {
87	    if (pwd->pw_name[0]) {
88		VSTRING_ADDCH(result, TOUPPER(pwd->pw_name[0]));
89		vstring_strcat(result, pwd->pw_name + 1);
90	    }
91	} else {
92	    VSTRING_ADDCH(result, ch);
93	}
94    }
95    VSTRING_TERMINATE(result);
96    return (vstring_str(result));
97}
98
99#ifdef TEST
100
101#include <stdio.h>
102
103int     main(int unused_argc, char **unused_argv)
104{
105    const char *cp = fullname();
106
107    printf("%s\n", cp ? cp : "null!");
108    return (0);
109}
110
111#endif
112