Use safe SIGINT handler
authorJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sun, 20 Nov 2016 11:10:55 +0000 (12:10 +0100)
committerJoseph C. Lehner <joseph.c.lehner@gmail.com>
Sun, 20 Nov 2016 11:22:15 +0000 (12:22 +0100)
ethsock.c
nmrp.c
nmrpd.h
tftp.c
util.c

index 3219a0dfa20085b05b4f2d8fc6e45fc48c819ae0..1664f7fd0490306e4750e4369eade9468f2d92b1 100644 (file)
--- a/ethsock.c
+++ b/ethsock.c
@@ -100,7 +100,7 @@ static bool get_intf_info(const char *intf, uint8_t *hwaddr, void *dummy)
        bool found;
 
        if (getifaddrs(&ifas) != 0) {
-               perror("getifaddrs");
+               xperror("getifaddrs");
                return false;
        }
 
@@ -152,7 +152,7 @@ static bool get_intf_info(const char *intf, uint8_t *hwaddr, DWORD *index)
 
        adapters = malloc(bufLen);
        if (!adapters) {
-               perror("malloc");
+               xperror("malloc");
                return false;
        }
 
@@ -285,7 +285,7 @@ struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
 
        sock = malloc(sizeof(struct ethsock));
        if (!sock) {
-               perror("malloc");
+               xperror("malloc");
                return NULL;
        }
 
@@ -492,7 +492,7 @@ static int ethsock_arp(struct ethsock *sock, uint8_t *hwaddr, uint32_t ipaddr, s
 
                *undo = malloc(sizeof(struct ethsock_arp_undo));
                if (!*undo) {
-                       perror("malloc");
+                       xperror("malloc");
                        return -1;
                }
 
@@ -683,7 +683,7 @@ static bool set_interface_up(int fd, const char *intf, bool up)
        strncpy(ifr.ifr_name, intf, IFNAMSIZ);
 
        if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
-               perror("ioctl(SIOCGIFFLAGS)");
+               xperror("ioctl(SIOCGIFFLAGS)");
                return false;
        }
 
@@ -694,7 +694,7 @@ static bool set_interface_up(int fd, const char *intf, bool up)
        }
 
        if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
-               perror("ioctl(SIOCSIFFLAGS)");
+               xperror("ioctl(SIOCSIFFLAGS)");
                return false;
        }
 
