Fix losing static address mappings appended to hosts file

This commit is contained in:
df
2020-10-16 15:03:13 +01:00
parent a9dcc648ae
commit 302d113377

View File

@@ -84,7 +84,7 @@ background()
} }
#endif #endif
void freehostents( struct hostent * h) { static void freehostents( struct hostent * h) {
for (struct hostent *p = h; p->h_name; ++p) { for (struct hostent *p = h; p->h_name; ++p) {
free(p->h_name); free(p->h_name);
free(p->h_addr_list); free(p->h_addr_list);
@@ -92,22 +92,31 @@ void freehostents( struct hostent * h) {
free(h); free(h);
} }
struct hostent * add_host(struct hostent * hosts, const char * hostname, struct in_addr ip) { /*
* Add the mapping from hostname to in_addr_ip to the hosts block.
* The return value is the pointer to the next entry after the added entry.
* Case 1. The block is initially empty. Populate it with a loop like
* for (p = hosts,i=0;; p = add_host(p, hostname[i], addr[i],++i);
* Case 2. The block is in use. The added entry replaces the first one with
* h_length == 0.
*/
static struct hostent * add_host(struct hostent * hosts, const char * hostname, struct in_addr ip) {
struct hostent * p; struct hostent * p;
int newname = 1; int newname = 1;
for (p=hosts;p->h_name;++p) { for (p=hosts;p->h_name;++p) {
newname = 1;
if (p->h_length == 0 || if (p->h_length == 0 ||
0 == (newname = strcasecmp(p->h_name, hostname))) 0 == (newname = strcasecmp(p->h_name, hostname)))
break; break;
} }
if (p->h_name) { if (p->h_name) {
if (0 != newname) { if (0 != newname) {
/* reusing an entry with a new name */
free(p->h_name); free(p->h_name);
p->h_name = strdup(hostname); p->h_name = strdup(hostname);
} }
} else { } else {
/* new entry */
p->h_name = strdup(hostname); p->h_name = strdup(hostname);
(p+1)->h_name = 0; (p+1)->h_name = 0;
} }
@@ -198,12 +207,18 @@ struct hostent * read_hosts(unsigned int extra) {
struct in_addr it; struct in_addr it;
it.s_addr = inet_addr(ip); it.s_addr = inet_addr(ip);
do { do {
char * dot = strrchr(name, '.');
if (dot && 0 == strcasecmp(dot, ".local")) {
struct hostent * pp = add_host(p, name, it); struct hostent * pp = add_host(p, name, it);
char * dot = strrchr(p->h_name, '.');
if (dot && 0 == strcasecmp(dot, ".local"))
/* flag as expendable */ /* flag as expendable */
p->h_length = 0; p->h_length = 0;
p = pp; p = pp;
} else {
/* try to push down non-local names */
struct hostent * pp = add_host(hostents, name, it);
/* not pushed down -> appended */
if (pp > p) p = pp;
}
/* running out of space? try for more */ /* running out of space? try for more */
if (--nleft < extra + 1) { if (--nleft < extra + 1) {
@@ -249,7 +264,7 @@ struct hostent * read_hosts(unsigned int extra) {
return hostents; return hostents;
} }
int write_hosts(const struct hostent * hostents) { static int write_hosts(const struct hostent * hostents) {
int ret = -1; int ret = -1;
FILE * hosts = fopen( HOSTFILE, "w"); FILE * hosts = fopen( HOSTFILE, "w");
if (!hosts) { if (!hosts) {
@@ -257,7 +272,7 @@ int write_hosts(const struct hostent * hostents) {
return ret; return ret;
} }
for (const struct hostent * p = hostents;p->h_name;++p) { for (const struct hostent * p = hostents;p->h_name;++p) {
//printf( "writing %.255s\n", p->h_name); /* printf( "writing %.255s\n", p->h_name); */
if (p->h_length > 0) { if (p->h_length > 0) {
for (struct in_addr ** pa = (struct in_addr **)(p->h_addr_list); *pa; ++pa) { for (struct in_addr ** pa = (struct in_addr **)(p->h_addr_list); *pa; ++pa) {
ret = fprintf( hosts, "%s\t%s\n", inet_ntoa(**pa), p->h_name); ret = fprintf( hosts, "%s\t%s\n", inet_ntoa(**pa), p->h_name);
@@ -268,13 +283,19 @@ int write_hosts(const struct hostent * hostents) {
return ret; return ret;
} }
void dump_hosts(const struct hostent * hostents) { #if 0
static void dump_host(const struct hostent * hostent) {
printf( "Host: %.255s\t%.32s\t%d\n", hostent->h_name,
inet_ntoa(*(struct in_addr *)(hostent->h_addr_list[0])),
hostent->h_length);
}
static void dump_hosts(const struct hostent * hostents) {
for (const struct hostent * p = hostents;p->h_name;++p) { for (const struct hostent * p = hostents;p->h_name;++p) {
printf( "Host: %.255s\t%.32s\t%d\n", p->h_name, dump_host(p);
inet_ntoa(*(struct in_addr *)(p->h_addr_list[0])),
p->h_length);
} }
} }
#endif
static void handler_stop(int sig) { static void handler_stop(int sig) {
(void)sig; (void)sig;
@@ -381,17 +402,15 @@ main(int argc, char **argv)
return 1; return 1;
} }
//dump_hosts(hosts); //dump_hosts(hosts);
struct hostent * p = hosts;
/* recognise own .local hostname */ /* recognise own .local hostname */
p = add_host(p, fullname, saddr); struct hostent * p = add_host(hosts, fullname, saddr);
for (int i = 0; i < numserv; ++i) { for (int i = 0; i < numserv; ++i) {
struct in_addr it; struct in_addr it;
it.s_addr = svcinfo[i].ipaddr; it.s_addr = svcinfo[i].ipaddr;
printf("Host %d: %s (%s)\n", i, svcinfo[i].hostname, inet_ntoa(it)); printf("Host %d: %s (%s)\n", i, svcinfo[i].hostname, inet_ntoa(it));
p = add_host(p, svcinfo[i].hostname, it); p = add_host(p, svcinfo[i].hostname, it);
} }
p->h_name = 0; /* p->h_name = 0; */
//dump_hosts(hosts);
write_hosts(hosts); write_hosts(hosts);
freehostents(hosts); freehostents(hosts);
} }