tty_log.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
  3. * geoffrey hing <ghing@net.ohio-state.edu>
  4. * Licensed under the GPL
  5. */
  6. #include <errno.h>
  7. #include <string.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <unistd.h>
  11. #include <sys/time.h>
  12. #include "init.h"
  13. #include "user.h"
  14. #include "os.h"
  15. #define TTY_LOG_DIR "./"
  16. /* Set early in boot and then unchanged */
  17. static char *tty_log_dir = TTY_LOG_DIR;
  18. static int tty_log_fd = -1;
  19. #define TTY_LOG_OPEN 1
  20. #define TTY_LOG_CLOSE 2
  21. #define TTY_LOG_WRITE 3
  22. #define TTY_LOG_EXEC 4
  23. #define TTY_READ 1
  24. #define TTY_WRITE 2
  25. struct tty_log_buf {
  26. int what;
  27. unsigned long tty;
  28. int len;
  29. int direction;
  30. unsigned long sec;
  31. unsigned long usec;
  32. };
  33. int open_tty_log(void *tty, void *current_tty)
  34. {
  35. struct timeval tv;
  36. struct tty_log_buf data;
  37. char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
  38. int fd;
  39. gettimeofday(&tv, NULL);
  40. if(tty_log_fd != -1){
  41. data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN,
  42. .tty = (unsigned long) tty,
  43. .len = sizeof(current_tty),
  44. .direction = 0,
  45. .sec = tv.tv_sec,
  46. .usec = tv.tv_usec } );
  47. write(tty_log_fd, &data, sizeof(data));
  48. write(tty_log_fd, &current_tty, data.len);
  49. return tty_log_fd;
  50. }
  51. sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
  52. (unsigned int) tv.tv_usec);
  53. fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))),
  54. 0644);
  55. if(fd < 0){
  56. printk("open_tty_log : couldn't open '%s', errno = %d\n",
  57. buf, -fd);
  58. }
  59. return fd;
  60. }
  61. void close_tty_log(int fd, void *tty)
  62. {
  63. struct tty_log_buf data;
  64. struct timeval tv;
  65. if(tty_log_fd != -1){
  66. gettimeofday(&tv, NULL);
  67. data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE,
  68. .tty = (unsigned long) tty,
  69. .len = 0,
  70. .direction = 0,
  71. .sec = tv.tv_sec,
  72. .usec = tv.tv_usec } );
  73. write(tty_log_fd, &data, sizeof(data));
  74. return;
  75. }
  76. os_close_file(fd);
  77. }
  78. static int log_chunk(int fd, const char *buf, int len)
  79. {
  80. int total = 0, try, missed, n;
  81. char chunk[64];
  82. while(len > 0){
  83. try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
  84. missed = copy_from_user_proc(chunk, (char *) buf, try);
  85. try -= missed;
  86. n = write(fd, chunk, try);
  87. if(n != try) {
  88. if(n < 0)
  89. return -errno;
  90. return -EIO;
  91. }
  92. if(missed != 0)
  93. return -EFAULT;
  94. len -= try;
  95. total += try;
  96. buf += try;
  97. }
  98. return total;
  99. }
  100. int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
  101. {
  102. struct timeval tv;
  103. struct tty_log_buf data;
  104. int direction;
  105. if(fd == tty_log_fd){
  106. gettimeofday(&tv, NULL);
  107. direction = is_read ? TTY_READ : TTY_WRITE;
  108. data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE,
  109. .tty = (unsigned long) tty,
  110. .len = len,
  111. .direction = direction,
  112. .sec = tv.tv_sec,
  113. .usec = tv.tv_usec } );
  114. write(tty_log_fd, &data, sizeof(data));
  115. }
  116. return log_chunk(fd, buf, len);
  117. }
  118. void log_exec(char **argv, void *tty)
  119. {
  120. struct timeval tv;
  121. struct tty_log_buf data;
  122. char **ptr,*arg;
  123. int len;
  124. if(tty_log_fd == -1) return;
  125. gettimeofday(&tv, NULL);
  126. len = 0;
  127. for(ptr = argv; ; ptr++){
  128. if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
  129. return;
  130. if(arg == NULL) break;
  131. len += strlen_user_proc(arg);
  132. }
  133. data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC,
  134. .tty = (unsigned long) tty,
  135. .len = len,
  136. .direction = 0,
  137. .sec = tv.tv_sec,
  138. .usec = tv.tv_usec } );
  139. write(tty_log_fd, &data, sizeof(data));
  140. for(ptr = argv; ; ptr++){
  141. if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
  142. return;
  143. if(arg == NULL) break;
  144. log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
  145. }
  146. }
  147. extern void register_tty_logger(int (*opener)(void *, void *),
  148. int (*writer)(int, const char *, int,
  149. void *, int),
  150. void (*closer)(int, void *));
  151. static int register_logger(void)
  152. {
  153. register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
  154. return 0;
  155. }
  156. __uml_initcall(register_logger);
  157. static int __init set_tty_log_dir(char *name, int *add)
  158. {
  159. tty_log_dir = name;
  160. return 0;
  161. }
  162. __uml_setup("tty_log_dir=", set_tty_log_dir,
  163. "tty_log_dir=<directory>\n"
  164. " This is used to specify the directory where the logs of all pty\n"
  165. " data from this UML machine will be written.\n\n"
  166. );
  167. static int __init set_tty_log_fd(char *name, int *add)
  168. {
  169. char *end;
  170. tty_log_fd = strtoul(name, &end, 0);
  171. if((*end != '\0') || (end == name)){
  172. printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
  173. tty_log_fd = -1;
  174. }
  175. *add = 0;
  176. return 0;
  177. }
  178. __uml_setup("tty_log_fd=", set_tty_log_fd,
  179. "tty_log_fd=<fd>\n"
  180. " This is used to specify a preconfigured file descriptor to which all\n"
  181. " tty data will be written. Preconfigure the descriptor with something\n"
  182. " like '10>tty_log tty_log_fd=10'.\n\n"
  183. );