chiark / gitweb /
Merge branches 'idx/verh' and 'idx/qmqpc'
[qmail] / maildirwatch.c
1 #include "getln.h"
2 #include "substdio.h"
3 #include "subfd.h"
4 #include "prioq.h"
5 #include "stralloc.h"
6 #include "str.h"
7 #include "exit.h"
8 #include "hfield.h"
9 #include "readwrite.h"
10 #include "open.h"
11 #include "headerbody.h"
12 #include "maildir.h"
13
14 #define FATAL "maildirwatch: fatal: "
15
16 void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); }
17
18 stralloc recipient = {0};
19 stralloc sender = {0};
20 stralloc fromline = {0};
21 stralloc text = {0};
22
23 void addtext(s,n) char *s; int n;
24 {
25  if (!stralloc_catb(&text,s,n)) die_nomem();
26  if (text.len > 158) text.len = 158;
27 }
28 void dobody(h) stralloc *h; { addtext(h->s,h->len); }
29 void doheader(h) stralloc *h;
30 {
31  int i;
32  switch(hfield_known(h->s,h->len))
33   {
34    case H_SUBJECT:
35      i = hfield_skipname(h->s,h->len);
36      addtext(h->s + i,h->len - i);
37      break;
38    case H_DELIVEREDTO:
39      i = hfield_skipname(h->s,h->len);
40      if (i < h->len)
41        if (!stralloc_copyb(&recipient,h->s + i,h->len - i - 1)) die_nomem();
42      break;
43    case H_RETURNPATH:
44      i = hfield_skipname(h->s,h->len);
45      if (i < h->len)
46        if (!stralloc_copyb(&sender,h->s + i,h->len - i - 1)) die_nomem();
47      break;
48    case H_FROM:
49      if (!stralloc_copyb(&fromline,h->s,h->len - 1)) die_nomem();
50      break;
51   }
52 }
53 void finishheader() { ; }
54
55 stralloc filenames = {0};
56 prioq pq = {0};
57
58 char inbuf[SUBSTDIO_INSIZE];
59 substdio ssin;
60
61 void main()
62 {
63  struct prioq_elt pe;
64  int fd;
65  int i;
66
67  if (maildir_chdir() == -1)
68    strerr_die1(111,FATAL,&maildir_chdir_err);
69
70  for (;;)
71   {
72    maildir_clean(&filenames);
73    if (maildir_scan(&pq,&filenames,1,0) == -1)
74      strerr_die1(111,FATAL,&maildir_scan_err);
75
76    substdio_putsflush(subfdout,"\033[;H\033[;J");
77
78    while (prioq_min(&pq,&pe))
79     {
80      prioq_delmin(&pq);
81
82      fd = open_read(filenames.s + pe.id);
83      if (fd == -1) continue;
84      substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf));
85
86      if (!stralloc_copys(&sender,"?")) die_nomem();
87      if (!stralloc_copys(&recipient,"?")) die_nomem();
88      if (!stralloc_copys(&fromline,"")) die_nomem();
89      if (!stralloc_copys(&text,"")) die_nomem();
90      if (headerbody(&ssin,doheader,finishheader,dobody) == -1)
91        strerr_die2x(111,FATAL,"trouble reading new message");
92
93      for (i = 0;i < fromline.len;++i)
94        if ((fromline.s[i] < 32) || (fromline.s[i] > 126))
95          fromline.s[i] = '/';
96      for (i = 0;i < sender.len;++i)
97        if ((sender.s[i] < 32) || (sender.s[i] > 126))
98          sender.s[i] = '?';
99      for (i = 0;i < recipient.len;++i)
100        if ((recipient.s[i] < 32) || (recipient.s[i] > 126))
101          recipient.s[i] = '?';
102      for (i = 0;i < text.len;++i)
103        if ((text.s[i] < 32) || (text.s[i] > 126))
104          text.s[i] = '/';
105      substdio_puts(subfdout,"FROM ");
106      substdio_put(subfdout,sender.s,sender.len);
107      substdio_puts(subfdout," TO <");
108      substdio_put(subfdout,recipient.s,recipient.len);
109      substdio_puts(subfdout,">\n");
110      if (fromline.len)
111       {
112        substdio_puts(subfdout,"\033[1m");
113        substdio_put(subfdout,fromline.s,fromline.len);
114        substdio_puts(subfdout,"\033[0m\n");
115       }
116      substdio_put(subfdout,text.s,text.len);
117      substdio_puts(subfdout,"\n\n");
118
119      close(fd);
120     }
121
122    substdio_flush(subfdout);
123    sleep(30);
124   }
125 }