#include #include #include #include #include #include #include #include "os.h" #include "vt.h" #include "fdset.h" #include "vbi.h" #include "lang.h" #include "misc.h" char *fmt = "%a %b %d %H:%M:%S %Z %Y"; int max_diff = 2*60*60; // default: 2 hours int set_time = 0; char *outfile = ""; static char *channel; u_int16_t sid; static void chk_time(int t) { struct tm *tm; time_t sys_t; int dt; char buf[256]; if (t < 0 || t > 235959 || t%100 > 59 || t/100%100 > 59) return; sys_t = time(0); tm = localtime(&sys_t); // Now convert to UTC seconds t = t/100/100 * 60*60 + t/100%100 * 60 + t%100; #ifdef BSD t -= tm->tm_gmtoff; // dst already included... #else t += timezone; if (tm->tm_isdst) t -= 60*60; #endif dt = t - sys_t % (24*60*60); if (dt <= -12*60*60) dt += 24*60*60; if (dt <= -max_diff || dt >= max_diff) fatal("time diff too big (%2d:%02d:%02d)", dt/60/60, abs(dt)/60%60, abs(dt)%60); sys_t += dt; if (set_time) { struct timeval tv[1]; tv->tv_sec = sys_t; tv->tv_usec = 500000; if (settimeofday(tv, 0) == -1) ioerror("settimeofday"); } if (*fmt) { tm = localtime(&sys_t); if (strftime(buf, sizeof(buf), fmt, tm)) puts(buf); } exit(0); } static void event(void *_, struct vt_event *ev) { switch (ev->type) { /* vbi may generate EV_PAGE, EV_HEADER, EV_XPACKET */ /* for event arguments see vt.h */ case EV_HEADER: // a new title line (for running headers) { static int last_t = -1; u8 *s = ev->p1; int i, t = 1; if (ev->i2 & PG_OUTOFSEQ) break; for (i = 32; i < 40; ++i) if (s[i] >= '0' && s[i] <= '9') t = t * 10+ s[i] - '0'; if (t >= 1000000 && t <= 1235959) if (t == last_t || t - last_t == 1) chk_time(t - 1000000); last_t = t; break; } } } static void usage(FILE *fp, int exit_val) { fprintf(fp, "usage: %s [options]\n", prgname); fprintf(fp, "\n" " Valid options:\t\tDefault:\n" " -d -delta \t7200 (2 hours)\n" " -f -format \t\t%%c\n" " -h -help\n" " -s -set\t\t\toff\n" " -to -timeout \t(none)\n" " -v -vbi \t\t/dev/vbi\n" " \t\t/dev/vbi0\n" " \t\t/dev/video0\n" " \t\t/dev/dvb/adapter0/demux0\n" ); exit(exit_val); } static int option(int argc, char **argv, int *ind, char **arg) { static struct { char *nam, *altnam; int arg; } opts[] = { { "-delta", "-d", 1 }, { "-format", "-f", 1 }, { "-help", "-h", 0 }, { "-set", "-s", 0 }, { "-timeout", "-to", 1 }, { "-vbi", "-v", 1 }, }; int i; if (*ind >= argc) return 0; *arg = argv[(*ind)++]; for (i = 0; i < NELEM(opts); ++i) if (streq(*arg, opts[i].nam) || streq(*arg, opts[i].altnam)) { if (opts[i].arg) if (*ind < argc) *arg = argv[(*ind)++]; else fatal("option %s requires an argument", *arg); return i+1; } if (**arg == '-') { fatal("%s: invalid option", *arg); usage(stderr, 1); } return -1; } int main(int argc, char **argv) { char *vbi_name = NULL; int timeout = 0; struct vbi *vbi; int opt, ind; char *arg; int ttpid = -1; setprgname(argv[0]); ind = 1; while (opt = option(argc, argv, &ind, &arg)) switch (opt) { case 1: // -delta max_diff = atoi(arg); if (max_diff < 1) fatal("-delta: illegal value '%s'", arg); if (max_diff > 12*60*60) { max_diff = 12*60*60; error("-delta: %d too big. Assuming %d", arg, max_diff); } break; case 2: // -format fmt = arg; break; case 3: // help usage(stdout, 0); break; case 4: // -set set_time = 1; break; case 5: // -timeout timeout = atoi(arg); if (timeout < 1 || timeout > 60*60) fatal("-timeout: illegal value '%s'", arg); break; case 6: // -vbi vbi_name = arg; break; case -1: usage(stderr, 1); break; } fdset_init(fds); if (timeout) { signal(SIGALRM, SIG_DFL); // kill me alarm(timeout); } vbi = vbi_open(vbi_name, 0, channel, outfile, sid, ttpid); // open device if (not vbi) fatal_ioerror(vbi_name); vbi_add_handler(vbi, event, 0); // register event handler for (;;) fdset_select(fds, -1); // call scheduler /* never reached */ vbi_del_handler(vbi, event, 0); vbi_close(vbi); exit(0); }