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