@@ -706,7 +706,7 @@ static bool set_interface_up(int fd, const char *intf, bool up)
 int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struct ethsock_ip_undo **undo)
 {
        if (undo && !(*undo = malloc(sizeof(struct ethsock_ip_undo)))) {
-               perror("malloc");
+               xperror("malloc");
                return -1;
        }
 
@@ -729,13 +729,13 @@ int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struc
        if (add) {
                set_addr(&ifr.ifr_addr, ipaddr);
                if (ioctl(fd, SIOCSIFADDR, &ifr) != 0) {
-                       perror("ioctl(SIOSIFADDR)");
+                       xperror("ioctl(SIOSIFADDR)");
                        goto out;
                }
 
                set_addr(&ifr.ifr_netmask, ipmask);
                if (ioctl(fd, SIOCSIFNETMASK, &ifr) != 0) {
-                       perror("ioctl(SIOCSIFNETMASK)");
+                       xperror("ioctl(SIOCSIFNETMASK)");
                        goto out;
                }
 
@@ -756,7 +756,7 @@ int ethsock_ip_add(struct ethsock *sock, uint32_t ipaddr, uint32_t ipmask, struc
        //set_addr(&ifra.ifra_broadaddr, (ipaddr & ipmask) | ~ipmask);
 
        if (ioctl(fd, add ? SIOCAIFADDR : SIOCDIFADDR, &ifra) != 0) {
-               perror(add ? "ioctl(SIOCAIFADDR)" : "ioctl(SIOCDIFADDR)");
+       xperroradd ? "ioctl(SIOCAIFADDR)" : "ioctl(SIOCDIFADDR)");
                goto out;
        }
 
diff --git a/nmrp.c b/nmrp.c
index c1bfb9c747936bd60d79e33219a391d93cf74748..80dcb8f14b83bdb584ffe4d48a19ac59241fcadb 100644 (file)
--- a/nmrp.c
+++ b/nmrp.c
@@ -385,21 +385,9 @@ static int is_valid_ip(struct ethsock *sock, struct in_addr *ipaddr,
        return status < 0 ? status : arg.result;
 }
 
-static struct ethsock *gsock = NULL;
-static struct ethsock_ip_undo *g_ip_undo = NULL;
-static struct ethsock_arp_undo *g_arp_undo = NULL;
-
 static void sigh(int sig)
 {
-       printf("\n");
-       if (gsock) {
-               ethsock_arp_del(gsock, &g_arp_undo);
-               ethsock_ip_del(gsock, &g_ip_undo);
-               ethsock_close(gsock);
-               gsock = NULL;
-       }
-
-       exit(1);
+       g_interrupted = 1;
 }
 
 static const char *spinner = "\\|/-";
@@ -413,6 +401,8 @@ int nmrp_do(struct nmrpd_args *args)
        time_t beg;
        int i, status, ulreqs, expect, upload_ok, autoip;
        struct ethsock *sock;
+       struct ethsock_ip_undo *ip_undo = NULL;
+       struct ethsock_arp_undo *arp_undo = NULL;
        uint32_t intf_addr;
        void (*sigh_orig)(int);
        struct {
@@ -493,7 +483,6 @@ int nmrp_do(struct nmrpd_args *args)
                return 1;
        }
 
-       gsock = sock;
        sigh_orig = signal(SIGINT, sigh);
 
        if (!autoip) {
@@ -510,7 +499,7 @@ int nmrp_do(struct nmrpd_args *args)
                        printf("Adding %s to interface %s.\n", args->ipaddr_intf, args->intf);
                }
 
-               if (ethsock_ip_add(sock, intf_addr, ipconf.mask.s_addr, &g_ip_undo) != 0) {
+               if (ethsock_ip_add(sock, intf_addr, ipconf.mask.s_addr, &ip_undo) != 0) {
                        goto out;
                }
        }
@@ -536,14 +525,14 @@ int nmrp_do(struct nmrpd_args *args)
        upload_ok = 0;
        beg = time_monotonic();
 
-       while (1) {
+       while (!g_interrupted) {
                printf("\rAdvertising NMRP server on %s ... %c",
                                args->intf, spinner[i]);
                fflush(stdout);
                i = (i + 1) & 3;
 
                if (pkt_send(sock, &tx) < 0) {
-                       perror("sendto");
+                       xperror("sendto");
                        goto out;
                }
 
@@ -568,7 +557,7 @@ int nmrp_do(struct nmrpd_args *args)
        expect = NMRP_C_CONF_REQ;
        ulreqs = 0;
 
-       do {
+       while (!g_interrupted) {
                if (expect != NMRP_C_NONE && rx.msg.code != expect) {
                        fprintf(stderr, "Received %s while waiting for %s!\n",
                                        msg_code_str(rx.msg.code), msg_code_str(expect));
@@ -606,7 +595,7 @@ int nmrp_do(struct nmrpd_args *args)
                                printf("Sending configuration: %s, netmask %s.\n",
                                                args->ipaddr, args->ipmask);
 
-                               if (ethsock_arp_add(sock, rx.eh.ether_shost, ipconf.addr.s_addr, &g_arp_undo) != 0) {
+                               if (ethsock_arp_add(sock, rx.eh.ether_shost, ipconf.addr.s_addr, &arp_undo) != 0) {
                                        goto out;
                                }
 
@@ -714,7 +703,7 @@ int nmrp_do(struct nmrpd_args *args)
                        msg_hton(&tx.msg);
 
                        if (pkt_send(sock, &tx) < 0) {
-                               perror("sendto");
+                               xperror("sendto");
                                goto out;
                        }
 
@@ -739,21 +728,21 @@ int nmrp_do(struct nmrpd_args *args)
 
                ethsock_set_timeout(sock, args->rx_timeout);
 
-       } while (1);
-
-       status = 0;
+       }
 
-       if (ulreqs) {
-               printf("Reboot your device now.\n");
-       } else {
-               printf("No upload request received.\n");
+       if (!g_interrupted) {
+               status = 0;
+               if (ulreqs) {
+                       printf("Reboot your device now.\n");
+               } else {
+                       printf("No upload request received.\n");
+               }
        }
 
 out:
        signal(SIGINT, sigh_orig);
-       gsock = NULL;
-       ethsock_arp_del(sock, &g_arp_undo);
-       ethsock_ip_del(sock, &g_ip_undo);
+       ethsock_arp_del(sock, &arp_undo);
+       ethsock_ip_del(sock, &ip_undo);
        ethsock_close(sock);
        return status;
 }
diff --git a/nmrpd.h b/nmrpd.h
index ce424e3fe6a1a1788ce0c3b484f8552d3d8d2136..8d2c73074713d8aab97ce7857b2708393b048518 100644 (file)
--- a/nmrpd.h
+++ b/nmrpd.h
 #ifndef NMRPD_H
 #define NMRPD_H
 #include <stdint.h>
+#include <signal.h>
 #include <stdbool.h>
 
 #if defined(_WIN32) || defined(_WIN64)
 #      define NMRPFLASH_WINDOWS
-#else
+#elif defined (__unix__)
 #      define NMRPFLASH_UNIX
 #      if defined(__linux__)
 #              define NMRPFLASH_LINUX
 #      elif defined(__APPLE__) && defined(__MACH__)
 #              define NMRPFLASH_OSX
 #              define NMRPFLASH_BSD
-#      elif defined(__unix__)
-#              if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
+#      elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
 #                      define NMRPFLASH_BSD
-#              else
-#                      warning "nmrpflash is not fully supported on your operating system"
-#              endif
+#      else
+#              warning "nmrpflash is not fully supported on this platform"
 #      endif
+#else
+#      warning "nmrpflash is not supported on this platform"
 #endif
 
 #ifndef NMRPFLASH_WINDOWS
@@ -105,7 +106,7 @@ const char *mac_to_str(uint8_t *mac);
 void win_perror2(const char *msg, DWORD err);
 void sock_perror(const char *msg);
 #else
-#define sock_perror(x) perror(x)
+#define sock_perror(x) xperror(x)
 #endif
 
 extern int verbosity;
@@ -142,4 +143,7 @@ time_t time_monotonic();
 char *lltostr(long long ll, int base);
 uint32_t bitcount(uint32_t n);
 uint32_t netmask(uint32_t count);
+void xperror(const char *msg);
+
+extern volatile sig_atomic_t g_interrupted;
 #endif
diff --git a/tftp.c b/tftp.c
index bb4d818d64e8594d672c1c336edf1230cf49cfd8..a291ac0ac0c521e5c1994958d57e4228c7026d8e 100644 (file)
--- a/tftp.c
+++ b/tftp.c
@@ -239,6 +239,10 @@ int tftp_put(struct nmrpd_args *args)
        sock = -1;
        ret = -1;
 
+       if (g_interrupted) {
+               goto cleanup;
+       }
+
        if (!strcmp(args->file_local, "-")) {
                fd = STDIN_FILENO;
                if (!file_remote) {
@@ -247,7 +251,7 @@ int tftp_put(struct nmrpd_args *args)
        } else {
                fd = open(args->file_local, O_RDONLY | O_BINARY);
                if (fd < 0) {
-                       perror("open");
+                       xperror("open");
                        ret = fd;
                        goto cleanup;
                } else if (!file_remote) {
@@ -268,7 +272,7 @@ int tftp_put(struct nmrpd_args *args)
 
        if (args->ipaddr_intf) {
                if ((addr.sin_addr.s_addr = inet_addr(args->ipaddr_intf)) == INADDR_NONE) {
-                       perror("inet_addr");
+                       xperror("inet_addr");
                        goto cleanup;
                }
 
@@ -279,7 +283,7 @@ int tftp_put(struct nmrpd_args *args)
        }
 
        if ((addr.sin_addr.s_addr = inet_addr(args->ipaddr)) == INADDR_NONE) {
-               perror("inet_addr");
+               xperror("inet_addr");
                goto cleanup;
        }
        addr.sin_port = htons(args->port);
@@ -293,7 +297,7 @@ int tftp_put(struct nmrpd_args *args)
 
        pkt_mkwrq(tx, file_remote);
 
-       do {
+       while (!g_interrupted) {
                if (!timeout && pkt_num(rx) == ACK) {
                        ackblock = pkt_num(rx + 2);
                } else {
@@ -307,7 +311,7 @@ int tftp_put(struct nmrpd_args *args)
                                pkt_mknum(tx + 2, block);
                                len = read(fd, tx + 4, 512);
                                if (len < 0) {
-                                       perror("read");
+                                       xperror("read");
                                        ret = len;
                                        goto cleanup;
                                } else if (!len) {
@@ -361,9 +365,9 @@ int tftp_put(struct nmrpd_args *args)
                                addr.sin_port = htons(port);
                        }
                }
-       } while(1);
+       }
 
-       ret = 0;
+       ret = !g_interrupted ? 0 : -1;
 
 cleanup:
        if (fd >= 0) {
diff --git a/util.c b/util.c
index a1b2c521b6d5f10000bdd6263a5c9354f4a9c5d2..2529650127ccd2240c16d93b5aea8d39a8896d58 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <errno.h>
 #include <time.h>
 #include <math.h>
 #include "nmrpd.h"
@@ -7,6 +8,8 @@
 #include <mach/mach_time.h>
 #endif
 
+volatile sig_atomic_t g_interrupted = 0;
+
 time_t time_monotonic()
 {
 #ifndef NMRPFLASH_WINDOWS
@@ -49,3 +52,12 @@ uint32_t netmask(uint32_t count)
 {
        return htonl(count <= 32 ? 0xffffffff << (32 - count) : 0);
 }
+
+void xperror(const char *msg)
+{
+       if (errno != EINTR) {
+               perror(msg);
+       } else {
+               printf("\n");
+       }
+}