📄 nxterm.c
字号:
break; default: /* any printable char */ sadd(c); if (++curx >= col) { sflush(); if (!wrap) { curx = col-1; } else { curx = 0; if (++cury >= row) { vscroll(1); } } } break; }}void printc(unsigned char c){ switch(escstate) { case 0: esc0(c); break; case 1: sflush(); esc1(c); break; case 2: sflush(); esc2(c); break; case 3: sflush(); esc3(c); break; case 4: sflush(); esc4(c); break; case 5: sflush(); esc5(c); break; default: escstate = 0; break; }}void init(){ curx = savx = 0; cury = savy = 0; wrap = 1; curon = 1; curvis = 0; escstate = 0;}/* * general code... */voidterm(void){ long in, l; GR_EVENT wevent; GR_EVENT_KEYSTROKE *kp; unsigned char buf[LARGEBUFFER]; GrRegisterInput(pipeh); while (42) { if (havefocus) draw_cursor(); GrGetNextEvent(&wevent); switch(wevent.type) { case GR_EVENT_TYPE_CLOSE_REQ: GrClose(); exit(0); break; case GR_EVENT_TYPE_KEY_DOWN: kp=(GR_EVENT_KEYSTROKE *)&wevent; /* toss all special keys*/ if (kp->ch & MWKEY_NONASCII_MASK) break; *buf = kp->ch & 0xff; write(pipeh, buf,1); break; case GR_EVENT_TYPE_FOCUS_IN: havefocus = GR_TRUE; break; case GR_EVENT_TYPE_FOCUS_OUT: havefocus = GR_FALSE; hide_cursor(); break; case GR_EVENT_TYPE_UPDATE: /* * if we get temporarily unmapped (moved), * set cursor state off. */ if (wevent.update.utype == GR_UPDATE_UNMAPTEMP) curvis = 0; break; case GR_EVENT_TYPE_FDINPUT: hide_cursor(); while ((in = read(pipeh, buf, sizeof(buf))) > 0) { for (l=0; l<in; l++) { printc(buf[l]); if (buf[l] == '\n') printc('\r'); } sflush(); } break; } }}void usage(char *s){ if (s) fprintf(stderr, "error: %s\n", s); printf("usage: nxterm [-b] [-d] [-f <font family>] [-s <font size>]\n"); printf(" [-g <geometry>] [-v] [-c] [-h] [program {args}]\n"); exit(0);}void *mysignal(int signum, void *handler){ struct sigaction sa, so; sa.sa_handler = handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sigaction(signum, &sa, &so); return so.sa_handler;}/* * guess what... :) */int main(int argc, char **argv){ GR_BITMAP bitmap1fg[7]; /* mouse cursor */ GR_BITMAP bitmap1bg[7]; GR_WM_PROPERTIES props; short xp, yp, fsize; char *family, *shell = NULL, *cptr, *geometry = NULL; struct passwd *pw; char buf[80]; short uid; char thesh[128];#ifdef __FreeBSD__ char *ptr;#endif#ifdef SIGTTOU /* just in case we're started in the background */ signal(SIGTTOU, SIG_IGN);#endif /* who am I? */ if (!(pw = getpwuid((uid = getuid())))) { fprintf(stderr, "error: wterm can't determine determine your login name\n"); exit(-1); } if (GrOpen() < 0) { fprintf(stderr, "cannot open graphics\n"); exit(1); } GrGetScreenInfo(&si); /* * scan arguments... */ console = 0; argv++; while (*argv && **argv=='-') switch (*(*argv+1)) { case 'b': cblink = 1; argv++; break; case 'c': console = 1; argv++; break; case 'd': debug = 1; argv++; break; case 'f': if (*++argv) { family = *argv++; } else { usage("-f option requires an argument"); } break; case 's': if (*++argv) { fsize = atoi(*argv++); } else { usage("-s option requires an argument"); } break; case 'g': if (*++argv) { geometry = *argv++; } else { usage("-g option requires an argument"); } break; case 'h': /* this will never return */ usage(""); case 'v': visualbell = 1; argv++; break; default: usage("unknown option"); } /* * now *argv either points to a program to start or is zero */ if (*argv) { shell = *argv; } if (!shell) { shell = getenv("SHELL="); } if (!shell) { shell = pw->pw_shell; } if (!shell) { shell = "/bin/sh"; } if (!*argv) { /* * the '-' makes the shell think it is a login shell, * we leave argv[0] alone if it isn`t a shell (ie. * the user specified the program to run as an argument * to wterm. */ cptr = strrchr(shell, '/'); sprintf (thesh, "-%s", cptr ? cptr + 1 : shell); *--argv = thesh; } col = 80; row = 25; xp = 0; yp = 0; if (geometry) { if (col < 1) { col = 80; } if (row < 1) { row = 25; } if (col > 0x7f) colmask = 0xffff; if (row > 0x7f) rowmask = 0xffff; } regFont=GrCreateFont(GR_FONT_SYSTEM_FIXED, 0, NULL); /*regFont=GrCreateFont(GR_FONT_OEM_FIXED, 0, NULL);*/ /*boldFont=GrCreateFont(GR_FONT_SYSTEM_FIXED, 0, NULL);*/ GrGetFontInfo(regFont, &fi); winw=col*fi.maxwidth; winh=row*fi.height; w1 = GrNewWindow(GR_ROOT_WINDOW_ID, 10,10,winw, winh,0,BLACK,LTBLUE); props.flags = GR_WM_FLAGS_TITLE; props.title = TITLE; GrSetWMProperties(w1, &props); GrSelectEvents(w1, GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_FOCUS_IN | GR_EVENT_MASK_FOCUS_OUT | GR_EVENT_MASK_UPDATE | GR_EVENT_MASK_CLOSE_REQ); GrMapWindow(w1); gc1 = GrNewGC(); GrSetGCFont(gc1, regFont);#define _ ((unsigned) 0) /* off bits */#define X ((unsigned) 1) /* on bits */#define MASK(a,b,c,d,e,f,g) \ (((((((((((((a * 2) + b) * 2) + c) * 2) + d) * 2) \ + e) * 2) + f) * 2) + g) << 9) bitmap1fg[0] = MASK(_,_,X,_,X,_,_); bitmap1fg[1] = MASK(_,_,_,X,_,_,_); bitmap1fg[2] = MASK(_,_,_,X,_,_,_); bitmap1fg[3] = MASK(_,_,_,X,_,_,_); bitmap1fg[4] = MASK(_,_,_,X,_,_,_); bitmap1fg[5] = MASK(_,_,_,X,_,_,_); bitmap1fg[6] = MASK(_,_,X,_,X,_,_); bitmap1bg[0] = MASK(_,X,X,X,X,X,_); bitmap1bg[1] = MASK(_,_,X,X,X,_,_); bitmap1bg[2] = MASK(_,_,X,X,X,_,_); bitmap1bg[3] = MASK(_,_,X,X,X,_,_); bitmap1bg[4] = MASK(_,_,X,X,X,_,_); bitmap1bg[5] = MASK(_,_,X,X,X,_,_); bitmap1bg[6] = MASK(_,X,X,X,X,X,_); GrSetCursor(w1, 7, 7, 3, 3, GREEN, BLACK, bitmap1fg, bitmap1bg); GrSetGCForeground(gc1, GREEN); GrSetGCBackground(gc1, BLACK); GrGetWindowInfo(w1,&wi); GrGetGCInfo(gc1,&gi); sprintf(buf, "wterm: %s", shell); /* * what kind of terminal do we want to emulate? */#ifdef __FreeBSD__ putenv ("TERM=wterm");#else putenv ("TERM=vt52");#endif /* * this one should enable us to get rid of an /etc/termcap entry for * both curses and ncurses, hopefully... */ if (termcap_string) { sprintf (termcap_string + strlen (termcap_string), "li#%d:co#%d:", row, col); putenv (termcap_string); } /* in case program absolutely needs terminfo entry, these 'should' * transmit the screen size of correctly (at least xterm sets these * and everything seems to work correctly...). Unlike putenv(), * setenv() allocates also the given string not just a pointer. */ sprintf (buf, "%d", col); setenv ("COLUMNS", buf, 1); sprintf (buf, "%d", row); setenv ("LINES", buf, 1); init(); /* * create a pty */#ifdef __FreeBSD__ winsz.ws_col = col; winsz.ws_row = row; if ((pid = forkpty(&pipeh, pty, NULL, &winsz)) < 0) { fprintf(stderr,"wterm: can't create pty\r\n"); perror("wterm"); sleep(2); GrKillWindow(w1); exit(-1); } if ((ptr = rindex(pty, '/'))) { strcpy(pty, ptr + 1); } if (!pid) { int i; for (i = getdtablesize(); --i >= 3; ) close (i); /* * SIG_IGN are not reset on exec() */ for (i = NSIG; --i >= 0; ) signal (i, SIG_DFL); /* caution: start shell with correct user id! */ seteuid(getuid()); setegid(getgid()); /* this shall not return */ execvp(shell, argv); /* oops? */ fprintf(stderr,"wterm: can't start shell\r\n"); sleep(3); GrKillWindow(w1); _exit(-1); }#else pipeh = term_init();#endif/* _write_utmp(pty, pw->pw_name, "", time(0)); */#if 0 /* catch some signals */ mysignal(SIGTERM, sigquit); mysignal(SIGHUP, sigquit); mysignal(SIGINT, SIG_IGN); mysignal(SIGQUIT, sigquit); mysignal(SIGPIPE, sigpipe); mysignal(SIGCHLD, sigchld);#endif /* prepare to catch console output */ if (console) { /* for any OS chr$(7) might cause endless loops if * catched from console */ visualbell = 1; console = 0; /* data will come to normal pipe handle */ ioctl(pipeh, TIOCCONS, 0); } term(); return 0;}#if ELKSchar * nargv[2] = {"/bin/sash", NULL};#else#if DOS_DJGPPchar * nargv[2] = {"bash", NULL};#elsechar * nargv[2] = {"/bin/sh", NULL};#endif#endifvoid sigchild(int signo){ GrClose(); exit(0);}int term_init(){ int tfd; int n = 0; pid_t pid; char pty_name[12];again: sprintf(pty_name, "/dev/ptyp%d", n); if ((tfd = open(pty_name, O_RDWR | O_NONBLOCK)) < 0) { if ((errno == EBUSY || errno == EIO) && n < 10) { n++; goto again; } fprintf(stderr, "Can't create pty %s\n", pty_name); return -1; } signal(SIGCHLD, sigchild); signal(SIGINT, sigchild); if ((pid = fork()) == -1) { fprintf(stderr, "No processes\n"); return -1; } if (!pid) { close(STDIN_FILENO); close(STDOUT_FILENO); close(tfd); setsid(); pty_name[5] = 't'; if ((tfd = open(pty_name, O_RDWR)) < 0) { fprintf(stderr, "Child: Can't open pty %s\n", pty_name); exit(1); } close(STDERR_FILENO); dup2(tfd, STDIN_FILENO); dup2(tfd, STDOUT_FILENO); dup2(tfd, STDERR_FILENO); execv(nargv[0], nargv); exit(1); } return tfd;}#if 0void _write_utmp(char *line, char *user, char *host, int time){ int fh, offset, isEmpty, isLine; struct utmp ut; if ((fh = open("/etc/utmp", O_RDWR)) < 0) { return; } /* first of all try to find an entry with the same line */ offset = 0; isEmpty = -1; isLine = -1; while ((isLine < 0) && (read(fh, &ut, sizeof(ut)) == sizeof(ut))) { if (!ut.ut_line[0]) { if (isEmpty < 0) { isEmpty = offset; } } else { if (!strncmp(ut.ut_line, line, sizeof(ut.ut_line))) { isLine = offset; } } offset += sizeof(ut); } if (isLine != -1) { /* we've found a match */ lseek(fh, isLine, SEEK_SET); } else if (isEmpty != -1) { /* no match found, but at least an empty entry */ lseek(fh, isLine, SEEK_SET); } else { /* not even an empty entry found, assume we can append to the file */ } if (time) { strncpy(ut.ut_line, line, sizeof(ut.ut_line)); strncpy(ut.ut_name, user, sizeof(ut.ut_name)); strncpy(ut.ut_host, host, sizeof(ut.ut_host)); ut.ut_time = time; } else { memset(&ut, 0, sizeof(ut)); } write(fh, &ut, sizeof(ut)); close(fh);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -