binreplay.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * Stuff the contents of a specified file into a specified tty.
  3. *
  4. * This file is Copyright 2010 by the GPSD project
  5. * SPDX-License-Identifier: BSD-2-clause
  6. */
  7. #include <err.h>
  8. #include <errno.h>
  9. #include <fcntl.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <sys/mman.h>
  14. #include <sys/stat.h>
  15. #include <sys/types.h>
  16. #include <termios.h>
  17. #include <time.h> /* For nanosleep() */
  18. #include <unistd.h>
  19. #ifndef __GLIBC__
  20. #include <util.h>
  21. #else
  22. #include <pty.h>
  23. #endif
  24. #define WRLEN 64
  25. void spinner(int);
  26. void usage(void);
  27. int main( int argc, char **argv){
  28. struct stat sb;
  29. struct termios term;
  30. char *buf, tn[32];
  31. int ifd, ofd, sfd;
  32. int dflag = 0, c, sleeptime, len, speed = 0;
  33. struct timespec delay;
  34. while((c = getopt(argc, argv, "d:r:s:")) != -1) {
  35. switch(c){
  36. case 'd':
  37. dflag = 1;
  38. strncpy(tn, optarg, sizeof(tn)-1);
  39. break;
  40. case 's':
  41. speed = atoi(optarg);
  42. switch (speed) {
  43. case 230400:
  44. case 115200:
  45. case 57600:
  46. case 38400:
  47. case 28800:
  48. case 19200:
  49. case 14400:
  50. case 9600:
  51. case 4800:
  52. break;
  53. default:
  54. fprintf(stderr, "invalid port speed: %d\n", speed);
  55. return 1;
  56. }
  57. break;
  58. default:
  59. usage();
  60. }
  61. }
  62. argc -= optind;
  63. argv += optind;
  64. if (argc != 1)
  65. usage();
  66. if (0 == speed)
  67. speed = 4800;
  68. printf("opening %s\n", argv[0]);
  69. if ((ifd = open(argv[0], O_RDONLY, 0444)) == -1)
  70. err(1, "open");
  71. if (fstat(ifd, &sb) == -1)
  72. err(1, "fstat");
  73. if ((buf = mmap(0, sb.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, ifd, 0)) == MAP_FAILED)
  74. err(1, "mmap");
  75. if (dflag){
  76. if ((ofd = open(tn, O_RDWR|O_NOCTTY, 0644)) == -1)
  77. err(1, "open");
  78. tcgetattr(ofd, &term);
  79. cfmakeraw(&term);
  80. cfsetispeed(&term, speed);
  81. cfsetospeed(&term, speed);
  82. #if 0
  83. term.c_cflag &= ~(PARENB | PARODD | CRTSCTS);
  84. term.c_cflag |= CREAD | CLOCAL;
  85. term.c_iflag = term.c_oflag = term.c_lflag = (tcflag_t) 0;
  86. #endif
  87. tcflush(ofd, TCIOFLUSH);
  88. tcsetattr(ofd, TCSANOW, &term);
  89. tcflush(ofd, TCIOFLUSH);
  90. } else {
  91. cfmakeraw(&term);
  92. cfsetospeed(&term, speed);
  93. cfsetispeed(&term, speed);
  94. if (openpty(&ofd, &sfd, tn, &term, NULL) == -1)
  95. err(1, "openpty");
  96. tcsetattr(ofd, TCSANOW, &term);
  97. tcsetattr(sfd, TCSANOW, &term);
  98. }
  99. sleeptime = 1000000 / (speed / (WRLEN * 10));
  100. printf("configured %s for %dbps - write delay %dus\n", tn, speed, sleeptime);
  101. for(len = 0; len < sb.st_size; len += WRLEN ){
  102. write(ofd, buf+len, WRLEN );
  103. // tcdrain(ofd);
  104. if (0 == dflag){
  105. tcflush(ofd, TCIFLUSH);
  106. // tcdrain(sfd);
  107. tcflush(sfd, TCIFLUSH);
  108. }
  109. spinner( len );
  110. /* wait sleeptime Sec */
  111. delay.tv_sec = (time_t)(sleeptime / 1000000000L);
  112. delay.tv_nsec = sleeptime % 1000000000L;
  113. nanosleep(&delay, NULL);
  114. }
  115. munmap(buf, sb.st_size);
  116. close(ifd);
  117. close(ofd);
  118. fprintf(stderr, "\010\010\010\010\010\010\010\010\010\010\010\010\n");
  119. return 0;
  120. }
  121. void spinner(int n){
  122. char *s = "|/-\\";
  123. if (n % (WRLEN * 4))
  124. return;
  125. n /= (WRLEN * 4);
  126. fprintf(stderr, "\010\010\010\010\010\010\010\010\010\010\010\010\010");
  127. fprintf(stderr, "%c %d", s[n%4], n);
  128. fflush(stderr);
  129. }
  130. void usage(void){
  131. fprintf(stderr, "usage: binreplay [-d <device>] [-s <port_speed>] <file>\n");
  132. exit(1);
  133. }