diff --git a/.gitignore b/.gitignore index e4a206d60f..b9f50c3c40 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ Makefile.in /configure /conf_nut_report_feature /conf??????/ +/dir.??????/ /cscope.* /depcomp /INSTALL diff --git a/clients/upsc.c b/clients/upsc.c index beb49bdd54..835b34d9ee 100644 --- a/clients/upsc.c +++ b/clients/upsc.c @@ -229,7 +229,9 @@ int main(int argc, char **argv) case 'V': fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_SUCCESS); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif case 'h': default: diff --git a/clients/upscmd.c b/clients/upscmd.c index 9061983f16..ea6fa93675 100644 --- a/clients/upscmd.c +++ b/clients/upscmd.c @@ -257,7 +257,9 @@ int main(int argc, char **argv) case 'V': fatalx(EXIT_SUCCESS, "Network UPS Tools upscmd %s", UPS_VERSION); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_SUCCESS); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif case 'h': default: diff --git a/clients/upsimage.c b/clients/upsimage.c index e9b92d38be..30c6ecc073 100644 --- a/clients/upsimage.c +++ b/clients/upsimage.c @@ -111,6 +111,9 @@ static int get_imgarg(const char *name) } /* write the HTML header then have gd dump the image */ +static void drawimage(gdImagePtr im) + __attribute__((noreturn)); + static void drawimage(gdImagePtr im) { printf("Pragma: no-cache\n"); diff --git a/clients/upslog.c b/clients/upslog.c index d57b906855..8401718378 100644 --- a/clients/upslog.c +++ b/clients/upslog.c @@ -110,6 +110,9 @@ static void setup_signals(void) fatal_with_errno(EXIT_FAILURE, "Can't install SIGUSR1 handler"); } +static void help(const char *prog) + __attribute__((noreturn)); + static void help(const char *prog) { printf("UPS status logger.\n"); @@ -403,7 +406,9 @@ int main(int argc, char **argv) switch(i) { case 'h': help(prog); +#ifndef HAVE___ATTRIBUTE__NORETURN break; +#endif case 's': monhost = optarg; diff --git a/clients/upsmon.c b/clients/upsmon.c index f3d0157944..4d1d883afd 100644 --- a/clients/upsmon.c +++ b/clients/upsmon.c @@ -418,6 +418,9 @@ static void set_pdflag(void) } /* the actual shutdown procedure */ +static void doshutdown(void) + __attribute__((noreturn)); + static void doshutdown(void) { int ret; @@ -1671,11 +1674,14 @@ static int check_pdflag(void) return EXIT_SUCCESS; } -static void help(const char *progname) +static void help(const char *arg_progname) + __attribute__((noreturn)); + +static void help(const char *arg_progname) { printf("Monitors UPS servers and may initiate shutdown if necessary.\n\n"); - printf("usage: %s [OPTIONS]\n\n", progname); + printf("usage: %s [OPTIONS]\n\n", arg_progname); printf(" -c send command to running process\n"); printf(" commands:\n"); printf(" - fsd: shutdown all master UPSes (use with caution)\n"); @@ -1692,6 +1698,9 @@ static void help(const char *progname) exit(EXIT_SUCCESS); } +static void runparent(int fd) + __attribute__((noreturn)); + static void runparent(int fd) { int ret; @@ -1747,7 +1756,9 @@ static void start_pipe(void) close(pipefd[1]); runparent(pipefd[0]); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* NOTREACHED */ +#endif } close(pipefd[0]); @@ -1933,7 +1944,9 @@ int main(int argc, char *argv[]) break; case 'h': help(argv[0]); +#ifndef HAVE___ATTRIBUTE__NORETURN break; +#endif case 'K': checking_flag = 1; break; @@ -1955,7 +1968,9 @@ int main(int argc, char *argv[]) break; default: help(argv[0]); +#ifndef HAVE___ATTRIBUTE__NORETURN break; +#endif } } diff --git a/clients/upsset.c b/clients/upsset.c index ba199a3010..a239426ed4 100644 --- a/clients/upsset.c +++ b/clients/upsset.c @@ -253,6 +253,10 @@ static void do_pickups(const char *currfunc) printf("\n"); } +static void error_page(const char *next, const char *title, + const char *fmt, ...) + __attribute__((noreturn)); + static void error_page(const char *next, const char *title, const char *fmt, ...) { @@ -282,6 +286,9 @@ static void error_page(const char *next, const char *title, exit(EXIT_SUCCESS); } +static void loginscreen(void) + __attribute__((noreturn)); + static void loginscreen(void) { do_header("Login"); @@ -506,6 +513,9 @@ static void send_auth(const char *next) "Password set failed: %s", upscli_strerror(&ups)); } +static void docmd(void) + __attribute__((noreturn)); + static void docmd(void) { char buf[SMALLBUF], *desc; @@ -768,6 +778,9 @@ static void print_rw(const char *upsname, const char *varname) printf("\n"); } +static void showsettings(void) + __attribute__((noreturn)); + static void showsettings(void) { int ret; @@ -910,6 +923,9 @@ static int setvar(const char *var, const char *val) } /* turn a form submission of settings into SET commands for upsd */ +static void savesettings(void) + __attribute__((noreturn)); + static void savesettings(void) { int changed = 0; @@ -956,6 +972,9 @@ static void savesettings(void) exit(EXIT_SUCCESS); } +static void initial_pickups(void) + __attribute__((noreturn)); + static void initial_pickups(void) { do_header("Select a UPS"); diff --git a/common/parseconf.c b/common/parseconf.c index 5729335d44..fe8f172b96 100644 --- a/common/parseconf.c +++ b/common/parseconf.c @@ -76,6 +76,8 @@ * */ +#include "common.h" + #include #include #include @@ -86,6 +88,7 @@ #include #include "parseconf.h" +#include "attribute.h" /* possible states */ @@ -98,6 +101,9 @@ #define STATE_ENDOFLINE 7 #define STATE_PARSEERR 8 +static void pconf_fatal(PCONF_CTX_t *ctx, const char *errtxt) + __attribute__((noreturn)); + static void pconf_fatal(PCONF_CTX_t *ctx, const char *errtxt) { if (ctx->errhandler) diff --git a/configure.ac b/configure.ac index 19595e3ea3..b3d6845e62 100644 --- a/configure.ac +++ b/configure.ac @@ -138,6 +138,7 @@ AC_C_BIGENDIAN AC_C_INLINE AC_C_FLEXIBLE_ARRAY_MEMBER AC_C_VARARRAYS +AX_C___ATTRIBUTE__ AC_CHECK_FUNCS(flock lockf fcvt fcvtl pow10 round abs_val abs) AC_CHECK_FUNCS(fabs, [], [], [#include ]) AC_CHECK_FUNCS(cfsetispeed tcsendbreak) diff --git a/drivers/apcupsd-ups.c b/drivers/apcupsd-ups.c index d1b2d3369a..32e2013a92 100644 --- a/drivers/apcupsd-ups.c +++ b/drivers/apcupsd-ups.c @@ -16,6 +16,8 @@ */ +#include "config.h" + #include #include #include @@ -24,6 +26,7 @@ #include "main.h" #include "apcupsd-ups.h" +#include "attribute.h" #define DRIVER_NAME "apcupsd network client UPS driver" #define DRIVER_VERSION "0.5" @@ -257,6 +260,9 @@ void upsdrv_updateinfo(void) poll_interval = (poll_interval > POLL_INTERVAL_MIN) ? POLL_INTERVAL_MIN : poll_interval; } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { fatalx(EXIT_FAILURE, "shutdown not supported"); diff --git a/drivers/bcmxcp_usb.c b/drivers/bcmxcp_usb.c index 242feaa22c..46af55f4b6 100644 --- a/drivers/bcmxcp_usb.c +++ b/drivers/bcmxcp_usb.c @@ -195,7 +195,7 @@ int get_answer(unsigned char *data, unsigned char command) } if (need_data > 0) /* We need more data */ - continue; + continue; /* Now validate XCP frame */ /* Check header */ @@ -204,7 +204,7 @@ int get_answer(unsigned char *data, unsigned char command) /* Sometime we read something wrong. bad cables? bad ports? */ my_buf = memchr(my_buf, PW_COMMAND_START_BYTE, bytes_read); if (!my_buf) - return -1; + return -1; } /* Read block number byte */ @@ -263,9 +263,9 @@ int get_answer(unsigned char *data, unsigned char command) end_length += length; tail = bytes_read - (length + PW_HEADER_SIZE); if (tail > 0) - my_buf = memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, tail); + my_buf = memmove(&buf[0], my_buf + length + PW_HEADER_SIZE, tail); else if (tail == 0) - my_buf = &buf[0]; + my_buf = &buf[0]; bytes_read = tail; } @@ -345,6 +345,9 @@ void upsdrv_reconnect(void) } /* USB functions */ +static void nutusb_open_error(const char *port) + __attribute__((noreturn)); + static void nutusb_open_error(const char *port) { printf("Unable to find POWERWARE UPS device on USB bus (%s)\n\n", port); @@ -432,7 +435,7 @@ usb_dev_handle *nutusb_open(const char *port) { upsdebugx(1, "Can't reset POWERWARE USB endpoint: %s", usb_strerror()); if (dev_claimed) - usb_release_interface(dev_h, 0); + usb_release_interface(dev_h, 0); usb_reset(dev_h); sleep(5); /* Wait reconnect */ errout = 1; diff --git a/drivers/blazer.c b/drivers/blazer.c index fef9e1e4ed..c9592cc3fc 100644 --- a/drivers/blazer.c +++ b/drivers/blazer.c @@ -808,6 +808,8 @@ void upsdrv_updateinfo(void) dstate_dataok(); } +void upsdrv_shutdown(void) + __attribute__((noreturn)); void upsdrv_shutdown(void) { diff --git a/drivers/blazer_usb.c b/drivers/blazer_usb.c index 33f5c2dec5..d7f24c7ae0 100644 --- a/drivers/blazer_usb.c +++ b/drivers/blazer_usb.c @@ -435,11 +435,15 @@ int blazer_command(const char *cmd, char *buf, size_t buflen) { case -EBUSY: /* Device or resource busy */ fatal_with_errno(EXIT_FAILURE, "Got disconnected by another driver"); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif case -EPERM: /* Operation not permitted */ fatal_with_errno(EXIT_FAILURE, "Permissions problem"); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif case -EPIPE: /* Broken pipe */ if (usb_clear_halt(udev, 0x81) == 0) { diff --git a/drivers/clone.c b/drivers/clone.c index b9aec2478f..052184ecee 100644 --- a/drivers/clone.c +++ b/drivers/clone.c @@ -18,8 +18,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" #include "main.h" #include "parseconf.h" +#include "attribute.h" #include #include @@ -520,6 +522,9 @@ void upsdrv_updateinfo(void) } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { fatalx(EXIT_FAILURE, "shutdown not supported"); diff --git a/drivers/dstate.c b/drivers/dstate.c index b2c7b893df..348890d668 100644 --- a/drivers/dstate.c +++ b/drivers/dstate.c @@ -32,6 +32,7 @@ #include "dstate.h" #include "state.h" #include "parseconf.h" +#include "attribute.h" static int sockfd = -1, stale = 1, alarm_active = 0, ignorelb = 0; static char *sockfn = NULL; @@ -43,6 +44,9 @@ struct ups_handler upsh; /* this may be a frequent stumbling point for new users, so be verbose here */ +static void sock_fail(const char *fn) + __attribute__((noreturn)); + static void sock_fail(const char *fn) { int sockerr; diff --git a/drivers/dummy-ups.c b/drivers/dummy-ups.c index 7668a1de32..67f6ed2a03 100644 --- a/drivers/dummy-ups.c +++ b/drivers/dummy-ups.c @@ -139,10 +139,9 @@ void upsdrv_initinfo(void) } /* FIXME: commands and settable variable! */ break; - default: case MODE_NONE: + default: fatalx(EXIT_FAILURE, "no suitable definition found!"); - break; } upsh.instcmd = instcmd; @@ -188,6 +187,9 @@ void upsdrv_updateinfo(void) } } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { fatalx(EXIT_FAILURE, "shutdown not supported"); diff --git a/drivers/ivtscd.c b/drivers/ivtscd.c index b69864857a..fb483d0bbc 100644 --- a/drivers/ivtscd.c +++ b/drivers/ivtscd.c @@ -18,8 +18,10 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" #include "main.h" #include "serial.h" +#include "attribute.h" #define DRIVER_NAME "IVT Solar Controller driver" #define DRIVER_VERSION "0.02" @@ -177,6 +179,9 @@ void upsdrv_updateinfo(void) dstate_dataok(); } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { while (1) { diff --git a/drivers/libusb.c b/drivers/libusb.c index 6284d4396e..d4aa5c54d7 100644 --- a/drivers/libusb.c +++ b/drivers/libusb.c @@ -251,7 +251,15 @@ static int libusb_open(usb_dev_handle **udevp, USBDevice_t *curDevice, USBDevice goto next_device; } else if (ret==-1) { fatal_with_errno(EXIT_FAILURE, "matcher"); +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunreachable-code-break" +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif goto next_device; +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic pop +#endif } else if (ret==-2) { upsdebugx(2, "matcher: unspecified error"); goto next_device; diff --git a/drivers/liebert.c b/drivers/liebert.c index 3e8a025ce9..4df8b74a65 100644 --- a/drivers/liebert.c +++ b/drivers/liebert.c @@ -21,8 +21,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "config.h" #include "main.h" #include "serial.h" +#include "attribute.h" #define DRIVER_NAME "Liebert MultiLink UPS driver" #define DRIVER_VERSION "1.02" @@ -39,6 +41,9 @@ upsdrv_info_t upsdrv_info = { #define ML_ONBATTERY 0x55 +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { /* XXX: replace with a proper shutdown function (raise DTR) */ diff --git a/drivers/macosx-ups.c b/drivers/macosx-ups.c index 4873855ad8..5057caef86 100644 --- a/drivers/macosx-ups.c +++ b/drivers/macosx-ups.c @@ -18,7 +18,9 @@ * */ +#include "config.h" #include "main.h" +#include "attribute.h" #include @@ -257,6 +259,9 @@ void upsdrv_updateinfo(void) CFRelease(power_dictionary); } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ diff --git a/drivers/main.c b/drivers/main.c index a01250c764..e1ea9b0958 100644 --- a/drivers/main.c +++ b/drivers/main.c @@ -20,8 +20,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "common.h" #include "main.h" #include "dstate.h" +#include "attribute.h" /* data which may be useful to the drivers */ int upsfd = -1; @@ -77,6 +79,9 @@ void upsdrv_banner (void) } /* power down the attached load immediately */ +static void forceshutdown(void) + __attribute__((noreturn)); + static void forceshutdown(void) { upslogx(LOG_NOTICE, "Initiating UPS shutdown"); diff --git a/drivers/metasys.c b/drivers/metasys.c index 745644bd6c..9ea77e4d12 100644 --- a/drivers/metasys.c +++ b/drivers/metasys.c @@ -535,7 +535,6 @@ void upsdrv_initinfo(void) default: fatal_with_errno(EXIT_FAILURE, "Unknown UPS"); - break; } /* Get the serial number */ diff --git a/drivers/nut-ipmipsu.c b/drivers/nut-ipmipsu.c index 4878c5a308..4eeefc3d1f 100644 --- a/drivers/nut-ipmipsu.c +++ b/drivers/nut-ipmipsu.c @@ -136,6 +136,9 @@ void upsdrv_updateinfo(void) */ } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { fatalx(EXIT_FAILURE, "shutdown not supported"); diff --git a/drivers/nutdrv_atcl_usb.c b/drivers/nutdrv_atcl_usb.c index 147b7d9d84..597b3e0110 100644 --- a/drivers/nutdrv_atcl_usb.c +++ b/drivers/nutdrv_atcl_usb.c @@ -320,7 +320,15 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev goto next_device; case -1: fatal_with_errno(EXIT_FAILURE, "matcher"); +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunreachable-code-break" +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif goto next_device; +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic pop +#endif case -2: upsdebugx(4, "matcher: unspecified error"); goto next_device; diff --git a/drivers/nutdrv_qx.c b/drivers/nutdrv_qx.c index 9771e9f29f..55ed3c1e5e 100644 --- a/drivers/nutdrv_qx.c +++ b/drivers/nutdrv_qx.c @@ -35,7 +35,9 @@ #define DRIVER_VERSION "0.28" +#include "config.h" #include "main.h" +#include "attribute.h" #include @@ -1538,6 +1540,9 @@ int setvar(const char *varname, const char *val) } /* Try to shutdown the UPS */ +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { int retry; diff --git a/drivers/richcomm_usb.c b/drivers/richcomm_usb.c index 976d1c209e..79184fce61 100644 --- a/drivers/richcomm_usb.c +++ b/drivers/richcomm_usb.c @@ -312,7 +312,15 @@ static int usb_device_open(usb_dev_handle **handlep, USBDevice_t *device, USBDev goto next_device; case -1: fatal_with_errno(EXIT_FAILURE, "matcher"); +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunreachable-code-break" +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif goto next_device; +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic pop +#endif case -2: upsdebugx(4, "matcher: unspecified error"); goto next_device; diff --git a/drivers/riello_ser.c b/drivers/riello_ser.c index 0392259262..3b54fe2158 100644 --- a/drivers/riello_ser.c +++ b/drivers/riello_ser.c @@ -904,6 +904,9 @@ void upsdrv_updateinfo(void) */ } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ diff --git a/drivers/riello_usb.c b/drivers/riello_usb.c index 2143c31ed1..ddbfb7de76 100644 --- a/drivers/riello_usb.c +++ b/drivers/riello_usb.c @@ -358,11 +358,15 @@ int riello_command(uint8_t *cmd, uint8_t *buf, uint16_t length, uint16_t buflen) { case -EBUSY: /* Device or resource busy */ fatal_with_errno(EXIT_FAILURE, "Got disconnected by another driver"); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif case -EPERM: /* Operation not permitted */ fatal_with_errno(EXIT_FAILURE, "Permissions problem"); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif case -EPIPE: /* Broken pipe */ if (usb_clear_halt(udev, 0x81) == 0) { diff --git a/drivers/serial.c b/drivers/serial.c index 7725eea1d1..c2dd23fb77 100644 --- a/drivers/serial.c +++ b/drivers/serial.c @@ -21,6 +21,7 @@ #include "timehead.h" #include "serial.h" #include "main.h" +#include "attribute.h" #include #include @@ -36,6 +37,9 @@ static unsigned int comm_failures = 0; +static void ser_open_error(const char *port) + __attribute__((noreturn)); + static void ser_open_error(const char *port) { struct stat fs; diff --git a/drivers/skel.c b/drivers/skel.c index dc778ff28d..f3e0dba44d 100644 --- a/drivers/skel.c +++ b/drivers/skel.c @@ -12,7 +12,9 @@ * or docs/snmp-subdrivers.txt for SNMP devices */ +#include "config.h" #include "main.h" +#include "attribute.h" /* #include "serial.h" */ @@ -92,6 +94,9 @@ void upsdrv_updateinfo(void) */ } +void upsdrv_shutdown(void) + __attribute__((noreturn)); + void upsdrv_shutdown(void) { /* tell the UPS to shut down, then return - DO NOT SLEEP HERE */ diff --git a/drivers/tripplite_usb.c b/drivers/tripplite_usb.c index 622a64ba72..6d0f02f0f2 100644 --- a/drivers/tripplite_usb.c +++ b/drivers/tripplite_usb.c @@ -506,7 +506,9 @@ void usb_comm_fail(int res, const char *msg) case -EBUSY: upslogx(LOG_WARNING, "%s: Device claimed by another process", msg); fatalx(EXIT_FAILURE, "Terminating: EBUSY"); +#ifndef HAVE___ATTRIBUTE__NORETURN break; +#endif default: upslogx(LOG_WARNING, "%s: Device detached? (error %d: %s)", msg, res, usb_strerror()); @@ -735,7 +737,16 @@ static int control_outlet(int outlet_id, int state) } else { return 1; } +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunreachable-code-break" +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif break; +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic pop +#endif + case TRIPP_LITE_SMART_3005: snprintf(k_cmd, sizeof(k_cmd)-1, "N%c", 5); ret = send_cmd((unsigned char *)k_cmd, strlen(k_cmd) + 1, (unsigned char *)buf, sizeof buf); @@ -748,7 +759,16 @@ static int control_outlet(int outlet_id, int state) } else { return 1; } +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunreachable-code-break" +#pragma GCC diagnostic ignored "-Wunreachable-code" +#endif break; +#if defined (__GNUC__) || defined (__clang__) +#pragma GCC diagnostic pop +#endif + default: upslogx(LOG_ERR, "control_outlet unimplemented for protocol %04x", tl_model); } diff --git a/drivers/upsdrvctl.c b/drivers/upsdrvctl.c index 1f92f1f00f..f9f2d5d294 100644 --- a/drivers/upsdrvctl.c +++ b/drivers/upsdrvctl.c @@ -28,6 +28,7 @@ #include "proto.h" #include "common.h" #include "upsconf.h" +#include "attribute.h" typedef struct { char *upsname; @@ -330,6 +331,9 @@ static void start_driver(const ups_t *ups) } } +static void help(const char *progname) + __attribute__((noreturn)); + static void help(const char *progname) { printf("Starts and stops UPS drivers via ups.conf.\n\n"); @@ -491,7 +495,6 @@ int main(int argc, char **argv) case 'h': default: help(prog); - break; } } diff --git a/drivers/usbhid-ups.c b/drivers/usbhid-ups.c index ee04423311..e3eabe20cc 100644 --- a/drivers/usbhid-ups.c +++ b/drivers/usbhid-ups.c @@ -935,10 +935,14 @@ void upsdrv_initups(void) break; case -1: fatal_with_errno(EXIT_FAILURE, "HIDNewRegexMatcher()"); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif default: fatalx(EXIT_FAILURE, "invalid regular expression: %s", regex_array[ret]); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif } /* link the matchers */ diff --git a/include/attribute.h b/include/attribute.h index a51632db49..f6ce29b4f4 100644 --- a/include/attribute.h +++ b/include/attribute.h @@ -22,10 +22,50 @@ #ifndef NUT_ATTRIBUTE_H_SEEN #define NUT_ATTRIBUTE_H_SEEN 1 -#ifndef __attribute__ +/* To complicate matters, compilers with native support + * for the keyword may expose or not expose it as a macro... + * but for those that perform such courtesy, or are known + * supporters, we can put up the flag. For others, someone + * with those compilers should check and file PRs to NUT. + */ +#if (!defined HAVE___ATTRIBUTE__) || (HAVE___ATTRIBUTE__ == 0) # if ( defined(__GNUC__) && ( __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) ) ) || ( defined(__STRICT_ANSI__) && __STRICT_ANSI__ ) -# define __attribute__(x) +# ifndef __attribute__ +# define __attribute__(x) +# endif +# ifndef HAVE___ATTRIBUTE__ +# define HAVE___ATTRIBUTE__ 0 +# endif +# else +# if defined(__clang__) || defined(__GNUC__) || defined(__SUNPRO_C) +# ifndef HAVE___ATTRIBUTE__ +# define HAVE___ATTRIBUTE__ 1 +# endif +# else +# ifndef HAVE___ATTRIBUTE__ +# define HAVE___ATTRIBUTE__ 0 +# endif +# endif # endif #endif +#if (!defined HAVE___ATTRIBUTE__) || (HAVE___ATTRIBUTE__ == 0) +# ifdef HAVE___ATTRIBUTE__UNUSED_ARG +# undef HAVE___ATTRIBUTE__UNUSED_ARG +# endif +# ifdef HAVE___ATTRIBUTE__UNUSED_FUNC +# undef HAVE___ATTRIBUTE__UNUSED_FUNC +# endif +# ifdef HAVE___ATTRIBUTE__NORETURN +# undef HAVE___ATTRIBUTE__NORETURN +# endif +# ifdef HAVE___ATTRIBUTE__ +# undef HAVE___ATTRIBUTE__ +# endif +#endif + +/* Other source files now can simply check for `ifdef HAVE___ATTRIBUTE__*` + * as usual, and not bother about 0/1 values of the macro as well. + */ + #endif /* NUT_ATTRIBUTE_H_SEEN */ diff --git a/m4/ax_c___attribute__.m4 b/m4/ax_c___attribute__.m4 new file mode 100644 index 0000000000..625a46c589 --- /dev/null +++ b/m4/ax_c___attribute__.m4 @@ -0,0 +1,132 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_c___attribute__.html +# +# Downloaded into the Network UPS Tools (NUT) codebase from +# http://git.savannah.gnu.org/gitweb/?p=autoconf-archive.git;a=blob_plain;f=m4/ax_c___attribute__.m4 +# as of 2020-11-20 and adapted for attribute supports we needed +# =========================================================================== +# +# SYNOPSIS +# +# AX_C___ATTRIBUTE__ +# +# DESCRIPTION +# +# Provides a test for the compiler support of __attribute__ extensions. +# Defines HAVE___ATTRIBUTE__ if it is found. +# Also in particular defines +# HAVE___ATTRIBUTE__UNUSED_ARG +# HAVE___ATTRIBUTE__UNUSED_FUNC +# HAVE___ATTRIBUTE__NORETURN +# if support for respective values and use-cases of interest for NUT +# codebase is found. +# +# LICENSE +# +# Copyright (c) 2008 Stepan Kasal +# Copyright (c) 2008 Christian Haggstrom +# Copyright (c) 2008 Ryan McCabe +# Copyright (c) 2020 Jim Klimov +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 9 + +AC_DEFUN([AX_C___ATTRIBUTE__], [ + AC_CACHE_CHECK([for __attribute__((unused)) for function arguments], [ax_cv___attribute__unused_arg], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + static void foo( int); + static void + foo(__attribute__ ((unused)) int i) { + return; + } + ]], [func(1);])], + [ax_cv___attribute__unused_arg=yes], + [ax_cv___attribute__unused_arg=no] + ) + ]) + + AC_CACHE_CHECK([for __attribute__((unused)) for functions], [ax_cv___attribute__unused_func], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + static void foo(void) __attribute__ ((unused)); + static void + foo(void) { + return; + } + ]], [])], + [ax_cv___attribute__unused_func=yes], + [ax_cv___attribute__unused_func=no] + ) + ]) + + AC_CACHE_CHECK([for __attribute__((noreturn))], [ax_cv___attribute__noreturn], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + static void foo(void) __attribute__ ((noreturn)); + static void + foo(void) { + exit(1); + } + ]], [foo();])], + [ax_cv___attribute__noreturn=yes], + [ax_cv___attribute__noreturn=no] + ) + ]) + + AC_CACHE_CHECK([for at least some __attribute__ support], [ax_cv___attribute__], + [if test "$ax_cv___attribute__unused_arg" = "yes" \ + || test "$ax_cv___attribute__unused_func" = "yes" \ + || test "$ax_cv___attribute__noreturn" = "yes" \ + ; then + dnl # Some values did not error, support for keyword itself exists + ax_cv___attribute__=yes + else + dnl # At least none of the options we are interested in work... + ax_cv___attribute__=no + fi + ]) + + if test "$ax_cv___attribute__unused_arg" = "yes"; then + AC_DEFINE([HAVE___ATTRIBUTE__UNUSED_ARG], 1, [define if your compiler has __attribute__((unused)) for function arguments]) + fi + + if test "$ax_cv___attribute__unused_func" = "yes"; then + AC_DEFINE([HAVE___ATTRIBUTE__UNUSED_FUNC], 1, [define if your compiler has __attribute__((unused)) for functions]) + fi + if test "$ax_cv___attribute__noreturn" = "yes"; then + AC_DEFINE([HAVE___ATTRIBUTE__NORETURN], 1, [define if your compiler has __attribute__((noreturn))]) + fi + + if test "$ax_cv___attribute__" = "yes"; then + AC_DEFINE([HAVE___ATTRIBUTE__], 1, [define if your compiler has __attribute__]) + fi +]) diff --git a/server/upsd.c b/server/upsd.c index a9343f5f8c..8f96dabe39 100644 --- a/server/upsd.c +++ b/server/upsd.c @@ -1074,10 +1074,13 @@ static void mainloop(void) } } -static void help(const char *progname) +static void help(const char *arg_progname) + __attribute__((noreturn)); + +static void help(const char *arg_progname) { printf("Network server for UPS data.\n\n"); - printf("usage: %s [OPTIONS]\n", progname); + printf("usage: %s [OPTIONS]\n", arg_progname); printf("\n"); printf(" -c send via signal to background process\n"); @@ -1167,16 +1170,14 @@ int main(int argc, char **argv) while ((i = getopt(argc, argv, "+h46p:qr:i:fu:Vc:D")) != -1) { switch (i) { - case 'h': - help(progname); - break; - case 'p': case 'i': fatalx(EXIT_FAILURE, "Specifying a listening addresses with '-i
' and '-p '\n" "is deprecated. Use 'LISTEN
[]' in 'upsd.conf' instead.\n" "See 'man 8 upsd.conf' for more information."); +#ifndef HAVE___ATTRIBUTE__NORETURN exit(EXIT_FAILURE); /* Should not get here in practice, but compiler is afraid we can fall through */ +#endif case 'q': nut_log_level++; @@ -1217,9 +1218,9 @@ int main(int argc, char **argv) opt_af = AF_INET6; break; + case 'h': default: help(progname); - break; } }