21 Commits

Author SHA1 Message Date
f5a0532389 Just a small change in the ‘README’ file. 2025-12-14 23:21:32 +01:00
6c00ac8ee6 Add Debian dependency installer and run it from all.sh 2025-12-14 18:32:50 +01:00
e352e92c3c Harden automation: apply only build patches, default clean, install binaries 2025-12-14 17:03:40 +01:00
c30f6ceaea Fix build order (make an -> core build -> bundled tools) 2025-12-14 16:35:34 +01:00
d6ec34c922 Add build/install scripts 2025-12-14 16:04:04 +01:00
4c170cf105 Add maintained patch set for modern toolchains 2025-12-14 13:22:12 +01:00
9a972c418a Add documented patch series and build instructions 2025-12-14 13:20:03 +01:00
8f89723b4f Add missing headers for modern toolchains 2025-12-14 12:29:18 +01:00
789c2d97f6 Replace gets() with fgets() 2025-12-14 12:27:37 +01:00
a67eeb9fd2 Fix scandir() callback signatures 2025-12-14 12:27:37 +01:00
f7567c5512 Fix utime() usage for modern glibc 2025-12-14 12:27:25 +01:00
Chris N
cab1094665 Merge pull request #1 from uw-imap/patches
Patches
2019-01-04 00:09:03 -06:00
Chris
b4cecc5315 Update Readme and added patch files 2019-01-04 00:01:25 -06:00
Chris
9eb7bb9d59 Revert "imap-2007e-system_c_client.patch"
This reverts commit fc0899b6db.
2019-01-03 06:36:08 -06:00
Chris
72e02acb0a gitignore for patch backups 2019-01-03 04:27:05 -06:00
Chris
0f65bf936f imap-2007e-authmd5.patch 2019-01-03 04:24:23 -06:00
Chris
1954d712b0 imap-2007e-shared.patch 2019-01-03 04:24:23 -06:00
Chris
c95dae6cbf imap-2007e-overflow.patch 2019-01-03 04:24:23 -06:00
Chris
5605311cd1 imap-2007-paths.patch 2019-01-03 04:24:23 -06:00
Chris
cbcf2194b1 imap-2007f-ldflags.patch 2019-01-03 04:21:04 -06:00
Chris
15d6fe1705 1006_openssl1.1_autoverify.patch 2019-01-03 04:21:04 -06:00
42 changed files with 2563 additions and 84 deletions

3
.gitignore vendored
View File

@@ -40,3 +40,6 @@ m4/ltsugar.m4
m4/ltversion.m4 m4/ltversion.m4
m4/lt~obsolete.m4 m4/lt~obsolete.m4
autom4te.cache autom4te.cache
*.orig
sources

View File

@@ -669,8 +669,6 @@ an ua:
$(TOOLS)/$@ "$(LN)" src/ansilib c-client $(TOOLS)/$@ "$(LN)" src/ansilib c-client
$(TOOLS)/$@ "$(LN)" src/charset c-client $(TOOLS)/$@ "$(LN)" src/charset c-client
$(TOOLS)/$@ "$(LN)" src/osdep/$(SYSTEM) c-client $(TOOLS)/$@ "$(LN)" src/osdep/$(SYSTEM) c-client
cp -alf /usr/include/imap/* c-client/
#sleep 5
$(TOOLS)/$@ "$(LN)" src/mtest mtest $(TOOLS)/$@ "$(LN)" src/mtest mtest
$(TOOLS)/$@ "$(LN)" src/ipopd ipopd $(TOOLS)/$@ "$(LN)" src/ipopd ipopd
$(TOOLS)/$@ "$(LN)" src/imapd imapd $(TOOLS)/$@ "$(LN)" src/imapd imapd

177
README.md
View File

@@ -1 +1,176 @@
# uw-imap ## 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.
## imap tools and server, c-client/libc-client/uw-imap-devel
The sources have been incrementally patched with the following from the Fedora Package Sources for uw-imap[[1]].
See the [_patches_](supplemental/patches) directory in this repository for the contents.
- 1006_openssl1.1_autoverify.patch
- imap-2004a-doc.patch
- imap-2007e-authmd5.patch
- imap-2007e-overflow.patch
- imap-2007e-poll.patch
- imap-2007e-shared.patch
- imap-2007e-system_c_client.patch
- imap-2007f-format-security.patch
- imap-2007f-ldflags.patch
Additional information is available at https://www.washington.edu/imap/
[1]: https://src.fedoraproject.org/rpms/uw-imap/tree/f29
## ORIGINAL [README](./README)
/* ========================================================================
* Copyright 1988-2007 University of Washington
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* ========================================================================
*/
IMAP Toolkit Environment
4 April 2007
Mark Crispin
UNIX QUICK BUILD NOTES
These quick build notes assume that you have installed OpenSSL before
attempting to build this software, and that you do not have any non-default
configuration parameters.
If you need additional information in building this software with OpenSSL,
please refer to the docs/SSLBUILD file for more information.
If you intend to build this software with a non-default configuration
(including building a non-compliant server without SSL support), please
refer to the docs/BUILD file for more information.
1) Look in the top-level Makefile and find your system type code. For example,
modern versions of Linux will use either "slx", "lnp", or one of the
lnp-variants (such as "lrh").
2) Type "make" followed by the system type, e.g. "make slx".
3) Install the POP2 daemon (ipopd/ipop2d), the POP3 daemon (ipopd/ipop3d), and
the IMAP daemon (imapd/imapd) on a system directory of your choosing.
4) Update /etc/services to register the pop2 service on TCP port 109, the
pop3 service on TCP port 110, and the imap service on TCP port 143. Also
update Yellow Pages/NIS/NetInfo/etc. if appropriate on your system.
5) Update /etc/inetd.conf (or install files on /etc/xinetd.d) to invoke the
POP2, POP3, and IMAP daemons on their associated services.
6) If your system uses PAM authentication, be sure to set up /etc/pam.d/imap
(*not* /etc/pam.d/imapd) and /etc/pam.d/pop (*not* /etc/pam.d/ipop3d or
/etc/pam.d/pop3d or /etc/pam.d/popd or /etc/pam.d/pop3).
7) Unless you built your system without SSL support, you will need to set
up SSL server certificates as described in docs/SSLBUILD.
6) That's all!
Read the file docs/BUILD and docs/SSLBUILD if you need more detailed
information and/or you don't understand these quick build instructions.
MISCELLANEOUS NOTES
mtest has been run under UNIX, DOS, Windows, NT, Macintosh, TOPS-20, and
VMS. It is a very primitive interface, however, and is suited mainly as a
model of how to write a main program for c-client. You should take a look at
the source to figure out how to use it. Briefly, it first asks for a mailbox
name (either a local file path or an IMAP mailbox in the form
"{hostname}mailbox") and then puts you in a command mode where "?" will give
you a list of commands.
Pine is available separately on the FTP.CAC.Washington.EDU archives.
The focus of development and support is for UNIX and Win32 (including
Windows 95/98/Millenium, Windows NT, and Windows 2000). The other ports are
not frequently used or tested, and may be incomplete.

View File

@@ -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/5] 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

View File

@@ -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/5] 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

View File

@@ -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/5] 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

View File

@@ -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/5] 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

View File

@@ -0,0 +1,795 @@
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

17
scripts/all.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
# Defaults suitable for automation
: "${CLEAN:=1}"
: "${PREFIX:=/usr/local/imap}"
: "${DEPS_AUTO:=1}"
# Install deps first (Debian/Ubuntu)
./scripts/deps-debian.sh
./scripts/apply-patches.sh
CLEAN="$CLEAN" ./scripts/build.sh
PREFIX="$PREFIX" ./scripts/install.sh

