From 9b6b37f24d84bee56b98e06d91f20092810f59bc Mon Sep 17 00:00:00 2001 From: hinus Date: Tue, 17 Aug 2021 10:33:57 +0800 Subject: [PATCH] Title: Page up and donw on console Issue: https://gitee.com/hinus/linux_kernel_011/issues/I40CGQ https://gitee.com/hinus/linux_kernel_011/issues/I45OEJ Description: Write control sequence to console and 'sys_unlink' LTT: vi --- fs/namei.c | 61 ++++++- kernel/chr_drv/console.c | 336 ++++++++++++++++++++++++++++++++++++++- kernel/main.c | 5 +- 3 files changed, 394 insertions(+), 8 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 93f1c2d..8d4976b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -578,7 +578,66 @@ int sys_mknod(const char * filename, int mode, int dev) { } int sys_unlink(const char * name) { - printk("unimplement sys call unlink\n"); + const char * basename; + int namelen; + struct m_inode * dir, * inode; + struct buffer_head * bh; + struct dir_entry * de; + + if (!(dir = dir_namei(name,&namelen,&basename, NULL))) + return -ENOENT; + + if (!namelen) { + iput(dir); + return -ENOENT; + } + + if (!permission(dir,MAY_WRITE)) { + iput(dir); + return -EPERM; + } + + bh = find_entry(&dir,basename,namelen,&de); + if (!bh) { + iput(dir); + return -ENOENT; + } + + if (!(inode = iget(dir->i_dev, de->inode))) { + iput(dir); + brelse(bh); + return -ENOENT; + } + + if ((dir->i_mode & S_ISVTX) && !suser() && + current->euid != inode->i_uid && + current->euid != dir->i_uid) { + iput(dir); + iput(inode); + brelse(bh); + return -EPERM; + } + + if (S_ISDIR(inode->i_mode)) { + iput(inode); + iput(dir); + brelse(bh); + return -EPERM; + } + + if (!inode->i_nlinks) { + printk("Deleting nonexistent file (%04x:%d), %d\n", + inode->i_dev,inode->i_num,inode->i_nlinks); + inode->i_nlinks=1; + } + de->inode = 0; + bh->b_dirt = 1; + brelse(bh); + inode->i_nlinks--; + inode->i_dirt = 1; + inode->i_ctime = CURRENT_TIME; + iput(inode); + iput(dir); return 0; } diff --git a/kernel/chr_drv/console.c b/kernel/chr_drv/console.c index c67c45a..319b7ac 100644 --- a/kernel/chr_drv/console.c +++ b/kernel/chr_drv/console.c @@ -19,6 +19,8 @@ #define VIDEO_TYPE_EGAM 0x20 /* EGA/VGA in Monochrome Mode */ #define VIDEO_TYPE_EGAC 0x21 /* EGA/VGA in Color Mode */ +#define NPAR 16 + extern void keyboard_interrupt(void); static unsigned char video_type; /* Type of display being used */ @@ -38,8 +40,12 @@ static unsigned long pos; static unsigned long x, y; static unsigned long state = 0; static unsigned long top, bottom; +static unsigned long npar, par[NPAR]; +static unsigned long ques = 0; static unsigned long attr = 0x07; +#define RESPONSE "\033[?1;2c" + static inline void gotoxy(int new_x,unsigned int new_y) { if (new_x > video_num_columns || new_y >= video_num_lines) return; @@ -67,6 +73,18 @@ static inline void set_cursor() { sti(); } +static void respond(struct tty_struct * tty) { + char * p = RESPONSE; + + cli(); + while (*p) { + PUTCH(*p,tty->read_q); + p++; + } + sti(); + copy_to_cooked(tty); +} + static void scrdown() { if (bottom <= top) return; @@ -174,6 +192,175 @@ static void del() { } } +static void csi_J(int vpar) { + long count, start; + + switch (vpar) { + case 0: + count = (scr_end-pos)>>1; + start = pos; + break; + case 1: + count = (pos-origin)>>1; + start = origin; + break; + case 2: + count = video_num_columns * video_num_lines; + start = origin; + break; + default: + return; + } + + __asm__("cld\n\t" + "rep\n\t" + "stosw\n\t" + ::"c" (count), + "D" (start),"a" (video_erase_char) + :); +} + +static void csi_K(int vpar) { + long count, start; + + switch (vpar) { + case 0: + if (x>=video_num_columns) + return; + count = video_num_columns-x; + start = pos; + break; + case 1: + start = pos - (x<<1); + count = (x=video_num_columns) + return; + i = x; + while (++i < video_num_columns) { + *p = *(p+1); + p++; + } + *p = video_erase_char; +} + +static void delete_line() { + int oldtop,oldbottom; + + oldtop = top; + oldbottom = bottom; + top = y; + bottom = video_num_lines; + scrup(); + top = oldtop; + bottom = oldbottom; +} + +static void insert_char() { + int i=x; + unsigned short tmp, old = video_erase_char; + unsigned short * p = (unsigned short *) pos; + + while (i++ video_num_columns) + nr = video_num_columns; + else if (!nr) + nr = 1; + while (nr--) + insert_char(); +} + +static void csi_L(unsigned int nr) { + if (nr > video_num_lines) + nr = video_num_lines; + else if (!nr) + nr = 1; + while (nr--) + insert_line(); +} + +static void csi_P(unsigned int nr) { + if (nr > video_num_columns) + nr = video_num_columns; + else if (!nr) + nr = 1; + while (nr--) + delete_char(); +} + +static void csi_M(unsigned int nr) { + if (nr > video_num_lines) + nr = video_num_lines; + else if (!nr) + nr=1; + while (nr--) + delete_line(); +} + +static int saved_x = 0; +static int saved_y = 0; + +static void save_cur() { + saved_x=x; + saved_y=y; +} + +static void restore_cur() { + gotoxy(saved_x, saved_y); +} + void con_init() { register unsigned char a; char * display_desc = "????"; @@ -239,6 +426,9 @@ void con_init() { outb_p(a,0x61); } +enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, + ESsetterm, ESsetgraph }; + void con_write(struct tty_struct* tty) { int nr; char c; @@ -268,7 +458,7 @@ void con_write(struct tty_struct* tty) { lf(); else if (c == 13) cr(); - else if (c == 127) { + else if (c == ERASE_CHAR(tty)) { del(); } else if (c == 8) { @@ -277,13 +467,147 @@ void con_write(struct tty_struct* tty) { pos -= 2; } } + else if (c == 9) { + c=8-(x&7); + x += c; + pos += c<<1; + if (x > video_num_columns) { + x -= video_num_columns; + pos -= video_size_row; + lf(); + } + c = 9; + } break; - case 1: - if (c == '[') { - state = 2; + case ESesc: + state = ESnormal; + switch (c) { + case '[': + state = ESsquare; + break; + case 'E': + gotoxy(0, y+1); + break; + case 'M': + ri(); + break; + case 'D': + lf(); + break; + case 'Z': + respond(tty); + break; + case '7': + save_cur(); + break; + case '8': + restore_cur(); + break; + } + break; + case ESsquare: + for(npar=0;npar='0' && c<='9') { + par[npar]=10*par[npar]+c-'0'; + break; + } + else + state=ESgotpars; + case ESgotpars: + state = ESnormal; + if (ques) { + ques = 0; + break; } - else if (c == 'M') { - ri(); + switch(c) { + case 'G': case '`': + if (par[0]) par[0]--; + gotoxy(par[0], y); + break; + case 'A': + if (!par[0]) par[0]++; + gotoxy(x, y - par[0]); + break; + case 'B': case 'e': + if (!par[0]) par[0]++; + gotoxy(x, y + par[0]); + break; + case 'C': case 'a': + if (!par[0]) par[0]++; + gotoxy(x + par[0], y); + break; + case 'D': + if (!par[0]) par[0]++; + gotoxy(x - par[0], y - 1); + break; + case 'E': + if (!par[0]) par[0]++; + gotoxy(0, y + par[0]); + break; + case 'F': + if (!par[0]) par[0]++; + gotoxy(0, y - par[0]); + break; + case 'd': + if (!par[0]) par[0]--; + gotoxy(x, par[0]); + break; + case 'H': case 'f': + if (par[0]) par[0]--; + if (par[1]) par[1]--; + gotoxy(par[1],par[0]); + break; + case 'J': + csi_J(par[0]); + break; + case 'K': + csi_K(par[0]); + break; + case 'L': + csi_L(par[0]); + break; + case 'M': + csi_M(par[0]); + break; + case 'P': + csi_P(par[0]); + break; + case '@': + csi_at(par[0]); + break; + case 'm': + csi_m(par[0]); + break; + case 'r': + if (par[0]) par[0]--; + if (!par[1]) par[1] = video_num_lines; + if (par[0] < par[1] && + par[1] <= video_num_lines) { + top=par[0]; + bottom=par[1]; + } + break; + case 's': + save_cur(); + break; + case 'u': + restore_cur(); + break; } break; } diff --git a/kernel/main.c b/kernel/main.c index 32f7e92..0725fa1 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -146,7 +146,7 @@ static void easy_shell() { char a[10]; while (1) { i = read(0, a, 9); - a[i - 1] = 0; + a[--i] = 0; if (strcmp(a, "mk") == 0) { mkdir("/hinusDocs", 0); @@ -163,6 +163,9 @@ static void easy_shell() { else if (strcmp(a, "sy") == 0) { sync(); } + else { + write(1, a, i); + } } } -- Gitee