alevt-date.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <sys/time.h>
  4. #include <time.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <signal.h>
  8. #include "os.h"
  9. #include "vt.h"
  10. #include "fdset.h"
  11. #include "vbi.h"
  12. #include "lang.h"
  13. #include "misc.h"
  14. char *fmt = "%a %b %d %H:%M:%S %Z %Y";
  15. int max_diff = 2*60*60; // default: 2 hours
  16. int set_time = 0;
  17. char *outfile = "";
  18. static char *channel;
  19. u_int16_t sid;
  20. static void chk_time(int t)
  21. {
  22. struct tm *tm;
  23. time_t sys_t;
  24. int dt;
  25. char buf[256];
  26. if (t < 0 || t > 235959 || t%100 > 59 || t/100%100 > 59)
  27. return;
  28. sys_t = time(0);
  29. tm = localtime(&sys_t);
  30. // Now convert to UTC seconds
  31. t = t/100/100 * 60*60 + t/100%100 * 60 + t%100;
  32. #ifdef BSD
  33. t -= tm->tm_gmtoff; // dst already included...
  34. #else
  35. t += timezone;
  36. if (tm->tm_isdst)
  37. t -= 60*60;
  38. #endif
  39. dt = t - sys_t % (24*60*60);
  40. if (dt <= -12*60*60)
  41. dt += 24*60*60;
  42. if (dt <= -max_diff || dt >= max_diff)
  43. fatal("time diff too big (%2d:%02d:%02d)", dt/60/60, abs(dt)/60%60, abs(dt)%60);
  44. sys_t += dt;
  45. if (set_time)
  46. {
  47. struct timeval tv[1];
  48. tv->tv_sec = sys_t;
  49. tv->tv_usec = 500000;
  50. if (settimeofday(tv, 0) == -1)
  51. ioerror("settimeofday");
  52. }
  53. if (*fmt)
  54. {
  55. tm = localtime(&sys_t);
  56. if (strftime(buf, sizeof(buf), fmt, tm))
  57. puts(buf);
  58. }
  59. exit(0);
  60. }
  61. static void event(void *_, struct vt_event *ev)
  62. {
  63. switch (ev->type)
  64. {
  65. /* vbi may generate EV_PAGE, EV_HEADER, EV_XPACKET */
  66. /* for event arguments see vt.h */
  67. case EV_HEADER: // a new title line (for running headers)
  68. {
  69. static int last_t = -1;
  70. u8 *s = ev->p1;
  71. int i, t = 1;
  72. if (ev->i2 & PG_OUTOFSEQ)
  73. break;
  74. for (i = 32; i < 40; ++i)
  75. if (s[i] >= '0' && s[i] <= '9')
  76. t = t * 10+ s[i] - '0';
  77. if (t >= 1000000 && t <= 1235959)
  78. if (t == last_t || t - last_t == 1)
  79. chk_time(t - 1000000);
  80. last_t = t;
  81. break;
  82. }
  83. }
  84. }
  85. static void usage(FILE *fp, int exit_val)
  86. {
  87. fprintf(fp, "usage: %s [options]\n", prgname);
  88. fprintf(fp,
  89. "\n"
  90. " Valid options:\t\tDefault:\n"
  91. " -d -delta <max_secs>\t7200 (2 hours)\n"
  92. " -f -format <fmtstr>\t\t%%c\n"
  93. " -h -help\n"
  94. " -s -set\t\t\toff\n"
  95. " -to -timeout <seconds>\t(none)\n"
  96. " -v -vbi <vbidev>\t\t/dev/vbi\n"
  97. " \t\t/dev/vbi0\n"
  98. " \t\t/dev/video0\n"
  99. " \t\t/dev/dvb/adapter0/demux0\n"
  100. );
  101. exit(exit_val);
  102. }
  103. static int option(int argc, char **argv, int *ind, char **arg)
  104. {
  105. static struct { char *nam, *altnam; int arg; } opts[] = {
  106. { "-delta", "-d", 1 },
  107. { "-format", "-f", 1 },
  108. { "-help", "-h", 0 },
  109. { "-set", "-s", 0 },
  110. { "-timeout", "-to", 1 },
  111. { "-vbi", "-v", 1 },
  112. };
  113. int i;
  114. if (*ind >= argc)
  115. return 0;
  116. *arg = argv[(*ind)++];
  117. for (i = 0; i < NELEM(opts); ++i)
  118. if (streq(*arg, opts[i].nam) || streq(*arg, opts[i].altnam))
  119. {
  120. if (opts[i].arg)
  121. if (*ind < argc)
  122. *arg = argv[(*ind)++];
  123. else
  124. fatal("option %s requires an argument", *arg);
  125. return i+1;
  126. }
  127. if (**arg == '-')
  128. {
  129. fatal("%s: invalid option", *arg);
  130. usage(stderr, 1);
  131. }
  132. return -1;
  133. }
  134. int main(int argc, char **argv)
  135. {
  136. char *vbi_name = NULL;
  137. int timeout = 0;
  138. struct vbi *vbi;
  139. int opt, ind;
  140. char *arg;
  141. int ttpid = -1;
  142. setprgname(argv[0]);
  143. ind = 1;
  144. while (opt = option(argc, argv, &ind, &arg))
  145. switch (opt)
  146. {
  147. case 1: // -delta
  148. max_diff = atoi(arg);
  149. if (max_diff < 1)
  150. fatal("-delta: illegal value '%s'", arg);
  151. if (max_diff > 12*60*60)
  152. {
  153. max_diff = 12*60*60;
  154. error("-delta: %d too big. Assuming %d", arg, max_diff);
  155. }
  156. break;
  157. case 2: // -format
  158. fmt = arg;
  159. break;
  160. case 3: // help
  161. usage(stdout, 0);
  162. break;
  163. case 4: // -set
  164. set_time = 1;
  165. break;
  166. case 5: // -timeout
  167. timeout = atoi(arg);
  168. if (timeout < 1 || timeout > 60*60)
  169. fatal("-timeout: illegal value '%s'", arg);
  170. break;
  171. case 6: // -vbi
  172. vbi_name = arg;
  173. break;
  174. case -1:
  175. usage(stderr, 1);
  176. break;
  177. }
  178. fdset_init(fds);
  179. if (timeout)
  180. {
  181. signal(SIGALRM, SIG_DFL); // kill me
  182. alarm(timeout);
  183. }
  184. vbi = vbi_open(vbi_name, 0, channel, outfile, sid, ttpid); // open device
  185. if (not vbi)
  186. fatal_ioerror(vbi_name);
  187. vbi_add_handler(vbi, event, 0); // register event handler
  188. for (;;)
  189. fdset_select(fds, -1); // call scheduler
  190. /* never reached */
  191. vbi_del_handler(vbi, event, 0);
  192. vbi_close(vbi);
  193. exit(0);
  194. }