123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
- * geoffrey hing <ghing@net.ohio-state.edu>
- * Licensed under the GPL
- */
- #include <errno.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include "init.h"
- #include "user.h"
- #include "kern_util.h"
- #include "os.h"
- #define TTY_LOG_DIR "./"
- /* Set early in boot and then unchanged */
- static char *tty_log_dir = TTY_LOG_DIR;
- static int tty_log_fd = -1;
- #define TTY_LOG_OPEN 1
- #define TTY_LOG_CLOSE 2
- #define TTY_LOG_WRITE 3
- #define TTY_LOG_EXEC 4
- #define TTY_READ 1
- #define TTY_WRITE 2
- struct tty_log_buf {
- int what;
- unsigned long tty;
- int len;
- int direction;
- unsigned long sec;
- unsigned long usec;
- };
- int open_tty_log(void *tty, void *current_tty)
- {
- struct timeval tv;
- struct tty_log_buf data;
- char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
- int fd;
- gettimeofday(&tv, NULL);
- if(tty_log_fd != -1){
- data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN,
- .tty = (unsigned long) tty,
- .len = sizeof(current_tty),
- .direction = 0,
- .sec = tv.tv_sec,
- .usec = tv.tv_usec } );
- os_write_file(tty_log_fd, &data, sizeof(data));
- os_write_file(tty_log_fd, ¤t_tty, data.len);
- return(tty_log_fd);
- }
- sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
- (unsigned int) tv.tv_usec);
- fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))),
- 0644);
- if(fd < 0){
- printk("open_tty_log : couldn't open '%s', errno = %d\n",
- buf, -fd);
- }
- return(fd);
- }
- void close_tty_log(int fd, void *tty)
- {
- struct tty_log_buf data;
- struct timeval tv;
- if(tty_log_fd != -1){
- gettimeofday(&tv, NULL);
- data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE,
- .tty = (unsigned long) tty,
- .len = 0,
- .direction = 0,
- .sec = tv.tv_sec,
- .usec = tv.tv_usec } );
- os_write_file(tty_log_fd, &data, sizeof(data));
- return;
- }
- os_close_file(fd);
- }
- static int log_chunk(int fd, const char *buf, int len)
- {
- int total = 0, try, missed, n;
- char chunk[64];
- while(len > 0){
- try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
- missed = copy_from_user_proc(chunk, (char *) buf, try);
- try -= missed;
- n = os_write_file(fd, chunk, try);
- if(n != try) {
- if(n < 0)
- return(n);
- return(-EIO);
- }
- if(missed != 0)
- return(-EFAULT);
- len -= try;
- total += try;
- buf += try;
- }
- return(total);
- }
- int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
- {
- struct timeval tv;
- struct tty_log_buf data;
- int direction;
- if(fd == tty_log_fd){
- gettimeofday(&tv, NULL);
- direction = is_read ? TTY_READ : TTY_WRITE;
- data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE,
- .tty = (unsigned long) tty,
- .len = len,
- .direction = direction,
- .sec = tv.tv_sec,
- .usec = tv.tv_usec } );
- os_write_file(tty_log_fd, &data, sizeof(data));
- }
- return(log_chunk(fd, buf, len));
- }
- void log_exec(char **argv, void *tty)
- {
- struct timeval tv;
- struct tty_log_buf data;
- char **ptr,*arg;
- int len;
- if(tty_log_fd == -1) return;
- gettimeofday(&tv, NULL);
- len = 0;
- for(ptr = argv; ; ptr++){
- if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
- return;
- if(arg == NULL) break;
- len += strlen_user_proc(arg);
- }
- data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC,
- .tty = (unsigned long) tty,
- .len = len,
- .direction = 0,
- .sec = tv.tv_sec,
- .usec = tv.tv_usec } );
- os_write_file(tty_log_fd, &data, sizeof(data));
- for(ptr = argv; ; ptr++){
- if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
- return;
- if(arg == NULL) break;
- log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
- }
- }
- extern void register_tty_logger(int (*opener)(void *, void *),
- int (*writer)(int, const char *, int,
- void *, int),
- void (*closer)(int, void *));
- static int register_logger(void)
- {
- register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
- return(0);
- }
- __uml_initcall(register_logger);
- static int __init set_tty_log_dir(char *name, int *add)
- {
- tty_log_dir = name;
- return 0;
- }
- __uml_setup("tty_log_dir=", set_tty_log_dir,
- "tty_log_dir=<directory>\n"
- " This is used to specify the directory where the logs of all pty\n"
- " data from this UML machine will be written.\n\n"
- );
- static int __init set_tty_log_fd(char *name, int *add)
- {
- char *end;
- tty_log_fd = strtoul(name, &end, 0);
- if((*end != '\0') || (end == name)){
- printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
- tty_log_fd = -1;
- }
- *add = 0;
- return 0;
- }
- __uml_setup("tty_log_fd=", set_tty_log_fd,
- "tty_log_fd=<fd>\n"
- " This is used to specify a preconfigured file descriptor to which all\n"
- " tty data will be written. Preconfigure the descriptor with something\n"
- " like '10>tty_log tty_log_fd=10'.\n\n"
- );
- /*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
|