📄 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...
*/
void
term(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 ELKS
char * nargv[2] = {"/bin/sash", NULL};
#else
#if DOS_DJGPP
char * nargv[2] = {"bash", NULL};
#else
char * nargv[2] = {"/bin/sh", NULL};
#endif
#endif
void 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 0
void _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 + -