Files
uw-imap-2007f/patches/0005-Add-documented-patch-series-and-build-instructions.patch

796 lines
30 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 9a972c418aa23c5081b80160d2f2cebf4fb617b6 Mon Sep 17 00:00:00 2001
From: Christoph <ckubu@oopen.de>
Date: Sun, 14 Dec 2025 13:20:03 +0100
Subject: [PATCH 5/5] Add documented patch series and build instructions
---
README.md | 80 +++-
...001-Fix-utime-usage-for-modern-glibc.patch | 364 ++++++++++++++++++
...0002-Fix-scandir-callback-signatures.patch | 204 ++++++++++
patches/0003-Replace-gets-with-fgets.patch | 44 +++
...issing-headers-for-modern-toolchains.patch | 51 +++
5 files changed, 742 insertions(+), 1 deletion(-)
create mode 100644 patches/0001-Fix-utime-usage-for-modern-glibc.patch
create mode 100644 patches/0002-Fix-scandir-callback-signatures.patch
create mode 100644 patches/0003-Replace-gets-with-fgets.patch
create mode 100644 patches/0004-Add-missing-headers-for-modern-toolchains.patch
diff --git a/README.md b/README.md
index 8a75f5e..8c97985 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,82 @@
-# University of Washington IMAP toolkit
+## UW-IMAP 2007f modernized build for current Linux systems
+
+This repository contains a maintained, buildable version of **UW-IMAP 2007f**
+adapted for modern Linux toolchains (glibc ≥ 2.36, GCC ≥ 11, OpenSSL ≥ 3).
+
+The original UW-IMAP source no longer builds cleanly on current distributions.
+This repository keeps the upstream code intact and applies a small, focused
+patchset to restore buildability without functional changes.
+
+---
+
+## Scope
+
+This repository provides:
+
+- Upstream UW-IMAP 2007f source
+- A minimal patchset for:
+ - `utime()` compatibility with modern glibc
+ - `scandir()` callback signature fixes
+ - Removal of deprecated `gets()`
+ - Missing standard header includes
+- A reproducible build process
+
+Not included:
+
+- Distribution packaging
+- PHP / PECL bindings
+- Kerberos support (disabled by default)
+
+---
+
+## Build dependencies (Debian 12 / 13)
+
+The following packages are required to build UW-IMAP 2007f:
+
+
+ apt install \
+ build-essential \
+ autoconf \
+ automake \
+ libtool \
+ pkg-config \
+ libssl-dev \
+ libpam0g-dev \
+ libc6-dev \
+ libcrypt-dev \
+ bison \
+ flex
+
+## Notes
+
+ libc-client-dev is no longer available on modern Debian releases.
+ UW-IMAP must be built from source.
+
+ OpenSSL 3.x is supported via the included patchset.
+ Kerberos support is disabled (--without-kerberos).
+
+ Bundled tools (mtest, mlock, dmail, tmail) are built but optional.
+
+## Patches
+
+All local fixes are provided as a linear patch series:
+
+ patches/
+ 0001-Fix-utime-usage-for-modern-glibc.patch
+ 0002-Fix-scandir-callback-signatures.patch
+ 0003-Replace-gets-with-fgets.patch
+ 0004 -Add-missing-headers-for-modern-toolchains.patch
+ `
+
+## Build
+
+Example build without Kerberos:
+
+ make lnp SSLTYPE=unix.nopwd
+
+
+
+# Original README: University of Washington IMAP toolkit
This repository is a copy of the University of Washington IMAP toolkit _(imap-2007f.tar.gz/MD5:2126fd125ea26b73b20f01fcd5940369)_ which has become unavailable from the documented FTP and mirror sites. Posted here for both posterity and because a number of packages require the library and source/headers which may not always be suitable from the OS package manager.
_In my case it was to compile PHP7 with IMAP support and utilizing an alternative (newer) OpenSSL version. It was very difficult to find trustworthy already-patched sources for this purpose._ This seems to be a common problem for many in the same situation.
diff --git a/patches/0001-Fix-utime-usage-for-modern-glibc.patch b/patches/0001-Fix-utime-usage-for-modern-glibc.patch
new file mode 100644
index 0000000..a6e7825
--- /dev/null
+++ b/patches/0001-Fix-utime-usage-for-modern-glibc.patch
@@ -0,0 +1,364 @@
+From f7567c55126775c1c40ca77f77e7109de522c709 Mon Sep 17 00:00:00 2001
+From: Christoph <ckubu@oopen.de>
+Date: Sun, 14 Dec 2025 11:48:10 +0100
+Subject: [PATCH 1/4] Fix utime() usage for modern glibc
+
+---
+ src/osdep/unix/mbx.c | 12 ++++++------
+ src/osdep/unix/mmdf.c | 10 +++++-----
+ src/osdep/unix/mtx.c | 16 ++++++++--------
+ src/osdep/unix/os_slx.h | 20 ++++++++++++++++++++
+ src/osdep/unix/tenex.c | 16 ++++++++--------
+ src/osdep/unix/unix.c | 11 ++++++-----
+ 6 files changed, 53 insertions(+), 32 deletions(-)
+
+diff --git a/src/osdep/unix/mbx.c b/src/osdep/unix/mbx.c
+index 1ece5d8..251ccfb 100644
+--- a/src/osdep/unix/mbx.c
++++ b/src/osdep/unix/mbx.c
+@@ -300,7 +300,7 @@ int mbx_isvalid (MAILSTREAM **stream,char *name,char *tmp,int *ld,char *lock,
+ if (sbuf.st_ctime > sbuf.st_atime) {
+ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
+ tp[1] = sbuf.st_mtime;
+- utime (tmp,tp); /* set the times */
++ set_utime_from_tp (tmp,tp); /* set the times */
+ }
+ }
+ /* in case INBOX but not mbx format */
+@@ -774,7 +774,7 @@ void mbx_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags)
+ stream->user_flags[LOCAL->ffuserflag]) || (oldpid != LOCAL->lastpid))
+ mbx_update_header (stream);
+ tp[0] = time (0); /* make sure read comes after all that */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ if (LOCAL->ld >= 0) { /* unlock now */
+ unlockfd (LOCAL->ld,LOCAL->lock);
+@@ -1073,7 +1073,7 @@ long mbx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+ /* else preserve \Marked status */
+ else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
+ tp[1] = sbuf.st_mtime; /* preserve mtime */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ close (fd); /* close the file */
+ MM_NOCRITICAL (stream); /* release critical */
+ unlockfd (ld,lock); /* release exclusive parse/append permission */
+@@ -1211,7 +1211,7 @@ long mbx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
+ /* else preserve \Marked status */
+ else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
+ tp[1] = sbuf.st_mtime; /* preserve mtime */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ fclose (df); /* close the file */
+ MM_NOCRITICAL (dstream); /* release critical */
+ }
+@@ -1444,7 +1444,7 @@ long mbx_parse (MAILSTREAM *stream)
+ time_t tp[2];
+ tp[0] = time (0);
+ tp[1] = LOCAL->filetime;
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ stream->silent = silent; /* can pass up events now */
+ mail_exists (stream,nmsgs); /* notify upper level of new mailbox size */
+@@ -1812,7 +1812,7 @@ unsigned long mbx_rewrite (MAILSTREAM *stream,unsigned long *reclaimed,
+ fstat (LOCAL->fd,&sbuf); /* get new write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* reset atime to now */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ unlockfd (ld,lock); /* release exclusive parse/append permission */
+ /* notify upper level of new mailbox size */
+ mail_exists (stream,stream->nmsgs);
+diff --git a/src/osdep/unix/mmdf.c b/src/osdep/unix/mmdf.c
+index e962434..968e306 100644
+--- a/src/osdep/unix/mmdf.c
++++ b/src/osdep/unix/mmdf.c
+@@ -379,7 +379,7 @@ long mmdf_isvalid (char *name,char *tmp)
+ if ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) {
+ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
+ tp[1] = sbuf.st_mtime;
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ }
+ }
+ }
+@@ -1131,7 +1131,7 @@ long mmdf_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+ else tp[0] = /* else preserve \Marked status */
+ ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?
+ sbuf.st_atime : tp[1];
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ mmdf_unlock (fd,NIL,&lock); /* unlock and close mailbox */
+ if (tstream) { /* update last UID if we can */
+ MMDFLOCAL *local = (MMDFLOCAL *) tstream->local;
+@@ -1292,7 +1292,7 @@ long mmdf_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
+ ret = NIL; /* return error */
+ }
+ else tp[0] = tp[1] - 1; /* set atime to now-1 if successful copy */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ fclose (sf); /* done with scratch file */
+ /* force UIDVALIDITY assignment now */
+ if (tstream && !tstream->uid_validity) tstream->uid_validity = time (0);
+@@ -1550,7 +1550,7 @@ void mmdf_unlock (int fd,MAILSTREAM *stream,DOTLOCK *lock)
+ }
+ else now = 0; /* no time change needed */
+ /* set the times, note change */
+- if (now && !utime (stream->mailbox,tp)) LOCAL->filetime = tp[1];
++ if (now && !set_utime_from_tp(stream->mailbox,tp)) LOCAL->filetime = tp[1];
+ }
+ flock (fd,LOCK_UN); /* release flock'ers */
+ if (!stream) close (fd); /* close the file if no stream */
+@@ -2393,7 +2393,7 @@ long mmdf_rewrite (MAILSTREAM *stream,unsigned long *nexp,DOTLOCK *lock,
+ /* set atime to now, mtime a second earlier */
+ tp[1] = (tp[0] = time (0)) - 1;
+ /* set the times, note change */
+- if (!utime (stream->mailbox,tp)) LOCAL->filetime = tp[1];
++ if (!set_utime_from_tp(stream->mailbox,tp)) LOCAL->filetime = tp[1];
+ close (LOCAL->fd); /* close and reopen file */
+ if ((LOCAL->fd = open (stream->mailbox,O_RDWR,
+ (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL)))
+diff --git a/src/osdep/unix/mtx.c b/src/osdep/unix/mtx.c
+index 8e6f76e..b00cebf 100644
+--- a/src/osdep/unix/mtx.c
++++ b/src/osdep/unix/mtx.c
+@@ -196,7 +196,7 @@ int mtx_isvalid (char *name,char *tmp)
+ if (sbuf.st_ctime > sbuf.st_atime) {
+ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
+ tp[1] = sbuf.st_mtime;
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ }
+ }
+ }
+@@ -565,7 +565,7 @@ void mtx_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags)
+ fstat (LOCAL->fd,&sbuf); /* get current write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* make sure read comes after all that */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ }
+
+@@ -834,7 +834,7 @@ long mtx_expunge (MAILSTREAM *stream,char *sequence,long options)
+ fstat (LOCAL->fd,&sbuf); /* get new write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* reset atime to now */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ MM_NOCRITICAL (stream); /* release critical */
+ /* notify upper level of new mailbox size */
+ mail_exists (stream,stream->nmsgs);
+@@ -929,7 +929,7 @@ long mtx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+ /* else preserve \Marked status */
+ else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
+ tp[1] = sbuf.st_mtime; /* preserve mtime */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ close (fd); /* close the file */
+ unlockfd (ld,lock); /* release exclusive parse/append permission */
+ MM_NOCRITICAL (stream); /* release critical */
+@@ -946,7 +946,7 @@ long mtx_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+ fstat (LOCAL->fd,&sbuf); /* get current write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* make sure atime remains greater */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ }
+ if (ret && mail_parameters (NIL,GET_COPYUID,NIL))
+@@ -1062,7 +1062,7 @@ long mtx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
+ /* else preserve \Marked status */
+ else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
+ tp[1] = sbuf.st_mtime; /* preserve mtime */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ fclose (df); /* close the file */
+ unlockfd (ld,lock); /* release exclusive parse/append permission */
+ MM_NOCRITICAL (stream); /* release critical */
+@@ -1212,7 +1212,7 @@ long mtx_parse (MAILSTREAM *stream)
+ time_t tp[2];
+ tp[0] = time (0);
+ tp[1] = LOCAL->filetime;
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ stream->silent = silent; /* can pass up events now */
+ mail_exists (stream,nmsgs); /* notify upper level of new mailbox size */
+@@ -1312,7 +1312,7 @@ void mtx_update_status (MAILSTREAM *stream,unsigned long msgno,long syncflag)
+ fstat (LOCAL->fd,&sbuf); /* get new write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* make sure read is later */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ }
+ }
+diff --git a/src/osdep/unix/os_slx.h b/src/osdep/unix/os_slx.h
+index b5f39ff..a316317 100644
+--- a/src/osdep/unix/os_slx.h
++++ b/src/osdep/unix/os_slx.h
+@@ -50,6 +50,26 @@
+ #include <syslog.h>
+ #include <sys/file.h>
+
++#include <utime.h>
++
++static inline int set_utime_from_tp (const char *path, time_t *tp)
++{
++ struct utimbuf ub;
++ ub.actime = tp[0];
++ ub.modtime = tp[1];
++ return utime (path, &ub);
++}
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++int safe_flock (int fd, int operation);
++
++#ifdef __cplusplus
++}
++#endif
++
+
+ /* Linux gets this wrong */
+
+diff --git a/src/osdep/unix/tenex.c b/src/osdep/unix/tenex.c
+index eee61fb..fd03c23 100644
+--- a/src/osdep/unix/tenex.c
++++ b/src/osdep/unix/tenex.c
+@@ -203,7 +203,7 @@ int tenex_isvalid (char *name,char *tmp)
+ if (sbuf.st_ctime > sbuf.st_atime) {
+ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
+ tp[1] = sbuf.st_mtime;
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ }
+ }
+ }
+@@ -654,7 +654,7 @@ void tenex_flag (MAILSTREAM *stream,char *sequence,char *flag,long flags)
+ fstat (LOCAL->fd,&sbuf); /* get current write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* make sure read comes after all that */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ }
+
+@@ -924,7 +924,7 @@ long tenex_expunge (MAILSTREAM *stream,char *sequence,long options)
+ fstat (LOCAL->fd,&sbuf); /* get new write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* reset atime to now */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ MM_NOCRITICAL (stream); /* release critical */
+ /* notify upper level of new mailbox size */
+ mail_exists (stream,stream->nmsgs);
+@@ -1019,7 +1019,7 @@ long tenex_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+ /* else preserve \Marked status */
+ else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
+ tp[1] = sbuf.st_mtime; /* preserve mtime */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ close (fd); /* close the file */
+ unlockfd (ld,lock); /* release exclusive parse/append permission */
+ MM_NOCRITICAL (stream); /* release critical */
+@@ -1036,7 +1036,7 @@ long tenex_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+ fstat (LOCAL->fd,&sbuf); /* get current write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* make sure atime remains greater */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ }
+ if (ret && mail_parameters (NIL,GET_COPYUID,NIL))
+@@ -1159,7 +1159,7 @@ long tenex_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
+ /* else preserve \Marked status */
+ else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
+ tp[1] = sbuf.st_mtime; /* preserve mtime */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ fclose (df); /* close the file */
+ unlockfd (ld,lock); /* release exclusive parse/append permission */
+ MM_NOCRITICAL (stream); /* release critical */
+@@ -1324,7 +1324,7 @@ long tenex_parse (MAILSTREAM *stream)
+ time_t tp[2];
+ tp[0] = time (0);
+ tp[1] = LOCAL->filetime;
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ stream->silent = silent; /* can pass up events now */
+ mail_exists (stream,nmsgs); /* notify upper level of new mailbox size */
+@@ -1424,7 +1424,7 @@ void tenex_update_status (MAILSTREAM *stream,unsigned long msgno,long syncflag)
+ fstat (LOCAL->fd,&sbuf); /* get new write time */
+ tp[1] = LOCAL->filetime = sbuf.st_mtime;
+ tp[0] = time (0); /* make sure read is later */
+- utime (stream->mailbox,tp);
++ set_utime_from_tp(stream->mailbox,tp);
+ }
+ }
+ }
+diff --git a/src/osdep/unix/unix.c b/src/osdep/unix/unix.c
+index be3c437..58638d6 100644
+--- a/src/osdep/unix/unix.c
++++ b/src/osdep/unix/unix.c
+@@ -45,6 +45,7 @@ extern int errno; /* just in case */
+ #include "mail.h"
+ #include "osdep.h"
+ #include <time.h>
++#include <utime.h>
+ #include <sys/stat.h>
+ #include "unix.h"
+ #include "pseudo.h"
+@@ -228,7 +229,7 @@ DRIVER *unix_valid (char *name)
+ if ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) {
+ tp[0] = sbuf.st_atime; /* yes, preserve atime and mtime */
+ tp[1] = sbuf.st_mtime;
+- utime (file,tp); /* set the times */
++ set_utime_from_tp (file,tp); /* set the times */
+ }
+ }
+ }
+@@ -995,7 +996,7 @@ long unix_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options)
+ else tp[0] = /* else preserve \Marked status */
+ ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?
+ sbuf.st_atime : tp[1];
+- utime (file,tp); /* set the times */
++ set_utime_from_tp (file,tp); /* set the times */
+ unix_unlock (fd,NIL,&lock); /* unlock and close mailbox */
+ if (tstream) { /* update last UID if we can */
+ UNIXLOCAL *local = (UNIXLOCAL *) tstream->local;
+@@ -1156,7 +1157,7 @@ long unix_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
+ ret = NIL; /* return error */
+ }
+ else tp[0] = tp[1] - 1; /* set atime to now-1 if successful copy */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp (file,tp); /* set the times */
+ fclose (sf); /* done with scratch file */
+ /* force UIDVALIDITY assignment now */
+ if (tstream && !tstream->uid_validity) tstream->uid_validity = time (0);
+@@ -1421,7 +1422,7 @@ void unix_unlock (int fd,MAILSTREAM *stream,DOTLOCK *lock)
+ }
+ else now = 0; /* no time change needed */
+ /* set the times, note change */
+- if (now && !utime (stream->mailbox,tp)) LOCAL->filetime = tp[1];
++ if (now && !set_utime_from_tp (stream->mailbox,tp)) LOCAL->filetime = tp[1];
+ }
+ flock (fd,LOCK_UN); /* release flock'ers */
+ if (!stream) close (fd); /* close the file if no stream */
+@@ -2247,7 +2248,7 @@ long unix_rewrite (MAILSTREAM *stream,unsigned long *nexp,DOTLOCK *lock,
+ /* set atime to now, mtime a second earlier */
+ tp[1] = (tp[0] = time (0)) - 1;
+ /* set the times, note change */
+- if (!utime (stream->mailbox,tp)) LOCAL->filetime = tp[1];
++ if (!set_utime_from_tp (stream->mailbox,tp)) LOCAL->filetime = tp[1];
+ close (LOCAL->fd); /* close and reopen file */
+ if ((LOCAL->fd = open (stream->mailbox,O_RDWR,
+ (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL)))
+--
+2.47.3
+
diff --git a/patches/0002-Fix-scandir-callback-signatures.patch b/patches/0002-Fix-scandir-callback-signatures.patch
new file mode 100644
index 0000000..61e4bbf
--- /dev/null
+++ b/patches/0002-Fix-scandir-callback-signatures.patch
@@ -0,0 +1,204 @@
+From a67eeb9fd268efc3f13db05810880d2249e6ccce Mon Sep 17 00:00:00 2001
+From: Christoph <ckubu@oopen.de>
+Date: Sun, 14 Dec 2025 11:48:35 +0100
+Subject: [PATCH 2/4] Fix scandir() callback signatures
+
+---
+ src/osdep/unix/mh.c | 12 +++++++-----
+ src/osdep/unix/mix.c | 21 +++++++++++----------
+ src/osdep/unix/mx.c | 13 ++++++-------
+ src/osdep/unix/news.c | 14 ++++++++++----
+ 4 files changed, 34 insertions(+), 26 deletions(-)
+
+diff --git a/src/osdep/unix/mh.c b/src/osdep/unix/mh.c
+index 0226b7a..2f43774 100644
+--- a/src/osdep/unix/mh.c
++++ b/src/osdep/unix/mh.c
+@@ -103,8 +103,10 @@ long mh_copy (MAILSTREAM *stream,char *sequence,char *mailbox,
+ long options);
+ long mh_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);
+
+-int mh_select (struct direct *name);
+-int mh_numsort (const void *d1,const void *d2);
++#include <dirent.h>
++
++int mh_select (const struct dirent *name);
++int mh_numsort (const struct dirent **d1, const struct dirent **d2);
+ char *mh_file (char *dst,char *name);
+ long mh_canonicalize (char *pattern,char *ref,char *pat);
+ void mh_setdate (char *file,MESSAGECACHE *elt);
+@@ -1194,7 +1196,7 @@ long mh_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data)
+ * Returns: T to use file name, NIL to skip it
+ */
+
+-int mh_select (struct direct *name)
++int mh_select (const struct dirent *name)
+ {
+ char c;
+ char *s = name->d_name;
+@@ -1209,7 +1211,7 @@ int mh_select (struct direct *name)
+ * Returns: negative if d1 < d2, 0 if d1 == d2, postive if d1 > d2
+ */
+
+-int mh_numsort (const void *d1,const void *d2)
++int mh_numsort (const struct dirent **d1, const struct dirent **d2)
+ {
+ return atoi ((*(struct direct **) d1)->d_name) -
+ atoi ((*(struct direct **) d2)->d_name);
+@@ -1279,5 +1281,5 @@ void mh_setdate (char *file,MESSAGECACHE *elt)
+ time_t tp[2];
+ tp[0] = time (0); /* atime is now */
+ tp[1] = mail_longdate (elt); /* modification time */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ }
+diff --git a/src/osdep/unix/mix.c b/src/osdep/unix/mix.c
+index fbf4a02..546ac99 100644
+--- a/src/osdep/unix/mix.c
++++ b/src/osdep/unix/mix.c
+@@ -125,7 +125,7 @@ long mix_unsubscribe (MAILSTREAM *stream,char *mailbox);
+ long mix_create (MAILSTREAM *stream,char *mailbox);
+ long mix_delete (MAILSTREAM *stream,char *mailbox);
+ long mix_rename (MAILSTREAM *stream,char *old,char *newname);
+-int mix_rselect (struct direct *name);
++int mix_rselect (const struct dirent *name);
+ MAILSTREAM *mix_open (MAILSTREAM *stream);
+ void mix_close (MAILSTREAM *stream,long options);
+ void mix_abort (MAILSTREAM *stream);
+@@ -140,8 +140,8 @@ THREADNODE *mix_thread (MAILSTREAM *stream,char *type,char *charset,
+ long mix_ping (MAILSTREAM *stream);
+ void mix_check (MAILSTREAM *stream);
+ long mix_expunge (MAILSTREAM *stream,char *sequence,long options);
+-int mix_select (struct direct *name);
+-int mix_msgfsort (const void *d1,const void *d2);
++int mix_select (const struct dirent *name);
++int mix_msgfsort (const struct dirent **d1, const struct dirent **d2);
+ long mix_addset (SEARCHSET **set,unsigned long start,unsigned long size);
+ long mix_burp (MAILSTREAM *stream,MIXBURP *burp,unsigned long *reclaimed);
+ long mix_burp_check (SEARCHSET *set,size_t size,char *file);
+@@ -587,7 +587,7 @@ long mix_rename (MAILSTREAM *stream,char *old,char *newname)
+ * Returns: T if mix file name, NIL otherwise
+ */
+
+-int mix_rselect (struct direct *name)
++int mix_rselect (const struct dirent *name)
+ {
+ return mix_dirfmttest (name->d_name);
+ }
+@@ -1146,7 +1146,7 @@ long mix_expunge (MAILSTREAM *stream,char *sequence,long options)
+ * ".mix" with no suffix was used by experimental versions
+ */
+
+-int mix_select (struct direct *name)
++int mix_select (const struct dirent *name)
+ {
+ char c,*s;
+ /* make sure name has prefix */
+@@ -1165,15 +1165,16 @@ int mix_select (struct direct *name)
+ * Returns: -1 if d1 < d2, 0 if d1 == d2, 1 d1 > d2
+ */
+
+-int mix_msgfsort (const void *d1,const void *d2)
++int mix_msgfsort (const struct dirent **d1, const struct dirent **d2)
+ {
+- char *n1 = (*(struct direct **) d1)->d_name + sizeof (MIXNAME) - 1;
+- char *n2 = (*(struct direct **) d2)->d_name + sizeof (MIXNAME) - 1;
+- return compare_ulong (*n1 ? strtoul (n1,NIL,16) : 0,
+- *n2 ? strtoul (n2,NIL,16) : 0);
++ const char *n1 = (*d1)->d_name + sizeof (MIXNAME) - 1;
++ const char *n2 = (*d2)->d_name + sizeof (MIXNAME) - 1;
++ return compare_ulong (*n1 ? strtoul (n1, NIL, 16) : 0,
++ *n2 ? strtoul (n2, NIL, 16) : 0);
+ }
+
+
++
+ /* MIX add a range to a set
+ * Accepts: pointer to set to add
+ * start of set
+diff --git a/src/osdep/unix/mx.c b/src/osdep/unix/mx.c
+index 4549527..943f7da 100644
+--- a/src/osdep/unix/mx.c
++++ b/src/osdep/unix/mx.c
+@@ -98,8 +98,8 @@ long mx_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);
+ long mx_append_msg (MAILSTREAM *stream,char *flags,MESSAGECACHE *elt,
+ STRING *st,SEARCHSET *set);
+
+-int mx_select (struct direct *name);
+-int mx_numsort (const void *d1,const void *d2);
++int mx_select (const struct dirent *name);
++int mx_numsort (const struct dirent **d1, const struct dirent **d2);
+ char *mx_file (char *dst,char *name);
+ long mx_lockindex (MAILSTREAM *stream);
+ void mx_unlockindex (MAILSTREAM *stream);
+@@ -1110,7 +1110,7 @@ long mx_append_msg (MAILSTREAM *stream,char *flags,MESSAGECACHE *elt,
+ * Returns: T to use file name, NIL to skip it
+ */
+
+-int mx_select (struct direct *name)
++int mx_select (const struct dirent *name)
+ {
+ char c;
+ char *s = name->d_name;
+@@ -1125,10 +1125,9 @@ int mx_select (struct direct *name)
+ * Returns: negative if d1 < d2, 0 if d1 == d2, postive if d1 > d2
+ */
+
+-int mx_numsort (const void *d1,const void *d2)
++int mx_numsort (const struct dirent **d1, const struct dirent **d2)
+ {
+- return atoi ((*(struct direct **) d1)->d_name) -
+- atoi ((*(struct direct **) d2)->d_name);
++ return atoi ((*d1)->d_name) - atoi ((*d2)->d_name);
+ }
+
+
+@@ -1283,5 +1282,5 @@ void mx_setdate (char *file,MESSAGECACHE *elt)
+ time_t tp[2];
+ tp[0] = time (0); /* atime is now */
+ tp[1] = mail_longdate (elt); /* modification time */
+- utime (file,tp); /* set the times */
++ set_utime_from_tp(file,tp); /* set the times */
+ }
+diff --git a/src/osdep/unix/news.c b/src/osdep/unix/news.c
+index 4cf5bb7..e0dbb52 100644
+--- a/src/osdep/unix/news.c
++++ b/src/osdep/unix/news.c
+@@ -76,8 +76,12 @@ long news_create (MAILSTREAM *stream,char *mailbox);
+ long news_delete (MAILSTREAM *stream,char *mailbox);
+ long news_rename (MAILSTREAM *stream,char *old,char *newname);
+ MAILSTREAM *news_open (MAILSTREAM *stream);
+-int news_select (struct direct *name);
+-int news_numsort (const void *d1,const void *d2);
++
++#include <dirent.h> /* falls nicht schon drin */
++
++int news_select (const struct dirent *name);
++int news_numsort (const struct dirent **d1, const struct dirent **d2);
++
+ void news_close (MAILSTREAM *stream,long options);
+ void news_fast (MAILSTREAM *stream,char *sequence,long flags);
+ void news_flags (MAILSTREAM *stream,char *sequence,long flags);
+@@ -402,7 +406,8 @@ MAILSTREAM *news_open (MAILSTREAM *stream)
+ * Returns: T to use file name, NIL to skip it
+ */
+
+-int news_select (struct direct *name)
++int news_select (const struct dirent *name)
++
+ {
+ char c;
+ char *s = name->d_name;
+@@ -417,7 +422,8 @@ int news_select (struct direct *name)
+ * Returns: negative if d1 < d2, 0 if d1 == d2, postive if d1 > d2
+ */
+
+-int news_numsort (const void *d1,const void *d2)
++int news_numsort (const struct dirent **d1, const struct dirent **d2)
++
+ {
+ return atoi ((*(struct direct **) d1)->d_name) -
+ atoi ((*(struct direct **) d2)->d_name);
+--
+2.47.3
+
diff --git a/patches/0003-Replace-gets-with-fgets.patch b/patches/0003-Replace-gets-with-fgets.patch
new file mode 100644
index 0000000..be6ad5e
--- /dev/null
+++ b/patches/0003-Replace-gets-with-fgets.patch
@@ -0,0 +1,44 @@
+From 789c2d97f672fd25cb0f5495892f13eda9fef440 Mon Sep 17 00:00:00 2001
+From: Christoph <ckubu@oopen.de>
+Date: Sun, 14 Dec 2025 11:49:00 +0100
+Subject: [PATCH 3/4] Replace gets() with fgets()
+
+---
+ src/mtest/mtest.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/src/mtest/mtest.c b/src/mtest/mtest.c
+index 69af568..c15a853 100644
+--- a/src/mtest/mtest.c
++++ b/src/mtest/mtest.c
+@@ -38,6 +38,7 @@
+ #include <signal.h>
+ #include "c-client.h"
+ #include "imap4r1.h"
++#include <string.h>
+
+ /* Excellent reasons to hate ifdefs, and why my real code never uses them */
+
+@@ -595,7 +596,8 @@ void status (MAILSTREAM *stream)
+ void prompt (char *msg,char *txt)
+ {
+ printf ("%s",msg);
+- gets (txt);
++ if (!fgets (txt, sizeof (txt), stdin)) txt[0] = '\0';
++ txt[strcspn (txt, "\r\n")] = '\0';
+ }
+
+ /* Interfaces to C-client */
+@@ -779,7 +781,8 @@ void smtptest (long debug)
+ puts (" Msg (end with a line with only a '.'):");
+ body->type = TYPETEXT;
+ *text = '\0';
+- while (gets (line)) {
++ while (fgets (line, sizeof (line), stdin)) {
++ line[strcspn (line, "\r\n")] = '\0';
+ if (line[0] == '.') {
+ if (line[1] == '\0') break;
+ else strcat (text,".");
+--
+2.47.3
+
diff --git a/patches/0004-Add-missing-headers-for-modern-toolchains.patch b/patches/0004-Add-missing-headers-for-modern-toolchains.patch
new file mode 100644
index 0000000..cc6f71e
--- /dev/null
+++ b/patches/0004-Add-missing-headers-for-modern-toolchains.patch
@@ -0,0 +1,51 @@
+From 8f89723b4f32c3ce70dbb3f99f1c176e4492692d Mon Sep 17 00:00:00 2001
+From: Christoph <ckubu@oopen.de>
+Date: Sun, 14 Dec 2025 11:49:29 +0100
+Subject: [PATCH 4/4] Add missing headers for modern toolchains
+
+---
+ src/dmail/dmail.c | 1 +
+ src/mlock/mlock.c | 2 ++
+ src/tmail/tmail.c | 1 +
+ 3 files changed, 4 insertions(+)
+
+diff --git a/src/dmail/dmail.c b/src/dmail/dmail.c
+index f78b957..b569c16 100644
+--- a/src/dmail/dmail.c
++++ b/src/dmail/dmail.c
+@@ -35,6 +35,7 @@ extern int errno; /* just in case */
+ #include <sys/stat.h>
+ #include "c-client.h"
+ #include "dquota.h"
++#include <ctype.h>
+
+
+ /* Globals */
+diff --git a/src/mlock/mlock.c b/src/mlock/mlock.c
+index 1dca40e..95f3729 100644
+--- a/src/mlock/mlock.c
++++ b/src/mlock/mlock.c
+@@ -40,6 +40,8 @@
+ #include <netdb.h>
+ #include <ctype.h>
+ #include <string.h>
++#include <unistd.h> /* write, read, close, link, unlink, chdir, sleep, getpid, gethostname */
++#include <time.h> /* time */
+
+ #define LOCKTIMEOUT 5 /* lock timeout in minutes */
+ #define LOCKPROTECTION 0664
+diff --git a/src/tmail/tmail.c b/src/tmail/tmail.c
+index ed5fc58..95ecbd2 100644
+--- a/src/tmail/tmail.c
++++ b/src/tmail/tmail.c
+@@ -35,6 +35,7 @@ extern int errno; /* just in case */
+ #include <sys/stat.h>
+ #include "c-client.h"
+ #include "tquota.h"
++#include <ctype.h>
+
+
+ /* Globals */
+--
+2.47.3
+
--
2.47.3