main.c
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:6k
- /* $Id: main.c,v 1.1 2000/01/15 01:45:37 edwardc Exp $ */
- /*
- * hztty -- version 1.1
- *
- * This program creates a pseudo terminal on top of cxterm that
- * facilitates you to read/write Chinese characters in different
- * encoding or different representation, such as the zW/HZ standard.
- * It turns the current cxterm session into the "new encoding aware"
- * cxterm and creates a new shell session for you.
- *
- * This program must be run on top of cxterm. (It's possible to run
- * in a terminal that supports Chinese, like kermit on CCDOS, ET, KC,
- * or Chinese Windows, etc.)
- *
- * The conversion is implemented in a configurable I/O stream style.
- * Conversion modules are specified in command line options "-O" (for
- * output) and "-I" (for input). In each direction, conversion modules
- * can be piped one to one using connection character ':'. For example,
- * specifying "hz2gb:gb2big" in output stream translate the cxterm screen
- * output from zW/HZ to GB, then from GB to Big5.
- *
- * Yongguang ZHANG (ygz@cs.purdue.edu)
- * Purdue University August 04, 1993
- */
- /*
- * Copyright 1992 by Yongguang Zhang
- */
- #ifndef lint
- static char *rcs_id="$Id: main.c,v 1.1 2000/01/15 01:45:37 edwardc Exp $";
- #endif /* lint */
- #include "config.h"
- #include "io.h"
- extern int get_pty();
- extern int get_tty();
- extern void get_term_mode();
- extern void set_term_mode();
- extern void make_raw();
- extern void addutmp();
- extern void rmutmp();
- static int loginsh = 0;
- static int utmp = 1; /* update utmp by default */
- static char *term = "vt100";
- int master;
- int slave;
- int child;
- int subchild = 0;
- int in_raw = 0;
- char *i_stream = NULL;
- char *o_stream = NULL;
- int debug = 0; /* the debug flag */
- static char *shell[] = { "sh", "-i", (char *)0 };
- static char **cmdargv;
- static char *cmd;
- static char *progname;
- static struct term_mode defmode, rawmode;
- static void usage();
- static void getmaster();
- static void getslave();
- static void doinput();
- static void dooutput();
- static void doshell();
- #ifdef WINSIZE
- static struct WINSIZE winsz;
- static SIGNAL_T sigwinch ();
- #endif
- static SIGNAL_T finish ();
- static void fail();
- static void done();
- main(argc, argv)
- int argc;
- char *argv[];
- {
- extern int getopt();
- extern char *optarg;
- extern int optind;
- int ch;
- progname = *argv;
- while ((ch = getopt(argc, argv, "I:O:T:lud")) != EOF)
- switch(ch) {
- case 'I':
- i_stream = optarg;
- break;
- case 'O':
- o_stream = optarg;
- break;
- case 'T':
- term = optarg;
- break;
- case 'l':
- loginsh = 1;
- break;
- case 'u':
- utmp = 0; /* disable utmp */
- break;
- case 'd':
- debug = 1;
- break;
- case '?':
- default:
- usage();
- }
- argc -= optind;
- argv += optind;
- if ((! i_stream) && (! o_stream)) {
- i_stream = DEF_ISTREAM;
- o_stream = DEF_OSTREAM;
- }
- if (argc == 0) {
- cmdargv = shell;
- cmd = (char *)getenv("SHELL");
- if (! cmd) cmd = "/bin/sh";
- } else {
- cmdargv = argv;
- cmd = *argv;
- }
- if (loginsh)
- *cmdargv = "-";
- getmaster();
- get_term_mode(0, &defmode);
- make_raw(&defmode, &rawmode);
- set_term_mode(0, &rawmode);
- in_raw = 1;
- (void) signal(SIGCHLD, finish);
- child = fork();
- if (child < 0) {
- perror("fork");
- fail();
- }
- if (child == 0) {
- (void) signal(SIGCHLD, finish);
- subchild = child = fork();
- if (child < 0) {
- perror("fork");
- fail();
- }
- if (child == 0) {
- doshell();
- }
- #if defined(SIGWINCH) && defined(WINSIZE)
- (void) signal(SIGWINCH, sigwinch);
- #endif
- dooutput();
- }
- doinput();
- exit (0);
- }
- static void usage()
- {
- (void)fprintf(stderr,
- "usage: %s [ -lu ] [-T term] [-I input_steams] [-O output_streams] [command ...]n",
- progname);
- exit (1);
- }
- /* stdin --> pty */
- static void doinput()
- {
- register int cc;
- char ibuf[BUFSIZ];
- if (in_stream_setup (i_stream) < 0)
- fail ();
- for (;;) {
- cc = stream_read(0, ibuf, BUFSIZ);
- if (cc < 0)
- break;
- if (cc > 0)
- (void) write(master, ibuf, cc);
- }
- done();
- }
- /* pty --> stdout */
- static void dooutput()
- {
- register int cc;
- char obuf[BUFSIZ];
- if (out_stream_setup (o_stream) < 0)
- fail ();
- (void) close(0);
- for (;;) {
- cc = read(master, obuf, sizeof (obuf));
- if (cc <= 0)
- break;
- (void) stream_write(1, obuf, cc);
- }
- done();
- }
- /* tty <-> shell */
- static void doshell()
- {
- char envbuf[20];
- getslave();
- (void) close(master);
- (void) dup2(slave, 0);
- (void) dup2(slave, 1);
- (void) dup2(slave, 2);
- (void) close(slave);
- if (utmp)
- addutmp ();
- #if defined(sequent) || defined(__convex__)
- setenv ("TERM", term, 1);
- #else
- sprintf (envbuf, "TERM=%s", term);
- putenv (envbuf);
- #endif
- printf ("[%s started]n", progname);
- sleep(1);
- /* now execute the shell command */
- execvp (cmd, cmdargv);
- perror (cmd);
- fail();
- }
- static SIGNAL_T
- finish()
- {
- #if defined(SYSV) || defined(POSIX)
- int status;
- #else
- union wait status;
- #endif
- register int pid;
- register int die = 0;
- #if defined(SYSV) || defined(POSIX)
- while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0)
- #else
- while ((pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0))>0)
- #endif
- if (pid == child)
- die = 1;
- fflush (stdout);
- if (die)
- done();
- SIGNAL_RETURN;
- }
- static void fail()
- {
- if (child) {
- kill (child, SIGTERM);
- sleep (1); /* wait for the child to die */
- kill (child, SIGKILL);
- }
- done();
- }
- static void done()
- {
- if (subchild) {
- (void) close(master);
- if (utmp)
- rmutmp (subchild);
- } else {
- if (in_raw)
- set_term_mode (0, &defmode);
- printf ("n[%s exited]n", progname);
- }
- exit (0);
- }
- static void getmaster()
- {
- if (get_pty (&master) != 0) {
- fprintf(stderr, "Out of pty'sn");
- fail();
- }
- #ifdef GETWINSZ
- (void) ioctl(0, GETWINSZ, &winsz);
- #endif
- }
- static void getslave()
- {
- if (get_tty (master, &slave) != 0) {
- fprintf(stderr, "Fail to open ttyn");
- fail();
- }
- #ifdef SETWINSZ
- (void) ioctl (slave, SETWINSZ, &winsz);
- #endif
- set_term_mode(slave, &defmode);
- }
- #ifdef WINSIZE
- static SIGNAL_T
- sigwinch ()
- {
- struct WINSIZE ws;
- if (ioctl(1, GETWINSZ, &ws) != 0)
- SIGNAL_RETURN;
- (void) ioctl(master, SETWINSZ, &ws);
- #ifdef notdef /* SIGWINCH */
- { int pgrp;
- if (ioctl (master, TIOCGPGRP, (char *)&pgrp))
- killpg (pgrp, SIGWINCH);
- }
- #endif
- SIGNAL_RETURN;
- }
- #endif