#pragma noroot #include "less.h" #if __MSDOS__ #include #include #include #include #endif #ifdef _ORCAC_ #include #include segment "LoadSegONE"; #endif #define ISPIPE(fd) ((fd)==STDIN_FILENO) extern int ispipe; extern int new_file; extern int errmsgs; extern int quit_at_eof; extern int file; extern int cbufs; extern char *every_first_cmd; extern int any_display; extern int force_open; extern int is_tty; extern IFILE curr_ifile; extern IFILE old_ifile; extern struct scrpos initial_scrpos; #if LOGFILE extern int logfile; extern int force_logfile; extern char *namelogfile; #endif /* * Edit a new file. * Filename == "-" means standard input. * Filename == NULL means just close the current file. */ public int edit(filename, just_looking) register char *filename; int just_looking; { register int f; char *s; int answer; int no_display; struct scrpos scrpos; PARG parg; if (filename == NULL) { /* * Close the current file, but don't open a new one. */ f = -1; } else if (strcmp(filename, "-") == 0) { /* * Use standard input. */ f = STDIN_FILENO; } else if ((parg.p_string = bad_file(filename)) != NULL) { error("\r%s\r", &parg); free(parg.p_string); return (1); #if __MSDOS__ } else if ((f = open(filename, O_RDONLY|O_BINARY)) < 0) #else /* } else if ((f = open(filename, 0)) < 0)*/ } else if ((f = open(filename, O_RDONLY|O_BINARY)) < 0) #endif { parg.p_string = errno_message(filename); error("%s", &parg); free(parg.p_string); return (1); } else if (!force_open && !just_looking && bin_file(f)) { parg.p_string = filename; answer = query("\"%s\" may be a binary file. Continue? ", &parg); if (answer != 'y' && answer != 'Y') { close(f); return (1); } } if (f >= 0 && isatty(f)) { /* * Not really necessary to call this an error, * but if the control terminal (for commands) * and the input file (for data) are the same, * we get weird results at best. */ #if __MSDOS__ parg.p_string = "less -?"; #else parg.p_string = "less -\\?"; #endif error("Cannot take input from a terminal (\"%s\" for help)", &parg); if (!ISPIPE(f)) close(f); return (1); } #if LOGFILE s = namelogfile; end_logfile(); if (f >= 0 && ISPIPE(f) && s != NULL && is_tty) use_logfile(s); #endif /* * We are now committed to using the new file. * Close the current input file and set up to use the new one. */ if (curr_ifile != NULL_IFILE) { /* * Save the current position so that we can return to * the same position if we edit this file again. */ get_scrpos(&scrpos); if (scrpos.pos != NULL_POSITION) { store_pos(curr_ifile, &scrpos); lastmark(); } } /* * Close the current file, unless it is a pipe. */ if (!ISPIPE(file)) close(file); file = f; if (f < 0) return (1); /* * Get the new ifile. * Get the saved position for that file. */ old_ifile = curr_ifile; curr_ifile = get_ifile(filename, curr_ifile); get_pos(curr_ifile, &initial_scrpos); ispipe = ISPIPE(f); if (ispipe) ch_pipe(); else ch_nonpipe(); (void) ch_nbuf(cbufs); ch_flush(); new_file = 1; #if __MSDOS__ top_filename(); #endif if (every_first_cmd != NULL) ungetsc(every_first_cmd); no_display = !any_display; flush(); any_display = 1; if (is_tty) { /* * Output is to a real tty. */ /* * Indicate there is nothing displayed yet. */ pos_clear(); clr_linenum(); if (no_display && errmsgs > 0) { /* * We displayed some messages on error output * (file descriptor 2; see error() function). * Before erasing the screen contents, * display the file name and wait for a keystroke. */ parg.p_string = filename; error("%s", &parg); } } return (0); } /* * Edit a space-separated list of files. * For each filename in the list, enter it into the ifile list. * Then edit the first one. */ public void edit_list(list) char *list; { register char *s; register char *es; register char *filename; char *good_filename; IFILE save_curr_ifile; /* * good_filename keeps track of the first valid filename. */ good_filename = NULL; s = list; es = s + strlen(s); save_curr_ifile = curr_ifile; while ((s = skipsp(s)) < es) { /* * Get the next filename and null terminate it. */ filename = s; while (*s != ' ' && *s != '\0') s++; if (*s != '\0') *s++ = '\0'; /* * Try to edit the file. * This enters it into the command line list (if it is good). * If it is the first good file we've seen, remember it. * {{ A little weirdness here: if any of the filenames * are already in the list, subsequent ones get * entered after the position where that one already * was, instead of at the end. }} */ if (edit(filename, 1) == 0 && good_filename == NULL) good_filename = filename; } /* * Edit the first valid filename in the list. */ if (good_filename != NULL) { curr_ifile = save_curr_ifile; (void) edit(good_filename, 0); } } /* * Edit the first file in the command line (ifile) list. */ public int edit_first(void) { curr_ifile = NULL_IFILE; return (edit_next(1)); } /* * Edit the last file in the command line (ifile) list. */ public int edit_last(void) { curr_ifile = NULL_IFILE; return (edit_prev(1)); } /* * Edit the next file in the command line (ifile) list. */ public int edit_next(n) int n; { IFILE h; h = curr_ifile; while (--n >= 0 || edit(get_filename(h), 0)) { if ((h = next_ifile(h)) == NULL_IFILE) /* * Reached end of the ifile list. */ return (1); } /* * Found a file that we can edit. */ return (0); } /* * Edit the previous file in the command line list. */ public int edit_prev(n) int n; { IFILE h; h = curr_ifile; while (--n >= 0 || edit(get_filename(h), 0)) { if ((h = prev_ifile(h)) == NULL_IFILE) /* * Reached beginning of the ifile list. */ return (1); } /* * Found a file that we can edit. */ return (0); } /* * Edit a specific file in the command line (ifile) list. */ public int edit_index(n) int n; { IFILE h; h = NULL_IFILE; do { if ((h = next_ifile(h)) == NULL_IFILE) { /* * Reached end of the list without finding it. */ return (1); } } while (get_index(h) != n); return (edit(get_filename(h), 0)); } /* * Copy a file directly to standard output. * Used if standard output is not a tty. */ public void cat_file(void) { register int c; while ((c = ch_forw_get()) != EOI) putchr(c); flush(); } #if LOGFILE /* * If the user asked for a log file and our input file * is standard input, create the log file. * We take care not to blindly overwrite an existing file. */ public void use_logfile(filename) char *filename; { register int exists; register int answer; PARG parg; /* * {{ We could use access() here. }} */ /* exists = open(filename, 0);*/ exists = open(filename, O_RDWR); close(exists); exists = (exists >= 0); /* * Decide whether to overwrite the log file or append to it. * (If it doesn't exist we "overwrite" it. */ if (!exists || force_logfile) { /* * Overwrite (or create) the log file. */ answer = 'O'; } else { /* * Ask user what to do. */ parg.p_string = filename; answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg); } loop: switch (answer) { case 'O': case 'o': /* * Overwrite: create the file. */ logfile = creat(filename, 0644); break; case 'A': case 'a': /* * Append: open the file and seek to the end. */ #if __MSDOS__ logfile = open(filename, O_APPEND|O_WRONLY); #else /* logfile = open(filename, 1);*/ logfile = open(filename, O_APPEND|O_WRONLY); #endif if (lseek(logfile, (offset_t)0, 2) == BAD_LSEEK) { close(logfile); logfile = -1; } break; case 'D': case 'd': /* * Don't do anything. */ return; case 'q': quit(0); /*NOTREACHED*/ default: /* * Eh? */ answer = query("Overwrite, Append, or Don't log? ", NULL_PARG); goto loop; } if (logfile < 0) { /* * Error in opening logfile. */ parg.p_string = filename; error("Cannot write to \"%s\"", &parg); } } #endif