Remove OS-specific defines. Remove GECOS ampersand-magic, along with it.
[mmh] / sbr / mts.c
1 /*
2 ** mts.c -- definitions for the mail transport system
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>   /* for snprintf() */
10 #include <h/nmh.h>
11 #include <h/utils.h>
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <pwd.h>
15 #include <netdb.h>
16
17 #define NOTOK  (-1)
18 #define OK     0
19
20 /*
21 ** static prototypes
22 */
23 static void getuserinfo(void);
24
25 /* Cache the username and fullname of the user */
26 static char username[BUFSIZ];
27 static char fullname[BUFSIZ];
28
29
30 /*
31 ** Get the fully qualified name of the local host.
32 */
33 char *
34 LocalName(void)
35 {
36         static char buffer[BUFSIZ] = "";
37         struct addrinfo hints, *res;
38
39         /* check if we have cached the local name */
40         if (buffer[0])
41                 return buffer;
42
43         memset(buffer, 0, sizeof(buffer));
44         /* first get our local name */
45         gethostname(buffer, sizeof(buffer) - 1);
46
47         /* now fully qualify our name */
48         memset(&hints, 0, sizeof(hints));
49         hints.ai_flags = AI_CANONNAME;
50         hints.ai_family = PF_UNSPEC;
51         if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
52                 strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
53                 freeaddrinfo(res);
54         }
55
56         return buffer;
57 }
58
59
60 /*
61 ** Get the username of current user
62 */
63 char *
64 getusername(void)
65 {
66         if (username[0] == '\0')
67                 getuserinfo();
68
69         return username;
70 }
71
72
73 /*
74 ** Get full name of current user (typically from GECOS
75 ** field of password file).
76 */
77 char *
78 getfullname(void)
79 {
80         if (username[0] == '\0')
81                 getuserinfo();
82
83         return fullname;
84 }
85
86
87 /*
88 ** Find the user's username and full name, and cache them.
89 */
90 static void
91 getuserinfo(void)
92 {
93         unsigned char *cp;
94         char *np;
95         struct passwd *pw;
96         int needquotes = 0;
97         char tmp[BUFSIZ];
98         char *tp;
99
100         if (!(pw = getpwuid(getuid())) || !pw->pw_name || !*pw->pw_name) {
101                 strncpy(username, "unknown", sizeof(username));
102                 snprintf(fullname, sizeof(fullname),
103                                 "The Unknown User-ID (%d)", (int)getuid());
104                 return;
105         }
106
107         np = pw->pw_gecos;
108
109         /*
110         ** Get the user's real name from the GECOS field.  Stop once
111         ** we hit a ',', which some OSes use to separate other 'finger'
112         ** information in the GECOS field, like phone number.
113         */
114         for (cp = tmp; *np != '\0' && *np != ',';) {
115                 *cp++ = *np++;
116         }
117         *cp = '\0';
118         strncpy(username, pw->pw_name, sizeof(username));
119
120         /*
121         ** The $SIGNATURE environment variable overrides the GECOS field's
122         ** idea of your real name.
123         */
124         if ((cp = getenv("SIGNATURE")) && *cp)
125                 strncpy(tmp, cp, sizeof(tmp));
126
127         /* quote the fullname as needed */
128         needquotes = 0;
129         for (tp=tmp; *tp; tp++) {
130                 switch (*tp) {
131                 case '(': case ')': case '<': case '>': case '[': case ']':
132                 case ':': case ';': case '@': case '\\': case ',': case '.':
133                 case '"':  /* cf. RFC 5322 */
134                         break;  /* ... the switch */
135                 default:
136                         continue;  /* ... the loop */
137                 }
138                 /* we've found a special char */
139                 needquotes = 1;
140                 break;
141         }
142         cp=fullname;
143         if (needquotes) {
144                 *cp++ = '"';
145         }
146         for (tp=tmp; *tp; *cp++=*tp++) {
147                 if (*tp == '"') {
148                         *cp++ = '\\';  /* prepend backslash */
149                 }
150         }
151         if (needquotes) {
152                 *cp++ = '"';
153         }
154         *cp = '\0';
155
156         return;
157 }