xref: /illumos-gate/usr/src/cmd/ypcmd/mkalias.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1996, by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /*
28  * mkmap - program to convert the mail.aliases map into an
29  * inverse map of <user@host> back to <preferred-alias>
30  */
31 
32 #pragma ident	"%Z%%M%	%I%	%E% SMI"
33 
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <fcntl.h>
38 #include <ndbm.h>
39 #include <stdio.h>
40 #include <ctype.h>
41 #include <netdb.h>
42 #include <sys/systeminfo.h>
43 
44 #include "ypdefs.h"
45 USE_YP_PREFIX
46 USE_YP_MASTER_NAME
47 USE_YP_LAST_MODIFIED
48 
49 #define	MKAL_INCLUDE ":include:"
50 
51 void CopyName(char *dst, char *src, int len);
52 int HostCheck(char *h, char *a);
53 void DoName(char *cp);
54 void UpperCase(char *cp);
55 void AddYPEntries(void);
56 
57 int Verbose = 0;	/* to get the gory details */
58 int UucpOK = 0;		/* pass all UUCP names right through */
59 int DomainOK = 0;	/* pass all Domain names (with dots) */
60 int ErrorCheck = 0;	/* check carefully for errors */
61 int NoOutput = 0;	/* no output, just do the check */
62 int Simple = 0;		/* Do not do the user name preference step */
63 int NameMode = 0;	/* Try to capitalize as names */
64 
65 DBM *Indbm=NULL, *Scandbm=NULL, *Outdbm=NULL;
66 
67 int
68 IsMailingList(char *s)
69 {
70 	/*
71 	 * returns true if the given string is a mailing list
72 	 */
73 	char *p;
74 
75 	if (strchr(s, ','))
76 		return (1);
77 	if (strchr(s, '|'))
78 		return (1);
79 	p = strchr(s, ':');
80 	if (p && strncmp(p, MKAL_INCLUDE, sizeof (MKAL_INCLUDE)))
81 		return (1);
82 	return (0);
83 }
84 
85 int
86 IsQualified(char *s, char *p, char *h)
87 {
88 	/*
89 	 * returns true if the given string is qualified with a host name
90 	 */
91 	register char *middle;
92 
93 	middle = strchr(s, '@');
94 	if (middle) {
95 		for (middle = s; *middle != '@'; *p++ = *middle++)
96 			continue;
97 		*p = '\0';
98 		CopyName(h, middle+1, strlen(middle + 1));
99 		return (1);
100 	}
101 	middle = strrchr(s, '!');
102 	if (middle) {
103 		strcpy(p, middle+1);
104 		*middle = '\0';
105 		CopyName(h, s, strlen(s));
106 		*middle = '!';
107 		return (1);
108 	}
109 	return (0);
110 }
111 
112 int
113 IsMaint(char *s)
114 {
115 	/*
116 	 * returns true if the given string is one of the maintenence
117 	 * strings used in sendmail or NIS.
118 	 */
119 	if (*s == '@')
120 		return (1);
121 	if (strncmp(s, yp_prefix, yp_prefix_sz) == 0)
122 		return (1);
123 	return (0);
124 }
125 
126 void
127 CopyName(char *dst, char *src, int len)
128 {
129 	/*
130 	* copy a string, but ignore white space
131 	*/
132 	while (*src && len--) {
133 		if (isspace(*src))
134 			src++;
135 		else
136 			*dst++ = *src++;
137 	}
138 	*dst = '\0';
139 }
140 
141 int
142 Compare(char *s1, char *s2)
143 {
144 	/*
145 	 * compare strings, but ignore white space
146 	 */
147 	while (*s1 != '\0' && isspace(*s1))
148 		s1++;
149 	while (*s2 != '\0' && isspace(*s2))
150 		s2++;
151 	return (strcmp(s1, s2));
152 }
153 
154 void
155 ProcessMap(void)
156 {
157 	datum key, value, part, partvalue;
158 	char address[PBLKSIZ];	/* qualified version */
159 	char user[PBLKSIZ];		/* unqualified version */
160 	char userpart[PBLKSIZ];	/* unqualified part of qualified addr. */
161 	char hostpart[PBLKSIZ];	/* rest of qualified addr. */
162 
163 	for (key = dbm_firstkey(Scandbm); key.dptr != NULL;
164 						key = dbm_nextkey(Scandbm)) {
165 		value = dbm_fetch(Indbm, key);
166 		CopyName(address, value.dptr, value.dsize);
167 		CopyName(user, key.dptr, key.dsize);
168 		if (address == NULL) continue;
169 		if (IsMailingList(address)) continue;
170 		if (!IsQualified(address, userpart, hostpart)) continue;
171 		if (IsMaint(user)) continue;
172 		if (ErrorCheck && HostCheck(hostpart, address)) {
173 			printf("Invalid host %s in %s:%s\n",
174 				hostpart, user, address);
175 			continue;
176 		}
177 		part.dptr = userpart;
178 		part.dsize = strlen(userpart) + 1;
179 		if (Simple)
180 			partvalue.dptr = NULL;
181 		else
182 			partvalue = dbm_fetch(Indbm, part);
183 		value.dptr = address;
184 		value.dsize = strlen(address) + 1;
185 		if (partvalue.dptr != NULL &&
186 			Compare(partvalue.dptr, user) == 0) {
187 
188 			if (NameMode)
189 				DoName(userpart);
190 			if (!NoOutput)
191 				dbm_store(Outdbm, value, part, DBM_REPLACE);
192 			if (Verbose) printf("%s --> %s --> %s\n",
193 						userpart, user, address);
194 		} else {
195 			if (NameMode)
196 				DoName(user);
197 			key.dptr = user;
198 			key.dsize = strlen(user) + 1;
199 			if (!NoOutput)
200 				dbm_store(Outdbm, value, key, DBM_REPLACE);
201 			if (Verbose)
202 				printf("%s --> %s\n", user, address);
203 		}
204 	}
205 }
206 
207 
208 /*
209  * Returns true if this is an invalid host
210  */
211 int
212 HostCheck(char *h, char *a)
213 {
214 	struct hostent *hp;
215 
216 	if (DomainOK && strchr(a, '.'))
217 		return (0);
218 
219 	if (UucpOK && strchr(a, '!'))
220 		return (0);
221 
222 	hp = gethostbyname(h);
223 	return (hp == NULL);
224 }
225 
226 /*
227  * Apply some Heurisitcs to upper case-ify the name
228  * If it has a dot in it.
229  */
230 void
231 DoName(char *cp)
232 {
233 	if (strchr(cp, '.') == NULL)
234 		return;
235 
236 	while (*cp) {
237 		UpperCase(cp);
238 		while (*cp && *cp != '-' && *cp != '.')
239 			cp++;
240 		if (*cp)
241 			cp++;	/* skip past punctuation */
242 	}
243 }
244 
245 /*
246  * upper cases one name - stops at a .
247  */
248 void
249 UpperCase(char *cp)
250 {
251 	register ch = cp[0];
252 
253 	if (isupper(ch))
254 		ch = tolower(ch);
255 
256 	if (ch == 'f' && cp[1] == 'f')
257 		return; /* handle ff */
258 
259 	if (ch == 'm' && cp[1] == 'c' && islower(cp[2]))
260 		cp[2] = toupper(cp[2]);
261 	if (islower(ch))
262 		cp[0] = toupper(ch);
263 }
264 
265 void
266 AddYPEntries(void)
267 {
268 	datum key, value;
269 	char last_modified[PBLKSIZ];
270 	char host_name[PBLKSIZ];
271 	time_t now;
272 
273 	/*
274 	 * Add the special NIS entries.
275 	 */
276 	key.dptr = yp_last_modified;
277 	key.dsize = yp_last_modified_sz;
278 	time(&now);
279 	sprintf(last_modified, "%10.10d", now);
280 	value.dptr = last_modified;
281 	value.dsize = strlen(value.dptr);
282 	dbm_store(Outdbm, key, value, DBM_REPLACE);
283 
284 	key.dptr = yp_master_name;
285 	key.dsize = yp_master_name_sz;
286 	sysinfo(SI_HOSTNAME, host_name, sizeof (host_name));
287 	value.dptr = host_name;
288 	value.dsize = strlen(value.dptr);
289 	dbm_store(Outdbm, key, value, DBM_REPLACE);
290 }
291 
292 int
293 main(int argc, char *argv[])
294 {
295 	while (argc > 1 && argv[1][0] == '-') {
296 	switch (argv[1][1]) {
297 		case 'v':
298 			Verbose = 1;
299 			break;
300 
301 		case 'u':
302 			UucpOK = 1;
303 			break;
304 
305 		case 'd':
306 			DomainOK = 1;
307 			break;
308 
309 		case 'e':
310 			ErrorCheck = 1;
311 			break;
312 
313 		case 's':
314 			Simple = 1;
315 			break;
316 
317 		case 'n':
318 			NameMode = 1;
319 			break;
320 
321 		default:
322 			printf("Unknown option %c\n", argv[1][1]);
323 			break;
324 		}
325 		argc--; argv++;
326 	}
327 	if (argc < 2) {
328 printf("Usage: mkalias [-e] [-v] [-u] [-d] [-s] [-n] <input> <output>\n");
329 		exit(1);
330 	}
331 	Indbm = dbm_open(argv[1], O_RDONLY, 0);
332 	if (Indbm == NULL) {
333 		printf("Unable to open input database %s\n", argv[1]);
334 		exit(1);
335 	}
336 	Scandbm = dbm_open(argv[1], O_RDONLY, 0);
337 	if (Scandbm == NULL) {
338 		printf("Unable to open input database %s\n", argv[1]);
339 		exit(1);
340 	}
341 	if (argv[2] == NULL)
342 		NoOutput = 1;
343 	else {
344 		Outdbm = dbm_open(argv[2], O_RDWR|O_CREAT|O_TRUNC, 0644);
345 		if (Outdbm == NULL) {
346 			printf("Unable to open output database %s\n", argv[2]);
347 			exit(1);
348 		}
349 	}
350 	ProcessMap();
351 	dbm_close(Indbm);
352 	dbm_close(Scandbm);
353 	if (!NoOutput) {
354 		AddYPEntries();
355 		dbm_close(Outdbm);
356 	}
357 	return (0);
358 }
359