void cleanup_rlwrap_and_exit(int status) { unblock_all_signals(); DPRINTF0(DEBUG_TERMIO, "Cleaning up"); if (write_histfile && (histsize==0 || history_total_bytes() > 0)) /* avoid creating empty .speling_eror_history file after typo */ write_history(history_filename); /* ignore errors */ close_logfile(); DPRINTF4(DEBUG_SIGNALS, "command_pid: %d, commands_exit_status: %x, filter_pid: %d, filters_exit_status: %x", command_pid, commands_exit_status, filter_pid, filters_exit_status); mymicrosleep(10); /* we may have got an EOF or EPIPE because the filter or command died, but this doesn't mean that SIGCHLD has been caught already. Taking a little nap now improves the chance that we will catch it (no grave problem if we miss it, but diagnostics, exit status and transparent signal handling depend on it) */ if (filter_pid) kill_filter(); else if (filter_is_dead) { int filters_killer = killed_by(filters_exit_status); errno = 0; mywarn((filters_killer ? "filter was killed by signal %d (%s)": WEXITSTATUS(filters_exit_status) ? "filter died" : "filter exited"), filters_killer, signal_name(filters_killer)); } if (debug) debug_postmortem(); if (terminal_settings_saved) if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_terminal_settings) < 0) /* ignore errors (almost dead anyway) */ ; /* fprintf(stderr, "Arggh\n"); don't use myerror!!*/ if (!newline_came_last) /* print concluding newline, if necessary */ my_putstr("\n"); if (status != EXIT_SUCCESS) /* rlwrap itself has failed, rather than the wrapped command */ exit(status); else { int commands_killer = killed_by(commands_exit_status); if (commands_killer) suicide_by(commands_killer, commands_exit_status); /* command terminated by signal, make rlwrap's parent believe rlwrap was killed by it */ else exit(WEXITSTATUS(commands_exit_status)); /* propagate command's exit status */ } }
int read_partdata(FILE *f, FILE *ftag, Slice *s) /* Read one block (128k particles) of data into Slice s. Allocate needed storage, erasing and freeing previous storage. */ /* This cannot be done with s->pid!=NULL, so s->pid is ignored and s->numlist is reset to BLOCKSIZE */ /* Unlike other routines, this stores both positions and velocities in all cases (since the storage requirements are already small */ /* If ftag==NULL, don't read the tag file. Otherwise do read it. */ { if (s->pid!=NULL) mywarn("Non-trivial pid[] not supported with incremental reads"); /* If we need to reallocate memory, do it. Otherwise, just write over */ if (s->px==NULL || s->vx==NULL || s->numlist!=s->numperblock) { if (s->px!=NULL) free_vector(s->px,1,s->numlist); if (s->py!=NULL) free_vector(s->py,1,s->numlist); if (s->pz!=NULL) free_vector(s->pz,1,s->numlist); if (s->vx!=NULL) free_vector(s->vx,1,s->numlist); if (s->vy!=NULL) free_vector(s->vy,1,s->numlist); if (s->vz!=NULL) free_vector(s->vz,1,s->numlist); if (ftag!=NULL && s->ntag!=NULL) free_ivector(s->ntag, 1, s->numlist); s->numlist = s->numperblock; s->px = vector(1,s->numlist); s->py = vector(1,s->numlist); s->pz = vector(1,s->numlist); s->vx = vector(1,s->numlist); s->vy = vector(1,s->numlist); s->vz = vector(1,s->numlist); if (ftag!=NULL) s->ntag = ivector(1, s->numlist); s->offset=0; /* fprintf(stderr, "Reallocating data arrays.\n"); */ } else s->offset+=s->numlist; f77read(f,s->px+1,4*s->numlist); f77read(f,s->py+1,4*s->numlist); f77read(f,s->pz+1,4*s->numlist); f77read(f,s->vx+1,4*s->numlist); f77read(f,s->vy+1,4*s->numlist); f77read(f,s->vz+1,4*s->numlist); if (ftag!=NULL) readtag(ftag, s->numlist, s->ntag); normalizedata(s,1,1); return 0; }
int f77read(FILE *f, void *p, int maxbytes) /* Read a FORTRAN style block from the given file */ /* maxbytes is the amount of space the pointer p points to */ /* Space must be allocated to read the whole block into p */ /* Return amount read, scream if there's a problem */ /* Reading is done ZERO-OFFSET */ { int size, size2; if (fread(&size,4,1,f)!=1) myerror("f77read(): Error reading begin delimiter."); if (size>maxbytes) myerror("f77read(): Block delimiter exceeds size of storage."); if (size<maxbytes) mywarn("f77read(): Block size is smaller than size of storage."); if (fread(p,1,size,f)!=size) myerror("f77read(): Error reading data."); if (fread(&size2,4,1,f)!=1) myerror("f77read(): Error reading end delimiter."); if (size!=size2) myerror("f77read(): Delimiters do not match."); return size; }
/* returns TRUE if 'string' matches the 'regexp' (or is a superstring of it, when we don't HAVE_REGEX_H). The regexp is recompiled with every call, which doesn't really hurt as this function is not called often: at most twice for every prompt. 'string' and 'regexp' may be NULL (in which case FALSE is returned) Only used for the --forget-regexp and the --prompt-regexp options */ int match_regexp (const char *string, const char *regexp, int case_insensitive) { int result; if (!regexp || !string) return FALSE; #ifndef HAVE_REGEX_H { static int been_warned = 0; char *metachars = "*()+?"; char *lc_string = (case_insensitive ? lowercase(string) : mysavestring(string)); char *lc_regexp = (case_insensitive ? lowercase(regexp) : mysavestring(regexp)); if (scan_metacharacters(regexp, metachars) && !been_warned++) /* warn only once if the user specifies a metacharacter */ mywarn("one of the regexp metacharacters \"%s\" occurs in regexp(?) \"%s\"\n" " ...but on your platform, regexp matching is not supported!", metachars, regexp); result = mystrstr(lc_string, lc_regexp); free(lc_string); free(lc_regexp); } #else { regex_t *compiled_regexp = mymalloc(sizeof(regex_t)); int compile_error = regcomp(compiled_regexp, regexp, REG_EXTENDED|REG_NOSUB|(case_insensitive ? REG_ICASE : 0)); if (compile_error) { int size = regerror(compile_error, compiled_regexp, NULL, 0); char *error_message = mymalloc(size); regerror(compile_error, compiled_regexp, error_message, size); errno=0; myerror("in regexp \"%s\": %s", regexp, error_message); } else { result = !regexec(compiled_regexp, string, 0, NULL, 0); free(compiled_regexp); } } #endif return result; }
static char * check_optarg(char opt, int remaining) { if (!optarg) last_option_didnt_have_optional_argument = TRUE; /* if this variable is set, and if command is not found, suggest that it may have been meant as optional argument (e.g. 'rlwrap -a password sqlplus' will try to execute 'password sqlplus' ) */ #ifndef GETOPT_GROKS_OPTIONAL_ARGS if (optarg && /* is there an optional arg? have a look at it: */ ((optarg[0] == '-' && isalpha(optarg[1])) || /* looks like next option */ remaining == 0)) /* or is last item on command line */ mywarn ("on this system, the getopt() library function doesn't\n" "grok optional arguments, so '%s' is taken as an argument to the -%c option\n" "Is this what you meant? If not, please provide an argument", optarg, opt); #endif return optarg; }
int slave_is_in_raw_mode() { struct termios *pterm_slave; static int been_warned = 0; int in_raw_mode; if (always_echo) return FALSE; if (command_is_dead) return FALSE; /* filter last words too (even if ncurses-ridden) */ if (!(pterm_slave = my_tcgetattr(slave_pty_fd, "slave pty"))) { if (been_warned++ == 1) /* only warn once, but not the first time (as this usually means that the rlwrapped command has just died) - this is still a race when signals get delivered very late*/ mywarn("tcgetattr error on slave pty (from parent process)"); return TRUE; } in_raw_mode = !(pterm_slave -> c_lflag & ICANON); myfree(pterm_slave); return in_raw_mode; }
/* returns TRUE if the -N option has been specified, we can read /proc/<command_pid>/wchan, (which happens only on linux, as far as I know) and what we read there contains the word "wait" meaning (presumably...) that command is waiting for one of its children if otherwise returns FALSE */ int dont_wrap_command_waits() { static char command_wchan[MAXPATHLEN+1]; static int initialised = FALSE; static int wchan_fd; static int been_warned = 0; char buffer[BUFFSIZE]; int nread, result = FALSE; DEBUG_RANDOM_SLEEP; if (!commands_children_not_wrapped) return FALSE; if (!initialised) { /* first time we're called after birth of child */ snprintf2(command_wchan, MAXPATHLEN , "%s/%d/wchan", PROC_MOUNTPOINT, command_pid); initialised = TRUE; } if (command_is_dead) return TRUE; /* This is lazy!! signal may not have been delivered @@@ */ wchan_fd = open(command_wchan, O_RDONLY); if (wchan_fd < 0) { if (been_warned++ == 0) { mywarn("you probably specified the -N (-no-children) option" " - but spying\non %s's wait status does not work on" " your system, as we cannot read %s", command_name, command_wchan); } return FALSE; } if (((nread = read(wchan_fd, buffer, BUFFSIZE -1)) > 0)) { buffer[nread] = '\0'; DPRINTF1(DEBUG_READLINE, "read commands wchan: <%s> ", buffer); result = (strstr(buffer, "wait") != NULL); } close(wchan_fd); DEBUG_RANDOM_SLEEP; return result; }
int read_alldata(FILE *f, FILE *ftag, Slice *s, int conp, int conv) /* Read all the data, including the tags if ftag!=NULL. */ /* Store positions and velocities unless conp or conv = 0 */ /* Assume that the data file header has been skipped, but read the tag file header. */ { int block; float *dummylist; dummylist = NULL; if (!conp || !conv) dummylist = vector(1,s->numperblock); if (s->pid!=NULL) mywarn("Non-NULL s->pid[] passed to read_alldata(). Ignoring..."); s->numlist=s->numpart; if (conp) { s->px=vector(1,s->numlist); s->py=vector(1,s->numlist); s->pz=vector(1,s->numlist); } if (conv) { s->vx=vector(1,s->numlist); s->vy=vector(1,s->numlist); s->vz=vector(1,s->numlist); } if (ftag!=NULL) s->ntag = ivector(1,s->numlist); printf("Reading data..."); for (block=0;block<s->numblocks;block++) { /* Read the three position blocks */ if (conp) { /* Store the data */ f77read(f, s->px+s->numperblock*block+1, s->numperblock*4); f77read(f, s->py+s->numperblock*block+1, s->numperblock*4); f77read(f, s->pz+s->numperblock*block+1, s->numperblock*4); } else { /* Don't store the data */ f77read(f, dummylist+1, s->numperblock*4); f77read(f, dummylist+1, s->numperblock*4); f77read(f, dummylist+1, s->numperblock*4); } /* Now read the three velocity blocks */ if (conv) { /* Store the data */ f77read(f, s->vx+s->numperblock*block+1, s->numperblock*4); f77read(f, s->vy+s->numperblock*block+1, s->numperblock*4); f77read(f, s->vz+s->numperblock*block+1, s->numperblock*4); } else { /* Don't store the data */ f77read(f, dummylist+1, s->numperblock*4); f77read(f, dummylist+1, s->numperblock*4); f77read(f, dummylist+1, s->numperblock*4); } if (block%8==1) {printf("."); fflush(stdout);} } if (dummylist!=NULL) free_vector(dummylist, 1, s->numperblock); normalizedata(s,conp,conv); if (ftag!=NULL) { printf("tags..."); fflush(stdout); readalltags(ftag, s); } printf("done!"); fflush(stdout); return 0; }
char * read_options_and_command_name(int argc, char **argv) { int c; char *opt_C = NULL; int option_count = 0; int opt_b = FALSE; int opt_f = FALSE; int remaining = -1; /* remaining number of arguments on command line */ int longindex = -1; /* index of current option in longopts[], set by getopt_long */ full_program_name = mysavestring(argv[0]); program_name = mybasename(full_program_name); /* normally "rlwrap"; needed by myerror() */ rl_basic_word_break_characters = " \t\n\r(){}[],+-=&^%$#@\";|\\"; opterr = 0; /* we do our own error reporting */ while (1) { #ifdef HAVE_GETOPT_LONG c = getopt_long(argc, argv, optstring, longopts, &longindex); #else c = getopt(argc, argv, optstring); #endif if (c == EOF) break; option_count++; last_option_didnt_have_optional_argument = FALSE; remaining = argc - optind; last_opt = c; switch (c) { case 'a': always_readline = TRUE; if (check_optarg('a', remaining)) password_prompt_search_string = mysavestring(optarg); break; case 'A': ansi_colour_aware = TRUE; break; case 'b': rl_basic_word_break_characters = add3strings("\r\n \t", optarg, ""); opt_b = TRUE; break; case 'c': complete_filenames = TRUE; break; case 'C': opt_C = mysavestring(optarg); break; case 'd': #ifdef DEBUG if (option_count > 1) myerror("-d or --debug option has to be the *first* rlwrap option"); if (check_optarg('d', remaining)) debug = atoi(optarg); else debug = DEBUG_DEFAULT; #else myerror ("To use -d( for debugging), configure %s with --enable-debug and rebuild", program_name); #endif break; case 'D': history_duplicate_avoidance_policy=atoi(optarg); if (history_duplicate_avoidance_policy < 0 || history_duplicate_avoidance_policy > 2) myerror("%s option with illegal value %d, should be 0, 1 or 2", current_option('D', longindex), history_duplicate_avoidance_policy); break; case 'f': if (strncmp(optarg, ".", 10) == 0) feed_history_into_completion_list = TRUE; else feed_file_into_completion_list(optarg); opt_f = TRUE; break; case 'F': myerror("The -F (--history-format) option is obsolete. Use -z \"history_format '%s'\" instead", optarg); case 'g': forget_regexp = mysavestring(optarg); match_regexp("just testing", forget_regexp, 1); break; case 'h': usage(EXIT_SUCCESS); /* will call exit() */ case 'H': history_filename = mysavestring(optarg); break; case 'i': if (opt_f) myerror("-i option has to precede -f options"); completion_is_case_sensitive = FALSE; break; case 'I': pass_on_sigINT_as_sigTERM = TRUE; break; case 'l': open_logfile(optarg); break; case 'n': nowarn = TRUE; break; case 'm': #ifndef HAVE_SYSTEM mywarn("the -m option doesn't work on this system"); #endif multiline_separator = (check_optarg('m', remaining) ? mysavestring(optarg) : " \\ "); break; case 'N': commands_children_not_wrapped = TRUE; break; case 'o': one_shot_rlwrap = TRUE; impatient_prompt = FALSE; wait_before_prompt = 200; break; case 'O': prompt_regexp = mysavestring(optarg); match_regexp("just testing", prompt_regexp, 1); break; case 'p': colour_the_prompt = TRUE; initialise_colour_codes(check_optarg('p', remaining) ? colour_name_to_ansi_code(optarg) : colour_name_to_ansi_code("Red")); break; case 'P': pre_given = mysavestring(optarg); always_readline = TRUE; /* pre_given does not work well with transparent mode */ break; case 'q': rl_basic_quote_characters = mysavestring(optarg); break; case 'r': remember_for_completion = TRUE; break; case 'R': renice = TRUE; break; case 's': histsize = atoi(optarg); if (histsize < 0) { write_histfile = 0; histsize = -histsize; } break; case 'S': substitute_prompt = mysavestring(optarg);break; case 't': client_term_name=mysavestring(optarg);break; #ifdef DEBUG case 'T': test_terminal(); exit(EXIT_SUCCESS); #endif case 'v': printf("rlwrap %s\n", VERSION); exit(EXIT_SUCCESS); case 'w': wait_before_prompt = atoi(optarg); if (wait_before_prompt < 0) { wait_before_prompt *= -1; impatient_prompt = FALSE; } break; case 'z': filter_command = mysavestring(optarg); break; case '?': assert(optind > 0); myerror("unrecognised option %s\ntry '%s --help' for more information", argv[optind-1], full_program_name); case ':': assert(optind > 0); myerror ("option %s requires an argument \ntry '%s --help' for more information", argv[optind-1], full_program_name); default: usage(EXIT_FAILURE); } } if (!complete_filenames && !opt_b) { /* use / and . as default breaking characters whenever we don't complete filenames */ rl_basic_word_break_characters = add2strings(rl_basic_word_break_characters, "/."); } if (optind >= argc) { /* rlwrap -a -b -c with no command specified */ if (filter_command) { /* rlwrap -z filter with no command specified */ mysignal(SIGALRM, &handle_sigALRM); /* needed for read_patiently2 */ spawn_filter(filter_command); pass_through_filter(TAG_OUTPUT,""); /* ignore result but allow TAG_OUTPUT_OUT_OF_BAND */ cleanup_rlwrap_and_exit(EXIT_SUCCESS); } else { usage(EXIT_FAILURE); } } if (opt_C) { int countback = atoi(opt_C); /* investigate whether -C option argument is numeric */ if (countback > 0) { /* e.g -C 1 or -C 12 */ if (argc - countback < optind) /* -C 666 */ myerror("when using -C %d you need at least %d non-option arguments", countback, countback); else if (argv[argc - countback][0] == '-') /* -C 2 perl -d blah.pl */ myerror("the last argument minus %d appears to be an option!", countback); else { /* -C 1 perl test.cgi */ command_name = mysavestring(mybasename(argv[argc - countback])); } } else if (countback == 0) { /* -C name1 name2 or -C 0 */ if (opt_C[0] == '0' && opt_C[1] == '\0') /* -C 0 */ myerror("-C 0 makes no sense"); else if (strlen(mybasename(opt_C)) != strlen(opt_C)) /* -C dir/name */ myerror("-C option argument should not contain directory components"); else if (opt_C[0] == '-') /* -C -d (?) */ myerror("-C option needs argument"); else /* -C name */ command_name = opt_C; } else { /* -C -2 */ myerror ("-C option needs string or positive number as argument, perhaps you meant -C %d?", -countback); } } else { /* no -C option given, use command name */ command_name = mysavestring(mybasename(argv[optind])); } assert(command_name != NULL); return command_name; }