Add trivial HM decoder
[doldaconnect.git] / config / speedrec.c
1 #include <string.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/file.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <errno.h>
8 #include <time.h>
9 #include <sys/poll.h>
10 #include <signal.h>
11
12 char buf[4096];
13 volatile int eof;
14
15 void sighandler(int sig)
16 {
17     eof = 1;
18 }
19
20 int main(int argc, char **argv)
21 {
22     int i;
23     int ret, fd;
24     time_t starttime, endtime;
25     long long numbytes;
26     size_t datalen;
27     struct pollfd pfd[2];
28     FILE *recfile;
29     int thisrec, numrecs, numuses, maxrec;
30     int recs[5];
31     
32     if(argc < 2)
33     {
34         fprintf(stderr, "usage: speedrec recfile\n");
35         exit(1);
36     }
37     numbytes = 0;
38     starttime = endtime = 0;
39     datalen = 0;
40     eof = 0;
41     signal(SIGHUP, sighandler);
42     signal(SIGINT, sighandler);
43     signal(SIGTERM, sighandler);
44     while(1)
45     {
46         pfd[0].fd = 0;
47         if(eof || (datalen >= sizeof(buf)))
48             pfd[0].events = 0;
49         else
50             pfd[0].events = POLLIN;
51         pfd[1].fd = 1;
52         if(datalen > 0)
53             pfd[1].events = POLLOUT;
54         else
55             pfd[1].events = 0;
56         pfd[0].revents = pfd[1].revents = 0;
57         ret = poll(pfd, 2, -1);
58         if((ret < 0) && (errno != EINTR))
59         {
60             perror("cannot poll");
61             exit(1);
62         }
63         if(pfd[0].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL))
64         {
65             ret = read(0, buf + datalen, sizeof(buf) - datalen);
66             if((ret < 0) && (errno != EINTR))
67             {
68                 perror("cannot read");
69                 exit(1);
70             }
71             if(ret == 0)
72                 eof = 1;
73             if(ret > 0)
74             {
75                 datalen += ret;
76                 if(starttime == 0)
77                     starttime = time(NULL);
78                 endtime = time(NULL);
79             }
80             numbytes += ret;
81         }
82         if(pfd[1].revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL))
83         {
84             ret = write(1, buf, datalen);
85             if((ret < 0) && (errno != EINTR))
86             {
87                 perror("cannot write");
88                 exit(1);
89             }
90             memmove(buf, buf + ret, datalen -= ret);
91         }
92         if(eof && (datalen == 0))
93             break;
94     }
95     if((starttime == 0) || (endtime == 0) || (endtime == starttime))
96         exit(0);
97     if(numbytes == 0)
98         exit(0);
99     thisrec = (int)(numbytes / ((long long)(endtime - starttime)));
100     if((fd = open(argv[1], O_RDWR | O_CREAT, 0666)) < 0)
101     {
102         perror(argv[1]);
103         exit(1);
104     }
105     recfile = fdopen(fd, "r+");
106     close(0);
107     close(1);
108     flock(fd, LOCK_EX);
109     if(fscanf(recfile, "%i\n", &numuses) < 1)
110         numuses = 0;
111     if(fscanf(recfile, "%i\n", &maxrec) < 1)
112         maxrec = 0;
113     if(fscanf(recfile, "%i\n", &numrecs) < 1)
114         numrecs = 0;
115     for(i = 0; i < numrecs; i++)
116         fscanf(recfile, "%i\n", &recs[i]);
117     if(numrecs == 5)
118     {
119         for(i = 0; i < 4; i++)
120             recs[i] = recs[i + 1];
121         numrecs = 4;
122     }
123     recs[numrecs++] = thisrec;
124     rewind(recfile);
125     ftruncate(fd, 0);
126     fprintf(recfile, "%i\n", numuses + 1);
127     fprintf(recfile, "%i\n", (thisrec > maxrec)?thisrec:maxrec);
128     fprintf(recfile, "%i\n", numrecs);
129     for(i = 0; i < numrecs; i++)
130         fprintf(recfile, "%i\n", recs[i]);
131     flock(fd, LOCK_UN);
132     fclose(recfile);
133     return(0);
134 }