]>
diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/vmh.c
1 /* vmh.c - visual front-end to mh */
3 static char ident
[] = "@(#)$Id: vmh.c,v 1.20 1993/08/25 17:29:44 jromine Exp $";
5 #if defined(SYS5) && !defined(TERMINFO)
7 * Define TERMINFO if you have it.
8 * You get it automatically if you're running SYS5, and you don't get
9 * it if you're not. (If you're not SYS5, you probably have termcap.)
10 * We distinguish TERMINFO from SYS5 because in this file SYS5 really
11 * means "AT&T line discipline" (termio, not sgttyb), whereas terminfo
12 * is quite a separate issue.
18 Pass signals to client during execution
20 Figure out a way for the user to say how big the Scan/Display
23 If curses ever gets fixed, then XYZ code can be removed
28 #define _SYS_REG_H /* NCR redefines "ERR" in <sys/reg.h> */
30 #undef OK /* tricky */
32 #include <term.h> /* variables describing terminal capabilities */
35 #include "../h/vmhsbr.h"
41 #define sigmask(s) (1 << ((s) - 1))
42 #endif /* not sigmask */
52 #include <sys/types.h>
60 #define TCGETATTR /* tcgetattr() */
64 #define _maxx maxx /* curses.h */
66 #define _curx curx /* curses.h */
68 void __cputchar
__P((int));
70 #define _putchar __cputchar
71 #include <sys/ioctl.h> /* sgttyb */
74 #define ALARM ((unsigned int) 10)
75 #define PAUSE ((unsigned int) 2)
78 #define abs(a) ((a) > 0 ? (a) : -(a))
88 static struct swit switches
[] = {
105 static int PEERpid
= NOTOK
;
107 static jmp_buf PEERctx
;
111 static char *myprompt
= "(%s) ";
114 static WINDOW
*Status
;
115 static WINDOW
*Display
;
116 static WINDOW
*Command
;
120 WINDOW
*windows
[NWIN
+ 1];
132 static struct line
*lhead
= NULL
;
133 static struct line
*ltop
= NULL
;
134 static struct line
*ltail
= NULL
;
136 static int did_less
= 0;
137 static int smallmove
= SMALLMOVE
;
138 static int largemove
= LARGEMOVE
;
143 static int tty_ready
= NOTOK
;
147 #define ERASE sg.sg_erase
148 #define KILL sg.sg_kill
149 static struct sgttyb sg
;
151 #define EOFC tc.t_eofc
152 #define INTR tc.t_intrc
153 static struct tchars tc
;
155 #define ERASE sg.c_cc[VERASE]
156 #define KILL sg.c_cc[VKILL]
157 #define EOFC sg.c_cc[VEOF]
158 #define INTR sg.c_cc[VINTR]
159 static struct termio sg
;
163 #define WERASC ('W' & 037)
166 #define WERASC ltc.t_werasc
167 static struct ltchars ltc
;
169 #define WERASC sg.c_cc[VWERASE]
170 #undef TIOCGLTC /* the define exists, but struct ltchars doesn't */
172 #endif /* TIOCGLTC */
175 #if !defined(SYS5) && !defined(BSD44)
177 #endif /* not SYS5 */
184 static TYPESIG
ALRMser (), PIPEser (), SIGser ();
186 static TYPESIG
TSTPser ();
194 extern char *sys_errlist
[];
197 static void adorn ();
199 static vmh(), lreset(), linsert(), ladvance(), lretreat(), lgo();
200 static TTYon(), TTYoff(), foreground();
201 static int PEERinit(), pINI(), pLOOP(), pTTY(), pWIN(), WINinit();
202 static int WINgetstr(), WINless(), WINputc(), TTYinit(), pWINaux();
221 setlocale(LC_ALL
, "");
223 invo_name
= r1bindex (argv
[0], '/');
224 if ((cp
= m_find (invo_name
)) != NULL
) {
225 ap
= brkstring (cp
= getcpy (cp
), " ", "\n");
226 ap
= copyip (ap
, arguments
);
230 (void) copyip (argv
+ 1, ap
);
237 switch (smatch (++cp
, switches
)) {
239 ambigsw (cp
, switches
);
245 (void) sprintf (buffer
, "%s [switches for vmhproc]",
247 help (buffer
, switches
);
251 if (!(myprompt
= *argp
++) || *myprompt
== '-')
252 adios (NULLCP
, "missing argument to %s", argp
[-2]);
256 if (!(vmhproc
= *argp
++) || *vmhproc
== '-')
257 adios (NULLCP
, "missing argument to %s", argp
[-2]);
268 if (TTYinit (nprog
) == NOTOK
|| WINinit (nprog
) == NOTOK
) {
271 vec
[0] = r1bindex (vmhproc
, '/');
272 execvp (vmhproc
, vec
);
273 adios (vmhproc
, "unable to exec");
276 (void) PEERinit (vecp
, vec
);
290 (void) pLOOP (RC_QRY
, NULLCP
);
292 wmove (Command
, 0, 0);
293 wprintw (Command
, myprompt
, invo_name
);
297 switch (WINgetstr (Command
, buffer
)) {
302 done (0); /* NOTREACHED */
306 (void) pLOOP (RC_CMD
, buffer
);
314 static int PEERinit (vecp
, vec
)
323 if (pipe (pfd0
) == NOTOK
|| pipe (pfd1
) == NOTOK
)
324 adios ("pipe", "unable to");
326 switch (PEERpid
= fork ()) {
328 * Calling vfork() and then another routine [like close()] before
329 * an exec() messes up the stack frame, causing crib death.
330 * Use fork() instead.
333 switch (PEERpid
= vfork ()) {
334 #endif /* not hpux */
336 adios ("vfork", "unable to");/* NOTREACHED */
339 (void) close (pfd0
[0]);
340 (void) close (pfd1
[1]);
342 vec
[vecp
++] = "-vmhread";
343 (void) sprintf (buf1
, "%d", pfd1
[0]);
345 vec
[vecp
++] = "-vmhwrite";
346 (void) sprintf (buf2
, "%d", pfd0
[1]);
350 (void) signal (SIGINT
, SIG_DFL
);
351 (void) signal (SIGQUIT
, SIG_DFL
);
353 vec
[0] = r1bindex (vmhproc
, '/');
354 execvp (vmhproc
, vec
);
356 _exit (-1); /* NOTREACHED */
359 (void) close (pfd0
[1]);
360 (void) close (pfd1
[0]);
362 (void) rcinit (pfd0
[0], pfd1
[1]);
373 register struct record
*rc
= &rcs
;
379 (void) sprintf (bp
, "%d %d", RC_VRSN
, numwins
);
381 for (w
= windows
; *w
; w
++) {
382 (void) sprintf (bp
, " %d", (*w
) -> _maxy
);
386 switch (str2rc (RC_INI
, buffer
, rc
)) {
392 adios (NULLCP
, "%s", rc
-> rc_data
);
394 adios (NULLCP
, "pINI peer error");
397 adios (NULLCP
, "%s", rc
-> rc_data
);
400 adios (NULLCP
, "pINI protocol screw-up");
407 static int pLOOP (code
, str
)
413 register struct record
*rc
= &rcs
;
417 (void) str2peer (code
, str
);
419 switch (peer2rc (rc
)) {
421 if (pTTY (rc
) == NOTOK
)
426 if (sscanf (rc
-> rc_data
, "%d", &i
) != 1
429 (void) fmt2peer (RC_ERR
, "no such window \"%s\"",
433 if (pWIN (windows
[i
- 1]) == NOTOK
)
442 adorn (NULLCP
, "%s", rc
-> rc_data
);
444 adorn (NULLCP
, "pLOOP(%s) peer error",
445 code
== RC_QRY
? "QRY" : "CMD");
450 adorn (NULLCP
, "%s", rc
-> rc_data
);
452 i
= pidwait (PEERpid
, OK
);
457 adios (NULLCP
, "%s", rc
-> rc_data
);
460 adios (NULLCP
, "pLOOP(%s) protocol screw-up",
461 code
== RC_QRY
? "QRY" : "CMD");
468 register struct record
*r
;
470 TYPESIG (*hstat
) (), (*istat
) (), (*qstat
) (), (*tstat
) ();
472 register struct record
*rc
= &rcs
;
478 hstat
= signal (SIGHUP
, SIG_IGN
);
479 istat
= signal (SIGINT
, SIG_IGN
);
480 qstat
= signal (SIGQUIT
, SIG_IGN
);
481 tstat
= signal (SIGTERM
, SIG_IGN
);
483 (void) rc2rc (RC_ACK
, 0, NULLCP
, rc
);
485 (void) signal (SIGHUP
, hstat
);
486 (void) signal (SIGINT
, istat
);
487 (void) signal (SIGQUIT
, qstat
);
488 (void) signal (SIGTERM
, tstat
);
492 if (r
-> rc_len
&& strcmp (r
-> rc_data
, "FAST") == 0)
496 (void) signal (SIGTSTP
, SIG_IGN
);
500 tputs (SO
, 0, _putchar
);
502 putp(enter_standout_mode
);
503 #endif /* TERMINFO */
504 fprintf (stdout
, "Type any key to continue... ");
505 (void) fflush (stdout
);
508 tputs (SE
, 0, _putchar
);
510 putp(exit_standout_mode
);
511 #endif /* TERMINFO */
514 (void) signal (SIGTSTP
, TSTPser
);
520 switch (rc
-> rc_type
) {
522 (void) rc2peer (RC_ACK
, 0, NULLCP
);
527 adorn (NULLCP
, "%s", rc
-> rc_data
);
529 adorn (NULLCP
, "pTTY peer error");
533 adios (NULLCP
, "%s", rc
-> rc_data
);
536 adios (NULLCP
, "pTTY protocol screw-up");
549 if ((i
= pWINaux (w
)) == OK
&& did_less
)
550 (void) WINless (w
, 1);
559 static int pWINaux (w
)
567 register struct record
*rc
= &rcs
;
579 switch (rc2rc (RC_ACK
, 0, NULLCP
, rc
)) {
581 if (eol
&& WINputc (w
, '\n') == ERR
&& WINless (w
, 0))
583 for (bp
= rc
-> rc_data
, n
= rc
-> rc_len
; n
-- > 0; ) {
584 if ((c
= *bp
++) == '\n')
586 if (WINputc (w
, c
) == ERR
)
587 if (n
== 0 && c
== '\n')
590 if (WINless (w
, 0)) {
592 (void) fmt2peer (RC_ERR
, "flush window");
593 #ifdef XYZ /* should NEVER happen... */
604 (void) rc2peer (RC_ACK
, 0, NULLCP
);
614 adorn (NULLCP
, "%s", rc
-> rc_data
);
616 adorn (NULLCP
, "pWIN peer error");
620 adios (NULLCP
, "%s", rc
-> rc_data
);
623 adios (NULLCP
, "pWIN protocol screw-up");
636 (void) rc2peer (RC_FIN
, 0, NULLCP
);
639 switch (setjmp (PEERctx
)) {
641 (void) signal (SIGALRM
, ALRMser
);
642 (void) alarm (ALARM
);
644 status
= pidwait (PEERpid
, OK
);
650 (void) kill (PEERpid
, SIGKILL
);
661 static int WINinit (nprog
) {
662 register int nlines
, /* not "lines" because terminfo uses that */
667 if (initscr () == (WINDOW
*) ERR
)
671 adios (NULLCP
, "could not initialize terminal");
673 (void) signal (SIGTSTP
, SIG_DFL
);
680 if (cursor_address
== NULL
) /* assume mtr wanted "cm", not "CM" */
681 #endif /* TERMINFO */
686 "sorry, your terminal isn't powerful enough to run %s",
690 if (tgetflag ("xt") || tgetnum ("sg") > 0)
691 SO
= SE
= US
= UE
= NULL
;
694 * If termcap mapped directly to terminfo, we'd use the following:
695 * if (teleray_glitch || magic_cookie_glitch > 0)
696 * enter_standout_mode = exit_standout_mode =
697 * enter_underline_mode = exit_underline_mode = NULL;
698 * But terminfo does the right thing so we don't have to resort to that.
700 #endif /* TERMINFO */
702 if ((nlines
= LINES
- 1) < 11)
703 adios (NULLCP
, "screen too small");
704 if ((top
= nlines
/ 3 + 1) > LINES
/ 4 + 2)
706 bottom
= nlines
- top
- 2;
709 Scan
= windows
[numwins
++] = newwin (top
, COLS
, 0, 0);
710 Status
= windows
[numwins
++] = newwin (1, COLS
, top
, 0);
714 Display
= windows
[numwins
++] = newwin (bottom
, COLS
, top
+ 1, 0);
715 Command
= newwin (1, COLS
- 1, top
+ 1 + bottom
, 0);
716 windows
[numwins
] = NULL
;
718 largemove
= Display
-> _maxy
/ 2 + 2;
724 static int WINgetstr (w
, buffer
)
735 switch (c
= toascii (wgetch (w
))) {
737 adios (NULLCP
, "wgetch lost");
747 leaveok (curscr
, FALSE
);
748 wmove (w
, 0, w
-> _curx
- (bp
- buffer
));
750 leaveok (curscr
, TRUE
);
758 wprintw (w
, "Interrupt");
779 w
-> _curx
-= bp
- buffer
;
789 } while (isspace (*bp
) && bp
> buffer
);
794 } while (!isspace (*bp
) && bp
> buffer
);
802 if (c
>= ' ' && c
< '\177')
803 (void) waddch (w
, *bp
++ = c
);
813 static int WINwritev (w
, iov
, n
)
815 register struct iovec
*iov
;
822 for (i
= 0; i
< n
; i
++, iov
++)
823 wprintw (w
, "%*.*s", iov
-> iov_len
, iov
-> iov_len
, iov
-> iov_base
);
837 " forward backwards", NULL
,
838 " ------- ---------", NULL
,
839 "next screen SPACE", NULL
,
840 "next %d line%s RETURN y", &smallmove
,
841 "next %d line%s EOT u", &largemove
,
844 "refresh CTRL-L", NULL
,
852 static int WINless (w
, fin
)
865 register struct line
*lbottom
;
880 if (nfresh
|| nwait
) {
892 (void) lgo (ltail
-> l_no
- w
-> _maxy
+ 1);
897 ltop
= lbottom
&& lbottom
-> l_prev
? lbottom
-> l_prev
900 for (lbottom
= ltop
; lbottom
; lbottom
= lbottom
-> l_next
)
901 if (waddstr (w
, lbottom
-> l_buf
) == ERR
902 || waddch (w
, '\n') == ERR
)
907 if (nlatch
&& (ltail
-> l_no
>= w
-> _maxy
)) {
908 (void) lgo (ltail
-> l_no
- w
-> _maxy
+ 1);
914 while (waddstr (w
, "~\n") != ERR
)
926 wmove (Command
, 0, 0);
929 wprintw (Command
, "%s", cp
);
934 wprintw (Command
, fin
? "top:%d bot:%d end:%d" : "top:%d bot:%d",
935 ltop
-> l_no
, lbottom
-> l_no
, ltail
-> l_no
);
936 wprintw (Command
, ">> ");
940 c
= toascii (wgetch (Command
));
954 ltop
= lbottom
-> l_next
;
964 if (ladvance (smallmove
))
972 if (lretreat (smallmove
))
980 if (ladvance (largemove
))
987 if (lretreat (largemove
))
997 if (lgo (n
? n
: ltail
-> l_no
- w
-> _maxy
+ 1))
1010 for (i
= 0; hlpmsg
[i
].h_msg
; i
++) {
1011 if (hlpmsg
[i
].h_val
)
1012 wprintw (w
, hlpmsg
[i
].h_msg
, *hlpmsg
[i
].h_val
,
1013 *hlpmsg
[i
].h_val
!= 1 ? "s" : "");
1015 (void) waddstr (w
, hlpmsg
[i
].h_msg
);
1016 (void) waddch (w
, '\n');
1030 wmove (Command
, 0, 0);
1032 while (isdigit (c
)) {
1033 wprintw (Command
, "%c", c
);
1035 i
= i
* 10 + c
- '0';
1036 c
= toascii (wgetch (Command
));
1048 cp
= "not understood";
1056 static int WINputc (w
, c
)
1066 if (WINputc (w
, 'M') == ERR
|| WINputc (w
, '-') == ERR
)
1071 if (c
< ' ' || c
== '\177') {
1072 if (WINputc (w
, '^') == ERR
)
1084 return waddch (w
, c
);
1086 if ((x
= w
-> _curx
) < 0 || x
>= w
-> _maxx
1087 || (y
= w
-> _cury
) < 0 || y
>= w
-> _maxy
)
1092 for (x
= 8 - (x
& 0x07); x
> 0; x
--)
1093 if (WINputc (w
, ' ') == ERR
)
1098 if (++y
< w
-> _maxy
)
1099 (void) waddch (w
, c
);
1105 if (++x
< w
-> _maxx
)
1106 (void) waddch (w
, c
);
1116 register struct line
*lp
,
1119 for (lp
= lhead
; lp
; lp
= mp
) {
1124 lhead
= ltop
= ltail
= NULL
;
1132 register struct line
*lp
;
1134 if ((lp
= (struct line
*) calloc ((unsigned) 1, sizeof *lp
)) == NULL
)
1135 adios (NULLCP
, "unable to allocate line storage");
1137 lp
-> l_no
= (ltail
? ltail
-> l_no
: 0) + 1;
1139 lp
-> l_buf
= getcpy (w
-> _y
[w
-> _cury
]);
1141 lp
-> l_buf
= getcpy (w
-> lines
[w
-> _cury
]->line
);
1143 for (cp
= lp
-> l_buf
+ strlen (lp
-> l_buf
) - 1; cp
>= lp
-> l_buf
; cp
--)
1154 ltail
-> l_next
= lp
;
1155 lp
-> l_prev
= ltail
;
1161 static int ladvance (n
)
1165 register struct line
*lp
;
1167 for (i
= 0, lp
= ltop
; i
< n
&& lp
; i
++, lp
= lp
-> l_next
)
1178 static int lretreat (n
)
1182 register struct line
*lp
;
1184 for (i
= 0, lp
= ltop
; i
< n
&& lp
; i
++, lp
= lp
-> l_prev
)
1202 register struct line
*lp
;
1204 if ((i
= n
- (lp
= lhead
) -> l_no
)
1205 > (j
= abs (n
- (ltop
? ltop
: ltail
) -> l_no
)))
1206 i
= j
, lp
= ltop
? ltop
: ltail
;
1207 if (i
> (j
= abs (ltail
-> l_no
- n
)))
1210 if (n
>= lp
-> l_no
) {
1211 for (; lp
; lp
= lp
-> l_next
)
1212 if (lp
-> l_no
== n
)
1216 for (; lp
; lp
= lp
-> l_prev
)
1217 if (lp
-> l_no
== n
)
1232 static int TTYinit (nprog
) {
1233 if (!isatty (fileno (stdin
)) || !isatty (fileno (stdout
)))
1237 adios (NULLCP
, "not a tty");
1241 if (ioctl (fileno (stdin
), TIOCGETP
, (char *) &sg
) == NOTOK
)
1242 adios ("failed", "ioctl TIOCGETP");
1243 if (ioctl (fileno (stdin
), TIOCGETC
, (char *) &tc
) == NOTOK
)
1244 adios ("failed", "ioctl TIOCGETC");
1247 if( tcgetattr( fileno(stdin
), &sg
) == NOTOK
)
1248 adios( "failed", "tcgetattr");
1250 if (ioctl (fileno (stdin
), TCGETA
, &sg
) == NOTOK
)
1251 adios ("failed", "ioctl TCGETA");
1255 if (ioctl (fileno (stdin
), TIOCGLTC
, (char *) <c
) == NOTOK
)
1256 adios ("failed", "ioctl TIOCGLTC");
1257 #endif /* TIOCGLTC */
1263 (void) signal (SIGPIPE
, PIPEser
);
1271 if (tty_ready
== DONE
)
1276 (void) ioctl (fileno (stdin
), TIOCSETC
, (char *) &tc
);
1278 (void) ioctl (fileno (stdin
), TCSETA
, &sg
);
1284 scrollok (curscr
, FALSE
);
1290 (void) signal (SIGHUP
, SIGser
);
1291 (void) signal (SIGINT
, SIGser
);
1292 (void) signal (SIGQUIT
, SIGser
);
1294 (void) signal (SIGTSTP
, TSTPser
);
1295 #endif /* SIGTSTP */
1301 if (tty_ready
== NOTOK
)
1306 (void) ioctl (fileno (stdin
), TIOCSETC
, (char *) &tc
);
1308 (void) ioctl (fileno (stdin
), TCSETA
, &sg
);
1311 leaveok (curscr
, TRUE
);
1312 mvcur (0, COLS
- 1, LINES
- 1, 0);
1314 if (tty_ready
== DONE
) {
1317 tputs (CE
, 0, _putchar
);
1319 #else /* TERMINFO */
1321 #endif /* TERMINFO */
1322 fprintf (stdout
, "\r\n");
1324 (void) fflush (stdout
);
1328 (void) signal (SIGHUP
, SIG_DFL
);
1329 (void) signal (SIGINT
, SIG_DFL
);
1330 (void) signal (SIGQUIT
, SIG_DFL
);
1332 (void) signal (SIGTSTP
, SIG_DFL
);
1333 #endif /* SIGTSTP */
1338 static foreground () {
1342 TYPESIG (*tstat
) ();
1344 if ((pgrp
= getpgrp (0)) == NOTOK
)
1345 adios ("process group", "unable to determine");
1347 if (ioctl (fileno (stdin
), TIOCGPGRP
, (char *) &tpgrp
) == NOTOK
)
1348 adios ("tty's process group", "unable to determine");
1352 tstat
= signal (SIGTTIN
, SIG_DFL
);
1353 (void) kill (0, SIGTTIN
);
1354 (void) signal (SIGTTIN
, tstat
);
1357 (void) signal (SIGTTIN
, SIG_IGN
);
1358 (void) signal (SIGTTOU
, SIG_IGN
);
1359 (void) signal (SIGTSTP
, SIG_IGN
);
1360 #endif /* TIOCGPGRP */
1366 (void) signal (SIGTTIN
, SIG_DFL
);
1367 (void) signal (SIGTTOU
, SIG_DFL
);
1368 (void) signal (SIGTSTP
, SIG_DFL
);
1369 #endif /* TIOCGPGRP */
1376 static TYPESIG
ALRMser (sig
)
1379 longjmp (PEERctx
, DONE
);
1387 static TYPESIG
PIPEser (sig
)
1391 (void) signal (sig
, SIG_IGN
);
1394 adios (NULLCP
, "lost peer");
1402 static TYPESIG
SIGser (sig
)
1406 (void) signal (sig
, SIG_IGN
);
1414 static TYPESIG
TSTPser (sig
)
1418 tputs (tgoto (CM
, 0, LINES
- 1), 0, _putchar
);
1419 #else /* TERMINFO */
1420 move(LINES
- 1, 0); /* to lower left corner */
1421 clrtoeol(); /* clear bottom line */
1422 wrefresh(curscr
); /* flush out everything */
1423 #endif /* TERMINFO */
1424 (void) fflush (stdout
);
1428 (void) sigsetmask (sigblock (0) & ~sigmask (SIGTSTP
));
1431 (void) kill (getpid (), sig
);
1434 (void) sigblock (sigmask (SIGTSTP
));
1440 #endif /* SIGTSTP */
1457 static void adorn (what
, fmt
, a
, b
, c
, d
, e
, f
)
1467 char *cp
= invo_name
;
1470 advise (what
, fmt
, a
, b
, c
, d
, e
, f
);
1478 void advertise (what
, tail
, fmt
, a
, b
, c
, d
, e
, f
)
1490 char buffer
[BUFSIZ
],
1492 struct iovec iob
[20];
1493 register struct iovec
*iov
= iob
;
1495 (void) fflush (stdout
);
1497 (void) fflush (stderr
);
1500 iov
-> iov_len
= strlen (iov
-> iov_base
= invo_name
);
1502 iov
-> iov_len
= strlen (iov
-> iov_base
= ": ");
1506 (void) sprintf (buffer
, fmt
, a
, b
, c
, d
, e
, f
);
1507 iov
-> iov_len
= strlen (iov
-> iov_base
= buffer
);
1511 iov
-> iov_len
= strlen (iov
-> iov_base
= " ");
1513 iov
-> iov_len
= strlen (iov
-> iov_base
= what
);
1515 iov
-> iov_len
= strlen (iov
-> iov_base
= ": ");
1518 if (eindex
> 0 && eindex
< sys_nerr
)
1519 iov
-> iov_len
= strlen (iov
-> iov_base
= sys_errlist
[eindex
]);
1521 (void) sprintf (err
, "Error %d", eindex
);
1522 iov
-> iov_len
= strlen (iov
-> iov_base
= err
);
1526 if (tail
&& *tail
) {
1527 iov
-> iov_len
= strlen (iov
-> iov_base
= ", ");
1529 iov
-> iov_len
= strlen (iov
-> iov_base
= tail
);
1532 iov
-> iov_len
= strlen (iov
-> iov_base
= "\n");
1535 if (tty_ready
== DONE
)
1536 (void) WINwritev (Display
, iob
, iov
- iob
);
1538 (void) writev (fileno (stderr
), iob
, iov
- iob
);
1544 static int writev (fd
, iov
, n
)
1546 register struct iovec
*iov
;
1552 for (i
= j
= 0; i
< n
; i
++, iov
++)
1553 if (write (fd
, iov
-> iov_base
, iov
-> iov_len
) != iov
-> iov_len
)
1556 j
+= iov
-> iov_len
;