Mercurial > freewnn
comparison Wnn/uum/jhlp.c @ 0:bbc77ca4def5
initial import
author | Yoshiki Yazawa <yaz@cc.rim.or.jp> |
---|---|
date | Thu, 13 Dec 2007 04:30:14 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:bbc77ca4def5 |
---|---|
1 /* | |
2 * $Id: jhlp.c,v 1.23 2006/09/25 17:31:36 aonoto Exp $ | |
3 */ | |
4 | |
5 /* | |
6 * FreeWnn is a network-extensible Kana-to-Kanji conversion system. | |
7 * This file is part of FreeWnn. | |
8 * | |
9 * Copyright Kyoto University Research Institute for Mathematical Sciences | |
10 * 1987, 1988, 1989, 1990, 1991, 1992 | |
11 * Copyright OMRON Corporation. 1987, 1988, 1989, 1990, 1991, 1992, 1999 | |
12 * Copyright ASTEC, Inc. 1987, 1988, 1989, 1990, 1991, 1992 | |
13 * Copyright FreeWnn Project 1999, 2000, 2002, 2003, 2006 | |
14 * Copyright Canna Project 2002 | |
15 * Copyright Taketo Kabe 2003 | |
16 * | |
17 * Maintainer: FreeWnn Project | |
18 * | |
19 * This program is free software; you can redistribute it and/or modify | |
20 * it under the terms of the GNU General Public License as published by | |
21 * the Free Software Foundation; either version 2 of the License, or | |
22 * (at your option) any later version. | |
23 * | |
24 * This program is distributed in the hope that it will be useful, | |
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
27 * GNU General Public License for more details. | |
28 * | |
29 * You should have received a copy of the GNU General Public License | |
30 * along with this program; if not, write to the Free Software | |
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
32 */ | |
33 | |
34 #ifndef lint | |
35 static char *rcs_id = "$Id: jhlp.c,v 1.23 2006/09/25 17:31:36 aonoto Exp $"; | |
36 #endif /* lint */ | |
37 | |
38 #ifdef HAVE_CONFIG_H | |
39 # include <config.h> | |
40 #endif | |
41 | |
42 #include <stdio.h> | |
43 #include <sys/types.h> | |
44 #include <setjmp.h> | |
45 #include <signal.h> | |
46 #if STDC_HEADERS | |
47 # include <stdlib.h> | |
48 # include <string.h> | |
49 #else | |
50 # if HAVE_STRINGS_H | |
51 # include <strings.h> | |
52 # endif | |
53 # if HAVE_MALLOC_H | |
54 # include <malloc.h> | |
55 # endif | |
56 #endif /* STDC_HEADERS */ | |
57 #include <errno.h> | |
58 #include <sys/ioctl.h> | |
59 #include <sys/stat.h> | |
60 #ifdef HAVE_SYS_PARAM_H | |
61 # include <sys/param.h> | |
62 #endif | |
63 #if TIME_WITH_SYS_TIME | |
64 # include <sys/time.h> | |
65 # include <time.h> | |
66 #else | |
67 # if HAVE_SYS_TIME_H | |
68 # include <sys/time.h> | |
69 # else | |
70 # include <time.h> | |
71 # endif /* HAVE_SYS_TIME_H */ | |
72 #endif /* TIME_WITH_SYS_TIME */ | |
73 #if HAVE_FCNTL_H | |
74 # include <fcntl.h> | |
75 #endif | |
76 #include <pwd.h> | |
77 #ifdef HAVE_UNISTD_H | |
78 # include <unistd.h> | |
79 #endif | |
80 #if HAVE_SYS_WAIT_H | |
81 # include <sys/wait.h> | |
82 #endif | |
83 #ifdef HAVE_LIBUTIL_H | |
84 # include <libutil.h> | |
85 #endif | |
86 | |
87 /* Solaris 2.x needs termio.h , so include both. */ | |
88 #if HAVE_TERMIOS_H | |
89 # include <termios.h> | |
90 #endif | |
91 #if HAVE_TERMIO_H | |
92 # include <termio.h> | |
93 #endif | |
94 | |
95 #if defined(HAVE_TERMIOS_H) | |
96 /* # include <termios.h> */ | |
97 # define USE_TERMIOS 1 | |
98 #elif defined(HAVE_TERMIO_H) | |
99 /* # include <termio.h> */ | |
100 # define USE_TERMIO 1 | |
101 #elif defined(HAVE_SYS_TERMIO_H) | |
102 # include <sys/termio.h> | |
103 # define USE_TERMIO 1 | |
104 #elif defined(HAVE_SGTTY_H) | |
105 # include <sgtty.h> | |
106 # define USE_SGTTY | |
107 #else | |
108 # error "No termio header." | |
109 #endif /* HAVE_TERMIOS_H */ | |
110 | |
111 #ifdef HAVE_LIBSPT | |
112 # include <libspt.h> /* lib from Canna. not used w/FreeWnn */ | |
113 #endif | |
114 | |
115 /* | |
116 * Enable old Linux specific code. | |
117 * We hope you don't have to use this #define ... | |
118 * (We will remove this #define and related code in near future.) | |
119 */ | |
120 /* #define USE_LINUX_TERM */ | |
121 | |
122 | |
123 #include "sdefine.h" | |
124 | |
125 #include "jllib.h" | |
126 #include "commonhd.h" | |
127 #include "sheader.h" | |
128 #include "wnn_config.h" | |
129 #include "wnn_os.h" | |
130 | |
131 /* old system check (don't know if it works) */ | |
132 #ifdef nec_ews_svr2 | |
133 # include <sys/jtermio.h> | |
134 #endif /* nec_ews_svr2 */ | |
135 #if defined(uniosu) | |
136 # include <sys/pty.h> | |
137 #endif /* defined(uniosu) */ | |
138 #ifdef SVR4 | |
139 #include <sys/stropts.h> | |
140 #include <sys/euc.h> | |
141 #include <sys/eucioctl.h> | |
142 #endif /* SVR4 */ | |
143 | |
144 #define ERROR -1 | |
145 | |
146 jmp_buf kk_env; | |
147 #ifdef TIOCSSIZE | |
148 struct ttysize pty_rowcol; | |
149 #endif /* TIOCSSIZE */ | |
150 | |
151 int ttyfd; /* master tty */ | |
152 | |
153 char *tname; /* terminal name */ | |
154 char *cmdnm = "csh"; /* char *cmdnm = "csh"; */ | |
155 | |
156 int child_id; | |
157 char *prog; | |
158 #ifdef HAVE_LIBSPT | |
159 spt_handle *spth = NULL; | |
160 #endif | |
161 int need_utmp_clear = 0; | |
162 | |
163 static void save_signals (void); | |
164 static void restore_signals (void); | |
165 static RETSIGTYPE terminate_handler (void); | |
166 static void do_end (void); | |
167 static void open_pty (void); | |
168 static void open_pty_traditional (void); | |
169 static void open_ttyp (void); | |
170 static void do_main (void); | |
171 static void exec_cmd (char **); | |
172 static void parse_options (int, char **); | |
173 static void setsize (void); | |
174 static void get_rubout (void); | |
175 static void usage (char *); | |
176 static void change_size (void); | |
177 static void default_usage (void); | |
178 static void j_term_save (void); | |
179 static unsigned char keyin0 (void); | |
180 | |
181 int | |
182 main (int argc, char **argv) | |
183 { | |
184 char *name; | |
185 char *p; | |
186 char nlspath[64]; | |
187 FuncDataBase *f; | |
188 char *server_env; | |
189 char errprefix[1024] = "error"; | |
190 int i; | |
191 | |
192 prog = argv[0]; | |
193 flow_control = FLOW_CONTROL; | |
194 code_trans = default_code_trans; | |
195 | |
196 strcpy (username, getpwuid (getuid ())->pw_name); | |
197 if ((name = getenv (WNN_USERNAME_ENV)) != NULL) | |
198 { | |
199 strncpy(username, name, PATHNAMELEN-1); | |
200 username[PATHNAMELEN-1] = '\0'; | |
201 } | |
202 for (i = 1; i < argc;) | |
203 { | |
204 if (!strcmp (argv[i++], "-L")) | |
205 { | |
206 if (i >= argc || argv[i][0] == '-') | |
207 default_usage (); | |
208 strncpy(lang_dir, argv[i++], LANGDIRLEN-1); | |
209 lang_dir[LANGDIRLEN-1] = '\0'; | |
210 for (; i < argc; i++) | |
211 { | |
212 argv[i - 2] = argv[i]; | |
213 } | |
214 argv[i - 2] = NULL; | |
215 argc -= 2; | |
216 break; | |
217 } | |
218 } | |
219 | |
220 if (*lang_dir == '\0') | |
221 { | |
222 #ifndef CANNA | |
223 if ((p = getenv ("LANG")) != NULL) | |
224 { | |
225 if (strlen (p) >= 4) | |
226 { | |
227 strncpy (lang_dir, p, 5); | |
228 lang_dir[5] = '\0'; | |
229 } | |
230 else | |
231 { | |
232 strcpy (lang_dir, p); | |
233 } | |
234 } | |
235 #else /* CANNA */ | |
236 strcpy (lang_dir, WNN_DEFAULT_LANG); | |
237 #endif /* CANNA */ | |
238 } | |
239 for (f = function_db; *lang_dir && f && f->lang; f++) | |
240 { | |
241 if (!strcmp (f->lang, lang_dir)) | |
242 { | |
243 lang_db = f; | |
244 break; | |
245 } | |
246 } | |
247 if (lang_db == NULL) | |
248 { | |
249 if (*lang_dir) | |
250 fprintf (stderr, "Lang \"%s\" is wrong, use default lang \"%s\".\n", lang_dir, WNN_DEFAULT_LANG); | |
251 strcpy (lang_dir, WNN_DEFAULT_LANG); | |
252 for (f = function_db; *lang_dir && f && f->lang; f++) | |
253 { | |
254 if (!strcmp (f->lang, lang_dir)) | |
255 { | |
256 lang_db = f; | |
257 break; | |
258 } | |
259 } | |
260 if (lang_db == NULL) | |
261 { | |
262 fprintf (stderr, "Default lang \"%s\" is wrong.\n", lang_dir); | |
263 exit (1); | |
264 } | |
265 } | |
266 f_table = &(lang_db->f_table); | |
267 code_trans = lang_db->code_trans; | |
268 tty_c_flag = lang_db->tty_code; | |
269 pty_c_flag = lang_db->pty_code; | |
270 internal_code = lang_db->internal_code; | |
271 file_code = lang_db->file_code; | |
272 | |
273 parse_options (argc, argv); | |
274 | |
275 strcpy (nlspath, LIBDIR); | |
276 strcat (nlspath, "/%L/%N"); | |
277 cd = msg_open ("uum.msg", nlspath, lang_dir); | |
278 | |
279 if (*def_servername == '\0') | |
280 { | |
281 if (!(server_env = get_server_env (lang_dir))) | |
282 { | |
283 server_env = WNN_DEF_SERVER_ENV; | |
284 } | |
285 if (name = getenv (server_env)) | |
286 { | |
287 strncpy(def_servername, name, PATHNAMELEN-1); | |
288 def_servername[PATHNAMELEN-1] = '\0'; | |
289 strcpy(def_reverse_servername, def_servername); | |
290 } | |
291 } | |
292 | |
293 if (!isatty (0)) | |
294 { | |
295 fprintf (stderr, "Input must be a tty.\n"); | |
296 exit (1); | |
297 } | |
298 | |
299 if ((p = getenv (WNN_COUNTDOWN_ENV)) == NULL) | |
300 { | |
301 if (setenv (WNN_COUNTDOWN_ENV, "0", 1) != 0) | |
302 { | |
303 #if HAVE_SNPRINTF | |
304 snprintf (errprefix, sizeof (errprefix), | |
305 "error at %s (%d)", __FILE__, __LINE__); | |
306 #endif /* HAVE_SNPRINTF */ | |
307 perror (errprefix); | |
308 exit (1); | |
309 } | |
310 } | |
311 else if (atoi (p) <= 0) | |
312 { | |
313 puteustring (MSG_GET (4), stdout); | |
314 /* | |
315 puteustring("uumからuumは起こせません。\n",stdout); | |
316 */ | |
317 exit (126); | |
318 } | |
319 else | |
320 { | |
321 sprintf (p, "%d", atoi (p) - 1); | |
322 if (setenv (WNN_COUNTDOWN_ENV, p, 1) != 0) | |
323 { | |
324 #if HAVE_SNPRINTF | |
325 snprintf (errprefix, sizeof (errprefix), | |
326 "error at %s (%d)", __FILE__, __LINE__); | |
327 #endif /* HAVE_SNPRINTF */ | |
328 perror (errprefix); | |
329 exit (1); | |
330 } | |
331 } | |
332 | |
333 if ((tname = getenv ("TERM")) == NULL) | |
334 { | |
335 fprintf (stderr, "Sorry. Please set your terminal type.\r\n"); | |
336 exit (1); | |
337 } | |
338 | |
339 /* 2003.06 should delete this? */ | |
340 #ifndef HAVE_LIBSPT | |
341 /* saveutmp() does utmp handling if USE_UTMP is set to 1 */ | |
342 if (saveutmp () < 0) | |
343 { | |
344 puts ("Can't save utmp\n"); | |
345 } | |
346 #endif /* !HAVE_LIBSPT */ | |
347 | |
348 | |
349 if (optind) | |
350 { | |
351 optind--; | |
352 argc -= optind; | |
353 argv += optind; | |
354 } | |
355 if (argc > 1) | |
356 { | |
357 cmdnm = *++argv; | |
358 } | |
359 else | |
360 { | |
361 if ((name = getenv ("SHELL")) != NULL) | |
362 { | |
363 cmdnm = name; | |
364 } | |
365 argv[0] = cmdnm; | |
366 argv[1] = NULL; | |
367 } | |
368 | |
369 j_term_save (); | |
370 /* do_end () is allowed from here */ | |
371 save_signals (); | |
372 | |
373 #if HAVE_TERMINFO /* TERMINFO */ | |
374 if (openTermData () == -1) | |
375 { | |
376 fprintf (stderr, "Sorry. Something is wrong with terminfo, maybe.\r\n"); | |
377 exit (21); | |
378 } | |
379 maxlength = columns; | |
380 crow = lines - conv_lines; | |
381 #else /* Assume TERMCAP */ | |
382 if (getTermData () == -1) | |
383 { | |
384 fprintf (stderr, "Sorry. Something is wrong with termcap, maybe.\r\n"); | |
385 exit (21); | |
386 } | |
387 #endif /* HAVE_TERMINFO */ | |
388 #if defined(BSD43) || defined(DGUX) | |
389 setsize (); | |
390 #endif /* BSD43 */ | |
391 | |
392 #if !HAVE_TERMINFO /* Assume TERMCAP */ | |
393 if (set_TERMCAP () == -1) | |
394 { | |
395 fprintf (stderr, "Sorry. Something is wrong with termcap, maybe.\r\n"); | |
396 exit (21); | |
397 } | |
398 #endif /* !HAVE_TERMINFO */ | |
399 | |
400 ttyfd = 0; | |
401 open_pty (); | |
402 /* It is normal to open tty here, before fork(). | |
403 Don't know why linux is different. | |
404 So temporally comment it out to make it as other OSes. */ | |
405 #ifndef USE_LINUX_TERM | |
406 open_ttyp (); | |
407 #endif | |
408 exec_cmd (argv); | |
409 | |
410 get_rubout (); | |
411 | |
412 switch (init_uum ()) | |
413 { /* initialize of kana-kanji henkan */ | |
414 case -1: | |
415 terminate_handler (); | |
416 break; | |
417 case -2: | |
418 epilogue (); | |
419 do_end (); | |
420 break; | |
421 } | |
422 | |
423 fcntl (ttyfd, F_SETFL, O_NDELAY); | |
424 | |
425 if (j_term_init () == ERROR) | |
426 { | |
427 uum_err ("term initialize fault."); | |
428 } | |
429 | |
430 #ifndef CANNA | |
431 if (!jl_isconnect (bun_data_)) | |
432 { | |
433 if (!servername || *servername == 0) | |
434 { | |
435 printf ("%s\r\n", wnn_perror ()); | |
436 } | |
437 else | |
438 { | |
439 printf ("jserver(at %s):%s\r\n", servername, wnn_perror ()); | |
440 } | |
441 flush (); | |
442 } | |
443 #endif /* CANNA */ | |
444 | |
445 puteustring (MSG_GET (1), | |
446 /* | |
447 "\ruum(かな漢字変換フロントエンドプロセッサ)\r\n", | |
448 */ | |
449 stdout); | |
450 initial_message_out (); /* print message if exists. */ | |
451 | |
452 #if defined(uniosu) | |
453 if (setjmp (kk_env)) | |
454 { | |
455 disconnect_jserver (); | |
456 ioctl_off (); | |
457 connect_jserver (0); | |
458 } | |
459 #endif /* defined(uniosu) */ | |
460 | |
461 do_main (); | |
462 return 0; | |
463 } | |
464 | |
465 /* | |
466 each options handling functions | |
467 */ | |
468 | |
469 static int | |
470 do_h_opt (void) | |
471 { | |
472 henkan_off_flag = 1; | |
473 defined_by_option |= OPT_WAKING_UP_MODE; | |
474 return 0; | |
475 } | |
476 | |
477 static int | |
478 do_H_opt (void) | |
479 { | |
480 henkan_off_flag = 0; | |
481 defined_by_option |= OPT_WAKING_UP_MODE; | |
482 return 0; | |
483 } | |
484 | |
485 #ifdef JAPANESE | |
486 int | |
487 do_u_opt (void) | |
488 { | |
489 pty_c_flag = J_EUJIS; | |
490 return 0; | |
491 } | |
492 | |
493 int | |
494 do_j_opt (void) | |
495 { | |
496 pty_c_flag = J_JIS; | |
497 return 0; | |
498 } | |
499 | |
500 int | |
501 do_s_opt (void) | |
502 { | |
503 pty_c_flag = J_SJIS; | |
504 return 0; | |
505 } | |
506 | |
507 int | |
508 do_U_opt (void) | |
509 { | |
510 tty_c_flag = J_EUJIS; | |
511 return 0; | |
512 } | |
513 | |
514 int | |
515 do_J_opt (void) | |
516 { | |
517 tty_c_flag = J_JIS; | |
518 return 0; | |
519 } | |
520 | |
521 int | |
522 do_S_opt (void) | |
523 { | |
524 tty_c_flag = J_SJIS; | |
525 return 0; | |
526 } | |
527 #endif /* JAPANESE */ | |
528 | |
529 #ifdef CHINESE | |
530 int | |
531 do_b_opt (void) | |
532 { | |
533 pty_c_flag = C_BIG5; | |
534 return 0; | |
535 } | |
536 | |
537 int | |
538 do_t_opt (void) | |
539 { | |
540 pty_c_flag = C_ECNS11643; | |
541 return 0; | |
542 } | |
543 | |
544 int | |
545 do_B_opt (void) | |
546 { | |
547 tty_c_flag = C_BIG5; | |
548 return 0; | |
549 } | |
550 | |
551 int | |
552 do_T_opt (void) | |
553 { | |
554 tty_c_flag = C_ECNS11643; | |
555 return 0; | |
556 } | |
557 #endif /* CHINESE */ | |
558 | |
559 #ifdef KOREAN | |
560 int | |
561 do_u_opt (void) | |
562 { | |
563 pty_c_flag = K_EUKSC; | |
564 return 0; | |
565 } | |
566 | |
567 int | |
568 do_U_opt (void) | |
569 { | |
570 tty_c_flag = K_EUKSC; | |
571 return 0; | |
572 } | |
573 #endif /* KOREAN */ | |
574 | |
575 static int | |
576 do_P_opt (void) | |
577 { | |
578 sleep (20); | |
579 return 0; | |
580 } | |
581 | |
582 static int | |
583 do_x_opt (void) | |
584 { | |
585 flow_control = 0; | |
586 defined_by_option |= OPT_FLOW_CTRL; | |
587 return 0; | |
588 } | |
589 | |
590 static int | |
591 do_X_opt (void) | |
592 { | |
593 flow_control = 1; | |
594 defined_by_option |= OPT_FLOW_CTRL; | |
595 return 0; | |
596 } | |
597 | |
598 static int | |
599 do_k_opt (void) | |
600 { | |
601 strncpy(uumkey_name_in_uumrc, optarg, PATHNAMELEN-1); | |
602 uumkey_name_in_uumrc[PATHNAMELEN-1] = '\0'; | |
603 if (*uumkey_name_in_uumrc == '\0') | |
604 { | |
605 return -1; | |
606 } | |
607 defined_by_option |= OPT_WNNKEY; | |
608 return 0; | |
609 } | |
610 | |
611 static int | |
612 do_c_opt (void) | |
613 { | |
614 strncpy(convkey_name_in_uumrc, optarg, PATHNAMELEN-1); | |
615 convkey_name_in_uumrc[PATHNAMELEN-1] = '\0'; | |
616 if (*convkey_name_in_uumrc == '\0') | |
617 { | |
618 return -1; | |
619 } | |
620 defined_by_option |= OPT_CONVKEY; | |
621 return 0; | |
622 } | |
623 | |
624 static int | |
625 do_r_opt (void) | |
626 { | |
627 strncpy(rkfile_name_in_uumrc, optarg, PATHNAMELEN-1); | |
628 rkfile_name_in_uumrc[PATHNAMELEN-1] = '\0'; | |
629 if (*rkfile_name_in_uumrc == '\0') | |
630 { | |
631 return -1; | |
632 } | |
633 defined_by_option |= OPT_RKFILE; | |
634 return 0; | |
635 } | |
636 | |
637 static int | |
638 do_l_opt (void) | |
639 { | |
640 conv_lines = atoi (optarg); | |
641 return 0; | |
642 } | |
643 | |
644 static int | |
645 do_D_opt (void) | |
646 { | |
647 strncpy(def_servername, optarg, PATHNAMELEN-1); | |
648 def_servername[PATHNAMELEN-1] = '\0'; | |
649 strcpy(def_reverse_servername, def_servername); | |
650 if (*def_servername == '\0') | |
651 { | |
652 return -1; | |
653 } | |
654 return 0; | |
655 } | |
656 | |
657 static int | |
658 do_n_opt (void) | |
659 { | |
660 strncpy(username, optarg, PATHNAMELEN-1); | |
661 username[PATHNAMELEN-1] = '\0'; | |
662 if (*username == '\0') | |
663 { | |
664 return -1; | |
665 } | |
666 return 0; | |
667 } | |
668 | |
669 static int | |
670 do_v_opt (void) | |
671 { | |
672 defined_by_option |= OPT_VERBOSE; | |
673 return 0; | |
674 } | |
675 | |
676 static int (*do_opt[]) (void) = | |
677 { | |
678 do_h_opt, /* 'h' : waking_up_in_henkan_mode */ | |
679 do_H_opt, /* 'H' : waking_up_no_henkan_mode */ | |
680 do_P_opt, /* 'P' : sleep 20 seconds (for debug) */ | |
681 do_x_opt, /* 'x' : disable tty's flow control */ | |
682 do_X_opt, /* 'X' : enable tty's flow control */ | |
683 do_k_opt, /* 'k' : specify uumkey file */ | |
684 do_c_opt, /* 'c' : specify convert_key file */ | |
685 do_r_opt, /* 'r' : specify romkan mode file */ | |
686 do_l_opt, /* 'l' : specify # of lines used for henkan */ | |
687 do_D_opt, /* 'D' : specify hostname of jserver */ | |
688 do_n_opt, /* 'n' : specify username for jserver */ | |
689 do_v_opt, /* 'v' : verbose */ | |
690 }; | |
691 | |
692 static void | |
693 parse_options (argc, argv) | |
694 int argc; | |
695 char **argv; | |
696 { | |
697 register int c; | |
698 register char *default_getoptstr = GETOPTSTR; | |
699 register char *default_ostr = OPTIONS; | |
700 char ostr[64]; | |
701 register char *p; | |
702 | |
703 strcpy (ostr, default_getoptstr); | |
704 strcat (ostr, lang_db->getoptstr); | |
705 while ((c = getopt (argc, argv, ostr)) != EOF) | |
706 { | |
707 if (!(p = strchr (default_ostr, c)) || (*do_opt[p - default_ostr]) () < 0) | |
708 { | |
709 if (!(p = strchr (lang_db->ostr, c)) || (*lang_db->do_opt[p - lang_db->ostr]) () < 0) | |
710 { | |
711 strcpy (ostr, default_ostr); | |
712 strcat (ostr, lang_db->ostr); | |
713 usage (ostr); | |
714 } | |
715 } | |
716 } | |
717 } | |
718 | |
719 /** tty に対する ioctl のセット */ | |
720 | |
721 #ifdef USE_SGTTY | |
722 # if defined(BSD43) || defined(DGUX) /* should be "defined(LPASS8)"? */ | |
723 # define SET_PASS8 1 | |
724 # endif | |
725 | |
726 struct sgttyb savetmio; | |
727 struct sgttyb ttyb_def = { B9600, B9600, 0x7f, 0x15, | |
728 EVENP | ODDP | ECHO | CRMOD }; | |
729 int local_mode_def = LCRTBS | LCRTERA | LCRTKIL | LCTLECH | LPENDIN | LDECCTQ; | |
730 /* added later */ | |
731 struct tchars tcharsv; | |
732 struct ltchars ltcharsv; | |
733 struct sgttyb ttyb; | |
734 int local_mode; | |
735 # ifdef SET_PASS8 | |
736 static int local_mode_sv; | |
737 # endif | |
738 | |
739 static void | |
740 get_rubout (void) | |
741 { | |
742 rubout_code = savetmio.sg_erase; | |
743 } | |
744 | |
745 int | |
746 j_term_init (void) | |
747 { | |
748 struct sgttyb buf; | |
749 | |
750 buf = savetmio; | |
751 buf.sg_flags |= RAW; | |
752 buf.sg_flags &= ~ECHO; | |
753 ioctl (ttyfd, TIOCSETP, &buf); | |
754 # ifdef SET_PASS8 | |
755 ioctl (ttyfd, TIOCLSET, &local_mode); | |
756 # endif | |
757 | |
758 return 0; | |
759 } | |
760 | |
761 static_void | |
762 j_term_save (void) | |
763 { | |
764 ioctl (ttyfd, TIOCGETC, &tcharsv); | |
765 ioctl (ttyfd, TIOCGLTC, <charsv); | |
766 if (ioctl (ttyfd, TIOCGETP, &ttyb)) | |
767 ttyb = ttyb_def; | |
768 savetmio = ttyb; | |
769 # ifdef SET_PASS8 | |
770 if (ioctl (ttyfd, TIOCLGET, &local_mode_sv)) | |
771 local_mode_sv = local_mode_def; | |
772 local_mode = local_mode_sv | LPASS8; /* set PASS8 */ | |
773 # else /* !SET_PASS8 */ | |
774 if (ioctl (ttyfd, TIOCLGET, &local_mode)) | |
775 local_mode = local_mode_def; | |
776 # endif /* !SET_PASS8 */ | |
777 } | |
778 | |
779 static void | |
780 j_term_restore (void) | |
781 { | |
782 ioctl (ttyfd, TIOCSETP, &savetmio); | |
783 # ifdef SET_PASS8 | |
784 ioctl (ttyfd, TIOCLSET, &local_mode_sv); | |
785 # endif /* SET_PASS8 */ | |
786 } | |
787 | |
788 static void | |
789 j_term_p_init (int ttypfd) | |
790 { | |
791 int word; | |
792 ioctl (ttypfd, TIOCSETC, &tcharsv); | |
793 ioctl (ttypfd, TIOCSLTC, <charsv); | |
794 ioctl (ttypfd, TIOCSETP, &ttyb); | |
795 ioctl (ttypfd, TIOCLSET, &local_mode); | |
796 if (pty_c_flag == J_JIS) | |
797 { | |
798 word = LCTLECH; | |
799 ioctl (ttypfd, TIOCLBIC, &word); | |
800 } | |
801 } | |
802 #endif /* USE_SGTTY */ | |
803 | |
804 #if defined(USE_TERMIO) || defined(USE_TERMIOS) | |
805 | |
806 #ifdef USE_TERMIOS | |
807 # define TERMIO termios | |
808 # define GET_TERMATTR(fd, tio) tcgetattr(fd, tio) | |
809 # define SET_TERMATTR(fd, tio) tcsetattr(fd, TCSADRAIN, tio) | |
810 # define UNDEF_STTY _POSIX_VDISABLE | |
811 # define SET_ATTR_ERROR "error in tcsetattr.\n" | |
812 #else /* !USE_TERMIOS */ | |
813 # define TERMIO termio | |
814 # define GET_TERMATTR(fd, tio) ioctl(fd, TCGETA, tio) | |
815 # ifdef TCSETAW | |
816 # define SET_TERMATTR(fd, tio) ioctl(fd, TCSETAW, tio) | |
817 # define SET_ATTR_ERROR "error in ioctl TCSETAW.\n" | |
818 # else | |
819 # define SET_TERMATTR(fd, tio) ioctl(fd, TCSETA, tio) | |
820 # define SET_ATTR_ERROR "error in ioctl TCSETA.\n" | |
821 # endif | |
822 # define UNDEF_STTY 0xff | |
823 #endif /* !USE_TERMIOS */ | |
824 #ifdef CERASE | |
825 # define WNN_CERASE CERASE | |
826 #else | |
827 # define WNN_CERASE 0x7f | |
828 #endif | |
829 | |
830 struct TERMIO savetmio; | |
831 | |
832 static void | |
833 set_default_termio (struct TERMIO *terms) | |
834 { | |
835 bzero (terms, sizeof *terms); | |
836 terms->c_iflag = IGNBRK | ICRNL | IXON; | |
837 terms->c_oflag = OPOST; | |
838 #ifdef ONLCR | |
839 terms->c_oflag |= ONLCR; | |
840 #endif | |
841 terms->c_cflag = CS8 | CSTOPB | CREAD | CLOCAL; | |
842 #ifndef USE_TERMIOS | |
843 terms->c_cflag |= B9600; | |
844 #endif | |
845 terms->c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK; | |
846 #ifdef USE_TERMIOS | |
847 terms->c_cc[VINTR] = 0x3; | |
848 terms->c_cc[VQUIT] = 0x1c; | |
849 terms->c_cc[VERASE] = 0x8; | |
850 terms->c_cc[VKILL] = 0x15; | |
851 terms->c_cc[VEOF] = 0x4; | |
852 terms->c_cc[VEOL] = _POSIX_VDISABLE; | |
853 # ifdef VEOL2 | |
854 terms->c_cc[VEOL2] = _POSIX_VDISABLE; | |
855 # endif | |
856 cfsetospeed (terms, B9600); | |
857 cfsetispeed (terms, B9600); | |
858 #else /* !USE_TERMIOS */ | |
859 terms->c_line = 0; | |
860 terms->c_cc[0] = 0x3; | |
861 terms->c_cc[1] = 0x1c; | |
862 terms->c_cc[2] = 0x8; | |
863 terms->c_cc[3] = 0x15; | |
864 terms->c_cc[4] = 0x4; | |
865 terms->c_cc[5] = 0; | |
866 terms->c_cc[6] = 0; | |
867 terms->c_cc[7] = 0; | |
868 #endif /* !USE_TERMIOS */ | |
869 } | |
870 | |
871 #if defined(uniosu) | |
872 struct jtermio savejtmio; | |
873 struct auxtermio auxterm = { | |
874 0, /* -tostop */ | |
875 {0x1a, 0, 0, 0, 0, 0, 0, 0} /* c_cc2 */ | |
876 }; | |
877 #endif /* defined(uniosu) */ | |
878 | |
879 static void | |
880 get_rubout (void) | |
881 { | |
882 if (savetmio.c_cc[VERASE] == UNDEF_STTY) | |
883 { | |
884 rubout_code = RUBOUT; | |
885 } | |
886 else | |
887 { | |
888 rubout_code = savetmio.c_cc[VERASE]; | |
889 } | |
890 } | |
891 | |
892 int | |
893 j_term_init (void) | |
894 { | |
895 struct TERMIO buf1; | |
896 #if defined(uniosu) | |
897 struct jtermio buf2; | |
898 #endif /* defined(uniosu) */ | |
899 | |
900 buf1 = savetmio; | |
901 #ifdef linux | |
902 buf1.c_lflag &= ~(ECHONL | ECHOK | ECHOE | ECHO | XCASE | ICANON | ISIG); | |
903 buf1.c_iflag = 0; | |
904 buf1.c_oflag &= ~OPOST; | |
905 buf1.c_cflag |= CS8; | |
906 buf1.c_cc[VMIN] = 1; /* cf. ICANON */ | |
907 buf1.c_cc[VTIME] = 0; | |
908 buf1.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IUCLC | IXON); | |
909 #else /* !linux */ | |
910 buf1.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON); | |
911 # ifdef IUCLC | |
912 buf1.c_iflag &= ~(IUCLC); | |
913 # endif | |
914 if (flow_control) | |
915 { | |
916 buf1.c_iflag |= IXON; | |
917 } | |
918 buf1.c_lflag &= ~(ECHONL | ECHOK | ECHOE | ECHO | ICANON | ISIG); | |
919 # ifdef XCASE | |
920 buf1.c_lflag &= ~(XCASE); | |
921 # endif | |
922 # ifdef IEXTEN | |
923 buf1.c_lflag &= ~(IEXTEN); | |
924 # endif | |
925 buf1.c_oflag = OPOST; | |
926 # ifdef USE_TERMIOS | |
927 buf1.c_cc[VMIN] = 1; | |
928 buf1.c_cc[VTIME] = 0; | |
929 cfsetispeed(&buf1, cfgetispeed(&savetmio)); | |
930 cfsetospeed(&buf1, cfgetospeed(&savetmio)); | |
931 # else /* !USE_TERMIOS */ | |
932 buf1.c_cc[VEOF] = 1; /* cf. ICANON */ | |
933 buf1.c_cc[VEOL] = 0; | |
934 /* not needed? cf.ISIG*/ | |
935 buf1.c_cc[VINTR] = WNN_CERASE; | |
936 buf1.c_cc[VQUIT] = WNN_CERASE; | |
937 buf1.c_cc[VERASE] = WNN_CERASE; | |
938 buf1.c_cc[VKILL] = WNN_CERASE; | |
939 # endif /* !USE_TERMIOS */ | |
940 #endif /* !linux */ | |
941 if (SET_TERMATTR (ttyfd, &buf1) < 0) | |
942 { | |
943 fprintf (stderr, SET_ATTR_ERROR); | |
944 exit (1); | |
945 } | |
946 | |
947 #if defined(uniosu) | |
948 buf2 = savejtmio; | |
949 buf2.j_flg = CONVTOEXT | WNN_EXIST; | |
950 buf2.j_level = jterm; | |
951 switch (jcode_set) | |
952 { | |
953 case 0: | |
954 buf2.j_ecode = JIS; | |
955 break; | |
956 case 1: | |
957 buf2.j_ecode = SJIS; | |
958 break; | |
959 case 2: | |
960 buf2.j_ecode = UJIS; | |
961 break; | |
962 default: | |
963 fprintf (stderr, "uum: kanji code set not supported in terminfo\n"); | |
964 exit (1); | |
965 } | |
966 if (jis_kanji_in) | |
967 { | |
968 strcpy (buf2.j_jst, jis_kanji_in); | |
969 buf2.j_jstl = strlen (jis_kanji_in); | |
970 } | |
971 if (jis_kanji_out) | |
972 { | |
973 strcpy (buf2.j_jend, jis_kanji_out); | |
974 buf2.j_jendl = strlen (jis_kanji_out); | |
975 } | |
976 if (jgaiji_start_address) | |
977 { | |
978 *(short *) buf2.j_gcsa = jgaiji_start_address; | |
979 } | |
980 if (jgaiji_disp) | |
981 { | |
982 strcpy (buf2.j_gdsp, jgaiji_disp); | |
983 buf2.j_gdspl = strlen (jgaiji_disp); | |
984 } | |
985 | |
986 if (ioctl (ttyfd, JTERMSET, &buf2) < 0) | |
987 { | |
988 fprintf (stderr, "error in ioctl JTERMSET.\n"); | |
989 exit (1); | |
990 } | |
991 #endif /* defined(uniosu) */ | |
992 | |
993 return 0; | |
994 } | |
995 | |
996 static void | |
997 j_term_save (void) | |
998 { | |
999 if (GET_TERMATTR (ttyfd, &savetmio) < 0) | |
1000 { | |
1001 set_default_termio (&savetmio); | |
1002 } | |
1003 #if defined(uniosu) | |
1004 if (ioctl (ttyfd, JTERMGET, &savejtmio) < 0) | |
1005 { | |
1006 fprintf (stderr, "uum: error in ioctl JTERMGET in open_ttyp.\n"); | |
1007 exit (1); | |
1008 } | |
1009 #endif /* defined(uniosu) */ | |
1010 } | |
1011 | |
1012 static void | |
1013 j_term_restore (void) | |
1014 { | |
1015 if (SET_TERMATTR (ttyfd, &savetmio) < 0) | |
1016 { | |
1017 fprintf (stderr, SET_ATTR_ERROR); | |
1018 exit (1); | |
1019 } | |
1020 | |
1021 #if defined(uniosu) | |
1022 if (ioctl (ttyfd, JTERMSET, &savejtmio) < 0) | |
1023 { | |
1024 fprintf (stderr, "error in ioctl JTERMSET.\n"); | |
1025 exit (1); | |
1026 } | |
1027 #endif /* defined(uniosu) */ | |
1028 } | |
1029 | |
1030 static void | |
1031 j_term_p_init (int ttypfd) | |
1032 { | |
1033 struct TERMIO buf1; | |
1034 #if defined(uniosu) | |
1035 struct TERMIO buf2; | |
1036 #endif | |
1037 buf1 = savetmio; | |
1038 #ifdef DGUX /* copied from JLS5.4.2 */ | |
1039 /* should clear on all platforms? */ | |
1040 buf1.c_iflag &= ~ISTRIP; | |
1041 #endif /* DGUX */ | |
1042 #ifdef nec_ews_svr2 | |
1043 buf1.c_line = JAPANLD; | |
1044 #endif | |
1045 #ifdef USE_TERMIOS | |
1046 cfsetispeed(&buf1, cfgetispeed(&savetmio)); | |
1047 cfsetospeed(&buf1, cfgetospeed(&savetmio)); | |
1048 #endif | |
1049 if (SET_TERMATTR (ttypfd, &buf1) < 0) | |
1050 { | |
1051 fprintf (stderr, SET_ATTR_ERROR); | |
1052 exit (1); | |
1053 } | |
1054 #if defined(uniosu) | |
1055 buf2 = savejtmio; | |
1056 buf2.j_flg = CONVTOEXT | KANJIINPUT; /* kanji input & output ok */ | |
1057 buf2.j_level = jterm; | |
1058 switch (jcode_set) | |
1059 { | |
1060 case 0: | |
1061 buf2.j_ecode = JIS; | |
1062 break; | |
1063 case 1: | |
1064 buf2.j_ecode = SJIS; | |
1065 break; | |
1066 case 2: | |
1067 buf2.j_ecode = UJIS; | |
1068 break; | |
1069 default: | |
1070 fprintf (stderr, "uum: kanji code set not supported in terminfo.\n"); | |
1071 exit (1); | |
1072 } | |
1073 | |
1074 if (jis_kanji_in) | |
1075 { | |
1076 strcpy (buf2.j_jst, jis_kanji_in); | |
1077 buf2.j_jstl = strlen (jis_kanji_in); | |
1078 } | |
1079 if (jis_kanji_out) | |
1080 { | |
1081 strcpy (buf2.j_jend, jis_kanji_out); | |
1082 buf2.j_jendl = strlen (jis_kanji_out); | |
1083 } | |
1084 if (jgaiji_start_address) | |
1085 { | |
1086 *(short *) buf2.j_gcsa = jgaiji_start_address; | |
1087 } | |
1088 if (jgaiji_disp) | |
1089 { | |
1090 strcpy (buf2.j_gdsp, jgaiji_disp); | |
1091 buf2.j_gdspl = strlen (jgaiji_disp); | |
1092 } | |
1093 | |
1094 if (ioctl (ttypfd, JTERMSET, &buf2) < 0) | |
1095 { | |
1096 fprintf (stderr, "error in ioctl JTERMSET.\n"); | |
1097 exit (1); | |
1098 } | |
1099 | |
1100 if (ioctl (ttypfd, TIOCSETAUX, &auxterm) < 0) | |
1101 { | |
1102 fprintf (stderr, "error in ioctl TIOCSETAUX.\n"); | |
1103 exit (1); | |
1104 } | |
1105 | |
1106 #endif /* defined(uniosu) */ | |
1107 } | |
1108 #endif /* USE_TERMIO || USE_TERMIOS */ | |
1109 | |
1110 /** signal SIGCHLD を受けた後の処理をする。*/ | |
1111 RETSIGTYPE | |
1112 chld_handler (void) | |
1113 { | |
1114 #ifdef HAVE_WAIT3 | |
1115 #ifdef HAVE_UNION_WAIT | |
1116 union wait status; | |
1117 #else /* POSIX */ | |
1118 int status; | |
1119 #endif | |
1120 int pid; | |
1121 | |
1122 if ((pid = wait3 (&status, WNOHANG | WUNTRACED, NULL)) == child_id) | |
1123 { | |
1124 if (WIFSTOPPED (status)) | |
1125 { | |
1126 #ifdef SIGCONT | |
1127 kill (pid, SIGCONT); | |
1128 #ifdef GETPGID | |
1129 KILLPG (GETPGID (pid), SIGCONT); | |
1130 #endif | |
1131 #endif | |
1132 } | |
1133 else | |
1134 { | |
1135 signal (SIGCHLD, SIG_IGN); | |
1136 printf (MSG_GET (3)); | |
1137 /* | |
1138 printf("\r\nuumを終わります。\r\n"); | |
1139 */ | |
1140 #ifdef HAVE_LIBSPT | |
1141 if (spth) | |
1142 spt_utmp_set_exit (spth, *(int *)&status); | |
1143 #endif | |
1144 epilogue (); | |
1145 do_end (); | |
1146 } | |
1147 } | |
1148 #else /* ! HAVE_WAIT3 */ | |
1149 if (wait (0) == child_id) | |
1150 { | |
1151 signal (SIGCHLD, SIG_IGN); | |
1152 printf (MSG_GET (3)); | |
1153 /* | |
1154 printf("\r\nuumを終わります。\r\n"); | |
1155 */ | |
1156 epilogue (); | |
1157 do_end (); | |
1158 } | |
1159 #endif /* HAVE_WAIT3 */ | |
1160 | |
1161 re_signal (SIGCHLD, chld_handler); | |
1162 | |
1163 /* not reached */ | |
1164 #ifndef RETSIGTYPE_VOID | |
1165 return 0; | |
1166 #endif | |
1167 } | |
1168 | |
1169 /** signal SIGTERM を受けた時の処理をする。*/ | |
1170 static RETSIGTYPE | |
1171 terminate_handler (void) | |
1172 { | |
1173 signal (SIGCHLD, SIG_IGN); | |
1174 epilogue_no_close (); | |
1175 do_end (); | |
1176 | |
1177 /* not reached */ | |
1178 #ifndef RETSIGTYPE_VOID | |
1179 return 0; | |
1180 #endif | |
1181 } | |
1182 | |
1183 #ifdef SIGWINCH | |
1184 RETSIGTYPE | |
1185 resize_handler (void) | |
1186 { | |
1187 re_signal (SIGWINCH, resize_handler); | |
1188 change_size (); | |
1189 | |
1190 /* not reached */ | |
1191 #ifndef RETSIGTYPE_VOID | |
1192 return 0; | |
1193 #endif | |
1194 } | |
1195 #endif /* SIGWINCH */ | |
1196 | |
1197 /** メインループ */ | |
1198 | |
1199 /* Assume fd_set, FD_ZERO() family. | |
1200 though we may use glue in jserver/de.c */ | |
1201 fd_set sel_ptn; | |
1202 int ptyfd; | |
1203 | |
1204 static void | |
1205 do_main (void) | |
1206 { | |
1207 #ifndef CANNA | |
1208 unsigned char *buf; | |
1209 int ml; | |
1210 | |
1211 if ((buf = (unsigned char *) malloc (maxchg * 4)) == NULL) | |
1212 { | |
1213 printf (MSG_GET (2)); | |
1214 printf (MSG_GET (3)); | |
1215 /* | |
1216 printf("malloc に失敗しました。uumを終わります。\r\n"); | |
1217 */ | |
1218 epilogue (); | |
1219 do_end (); | |
1220 } | |
1221 #else /* CANNA */ | |
1222 extern void canna_mainloop(); | |
1223 #endif /* CANNA */ | |
1224 | |
1225 FD_ZERO (&sel_ptn); | |
1226 FD_SET (ptyfd, &sel_ptn); | |
1227 FD_SET (ttyfd, &sel_ptn); | |
1228 | |
1229 if (henkan_off_flag == 0) | |
1230 { | |
1231 disp_mode (); | |
1232 } | |
1233 | |
1234 #ifndef CANNA | |
1235 for (;;) | |
1236 { | |
1237 ml = kk (); | |
1238 make_history (return_buf, ml); | |
1239 ml = (*code_trans[(internal_code << 2) | pty_c_flag]) (buf, return_buf, sizeof (w_char) * ml); | |
1240 if (ml > 0) | |
1241 write (ptyfd, buf, ml); | |
1242 } | |
1243 #else /* CANNA */ | |
1244 canna_mainloop(); | |
1245 #endif /* CANNA */ | |
1246 } | |
1247 | |
1248 int | |
1249 keyin2 (void) | |
1250 { | |
1251 int total, ret; | |
1252 unsigned char in; | |
1253 | |
1254 in = keyin0 (); | |
1255 if (in == 0xff) | |
1256 return (-1); | |
1257 total = (int) (in & 0xff); | |
1258 if (henkan_off_flag == 0 || pty_c_flag != tty_c_flag) | |
1259 { | |
1260 ret = get_cswidth_by_char (in); | |
1261 for (; ret > 1; ret--) | |
1262 { | |
1263 total = ((total & 0xff) << 8) + (int) (keyin0 () & 0xff); | |
1264 } | |
1265 } | |
1266 return (total); | |
1267 } | |
1268 | |
1269 /** convert_key nomi okonau key-in function */ | |
1270 int | |
1271 conv_keyin (char *inkey) | |
1272 { | |
1273 return keyin1 (keyin2, inkey); | |
1274 } | |
1275 | |
1276 /** キー入力関数 1 */ | |
1277 int | |
1278 keyin (void) | |
1279 { | |
1280 char inkey[16]; | |
1281 return (conv_keyin (inkey)); | |
1282 } | |
1283 | |
1284 /** キー入力関数 2 */ | |
1285 static unsigned char | |
1286 keyin0 (void) | |
1287 { | |
1288 static unsigned char buf[BUFSIZ]; | |
1289 static unsigned char outbuf[BUFSIZ]; | |
1290 static unsigned char *bufend = outbuf; | |
1291 static unsigned char *bufstart = outbuf; | |
1292 int n; | |
1293 fd_set rfds, mask; | |
1294 int i, j; | |
1295 unsigned char *p; | |
1296 extern int henkan_off_flag; | |
1297 struct timeval time_out; /* If your OS's select was implemented as | |
1298 a pointer for int, you must modify the | |
1299 time_out variable to integer */ | |
1300 int sel_ret; | |
1301 | |
1302 if (bufstart < bufend) | |
1303 { | |
1304 return (*bufstart++); | |
1305 } | |
1306 for (;;) | |
1307 { | |
1308 if ((n = read (ttyfd, buf, BUFSIZ)) > 0) | |
1309 { | |
1310 if (henkan_off_flag == 1) | |
1311 { | |
1312 if (tty_c_flag == pty_c_flag) | |
1313 { | |
1314 i = through (outbuf, buf, n); | |
1315 } | |
1316 else | |
1317 { | |
1318 i = (*code_trans[(tty_c_flag << 2) | file_code]) (outbuf, buf, n); | |
1319 } | |
1320 } | |
1321 else | |
1322 { | |
1323 i = (*code_trans[(tty_c_flag << 2) | file_code]) (outbuf, buf, n); | |
1324 } | |
1325 if (i <= 0) | |
1326 continue; | |
1327 bufstart = outbuf; | |
1328 bufend = outbuf + i; | |
1329 return (*bufstart++); | |
1330 } | |
1331 | |
1332 time_out.tv_sec = 0; | |
1333 time_out.tv_usec = 200 * 1000; /* 200 msec 間待つのだゾ! */ | |
1334 for (rfds = sel_ptn; | |
1335 #ifdef linux | |
1336 (sel_ret = select (FD_SETSIZE, &rfds, 0, 0, NULL)) < 0 && errno == EINTR; | |
1337 #else | |
1338 /* FD_SETSIZE should be 20 in classical env. */ | |
1339 (sel_ret = select (FD_SETSIZE, &rfds, 0, 0, &time_out)) < 0 && errno == EINTR; | |
1340 #endif | |
1341 rfds = sel_ptn) | |
1342 ; | |
1343 if (sel_ret == 0) | |
1344 { | |
1345 if ((tty_c_flag == J_JIS) && ((i = flush_designate ((w_char *) outbuf)) > 0)) | |
1346 { | |
1347 /* 溜まっているESCを吐き出す */ | |
1348 bufstart = outbuf; | |
1349 bufend = outbuf + i; | |
1350 return (*bufstart++); | |
1351 } | |
1352 return (0xff); | |
1353 } | |
1354 | |
1355 if (FD_ISSET(ptyfd, &rfds)) | |
1356 { | |
1357 if ((n = read (ptyfd, buf, BUFSIZ)) <= 0) | |
1358 { | |
1359 epilogue (); | |
1360 do_end (); | |
1361 } | |
1362 #if defined(uniosu) | |
1363 if (*buf == PIOCPKT_IOCTL) | |
1364 { | |
1365 arrange_ioctl (1); | |
1366 } | |
1367 else if (*buf == 0) | |
1368 #endif /* defined(uniosu) */ | |
1369 { /* sequence of data */ | |
1370 #if defined(uniosu) | |
1371 i = (*code_trans[(pty_c_flag << 2) | tty_c_flag]) (outbuf, buf + 1, n - 1); | |
1372 #else /* defined(uniosu) */ | |
1373 i = (*code_trans[(pty_c_flag << 2) | tty_c_flag]) (outbuf, buf, n); | |
1374 #endif /* defined(uniosu) */ | |
1375 if (i <= 0) | |
1376 continue; | |
1377 p = outbuf; | |
1378 push_cursor (); | |
1379 kk_restore_cursor (); | |
1380 while ((j = write (ttyfd, p, i)) < i) | |
1381 { | |
1382 if (j >= 0) | |
1383 { | |
1384 p += j; | |
1385 i -= j; | |
1386 } | |
1387 FD_ZERO (&mask); | |
1388 FD_SET (ttyfd, &mask); | |
1389 select (32, 0, &mask, 0, 0); | |
1390 } | |
1391 pop_cursor (); | |
1392 } | |
1393 } | |
1394 if (FD_ISSET(ttyfd, &rfds)) | |
1395 { | |
1396 if ((n = read (ttyfd, buf, BUFSIZ)) > 0) | |
1397 { | |
1398 if (henkan_off_flag == 1) | |
1399 { | |
1400 if (tty_c_flag == pty_c_flag) | |
1401 { | |
1402 i = through (outbuf, buf, n); | |
1403 } | |
1404 else | |
1405 { | |
1406 i = (*code_trans[(tty_c_flag << 2) | file_code]) (outbuf, buf, n); | |
1407 } | |
1408 } | |
1409 else | |
1410 { | |
1411 i = (*code_trans[(tty_c_flag << 2) | file_code]) (outbuf, buf, n); | |
1412 } | |
1413 if (i <= 0) | |
1414 continue; | |
1415 bufstart = outbuf; | |
1416 bufend = outbuf + i; | |
1417 return (*bufstart++); | |
1418 #ifdef nodef | |
1419 } | |
1420 else | |
1421 { /* Consider it as EOF */ | |
1422 epilogue (); | |
1423 do_end (); | |
1424 #endif /* It seems that select does not return EOF when Non-brock | |
1425 What should I do? */ | |
1426 } | |
1427 } | |
1428 } | |
1429 } | |
1430 | |
1431 | |
1432 #if defined(uniosu) | |
1433 /** pty から ioctl がかかった時の処理 */ | |
1434 int | |
1435 arrange_ioctl (int jflg) | |
1436 /* jflg: jtermio の j_flg の変換フラグがオフの時 0 オンの時 1 */ | |
1437 { | |
1438 struct jtermio jbuf1; | |
1439 struct TERMIO frombuf; | |
1440 struct TERMIO tobuf; | |
1441 int i; | |
1442 | |
1443 GET_TERMATTR (ptyfd, &frombuf); | |
1444 GET_TERMATTR (ttyfd, &frombuf); | |
1445 | |
1446 if ((i = (frombuf.c_iflag & IXON)) != (tobuf.c_iflag & IXON)) | |
1447 { | |
1448 if (i == 0) | |
1449 { | |
1450 tobuf.c_iflag &= ~IXON; | |
1451 } | |
1452 else | |
1453 { | |
1454 tobuf.c_iflag |= IXON; | |
1455 } | |
1456 } | |
1457 if ((i = (frombuf.c_iflag & IXOFF)) != (tobuf.c_iflag & IXOFF)) | |
1458 { | |
1459 if (i == 0) | |
1460 { | |
1461 tobuf.c_iflag &= ~IXOFF; | |
1462 } | |
1463 else | |
1464 { | |
1465 tobuf.c_iflag |= IXOFF; | |
1466 } | |
1467 } | |
1468 if ((i = (frombuf.c_oflag & OPOST)) != (tobuf.c_oflag & OPOST)) | |
1469 { | |
1470 if (i == 0) | |
1471 { | |
1472 tobuf.c_oflag &= ~OPOST; | |
1473 } | |
1474 else | |
1475 { | |
1476 tobuf.c_oflag |= OPOST; | |
1477 } | |
1478 } | |
1479 tobuf.c_cflag = (tobuf.c_cflag & ~CBAUD) | (frombuf.c_cflag & CBAUD); | |
1480 | |
1481 SET_TERMATTR (ttyfd, &tobuf); /* set again */ | |
1482 | |
1483 ioctl (ptyfd, JTERMGET, &jbuf1); /* about Japanease */ | |
1484 | |
1485 if ((jflg) && ((jbuf1.j_flg & KANJIINPUT) == 0)) | |
1486 { | |
1487 jbuf1.j_flg &= ~(KANJIINPUT | CONVTOINT); /* kanji henkan flg off */ | |
1488 ioctl (ttyfd, JTERMSET, &jbuf1); | |
1489 kk_restore_cursor (); | |
1490 reset_cursor (); | |
1491 longjmp (kk_env, 1); | |
1492 } | |
1493 if ((!jflg) && ((jbuf1.j_flg & KANJIINPUT) != 0)) | |
1494 { | |
1495 jbuf1.j_flg &= ~(KANJIINPUT | CONVTOINT); /* kanji henkan flg off */ | |
1496 ioctl (ttyfd, JTERMSET, &jbuf1); | |
1497 return (1); | |
1498 } | |
1499 jbuf1.j_flg &= ~(KANJIINPUT | CONVTOINT); /* kanji henkan flg off */ | |
1500 ioctl (ttyfd, JTERMSET, &jbuf1); | |
1501 return (0); | |
1502 } | |
1503 #endif /* defined(uniosu) */ | |
1504 | |
1505 /** 子プロセスを起こす。*/ | |
1506 | |
1507 int ttypfd = -1; /* slave tty */ | |
1508 | |
1509 static void | |
1510 exec_cmd (char **argv) | |
1511 { | |
1512 int i; | |
1513 #if defined(HAVE_LIBSPT) && !defined(USE_LINUX_TERM) | |
1514 int r; | |
1515 const char *ttynm; | |
1516 #elif !defined(HAVE_SETSID) || defined(USE_LINUX_TERM) | |
1517 #ifdef BSD42 | |
1518 int pid; | |
1519 #endif | |
1520 #endif /* (!HAVE_LIBSPT && !HAVE_SETSID) || USE_LINUX_TERM */ | |
1521 #if defined(SIGWINCH) && defined(TIOCSWINSZ) /* || defined(linux) */ | |
1522 struct winsize win; | |
1523 extern int Term_RowWidth; | |
1524 #endif | |
1525 | |
1526 child_id = fork (); | |
1527 if (child_id < 0) | |
1528 uum_err ("cannot fork."); | |
1529 if (!child_id) | |
1530 { | |
1531 /* --- start changing controlling tty --- */ | |
1532 #if defined(HAVE_LIBSPT) && !defined(USE_LINUX_TERM) | |
1533 #if defined(SIGWINCH) && defined(TIOCSWINSZ) | |
1534 if (ioctl (ttyfd, TIOCGWINSZ, &win) == 0) | |
1535 ioctl (ttypfd, TIOCSWINSZ, &win); | |
1536 #endif /* SIGWINCH && TIOCSWINSZ */ | |
1537 spt_detach_handle (spth); | |
1538 spth = NULL; | |
1539 if (spt_detach_ctty () || spt_set_ctty2 (ttypfd)) | |
1540 { | |
1541 uum_err ("cannot change controlling tty."); | |
1542 } | |
1543 | |
1544 #elif defined(HAVE_SETSID) && !defined(USE_LINUX_TERM) /* !HAVE_LIBSPT */ | |
1545 | |
1546 int fd; | |
1547 # if defined(SIGWINCH) && defined(TIOCSWINSZ) | |
1548 if (ioctl (ttyfd, TIOCGWINSZ, &win) == 0) | |
1549 ioctl (ttypfd, TIOCSWINSZ, &win); | |
1550 # endif /* SIGWINCH && TIOCSWINSZ */ | |
1551 setsid (); | |
1552 # ifdef TIOCSCTTY | |
1553 ioctl (ttypfd, TIOCSCTTY, 0); | |
1554 # else | |
1555 close (open (ttyname (ttypfd), O_WRONLY, 0)); | |
1556 # endif | |
1557 if ((fd = open("/dev/tty", O_WRONLY)) < 0) | |
1558 { | |
1559 uum_err ("cannot change controlling tty."); | |
1560 } | |
1561 close (fd); | |
1562 /* disable utmp logging for now */ | |
1563 | |
1564 #else /* (!HAVE_LIBSPT && !HAVE_SETSID) || USE_LINUX_TERM */ | |
1565 | |
1566 #ifdef BSD42 | |
1567 #ifdef TIOCNOTTY | |
1568 /* set notty */ | |
1569 { | |
1570 int fd; | |
1571 if ((fd = open ("/dev/tty", O_WRONLY)) >= 0) | |
1572 { | |
1573 (void) ioctl (fd, TIOCNOTTY, 0); | |
1574 close (fd); | |
1575 } | |
1576 } | |
1577 #endif /* TIOCNOTTY */ | |
1578 #ifdef TIOCSCTTY | |
1579 setsid (); | |
1580 ioctl (ttypfd, TIOCSCTTY, 0); | |
1581 #endif /* TIOCSCTTY */ | |
1582 /* set tty process group */ | |
1583 pid = getpid (); | |
1584 ioctl (ttypfd, TIOCSPGRP, &pid); | |
1585 setpgrp (0, 0); | |
1586 close (open (ttyname (ttypfd), O_WRONLY, 0)); | |
1587 setpgrp (0, pid); | |
1588 #endif /* BSD42 */ | |
1589 #if defined(SYSVR2) && !defined(linux) | |
1590 setpgrp (); /* should setpgrp() AFTER fork() */ | |
1591 close (open (ttyname (ttypfd), O_WRONLY, 0)); | |
1592 #endif /* SYSVR2 */ | |
1593 | |
1594 #if 0 | |
1595 /* unneccessary? */ | |
1596 /* setutmp() does utmp handling if USE_UTMP is set to 1 */ | |
1597 if (setutmp (ttypfd) == ERROR) | |
1598 { | |
1599 puts ("Can't set utmp."); | |
1600 } | |
1601 else | |
1602 { | |
1603 need_utmp_clear = 1; | |
1604 } | |
1605 #endif | |
1606 | |
1607 /* It is bizarre to open tty after fork(). | |
1608 So, try to do same as other os. | |
1609 If it does work, we can remove this. */ | |
1610 # ifdef linux | |
1611 setsid (); | |
1612 open_ttyp (); | |
1613 close (ptyfd); | |
1614 ioctl (ttypfd, TCSETA, &savetmio); | |
1615 # endif | |
1616 # if defined(SIGWINCH) && defined(TIOCSWINSZ) /* || defined(linux) */ | |
1617 ioctl (ttyfd, TIOCGWINSZ, &win); | |
1618 # endif | |
1619 | |
1620 #endif /* (!HAVE_LIBSPT && !HAVE_SETSID) || USE_LINUX_TERM */ | |
1621 /* --- finish changing controlling tty --- */ | |
1622 | |
1623 #ifndef linux | |
1624 setgid (getgid ()); | |
1625 setuid (getuid ()); | |
1626 #endif | |
1627 #ifdef HAVE_DUP2 | |
1628 dup2 (ttypfd, 0); | |
1629 dup2 (ttypfd, 1); | |
1630 dup2 (ttypfd, 2); | |
1631 #else /* !HAVE_DUP2 */ | |
1632 close (0); | |
1633 close (1); | |
1634 close (2); | |
1635 if (dup (ttypfd) != 0 || dup (ttypfd) != 1 || dup (ttypfd) != 2) | |
1636 { | |
1637 uum_err ("redirection fault."); | |
1638 } | |
1639 #endif /* !HAVE_DUP2 */ | |
1640 for (i = WNN_NFD - 1; i > 2; i--) | |
1641 { | |
1642 close (i); | |
1643 } | |
1644 | |
1645 restore_signals (); | |
1646 | |
1647 #ifdef SIGTSTP | |
1648 signal (SIGTSTP, SIG_IGN); | |
1649 #endif | |
1650 #ifdef SIGTTIN | |
1651 signal (SIGTTIN, SIG_IGN); | |
1652 #endif | |
1653 #ifdef SIGTTOU | |
1654 signal (SIGTTOU, SIG_IGN); | |
1655 #endif | |
1656 | |
1657 #if defined(SIGWINCH) && defined(TIOCSWINSZ) /* || defined(linux) */ | |
1658 crow = win.ws_row = Term_RowWidth = win.ws_row - conv_lines; | |
1659 ioctl (ttyfd, TIOCSWINSZ, &win); | |
1660 #endif | |
1661 #ifdef linux | |
1662 setgid (getgid ()); | |
1663 setuid (getuid ()); | |
1664 #endif | |
1665 execvp (cmdnm, argv); | |
1666 uum_err ("exec fault."); | |
1667 } | |
1668 | |
1669 /* parent */ | |
1670 #ifdef HAVE_LIBSPT | |
1671 ttynm = ttyname (0); | |
1672 if (ttynm) | |
1673 { | |
1674 ttynm = strchr (ttynm + 1, '/'); | |
1675 if (ttynm && ttynm[1]) | |
1676 { | |
1677 spt_utmp_set_host (spth, ttynm + 1); | |
1678 } | |
1679 } | |
1680 spt_utmp_set_pid (spth, child_id); | |
1681 r = spt_login_utmp (spth); | |
1682 if (!r) | |
1683 { | |
1684 need_utmp_clear = 1; | |
1685 } | |
1686 else | |
1687 { | |
1688 spt_perror ("exec_cmd (login_utmp)", r); | |
1689 } | |
1690 #else /* !HAVE_LIBSPT */ | |
1691 /* setutmp() does utmp handling if USE_UTMP is set to 1 */ | |
1692 if (setutmp (ttypfd) == ERROR) | |
1693 { | |
1694 puts ("Can't set utmp."); | |
1695 } | |
1696 else | |
1697 { | |
1698 need_utmp_clear = 1; | |
1699 } | |
1700 #endif /* HAVE_LIBSPT */ | |
1701 } | |
1702 | |
1703 #if !(HAVE_SETENV) | |
1704 /** 環境変数のセット */ | |
1705 /* | |
1706 * This function causes memory leak, but I leave it as it is. Anyway, | |
1707 * this function is called only a few times at the startup of uum. | |
1708 * The 3rd parameter is ignored. It is added for compatibility only. | |
1709 */ | |
1710 int | |
1711 setenv (char *var, char *value, int overwrite) | |
1712 { | |
1713 extern char **environ; | |
1714 char **newenv; | |
1715 int i, j; | |
1716 | |
1717 j = strlen (var); | |
1718 for (i = 0; environ[i] != NULL; i++) | |
1719 { | |
1720 if (strncmp (var, environ[i], j) == 0 && environ[i][j] == '=') | |
1721 { | |
1722 break; | |
1723 } | |
1724 } | |
1725 if (environ[i] == NULL) | |
1726 { | |
1727 if ((newenv = (char **) malloc ((sizeof (char *)) * (i + 2))) == NULL) | |
1728 { | |
1729 return (-1); | |
1730 } | |
1731 for (j = 0; j < i + 1; j++) | |
1732 { | |
1733 newenv[j] = environ[j]; | |
1734 } | |
1735 newenv[i + 1] = NULL; | |
1736 environ = newenv; | |
1737 } | |
1738 if ((environ[i] = malloc (strlen (var) + strlen (value) + 2)) == NULL) | |
1739 { | |
1740 return (-1); | |
1741 } | |
1742 strcpy (environ[i], var); | |
1743 strcat (environ[i], "="); | |
1744 strcat (environ[i], value); | |
1745 return (0); | |
1746 } | |
1747 #endif /* !HAVE_SETENV */ | |
1748 | |
1749 #ifdef SVR4 | |
1750 static int | |
1751 euc_set (eucioc_t *eucioc, int ttyfd) | |
1752 { | |
1753 struct strioctl sb; | |
1754 | |
1755 sb.ic_cmd = EUC_WSET; | |
1756 sb.ic_timout = 0; | |
1757 sb.ic_len = sizeof (struct eucioc); | |
1758 sb.ic_dp = (char *) eucioc; | |
1759 if (ioctl (ttyfd, I_STR, &sb) < 0) | |
1760 { | |
1761 return (1); | |
1762 } | |
1763 return (0); | |
1764 } | |
1765 | |
1766 static int | |
1767 set_euc_term (int ttyfd) | |
1768 { | |
1769 eucioc_t eucioc; | |
1770 | |
1771 /* for Japanese EUC */ | |
1772 eucioc.eucw[0] = 1; | |
1773 eucioc.eucw[1] = 2; | |
1774 eucioc.eucw[2] = 2; | |
1775 eucioc.eucw[3] = 3; | |
1776 eucioc.scrw[0] = 1; | |
1777 eucioc.scrw[1] = 2; | |
1778 eucioc.scrw[2] = 1; | |
1779 eucioc.scrw[3] = 2; | |
1780 if (euc_set (&eucioc, ttyfd) != 0) | |
1781 { | |
1782 fprintf (stderr, "eucwidth set failed\n"); | |
1783 return (1); | |
1784 } | |
1785 return (0); | |
1786 } | |
1787 | |
1788 #endif /* SVR4 */ | |
1789 | |
1790 #ifdef nec_ews_svr2 | |
1791 static void | |
1792 set_jterm (int ttyfd, int ttypfd) | |
1793 { | |
1794 struct jtermio buf; | |
1795 | |
1796 if (ioctl (ttyfd, TCJGETA, &buf) == -1) | |
1797 { | |
1798 fprintf (stderr, "error in ioctl TCJGETA.\n"); | |
1799 exit (1); | |
1800 } | |
1801 buf.c_iflag = 0; | |
1802 buf.c_oflag = 0; | |
1803 if (ioctl (ttypfd, TCJSETA, &buf) < 0) | |
1804 { | |
1805 fprintf (stderr, "error in ioctl TCSETA.\n"); | |
1806 exit (1); | |
1807 } | |
1808 } | |
1809 #endif /* nec_ews_svr2 */ | |
1810 | |
1811 #ifdef sony | |
1812 static void | |
1813 set_sony_jterm (int ttyfd, int ttypfd) | |
1814 { | |
1815 #ifdef TIOCKGET | |
1816 int tmode, jmode = 0; | |
1817 struct jtchars jtc; | |
1818 | |
1819 if (ioctl(ttyfd, TIOCKGET, &tmode) < 0) | |
1820 { | |
1821 fprintf(stderr, "error in ioctl TIOCKGET.\n"); | |
1822 exit (1); | |
1823 } | |
1824 jmode = tmode; | |
1825 tmode &= ~(KM_SYSCODE | KM_TTYPE); | |
1826 switch (pty_c_flag) | |
1827 { | |
1828 case J_EUJIS: | |
1829 tmode |= KM_EUC | KM_SYSEUC; | |
1830 break; | |
1831 case J_JIS: | |
1832 tmode |= KM_ASCII; | |
1833 break; | |
1834 case J_SJIS: | |
1835 tmode |= KM_SJIS | KM_SYSSJIS; | |
1836 break; | |
1837 } | |
1838 if (ioctl(ttypfd, TIOCKSET, &tmode) < 0) | |
1839 { | |
1840 fprintf(stderr, "error in ioctl TIOCKSET.\n"); | |
1841 exit (1); | |
1842 } | |
1843 #endif /* TIOCKGET */ | |
1844 | |
1845 #ifdef TIOCKGETC | |
1846 if ((jmode & KM_TTYPE) == KM_JIS) | |
1847 { | |
1848 ioctl(ttyfd, TIOCKGETC, &jtc); | |
1849 jtc.t_ascii = 'B'; | |
1850 jtc.t_kanji = 'B'; | |
1851 if (ioctl(ttypfd, TIOCKSETC, &jtc) < 0) | |
1852 { | |
1853 fprintf(stderr, "error in ioctl TIOCKSETC.\n"); | |
1854 exit(1); | |
1855 } | |
1856 } | |
1857 #endif | |
1858 } | |
1859 #endif /* sony */ | |
1860 | |
1861 /** ttyp のオープン */ | |
1862 | |
1863 #ifndef HAVE_LIBSPT | |
1864 /* ways to get a pty' | |
1865 == Traditional | |
1866 Try opening each /dev/ptyXX and use the succeeded one | |
1867 == SGI IRIX | |
1868 use _getpty() | |
1869 == BSD? (HAVE_OPENPTY) | |
1870 use openpty() | |
1871 == STREAMS (Solaris) (HAVE_PTSNAME) | |
1872 use posix_openpt() (or open /dev/ptmx directly) and ptsname() | |
1873 (see pts(7D) for EXAMPLE) | |
1874 */ | |
1875 | |
1876 #if !defined(sgi) && !defined(HAVE_PTSNAME) | |
1877 char tty_master[32]; /*VVVV overflow?*/ | |
1878 #endif | |
1879 char tty_slave [32]; /*VVVV overflow?*/ | |
1880 | |
1881 #if defined(BSD43) || defined(DGUX) /* FOR PASS8 */ | |
1882 static int local_mode_sv; | |
1883 #endif | |
1884 #endif /* !HAVE_LIBSPT */ | |
1885 | |
1886 /* open slave side of pty to ttypfd */ | |
1887 static void | |
1888 open_ttyp (void) | |
1889 { | |
1890 #ifdef HAVE_LIBSPT | |
1891 if ((ttypfd = spt_open_slave(spth)) == ERROR) | |
1892 #else /* HAVE_LIBSPT */ | |
1893 # if defined(sgi) | |
1894 if ((ttypfd = open (tty_slave, O_RDWR)) == ERROR) | |
1895 # elif defined(HAVE_PTSNAME) | |
1896 if ((ttypfd = open(tty_slave, O_RDWR)) == ERROR /* open slave */ | |
1897 # if defined(I_PUSH) | |
1898 /* for systems that have STREAMS */ | |
1899 || ioctl (ttypfd, I_PUSH, "ptem") == ERROR /* push ptem */ | |
1900 || ioctl (ttypfd, I_PUSH, "ldterm") == ERROR /* push ldterm */ | |
1901 # endif | |
1902 ) | |
1903 # elif defined (HAVE_OPENPTY) | |
1904 if (ttypfd < 0) /* already open */ | |
1905 # else | |
1906 if ((ttypfd = open (tty_slave, O_RDWR, 0)) == ERROR) /* old method */ | |
1907 # endif /* sgi */ | |
1908 #endif /* HAVE_LIBSPT */ | |
1909 { | |
1910 perror(tty_slave); /* debug */ | |
1911 uum_err ("Can't open ttyp."); | |
1912 } | |
1913 #if defined(HAVE_LIBSPT) | |
1914 spt_init_slavefd(spth, ttypfd); | |
1915 #else | |
1916 /* #if !defined(linux) */ | |
1917 chown (tty_slave, getuid (), getgid ()); | |
1918 chmod (tty_slave, 0622); | |
1919 /* #endif */ /* linux */ | |
1920 #endif /* HAVE_LIBSPT */ | |
1921 | |
1922 /* | |
1923 * We save terminal settings in main() instead of here. | |
1924 * When defined(linux) open_ttyp() is invoked from child! | |
1925 */ | |
1926 #ifndef USE_LINUX_TERM | |
1927 j_term_p_init (ttypfd); | |
1928 #endif | |
1929 | |
1930 #ifdef TIOCSSIZE | |
1931 pty_rowcol.ts_lines = crow; /* instead of lines */ | |
1932 pty_rowcol.ts_cols = maxlength; /* instead of columns */ | |
1933 ioctl (ttypfd, TIOCSSIZE, &pty_rowcol); | |
1934 #endif /* TIOCSSIZE */ | |
1935 | |
1936 #ifdef SVR4 | |
1937 set_euc_term(ttypfd); | |
1938 #endif | |
1939 #if defined(nec_ews_svr2) | |
1940 set_jterm (ttyfd, ttypfd); | |
1941 #endif | |
1942 #ifdef sony | |
1943 set_sony_jterm(ttyfd, ttypfd); | |
1944 #endif | |
1945 } | |
1946 | |
1947 #if defined(HAVE_PTSNAME) && ! defined(HAVE_POSIX_OPENPT) | |
1948 /* Maybe harmless on defined(HAVE_LIBSPT) */ | |
1949 #if !defined(HAVE__DEV_PTMX) | |
1950 #warning "If not cross compile, you must check pts master device (other than /dev/ptmx)." | |
1951 /* but continue anyway. */ | |
1952 #endif | |
1953 | |
1954 /* fallback function to posix_openpt */ | |
1955 static int | |
1956 posix_openpt (int flags) | |
1957 { | |
1958 return open("/dev/ptmx", flags); | |
1959 } | |
1960 #endif /* HAVE_PTSNAME && !HAVE_POSIX_OPENPT */ | |
1961 | |
1962 /** pty のオープン */ | |
1963 /* allocate a new pty master into int ptyfd */ | |
1964 static void | |
1965 open_pty (void) | |
1966 { | |
1967 #if defined(HAVE_LIBSPT) | |
1968 int r; | |
1969 r = spt_open_pty(&spth, &ptyfd, NULL, NULL); | |
1970 if (r != SPT_E_NONE && r != SPT_E_CHOWN_FAIL) | |
1971 uum_err ("Can't get pty."); | |
1972 | |
1973 #elif defined(sgi) | |
1974 char *tty_name_buff; | |
1975 extern char *_getpty (int *, int, mode_t, int); | |
1976 tty_name_buff = _getpty (&ptyfd, O_RDWR | O_NDELAY, 0600, 0); | |
1977 if (tty_name_buff == 0) | |
1978 uum_err ("Can't get pty."); | |
1979 strcpy (tty_slave, tty_name_buff); | |
1980 | |
1981 #elif defined(HAVE_PTSNAME) | |
1982 char *p; | |
1983 ptyfd = posix_openpt(O_RDWR); /* open master */ | |
1984 if (ptyfd < 0) | |
1985 uum_err ("Could not get a pty."); | |
1986 grantpt (ptyfd); /* change permission of slave */ | |
1987 unlockpt (ptyfd); /* unlock slave */ | |
1988 | |
1989 p = ptsname (ptyfd); /* get name of slave */ | |
1990 strcpy(tty_slave, p); | |
1991 /* you can't get path of the "master" by ttyname; | |
1992 * only the open filedes ptyfd is available. | |
1993 */ | |
1994 /* strcpy (tty_master, "/dev/ptm/x"); */ | |
1995 | |
1996 #elif HAVE_OPENPTY | |
1997 if (openpty(&ptyfd, &ttypfd, tty_slave, NULL, NULL) == ERROR) | |
1998 uum_err ("Could not get a pty."); | |
1999 /* Note: slave tty is ALREADY OPEN as ttypfd */ | |
2000 strcpy(tty_master, ttyname(ptyfd)); | |
2001 | |
2002 #else | |
2003 /* Traditional method that search in /dev/ttyXX */ | |
2004 open_pty_traditional (); | |
2005 #endif /* HAVE_LIBSPT */ | |
2006 | |
2007 return; | |
2008 } | |
2009 | |
2010 #if !(HAVE_LIBSPT) && !(sgi) && !(HAVE_PTSNAME) && !(HAVE_OPENPTY) | |
2011 static void | |
2012 open_pty_traditional (void) | |
2013 { | |
2014 int ptyno; | |
2015 | |
2016 #ifdef hpux | |
2017 # define MAXPTYS (11*16) | |
2018 # define PTYDEV ";/dev/ptym/pty" | |
2019 # define TTYDEV "/dev/pty/tty" | |
2020 #else | |
2021 # define MAXPTYS 32 | |
2022 # define PTYDEV "/dev/pty" | |
2023 # define TTYDEV "/dev/tty" | |
2024 #endif | |
2025 | |
2026 for (ptyno = 0; ptyno < MAXPTYS; ptyno++) /* sysconf? */ | |
2027 { | |
2028 /* | |
2029 * Change pseudo-devices. | |
2030 * Because FreeBSD's master pseudo-devices are pty[p-sP-S][0-9a-v]. | |
2031 * Patched by Hidekazu Kuroki(hidekazu@cs.titech.ac.jp) 1996/8/20 | |
2032 */ | |
2033 #if (defined(BSD) && (BSD >= 199306)) /* 4.4BSD-Lite by Taoka */ | |
2034 # define PTXNAME(b, PFX, no) \ | |
2035 sprintf ((b), PFX "%1c%1c", "pqrsPQRS"[((no) >> 5)], "0123456789abcdefghijklmnopqrstuv"[(no) & 0x1f]) | |
2036 #elif defined(hpux) | |
2037 # define PTXNAME(b, PFX, no) \ | |
2038 sprintf ((b), PFX "%1c%1c", "zyxwvutsrqp"[(no)>>4], "fedcba9876543210"[(no)&0x0f]) | |
2039 #else /* !4.4BSD-Lite, !hpux */ | |
2040 # define PTXNAME(b, PFX, no) \ | |
2041 sprintf ((b), PFX "%1c%1c", 'p' + ((no) >> 4), "0123456789abcdef"[(no) & 0x0f]); | |
2042 #endif /* !4.4BSD-Lite */ | |
2043 #define PTMNAME(b, no) PTXNAME(b, PTYDEV, no) | |
2044 #define PTSNAME(b, no) PTXNAME(b, TTYDEV, no) | |
2045 | |
2046 PTMNAME(tty_master, ptyno); | |
2047 fprintf(stderr, "trying master <%s>\n", tty_master); /* debug */ | |
2048 if ((ptyfd = open (tty_master, O_RDWR, 0)) != ERROR) | |
2049 { | |
2050 # if defined(uniosu) | |
2051 if (ioctl (ptyfd, PIOCPKT, 1) < 0) | |
2052 { /* packet mode on */ | |
2053 fprintf (stderr, "error in ioctl PIOCPKT.\n"); | |
2054 exit (1); | |
2055 } | |
2056 # endif /* uniosu */ | |
2057 return; | |
2058 } | |
2059 } | |
2060 uum_err ("Can't get pty."); | |
2061 } | |
2062 #endif /* !(HAVE_LIBSPT) && !(sgi) && !(HAVE_PTSNAME) && !(HAVE_OPENPTY) */ | |
2063 | |
2064 /** エラーだよ。さようなら。 */ | |
2065 void | |
2066 uum_err (char *s) | |
2067 { | |
2068 puts (s); | |
2069 fclose (stdout); | |
2070 fclose (stderr); | |
2071 fclose (stdin); | |
2072 do_end (); | |
2073 } | |
2074 | |
2075 /** 立つ鳥後を濁さず 終わりの処理 */ | |
2076 static void | |
2077 do_end (void) | |
2078 { | |
2079 #ifdef USE_LIBSPT | |
2080 int r; | |
2081 #endif | |
2082 | |
2083 static int do_end_flg = 0; | |
2084 if (do_end_flg == 1) | |
2085 return; | |
2086 do_end_flg = 1; | |
2087 | |
2088 signal (SIGCHLD, SIG_DFL); | |
2089 fcntl (ttyfd, F_SETFL, 0); | |
2090 j_term_restore (); | |
2091 | |
2092 #if !defined(HAVE_LIBSPT) && !defined(sgi) | |
2093 # ifndef HAVE_PTSNAME | |
2094 if (chown (tty_master, 0, 0) == ERROR) | |
2095 { | |
2096 perror (prog); | |
2097 } | |
2098 if (chmod (tty_master, 0666) == ERROR) | |
2099 { | |
2100 perror (prog); | |
2101 } | |
2102 | |
2103 if (chown (tty_slave, 0, 0) == ERROR) | |
2104 { | |
2105 perror (prog); | |
2106 } | |
2107 if (chmod (tty_slave, 0666) == ERROR) | |
2108 { | |
2109 perror (prog); | |
2110 } | |
2111 # endif /* HAVE_PTSNAME */ | |
2112 | |
2113 #endif /* !HAVE_LIBSPT && !sgi */ | |
2114 close (ttyfd); | |
2115 #ifdef HAVE_LIBSPT | |
2116 if (spth && need_utmp_clear && (r = spt_logout_utmp(spth))) | |
2117 spt_perror(NULL, r); | |
2118 if (spth && (r = spt_close_pty(spth))) | |
2119 spt_perror(NULL, r); | |
2120 #else | |
2121 /* needless? */ | |
2122 /* resetutmp() does utmp handling if USE_UTMP is set to 1 */ | |
2123 if (need_utmp_clear) | |
2124 { | |
2125 if (resetutmp (ttypfd) == ERROR) | |
2126 { | |
2127 printf ("Can't reset utmp."); | |
2128 } | |
2129 need_utmp_clear = 0; /* for safety */ | |
2130 } | |
2131 close (ptyfd); | |
2132 #endif /* HAVE_LIBSPT */ | |
2133 | |
2134 chdir ("/tmp"); /* to avoid making too many mon.out files */ | |
2135 | |
2136 KILLPG (child_id, SIGHUP); | |
2137 exit (0); | |
2138 } | |
2139 | |
2140 #if defined(uniosu) | |
2141 /** 仮名漢字変換を ioctl でオフした時の keyin に代わる関数 */ | |
2142 int | |
2143 ioctl_off (void) | |
2144 { | |
2145 static unsigned char buf[BUFSIZ]; | |
2146 int n; | |
2147 fd_set rfds; | |
2148 | |
2149 kk_restore_cursor (); | |
2150 clr_line_all (); | |
2151 display_henkan_off_mode (); | |
2152 | |
2153 for (;;) | |
2154 { | |
2155 if ((n = read (ttyfd, buf, BUFSIZ)) > 0) | |
2156 { | |
2157 write (ptyfd, buf, n); | |
2158 } | |
2159 rfds = sel_ptn; | |
2160 select (FD_SETSIZE, &rfds, 0, 0, NULL); | |
2161 if (FD_ISSET(ptyfd, &rfds)) | |
2162 { | |
2163 if ((n = read (ptyfd, buf, BUFSIZ)) <= 0) | |
2164 { | |
2165 epilogue (); | |
2166 do_end (); | |
2167 } | |
2168 if (*buf == 0) | |
2169 { /* sequence of data */ | |
2170 write (ttyfd, buf + 1, n - 1); | |
2171 } | |
2172 else if (*buf == PIOCPKT_IOCTL) | |
2173 { | |
2174 if (arrange_ioctl (0) > 0) | |
2175 { | |
2176 return; | |
2177 } | |
2178 } | |
2179 } | |
2180 if (FD_ISSET(ttyfd, &rfds)) | |
2181 { | |
2182 if ((n = read (ttyfd, buf, BUFSIZ)) > 0) | |
2183 { | |
2184 write (ptyfd, buf, n); | |
2185 } | |
2186 } | |
2187 } | |
2188 } | |
2189 #endif /* defined(uniosu) */ | |
2190 | |
2191 static void | |
2192 default_usage (void) | |
2193 { | |
2194 fprintf (stderr, "%s: Bad -L option\n", prog); | |
2195 exit (0); | |
2196 } | |
2197 | |
2198 static void | |
2199 usage (char *optstr) | |
2200 { | |
2201 printf ("usage: prog %s by lang \"%s\"\n", optstr, lang_dir); | |
2202 exit (0); | |
2203 } | |
2204 | |
2205 /* | |
2206 save/restore signal settings | |
2207 */ | |
2208 | |
2209 intfnptr sigpipe, sighup, sigint, sigquit, sigterm, sigtstp, sigttin, sigttou, sigchld; | |
2210 #ifdef SIGWINCH | |
2211 intfnptr sigwinch; | |
2212 #endif /* SIGWINCH */ | |
2213 | |
2214 static void | |
2215 save_signals (void) | |
2216 { | |
2217 sigpipe = signal (SIGPIPE, SIG_IGN); | |
2218 #ifdef linux /* XXX */ | |
2219 sighup = signal (SIGHUP, SIG_IGN); | |
2220 #endif | |
2221 sighup = signal (SIGHUP, terminate_handler); | |
2222 sigint = signal (SIGINT, SIG_IGN); | |
2223 sigquit = signal (SIGQUIT, SIG_IGN); | |
2224 sigterm = signal (SIGTERM, terminate_handler); | |
2225 sigchld = signal (SIGCHLD, chld_handler); | |
2226 #ifdef SIGWINCH | |
2227 sigwinch = signal (SIGWINCH, resize_handler); | |
2228 #endif /* SIGWINCH */ | |
2229 #ifdef SIGTSTP | |
2230 sigtstp = signal (SIGTSTP, SIG_IGN); | |
2231 sigttin = signal (SIGTTIN, SIG_IGN); | |
2232 sigttou = signal (SIGTTOU, SIG_IGN); | |
2233 #endif /* SIGTSTP */ | |
2234 } | |
2235 | |
2236 static void | |
2237 restore_signals (void) | |
2238 { | |
2239 signal (SIGPIPE, sigpipe); | |
2240 signal (SIGHUP, sighup); | |
2241 signal (SIGINT, sigint); | |
2242 signal (SIGQUIT, sigquit); | |
2243 signal (SIGTERM, sigterm); | |
2244 signal (SIGCHLD, sigchld); | |
2245 #ifdef SIGWINCH | |
2246 signal (SIGWINCH, sigwinch); | |
2247 #endif /* SIGWINCH */ | |
2248 #ifdef SIGTSTP | |
2249 signal (SIGTSTP, sigtstp); | |
2250 signal (SIGTTIN, sigttin); | |
2251 signal (SIGTTOU, sigttou); | |
2252 #endif /* SIGTSTP */ | |
2253 } | |
2254 | |
2255 #if defined(BSD43) || defined(DGUX) | |
2256 static void | |
2257 setsize (void) | |
2258 { | |
2259 int i; | |
2260 struct winsize win; | |
2261 extern int Term_LineWidth, Term_RowWidth, maxlength; | |
2262 | |
2263 if (ioctl (ttyfd, TIOCGWINSZ, &win) < 0) | |
2264 { | |
2265 /* Default set at getTermData() */ | |
2266 return; | |
2267 } | |
2268 else | |
2269 { | |
2270 if ((i = win.ws_row) != 0) | |
2271 { | |
2272 crow = Term_RowWidth = i - conv_lines; | |
2273 } | |
2274 if ((i = win.ws_col) != 0) | |
2275 { | |
2276 maxlength = Term_LineWidth = i; | |
2277 } | |
2278 } | |
2279 } | |
2280 #endif /* BSD43 */ | |
2281 | |
2282 #ifdef SIGWINCH | |
2283 static void | |
2284 change_size (void) | |
2285 { | |
2286 register int i; | |
2287 struct winsize win; | |
2288 extern int Term_LineWidth, Term_RowWidth, maxlength; | |
2289 | |
2290 if (ioctl (ttyfd, TIOCGWINSZ, &win) < 0) | |
2291 { | |
2292 /* Default set at getTermData() */ | |
2293 return; | |
2294 } | |
2295 else | |
2296 { | |
2297 throw_cur_raw (0, crow); | |
2298 clr_line (); | |
2299 | |
2300 if ((i = win.ws_row) != 0) | |
2301 { | |
2302 crow = Term_RowWidth = i - conv_lines; | |
2303 #ifdef TIOCSWINSZ | |
2304 win.ws_row = crow; | |
2305 #endif | |
2306 } | |
2307 if ((i = win.ws_col) != 0) | |
2308 { | |
2309 maxlength = Term_LineWidth = i; | |
2310 } | |
2311 #ifdef TIOCSWINSZ | |
2312 ioctl (ttypfd, TIOCSWINSZ, &win); | |
2313 #else /* !TIOCSWINSZ */ | |
2314 #ifdef TIOCSSIZE | |
2315 pty_rowcol.ts_lines = crow; /* instead of lines */ | |
2316 pty_rowcol.ts_cols = maxlength; /* instead of columns */ | |
2317 ioctl (ttypfd, TIOCSSIZE, &pty_rowcol); | |
2318 #endif /* TIOCSSIZE */ | |
2319 #ifdef sun /* When your machine needs SIGWINCH, add your machine */ | |
2320 { | |
2321 int grp; | |
2322 ioctl (ptyfd, TIOCGPGRP, &grp); | |
2323 KILLPG (grp, SIGWINCH); | |
2324 } | |
2325 #endif /* sun */ | |
2326 #endif /* !TIOCSWINSZ */ | |
2327 | |
2328 #ifndef CANNA | |
2329 set_scroll_region (0, crow - 1); | |
2330 if (henkan_off_flag) | |
2331 { | |
2332 kk_restore_cursor (); | |
2333 throw_cur_raw (0, 0); | |
2334 kk_save_cursor (); | |
2335 display_henkan_off_mode (); | |
2336 set_screen_vars_default (); | |
2337 t_print_l (); | |
2338 kk_restore_cursor (); | |
2339 } | |
2340 else | |
2341 { | |
2342 kk_restore_cursor (); | |
2343 throw_cur_raw (0, 0); | |
2344 kk_save_cursor (); | |
2345 disp_mode (); | |
2346 set_screen_vars_default (); | |
2347 t_print_l (); | |
2348 } | |
2349 #else /* CANNA */ | |
2350 set_scroll_region(0, crow - 1); | |
2351 set_screen_vars_default(); | |
2352 t_print_l(); | |
2353 #endif /* CANNA */ | |
2354 } | |
2355 } | |
2356 #endif /* SIGWINCH */ |