#ifndef INCINDEXFILE_H
#define INCINDEXFILE_H
-int incindexfile(const char *listdir);
+#include "mlmmj.h"
+
+int incindexfile(struct mlmmj_list *list);
#endif /* INCINDEXFILE_H */
--- /dev/null
+/*
+ * Copyright (C) 2021 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef MLMMJ_UTILS_H
+#define MLMMJ_UTILS_H
+
+intmax_t strtoim(const char *, intmax_t, intmax_t, const char **);
+
+#endif
EXTRA_DIST = mlmmj-make-ml
mlmmj_send_SOURCES = mlmmj.c mlmmj-send.c mail-functions.c itoa.c chomp.c \
- incindexfile.c checkwait_smtpreply.c \
+ incindexfile.c checkwait_smtpreply.c utils.c \
mylocking.c init_sockfd.c strgen.c random-int.c \
print-version.c log_error.c mygetline.c memory.c \
controls.c getaddrsfromfd.c readn.c \
log_oper.c mylocking.c readn.c
mlmmj_process_SOURCES = mlmmj.c mlmmj-process.c find_email_adr.c \
- incindexfile.c itoa.c chomp.c \
+ incindexfile.c itoa.c chomp.c utils.c \
mylocking.c listcontrol.c random-int.c strgen.c \
print-version.c send_help.c prepstdreply.c \
do_all_the_voodoo_here.c mygetline.c gethdrline.c \
-/* Copyright (C) 2002, 2003 Mads Martin Joergensen <mmj at mmj.dk>
- *
- * $Id$
+/*
+ * Copyright (C) 2002, 2003 Mads Martin Joergensen <mmj at mmj.dk>
+ * Copyright (C) 2021 Baptiste Daroussin <bapt@FreeBSD.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* IN THE SOFTWARE.
*/
+#include <sys/limits.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
+#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "log_error.h"
#include "strgen.h"
#include "memory.h"
+#include "utils.h"
-#define INTBUF_SIZE 32
-
-int incindexfile(const char *listdir)
+int incindexfile(struct mlmmj_list *list)
{
- int fd, lock;
- long int index = 0;
- char intbuf[INTBUF_SIZE] = "uninitialized";
- size_t i;
- char *indexfilename;
-
- indexfilename = concatstr(2, listdir, "/index");
- fd = open(indexfilename, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
+ int fd;
+ int index = 0;
+ FILE *fp;
+ char *line = NULL;
+ size_t linecap = 0;
+ const char *errstr;
+ fd = openat(list->fd, "index", O_RDWR|O_CREAT|O_EXLOCK|O_CLOEXEC, S_IRUSR|S_IWUSR);
if(fd == -1) {
- myfree(indexfilename);
log_error(LOG_ARGS, "Error opening index file");
return 0;
}
- lock = myexcllock(fd);
-
- if(lock) {
- myfree(indexfilename);
- log_error(LOG_ARGS, "Error locking index file");
+ fp = fdopen(fd, "r");
+ if (fp == NULL) {
+ log_error(LOG_ARGS, "Error fdopening index file");
close(fd);
return 0;
}
- readn(fd, intbuf, INTBUF_SIZE);
- for(i=0; i<sizeof(intbuf); i++) {
- if(intbuf[i] < '0' || intbuf[i] > '9') {
- intbuf[i] = '\0';
- break;
- }
+ index = 0;
+ if (getline(&line, &linecap, fp) > 0) {
+ /* eliminate everything which is not a number */
+ line[strspn(line, "0123456789")] = '\0';
+ index = strtoim(line, 0, INT_MAX, &errstr);
+ myfree(line);
+ if (errstr != NULL)
+ log_error(LOG_ARGS, "Error reading index file: invalid line: %s", line);
}
- index = atol(intbuf);
index++;
- itoa(index, intbuf);
lseek(fd, 0, SEEK_SET);
- dprintf(fd, "%s", intbuf);
-
- close(fd); /* Lock is also released */
- myfree(indexfilename);
+ fprintf(fp, "%d\n", index);
+ fclose(fp); /* Lock is also released */
- return index;
+ return (index);
}
/* initialize the archive filename */
if(archive) {
- mindex = incindexfile(list.dir);
+ mindex = incindexfile(&list);
len = strlen(list.dir) + 9 + 20;
archivefilename = mymalloc(len);
snprintf(archivefilename, len, "%s/archive/%d", list.dir,
--- /dev/null
+/*
+ * Copyright (C) 2021 Baptiste Daroussin <bapt@FreeBSD.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+
+intmax_t
+strtoim(const char *np, intmax_t minval, intmax_t maxval, const char **errpp)
+{
+ char *endp;
+ intmax_t ret;
+
+ *errpp = NULL;
+ if (minval > maxval) {
+ errno = EINVAL;
+ *errpp = "invalid";
+ return (0);
+ }
+ errno = 0;
+ ret = strtoimax(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);
+}