/tools/tty.c

http://datacard.googlecode.com/ · C · 179 lines · 134 code · 23 blank · 22 comment · 25 complexity · 61167d76a8d9d333668019075d414b87 MD5 · raw file

  1. #include <stdio.h>
  2. #include <termios.h> /* struct termios tcgetattr() tcsetattr() */
  3. #include <fcntl.h> /* O_RDWR O_NOCTTY */
  4. #include <sys/stat.h> /* S_IRUSR | S_IRGRP | S_IROTH */
  5. #include <string.h> /* strrchr() */
  6. #include <limits.h> /* PATH_MAX */
  7. #include <stdlib.h> /* realpath() */
  8. #include <unistd.h> /* getpid() */
  9. #include <errno.h> /* errno */
  10. #include <signal.h> /* kill() */
  11. #/* return length of lockname */
  12. static int lock_build(const char * devname, char * buf, unsigned length)
  13. {
  14. const char * basename;
  15. char resolved_path[PATH_MAX];
  16. /* follow symlinks */
  17. if(realpath(devname, resolved_path) != NULL)
  18. devname = resolved_path;
  19. /*
  20. while(1)
  21. {
  22. len = readlink(devname, symlink, sizeof(symlink) - 1);
  23. if(len <= 0)
  24. break;
  25. symlink[len] = 0;
  26. if(symlink[0] == '/')
  27. devname = symlink;
  28. else
  29. {
  30. // TODO
  31. memmove()
  32. memcpy(symlink, devname);
  33. }
  34. }
  35. */
  36. basename = strrchr(devname, '/');
  37. if(basename)
  38. basename++;
  39. else
  40. basename = devname;
  41. /* TODO: use asterisk build settings for /var/lock */
  42. return snprintf(buf, length, "/var/lock/LOCK..%s", basename);
  43. }
  44. #/* return 0 on error */
  45. static int lock_create(const char * lockfile)
  46. {
  47. int fd;
  48. int len = 0;
  49. char pidb[21];
  50. fd = open(lockfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IRGRP | S_IROTH);
  51. if(fd >= 0)
  52. {
  53. len = snprintf(pidb, sizeof(pidb), "%d", getpid());
  54. len = write(fd, pidb, len);
  55. close(fd);
  56. }
  57. return len;
  58. }
  59. #/* return pid of owner, 0 if free */
  60. static int lock_try(const char * devname)
  61. {
  62. int fd;
  63. int len;
  64. int pid = 0;
  65. char name[256];
  66. char pidb[21];
  67. lock_build(devname, name, sizeof(name));
  68. /* FIXME: rise condition: some time between lock check and got lock */
  69. fd = open(name, O_RDONLY);
  70. if(fd >= 0)
  71. {
  72. len = read(fd, pidb, sizeof(pidb) - 1);
  73. if(len > 0)
  74. {
  75. pidb[len] = 0;
  76. len = strtol(pidb, NULL, 10);
  77. if(kill(len, 0) == 0)
  78. pid = len;
  79. }
  80. close(fd);
  81. }
  82. if(pid == 0)
  83. {
  84. unlink(name);
  85. lock_create(name);
  86. }
  87. return pid;
  88. }
  89. int opentty (const char* dev)
  90. {
  91. int pid;
  92. int fd;
  93. struct termios term_attr;
  94. fd = open (dev, O_RDWR | O_NOCTTY);
  95. if (fd < 0)
  96. {
  97. return -1;
  98. }
  99. if (tcgetattr (fd, &term_attr) != 0)
  100. {
  101. close(fd);
  102. return -1;
  103. }
  104. term_attr.c_cflag = B115200 | CS8 | CREAD | CRTSCTS;
  105. term_attr.c_iflag = 0;
  106. term_attr.c_oflag = 0;
  107. term_attr.c_lflag = 0;
  108. term_attr.c_cc[VMIN] = 1;
  109. term_attr.c_cc[VTIME] = 0;
  110. if (tcsetattr (fd, TCSAFLUSH, &term_attr) != 0)
  111. {
  112. }
  113. pid = lock_try(dev);
  114. if(pid != 0)
  115. {
  116. close(fd);
  117. return -1;
  118. }
  119. return fd;
  120. }
  121. #/* */
  122. void closetty(const char * dev, int fd)
  123. {
  124. char name[256];
  125. close(fd);
  126. /* remove lock */
  127. lock_build(dev, name, sizeof(name));
  128. unlink(name);
  129. }
  130. #/* */
  131. size_t write_all (int fd, const char* buf, size_t count)
  132. {
  133. ssize_t out_count;
  134. size_t total = 0;
  135. unsigned errs = 10;
  136. while (count > 0)
  137. {
  138. out_count = write (fd, buf, count);
  139. if (out_count <= 0)
  140. {
  141. if(errno == EINTR || errno == EAGAIN)
  142. {
  143. errs--;
  144. if(errs != 0)
  145. continue;
  146. }
  147. break;
  148. }
  149. // fprintf(stdout, "%*s", out_count, buf);
  150. errs = 10;
  151. count -= out_count;
  152. buf += out_count;
  153. total += out_count;
  154. }
  155. return total;
  156. }