]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
Rework controls
authorBaptiste Daroussin <bapt@FreeBSD.org>
Fri, 17 Dec 2021 07:52:28 +0000 (08:52 +0100)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Fri, 17 Dec 2021 07:52:28 +0000 (08:52 +0100)
Fix ctrlsizet by using the new strtouim instead of strtoim, size_t
is an unsigned.
Factorize ctrllong and ctrlint

Add test suite

include/utils.h
src/controls.c
src/utils.c
tests/mlmmj.c

index bb88aea41defe207cec9f80b06d04eac7a650193..b40b798f81270eca6596fa4937cd4675c38cdb9a 100644 (file)
@@ -27,5 +27,6 @@
 
 intmax_t strtoim(const char *, intmax_t, intmax_t, const char **);
 time_t strtotimet(const char *, const char **);
+uintmax_t strtouim(const char *, uintmax_t, uintmax_t, const char **);
 
 #endif
index 6a8306cefa6137c1a110e4c2cc1c8806d3e8eb74..b042d5cfac757dde61346b378deadfae56895cd6 100644 (file)
  * IN THE SOFTWARE.
  */
 
+#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/limits.h>
 
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -179,8 +182,8 @@ statctrl(struct mlmmj_list *list, const char *ctrlstr)
        return (true);
 }
 
-time_t
-ctrltimet(struct mlmmj_list *list, const char *ctrlstr)
+static intmax_t
+ctrlim(struct mlmmj_list *list, const char *ctrlstr, intmax_t min, intmax_t max)
 {
        const char *errstr;
        char *val = ctrlvalue(list, ctrlstr);
@@ -189,7 +192,7 @@ ctrltimet(struct mlmmj_list *list, const char *ctrlstr)
        if (val == NULL)
                return (0);
 
-       ret = strtotimet(val, &errstr);
+       ret = strtoim(val, min, max, &errstr);
        if (errstr != NULL) {
                log_error(LOG_ARGS, "Invalid value for '%s': %s", ctrlstr, errstr);
        }
@@ -197,17 +200,17 @@ ctrltimet(struct mlmmj_list *list, const char *ctrlstr)
        return (ret);
 }
 
-long
-ctrllong(struct mlmmj_list *list, const char *ctrlstr)
+time_t
+ctrltimet(struct mlmmj_list *list, const char *ctrlstr)
 {
        const char *errstr;
        char *val = ctrlvalue(list, ctrlstr);
-       long ret;
+       time_t ret;
 
        if (val == NULL)
                return (0);
 
-       ret = strtoim(val, LONG_MIN, LONG_MAX, &errstr);
+       ret = strtotimet(val, &errstr);
        if (errstr != NULL) {
                log_error(LOG_ARGS, "Invalid value for '%s': %s", ctrlstr, errstr);
        }
@@ -215,22 +218,16 @@ ctrllong(struct mlmmj_list *list, const char *ctrlstr)
        return (ret);
 }
 
+long
+ctrllong(struct mlmmj_list *list, const char *ctrlstr)
+{
+       return (ctrlim(list, ctrlstr, LONG_MIN, LONG_MAX));
+}
+
 int
 ctrlint(struct mlmmj_list *list, const char *ctrlstr)
 {
-       const char *errstr;
-       char *val = ctrlvalue(list, ctrlstr);
-       int ret;
-
-       if (val == NULL)
-               return (0);
-
-       ret = strtoim(val, INT_MIN, INT_MAX, &errstr);
-       if (errstr != NULL) {
-               log_error(LOG_ARGS, "Invalid value for '%s': %s", ctrlstr, errstr);
-       }
-       free(val);
-       return (ret);
+       return (ctrlim(list, ctrlstr, INT_MIN, INT_MAX));
 }
 
 size_t
@@ -238,12 +235,12 @@ ctrlsizet(struct mlmmj_list *list, const char *ctrlstr)
 {
        const char *errstr;
        char *val = ctrlvalue(list, ctrlstr);
-       size_t ret;
+       time_t ret;
 
        if (val == NULL)
                return (0);
 
-       ret = strtoim(val, 0, SIZE_T_MAX, &errstr);
+       ret = strtouim(val, 0, SIZE_MAX, &errstr);
        if (errstr != NULL) {
                log_error(LOG_ARGS, "Invalid value for '%s': %s", ctrlstr, errstr);
        }
index 661acb13c54117197accd772a23b32cf5d9f3760..6039585f59959383542ea2d3765123e4e4c66f97 100644 (file)
@@ -66,3 +66,35 @@ strtotimet(const char *np, const char **errpp)
                return ((time_t)strtoim(np, INT_MIN, INT_MAX, errpp));
        return ((time_t)strtoim(np, LLONG_MIN, LLONG_MAX, errpp));
 }
+
+uintmax_t
+strtouim(const char *np, uintmax_t minval, uintmax_t maxval, const char **errpp)
+{
+       char *endp;
+       uintmax_t ret;
+
+       *errpp = NULL;
+       if (minval > maxval || np == NULL) {
+               errno = EINVAL;
+               *errpp = "invalid";
+               return (0);
+       }
+       errno = 0;
+       ret = strtoumax(np, &endp, 10);
+       if (endp == np || *endp != '\0') {
+               errno = EINVAL;
+               *errpp = "invalid";
+               return (0);
+       }
+       if (ret < minval) {
+               errno = ERANGE;
+               *errpp = "too small";
+               return (0);
+       }
+       if (errno == ERANGE || ret > maxval) {
+               errno = ERANGE;
+               *errpp = "too large";
+               return (0);
+       }
+       return (ret);
+}
index 78ba9d924619a30e44d7dbd27ba10566f7f29170..adb8351569f763e3b5e2cbcc7bce182e97f07f2e 100644 (file)
@@ -63,6 +63,7 @@ ATF_TC(mygetline);
 ATF_TC(unsubscribe);
 ATF_TC(lowercase);
 ATF_TC(subbed);