44
scripts/apply-patches.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PATCHDIR="${ROOT}/patches"
usage() {
cat <<USAGE
Usage: $0
Applies patches 00010004 to the working tree (idempotent).
USAGE
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
cd "$ROOT"
if [[ ! -d "$PATCHDIR" ]]; then
echo "ERROR: patches/ directory not found at: $PATCHDIR" >&2
exit 1
fi
shopt -s nullglob
patches=( "$PATCHDIR"/000[1-4]-*.patch )
if (( ${#patches[@]} == 0 )); then
echo "ERROR: no 00010004 patches found in $PATCHDIR" >&2
exit 1
fi
for p in "${patches[@]}"; do
echo "==> Checking $(basename "$p")"
if patch --dry-run -p1 < "$p" >/dev/null 2>&1; then
echo "==> Applying $(basename "$p")"
patch -p1 < "$p"
else
echo "==> Skipping $(basename "$p") (already applied or does not apply cleanly)"
fi
done
echo "Done."

71
scripts/build.sh Executable file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SSLTYPE="${SSLTYPE:-unix.nopwd}" # recommended for RFC 3501 compliance
TARGET="${TARGET:-lnp}" # what you used successfully
CLEAN="${CLEAN:-0}" # set to 1 for a clean build
usage() {
cat <<USAGE
Usage: $0
Build UW-IMAP in a deterministic, legacy-compatible order.
Environment:
SSLTYPE (default: unix.nopwd)
TARGET (default: lnp)
CLEAN (default: 0) set to 1 to remove build artifacts before building
Examples:
$0
CLEAN=1 $0
SSLTYPE=unix.nopwd TARGET=lnp CLEAN=1 $0
USAGE
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
cd "$ROOT"
if [[ -d patches ]]; then
echo "Hint: run ./scripts/apply-patches.sh before building if needed."
fi
if [[ "$CLEAN" == "1" ]]; then
echo "==> Cleaning previous build artifacts"
make clean || true
# Remove common UW-IMAP build byproducts/symlink trees that can break rebuilds
rm -f OSTYPE CFLAGS CCTYPE LDFLAGS OSCFLAGS ARCHIVE SPECIALS an 2>/dev/null || true
rm -rf c-client mtest ipopd imapd mailutil mlock dmail tmail rebuild 2>/dev/null || true
fi
# Ensure tools/an exists and is executable (should be part of the repo)
if [[ ! -f tools/an ]]; then
echo "ERROR: tools/an not found. Repository checkout seems incomplete." >&2
exit 1
fi
chmod +x tools/an 2>/dev/null || true
echo "==> Step 1/3: Prepare symlinks (make an)"
# This creates the symlink layout expected by the rest of the build (c-client/, mtest/, ...)
make an
echo "==> Step 2/3: Build core (make ${TARGET} SSLTYPE=${SSLTYPE})"
# IMPORTANT: do NOT use -j here; UW-IMAP's legacy build is not reliably parallel-safe.
make "${TARGET}" "SSLTYPE=${SSLTYPE}"
echo "==> Step 3/3: Build bundled tools (make bundled)"
# Bundled tools depend on generated headers like c-client/osdep.h.
#make bundled || true
make bundled
echo "Build done."
echo "Artifacts:"
echo " c-client/c-client.a: $(test -f c-client/c-client.a && echo OK || echo MISSING)"
echo " c-client/osdep.h: $(test -f c-client/osdep.h && echo OK || echo MISSING)"

101
scripts/deps-debian.sh Executable file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<USAGE
Usage: $0
Installs required build dependencies on Debian/Ubuntu using apt.
Environment:
DEPS_AUTO (default: 1) set to 0 to only print missing packages and exit non-zero
APT_YES (default: 1) set to 0 to run apt without -y
USAGE
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
DEPS_AUTO="${DEPS_AUTO:-1}"
APT_YES="${APT_YES:-1}"
# Must have apt
if ! command -v apt-get >/dev/null 2>&1; then
echo "ERROR: apt-get not found. This script supports Debian/Ubuntu only." >&2
exit 1
fi
# Basic distro check (soft)
if [[ -r /etc/os-release ]]; then
. /etc/os-release
case "${ID:-}" in
debian|ubuntu|linuxmint|pop) : ;;
*)
echo "WARN: Detected ID=${ID:-unknown}. Proceeding anyway (apt-based system assumed)." >&2
;;
esac
fi
# Packages needed to build UW-IMAP 2007f with modern toolchains
PKGS=(
build-essential
autoconf
automake
libtool
pkg-config
libssl-dev
libpam0g-dev
libc6-dev
libcrypt-dev
bison
flex
patch
ca-certificates
)
missing=()
for p in "${PKGS[@]}"; do
if dpkg -s "$p" >/dev/null 2>&1; then
continue
fi
missing+=( "$p" )
done
if (( ${#missing[@]} == 0 )); then
echo "==> Dependencies already satisfied."
exit 0
fi
echo "==> Missing packages:"
printf ' - %s\n' "${missing[@]}"
if [[ "$DEPS_AUTO" != "1" ]]; then
echo "DEPS_AUTO=0 -> not installing automatically." >&2
exit 2
fi
# Choose privilege escalation
SUDO=""
if [[ "$(id -u)" -ne 0 ]]; then
if command -v sudo >/dev/null 2>&1; then
SUDO="sudo"
else
echo "ERROR: Not running as root and sudo not found." >&2
exit 1
fi
fi
yesflag=()
if [[ "$APT_YES" == "1" ]]; then
yesflag=( -y )
fi
echo "==> Updating apt index"
$SUDO apt-get update
echo "==> Installing dependencies"
$SUDO apt-get install "${yesflag[@]}" "${missing[@]}"
echo "==> Done."

76
scripts/install.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PREFIX="${PREFIX:-/usr/local/imap}"
usage() {
cat <<USAGE
Usage: $0
Environment:
PREFIX (default: /usr/local/imap)
Installs:
- headers to: \$PREFIX/include
- static lib to: \$PREFIX/lib/libc-client.a
- binaries to: \$PREFIX/bin (if present)
USAGE
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
cd "$ROOT"
SRC_LIB="${ROOT}/c-client/c-client.a"
SRC_HDR_DIR="${ROOT}/c-client"
if [[ ! -f "$SRC_LIB" ]]; then
echo "ERROR: $SRC_LIB not found. Build first (./scripts/build.sh)." >&2
exit 1
fi
echo "==> Installing to PREFIX=$PREFIX"
install -d -m 0755 "$PREFIX/include" "$PREFIX/lib" "$PREFIX/bin"
echo "==> Installing headers"
install -m 0644 "$SRC_HDR_DIR"/*.h "$PREFIX/include/"
echo "==> Installing libc-client.a"
install -m 0644 "$SRC_LIB" "$PREFIX/lib/libc-client.a"
echo "==> Installing binaries (if present)"
# Common outputs after 'make bundled'
bins=(
"$ROOT/mtest/mtest"
"$ROOT/imapd/imapd"
"$ROOT/ipopd/ipopd"
"$ROOT/mailutil/mailutil"
"$ROOT/mlock/mlock"
"$ROOT/dmail/dmail"
"$ROOT/tmail/tmail"
)
installed_any=0
for b in "${bins[@]}"; do
if [[ -x "$b" ]]; then
install -m 0755 "$b" "$PREFIX/bin/"
echo " installed: $(basename "$b")"
installed_any=1
else
echo " skipped: $(basename "$b") (not found/executable)"
fi
done
echo "==> Done."
echo "Installed:"
echo " Headers: $PREFIX/include/*.h"
echo " Library: $PREFIX/lib/libc-client.a"
if [[ "$installed_any" -eq 1 ]]; then
echo " Binaries: $PREFIX/bin/"
else
echo " Binaries: none (run ./scripts/build.sh to build bundled tools)"
fi

View File

@@ -42,17 +42,17 @@ typedef struct {
/* Prototypes */ /* Prototypes */
long auth_md5_valid (void); static long auth_md5_valid (void);
long auth_md5_client (authchallenge_t challenger,authrespond_t responder, static long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
char *service,NETMBX *mb,void *stream, char *service,NETMBX *mb,void *stream,
unsigned long *trial,char *user); unsigned long *trial,char *user);
char *auth_md5_server (authresponse_t responder,int argc,char *argv[]); static char *auth_md5_server (authresponse_t responder,int argc,char *argv[]);
char *auth_md5_pwd (char *user); static char *auth_md5_pwd (char *user);
char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]); char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]);
char *hmac_md5 (char *text,unsigned long tl,char *key,unsigned long kl); static char *hmac_md5 (char *text,unsigned long tl,char *key,unsigned long kl);
void md5_init (MD5CONTEXT *ctx); static void md5_init (MD5CONTEXT *ctx);
void md5_update (MD5CONTEXT *ctx,unsigned char *data,unsigned long len); static void md5_update (MD5CONTEXT *ctx,unsigned char *data,unsigned long len);
void md5_final (unsigned char *digest,MD5CONTEXT *ctx); static void md5_final (unsigned char *digest,MD5CONTEXT *ctx);
static void md5_transform (unsigned long *state,unsigned char *block); static void md5_transform (unsigned long *state,unsigned char *block);
static void md5_encode (unsigned char *dst,unsigned long *src,int len); static void md5_encode (unsigned char *dst,unsigned long *src,int len);
static void md5_decode (unsigned long *dst,unsigned char *src,int len); static void md5_decode (unsigned long *dst,unsigned char *src,int len);

View File

@@ -384,6 +384,9 @@ void rfc822_parse_content (BODY *body,STRING *bs,char *h,unsigned long depth,
if (CHR (bs) == '\012'){/* following LF? */ if (CHR (bs) == '\012'){/* following LF? */
c = SNX (bs); i--; /* yes, slurp it */ c = SNX (bs); i--; /* yes, slurp it */
} }
if (!i) /* Make sure we don't get an overflow for */
break; /* messages ending on \015 (or the following */
/* i-- will cause i to be MAXINT. Not good.) */
case '\012': /* at start of a line, start with -- ? */ case '\012': /* at start of a line, start with -- ? */
if (!(i && i-- && ((c = SNX (bs)) == '-') && i-- && if (!(i && i-- && ((c = SNX (bs)) == '-') && i-- &&
((c = SNX (bs)) == '-'))) break; ((c = SNX (bs)) == '-'))) break;

View File

@@ -35,6 +35,7 @@ extern int errno; /* just in case */
#include <sys/stat.h> #include <sys/stat.h>
#include "c-client.h" #include "c-client.h"
#include "dquota.h" #include "dquota.h"
#include <ctype.h>
/* Globals */ /* Globals */

View File

@@ -40,6 +40,8 @@
#include <netdb.h> #include <netdb.h>
#include <ctype.h> #include <ctype.h>
#include <string.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 LOCKTIMEOUT 5 /* lock timeout in minutes */
#define LOCKPROTECTION 0664 #define LOCKPROTECTION 0664

View File

@@ -38,6 +38,7 @@
#include <signal.h> #include <signal.h>
#include "c-client.h" #include "c-client.h"
#include "imap4r1.h" #include "imap4r1.h"
#include <string.h>
/* Excellent reasons to hate ifdefs, and why my real code never uses them */ /* 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) void prompt (char *msg,char *txt)
{ {
printf ("%s",msg); printf ("%s",msg);
gets (txt); if (!fgets (txt, sizeof (txt), stdin)) txt[0] = '\0';
txt[strcspn (txt, "\r\n")] = '\0';
} }
/* Interfaces to C-client */ /* Interfaces to C-client */
@@ -779,7 +781,8 @@ void smtptest (long debug)
puts (" Msg (end with a line with only a '.'):"); puts (" Msg (end with a line with only a '.'):");
body->type = TYPETEXT; body->type = TYPETEXT;
*text = '\0'; *text = '\0';
while (gets (line)) { while (fgets (line, sizeof (line), stdin)) {
line[strcspn (line, "\r\n")] = '\0';
if (line[0] == '.') { if (line[0] == '.') {
if (line[1] == '\0') break; if (line[1] == '\0') break;
else strcat (text,"."); else strcat (text,".");

View File

@@ -73,7 +73,7 @@ SSLRSA= # -lRSAglue -lrsaref
SSLCFLAGS= -I$(SSLINCLUDE) -I$(SSLINCLUDE)/openssl\ SSLCFLAGS= -I$(SSLINCLUDE) -I$(SSLINCLUDE)/openssl\
-DSSL_CERT_DIRECTORY=\"$(SSLCERTS)\" -DSSL_KEY_DIRECTORY=\"$(SSLKEYS)\" -DSSL_CERT_DIRECTORY=\"$(SSLCERTS)\" -DSSL_KEY_DIRECTORY=\"$(SSLKEYS)\"
SSLLDFLAGS= -L$(SSLLIB) -lssl $(SSLCRYPTO) $(SSLRSA) SSLLDFLAGS= -L$(SSLLIB) -lssl $(SSLCRYPTO) $(SSLRSA) $(EXTRALDFLAGS)
# Extended flags needed for non-standard passwd types. You may need to modify. # Extended flags needed for non-standard passwd types. You may need to modify.
@@ -96,11 +96,11 @@ CHECKPW=std
LOGINPW=std LOGINPW=std
SIGTYPE=bsd SIGTYPE=bsd
CRXTYPE=std CRXTYPE=std
ACTIVEFILE=/usr/lib/news/active ACTIVEFILE=/var/lib/news/active
SPOOLDIR=/usr/spool SPOOLDIR=/var/spool
MAILSPOOL=$(SPOOLDIR)/mail MAILSPOOL=$(SPOOLDIR)/mail
NEWSSPOOL=$(SPOOLDIR)/news NEWSSPOOL=$(SPOOLDIR)/news
RSHPATH=/usr/ucb/rsh RSHPATH=/usr/bin/rsh
MD5PWD=/etc/cram-md5.pwd MD5PWD=/etc/cram-md5.pwd
# Tries one of the test alternatives below if not specified. # Tries one of the test alternatives below if not specified.
LOCKPGM= LOCKPGM=
@@ -170,6 +170,10 @@ BUILD=$(MAKE) build EXTRACFLAGS='$(EXTRACFLAGS)'\
EXTRADRIVERS='$(EXTRADRIVERS)' EXTRAAUTHENTICATORS='$(EXTRAAUTHENTICATORS)'\ EXTRADRIVERS='$(EXTRADRIVERS)' EXTRAAUTHENTICATORS='$(EXTRAAUTHENTICATORS)'\
PASSWDTYPE=$(PASSWDTYPE) SSLTYPE=$(SSLTYPE) IP=$(IP) PASSWDTYPE=$(PASSWDTYPE) SSLTYPE=$(SSLTYPE) IP=$(IP)
# Need this for the shared library rule to work correctly
.SUFFIXES: .o .so
SOFILES=${BINARIES:.o=.so}
# Here if no make argument established # Here if no make argument established
@@ -498,7 +502,7 @@ lnp: # Linux Pluggable Authentication modules
ACTIVEFILE=/var/lib/news/active \ ACTIVEFILE=/var/lib/news/active \
RSHPATH=/usr/bin/rsh \ RSHPATH=/usr/bin/rsh \
BASECFLAGS="$(GCCCFLAGS)" \ BASECFLAGS="$(GCCCFLAGS)" \
BASELDFLAGS="$(PAMLDFLAGS)" BASELDFLAGS="$(EXTRALDFLAGS) $(PAMLDFLAGS)"
lnx: # Linux non-shadow passwords lnx: # Linux non-shadow passwords
@echo You are building for traditional Linux *without* shadow @echo You are building for traditional Linux *without* shadow
@@ -853,18 +857,24 @@ vu2: # VAX Ultrix 2.3, etc.
# Build it! # Build it!
build: clean once $(ARCHIVE) build: clean once $(ARCHIVE) $(SHLIBNAME)
all: $(ARCHIVE) all: $(ARCHIVE) $(SHLIBNAME)
$(ARCHIVE): $(BINARIES) $(ARCHIVE): $(BINARIES)
sh -c '$(RM) $(ARCHIVE) || true' sh -c '$(RM) $(ARCHIVE) || true'
@$(CAT) ARCHIVE @$(CAT) ARCHIVE
@$(SH) ARCHIVE @$(SH) ARCHIVE
.c.o: $(SHLIBNAME): $(SOFILES)
`$(CAT) CCTYPE` -c `$(CAT) CFLAGS` $*.c gcc -shared -Wl,-soname,$(SHLIBNAME) -o $(SHLIBNAME) $(SOFILES) `cat LDFLAGS`
ln -s $(SHLIBNAME) lib$(SHLIBBASE).so
.c.so: osdep.h
$(CC) -fPIC -DPIC -D_REENTRANT -c `$(CAT) CFLAGS` ${@:.so=.c} -o $@
.c.o:
$(CC) -fPIC -DPIC -D_REENTRANT -c `$(CAT) CFLAGS` $*.c
# Cleanup # Cleanup
@@ -903,8 +913,7 @@ utf8aux.o: mail.h misc.h osdep.h utf8.h
# OS-dependent # OS-dependent
OSDEPS= mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \
osdep.o:mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \
osdep.h env_unix.h tcp_unix.h \ osdep.h env_unix.h tcp_unix.h \
osdep.c env_unix.c fs_unix.c ftl_unix.c nl_unix.c tcp_unix.c ip_unix.c\ osdep.c env_unix.c fs_unix.c ftl_unix.c nl_unix.c tcp_unix.c ip_unix.c\
auths.c crexcl.c flockcyg.c flocklnx.c flocksim.c fsync.c \ auths.c crexcl.c flockcyg.c flocklnx.c flocksim.c fsync.c \
@@ -918,12 +927,19 @@ osdep.o:mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \
write.c sslstdio.c \ write.c sslstdio.c \
strerror.c strpbrk.c strstr.c strtok.c strtoul.c \ strerror.c strpbrk.c strstr.c strtok.c strtoul.c \
OSCFLAGS OSCFLAGS
osdep.o: $(OSDEPS)
$(CC) -fPIC -DPIC -D_REENTRANT `$(CAT) CFLAGS` `$(CAT) OSCFLAGS` -c osdep.c
@echo ========================================================================
@echo Building OS-dependent module @echo Building OS-dependent module
@echo If you get No such file error messages for files x509.h, ssl.h, @echo If you get No such file error messages for files x509.h, ssl.h,
@echo pem.h, buffer.h, bio.h, and crypto.h, that means that OpenSSL @echo pem.h, buffer.h, bio.h, and crypto.h, that means that OpenSSL
@echo is not installed on your system. Either install OpenSSL first @echo is not installed on your system. Either install OpenSSL first
@echo or build with command: make `$(CAT) OSTYPE` SSLTYPE=none @echo or build with command: make `$(CAT) OSTYPE` SSLTYPE=none
`$(CAT) CCTYPE` -c `$(CAT) CFLAGS` `$(CAT) OSCFLAGS` -c osdep.c @echo ========================================================================
osdep.so: $(OSDEPS)
$(CC) -fPIC -DPIC -D_REENTRANT `$(CAT) CFLAGS` `cat OSCFLAGS` -c osdep.c -o $@
osdep.c: osdepbas.c osdepckp.c osdeplog.c osdepssl.c osdep.c: osdepbas.c osdepckp.c osdeplog.c osdepssl.c
$(CAT) osdepbas.c osdepckp.c osdeplog.c osdepssl.c > osdep.c $(CAT) osdepbas.c osdepckp.c osdeplog.c osdepssl.c > osdep.c

View File

@@ -300,7 +300,7 @@ int mbx_isvalid (MAILSTREAM **stream,char *name,char *tmp,int *ld,char *lock,
if (sbuf.st_ctime > sbuf.st_atime) { if (sbuf.st_ctime > sbuf.st_atime) {
tp[0] = sbuf.st_atime; /* preserve atime and mtime */ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
tp[1] = sbuf.st_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 */ /* 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)) stream->user_flags[LOCAL->ffuserflag]) || (oldpid != LOCAL->lastpid))
mbx_update_header (stream); mbx_update_header (stream);
tp[0] = time (0); /* make sure read comes after all that */ 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 */ if (LOCAL->ld >= 0) { /* unlock now */
unlockfd (LOCAL->ld,LOCAL->lock); 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 preserve \Marked status */
else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0); else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
tp[1] = sbuf.st_mtime; /* preserve mtime */ 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 */ close (fd); /* close the file */
MM_NOCRITICAL (stream); /* release critical */ MM_NOCRITICAL (stream); /* release critical */
unlockfd (ld,lock); /* release exclusive parse/append permission */ 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 preserve \Marked status */
else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0); else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
tp[1] = sbuf.st_mtime; /* preserve mtime */ 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 */ fclose (df); /* close the file */
MM_NOCRITICAL (dstream); /* release critical */ MM_NOCRITICAL (dstream); /* release critical */
} }
@@ -1444,7 +1444,7 @@ long mbx_parse (MAILSTREAM *stream)
time_t tp[2]; time_t tp[2];
tp[0] = time (0); tp[0] = time (0);
tp[1] = LOCAL->filetime; tp[1] = LOCAL->filetime;
utime (stream->mailbox,tp); set_utime_from_tp(stream->mailbox,tp);
} }
stream->silent = silent; /* can pass up events now */ stream->silent = silent; /* can pass up events now */
mail_exists (stream,nmsgs); /* notify upper level of new mailbox size */ 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 */ fstat (LOCAL->fd,&sbuf); /* get new write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* reset atime to now */ 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 */ unlockfd (ld,lock); /* release exclusive parse/append permission */
/* notify upper level of new mailbox size */ /* notify upper level of new mailbox size */
mail_exists (stream,stream->nmsgs); mail_exists (stream,stream->nmsgs);

View File

@@ -103,8 +103,10 @@ long mh_copy (MAILSTREAM *stream,char *sequence,char *mailbox,
long options); long options);
long mh_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data); long mh_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data);
int mh_select (struct direct *name); #include <dirent.h>
int mh_numsort (const void *d1,const void *d2);
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); char *mh_file (char *dst,char *name);
long mh_canonicalize (char *pattern,char *ref,char *pat); long mh_canonicalize (char *pattern,char *ref,char *pat);
void mh_setdate (char *file,MESSAGECACHE *elt); 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 * 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 c;
char *s = name->d_name; 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 * 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) - return atoi ((*(struct direct **) d1)->d_name) -
atoi ((*(struct direct **) d2)->d_name); atoi ((*(struct direct **) d2)->d_name);
@@ -1279,5 +1281,5 @@ void mh_setdate (char *file,MESSAGECACHE *elt)
time_t tp[2]; time_t tp[2];
tp[0] = time (0); /* atime is now */ tp[0] = time (0); /* atime is now */
tp[1] = mail_longdate (elt); /* modification time */ tp[1] = mail_longdate (elt); /* modification time */
utime (file,tp); /* set the times */ set_utime_from_tp(file,tp); /* set the times */
} }

