Description: resolvconf support
 Makes dibbler resolvconf aware.

Author: Joerg Dorchain <joerg@dorchain.net>
Bug-Debian: http://bugs.debian.org/519805
Bug-Debian: http://bugs.debian.org/627317
Bug-Debian: http://bugs.debian.org/627786
Forwarded: no

--- dibbler-0.8.1.orig/Misc/Portable.h
+++ dibbler-0.8.1/Misc/Portable.h
@@ -164,6 +164,7 @@ struct link_state_notify_t
 #define SRVCONF_FILE       "/etc/dibbler/server.conf"
 #define RELCONF_FILE       "/etc/dibbler/relay.conf"
 #define RESOLVCONF_FILE    "/etc/resolv.conf"
+#define RESOLVCONF         "/sbin/resolvconf"
 #define NTPCONF_FILE       "/etc/ntp.conf"
 #define TIMEZONE_FILE      "/etc/localtime"
 #define TIMEZONES_DIR      "/usr/share/zoneinfo"
--- dibbler-0.8.1.orig/Port-linux/lowlevel-options-linux.c
+++ dibbler-0.8.1/Port-linux/lowlevel-options-linux.c
@@ -31,6 +31,46 @@
 
 extern char * Message;
 
+/* check whether the resolconf executable exists
+ * if not, return NULL,
+ * else return a pipe to it
+ * the pipe needs to be closed by the caller
+ *
+ * @param arg1
+ * @param arg2
+ * are command line arguments to resolvconf (-a|-d, "IFNAME")
+ */
+FILE *resolvconf_open(const char *arg1, const char *arg2)
+{
+    pid_t child;
+    int pipefd[2];
+
+    if (access(RESOLVCONF, X_OK) != 0)
+         return NULL;
+    if (pipe(pipefd) != 0)
+        return NULL;
+    switch(child=fork()) {
+      case 0: /* child */
+          close(pipefd[1]);
+	  close(0);
+	  dup(pipefd[0]);
+	  close(pipefd[0]);
+	  /* double fork so init reaps the child */
+	  if (!fork()) { /* child */
+	  	execl(RESOLVCONF, RESOLVCONF, arg1, arg2, (char *)NULL);
+	  } /* All other cases are meaningless here */
+	  exit(-1);
+	  break;
+      case -1: /* error */
+          return NULL;
+	  break;
+    }
+    /* parent */
+    close(pipefd[0]);
+    waitpid(child, NULL, 0);
+    return fdopen(pipefd[1], "w");
+}
+
 /* in iproute.c, borrowed from iproute2 */
 extern int iproute_modify(int cmd, unsigned flags, int argc, char **argv);
 
