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