00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #ifdef __WIN32__
00031 # include <windows.h>
00032 #endif
00033
00034 #ifdef HAVE_UNISTD_H
00035 # include <unistd.h>
00036 #endif
00037 #include <string.h>
00038 #include <slang.h>
00039 #include "slsh.h"
00040
00041 #include <signal.h>
00042 #include <errno.h>
00043
00044 #ifndef USE_GNU_READLINE
00045 # define USE_GNU_READLINE 0
00046 #endif
00047
00048 #define USE_SLANG_READLINE (!USE_GNU_READLINE)
00049
00050 #ifdef REAL_UNIX_SYSTEM
00051 # define SYSTEM_SUPPORTS_SIGNALS 1
00052 #else
00053 # define SYSTEM_SUPPORTS_SIGNALS 0
00054 #endif
00055
00056 #if USE_GNU_READLINE
00057 # include <readline/readline.h>
00058 # include <readline/history.h>
00059 #endif
00060
00061
00062 static int Use_Readline;
00063 static char *Prompt;
00064 static int Slsh_Quit = 0;
00065 static SLang_Load_Type *Readline_Load_Object;
00066 static SLang_RLine_Info_Type *Rline_Info;
00067
00068 static int open_readline (void);
00069 static void close_readline (void);
00070
00071 static void init_tty (void);
00072 static void reset_tty (void);
00073
00074 #if USE_GNU_READLINE
00075 static void gnu_rl_sigint_handler (int sig)
00076 {
00077 (void) sig;
00078 rl_delete_text (0, rl_end);
00079 rl_point = rl_end = 0;
00080 fprintf (stdout, "\n");
00081 rl_forced_update_display ();
00082 }
00083
00084 static void (*last_sig_sigint) (int);
00085 static void init_tty (void)
00086 {
00087 last_sig_sigint = SLsignal (SIGINT, gnu_rl_sigint_handler);
00088 }
00089
00090 static void reset_tty (void)
00091 {
00092 SLsignal (SIGINT, last_sig_sigint);
00093 }
00094
00095 #else
00096
00097 static SLang_RLine_Info_Type *Active_Rline_Info;
00098
00099 # if SYSTEM_SUPPORTS_SIGNALS
00100 static void (*last_sig_sigtstp) (int);
00101
00102 static void sig_sigtstp (int sig)
00103 {
00104 (void) sig;
00105 SLsig_block_signals ();
00106 reset_tty ();
00107 kill(getpid(),SIGSTOP);
00108 init_tty ();
00109 if (Active_Rline_Info != NULL)
00110 SLrline_redraw (Active_Rline_Info);
00111 SLsig_unblock_signals ();
00112 }
00113 # endif
00114
00115 # ifdef REAL_UNIX_SYSTEM
00116
00117 static int getkey_intr_hook (void)
00118 {
00119 return SLang_handle_interrupt ();
00120 }
00121 # endif
00122
00123 static int TTY_Inited = 0;
00124 static void init_tty (void)
00125 {
00126 int abort_char = 3;
00127 if (TTY_Inited)
00128 return;
00129 TTY_Inited++;
00130 # if SYSTEM_SUPPORTS_SIGNALS
00131 SLsig_block_signals ();
00132 SLang_TT_Read_FD = fileno (stdin);
00133 last_sig_sigtstp = SLsignal (SIGTSTP, sig_sigtstp);
00134 # endif
00135 # ifdef REAL_UNIX_SYSTEM
00136 abort_char = -1;
00137 # endif
00138
00139 if (-1 == SLang_init_tty (abort_char, 1, 0))
00140 {
00141 # if SYSTEM_SUPPORTS_SIGNALS
00142 SLsignal (SIGTSTP, last_sig_sigtstp);
00143 SLsig_unblock_signals ();
00144 # endif
00145 SLang_exit_error ("Error initializing terminal.");
00146 }
00147
00148 # ifdef REAL_UNIX_SYSTEM
00149 SLang_getkey_intr_hook = getkey_intr_hook;
00150 # endif
00151
00152 # if SYSTEM_SUPPORTS_SIGNALS
00153 SLtty_set_suspend_state (1);
00154 SLsig_unblock_signals ();
00155 # endif
00156 }
00157
00158 static void reset_tty (void)
00159 {
00160 if (TTY_Inited == 0)
00161 return;
00162 TTY_Inited = 0;
00163 # if SYSTEM_SUPPORTS_SIGNALS
00164 SLsig_block_signals ();
00165 SLsignal (SIGTSTP, last_sig_sigtstp);
00166 # endif
00167 SLang_reset_tty ();
00168 # if SYSTEM_SUPPORTS_SIGNALS
00169 SLsig_unblock_signals ();
00170 # endif
00171
00172
00173
00174
00175
00176 fputs ("\r\n", stdout);
00177 fflush (stdout);
00178 }
00179 #endif
00180
00181 static void close_readline ()
00182 {
00183 #if USE_SLANG_READLINE
00184 if (Rline_Info != NULL)
00185 {
00186 SLrline_close (Rline_Info);
00187 Rline_Info = NULL;
00188 }
00189 #endif
00190 }
00191
00192 static int open_readline ()
00193 {
00194 #if USE_GNU_READLINE
00195 return 0;
00196 #else
00197 close_readline ();
00198 if (NULL == (Rline_Info = SLrline_open (SLtt_Screen_Cols, SL_RLINE_BLINK_MATCH)))
00199 return -1;
00200 return 0;
00201 #endif
00202 }
00203
00204 #if USE_GNU_READLINE
00205 static void redisplay_dummy (void)
00206 {
00207 }
00208 #endif
00209 static char *read_input_line (SLang_RLine_Info_Type *rline, char *prompt, int noecho)
00210 {
00211 char *line;
00212 #ifdef REAL_UNIX_SYSTEM
00213 int stdin_is_noecho = 0;
00214 #endif
00215
00216 if (Use_Readline == 0)
00217 {
00218 char buf[1024];
00219 char *b;
00220
00221 fprintf (stdout, "%s", prompt); fflush (stdout);
00222 if (noecho)
00223 {
00224 #ifdef REAL_UNIX_SYSTEM
00225 if (isatty (fileno(stdin)))
00226 {
00227 (void) SLsystem ("stty -echo");
00228 stdin_is_noecho = 1;
00229 }
00230 #endif
00231 }
00232
00233 line = buf;
00234 while (1)
00235 {
00236 while (NULL == fgets (buf, sizeof (buf), stdin))
00237 {
00238 #ifdef EINTR
00239 if (errno == EINTR)
00240 {
00241 if (-1 == SLang_handle_interrupt ())
00242 {
00243 line = NULL;
00244 break;
00245 }
00246 continue;
00247 }
00248 #endif
00249 line = NULL;
00250 break;
00251 }
00252 break;
00253 }
00254 #ifdef REAL_UNIX_SYSTEM
00255 if (stdin_is_noecho)
00256 (void) SLsystem ("stty echo");
00257 #endif
00258 if (line == NULL)
00259 return NULL;
00260
00261
00262 b = line;
00263 while (*b && (*b != '\n'))
00264 b++;
00265 *b = 0;
00266
00267 return SLmake_string (line);
00268 }
00269 #if SYSTEM_SUPPORTS_SIGNALS
00270 init_tty ();
00271 #endif
00272 #if USE_GNU_READLINE
00273 (void) rline;
00274 if (noecho == 0)
00275 rl_redisplay_function = rl_redisplay;
00276 else
00277 {
00278
00279 (void) fputs (prompt, stdout); (void) fflush (stdout);
00280 rl_redisplay_function = redisplay_dummy;
00281 }
00282 line = readline (prompt);
00283 rl_redisplay_function = rl_redisplay;
00284 #else
00285 SLtt_get_screen_size ();
00286 SLrline_set_display_width (rline, SLtt_Screen_Cols);
00287 Active_Rline_Info = rline;
00288 (void) SLrline_set_echo (rline, (noecho == 0));
00289 line = SLrline_read_line (rline, prompt, NULL);
00290 Active_Rline_Info = NULL;
00291 #endif
00292 #if SYSTEM_SUPPORTS_SIGNALS
00293 reset_tty ();
00294 #else
00295 fputs ("\r\n", stdout);
00296 fflush (stdout);
00297 #endif
00298 return line;
00299 }
00300
00301
00302 static int save_input_line (SLang_RLine_Info_Type *rline, char *line)
00303 {
00304 char *p;
00305
00306 if (line == NULL)
00307 return 0;
00308
00309 p = line;
00310 while ((*p == ' ') || (*p == '\t') || (*p == '\n'))
00311 p++;
00312 if (*p == 0)
00313 return 0;
00314
00315 #if USE_GNU_READLINE
00316 (void) rline;
00317 add_history(line);
00318 return 0;
00319 #else
00320 return SLrline_save_line (rline);
00321 #endif
00322 }
00323
00324
00325
00326 static char *get_input_line (SLang_Load_Type *x)
00327 {
00328 char *prompt;
00329 char *line;
00330 int parse_level;
00331
00332 parse_level = x->parse_level;
00333 if (parse_level == 0)
00334 {
00335 if (-1 == SLang_run_hooks ("slsh_interactive_before_hook", 0))
00336 return NULL;
00337
00338 prompt = Prompt;
00339 if (prompt == NULL)
00340 prompt = "slsh> ";
00341 }
00342 else prompt = " ";
00343
00344 line = read_input_line (Rline_Info, prompt, 0);
00345
00346 if ((line == NULL)
00347 && (parse_level == 0)
00348 && (SLang_get_error() == 0))
00349 {
00350 Slsh_Quit = 1;
00351 return NULL;
00352 }
00353
00354 if (line == NULL)
00355 return NULL;
00356
00357
00358 (void) SLang_run_hooks ("slsh_interactive_after_hook", 1, line);
00359
00360 (void) save_input_line (Rline_Info, line);
00361
00362 return line;
00363 }
00364
00365 static char *read_using_readline (SLang_Load_Type *x)
00366 {
00367 char *s;
00368 static char *last_s;
00369
00370 if (last_s != NULL)
00371 {
00372 SLfree (last_s);
00373 last_s = NULL;
00374 }
00375
00376 if (SLang_get_error ())
00377 return NULL;
00378
00379 SLKeyBoard_Quit = 0;
00380
00381 s = get_input_line (x);
00382
00383 if (s == NULL)
00384 return NULL;
00385
00386 if ((x->parse_level == 0)
00387 && (1 == SLang_run_hooks ("slsh_interactive_massage_hook", 1, s)))
00388 {
00389 SLfree (s);
00390 if (-1 == SLpop_string (&s))
00391 return NULL;
00392 }
00393
00394 if (SLang_get_error ())
00395 {
00396 SLfree (s);
00397 return NULL;
00398 }
00399
00400 last_s = s;
00401 return s;
00402 }
00403
00404 static void enable_keyboard_interrupt (void)
00405 {
00406 static int is_enabled = 0;
00407
00408 if (is_enabled == 0)
00409 {
00410 (void) SLang_set_abort_signal (NULL);
00411 is_enabled = 1;
00412 }
00413 }
00414
00415 static void close_interactive (void)
00416 {
00417 close_readline ();
00418
00419 if (Readline_Load_Object == NULL)
00420 return;
00421
00422 SLdeallocate_load_type (Readline_Load_Object);
00423 Readline_Load_Object = NULL;
00424 #if !SYSTEM_SUPPORTS_SIGNALS
00425 reset_tty ();
00426 #endif
00427 }
00428
00429 static int open_interactive (void)
00430 {
00431 if (Use_Readline
00432 && (-1 == open_readline ()))
00433 return -1;
00434
00435 if (NULL == (Readline_Load_Object = SLallocate_load_type ("<stdin>")))
00436 {
00437 if (Use_Readline)
00438 close_readline ();
00439 return -1;
00440 }
00441
00442 Readline_Load_Object->read = read_using_readline;
00443 Readline_Load_Object->auto_declare_globals = 1;
00444
00445 #if !SYSTEM_SUPPORTS_SIGNALS
00446
00447
00448
00449
00450 init_tty ();
00451 #endif
00452 enable_keyboard_interrupt ();
00453
00454 return 0;
00455 }
00456
00457
00458 int slsh_use_readline (int use_readline)
00459 {
00460 Use_Readline = use_readline;
00461 return 0;
00462 }
00463
00464 int slsh_interactive (void)
00465 {
00466 Slsh_Quit = 0;
00467
00468 (void) SLang_add_cleanup_function (close_interactive);
00469
00470 if (-1 == open_interactive ())
00471 return -1;
00472
00473 while (Slsh_Quit == 0)
00474 {
00475 if (SLang_get_error ())
00476 {
00477 SLang_restart(1);
00478
00479 }
00480
00481 SLKeyBoard_Quit = 0;
00482 SLang_load_object (Readline_Load_Object);
00483 }
00484 close_interactive ();
00485
00486 return 0;
00487 }
00488
00489
00490 static SLang_RLine_Info_Type *Intrinsic_Rline_Info;
00491 #if USE_SLANG_READLINE
00492 static void close_intrinsic_readline (void)
00493 {
00494 if (Intrinsic_Rline_Info != NULL)
00495 {
00496 SLrline_close (Intrinsic_Rline_Info);
00497 Intrinsic_Rline_Info = NULL;
00498 }
00499 }
00500 #endif
00501
00502 static int readline_intrinsic_internal (char *prompt, int noecho)
00503 {
00504 char *line;
00505
00506 #if USE_SLANG_READLINE
00507 if ((Intrinsic_Rline_Info == NULL)
00508 && Use_Readline)
00509 {
00510 Intrinsic_Rline_Info = SLrline_open (SLtt_Screen_Cols, SL_RLINE_BLINK_MATCH);
00511 if (Intrinsic_Rline_Info == NULL)
00512 return -1;
00513 (void) SLang_add_cleanup_function (close_intrinsic_readline);
00514 }
00515 #endif
00516 enable_keyboard_interrupt ();
00517
00518 line = read_input_line (Intrinsic_Rline_Info, prompt, noecho);
00519 if (noecho == 0)
00520 (void) save_input_line (Intrinsic_Rline_Info, line);
00521 (void) SLang_push_malloced_string (line);
00522 return 0;
00523 }
00524
00525 void slsh_readline_intrinsic (char *prompt)
00526 {
00527 (void) readline_intrinsic_internal (prompt, 0);
00528 }
00529
00530 void slsh_readline_noecho_intrinsic (char *prompt)
00531 {
00532 (void) readline_intrinsic_internal (prompt, 1);
00533 }