]> Pileus Git - ~andy/fetchmail/blob - contrib/rawlog.patch
bec08b5efa2f2b8d45bf23a19e6578c2f391773e
[~andy/fetchmail] / contrib / rawlog.patch
1 This patch logs raw socket data, to assist debugging when discriminating
2 between server and fetchmail bugs.
3
4 Apply it to socket.c (works as of 6.3.20) and set the environment
5 variable FETCHMAIL_RAW_LOGFILE to a log file writable by fetchmail. If
6 it's not there, it gets created with mode 0600 (which requires directory
7 write permission).
8
9 The file gets appended to, so you can log into named pipes, character
10 (stream) devices and to the console if you're so inclined.
11
12 Note 1: any logging failures cause fetchmail to abort() forcefully.
13
14 Note 2: raw control characters persist in the log and are not filtered
15 out. In doubt use a pager that filters control characters, or use tools
16 such as a binary-capable text edtior, vim's xxd, or hexdump, or od, to
17 view the raw log message.
18
19 -- Matthias Andree, June 2011
20
21 diff --git a/socket.c b/socket.c
22 index c8117a5..89847fe 100644
23 --- a/socket.c
24 +++ b/socket.c
25 @@ -362,6 +362,49 @@ static     SSL *_ssl_context[FD_SETSIZE];
26 =======
27 Note 2: non-printable characters are hex-escaped, so it is safe to use
28 FETCHMAIL_RAW_LOGFILE=/dev/stderr or similar.
29
30 -- Matthias Andree, August 2011
31
32 diff --git a/sink.c b/sink.c
33 index 5d92556..ff6208d 100644
34 --- a/sink.c
35 +++ b/sink.c
36 @@ -649,6 +649,10 @@ int stuffline(struct query *ctl, char *buf)
37      while ((last += strlen(last)) && (last[-1] != '\n'))
38          last++;
39  
40 +    if (outlevel >= O_DEBUG && (size_t)(last - buf) != strlen(buf))
41 +       report(stdout, GT_("DEBUG: stuffline shipping line with NULs, length=%lu, strlen=%lu\n"), last - buf, strlen(buf));
42 +
43 +
44      /* fix message lines that have only \n termination (for qmail) */
45      if (ctl->forcecr)
46      {
47 diff --git a/socket.c b/socket.c
48 index e338207..dcaf19d 100644
49 --- a/socket.c
50 +++ b/socket.c
51 @@ -381,6 +381,49 @@ static     SSL *_ssl_context[FD_SETSIZE];
52 >>>>>>> legacy_63
53  static SSL     *SSLGetContext( int );
54  #endif /* SSL_ENABLE */
55  
56 +#include <fcntl.h>
57 +
58 +static const char *rawlogfile;
59 +static FILE *rlogstream;
60 +
61 +static int SockLog(void) {
62 +    static int haveinit;
63 +    static int wantlog;
64 +    static int logfd = -1;
65 +
66 +    if (!haveinit) {
67 +       haveinit = 1;
68 +       if ((rawlogfile = getenv("FETCHMAIL_RAW_LOGFILE"))) {
69 +           if ((logfd = open(rawlogfile, O_WRONLY|O_APPEND|O_CREAT, 0600)) == -1) {
70 +               report(stderr, GT_("FETCHMAIL_RAW_LOGFILE is set, but opening \"%s\" for appending write failed: %s\n"), rawlogfile, strerror(errno));
71 +               abort();
72 +           }
73 +           if (!(rlogstream = fdopen(logfd, "a"))) {
74 +               report(stderr, GT_("FETCHMAIL_RAW_LOGFILE is set, but fdopen(%d) failed: %s\n"), logfd, strerror(errno));
75 +               abort();
76 +           }
77 +           setvbuf(rlogstream, NULL, _IOLBF, 0);
78 +           wantlog = 1;
79 +       }
80 +    }
81 +    return wantlog;
82 +}
83 +
84 +static void LogPrintf(const char *fmt, ...) {
85 +    va_list va;
86 +    const char *locsav;
87 +    va_start(va, fmt);
88 +    if (!SockLog()) return;
89 +    locsav = setlocale(LC_ALL, NULL);
90 +    (void)setlocale(LC_ALL, "C");
91 +    if (EOF == vfprintf(rlogstream, fmt, va) || EOF == fflush(rlogstream)) {
92 +       report(stderr, GT_("FETCHMAIL_RAW_LOGFILE is set, but logging failed: %s\n"), strerror(errno));
93 +       abort();
94 +    }
95 +    (void)setlocale(LC_ALL, locsav);
96 +    va_end(va);
97 +}
98 +
99  int SockWrite(int sock, const char *buf, int len)
100  {
101      int n, wrlen = 0;
102 @@ -369,6 +412,8 @@ int SockWrite(int sock, const char *buf, int len)
103      SSL *ssl;
104  #endif
105  
106 +    LogPrintf("[>%d-%s count=%04d] %.*s%s", sock, SSLGetContext(sock) ? "crypt" : "plain", len, len, buf, (len < 1 || buf[len - 1] != '\n') ? "\n" : "");
107 +
108      while (len)
109      {
110  #ifdef SSL_ENABLE
111 @@ -471,6 +516,8 @@ int SockRead(int sock, char *buf, int len)
112             (!newline && len);
113      *bp = '\0';
114  
115 +    LogPrintf("[<%d-%s count=%04d] %.*s%s", sock, SSLGetContext(sock) ? "crypt" : "plain", bp - buf, bp - buf, buf, newline ? "" : "\n");
116 +
117      return bp - buf;
118  }
119