119304Speter/*- 219304Speter * Copyright (c) 1992, 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 1319304Speterstatic const char copyright[] = 14258231Sgjb"@(#) Copyright (c) 1992, 1993, 1994\n\ 1519304Speter The Regents of the University of California. All rights reserved.\n\ 16258231Sgjb@(#) Copyright (c) 1992, 1993, 1994, 1995, 1996\n\ 1719304Speter Keith Bostic. All rights reserved.\n"; 1819304Speter#endif /* not lint */ 1919304Speter 2019304Speter#ifndef lint 21254225Speterstatic const char sccsid[] = "$Id: main.c,v 11.0 2012/10/17 06:34:37 zy Exp $"; 2219304Speter#endif /* not lint */ 2319304Speter 2419304Speter#include <sys/types.h> 2519304Speter#include <sys/queue.h> 2619304Speter#include <sys/stat.h> 2719304Speter 2819304Speter#include <bitstring.h> 2919304Speter#include <errno.h> 3019304Speter#include <fcntl.h> 3119304Speter#include <limits.h> 3219304Speter#include <stdio.h> 3319304Speter#include <stdlib.h> 3419304Speter#include <string.h> 3519304Speter#include <unistd.h> 3619304Speter 3719304Speter#include "common.h" 3819304Speter#include "../vi/vi.h" 3919304Speter#include "pathnames.h" 4019304Speter 4119304Speterstatic void attach __P((GS *)); 4219304Speterstatic void v_estr __P((char *, int, char *)); 4319304Speterstatic int v_obsolete __P((char *, char *[])); 4419304Speter 4519304Speter/* 4619304Speter * editor -- 4719304Speter * Main editor routine. 4819304Speter * 4919304Speter * PUBLIC: int editor __P((GS *, int, char *[])); 5019304Speter */ 5119304Speterint 52254225Spetereditor( 53254225Speter GS *gp, 54254225Speter int argc, 55254225Speter char *argv[]) 5619304Speter{ 5719304Speter extern int optind; 5819304Speter extern char *optarg; 5919304Speter const char *p; 6019304Speter EVENT ev; 6119304Speter FREF *frp; 6219304Speter SCR *sp; 6319304Speter size_t len; 6419304Speter u_int flags; 6519304Speter int ch, flagchk, lflag, secure, startup, readonly, rval, silent; 6619304Speter char *tag_f, *wsizearg, path[256]; 67254225Speter CHAR_T *w; 68254225Speter size_t wlen; 6919304Speter 7019304Speter /* Initialize the busy routine, if not defined by the screen. */ 7119304Speter if (gp->scr_busy == NULL) 7219304Speter gp->scr_busy = vs_busy; 7319304Speter /* Initialize the message routine, if not defined by the screen. */ 7419304Speter if (gp->scr_msg == NULL) 7519304Speter gp->scr_msg = vs_msg; 76254225Speter gp->catd = (nl_catd)-1; 7719304Speter 7819304Speter /* Common global structure initialization. */ 79254225Speter TAILQ_INIT(gp->dq); 80254225Speter TAILQ_INIT(gp->hq); 81254225Speter SLIST_INIT(gp->ecq); 82254225Speter SLIST_INSERT_HEAD(gp->ecq, &gp->excmd, q); 8319304Speter gp->noprint = DEFAULT_NOPRINT; 8419304Speter 8519304Speter /* Structures shared by screens so stored in the GS structure. */ 86254225Speter TAILQ_INIT(gp->frefq); 87254225Speter TAILQ_INIT(gp->dcb_store.textq); 88254225Speter SLIST_INIT(gp->cutq); 89254225Speter SLIST_INIT(gp->seqq); 9019304Speter 9119304Speter /* Set initial screen type and mode based on the program name. */ 9219304Speter readonly = 0; 9319304Speter if (!strcmp(gp->progname, "ex") || !strcmp(gp->progname, "nex")) 9419304Speter LF_INIT(SC_EX); 9519304Speter else { 9619304Speter /* Nview, view are readonly. */ 9719304Speter if (!strcmp(gp->progname, "nview") || 9819304Speter !strcmp(gp->progname, "view")) 9919304Speter readonly = 1; 10019304Speter 10119304Speter /* Vi is the default. */ 10219304Speter LF_INIT(SC_VI); 10319304Speter } 10419304Speter 10519304Speter /* Convert old-style arguments into new-style ones. */ 10619304Speter if (v_obsolete(gp->progname, argv)) 10719304Speter return (1); 10819304Speter 10919304Speter /* Parse the arguments. */ 11019304Speter flagchk = '\0'; 11119304Speter tag_f = wsizearg = NULL; 11219304Speter lflag = secure = silent = 0; 11319304Speter startup = 1; 11419304Speter 11519304Speter /* Set the file snapshot flag. */ 11619304Speter F_SET(gp, G_SNAPSHOT); 11719304Speter 11819304Speter#ifdef DEBUG 11919304Speter while ((ch = getopt(argc, argv, "c:D:eFlRrSsT:t:vw:")) != EOF) 12019304Speter#else 12119304Speter while ((ch = getopt(argc, argv, "c:eFlRrSst:vw:")) != EOF) 12219304Speter#endif 12319304Speter switch (ch) { 12419304Speter case 'c': /* Run the command. */ 12519304Speter /* 12619304Speter * XXX 12719304Speter * We should support multiple -c options. 12819304Speter */ 12919304Speter if (gp->c_option != NULL) { 13019304Speter v_estr(gp->progname, 0, 13119304Speter "only one -c command may be specified."); 13219304Speter return (1); 13319304Speter } 13419304Speter gp->c_option = optarg; 13519304Speter break; 13619304Speter#ifdef DEBUG 13719304Speter case 'D': 13819304Speter switch (optarg[0]) { 13919304Speter case 's': 14019304Speter startup = 0; 14119304Speter break; 14219304Speter case 'w': 14319304Speter attach(gp); 14419304Speter break; 14519304Speter default: 14619304Speter v_estr(gp->progname, 0, 14719304Speter "usage: -D requires s or w argument."); 14819304Speter return (1); 14919304Speter } 15019304Speter break; 15119304Speter#endif 15219304Speter case 'e': /* Ex mode. */ 15319304Speter LF_CLR(SC_VI); 15419304Speter LF_SET(SC_EX); 15519304Speter break; 15619304Speter case 'F': /* No snapshot. */ 15719304Speter F_CLR(gp, G_SNAPSHOT); 15819304Speter break; 15919304Speter case 'l': /* Set lisp, showmatch options. */ 16019304Speter lflag = 1; 16119304Speter break; 16219304Speter case 'R': /* Readonly. */ 16319304Speter readonly = 1; 16419304Speter break; 16519304Speter case 'r': /* Recover. */ 16619304Speter if (flagchk == 't') { 16719304Speter v_estr(gp->progname, 0, 16819304Speter "only one of -r and -t may be specified."); 16919304Speter return (1); 17019304Speter } 17119304Speter flagchk = 'r'; 17219304Speter break; 17319304Speter case 'S': 17419304Speter secure = 1; 17519304Speter break; 17619304Speter case 's': 17719304Speter silent = 1; 17819304Speter break; 17919304Speter#ifdef DEBUG 18019304Speter case 'T': /* Trace. */ 18119304Speter if ((gp->tracefp = fopen(optarg, "w")) == NULL) { 18219304Speter v_estr(gp->progname, errno, optarg); 18319304Speter goto err; 18419304Speter } 18519304Speter (void)fprintf(gp->tracefp, 18619304Speter "\n===\ntrace: open %s\n", optarg); 18719304Speter break; 18819304Speter#endif 18919304Speter case 't': /* Tag. */ 19019304Speter if (flagchk == 'r') { 19119304Speter v_estr(gp->progname, 0, 19219304Speter "only one of -r and -t may be specified."); 19319304Speter return (1); 19419304Speter } 19519304Speter if (flagchk == 't') { 19619304Speter v_estr(gp->progname, 0, 19719304Speter "only one tag file may be specified."); 19819304Speter return (1); 19919304Speter } 20019304Speter flagchk = 't'; 20119304Speter tag_f = optarg; 20219304Speter break; 20319304Speter case 'v': /* Vi mode. */ 20419304Speter LF_CLR(SC_EX); 20519304Speter LF_SET(SC_VI); 20619304Speter break; 20719304Speter case 'w': 20819304Speter wsizearg = optarg; 20919304Speter break; 21019304Speter case '?': 21119304Speter default: 21219304Speter (void)gp->scr_usage(); 21319304Speter return (1); 21419304Speter } 21519304Speter argc -= optind; 21619304Speter argv += optind; 21719304Speter 21819304Speter /* 21919304Speter * -s option is only meaningful to ex. 22019304Speter * 22119304Speter * If not reading from a terminal, it's like -s was specified. 22219304Speter */ 22319304Speter if (silent && !LF_ISSET(SC_EX)) { 22419304Speter v_estr(gp->progname, 0, "-s option is only applicable to ex."); 22519304Speter goto err; 22619304Speter } 22719304Speter if (LF_ISSET(SC_EX) && F_ISSET(gp, G_SCRIPTED)) 22819304Speter silent = 1; 22919304Speter 23019304Speter /* 23119304Speter * Build and initialize the first/current screen. This is a bit 23219304Speter * tricky. If an error is returned, we may or may not have a 23319304Speter * screen structure. If we have a screen structure, put it on a 23419304Speter * display queue so that the error messages get displayed. 23519304Speter * 23619304Speter * !!! 23719304Speter * Everything we do until we go interactive is done in ex mode. 23819304Speter */ 23919304Speter if (screen_init(gp, NULL, &sp)) { 24019304Speter if (sp != NULL) 241254225Speter TAILQ_INSERT_HEAD(gp->dq, sp, q); 24219304Speter goto err; 24319304Speter } 24419304Speter F_SET(sp, SC_EX); 245254225Speter TAILQ_INSERT_HEAD(gp->dq, sp, q); 24619304Speter 24719304Speter if (v_key_init(sp)) /* Special key initialization. */ 24819304Speter goto err; 24919304Speter 25019304Speter { int oargs[5], *oargp = oargs; 25119304Speter if (lflag) { /* Command-line options. */ 25219304Speter *oargp++ = O_LISP; 25319304Speter *oargp++ = O_SHOWMATCH; 25419304Speter } 25519304Speter if (readonly) 25619304Speter *oargp++ = O_READONLY; 25719304Speter if (secure) 25819304Speter *oargp++ = O_SECURE; 25919304Speter *oargp = -1; /* Options initialization. */ 26019304Speter if (opts_init(sp, oargs)) 26119304Speter goto err; 26219304Speter } 26319304Speter if (wsizearg != NULL) { 26419304Speter ARGS *av[2], a, b; 26519304Speter (void)snprintf(path, sizeof(path), "window=%s", wsizearg); 26619304Speter a.bp = (CHAR_T *)path; 26719304Speter a.len = strlen(path); 26819304Speter b.bp = NULL; 26919304Speter b.len = 0; 27019304Speter av[0] = &a; 27119304Speter av[1] = &b; 27219304Speter (void)opts_set(sp, av, NULL); 27319304Speter } 27419304Speter if (silent) { /* Ex batch mode option values. */ 27519304Speter O_CLR(sp, O_AUTOPRINT); 27619304Speter O_CLR(sp, O_PROMPT); 27719304Speter O_CLR(sp, O_VERBOSE); 27819304Speter O_CLR(sp, O_WARN); 27919304Speter F_SET(sp, SC_EX_SILENT); 28019304Speter } 28119304Speter 28219304Speter sp->rows = O_VAL(sp, O_LINES); /* Make ex formatting work. */ 28319304Speter sp->cols = O_VAL(sp, O_COLUMNS); 28419304Speter 28519304Speter if (!silent && startup) { /* Read EXINIT, exrc files. */ 28619304Speter if (ex_exrc(sp)) 28719304Speter goto err; 28819304Speter if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) { 28919304Speter if (screen_end(sp)) 29019304Speter goto err; 29119304Speter goto done; 29219304Speter } 29319304Speter } 29419304Speter 29519304Speter /* 29619304Speter * List recovery files if -r specified without file arguments. 29719304Speter * Note, options must be initialized and startup information 29819304Speter * read before doing this. 29919304Speter */ 30019304Speter if (flagchk == 'r' && argv[0] == NULL) { 30119304Speter if (rcv_list(sp)) 30219304Speter goto err; 30319304Speter if (screen_end(sp)) 30419304Speter goto err; 30519304Speter goto done; 30619304Speter } 30719304Speter 30819304Speter /* 30919304Speter * !!! 31019304Speter * Initialize the default ^D, ^U scrolling value here, after the 31119304Speter * user has had every opportunity to set the window option. 31219304Speter * 31319304Speter * It's historic practice that changing the value of the window 31419304Speter * option did not alter the default scrolling value, only giving 31519304Speter * a count to ^D/^U did that. 31619304Speter */ 31719304Speter sp->defscroll = (O_VAL(sp, O_WINDOW) + 1) / 2; 31819304Speter 31919304Speter /* 32019304Speter * If we don't have a command-line option, switch into the right 32119304Speter * editor now, so that we position default files correctly, and 32219304Speter * so that any tags file file-already-locked messages are in the 32319304Speter * vi screen, not the ex screen. 32419304Speter * 32519304Speter * XXX 32619304Speter * If we have a command-line option, the error message can end 32719304Speter * up in the wrong place, but I think that the combination is 32819304Speter * unlikely. 32919304Speter */ 33019304Speter if (gp->c_option == NULL) { 33119304Speter F_CLR(sp, SC_EX | SC_VI); 33219304Speter F_SET(sp, LF_ISSET(SC_EX | SC_VI)); 33319304Speter } 33419304Speter 33519304Speter /* Open a tag file if specified. */ 336254225Speter if (tag_f != NULL) { 337254225Speter CHAR2INT(sp, tag_f, strlen(tag_f) + 1, w, wlen); 338254225Speter if (ex_tag_first(sp, w)) 339254225Speter goto err; 340254225Speter } 34119304Speter 34219304Speter /* 34319304Speter * Append any remaining arguments as file names. Files are recovery 34419304Speter * files if -r specified. If the tag option or ex startup commands 34519304Speter * loaded a file, then any file arguments are going to come after it. 34619304Speter */ 34719304Speter if (*argv != NULL) { 34819304Speter if (sp->frp != NULL) { 34919304Speter /* Cheat -- we know we have an extra argv slot. */ 350254225Speter *--argv = strdup(sp->frp->name); 35119304Speter if (*argv == NULL) { 35219304Speter v_estr(gp->progname, errno, NULL); 35319304Speter goto err; 35419304Speter } 35519304Speter } 35619304Speter sp->argv = sp->cargv = argv; 35719304Speter F_SET(sp, SC_ARGNOFREE); 35819304Speter if (flagchk == 'r') 35919304Speter F_SET(sp, SC_ARGRECOVER); 36019304Speter } 36119304Speter 36219304Speter /* 36319304Speter * If the ex startup commands and or/the tag option haven't already 36419304Speter * created a file, create one. If no command-line files were given, 36519304Speter * use a temporary file. 36619304Speter */ 36719304Speter if (sp->frp == NULL) { 36819304Speter if (sp->argv == NULL) { 36919304Speter if ((frp = file_add(sp, NULL)) == NULL) 37019304Speter goto err; 37119304Speter } else { 372254225Speter if ((frp = file_add(sp, sp->argv[0])) == NULL) 37319304Speter goto err; 37419304Speter if (F_ISSET(sp, SC_ARGRECOVER)) 37519304Speter F_SET(frp, FR_RECOVER); 37619304Speter } 37719304Speter 37819304Speter if (file_init(sp, frp, NULL, 0)) 37919304Speter goto err; 38019304Speter if (EXCMD_RUNNING(gp)) { 38119304Speter (void)ex_cmd(sp); 38219304Speter if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) { 38319304Speter if (screen_end(sp)) 38419304Speter goto err; 38519304Speter goto done; 38619304Speter } 38719304Speter } 38819304Speter } 38919304Speter 39019304Speter /* 39119304Speter * Check to see if we need to wait for ex. If SC_SCR_EX is set, ex 39219304Speter * was forced to initialize the screen during startup. We'd like to 39319304Speter * wait for a single character from the user, but we can't because 39419304Speter * we're not in raw mode. We can't switch to raw mode because the 39519304Speter * vi initialization will switch to xterm's alternate screen, causing 39619304Speter * us to lose the messages we're pausing to make sure the user read. 39719304Speter * So, wait for a complete line. 39819304Speter */ 39919304Speter if (F_ISSET(sp, SC_SCR_EX)) { 40019304Speter p = msg_cmsg(sp, CMSG_CONT_R, &len); 40119304Speter (void)write(STDOUT_FILENO, p, len); 40219304Speter for (;;) { 40319304Speter if (v_event_get(sp, &ev, 0, 0)) 40419304Speter goto err; 40519304Speter if (ev.e_event == E_INTERRUPT || 406254225Speter (ev.e_event == E_CHARACTER && 407254225Speter (ev.e_value == K_CR || ev.e_value == K_NL))) 40819304Speter break; 40919304Speter (void)gp->scr_bell(sp); 41019304Speter } 41119304Speter } 41219304Speter 41319304Speter /* Switch into the right editor, regardless. */ 41419304Speter F_CLR(sp, SC_EX | SC_VI); 41519304Speter F_SET(sp, LF_ISSET(SC_EX | SC_VI) | SC_STATUS_CNT); 41619304Speter 41719304Speter /* 41819304Speter * Main edit loop. Vi handles split screens itself, we only return 41919304Speter * here when switching editor modes or restarting the screen. 42019304Speter */ 42119304Speter while (sp != NULL) 42219304Speter if (F_ISSET(sp, SC_EX) ? ex(&sp) : vi(&sp)) 42319304Speter goto err; 42419304Speter 42519304Speterdone: rval = 0; 42619304Speter if (0) 42719304Spetererr: rval = 1; 42819304Speter 42919304Speter /* Clean out the global structure. */ 43019304Speter v_end(gp); 43119304Speter 43219304Speter return (rval); 43319304Speter} 43419304Speter 43519304Speter/* 43619304Speter * v_end -- 43719304Speter * End the program, discarding screens and most of the global area. 43819304Speter * 43919304Speter * PUBLIC: void v_end __P((GS *)); 44019304Speter */ 44119304Spetervoid 44219304Speterv_end(gp) 44319304Speter GS *gp; 44419304Speter{ 44519304Speter MSGS *mp; 44619304Speter SCR *sp; 44719304Speter 44819304Speter /* If there are any remaining screens, kill them off. */ 44919304Speter if (gp->ccl_sp != NULL) { 45019304Speter (void)file_end(gp->ccl_sp, NULL, 1); 45119304Speter (void)screen_end(gp->ccl_sp); 45219304Speter } 453254225Speter while ((sp = TAILQ_FIRST(gp->dq)) != NULL) 45419304Speter (void)screen_end(sp); 455254225Speter while ((sp = TAILQ_FIRST(gp->hq)) != NULL) 45619304Speter (void)screen_end(sp); 45719304Speter 45819304Speter#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY) 45919304Speter { FREF *frp; 46019304Speter /* Free FREF's. */ 461254225Speter while ((frp = TAILQ_FIRST(gp->frefq)) != NULL) { 462254225Speter TAILQ_REMOVE(gp->frefq, frp, q); 46319304Speter if (frp->name != NULL) 46419304Speter free(frp->name); 46519304Speter if (frp->tname != NULL) 46619304Speter free(frp->tname); 46719304Speter free(frp); 46819304Speter } 46919304Speter } 47019304Speter 47119304Speter /* Free key input queue. */ 47219304Speter if (gp->i_event != NULL) 47319304Speter free(gp->i_event); 47419304Speter 47519304Speter /* Free cut buffers. */ 47619304Speter cut_close(gp); 47719304Speter 47819304Speter /* Free map sequences. */ 47919304Speter seq_close(gp); 48019304Speter 48119304Speter /* Free default buffer storage. */ 482254225Speter (void)text_lfree(gp->dcb_store.textq); 48319304Speter 48419304Speter /* Close message catalogs. */ 48519304Speter msg_close(gp); 48619304Speter#endif 48719304Speter 48819304Speter /* Ring the bell if scheduled. */ 48919304Speter if (F_ISSET(gp, G_BELLSCHED)) 49019304Speter (void)fprintf(stderr, "\07"); /* \a */ 49119304Speter 49219304Speter /* 49319304Speter * Flush any remaining messages. If a message is here, it's almost 49419304Speter * certainly the message about the event that killed us (although 49519304Speter * it's possible that the user is sourcing a file that exits from the 49619304Speter * editor). 49719304Speter */ 498254225Speter while ((mp = SLIST_FIRST(gp->msgq)) != NULL) { 49919304Speter (void)fprintf(stderr, "%s%.*s", 50019304Speter mp->mtype == M_ERR ? "ex/vi: " : "", (int)mp->len, mp->buf); 501254225Speter SLIST_REMOVE_HEAD(gp->msgq, q); 50219304Speter#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY) 50319304Speter free(mp->buf); 50419304Speter free(mp); 50519304Speter#endif 50619304Speter } 50719304Speter 50819304Speter#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY) 50919304Speter /* Free any temporary space. */ 51019304Speter if (gp->tmp_bp != NULL) 51119304Speter free(gp->tmp_bp); 51219304Speter 51319304Speter#if defined(DEBUG) 51419304Speter /* Close debugging file descriptor. */ 51519304Speter if (gp->tracefp != NULL) 51619304Speter (void)fclose(gp->tracefp); 51719304Speter#endif 51819304Speter#endif 51919304Speter} 52019304Speter 52119304Speter/* 52219304Speter * v_obsolete -- 52319304Speter * Convert historic arguments into something getopt(3) will like. 52419304Speter */ 52519304Speterstatic int 526254225Speterv_obsolete( 527254225Speter char *name, 528254225Speter char *argv[]) 52919304Speter{ 53019304Speter size_t len; 53119304Speter char *p; 53219304Speter 53319304Speter /* 53419304Speter * Translate old style arguments into something getopt will like. 53519304Speter * Make sure it's not text space memory, because ex modifies the 53619304Speter * strings. 53719304Speter * Change "+" into "-c$". 53819304Speter * Change "+<anything else>" into "-c<anything else>". 53919304Speter * Change "-" into "-s" 54019304Speter * The c, T, t and w options take arguments so they can't be 54119304Speter * special arguments. 54219304Speter * 54319304Speter * Stop if we find "--" as an argument, the user may want to edit 54419304Speter * a file named "+foo". 54519304Speter */ 54619304Speter while (*++argv && strcmp(argv[0], "--")) 54719304Speter if (argv[0][0] == '+') { 54819304Speter if (argv[0][1] == '\0') { 549254225Speter argv[0] = strdup("-c$"); 55019304Speter if (argv[0] == NULL) 55119304Speter goto nomem; 55219304Speter } else { 55319304Speter p = argv[0]; 55419304Speter len = strlen(argv[0]); 555254225Speter argv[0] = malloc(len + 2); 55619304Speter if (argv[0] == NULL) 55719304Speter goto nomem; 55819304Speter argv[0][0] = '-'; 55919304Speter argv[0][1] = 'c'; 560254225Speter (void)strlcpy(argv[0] + 2, p + 1, len); 56119304Speter } 56219304Speter } else if (argv[0][0] == '-') 56319304Speter if (argv[0][1] == '\0') { 564254225Speter argv[0] = strdup("-s"); 56519304Speter if (argv[0] == NULL) { 56619304Speternomem: v_estr(name, errno, NULL); 56719304Speter return (1); 56819304Speter } 56919304Speter } else 57019304Speter if ((argv[0][1] == 'c' || argv[0][1] == 'T' || 57119304Speter argv[0][1] == 't' || argv[0][1] == 'w') && 57219304Speter argv[0][2] == '\0') 57319304Speter ++argv; 57419304Speter return (0); 57519304Speter} 57619304Speter 57719304Speter#ifdef DEBUG 57819304Speterstatic void 579254225Speterattach(GS *gp) 58019304Speter{ 58119304Speter int fd; 58219304Speter char ch; 58319304Speter 58419304Speter if ((fd = open(_PATH_TTY, O_RDONLY, 0)) < 0) { 58519304Speter v_estr(gp->progname, errno, _PATH_TTY); 58619304Speter return; 58719304Speter } 58819304Speter 58919304Speter (void)printf("process %lu waiting, enter <CR> to continue: ", 59019304Speter (u_long)getpid()); 59119304Speter (void)fflush(stdout); 59219304Speter 59319304Speter do { 59419304Speter if (read(fd, &ch, 1) != 1) { 59519304Speter (void)close(fd); 59619304Speter return; 59719304Speter } 59819304Speter } while (ch != '\n' && ch != '\r'); 59919304Speter (void)close(fd); 60019304Speter} 60119304Speter#endif 60219304Speter 60319304Speterstatic void 604254225Speterv_estr( 605254225Speter char *name, 606254225Speter int eno, 607254225Speter char *msg) 60819304Speter{ 60919304Speter (void)fprintf(stderr, "%s", name); 61019304Speter if (msg != NULL) 61119304Speter (void)fprintf(stderr, ": %s", msg); 61219304Speter if (eno) 61319304Speter (void)fprintf(stderr, ": %s", strerror(errno)); 61419304Speter (void)fprintf(stderr, "\n"); 61519304Speter} 616