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