@@ -166,15 +206,18 @@ int cfg_file_del(const char *file, const
 int dns_add(const char * ifname, int ifaceid, const char * addrPlain) {
     FILE * f;
     unsigned char c;
-    if ( !(f=fopen(RESOLVCONF_FILE,"a+"))) {
-	return LOWLEVEL_ERROR_FILE;
-    }
 
-    fseek(f, -1, SEEK_END);
-    c = fgetc(f);
-    fseek(f,0, SEEK_END);
-    if ( (c!=CR) && (c!=LF) ) {
-	fprintf(f,"\n");
+    if ( !(f=resolvconf_open("-a", ifname))) {
+	    if ( !(f=fopen(RESOLVCONF_FILE,"a+"))) {
+		return LOWLEVEL_ERROR_FILE;
+	    }
+
+	    fseek(f, -1, SEEK_END);
+	    c = fgetc(f);
+	    fseek(f,0, SEEK_END);
+	    if ( (c!=CR) && (c!=LF) ) {
+		fprintf(f,"\n");
+	    }
     }
 
     fprintf(f,"nameserver %s\n",addrPlain);
@@ -183,7 +226,12 @@ int dns_add(const char * ifname, int ifa
 }
 
 int dns_del(const char * ifname, int ifaceid, const char *addrPlain) {
-    return cfg_file_del(RESOLVCONF_FILE, "nameserver", addrPlain);
+    FILE *f;
+    
+    if ( !(f=resolvconf_open("-d", ifname)))
+	    return cfg_file_del(RESOLVCONF_FILE, "nameserver", addrPlain);
+    fclose(f);
+    return LOWLEVEL_NO_ERROR;
 }
 
 int domain_add(const char* ifname, int ifaceid, const char* domain) {
@@ -193,45 +241,54 @@ int domain_add(const char* ifname, int i
     unsigned char c;
     struct stat st;
 
-    memset(&st,0,sizeof(st));
-    stat(RESOLVCONF_FILE, &st);
-
-    unlink(RESOLVCONF_FILE".old");
-    rename(RESOLVCONF_FILE,RESOLVCONF_FILE".old");
-    if ( !(f = fopen(RESOLVCONF_FILE".old","r")) )
-	return LOWLEVEL_ERROR_FILE;
-    if ( !(f2= fopen(RESOLVCONF_FILE,"w+")))
-	return LOWLEVEL_ERROR_FILE;
-    while (fgets(buf,511,f)) {
-	if ( (!found) && (strstr(buf, "search")) ) {
-	    if (strlen(buf))
-		buf[strlen(buf)-1]=0;
-	    fprintf(f2, "%s %s\n", buf, domain);
-	    found = 1;
-	    continue;
-	}
-	fprintf(f2,"%s",buf);
-    }
+    if ( !(f=resolvconf_open("-a", ifname))) {
+	    memset(&st,0,sizeof(st));
+	    stat(RESOLVCONF_FILE, &st);
+
+	    unlink(RESOLVCONF_FILE".old");
+	    rename(RESOLVCONF_FILE,RESOLVCONF_FILE".old");
+	    if ( !(f = fopen(RESOLVCONF_FILE".old","r")) )
+		return LOWLEVEL_ERROR_FILE;
+	    if ( !(f2= fopen(RESOLVCONF_FILE,"w+")))
+		return LOWLEVEL_ERROR_FILE;
+	    while (fgets(buf,511,f)) {
+		if ( (!found) && (strstr(buf, "search")) ) {
+		    if (strlen(buf))
+			buf[strlen(buf)-1]=0;
+		    fprintf(f2, "%s %s\n", buf, domain);
+		    found = 1;
+		    continue;
+		}
+		fprintf(f2,"%s",buf);
+	    }
 
-    fseek(f2, -1, SEEK_END);
-    c = fgetc(f2);
-    fseek(f2,0, SEEK_END);
-    if ( (c!=CR) && (c!=LF) ) {
-	fprintf(f2,"\n");
-    }
+	    fseek(f2, -1, SEEK_END);
+	    c = fgetc(f2);
+	    fseek(f2,0, SEEK_END);
+	    if ( (c!=CR) && (c!=LF) ) {
+		fprintf(f2,"\n");
+	    }
 
-    if (!found)
-	fprintf(f2,"search %s\n",domain);
+	    if (!found)
+		fprintf(f2,"search %s\n",domain);
 
-    fclose(f);
-    fclose(f2);
-    chmod(RESOLVCONF_FILE,st.st_mode);
+	    fclose(f);
+	    fclose(f2);
+	    chmod(RESOLVCONF_FILE,st.st_mode);
+    } else {
+            fprintf(f, "search %s\n", domain);
+	    fclose(f);
+    }
 
     return LOWLEVEL_NO_ERROR;
 }
 
 int domain_del(const char * ifname, int ifaceid, const char *domain) {
-    return cfg_file_del(RESOLVCONF_FILE, "search", domain);
+    FILE * f;
+    if ( !(f=resolvconf_open("-d", ifname)))
+	    return cfg_file_del(RESOLVCONF_FILE, "search", domain);
+    fclose(f);
+    return LOWLEVEL_NO_ERROR;
 }
 
 int ntp_add(const char* ifname, const int ifindex, const char* addrPlain){