View File

@@ -125,7 +125,7 @@ long mix_unsubscribe (MAILSTREAM *stream,char *mailbox);
long mix_create (MAILSTREAM *stream,char *mailbox); long mix_create (MAILSTREAM *stream,char *mailbox);
long mix_delete (MAILSTREAM *stream,char *mailbox); long mix_delete (MAILSTREAM *stream,char *mailbox);
long mix_rename (MAILSTREAM *stream,char *old,char *newname); 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); MAILSTREAM *mix_open (MAILSTREAM *stream);
void mix_close (MAILSTREAM *stream,long options); void mix_close (MAILSTREAM *stream,long options);
void mix_abort (MAILSTREAM *stream); void mix_abort (MAILSTREAM *stream);
@@ -140,8 +140,8 @@ THREADNODE *mix_thread (MAILSTREAM *stream,char *type,char *charset,
long mix_ping (MAILSTREAM *stream); long mix_ping (MAILSTREAM *stream);
void mix_check (MAILSTREAM *stream); void mix_check (MAILSTREAM *stream);
long mix_expunge (MAILSTREAM *stream,char *sequence,long options); long mix_expunge (MAILSTREAM *stream,char *sequence,long options);
int mix_select (struct direct *name); int mix_select (const struct dirent *name);
int mix_msgfsort (const void *d1,const void *d2); int mix_msgfsort (const struct dirent **d1, const struct dirent **d2);
long mix_addset (SEARCHSET **set,unsigned long start,unsigned long size); long mix_addset (SEARCHSET **set,unsigned long start,unsigned long size);
long mix_burp (MAILSTREAM *stream,MIXBURP *burp,unsigned long *reclaimed); long mix_burp (MAILSTREAM *stream,MIXBURP *burp,unsigned long *reclaimed);
long mix_burp_check (SEARCHSET *set,size_t size,char *file); 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 * 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); 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 * ".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; char c,*s;
/* make sure name has prefix */ /* 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 * 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; const char *n1 = (*d1)->d_name + sizeof (MIXNAME) - 1;
char *n2 = (*(struct direct **) d2)->d_name + sizeof (MIXNAME) - 1; const char *n2 = (*d2)->d_name + sizeof (MIXNAME) - 1;
return compare_ulong (*n1 ? strtoul (n1,NIL,16) : 0, return compare_ulong (*n1 ? strtoul (n1, NIL, 16) : 0,
*n2 ? strtoul (n2,NIL,16) : 0); *n2 ? strtoul (n2, NIL, 16) : 0);
} }
/* MIX add a range to a set /* MIX add a range to a set
* Accepts: pointer to set to add * Accepts: pointer to set to add
* start of set * start of set

View File

@@ -379,7 +379,7 @@ long mmdf_isvalid (char *name,char *tmp)
if ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) { if ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) {
tp[0] = sbuf.st_atime; /* preserve atime and mtime */ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
tp[1] = sbuf.st_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 */ else tp[0] = /* else preserve \Marked status */
((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ? ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?
sbuf.st_atime : tp[1]; 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 */ mmdf_unlock (fd,NIL,&lock); /* unlock and close mailbox */
if (tstream) { /* update last UID if we can */ if (tstream) { /* update last UID if we can */
MMDFLOCAL *local = (MMDFLOCAL *) tstream->local; 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 */ ret = NIL; /* return error */
} }
else tp[0] = tp[1] - 1; /* set atime to now-1 if successful copy */ 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 */ fclose (sf); /* done with scratch file */
/* force UIDVALIDITY assignment now */ /* force UIDVALIDITY assignment now */
if (tstream && !tstream->uid_validity) tstream->uid_validity = time (0); 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 */ else now = 0; /* no time change needed */
/* set the times, note change */ /* 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 */ flock (fd,LOCK_UN); /* release flock'ers */
if (!stream) close (fd); /* close the file if no stream */ 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 */ /* set atime to now, mtime a second earlier */
tp[1] = (tp[0] = time (0)) - 1; tp[1] = (tp[0] = time (0)) - 1;
/* set the times, note change */ /* 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 */ close (LOCAL->fd); /* close and reopen file */
if ((LOCAL->fd = open (stream->mailbox,O_RDWR, if ((LOCAL->fd = open (stream->mailbox,O_RDWR,
(long) mail_parameters (NIL,GET_MBXPROTECTION,NIL))) (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL)))

View File

@@ -196,7 +196,7 @@ int mtx_isvalid (char *name,char *tmp)
if (sbuf.st_ctime > sbuf.st_atime) { if (sbuf.st_ctime > sbuf.st_atime) {
tp[0] = sbuf.st_atime; /* preserve atime and mtime */ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
tp[1] = sbuf.st_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 */ fstat (LOCAL->fd,&sbuf); /* get current write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* make sure read comes after all that */ 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 */ fstat (LOCAL->fd,&sbuf); /* get new write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* reset atime to now */ tp[0] = time (0); /* reset atime to now */
utime (stream->mailbox,tp); set_utime_from_tp(stream->mailbox,tp);
MM_NOCRITICAL (stream); /* release critical */ MM_NOCRITICAL (stream); /* release critical */
/* notify upper level of new mailbox size */ /* notify upper level of new mailbox size */
mail_exists (stream,stream->nmsgs); 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 preserve \Marked status */
else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0); else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
tp[1] = sbuf.st_mtime; /* preserve mtime */ 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 */ close (fd); /* close the file */
unlockfd (ld,lock); /* release exclusive parse/append permission */ unlockfd (ld,lock); /* release exclusive parse/append permission */
MM_NOCRITICAL (stream); /* release critical */ 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 */ fstat (LOCAL->fd,&sbuf); /* get current write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* make sure atime remains greater */ 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)) 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 preserve \Marked status */
else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0); else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
tp[1] = sbuf.st_mtime; /* preserve mtime */ 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 */ fclose (df); /* close the file */
unlockfd (ld,lock); /* release exclusive parse/append permission */ unlockfd (ld,lock); /* release exclusive parse/append permission */
MM_NOCRITICAL (stream); /* release critical */ MM_NOCRITICAL (stream); /* release critical */
@@ -1212,7 +1212,7 @@ long mtx_parse (MAILSTREAM *stream)
time_t tp[2]; time_t tp[2];
tp[0] = time (0); tp[0] = time (0);
tp[1] = LOCAL->filetime; tp[1] = LOCAL->filetime;
utime (stream->mailbox,tp); set_utime_from_tp(stream->mailbox,tp);
} }
stream->silent = silent; /* can pass up events now */ stream->silent = silent; /* can pass up events now */
mail_exists (stream,nmsgs); /* notify upper level of new mailbox size */ 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 */ fstat (LOCAL->fd,&sbuf); /* get new write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* make sure read is later */ tp[0] = time (0); /* make sure read is later */
utime (stream->mailbox,tp); set_utime_from_tp(stream->mailbox,tp);
} }
} }
} }

