chiark / gitweb /
do not use closed ipf->fd to signal eof; implement [perhaps_][x]close
[inn-innduct.git] / backends / overchan.c
1 /*  $Id: overchan.c 6135 2003-01-19 01:15:40Z rra $
2 **
3 **  Parse input to add to news overview database.
4 */
5
6 #include "config.h"
7 #include "clibrary.h"
8 #include "portable/time.h"
9 #include <errno.h>
10 #include <syslog.h>
11 #include <sys/stat.h>
12
13 #include "inn/innconf.h"
14 #include "inn/messages.h"
15 #include "inn/qio.h"
16 #include "libinn.h"
17 #include "ov.h"
18 #include "paths.h"
19
20 unsigned int NumArts;
21 unsigned int StartTime;
22 unsigned int TotOvTime;
23
24 /*
25  * Timer function (lifted from innd/timer.c). 
26  * This function is designed to report the number of milliseconds since
27  * the first invocation.  I wanted better resolution than time(), and
28  * something easier to work with than gettimeofday()'s struct timeval's.
29  */
30
31 static unsigned gettime(void)
32 {
33     static int                  init = 0;
34     static struct timeval       start_tv;
35     struct timeval              tv;
36     
37     if (! init) {
38         gettimeofday(&start_tv, NULL);
39         init++;
40     }
41     gettimeofday(&tv, NULL);
42     return((tv.tv_sec - start_tv.tv_sec) * 1000 + (tv.tv_usec - start_tv.tv_usec) / 1000);
43 }
44
45 /*
46 **  Process the input.  Data comes from innd in the form:
47 **  @token@ data
48 */
49
50 #define TEXT_TOKEN_LEN (2*sizeof(TOKEN)+2)
51 static void ProcessIncoming(QIOSTATE *qp)
52 {
53     char                *Data;
54     char                *p;
55     TOKEN               token;
56     unsigned int        starttime, endtime;
57     time_t              Time, Expires;
58
59     for ( ; ; ) {
60         /* Read the first line of data. */
61         if ((Data = QIOread(qp)) == NULL) {
62             if (QIOtoolong(qp)) {
63                 warn("line too long");
64                 continue;
65             }
66             break;
67         }
68
69         if (Data[0] != '@' || strlen(Data) < TEXT_TOKEN_LEN+2 
70             || Data[TEXT_TOKEN_LEN-1] != '@' || Data[TEXT_TOKEN_LEN] != ' ') {
71             warn("malformed token %s", Data);
72             continue;
73         }
74         token = TextToToken(Data);
75         Data += TEXT_TOKEN_LEN+1; /* skip over token and space */
76         for (p = Data; !ISWHITE(*p) ;p++) ;
77         *p++ = '\0';
78         Time = (time_t)atol(Data);
79         for (Data = p; !ISWHITE(*p) ;p++) ;
80         *p++ = '\0';
81         Expires = (time_t)atol(Data);
82         Data = p;
83         NumArts++;
84         starttime = gettime();
85         if (OVadd(token, Data, strlen(Data), Time, Expires) == OVADDFAILED)
86             syswarn("cannot write overview %s", Data);
87         endtime = gettime();
88         TotOvTime += endtime - starttime;
89     }
90     QIOclose(qp);
91 }
92
93
94 int main(int ac, char *av[])
95 {
96     QIOSTATE            *qp;
97     unsigned int        now;
98
99     /* First thing, set up our identity. */
100     message_program_name = "overchan";
101
102     /* Log warnings and fatal errors to syslog unless we were given command
103        line arguments, since we're probably running under innd. */
104     if (ac == 0) {
105         openlog("overchan", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);
106         message_handlers_warn(1, message_log_syslog_err);
107         message_handlers_die(1, message_log_syslog_err);
108         message_handlers_notice(1, message_log_syslog_notice);
109     }
110         
111     /* Set defaults. */
112     if (!innconf_read(NULL))
113         exit(1);
114     umask(NEWSUMASK);
115     if (innconf->enableoverview && !innconf->useoverchan)
116         warn("overchan is running while innd is creating overview data (you"
117              " can ignore this message if you are running makehistory -F)");
118
119     ac -= 1;
120     av += 1;
121
122     if (!OVopen(OV_WRITE))
123         die("cannot open overview");
124
125     StartTime = gettime();
126     if (ac == 0)
127         ProcessIncoming(QIOfdopen(STDIN_FILENO));
128     else {
129         for ( ; *av; av++)
130             if (strcmp(*av, "-") == 0)
131                 ProcessIncoming(QIOfdopen(STDIN_FILENO));
132             else if ((qp = QIOopen(*av)) == NULL)
133                 syswarn("cannot open %s", *av);
134             else
135                 ProcessIncoming(qp);
136     }
137     OVclose();
138     now = gettime();
139     notice("timings %u arts %u of %u ms", NumArts, TotOvTime, now - StartTime);
140     exit(0);
141     /* NOTREACHED */
142 }