praliases.c revision 42580
1/* 2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1983 Eric P. Allman. All rights reserved. 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * By using this file, you agree to the terms and conditions set 8 * forth in the LICENSE file which can be found at the top level of 9 * the sendmail distribution. 10 * 11 */ 12 13#ifndef lint 14static char copyright[] = 15"@(#) Copyright (c) 1988, 1993\n\ 16 The Regents of the University of California. All rights reserved.\n"; 17#endif /* not lint */ 18 19#ifndef lint 20static char sccsid[] = "@(#)praliases.c 8.21 (Berkeley) 12/27/1998"; 21#endif /* not lint */ 22 23#if !defined(NDBM) && !defined(NEWDB) 24 ERROR README: You must define one of NDBM or NEWDB in order to compile 25 ERROR README: praliases. 26#endif 27 28#ifdef NDBM 29# include <ndbm.h> 30#endif 31#ifndef NOT_SENDMAIL 32# define NOT_SENDMAIL 33#endif 34#include <sendmail.h> 35#include <pathnames.h> 36#ifdef NEWDB 37# include <db.h> 38# ifndef DB_VERSION_MAJOR 39# define DB_VERSION_MAJOR 1 40# endif 41#endif 42 43#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) || \ 44 defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) 45# ifndef HASSTRERROR 46# define HASSTRERROR 1 /* has strerror(3) */ 47# endif 48#endif 49 50#if !HASSTRERROR 51extern char *strerror __P((int)); 52#endif 53 54static void praliases __P((char *, int, char **)); 55#ifdef NDBM 56static void praliases_dbm __P((char *, int, char **)); 57#endif 58 59int 60main(argc, argv) 61 int argc; 62 char **argv; 63{ 64 extern char *optarg; 65 extern int optind; 66 char *cfile; 67#if _FFR_GRAB_ALIASFILE_OPTION 68 char *filename = NULL; 69#else 70 char *filename = "/etc/aliases"; 71#endif 72 FILE *cfp; 73 int ch; 74 char afilebuf[MAXLINE]; 75 char buf[MAXLINE]; 76 77 cfile = _PATH_SENDMAILCF; 78#if _FFR_GRAB_ALIASFILE_OPTION 79 while ((ch = getopt(argc, argv, "C:f:")) != -1) 80#else 81 while ((ch = getopt(argc, argv, "f:")) != -1) 82#endif 83 { 84 switch ((char)ch) { 85 case 'C': 86 cfile = optarg; 87 break; 88 case 'f': 89 filename = optarg; 90 break; 91 case '?': 92 default: 93 (void)fprintf(stderr, 94#if _FFR_GRAB_ALIASFILE_OPTION 95 "usage: praliases [-C cffile] [-f aliasfile]\n"); 96#else 97 "usage: praliases [-f aliasfile]\n"); 98#endif 99 exit(EX_USAGE); 100 } 101 } 102 argc -= optind; 103 argv += optind; 104 105 if (filename != NULL) 106 { 107 praliases(filename, argc, argv); 108 exit(EX_OK); 109 } 110 111 if ((cfp = fopen(cfile, "r")) == NULL) 112 { 113 fprintf(stderr, "praliases: "); 114 perror(cfile); 115 exit(EX_NOINPUT); 116 } 117 118 while (fgets(buf, sizeof(buf), cfp) != NULL) 119 { 120 register char *b, *p; 121 122 b = buf; 123 switch (*b++) 124 { 125 case 'O': /* option -- see if alias file */ 126 if (strncasecmp(b, " AliasFile", 10) == 0 && 127 !(isascii(b[10]) && isalnum(b[10]))) 128 { 129 /* new form -- find value */ 130 b = strchr(b, '='); 131 if (b == NULL) 132 continue; 133 while (isascii(*++b) && isspace(*b)) 134 continue; 135 } 136 else if (*b++ != 'A') 137 { 138 /* something else boring */ 139 continue; 140 } 141 142 /* this is the A or AliasFile option -- save it */ 143 if (strlen(b) >= sizeof afilebuf) 144 { 145 fprintf(stderr, 146 "AliasFile filename too long: %.30s...\n", 147 b); 148 (void) fclose(cfp); 149 exit(EX_CONFIG); 150 } 151 strcpy(afilebuf, b); 152 b = afilebuf; 153 154 for (p = b; p != NULL; ) 155 { 156 while (isascii(*p) && isspace(*p)) 157 p++; 158 if (*p == '\0') 159 break; 160 b = p; 161 162 p = strpbrk(p, " ,/"); 163 /* find end of spec */ 164 if (p != NULL) 165 p = strpbrk(p, ",\n"); 166 if (p != NULL) 167 *p++ = '\0'; 168 169 praliases(b, argc, argv); 170 } 171 172 default: 173 continue; 174 } 175 } 176 (void) fclose(cfp); 177 exit(EX_OK); 178} 179 180static void 181praliases(filename, argc, argv) 182 char *filename; 183 int argc; 184 char **argv; 185{ 186#ifdef NEWDB 187 DB *db; 188 DBT newdbkey, newdbcontent; 189 char buf[MAXNAME]; 190#endif 191 char *class; 192 193 class = strchr(filename, ':'); 194 if (class != NULL) 195 { 196 if (strncasecmp(filename, "dbm:", 4) == 0) 197 { 198#ifdef NDBM 199 praliases_dbm(class + 1, argc, argv); 200 return; 201#else 202 fprintf(stderr, "class dbm not available\n"); 203 exit(EX_DATAERR); 204#endif 205 } 206 filename = class + 1; 207 } 208#ifdef NEWDB 209 if (strlen(filename) + 4 >= sizeof buf) 210 { 211 fprintf(stderr, "Alias filename too long: %.30s...\n", filename); 212 exit(EX_USAGE); 213 } 214 (void) strcpy(buf, filename); 215 (void) strcat(buf, ".db"); 216# if DB_VERSION_MAJOR < 2 217 db = dbopen(buf, O_RDONLY, 0444, DB_HASH, NULL); 218# else 219 db = NULL; 220 errno = db_open(buf, DB_HASH, DB_RDONLY, 0444, NULL, NULL, &db); 221# endif 222 if (db != NULL) 223 { 224 if (!argc) 225 { 226# if DB_VERSION_MAJOR > 1 227 DBC *dbc; 228# endif 229 bzero(&newdbkey, sizeof newdbkey); 230 bzero(&newdbcontent, sizeof newdbcontent); 231 232# if DB_VERSION_MAJOR < 2 233 while(!db->seq(db, &newdbkey, &newdbcontent, R_NEXT)) 234# else 235# if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >=6 236 if ((errno = db->cursor(db, NULL, &dbc, 0)) == 0) 237# else 238 if ((errno = db->cursor(db, NULL, &dbc)) == 0) 239# endif 240 { 241 while ((errno = dbc->c_get(dbc, &newdbkey, 242 &newdbcontent, 243 DB_NEXT)) == 0) 244# endif 245 printf("%.*s:%.*s\n", 246 (int) newdbkey.size, 247 (char *) newdbkey.data, 248 (int) newdbcontent.size, 249 (char *) newdbcontent.data); 250# if DB_VERSION_MAJOR > 1 251 (void) dbc->c_close(dbc); 252 } 253 else 254 { 255 fprintf(stderr, 256 "praliases: %s: Could not set cursor: %s\n", 257 buf, strerror(errno)); 258 errno = db->close(db, 0); 259 exit(EX_DATAERR); 260 } 261# endif 262 } 263 else for (; *argv; ++argv) 264 { 265 bzero(&newdbkey, sizeof newdbkey); 266 bzero(&newdbcontent, sizeof newdbcontent); 267 newdbkey.data = *argv; 268 newdbkey.size = strlen(*argv) + 1; 269# if DB_VERSION_MAJOR < 2 270 if (!db->get(db, &newdbkey, &newdbcontent, 0)) 271# else 272 if ((errno = db->get(db, NULL, &newdbkey, 273 &newdbcontent, 0)) == 0) 274# endif 275 printf("%s:%.*s\n", (char *) newdbkey.data, 276 (int) newdbcontent.size, 277 (char *) newdbcontent.data); 278 else 279 printf("%s: No such key\n", 280 (char *) newdbkey.data); 281 } 282# if DB_VERSION_MAJOR < 2 283 (void)db->close(db); 284# else 285 errno = db->close(db, 0); 286# endif 287 } 288 else 289 { 290#endif 291#ifdef NDBM 292 praliases_dbm(filename, argc, argv); 293#endif 294#ifdef NEWDB 295 } 296#endif 297} 298 299#ifdef NDBM 300static void 301praliases_dbm(filename, argc, argv) 302 char *filename; 303 int argc; 304 char **argv; 305{ 306 DBM *dbp; 307 datum content, key; 308 309 if ((dbp = dbm_open(filename, O_RDONLY, 0)) == NULL) 310 { 311 (void)fprintf(stderr, 312 "praliases: %s: %s\n", filename, strerror(errno)); 313 exit(EX_OSFILE); 314 } 315 if (!argc) 316 { 317 for (key = dbm_firstkey(dbp); 318 key.dptr != NULL; key = dbm_nextkey(dbp)) 319 { 320 content = dbm_fetch(dbp, key); 321 (void)printf("%.*s:%.*s\n", 322 (int) key.dsize, key.dptr, 323 (int) content.dsize, content.dptr); 324 } 325 } 326 else 327 { 328 for (; *argv; ++argv) 329 { 330 /* 331 ** Use the sendmail adaptive algorithm of trying 332 ** the key first without, then if needed with, 333 ** the terminating NULL byte. 334 */ 335 key.dptr = *argv; 336 key.dsize = strlen(*argv); 337 content = dbm_fetch(dbp, key); 338 if (content.dptr == NULL) 339 { 340 key.dsize++; 341 content = dbm_fetch(dbp, key); 342 } 343 if (content.dptr != NULL) 344 (void)printf("%s:%.*s\n", key.dptr, 345 (int) content.dsize, content.dptr); 346 else 347 (void)printf("%s: No such key\n", key.dptr); 348 } 349 } 350 dbm_close(dbp); 351} 352#endif 353 354#if !HASSTRERROR 355 356char * 357strerror(eno) 358 int eno; 359{ 360 extern int sys_nerr; 361 extern char *sys_errlist[]; 362 static char ebuf[60]; 363 364 if (eno >= 0 && eno < sys_nerr) 365 return sys_errlist[eno]; 366 (void) sprintf(ebuf, "Error %d", eno); 367 return ebuf; 368} 369 370#endif /* !HASSTRERROR */ 371