View File

@@ -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, long mx_append_msg (MAILSTREAM *stream,char *flags,MESSAGECACHE *elt,
STRING *st,SEARCHSET *set); STRING *st,SEARCHSET *set);
int mx_select (struct direct *name); int mx_select (const struct dirent *name);
int mx_numsort (const void *d1,const void *d2); int mx_numsort (const struct dirent **d1, const struct dirent **d2);
char *mx_file (char *dst,char *name); char *mx_file (char *dst,char *name);
long mx_lockindex (MAILSTREAM *stream); long mx_lockindex (MAILSTREAM *stream);
void mx_unlockindex (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 * 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 c;
char *s = name->d_name; 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 * 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) - return atoi ((*d1)->d_name) - atoi ((*d2)->d_name);
atoi ((*(struct direct **) d2)->d_name);
} }
@@ -1283,5 +1282,5 @@ void mx_setdate (char *file,MESSAGECACHE *elt)
time_t tp[2]; time_t tp[2];
tp[0] = time (0); /* atime is now */ tp[0] = time (0); /* atime is now */
tp[1] = mail_longdate (elt); /* modification time */ tp[1] = mail_longdate (elt); /* modification time */
utime (file,tp); /* set the times */ set_utime_from_tp(file,tp); /* set the times */
} }

