tty_log.c 5.2 KB

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