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 14 static 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 20 static 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 51 extern char *strerror __P((int)); 52 #endif 53 54 static void praliases __P((char *, int, char **)); 55 #ifdef NDBM 56 static void praliases_dbm __P((char *, int, char **)); 57 #endif 58 59 int 60 main(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 180 static void 181 praliases(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 300 static void 301 praliases_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 356 char * 357 strerror(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