View File

@@ -76,8 +76,12 @@ long news_create (MAILSTREAM *stream,char *mailbox);
long news_delete (MAILSTREAM *stream,char *mailbox); long news_delete (MAILSTREAM *stream,char *mailbox);
long news_rename (MAILSTREAM *stream,char *old,char *newname); long news_rename (MAILSTREAM *stream,char *old,char *newname);
MAILSTREAM *news_open (MAILSTREAM *stream); 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_close (MAILSTREAM *stream,long options);
void news_fast (MAILSTREAM *stream,char *sequence,long flags); void news_fast (MAILSTREAM *stream,char *sequence,long flags);
void news_flags (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 * 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 c;
char *s = name->d_name; 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 * 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) - return atoi ((*(struct direct **) d1)->d_name) -
atoi ((*(struct direct **) d2)->d_name); atoi ((*(struct direct **) d2)->d_name);

View File

@@ -50,6 +50,26 @@
#include <syslog.h> #include <syslog.h>
#include <sys/file.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 */ /* Linux gets this wrong */

View File

@@ -227,8 +227,16 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags)
/* disable certificate validation? */ /* disable certificate validation? */
if (flags & NET_NOVALIDATECERT) if (flags & NET_NOVALIDATECERT)
SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL); SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL);
else SSL_CTX_set_verify (stream->context,SSL_VERIFY_PEER,ssl_open_verify); else {
#if OPENSSL_VERSION_NUMBER >= 0x10100000
X509_VERIFY_PARAM *param = SSL_CTX_get0_param(stream->context);
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
X509_VERIFY_PARAM_set1_host(param, host, 0);
#endif
SSL_CTX_set_verify (stream->context,SSL_VERIFY_PEER,ssl_open_verify);
/* set default paths to CAs... */ /* set default paths to CAs... */
}
SSL_CTX_set_default_verify_paths (stream->context); SSL_CTX_set_default_verify_paths (stream->context);
/* ...unless a non-standard path desired */ /* ...unless a non-standard path desired */
if (s = (char *) mail_parameters (NIL,GET_SSLCAPATH,NIL)) if (s = (char *) mail_parameters (NIL,GET_SSLCAPATH,NIL))
@@ -266,6 +274,7 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags)
if (SSL_write (stream->con,"",0) < 0) if (SSL_write (stream->con,"",0) < 0)
return ssl_last_error ? ssl_last_error : "SSL negotiation failed"; return ssl_last_error ? ssl_last_error : "SSL negotiation failed";
/* need to validate host names? */ /* need to validate host names? */
#if OPENSSL_VERSION_NUMBER < 0x10100000
if (!(flags & NET_NOVALIDATECERT) && if (!(flags & NET_NOVALIDATECERT) &&
(err = ssl_validate_cert (cert = SSL_get_peer_certificate (stream->con), (err = ssl_validate_cert (cert = SSL_get_peer_certificate (stream->con),
host))) { host))) {
@@ -275,6 +284,7 @@ static char *ssl_start_work (SSLSTREAM *stream,char *host,unsigned long flags)
sprintf (tmp,"*%.128s: %.255s",err,cert ? cert->name : "???"); sprintf (tmp,"*%.128s: %.255s",err,cert ? cert->name : "???");
return ssl_last_error = cpystr (tmp); return ssl_last_error = cpystr (tmp);
} }
#endif
return NIL; return NIL;
} }
@@ -313,6 +323,7 @@ static int ssl_open_verify (int ok,X509_STORE_CTX *ctx)
* Returns: NIL if validated, else string of error message * Returns: NIL if validated, else string of error message
*/ */
#if OPENSSL_VERSION_NUMBER < 0x10100000
static char *ssl_validate_cert (X509 *cert,char *host) static char *ssl_validate_cert (X509 *cert,char *host)
{ {
int i,n; int i,n;
@@ -342,6 +353,7 @@ static char *ssl_validate_cert (X509 *cert,char *host)
else ret = "Unable to locate common name in certificate"; else ret = "Unable to locate common name in certificate";
return ret; return ret;
} }
#endif
/* Case-independent wildcard pattern match /* Case-independent wildcard pattern match
* Accepts: base string * Accepts: base string

View File

@@ -203,7 +203,7 @@ int tenex_isvalid (char *name,char *tmp)
if (sbuf.st_ctime > sbuf.st_atime) { if (sbuf.st_ctime > sbuf.st_atime) {
tp[0] = sbuf.st_atime; /* preserve atime and mtime */ tp[0] = sbuf.st_atime; /* preserve atime and mtime */
tp[1] = sbuf.st_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 */ fstat (LOCAL->fd,&sbuf); /* get current write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* make sure read comes after all that */ 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 */ fstat (LOCAL->fd,&sbuf); /* get new write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* reset atime to now */ tp[0] = time (0); /* reset atime to now */
utime (stream->mailbox,tp); set_utime_from_tp(stream->mailbox,tp);
MM_NOCRITICAL (stream); /* release critical */ MM_NOCRITICAL (stream); /* release critical */
/* notify upper level of new mailbox size */ /* notify upper level of new mailbox size */
mail_exists (stream,stream->nmsgs); 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 preserve \Marked status */
else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0); else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
tp[1] = sbuf.st_mtime; /* preserve mtime */ 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 */ close (fd); /* close the file */
unlockfd (ld,lock); /* release exclusive parse/append permission */ unlockfd (ld,lock); /* release exclusive parse/append permission */
MM_NOCRITICAL (stream); /* release critical */ 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 */ fstat (LOCAL->fd,&sbuf); /* get current write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* make sure atime remains greater */ 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)) 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 preserve \Marked status */
else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0); else tp[0] = (sbuf.st_ctime > sbuf.st_atime) ? sbuf.st_atime : time(0);
tp[1] = sbuf.st_mtime; /* preserve mtime */ 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 */ fclose (df); /* close the file */
unlockfd (ld,lock); /* release exclusive parse/append permission */ unlockfd (ld,lock); /* release exclusive parse/append permission */
MM_NOCRITICAL (stream); /* release critical */ MM_NOCRITICAL (stream); /* release critical */
@@ -1324,7 +1324,7 @@ long tenex_parse (MAILSTREAM *stream)
time_t tp[2]; time_t tp[2];
tp[0] = time (0); tp[0] = time (0);
tp[1] = LOCAL->filetime; tp[1] = LOCAL->filetime;
utime (stream->mailbox,tp); set_utime_from_tp(stream->mailbox,tp);
} }
stream->silent = silent; /* can pass up events now */ stream->silent = silent; /* can pass up events now */
mail_exists (stream,nmsgs); /* notify upper level of new mailbox size */ 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 */ fstat (LOCAL->fd,&sbuf); /* get new write time */
tp[1] = LOCAL->filetime = sbuf.st_mtime; tp[1] = LOCAL->filetime = sbuf.st_mtime;
tp[0] = time (0); /* make sure read is later */ tp[0] = time (0); /* make sure read is later */
utime (stream->mailbox,tp); set_utime_from_tp(stream->mailbox,tp);
} }
} }
} }

