praliases.c revision 64565
1/*
2 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#ifndef lint
15static char copyright[] =
16"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\
17	All rights reserved.\n\
18     Copyright (c) 1983 Eric P. Allman.  All rights reserved.\n\
19     Copyright (c) 1988, 1993\n\
20	The Regents of the University of California.  All rights reserved.\n";
21#endif /* ! lint */
22
23#ifndef lint
24static char id[] = "@(#)$Id: praliases.c,v 8.59.4.10 2000/07/18 05:41:39 gshapiro Exp $";
25#endif /* ! lint */
26
27/* $FreeBSD: head/contrib/sendmail/praliases/praliases.c 64565 2000-08-12 22:19:16Z gshapiro $ */
28
29#include <sys/types.h>
30#include <ctype.h>
31#include <stdlib.h>
32#include <unistd.h>
33#ifdef EX_OK
34# undef EX_OK		/* unistd.h may have another use for this */
35#endif /* EX_OK */
36#include <sysexits.h>
37
38
39#ifndef NOT_SENDMAIL
40# define NOT_SENDMAIL
41#endif /* ! NOT_SENDMAIL */
42#include <sendmail/sendmail.h>
43#include <sendmail/pathnames.h>
44#include <libsmdb/smdb.h>
45
46static void praliases __P((char *, int, char **));
47
48uid_t	RealUid;
49gid_t	RealGid;
50char	*RealUserName;
51uid_t	RunAsUid;
52uid_t	RunAsGid;
53char	*RunAsUserName;
54int	Verbose = 2;
55bool	DontInitGroups = FALSE;
56uid_t	TrustedUid = 0;
57BITMAP256 DontBlameSendmail;
58
59extern void	syserr __P((const char *, ...));
60
61
62int
63main(argc, argv)
64	int argc;
65	char **argv;
66{
67	char *cfile;
68	char *filename = NULL;
69	FILE *cfp;
70	int ch;
71	char afilebuf[MAXLINE];
72	char buf[MAXLINE];
73	struct passwd *pw;
74	static char rnamebuf[MAXNAME];
75	extern char *optarg;
76	extern int optind;
77
78
79	clrbitmap(DontBlameSendmail);
80	RunAsUid = RealUid = getuid();
81	RunAsGid = RealGid = getgid();
82	pw = getpwuid(RealUid);
83	if (pw != NULL)
84	{
85		if (strlen(pw->pw_name) > MAXNAME - 1)
86			pw->pw_name[MAXNAME] = 0;
87		snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name);
88	}
89	else
90		(void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d",
91				(int) RealUid);
92	RunAsUserName = RealUserName = rnamebuf;
93
94	cfile = _PATH_SENDMAILCF;
95	while ((ch = getopt(argc, argv, "C:f:")) != -1)
96	{
97		switch ((char)ch) {
98		case 'C':
99			cfile = optarg;
100			break;
101		case 'f':
102			filename = optarg;
103			break;
104		case '?':
105		default:
106			(void)fprintf(stderr,
107				      "usage: praliases [-C cffile] [-f aliasfile]\n");
108			exit(EX_USAGE);
109		}
110	}
111	argc -= optind;
112	argv += optind;
113
114	if (filename != NULL)
115	{
116		praliases(filename, argc, argv);
117		exit(EX_OK);
118	}
119
120	if ((cfp = fopen(cfile, "r")) == NULL)
121	{
122		fprintf(stderr, "praliases: %s: %s\n",
123			cfile, errstring(errno));
124		exit(EX_NOINPUT);
125	}
126
127	while (fgets(buf, sizeof(buf), cfp) != NULL)
128	{
129		register char *b, *p;
130
131		b = strchr(buf, '\n');
132		if (b != NULL)
133			*b = '\0';
134
135		b = buf;
136		switch (*b++)
137		{
138		  case 'O':		/* option -- see if alias file */
139			if (strncasecmp(b, " AliasFile", 10) == 0 &&
140			    !(isascii(b[10]) && isalnum(b[10])))
141			{
142				/* new form -- find value */
143				b = strchr(b, '=');
144				if (b == NULL)
145					continue;
146				while (isascii(*++b) && isspace(*b))
147					continue;
148			}
149			else if (*b++ != 'A')
150			{
151				/* something else boring */
152				continue;
153			}
154
155			/* this is the A or AliasFile option -- save it */
156			if (strlcpy(afilebuf, b, sizeof afilebuf) >=
157			    sizeof afilebuf)
158			{
159				fprintf(stderr,
160					"praliases: AliasFile filename too long: %.30s\n",
161					b);
162				(void) fclose(cfp);
163				exit(EX_CONFIG);
164			}
165			b = afilebuf;
166
167			for (p = b; p != NULL; )
168			{
169				while (isascii(*p) && isspace(*p))
170					p++;
171				if (*p == '\0')
172					break;
173				b = p;
174
175				p = strpbrk(p, " ,/");
176
177				/* find end of spec */
178				if (p != NULL)
179				{
180					bool quoted = FALSE;
181
182					for (; *p != '\0'; p++)
183					{
184						/*
185						**  Don't break into a quoted
186						**  string.
187						*/
188
189						if (*p == '"')
190							quoted = !quoted;
191						else if (*p == ',' && !quoted)
192							break;
193					}
194
195					/* No more alias specs follow */
196					if (*p == '\0')
197					{
198						/* chop trailing whitespace */
199						while (isascii(*p) &&
200						       isspace(*p) &&
201						       p > b)
202							p--;
203						*p = '\0';
204						p = NULL;
205					}
206				}
207
208				if (p != NULL)
209				{
210					char *e = p - 1;
211
212					/* chop trailing whitespace */
213					while (isascii(*e) &&
214					       isspace(*e) &&
215					       e > b)
216						e--;
217					*++e = '\0';
218					*p++ = '\0';
219				}
220				praliases(b, argc, argv);
221			}
222
223		  default:
224			continue;
225		}
226	}
227	(void) fclose(cfp);
228	exit(EX_OK);
229	/* NOTREACHED */
230	return EX_OK;
231}
232
233static void
234praliases(filename, argc, argv)
235	char *filename;
236	int argc;
237	char **argv;
238{
239	int result;
240	char *colon;
241	char *db_name;
242	char *db_type;
243	SMDB_DATABASE *database = NULL;
244	SMDB_CURSOR *cursor = NULL;
245	SMDB_DBENT db_key, db_value;
246	SMDB_DBPARAMS params;
247	SMDB_USER_INFO user_info;
248
249	colon = strchr(filename, ':');
250	if (colon == NULL)
251	{
252		db_name = filename;
253		db_type = SMDB_TYPE_DEFAULT;
254	}
255	else
256	{
257		*colon = '\0';
258		db_name = colon + 1;
259		db_type = filename;
260	}
261
262	/* clean off arguments */
263	for (;;)
264	{
265		while (isascii(*db_name) && isspace(*db_name))
266			db_name++;
267		if (*db_name != '-')
268			break;
269		while (*db_name != '\0' &&
270		       !(isascii(*db_name) && isspace(*db_name)))
271			db_name++;
272	}
273
274	if (*db_name == '\0' || (db_type != NULL && *db_type == '\0'))
275	{
276		if (colon != NULL)
277			*colon = ':';
278		fprintf(stderr,	"praliases: illegal alias specification: %s\n",
279			filename);
280		goto fatal;
281	}
282
283	memset(&params, '\0', sizeof params);
284	params.smdbp_cache_size = 1024 * 1024;
285
286	user_info.smdbu_id = RunAsUid;
287	user_info.smdbu_group_id = RunAsGid;
288	strlcpy(user_info.smdbu_name, RunAsUserName, SMDB_MAX_USER_NAME_LEN);
289
290	result = smdb_open_database(&database, db_name, O_RDONLY, 0,
291				    SFF_ROOTOK, db_type, &user_info, &params);
292	if (result != SMDBE_OK)
293	{
294		fprintf(stderr, "praliases: %s: open: %s\n",
295			db_name, errstring(result));
296		goto fatal;
297	}
298
299	if (argc == 0)
300	{
301		memset(&db_key, '\0', sizeof db_key);
302		memset(&db_value, '\0', sizeof db_value);
303
304		result = database->smdb_cursor(database, &cursor, 0);
305		if (result != SMDBE_OK)
306		{
307			fprintf(stderr, "praliases: %s: set cursor: %s\n",
308				db_name, errstring(result));
309			goto fatal;
310		}
311
312		while ((result = cursor->smdbc_get(cursor, &db_key, &db_value,
313						   SMDB_CURSOR_GET_NEXT)) ==
314						   SMDBE_OK)
315		{
316#if 0
317			/* skip magic @:@ entry */
318			if (db_key.data.size == 2 &&
319			    db_key.data.data[0] == '@' &&
320			    db_key.data.data[1] == '\0' &&
321			    db_value.data.size == 2 &&
322			    db_value.data.data[0] == '@' &&
323			    db_value.data.data[1] == '\0')
324				continue;
325#endif /* 0 */
326
327			printf("%.*s:%.*s\n",
328			       (int) db_key.data.size,
329			       (char *) db_key.data.data,
330			       (int) db_value.data.size,
331			       (char *) db_value.data.data);
332		}
333
334		if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY)
335		{
336			fprintf(stderr,
337				"praliases: %s: get value at cursor: %s\n",
338				db_name, errstring(result));
339			goto fatal;
340		}
341	}
342	else for (; *argv != NULL; ++argv)
343	{
344		memset(&db_key, '\0', sizeof db_key);
345		memset(&db_value, '\0', sizeof db_value);
346		db_key.data.data = *argv;
347		db_key.data.size = strlen(*argv) + 1;
348		if (database->smdb_get(database, &db_key,
349				       &db_value, 0) == SMDBE_OK)
350		{
351			printf("%.*s:%.*s\n",
352			       (int) db_key.data.size,
353			       (char *) db_key.data.data,
354			       (int) db_value.data.size,
355			       (char *) db_value.data.data);
356		}
357		else
358			printf("%s: No such key\n", (char *) db_key.data.data);
359	}
360
361 fatal:
362	if (cursor != NULL)
363		(void) cursor->smdbc_close(cursor);
364	if (database != NULL)
365		(void) database->smdb_close(database);
366	if (colon != NULL)
367		*colon = ':';
368	return;
369}
370
371/*VARARGS1*/
372void
373#ifdef __STDC__
374message(const char *msg, ...)
375#else /* __STDC__ */
376message(msg, va_alist)
377	const char *msg;
378	va_dcl
379#endif /* __STDC__ */
380{
381	const char *m;
382	VA_LOCAL_DECL
383
384	m = msg;
385	if (isascii(m[0]) && isdigit(m[0]) &&
386	    isascii(m[1]) && isdigit(m[1]) &&
387	    isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
388		m += 4;
389	VA_START(msg);
390	(void) vfprintf(stderr, m, ap);
391	VA_END;
392	(void) fprintf(stderr, "\n");
393}
394
395/*VARARGS1*/
396void
397#ifdef __STDC__
398syserr(const char *msg, ...)
399#else /* __STDC__ */
400syserr(msg, va_alist)
401	const char *msg;
402	va_dcl
403#endif /* __STDC__ */
404{
405	const char *m;
406	VA_LOCAL_DECL
407
408	m = msg;
409	if (isascii(m[0]) && isdigit(m[0]) &&
410	    isascii(m[1]) && isdigit(m[1]) &&
411	    isascii(m[2]) && isdigit(m[2]) && m[3] == ' ')
412		m += 4;
413	VA_START(msg);
414	(void) vfprintf(stderr, m, ap);
415	VA_END;
416	(void) fprintf(stderr, "\n");
417}
418