+ATF_TC(controls);
 
 ATF_TC_HEAD(random_int, tc) { }
 ATF_TC_HEAD(statctrl, tc) { }
@@ -84,6 +85,7 @@ ATF_TC_HEAD(mygetline, tc) {}
 ATF_TC_HEAD(unsubscribe, tc) {}
 ATF_TC_HEAD(lowercase, tc) {}
 ATF_TC_HEAD(subbed, tc) {}
+ATF_TC_HEAD(controls, tc) {}
 
 #ifndef NELEM
 #define NELEM(array)    (sizeof(array) / sizeof((array)[0]))
@@ -319,6 +321,29 @@ ATF_TC_BODY(strtoim, tc)
        ATF_REQUIRE_EQ(errno, EINVAL);
        ATF_REQUIRE(errp != NULL);
        ATF_REQUIRE_STREQ(errp, "invalid");
+
+
+       ATF_REQUIRE_EQ(strtouim(NULL, 0, 10, &errp), 0);
+       ATF_REQUIRE(errp != NULL);
+       ATF_REQUIRE_STREQ(errp, "invalid");
+       ATF_REQUIRE_EQ(strtouim("10", 0, 10, &errp), 10);
+       ATF_CHECK(errp == NULL);
+       ATF_REQUIRE_EQ(strtouim("10", 0, 9, &errp), 0);
+       ATF_REQUIRE(errp != NULL);
+       ATF_REQUIRE_STREQ(errp, "too large");
+       ATF_REQUIRE_EQ(strtouim("1", 2, 9, &errp), 0);
+       ATF_REQUIRE(errp != NULL);
+       ATF_REQUIRE_STREQ(errp, "too small");
+       ATF_REQUIRE_EQ(strtouim("-1", 0, 9, &errp), 0);
+       ATF_REQUIRE(errp != NULL);
+       ATF_REQUIRE_STREQ(errp, "too large");
+       ATF_REQUIRE_EQ(strtouim("-1", 10, 9, &errp), 0);
+       ATF_REQUIRE(errp != NULL);
+       ATF_REQUIRE_STREQ(errp, "invalid");
+       ATF_REQUIRE_EQ(strtouim("ba12", 0, 9, &errp), 0);
+       ATF_REQUIRE_EQ(errno, EINVAL);
+       ATF_REQUIRE(errp != NULL);
+       ATF_REQUIRE_STREQ(errp, "invalid");
 }
 
 ATF_TC_BODY(strtotimet, tc)
@@ -511,6 +536,42 @@ ATF_TC_BODY(subbed, tc)
        ATF_CHECK_EQ(is_subbed(&list, "john@doe.org", false), SUB_NOMAIL);
 }
 
+ATF_TC_BODY(controls, tc)
+{
+       struct mlmmj_list list;
+       init_ml(true);
+       mlmmj_list_init(&list);
+       list.dir = "list";
+
+       ATF_CHECK(mlmmj_list_open(&list));
+       ATF_REQUIRE_EQ(rename("list/control", "list/notcontrol"), 0);
+       pid_t p = atf_utils_fork();
+       close(list.controlfd);
+       list.controlfd = -1;
+       if (p == 0) {
+               ctrlcontent(&list, "plop");
+       }
+       atf_utils_wait(p, 1, "", "mlmmj: Unable to open list/control\n");
+       ATF_REQUIRE_EQ(rename("list/notcontrol", "list/control"), 0);
+       ATF_REQUIRE_EQ(ctrlcontent(&list, "plop"), NULL);
+       ATF_REQUIRE_STREQ(ctrlcontent(&list, "listaddress"), "test@test");
+       ATF_REQUIRE_EQ(ctrltimet(&list, "listaddress"), 0);
+       ATF_REQUIRE_EQ(ctrltimet(&list, "plop"), 0);
+       FILE *f = fopen("list/control/val", "w");
+       fputs("12",f);
+       fclose(f);
+       ATF_REQUIRE_EQ(ctrltimet(&list, "val"), 12);
+       ATF_REQUIRE_EQ(ctrllong(&list, "listaddress"), 0);
+       ATF_REQUIRE_EQ(ctrllong(&list, "plop"), 0);
+       ATF_REQUIRE_EQ(ctrllong(&list, "val"), 12);
+       ATF_REQUIRE_EQ(ctrlint(&list, "listaddress"), 0);
+       ATF_REQUIRE_EQ(ctrlint(&list, "plop"), 0);
+       ATF_REQUIRE_EQ(ctrlint(&list, "val"), 12);
+       ATF_REQUIRE_EQ(ctrlsizet(&list, "listaddress"), 0);
+       ATF_REQUIRE_EQ(ctrlsizet(&list, "plop"), 0);
+       ATF_REQUIRE_EQ(ctrlsizet(&list, "val"), 12);
+}
+
 ATF_TP_ADD_TCS(tp)
 {
        ATF_TP_ADD_TC(tp, random_int);
@@ -533,6 +594,7 @@ ATF_TP_ADD_TCS(tp)
        ATF_TP_ADD_TC(tp, unsubscribe);
        ATF_TP_ADD_TC(tp, lowercase);
        ATF_TP_ADD_TC(tp, subbed);
+       ATF_TP_ADD_TC(tp, controls);
 
        return (atf_no_error());
 }