Removed support for UUCP bang path addresses.
[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 #ifdef HAVE_SYS_UTSNAME_H
18 # include <sys/utsname.h>
19 #endif
20
21 #define NOTOK  (-1)
22 #define OK     0
23
24 /*
25 ** static prototypes
26 */
27 static void getuserinfo(void);
28
29 /* Cache the username and fullname of the user */
30 static char username[BUFSIZ];
31 static char fullname[BUFSIZ];
32
33
34 /*
35 ** Get the fully qualified name of the local host.
36 */
37 char *
38 LocalName(void)
39 {
40         static char buffer[BUFSIZ] = "";
41         struct addrinfo hints, *res;
42 #ifdef HAVE_UNAME
43         struct utsname name;
44 #endif
45
46         /* check if we have cached the local name */
47         if (buffer[0])
48                 return buffer;
49
50         memset(buffer, 0, sizeof(buffer));
51 #ifdef HAVE_UNAME
52         /* first get our local name */
53         uname(&name);
54         strncpy(buffer, name.nodename, sizeof(buffer) - 1);
55 #else
56         /* first get our local name */
57         gethostname(buffer, sizeof(buffer) - 1);
58 #endif
59         /* now fully qualify our name */
60
61         memset(&hints, 0, sizeof(hints));
62         hints.ai_flags = AI_CANONNAME;
63         hints.ai_family = PF_UNSPEC;
64         if (getaddrinfo(buffer, NULL, &hints, &res) == 0) {
65                 strncpy(buffer, res->ai_canonname, sizeof(buffer) - 1);
66                 freeaddrinfo(res);
67         }
68
69         return buffer;
70 }
71
72
73 /*
74 ** Get the username of current user
75 */
76 char *
77 getusername(void)
78 {
79         if (username[0] == '\0')
80                 getuserinfo();
81
82         return username;
83 }
84
85
86 /*
87 ** Get full name of current user (typically from GECOS
88 ** field of password file).
89 */
90 char *
91 getfullname(void)
92 {
93         if (username[0] == '\0')
94                 getuserinfo();
95
96         return fullname;
97 }
98
99
100 /*
101 ** Find the user's username and full name, and cache them.
102 */
103 static void
104 getuserinfo(void)
105 {
106         unsigned char *cp;
107         char *np;
108         struct passwd *pw;
109         int needquotes = 0;
110         char tmp[BUFSIZ];
111         char *tp;
112
113         if (!(pw = getpwuid(getuid())) || !pw->pw_name || !*pw->pw_name) {
114                 strncpy(username, "unknown", sizeof(username));
115                 snprintf(fullname, sizeof(fullname),
116                                 "The Unknown User-ID (%d)", (int)getuid());
117                 return;
118         }
119
120         np = pw->pw_gecos;
121
122         /*
123         ** Get the user's real name from the GECOS field.  Stop once
124         ** we hit a ',', which some OSes use to separate other 'finger'
125         ** information in the GECOS field, like phone number.
126         */
127         for (cp = tmp; *np != '\0' && *np != ',';) {
128 #ifndef BSD42
129                 *cp++ = *np++;
130 #else /* BSD42 */
131                 /*
132                 ** On BSD(-derived) systems, the system utilities that
133                 ** deal with the GECOS field (finger, mail, sendmail,
134                 ** etc.) translate any '&' character in it to the login name,
135                 ** with the first letter capitalized.  So, for instance,
136                 ** fingering a user "bob" with the GECOS field "& Jones"
137                 ** would reveal him to be "In real life: Bob Jones".
138                 ** Surprisingly, though, the OS doesn't do the translation
139                 ** for you, so we have to do it manually here.
140                 */
141                 if (*np == '&') {  /* blech! */
142                         strcpy(cp, pw->pw_name);
143                         *cp = toupper(*cp);
144                         while (*cp)
145                                 cp++;
146                         np++;
147                 } else {
148                         *cp++ = *np++;
149                 }
150 #endif /* BSD42 */
151         }
152         *cp = '\0';
153         strncpy(username, pw->pw_name, sizeof(username));
154
155         /*
156         ** The $SIGNATURE environment variable overrides the GECOS field's
157         ** idea of your real name.
158         */
159         if ((cp = getenv("SIGNATURE")) && *cp)
160                 strncpy(tmp, cp, sizeof(tmp));
161
162         /* quote the fullname as needed */
163         needquotes = 0;
164         for (tp=tmp; *tp; tp++) {
165                 switch (*tp) {
166                 case '(': case ')': case '<': case '>': case '[': case ']':
167                 case ':': case ';': case '@': case '\\': case ',': case '.':
168                 case '"':  /* cf. RFC 5322 */
169                         break;  /* ... the switch */
170                 default:
171                         continue;  /* ... the loop */
172                 }
173                 /* we've found a special char */
174                 needquotes = 1;
175                 break;
176         }
177         cp=fullname;
178         if (needquotes) {
179                 *cp++ = '"';
180         }
181         for (tp=tmp; *tp; *cp++=*tp++) {
182                 if (*tp == '"') {
183                         *cp++ = '\\';  /* prepend backslash */
184                 }
185         }
186         if (needquotes) {
187                 *cp++ = '"';
188         }
189         *cp = '\0';
190
191         return;
192 }