diff -urN sendmail-8.11.6/sendmail/map.c sendmail-8.11.6-libphclient-phmap/sendmail/map.c --- sendmail-8.11.6/sendmail/map.c Sun Aug 19 07:55:27 2001 +++ sendmail-8.11.6-libphclient-phmap/sendmail/map.c Thu Aug 30 14:49:37 2001 @@ -4430,8 +4430,13 @@ ** Contributed by Mark D. Roth . Contact him for support. */ -# include -# include + +/* what version of the ph map code we're running */ +static char phmap_id[PH_BUF_SIZE]; + +/* sendmail version for phmap id string */ +extern const char Version[]; + /* ** PH_MAP_PARSEARGS -- parse ph map definition args. @@ -4442,20 +4447,23 @@ MAP *map; char *args; { - int i; - register int done; PH_MAP_STRUCT *pmap = NULL; + register int done; register char *p = args; + /* initialize version string */ + snprintf(phmap_id, PH_BUF_SIZE, + "sendmail-%s phmap-20010529 libphclient-%s", + Version, libphclient_version); + pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); /* defaults */ pmap->ph_servers = NULL; pmap->ph_field_list = NULL; - pmap->ph_to_server = NULL; - pmap->ph_from_server = NULL; - pmap->ph_sockfd = -1; + pmap->ph = NULL; pmap->ph_timeout = 0; + pmap->ph_fastclose = 0; map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; for (;;) @@ -4507,13 +4515,11 @@ map->map_tapp = ++p; break; -#if _FFR_PHMAP_TIMEOUT case 'l': while (isascii(*++p) && isspace(*p)) continue; pmap->ph_timeout = atoi(p); break; -#endif /* _FFR_PHMAP_TIMEOUT */ case 'S': map->map_spacesub = *++p; @@ -4529,7 +4535,13 @@ pmap->ph_servers = p; break; - case 'v': /* fields to search for */ + case 'v': + sm_syslog(LOG_WARNING, NULL, + "ph_map_parseargs: WARNING: -v option will be removed in a future release - please use -k instead"); + /* intentional fallthrough for backward compatibility */ + /* FALLTHROUGH */ + + case 'k': /* fields to search for */ while (isascii(*++p) && isspace(*p)) continue; pmap->ph_field_list = p; @@ -4566,8 +4578,6 @@ if (pmap->ph_field_list != NULL) pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); - else - pmap->ph_field_list = DEFAULT_PH_MAP_FIELDS; if (pmap->ph_servers != NULL) pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); @@ -4581,50 +4591,28 @@ return TRUE; } -#if _FFR_PHMAP_TIMEOUT /* ** PH_MAP_CLOSE -- close the connection to the ph server */ -static void -ph_map_safeclose(map) +void +ph_map_close(map) MAP *map; { - int save_errno = errno; PH_MAP_STRUCT *pmap; pmap = (PH_MAP_STRUCT *)map->map_db1; - if (pmap->ph_sockfd != -1) - { - (void) close(pmap->ph_sockfd); - pmap->ph_sockfd = -1; - } - if (pmap->ph_from_server != NULL) + if (pmap->ph) { - (void) fclose(pmap->ph_from_server); - pmap->ph_from_server = NULL; - } - if (pmap->ph_to_server != NULL) - { - (void) fclose(pmap->ph_to_server); - pmap->ph_to_server = NULL; + ph_set_sendhook(pmap->ph, NULL); + ph_set_recvhook(pmap->ph, NULL); + ph_close(pmap->ph, pmap->ph_fastclose); } + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); - errno = save_errno; } -void -ph_map_close(map) - MAP *map; -{ - PH_MAP_STRUCT *pmap; - - pmap = (PH_MAP_STRUCT *)map->map_db1; - (void) fprintf(pmap->ph_to_server, "quit\n"); - (void) fflush(pmap->ph_to_server); - ph_map_safeclose(map); -} static jmp_buf PHTimeout; @@ -4642,25 +4630,35 @@ errno = ETIMEDOUT; longjmp(PHTimeout, 1); } -#else /* _FFR_PHMAP_TIMEOUT */ -/* -** PH_MAP_CLOSE -- close the connection to the ph server -*/ -void -ph_map_close(map) - MAP *map; + + + +static void +ph_map_send_debug(text) + char *text; { - PH_MAP_STRUCT *pmap; + if (LogLevel > 9) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "ph_map_send_debug: ==> %s", text); + if (tTd(38, 20)) + dprintf("ph_map_send_debug: ==> %s", text); +} - pmap = (PH_MAP_STRUCT *)map->map_db1; - CloseQi(pmap->ph_to_server, pmap->ph_from_server); - pmap->ph_to_server = NULL; - pmap->ph_from_server = NULL; + +static void +ph_map_recv_debug(text) + char *text; +{ + if (LogLevel > 10) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "ph_map_recv_debug: <== %s", text); + if (tTd(38, 21)) + dprintf("ph_map_recv_debug: <== %s\n", text); } -#endif /* _FFR_PHMAP_TIMEOUT */ - /* + +/* ** PH_MAP_OPEN -- sub for opening PH map */ bool @@ -4668,16 +4666,10 @@ MAP *map; int mode; { -#if !_FFR_PHMAP_TIMEOUT - int save_errno = 0; -#endif /* !_FFR_PHMAP_TIMEOUT */ - int j; - char *hostlist, *tmp; - QIR *server_data = NULL; PH_MAP_STRUCT *pmap; -#if _FFR_PHMAP_TIMEOUT register EVENT *ev = NULL; -#endif /* _FFR_PHMAP_TIMEOUT */ + int ph_port, save_errno = 0; + char *hostlist, *host; if (tTd(38, 2)) dprintf("ph_map_open(%s)\n", map->map_mname); @@ -4717,11 +4709,13 @@ pmap = (PH_MAP_STRUCT *)map->map_db1; + /* try each host in the list */ hostlist = newstr(pmap->ph_servers); - tmp = strtok(hostlist, " "); - do + for (host = strtok(hostlist, " "); + host; + host = strtok(NULL, " ")) { -#if _FFR_PHMAP_TIMEOUT + /* set timeout */ if (pmap->ph_timeout != 0) { if (setjmp(PHTimeout) != 0) @@ -4730,7 +4724,7 @@ if (LogLevel > 1) sm_syslog(LOG_NOTICE, CurEnv->e_id, "timeout connecting to PH server %.100s", - tmp); + host); # ifdef ETIMEDOUT errno = ETIMEDOUT; # else /* ETIMEDOUT */ @@ -4740,57 +4734,27 @@ } ev = setevent(pmap->ph_timeout, ph_timeout, 0); } - if (!OpenQiSock(tmp, &(pmap->ph_sockfd)) && - !Sock2FILEs(pmap->ph_sockfd, &(pmap->ph_to_server), - &(pmap->ph_from_server)) && - fprintf(pmap->ph_to_server, "id sendmail+phmap\n") >= 0 && - fflush(pmap->ph_to_server) == 0 && - (server_data = ReadQi(pmap->ph_from_server, &j)) != NULL && - server_data->code == 200) + + /* open connection to server */ + if (!ph_open(&(pmap->ph), host, PH_ROUNDROBIN|PH_DONTID, + ph_map_send_debug, ph_map_recv_debug) && + !ph_id(pmap->ph, phmap_id)) { if (ev != NULL) clrevent(ev); - FreeQIR(server_data); -#else /* _FFR_PHMAP_TIMEOUT */ - if (OpenQi(tmp, &(pmap->ph_to_server), - &(pmap->ph_from_server)) >= 0) - { - if (fprintf(pmap->ph_to_server, - "id sendmail+phmap\n") < 0 || - fflush(pmap->ph_to_server) != 0 || - (server_data = ReadQi(pmap->ph_from_server, - &j)) == NULL || - server_data->code != 200) - { - save_errno = errno; - CloseQi(pmap->ph_to_server, - pmap->ph_from_server); - continue; - } - if (server_data != NULL) - FreeQIR(server_data); -#endif /* _FFR_PHMAP_TIMEOUT */ sm_free(hostlist); return TRUE; } -#if _FFR_PHMAP_TIMEOUT + ph_map_open_abort: + save_errno = errno; if (ev != NULL) clrevent(ev); - ph_map_safeclose(map); - if (server_data != NULL) - { - FreeQIR(server_data); - server_data = NULL; - } -#else /* _FFR_PHMAP_TIMEOUT */ - save_errno = errno; -#endif /* _FFR_PHMAP_TIMEOUT */ - } while (tmp = strtok(NULL, " ")); + pmap->ph_fastclose = PH_FASTCLOSE; + ph_map_close(map); + errno = save_errno; + } -#if !_FFR_PHMAP_TIMEOUT - errno = save_errno; -#endif /* !_FFR_PHMAP_TIMEOUT */ if (bitset(MF_NODEFER, map->map_mflags)) { if (errno == 0) @@ -4810,10 +4774,6 @@ ** PH_MAP_LOOKUP -- look up key from ph server */ -#if _FFR_PHMAP_TIMEOUT -# define MAX_PH_FIELDS 20 -#endif /* _FFR_PHMAP_TIMEOUT */ - char * ph_map_lookup(map, key, args, pstat) MAP *map; @@ -4821,25 +4781,15 @@ char **args; int *pstat; { - int j; - size_t sz; - char *tmp, *tmp2; - char *message = NULL, *field = NULL, *fmtkey; - QIR *server_data = NULL; - QIR *qirp; - char keybuf[MAXKEY + 1], fieldbuf[101]; -#if _FFR_PHMAP_TIMEOUT - QIR *hold_data[MAX_PH_FIELDS]; - int hold_data_idx = 0; + int i, save_errno = 0; register EVENT *ev = NULL; -#endif /* _FFR_PHMAP_TIMEOUT */ PH_MAP_STRUCT *pmap; + char *value = NULL; pmap = (PH_MAP_STRUCT *)map->map_db1; - *pstat = EX_OK; -#if _FFR_PHMAP_TIMEOUT + /* set timeout */ if (pmap->ph_timeout != 0) { if (setjmp(PHTimeout) != 0) @@ -4860,249 +4810,41 @@ ev = setevent(pmap->ph_timeout, ph_timeout, 0); } -#endif /* _FFR_PHMAP_TIMEOUT */ - /* check all relevant fields */ - tmp = pmap->ph_field_list; - do - { -#if _FFR_PHMAP_TIMEOUT - server_data = NULL; -#endif /* _FFR_PHMAP_TIMEOUT */ - while (isascii(*tmp) && isspace(*tmp)) - tmp++; - if (*tmp == '\0') - break; - sz = strcspn(tmp, " ") + 1; - if (sz > sizeof fieldbuf) - sz = sizeof fieldbuf; - (void) strlcpy(fieldbuf, tmp, sz); - field = fieldbuf; - tmp += sz; - - (void) strlcpy(keybuf, key, sizeof keybuf); - fmtkey = keybuf; - if (strcmp(field, "alias") == 0) - { - /* - ** for alias lookups, replace any punctuation - ** characters with '-' - */ - - for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) - { - if (isascii(*tmp2) && ispunct(*tmp2)) - *tmp2 = '-'; - } - tmp2 = field; - } - else if (strcmp(field,"spacedname") == 0) - { - /* - ** for "spaced" name lookups, replace any - ** punctuation characters with a space - */ - - for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) - { - if (isascii(*tmp2) && ispunct(*tmp2) && - *tmp2 != '*') - *tmp2 = ' '; - } - tmp2 = &(field[6]); - } - else - tmp2 = field; - - if (LogLevel > 9) - sm_syslog(LOG_NOTICE, CurEnv->e_id, - "ph_map_lookup: query %s=\"%s\" return email", - tmp2, fmtkey); - if (tTd(38, 20)) - dprintf("ph_map_lookup: query %s=\"%s\" return email\n", - tmp2, fmtkey); - - j = 0; - - if (fprintf(pmap->ph_to_server, "query %s=%s return email\n", - tmp2, fmtkey) < 0) - message = "qi query command failed"; - else if (fflush(pmap->ph_to_server) != 0) - message = "qi fflush failed"; - else if ((server_data = ReadQi(pmap->ph_from_server, - &j)) == NULL) - message = "ReadQi() returned NULL"; - -#if _FFR_PHMAP_TIMEOUT - if ((hold_data[hold_data_idx] = server_data) != NULL) - { - /* save pointer for later free() */ - hold_data_idx++; - } -#endif /* _FFR_PHMAP_TIMEOUT */ - - if (server_data == NULL || - (server_data->code >= 400 && - server_data->code < 500)) - { - /* temporary failure */ - *pstat = EX_TEMPFAIL; -#if _FFR_PHMAP_TIMEOUT - break; -#else /* _FFR_PHMAP_TIMEOUT */ - if (server_data != NULL) - { - FreeQIR(server_data); - server_data = NULL; - } - return NULL; -#endif /* _FFR_PHMAP_TIMEOUT */ - } - - /* - ** if we found a single match, break out. - ** otherwise, try the next field. - */ - - if (j == 1) - break; - - /* - ** check for a single response which is an error: - ** ReadQi() doesn't set j on error responses, - ** but we should stop here instead of moving on if - ** it happens (e.g., alias found but email field empty) - */ - - for (qirp = server_data; - qirp != NULL && qirp->code < 0; - qirp++) - { - if (tTd(38, 20)) - dprintf("ph_map_lookup: QIR: %d:%d:%d:%s\n", - qirp->code, qirp->subcode, qirp->field, - (qirp->message ? qirp->message - : "[NULL]")); - if (qirp->code <= -500) - { - j = 0; - goto ph_map_lookup_abort; - } - } - -#if _FFR_PHMAP_TIMEOUT - } while (*tmp != '\0' && hold_data_idx < MAX_PH_FIELDS); -#else /* _FFR_PHMAP_TIMEOUT */ - } while (*tmp != '\0'); -#endif /* _FFR_PHMAP_TIMEOUT */ + /* perform lookup */ + i = ph_email_resolve(pmap->ph, key, pmap->ph_field_list, &value); + if (i == -1) + *pstat = EX_TEMPFAIL; + else if (i == PH_NOMATCH || i == PH_DATAERR) + *pstat = EX_UNAVAILABLE; ph_map_lookup_abort: -#if _FFR_PHMAP_TIMEOUT if (ev != NULL) clrevent(ev); /* ** Return EX_TEMPFAIL if the timer popped - ** or we got a temporary PH error */ if (*pstat == EX_TEMPFAIL) - ph_map_safeclose(map); - - /* if we didn't find a single match, bail out */ - if (*pstat == EX_OK && j != 1) - *pstat = EX_UNAVAILABLE; + { + save_errno = errno; + pmap->ph_fastclose = PH_FASTCLOSE; + ph_map_close(map); + errno = save_errno; + } if (*pstat == EX_OK) { - /* - ** skip leading whitespace and chop at first address - */ - - for (tmp = server_data->message; - isascii(*tmp) && isspace(*tmp); - tmp++) - continue; - - for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) - { - if (isascii(*tmp2) && isspace(*tmp2)) - { - *tmp2 = '\0'; - break; - } - } - if (tTd(38,20)) - dprintf("ph_map_lookup: %s => %s\n", key, tmp); + dprintf("ph_map_lookup: %s => %s\n", key, value); if (bitset(MF_MATCHONLY, map->map_mflags)) - message = map_rewrite(map, key, strlen(key), NULL); + return map_rewrite(map, key, strlen(key), NULL); else - message = map_rewrite(map, tmp, strlen(tmp), args); + return map_rewrite(map, value, strlen(value), args); } - /* - ** Deferred free() of returned server_data values - ** the deferral is to avoid the risk of a free() being - ** interrupted by the event timer. By now the timeout event - ** has been cleared and none of the data is still in use. - */ - - while (--hold_data_idx >= 0) - { - if (hold_data[hold_data_idx] != NULL) - FreeQIR(hold_data[hold_data_idx]); - } - - if (*pstat == EX_OK) - return message; - return NULL; -#else /* _FFR_PHMAP_TIMEOUT */ - /* if we didn't find a single match, bail out */ - if (j != 1) - { - *pstat = EX_UNAVAILABLE; - if (server_data != NULL) - { - FreeQIR(server_data); - server_data = NULL; - } - return NULL; - } - - /* - ** skip leading whitespace and chop at first address - */ - - for (tmp = server_data->message; - isascii(*tmp) && isspace(*tmp); - tmp++) - continue; - - for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) - { - if (isascii(*tmp2) && isspace(*tmp2)) - { - *tmp2 = '\0'; - break; - } - } - - if (tTd(38,20)) - dprintf("ph_map_lookup: %s => %s\n", key, tmp); - - if (bitset(MF_MATCHONLY, map->map_mflags)) - message = map_rewrite(map, key, strlen(key), NULL); - else - message = map_rewrite(map, tmp, strlen(tmp), args); - if (server_data != NULL) - { - FreeQIR(server_data); - server_data = NULL; - } - return message; -#endif /* _FFR_PHMAP_TIMEOUT */ } #endif /* PH_MAP */ /* diff -urN sendmail-8.11.6/sendmail/sendmail.h sendmail-8.11.6-libphclient-phmap/sendmail/sendmail.h --- sendmail-8.11.6/sendmail/sendmail.h Wed Aug 15 16:59:08 2001 +++ sendmail-8.11.6-libphclient-phmap/sendmail/sendmail.h Thu Aug 30 14:49:37 2001 @@ -1010,18 +1010,18 @@ */ #ifdef PH_MAP + +# include + struct ph_map_struct { char *ph_servers; /* list of ph servers */ char *ph_field_list; /* list of fields to search for match */ - FILE *ph_to_server; - FILE *ph_from_server; - int ph_sockfd; - time_t ph_timeout; + PH *ph; /* PH server handle */ + int ph_fastclose; /* send "quit" command on close */ + time_t ph_timeout; /* timeout interval */ }; typedef struct ph_map_struct PH_MAP_STRUCT; - -# define DEFAULT_PH_MAP_FIELDS "alias callsign name spacedname" #endif /* PH_MAP */ /* ** Process List (proclist)