View File

@@ -45,6 +45,7 @@ extern int errno; /* just in case */
#include "mail.h" #include "mail.h"
#include "osdep.h" #include "osdep.h"
#include <time.h> #include <time.h>
#include <utime.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "unix.h" #include "unix.h"
#include "pseudo.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)) { if ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) {
tp[0] = sbuf.st_atime; /* yes, preserve atime and mtime */ tp[0] = sbuf.st_atime; /* yes, preserve atime and mtime */
tp[1] = sbuf.st_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 */ else tp[0] = /* else preserve \Marked status */
((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ? ((sbuf.st_ctime > sbuf.st_atime) || (sbuf.st_mtime > sbuf.st_atime)) ?
sbuf.st_atime : tp[1]; 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 */ unix_unlock (fd,NIL,&lock); /* unlock and close mailbox */
if (tstream) { /* update last UID if we can */ if (tstream) { /* update last UID if we can */
UNIXLOCAL *local = (UNIXLOCAL *) tstream->local; 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 */ ret = NIL; /* return error */
} }
else tp[0] = tp[1] - 1; /* set atime to now-1 if successful copy */ 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 */ fclose (sf); /* done with scratch file */
/* force UIDVALIDITY assignment now */ /* force UIDVALIDITY assignment now */
if (tstream && !tstream->uid_validity) tstream->uid_validity = time (0); 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 */ else now = 0; /* no time change needed */
/* set the times, note change */ /* 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 */ flock (fd,LOCK_UN); /* release flock'ers */
if (!stream) close (fd); /* close the file if no stream */ 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 */ /* set atime to now, mtime a second earlier */
tp[1] = (tp[0] = time (0)) - 1; tp[1] = (tp[0] = time (0)) - 1;
/* set the times, note change */ /* 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 */ close (LOCAL->fd); /* close and reopen file */
if ((LOCAL->fd = open (stream->mailbox,O_RDWR, if ((LOCAL->fd = open (stream->mailbox,O_RDWR,
(long) mail_parameters (NIL,GET_MBXPROTECTION,NIL))) (long) mail_parameters (NIL,GET_MBXPROTECTION,NIL)))

View File

@@ -35,6 +35,7 @@ extern int errno; /* just in case */
#include <sys/stat.h> #include <sys/stat.h>
#include "c-client.h" #include "c-client.h"
#include "tquota.h" #include "tquota.h"
#include <ctype.h>
/* Globals */ /* Globals */

View File

@@ -0,0 +1,58 @@
Description: Support OpenSSL 1.1
When building with OpenSSL 1.1 and newer, use the new built-in
hostname verification instead of code that doesn't compile due to
structs having been made opaque.
Bug-Debian: https://bugs.debian.org/828589
--- a/src/osdep/unix/ssl_unix.c
+++ b/src/osdep/unix/ssl_unix.c
@@ -227,8 +227,16 @@ static char *ssl_start_work (SSLSTREAM *
/* disable certificate validation? */
if (flags & NET_NOVALIDATECERT)
SSL_CTX_set_verify (stream->context,SSL_VERIFY_NONE,NIL);
- else SSL_CTX_set_verify (stream->context,SSL_VERIFY_PEER,ssl_open_verify);
+ else {
+#if OPENSSL_VERSION_NUMBER >= 0x10100000
+ X509_VERIFY_PARAM *param = SSL_CTX_get0_param(stream->context);
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ X509_VERIFY_PARAM_set1_host(param, host, 0);
+#endif
+
+ SSL_CTX_set_verify (stream->context,SSL_VERIFY_PEER,ssl_open_verify);
/* set default paths to CAs... */
+ }
SSL_CTX_set_default_verify_paths (stream->context);
/* ...unless a non-standard path desired */
if (s = (char *) mail_parameters (NIL,GET_SSLCAPATH,NIL))
@@ -266,6 +274,7 @@ static char *ssl_start_work (SSLSTREAM *
if (SSL_write (stream->con,"",0) < 0)
return ssl_last_error ? ssl_last_error : "SSL negotiation failed";
/* need to validate host names? */
+#if OPENSSL_VERSION_NUMBER < 0x10100000
if (!(flags & NET_NOVALIDATECERT) &&
(err = ssl_validate_cert (cert = SSL_get_peer_certificate (stream->con),
host))) {
@@ -275,6 +284,7 @@ static char *ssl_start_work (SSLSTREAM *
sprintf (tmp,"*%.128s: %.255s",err,cert ? cert->name : "???");
return ssl_last_error = cpystr (tmp);
}
+#endif
return NIL;
}
@@ -313,6 +323,7 @@ static int ssl_open_verify (int ok,X509_
* Returns: NIL if validated, else string of error message
*/
+#if OPENSSL_VERSION_NUMBER < 0x10100000
static char *ssl_validate_cert (X509 *cert,char *host)
{
int i,n;
@@ -342,6 +353,7 @@ static char *ssl_validate_cert (X509 *ce
else ret = "Unable to locate common name in certificate";
return ret;
}
+#endif
/* Case-independent wildcard pattern match
* Accepts: base string

View File

@@ -0,0 +1,5 @@
#Patches
The patches contained here are sourced from the [Fedora Package Sources rpms repository](https://src.fedoraproject.org/rpms/uw-imap/tree/f29).
All but the imap-2007e-system_c_client.patch have been applied (see https://github.com/uw-imap/imap/commit/9eb7bb9d595b0b56b5f7b751fad58059b888a0fa#commitcomment-31836821)

View File

@@ -0,0 +1,30 @@
Patch by Robert Scheck <redhat@linuxnetz.de> for uw-imap >= 2004a, which corrects
paths to imapd, ipop2d and ipop3d in the man pages.
This patch is based on Red Hat Bugzilla ID #127271 and solves ID #229781.
--- imap-2004a/src/imapd/imapd.8 2004-05-18 19:46:54.000000000 +0200
+++ imap-2004a/src/imapd/imapd.8.doc 2004-07-23 15:24:17.000000000 +0200
@@ -3,7 +3,7 @@
.SH NAME
IMAPd \- Internet Message Access Protocol server
.SH SYNOPSIS
-.B /usr/etc/imapd
+.B /usr/sbin/imapd
.SH DESCRIPTION
.I imapd
is a server which supports the
--- imap-2004a/src/ipopd/ipopd.8 2004-05-18 19:50:05.000000000 +0200
+++ imap-2004a/src/ipopd/ipopd.8.doc 2004-07-23 15:23:38.000000000 +0200
@@ -3,9 +3,9 @@
.SH NAME
IPOPd \- Post Office Protocol server
.SH SYNOPSIS
-.B /usr/etc/ipop2d
+.B /usr/sbin/ipop2d
.PP
-.B /usr/etc/ipop3d
+.B /usr/sbin/ipop3d
.SH DESCRIPTION
.I ipop2d
and

View File

@@ -0,0 +1,18 @@
diff -up imap-2007/src/osdep/unix/Makefile.paths imap-2007/src/osdep/unix/Makefile
--- imap-2007/src/osdep/unix/Makefile.paths 2007-12-17 16:10:24.000000000 -0600
+++ imap-2007/src/osdep/unix/Makefile 2007-12-21 09:30:04.000000000 -0600
@@ -96,11 +96,11 @@ CHECKPW=std
LOGINPW=std
SIGTYPE=bsd
CRXTYPE=std
-ACTIVEFILE=/usr/lib/news/active
-SPOOLDIR=/usr/spool
+ACTIVEFILE=/var/lib/news/active
+SPOOLDIR=/var/spool
MAILSPOOL=$(SPOOLDIR)/mail
NEWSSPOOL=$(SPOOLDIR)/news
-RSHPATH=/usr/ucb/rsh
+RSHPATH=/usr/bin/rsh
MD5PWD=/etc/cram-md5.pwd
# Tries one of the test alternatives below if not specified.
LOCKPGM=

View File

@@ -0,0 +1,29 @@
diff -up imap-2007e/src/c-client/auth_md5.c.authmd5 imap-2007e/src/c-client/auth_md5.c
--- imap-2007e/src/c-client/auth_md5.c.authmd5 2008-06-04 13:18:34.000000000 -0500
+++ imap-2007e/src/c-client/auth_md5.c 2009-07-07 19:24:12.348005485 -0500
@@ -42,17 +42,17 @@ typedef struct {
/* Prototypes */
-long auth_md5_valid (void);
-long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
+static long auth_md5_valid (void);
+static long auth_md5_client (authchallenge_t challenger,authrespond_t responder,
char *service,NETMBX *mb,void *stream,
unsigned long *trial,char *user);
-char *auth_md5_server (authresponse_t responder,int argc,char *argv[]);
-char *auth_md5_pwd (char *user);
+static char *auth_md5_server (authresponse_t responder,int argc,char *argv[]);
+static char *auth_md5_pwd (char *user);
char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]);
-char *hmac_md5 (char *text,unsigned long tl,char *key,unsigned long kl);
-void md5_init (MD5CONTEXT *ctx);
-void md5_update (MD5CONTEXT *ctx,unsigned char *data,unsigned long len);
-void md5_final (unsigned char *digest,MD5CONTEXT *ctx);
+static char *hmac_md5 (char *text,unsigned long tl,char *key,unsigned long kl);
+static void md5_init (MD5CONTEXT *ctx);
+static void md5_update (MD5CONTEXT *ctx,unsigned char *data,unsigned long len);
+static void md5_final (unsigned char *digest,MD5CONTEXT *ctx);
static void md5_transform (unsigned long *state,unsigned char *block);
static void md5_encode (unsigned char *dst,unsigned long *src,int len);
static void md5_decode (unsigned long *dst,unsigned char *src,int len);

View File

@@ -0,0 +1,13 @@
diff -up imap-2007e/src/c-client/rfc822.c.overflow imap-2007e/src/c-client/rfc822.c
--- imap-2007e/src/c-client/rfc822.c.overflow 2008-12-12 11:08:26.000000000 -0600
+++ imap-2007e/src/c-client/rfc822.c 2009-07-07 19:27:20.057772757 -0500
@@ -384,6 +384,9 @@ void rfc822_parse_content (BODY *body,ST
if (CHR (bs) == '\012'){/* following LF? */
c = SNX (bs); i--; /* yes, slurp it */
}
+ if (!i) /* Make sure we don't get an overflow for */
+ break; /* messages ending on \015 (or the following */
+ /* i-- will cause i to be MAXINT. Not good.) */
case '\012': /* at start of a line, start with -- ? */
if (!(i && i-- && ((c = SNX (bs)) == '-') && i-- &&
((c = SNX (bs)) == '-'))) break;

View File

@@ -0,0 +1,192 @@
http://anonscm.debian.org/cgit/collab-maint/uw-imap.git/plain/debian/patches/1005_poll.patch
Description: Use poll(2) instead of select(2) to support more than 1024 file descriptors
Author: Ben Smithurst <ben.smithurst@gradwell.com>
Bug-Debian: https://bugs.debian.org/478193
diff --git a/src/osdep/unix/os_lnx.c b/src/osdep/unix/os_lnx.c
index 03fd17d..671bbd6 100644
--- a/src/osdep/unix/os_lnx.c
+++ b/src/osdep/unix/os_lnx.c
@@ -41,6 +41,7 @@
extern int errno; /* just in case */
#include <pwd.h>
#include "misc.h"
+#include <poll.h>
#include "fs_unix.c"
diff --git a/src/osdep/unix/os_slx.c b/src/osdep/unix/os_slx.c
index c94d632..f6bf27d 100644
--- a/src/osdep/unix/os_slx.c
+++ b/src/osdep/unix/os_slx.c
@@ -42,6 +42,7 @@ extern int errno; /* just in case */
#include <pwd.h>
#include <shadow.h>
#include "misc.h"
+#include <poll.h>
#include "fs_unix.c"
diff --git a/src/osdep/unix/tcp_unix.c b/src/osdep/unix/tcp_unix.c
index 795fb4f..c69eaec 100644
--- a/src/osdep/unix/tcp_unix.c
+++ b/src/osdep/unix/tcp_unix.c
@@ -235,12 +235,11 @@ TCPSTREAM *tcp_open (char *host,char *service,unsigned long port)
int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port,
char *tmp,int *ctr,char *hst)
{
- int i,ti,sock,flgs;
+ int i,ti,sock,flgs,tmo;
+ struct pollfd pfd;
size_t len;
time_t now;
struct protoent *pt = getprotobyname ("tcp");
- fd_set rfds,wfds,efds;
- struct timeval tmo;
struct sockaddr *sadr = ip_sockaddr (family,adr,adrlen,port,&len);
blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
/* fetid Solaris */
@@ -252,14 +251,6 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port,
sprintf (tmp,"Unable to create TCP socket: %s",strerror (errno));
(*bn) (BLOCK_NONSENSITIVE,data);
}
- else if (sock >= FD_SETSIZE) {/* unselectable sockets are useless */
- sprintf (tmp,"Unable to create selectable TCP socket (%d >= %d)",
- sock,FD_SETSIZE);
- (*bn) (BLOCK_NONSENSITIVE,data);
- close (sock);
- sock = -1;
- errno = EMFILE;
- }
else { /* get current socket flags */
flgs = fcntl (sock,F_GETFL,0);
@@ -284,16 +275,11 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port,
if ((sock >= 0) && ctr) { /* want open timeout? */
now = time (0); /* open timeout */
ti = ttmo_open ? now + ttmo_open : 0;
- tmo.tv_usec = 0;
- FD_ZERO (&rfds); /* initialize selection vector */
- FD_ZERO (&wfds); /* initialize selection vector */
- FD_ZERO (&efds); /* handle errors too */
- FD_SET (sock,&rfds); /* block for error or readable or writable */
- FD_SET (sock,&wfds);
- FD_SET (sock,&efds);
+ pfd.fd = sock;
+ pfd.events = POLLIN | POLLOUT;
do { /* block under timeout */
- tmo.tv_sec = ti ? ti - now : 0;
- i = select (sock+1,&rfds,&wfds,&efds,ti ? &tmo : NIL);
+ tmo = ti ? ti - now : 0;
+ i = poll (&pfd, 1, ti ? tmo * 1000 : -1);
now = time (0); /* fake timeout if interrupt & time expired */
if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0;
} while ((i < 0) && (errno == EINTR));
@@ -302,7 +288,7 @@ int tcp_socket_open (int family,void *adr,size_t adrlen,unsigned short port,
fcntl (sock,F_SETFL,flgs);
/* This used to be a zero-byte read(), but that crashes Solaris */
/* get socket status */
- if(FD_ISSET(sock, &rfds)) while (((i = *ctr = read (sock,tmp,1)) < 0) && (errno == EINTR));
+ if(pfd.revents & POLLIN) while (((i = *ctr = read (sock,tmp,1)) < 0) && (errno == EINTR));
}
if (i <= 0) { /* timeout or error? */
i = i ? errno : ETIMEDOUT;/* determine error code */
@@ -545,9 +531,8 @@ long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s)
stream->ictr -=n;
}
if (size) {
- int i;
- fd_set fds,efds;
- struct timeval tmo;
+ int i, tmo;
+ struct pollfd pfd;
time_t t = time (0);
blocknotify_t bn=(blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
(*bn) (BLOCK_TCPREAD,NIL);
@@ -556,16 +541,13 @@ long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s)
time_t now = tl;
time_t ti = ttmo_read ? now + ttmo_read : 0;
if (tcpdebug) mm_log ("Reading TCP buffer",TCPDEBUG);
- tmo.tv_usec = 0;
- FD_ZERO (&fds); /* initialize selection vector */
- FD_ZERO (&efds); /* handle errors too */
- /* set bit in selection vectors */
- FD_SET (stream->tcpsi,&fds);
- FD_SET (stream->tcpsi,&efds);
+
+ pfd.events = POLLIN;
+ pfd.fd = stream->tcpsi;
errno = NIL; /* initially no error */
do { /* block under timeout */
- tmo.tv_sec = ti ? ti - now : 0;
- i = select (stream->tcpsi+1,&fds,NIL,&efds,ti ? &tmo : NIL);
+ tmo = ti ? ti - now : 0;
+ i = poll (&pfd, 1, ti ? tmo * 1000 : -1);
now = time (0); /* fake timeout if interrupt & time expired */
if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0;
} while ((i < 0) && (errno == EINTR));
@@ -605,9 +587,8 @@ long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s)
long tcp_getdata (TCPSTREAM *stream)
{
- int i;
- fd_set fds,efds;
- struct timeval tmo;
+ int i, tmo;
+ struct pollfd pfd;
time_t t = time (0);
blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
if (stream->tcpsi < 0) return NIL;
@@ -617,15 +598,12 @@ long tcp_getdata (TCPSTREAM *stream)
time_t now = tl;
time_t ti = ttmo_read ? now + ttmo_read : 0;
if (tcpdebug) mm_log ("Reading TCP data",TCPDEBUG);
- tmo.tv_usec = 0;
- FD_ZERO (&fds); /* initialize selection vector */
- FD_ZERO (&efds); /* handle errors too */
- FD_SET (stream->tcpsi,&fds);/* set bit in selection vectors */
- FD_SET (stream->tcpsi,&efds);
+ pfd.fd = stream->tcpsi;
+ pfd.events = POLLIN;
errno = NIL; /* initially no error */
do { /* block under timeout */
- tmo.tv_sec = ti ? ti - now : 0;
- i = select (stream->tcpsi+1,&fds,NIL,&efds,ti ? &tmo : NIL);
+ tmo = ti ? ti - now : 0;
+ i = poll (&pfd, 1, ti ? tmo * 1000 : -1);
now = time (0); /* fake timeout if interrupt & time expired */
if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0;
} while ((i < 0) && (errno == EINTR));
@@ -677,9 +655,8 @@ long tcp_soutr (TCPSTREAM *stream,char *string)
long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size)
{
- int i;
- fd_set fds,efds;
- struct timeval tmo;
+ int i, tmo;
+ struct pollfd pfd;
time_t t = time (0);
blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
if (stream->tcpso < 0) return NIL;
@@ -689,15 +666,12 @@ long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size)
time_t now = tl;
time_t ti = ttmo_write ? now + ttmo_write : 0;
if (tcpdebug) mm_log ("Writing to TCP",TCPDEBUG);
- tmo.tv_usec = 0;
- FD_ZERO (&fds); /* initialize selection vector */
- FD_ZERO (&efds); /* handle errors too */
- FD_SET (stream->tcpso,&fds);/* set bit in selection vector */
- FD_SET(stream->tcpso,&efds);/* set bit in error selection vector */
+ pfd.fd = stream->tcpso;
+ pfd.events = POLLOUT;
errno = NIL; /* block and write */
do { /* block under timeout */
- tmo.tv_sec = ti ? ti - now : 0;
- i = select (stream->tcpso+1,NIL,&fds,&efds,ti ? &tmo : NIL);
+ tmo = ti ? ti - now : 0;
+ i = poll (&pfd, 1, ti ? tmo * 1000 : -1);
now = time (0); /* fake timeout if interrupt & time expired */
if ((i < 0) && (errno == EINTR) && ti && (ti <= now)) i = 0;
} while ((i < 0) && (errno == EINTR));

View File

@@ -0,0 +1,74 @@
diff -up imap-2007e/src/osdep/unix/Makefile.shared imap-2007e/src/osdep/unix/Makefile
--- imap-2007e/src/osdep/unix/Makefile.shared 2009-07-07 19:28:02.909755512 -0500
+++ imap-2007e/src/osdep/unix/Makefile 2009-07-07 19:29:35.870006799 -0500
@@ -170,6 +170,10 @@ BUILD=$(MAKE) build EXTRACFLAGS='$(EXTRA
EXTRADRIVERS='$(EXTRADRIVERS)' EXTRAAUTHENTICATORS='$(EXTRAAUTHENTICATORS)'\
PASSWDTYPE=$(PASSWDTYPE) SSLTYPE=$(SSLTYPE) IP=$(IP)
+# Need this for the shared library rule to work correctly
+.SUFFIXES: .o .so
+SOFILES=${BINARIES:.o=.so}
+
# Here if no make argument established
@@ -845,18 +849,24 @@ vu2: # VAX Ultrix 2.3, etc.
# Build it!
-build: clean once $(ARCHIVE)
+build: clean once $(ARCHIVE) $(SHLIBNAME)
-all: $(ARCHIVE)
+all: $(ARCHIVE) $(SHLIBNAME)
$(ARCHIVE): $(BINARIES)
sh -c '$(RM) $(ARCHIVE) || true'
@$(CAT) ARCHIVE
@$(SH) ARCHIVE
-.c.o:
- `$(CAT) CCTYPE` -c `$(CAT) CFLAGS` $*.c
+$(SHLIBNAME): $(SOFILES)
+ gcc -shared -Wl,-soname,$(SHLIBNAME) -o $(SHLIBNAME) $(SOFILES) `cat LDFLAGS`
+ ln -s $(SHLIBNAME) lib$(SHLIBBASE).so
+.c.so: osdep.h
+ $(CC) -fPIC -DPIC -D_REENTRANT -c `$(CAT) CFLAGS` ${@:.so=.c} -o $@
+
+.c.o:
+ $(CC) -fPIC -DPIC -D_REENTRANT -c `$(CAT) CFLAGS` $*.c
# Cleanup
@@ -895,8 +905,7 @@ utf8aux.o: mail.h misc.h osdep.h utf8.h
# OS-dependent
-
-osdep.o:mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \
+OSDEPS= mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \
osdep.h env_unix.h tcp_unix.h \
osdep.c env_unix.c fs_unix.c ftl_unix.c nl_unix.c tcp_unix.c ip_unix.c\
auths.c crexcl.c flockcyg.c flocklnx.c flocksim.c fsync.c \
@@ -910,12 +919,19 @@ osdep.o:mail.h misc.h env.h fs.h ftl.h n
write.c sslstdio.c \
strerror.c strpbrk.c strstr.c strtok.c strtoul.c \
OSCFLAGS
+
+osdep.o: $(OSDEPS)
+ $(CC) -fPIC -DPIC -D_REENTRANT `$(CAT) CFLAGS` `$(CAT) OSCFLAGS` -c osdep.c
+ @echo ========================================================================
@echo Building OS-dependent module
@echo If you get No such file error messages for files x509.h, ssl.h,
@echo pem.h, buffer.h, bio.h, and crypto.h, that means that OpenSSL
@echo is not installed on your system. Either install OpenSSL first
@echo or build with command: make `$(CAT) OSTYPE` SSLTYPE=none
- `$(CAT) CCTYPE` -c `$(CAT) CFLAGS` `$(CAT) OSCFLAGS` -c osdep.c
+ @echo ========================================================================
+
+osdep.so: $(OSDEPS)
+ $(CC) -fPIC -DPIC -D_REENTRANT `$(CAT) CFLAGS` `cat OSCFLAGS` -c osdep.c -o $@
osdep.c: osdepbas.c osdepckp.c osdeplog.c osdepssl.c
$(CAT) osdepbas.c osdepckp.c osdeplog.c osdepssl.c > osdep.c

View File

@@ -0,0 +1,17 @@
diff -up imap-2007e/Makefile.system_c_client imap-2007e/Makefile
--- imap-2007e/Makefile.system_c_client 2008-06-04 13:43:35.000000000 -0500
+++ imap-2007e/Makefile 2011-06-13 14:13:04.467014334 -0500
@@ -665,9 +665,11 @@ an ua:
@$(MAKE) ssl$(SSLTYPE)
@echo Applying $@ process to sources...
$(TOOLS)/$@ "$(LN)" src/c-client c-client
- $(TOOLS)/$@ "$(LN)" src/ansilib c-client
- $(TOOLS)/$@ "$(LN)" src/charset c-client
+ $(TOOLS)/$@ "$(LN)" src/ansilib c-client
+ $(TOOLS)/$@ "$(LN)" src/charset c-client
$(TOOLS)/$@ "$(LN)" src/osdep/$(SYSTEM) c-client
+ cp -alf /usr/include/imap/* c-client/
+ #sleep 5
$(TOOLS)/$@ "$(LN)" src/mtest mtest
$(TOOLS)/$@ "$(LN)" src/ipopd ipopd
$(TOOLS)/$@ "$(LN)" src/imapd imapd

View File

@@ -0,0 +1,12 @@
diff -Naur imap-2007f.orig/src/osdep/unix/flocklnx.c imap-2007f/src/osdep/unix/flocklnx.c
--- imap-2007f.orig/src/osdep/unix/flocklnx.c 2011-07-23 02:20:11.000000000 +0200
+++ imap-2007f/src/osdep/unix/flocklnx.c 2014-04-14 19:17:46.429000000 +0200
@@ -57,7 +57,7 @@
case ENOLCK: /* lock table is full */
sprintf (tmp,"File locking failure: %s",strerror (errno));
mm_log (tmp,WARN); /* give the user a warning of what happened */
- if (!logged++) syslog (LOG_ERR,tmp);
+ if (!logged++) syslog (LOG_ERR, "%s", tmp);
/* return failure if non-blocking lock */
if (op & LOCK_NB) return -1;
sleep (5); /* slow down in case it loops */

View File

@@ -0,0 +1,21 @@
diff -up imap-2007f/src/osdep/unix/Makefile.ldflags imap-2007f/src/osdep/unix/Makefile
--- imap-2007f/src/osdep/unix/Makefile.ldflags 2018-04-24 13:18:45.333043626 +0200
+++ imap-2007f/src/osdep/unix/Makefile 2018-04-24 13:29:09.262125281 +0200
@@ -73,7 +73,7 @@ SSLRSA= # -lRSAglue -lrsaref
SSLCFLAGS= -I$(SSLINCLUDE) -I$(SSLINCLUDE)/openssl\
-DSSL_CERT_DIRECTORY=\"$(SSLCERTS)\" -DSSL_KEY_DIRECTORY=\"$(SSLKEYS)\"
-SSLLDFLAGS= -L$(SSLLIB) -lssl $(SSLCRYPTO) $(SSLRSA)
+SSLLDFLAGS= -L$(SSLLIB) -lssl $(SSLCRYPTO) $(SSLRSA) $(EXTRALDFLAGS)
# Extended flags needed for non-standard passwd types. You may need to modify.
@@ -502,7 +502,7 @@ lnp: # Linux Pluggable Authentication mo
ACTIVEFILE=/var/lib/news/active \
RSHPATH=/usr/bin/rsh \
BASECFLAGS="$(GCCCFLAGS)" \
- BASELDFLAGS="$(PAMLDFLAGS)"
+ BASELDFLAGS="$(EXTRALDFLAGS) $(PAMLDFLAGS)"
lnx: # Linux non-shadow passwords
@echo You are building for traditional Linux *without* shadow