main.c
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:6k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /* $Id: main.c,v 1.1 2000/01/15 01:45:37 edwardc Exp $ */
  2. /*
  3.  * hztty -- version 1.1
  4.  *
  5.  * This program creates a pseudo terminal on top of cxterm that
  6.  * facilitates you to read/write Chinese characters in different
  7.  * encoding or different representation, such as the zW/HZ standard.
  8.  * It turns the current cxterm session into the "new encoding aware"
  9.  * cxterm and creates a new shell session for you.  
  10.  *
  11.  * This program must be run on top of cxterm.  (It's possible to run
  12.  * in a terminal that supports Chinese, like kermit on CCDOS, ET, KC,
  13.  * or Chinese Windows, etc.) 
  14.  *
  15.  * The conversion is implemented in a configurable I/O stream style.
  16.  * Conversion modules are specified in command line options "-O" (for
  17.  * output) and "-I" (for input).  In each direction, conversion modules
  18.  * can be piped one to one using connection character ':'.  For example,
  19.  * specifying "hz2gb:gb2big" in output stream translate the cxterm screen
  20.  * output from zW/HZ to GB, then from GB to Big5.  
  21.  * 
  22.  * Yongguang ZHANG  (ygz@cs.purdue.edu)
  23.  * Purdue University August 04, 1993
  24.  */
  25. /*
  26.  * Copyright 1992 by Yongguang Zhang
  27.  */
  28. #ifndef lint
  29. static char *rcs_id="$Id: main.c,v 1.1 2000/01/15 01:45:37 edwardc Exp $";
  30. #endif /* lint */
  31. #include "config.h"
  32. #include "io.h"
  33. extern int get_pty();
  34. extern int get_tty();
  35. extern void get_term_mode();
  36. extern void set_term_mode();
  37. extern void make_raw();
  38. extern void addutmp();
  39. extern void rmutmp();
  40. static int loginsh = 0;
  41. static int utmp = 1; /* update utmp by default */
  42. static char *term = "vt100";
  43. int master;
  44. int slave;
  45. int child;
  46. int subchild = 0;
  47. int in_raw = 0;
  48. char *i_stream = NULL;
  49. char *o_stream = NULL;
  50. int debug = 0; /* the debug flag */
  51. static char *shell[] = { "sh", "-i", (char *)0 };
  52. static char **cmdargv;
  53. static char *cmd;
  54. static char *progname;
  55. static struct term_mode defmode, rawmode;
  56. static void usage();
  57. static void getmaster();
  58. static void getslave();
  59. static void doinput();
  60. static void dooutput();
  61. static void doshell();
  62. #ifdef WINSIZE
  63. static struct WINSIZE winsz;
  64. static SIGNAL_T sigwinch ();
  65. #endif
  66. static SIGNAL_T finish ();
  67. static void fail();
  68. static void done();
  69. main(argc, argv)
  70.      int argc;
  71.      char *argv[];
  72. {
  73.   extern int getopt();
  74.   extern char *optarg;
  75.   extern int optind;
  76.   int ch;
  77. progname = *argv;
  78. while ((ch = getopt(argc, argv, "I:O:T:lud")) != EOF)
  79. switch(ch) {
  80. case 'I':
  81. i_stream = optarg;
  82. break;
  83. case 'O':
  84. o_stream = optarg;
  85. break;
  86. case 'T':
  87. term = optarg;
  88. break;
  89. case 'l':
  90. loginsh = 1;
  91. break;
  92. case 'u':
  93. utmp = 0; /* disable utmp */
  94. break;
  95. case 'd':
  96. debug = 1;
  97. break;
  98. case '?':
  99. default:
  100. usage();
  101. }
  102. argc -= optind;
  103. argv += optind;
  104. if ((! i_stream) && (! o_stream)) {
  105. i_stream = DEF_ISTREAM;
  106. o_stream = DEF_OSTREAM;
  107. }
  108. if (argc == 0) {
  109. cmdargv = shell;
  110. cmd = (char *)getenv("SHELL");
  111. if (! cmd)  cmd = "/bin/sh";
  112. } else {
  113. cmdargv = argv;
  114. cmd = *argv;
  115. }
  116. if (loginsh)
  117. *cmdargv = "-";
  118. getmaster();
  119. get_term_mode(0, &defmode);
  120. make_raw(&defmode, &rawmode);
  121. set_term_mode(0, &rawmode);
  122. in_raw = 1;
  123. (void) signal(SIGCHLD, finish);
  124. child = fork();
  125. if (child < 0) {
  126. perror("fork");
  127. fail();
  128. }
  129. if (child == 0) {
  130. (void) signal(SIGCHLD, finish);
  131. subchild = child = fork();
  132. if (child < 0) {
  133. perror("fork");
  134. fail();
  135. }
  136. if (child == 0) {
  137. doshell();
  138. }
  139. #if defined(SIGWINCH) && defined(WINSIZE)
  140. (void) signal(SIGWINCH, sigwinch);
  141. #endif
  142. dooutput();
  143. }
  144. doinput();
  145. exit (0);
  146. }
  147. static void usage()
  148. {
  149. (void)fprintf(stderr,
  150.     "usage: %s [ -lu ] [-T term] [-I input_steams] [-O output_streams] [command ...]n",
  151.     progname);
  152. exit (1);
  153. }
  154. /* stdin --> pty */
  155. static void doinput()
  156. {
  157. register int cc;
  158. char ibuf[BUFSIZ];
  159. if (in_stream_setup (i_stream) < 0)
  160. fail ();
  161. for (;;) {
  162. cc = stream_read(0, ibuf, BUFSIZ);
  163. if (cc < 0)
  164. break;
  165. if (cc > 0)
  166. (void) write(master, ibuf, cc);
  167. }
  168. done();
  169. }
  170. /* pty --> stdout */
  171. static void dooutput()
  172. {
  173. register int cc;
  174. char obuf[BUFSIZ];
  175. if (out_stream_setup (o_stream) < 0)
  176. fail ();
  177. (void) close(0);
  178. for (;;) {
  179. cc = read(master, obuf, sizeof (obuf));
  180. if (cc <= 0)
  181. break;
  182. (void) stream_write(1, obuf, cc);
  183. }
  184. done();
  185. }
  186. /* tty <-> shell */
  187. static void doshell()
  188. {
  189.   char envbuf[20];
  190. getslave();
  191. (void) close(master);
  192. (void) dup2(slave, 0);
  193. (void) dup2(slave, 1);
  194. (void) dup2(slave, 2);
  195. (void) close(slave);
  196. if (utmp)
  197. addutmp ();
  198. #if defined(sequent) || defined(__convex__)
  199. setenv ("TERM", term, 1);
  200. #else
  201. sprintf (envbuf, "TERM=%s", term);
  202. putenv (envbuf);
  203. #endif
  204. printf ("[%s started]n", progname);
  205. sleep(1);
  206. /* now execute the shell command */
  207. execvp (cmd, cmdargv);
  208. perror (cmd);
  209. fail();
  210. }
  211. static SIGNAL_T
  212. finish()
  213. {
  214. #if defined(SYSV) || defined(POSIX)
  215. int status;
  216. #else
  217. union wait status;
  218. #endif
  219. register int pid;
  220. register int die = 0;
  221. #if defined(SYSV) || defined(POSIX)
  222. while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0)
  223. #else
  224. while ((pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0))>0)
  225. #endif
  226. if (pid == child)
  227. die = 1;
  228. fflush (stdout);
  229. if (die)
  230. done();
  231. SIGNAL_RETURN;
  232. }
  233. static void fail()
  234. {
  235. if (child) {
  236. kill (child, SIGTERM);
  237. sleep (1); /* wait for the child to die */
  238. kill (child, SIGKILL);
  239. }
  240. done();
  241. }
  242. static void done()
  243. {
  244. if (subchild) {
  245. (void) close(master);
  246. if (utmp)
  247. rmutmp (subchild);
  248. } else {
  249. if (in_raw)
  250. set_term_mode (0, &defmode);
  251. printf ("n[%s exited]n", progname);
  252. }
  253. exit (0);
  254. }
  255. static void getmaster()
  256. {
  257. if (get_pty (&master) != 0) {
  258. fprintf(stderr, "Out of pty'sn");
  259. fail();
  260. }
  261. #ifdef GETWINSZ
  262. (void) ioctl(0, GETWINSZ, &winsz);
  263. #endif
  264. }
  265. static void getslave()
  266. {
  267. if (get_tty (master, &slave) != 0) {
  268. fprintf(stderr, "Fail to open ttyn");
  269. fail();
  270. }
  271. #ifdef SETWINSZ
  272. (void) ioctl (slave, SETWINSZ, &winsz);
  273. #endif
  274. set_term_mode(slave, &defmode);
  275. }
  276. #ifdef WINSIZE
  277. static SIGNAL_T
  278. sigwinch ()
  279. {
  280.   struct WINSIZE ws;
  281. if (ioctl(1, GETWINSZ, &ws) != 0)
  282. SIGNAL_RETURN;
  283. (void) ioctl(master, SETWINSZ, &ws);
  284. #ifdef notdef /* SIGWINCH */
  285. { int pgrp;
  286. if (ioctl (master, TIOCGPGRP, (char *)&pgrp))
  287. killpg (pgrp, SIGWINCH);
  288. }
  289. #endif
  290. SIGNAL_RETURN;
  291. }
  292. #endif