| @@ -1,35 +1,35 @@ | | | @@ -1,35 +1,35 @@ |
1 | /* $NetBSD: ex_script.c,v 1.8 2017/11/06 03:27:34 rin Exp $ */ | | 1 | /* $NetBSD: ex_script.c,v 1.9 2018/08/07 11:41:23 rin Exp $ */ |
2 | /*- | | 2 | /*- |
3 | * Copyright (c) 1992, 1993, 1994 | | 3 | * Copyright (c) 1992, 1993, 1994 |
4 | * The Regents of the University of California. All rights reserved. | | 4 | * The Regents of the University of California. All rights reserved. |
5 | * Copyright (c) 1992, 1993, 1994, 1995, 1996 | | 5 | * Copyright (c) 1992, 1993, 1994, 1995, 1996 |
6 | * Keith Bostic. All rights reserved. | | 6 | * Keith Bostic. All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to Berkeley by | | 8 | * This code is derived from software contributed to Berkeley by |
9 | * Brian Hirt. | | 9 | * Brian Hirt. |
10 | * | | 10 | * |
11 | * See the LICENSE file for redistribution information. | | 11 | * See the LICENSE file for redistribution information. |
12 | */ | | 12 | */ |
13 | | | 13 | |
14 | #include "config.h" | | 14 | #include "config.h" |
15 | | | 15 | |
16 | #include <sys/cdefs.h> | | 16 | #include <sys/cdefs.h> |
17 | #if 0 | | 17 | #if 0 |
18 | #ifndef lint | | 18 | #ifndef lint |
19 | static const char sccsid[] = "Id: ex_script.c,v 10.38 2001/06/25 15:19:19 skimo Exp (Berkeley) Date: 2001/06/25 15:19:19 "; | | 19 | static const char sccsid[] = "Id: ex_script.c,v 10.38 2001/06/25 15:19:19 skimo Exp (Berkeley) Date: 2001/06/25 15:19:19 "; |
20 | #endif /* not lint */ | | 20 | #endif /* not lint */ |
21 | #else | | 21 | #else |
22 | __RCSID("$NetBSD: ex_script.c,v 1.8 2017/11/06 03:27:34 rin Exp $"); | | 22 | __RCSID("$NetBSD: ex_script.c,v 1.9 2018/08/07 11:41:23 rin Exp $"); |
23 | #endif | | 23 | #endif |
24 | | | 24 | |
25 | #include <sys/types.h> | | 25 | #include <sys/types.h> |
26 | #include <sys/ioctl.h> | | 26 | #include <sys/ioctl.h> |
27 | #include <sys/queue.h> | | 27 | #include <sys/queue.h> |
28 | #ifdef HAVE_SYS_SELECT_H | | 28 | #ifdef HAVE_SYS_SELECT_H |
29 | #include <sys/select.h> | | 29 | #include <sys/select.h> |
30 | #endif | | 30 | #endif |
31 | #include <sys/stat.h> | | 31 | #include <sys/stat.h> |
32 | #if defined(HAVE_SYS5_PTY) | | 32 | #if defined(HAVE_SYS5_PTY) |
33 | #include <sys/stropts.h> | | 33 | #include <sys/stropts.h> |
34 | #endif | | 34 | #endif |
35 | #include <sys/time.h> | | 35 | #include <sys/time.h> |
| @@ -252,84 +252,84 @@ sscr_getprompt(SCR *sp) | | | @@ -252,84 +252,84 @@ sscr_getprompt(SCR *sp) |
252 | * | | 252 | * |
253 | * PUBLIC: int sscr_exec __P((SCR *, db_recno_t)); | | 253 | * PUBLIC: int sscr_exec __P((SCR *, db_recno_t)); |
254 | */ | | 254 | */ |
255 | int | | 255 | int |
256 | sscr_exec(SCR *sp, db_recno_t lno) | | 256 | sscr_exec(SCR *sp, db_recno_t lno) |
257 | { | | 257 | { |
258 | SCRIPT *sc; | | 258 | SCRIPT *sc; |
259 | db_recno_t last_lno; | | 259 | db_recno_t last_lno; |
260 | size_t blen, len, last_len; | | 260 | size_t blen, len, last_len; |
261 | int isempty, matchprompt, rval; | | 261 | int isempty, matchprompt, rval; |
262 | ssize_t nw; | | 262 | ssize_t nw; |
263 | char *bp = NULL; | | 263 | char *bp = NULL; |
264 | const char *p; | | 264 | const char *p; |
265 | const CHAR_T *ip; | | 265 | const CHAR_T *wp; |
266 | size_t ilen; | | 266 | size_t wlen; |
267 | | | 267 | |
268 | sc = sp->script; | | 268 | sc = sp->script; |
269 | | | 269 | |
270 | /* If there's a prompt on the last line, append the command. */ | | 270 | /* If there's a prompt on the last line, append the command. */ |
271 | if (db_last(sp, &last_lno)) | | 271 | if (db_last(sp, &last_lno)) |
272 | return (1); | | 272 | return (1); |
273 | if (db_get(sp, last_lno, DBG_FATAL, __UNCONST(&ip), &ilen)) | | 273 | if (db_get(sp, last_lno, DBG_FATAL, __UNCONST(&wp), &wlen)) |
274 | return (1); | | 274 | return (1); |
275 | INT2CHAR(sp, ip, ilen, p, last_len); | | 275 | INT2CHAR(sp, wp, wlen, p, last_len); |
276 | if (last_len == sc->sh_prompt_len && | | 276 | if (last_len == sc->sh_prompt_len && |
277 | memcmp(p, sc->sh_prompt, last_len) == 0) { | | 277 | memcmp(p, sc->sh_prompt, last_len) == 0) { |
278 | matchprompt = 1; | | 278 | matchprompt = 1; |
279 | GET_SPACE_RETC(sp, bp, blen, last_len + 128); | | 279 | GET_SPACE_RETC(sp, bp, blen, last_len + 128); |
280 | memmove(bp, p, last_len); | | 280 | memmove(bp, p, last_len); |
281 | } else | | 281 | } else |
282 | matchprompt = 0; | | 282 | matchprompt = 0; |
283 | | | 283 | |
284 | /* Get something to execute. */ | | 284 | /* Get something to execute. */ |
285 | if (db_eget(sp, lno, __UNCONST(&ip), &ilen, &isempty)) { | | 285 | if (db_eget(sp, lno, __UNCONST(&wp), &wlen, &isempty)) { |
286 | if (isempty) | | 286 | if (isempty) |
287 | goto empty; | | 287 | goto empty; |
288 | goto err1; | | 288 | goto err1; |
289 | } | | 289 | } |
290 | | | 290 | |
291 | /* Empty lines aren't interesting. */ | | 291 | /* Empty lines aren't interesting. */ |
292 | if (ilen == 0) | | 292 | if (wlen == 0) |
293 | goto empty; | | 293 | goto empty; |
294 | INT2CHAR(sp, ip, ilen, p, len); | | 294 | INT2CHAR(sp, wp, wlen, p, len); |
295 | | | 295 | |
296 | /* Delete any prompt. */ | | 296 | /* Delete any prompt. */ |
297 | if (len >= sc->sh_prompt_len && | | 297 | if (len >= sc->sh_prompt_len && |
298 | memcmp(p, sc->sh_prompt, sc->sh_prompt_len) == 0) { | | 298 | memcmp(p, sc->sh_prompt, sc->sh_prompt_len) == 0) { |
299 | len -= sc->sh_prompt_len; | | 299 | len -= sc->sh_prompt_len; |
300 | if (len == 0) { | | 300 | if (len == 0) { |
301 | empty: msgq(sp, M_BERR, "151|No command to execute"); | | 301 | empty: msgq(sp, M_BERR, "151|No command to execute"); |
302 | goto err1; | | 302 | goto err1; |
303 | } | | 303 | } |
304 | p += sc->sh_prompt_len; | | 304 | p += sc->sh_prompt_len; |
305 | } | | 305 | } |
306 | | | 306 | |
307 | /* Push the line to the shell. */ | | 307 | /* Push the line to the shell. */ |
308 | if ((size_t)(nw = write(sc->sh_master, p, len)) != len) | | 308 | if ((size_t)(nw = write(sc->sh_master, p, len)) != len) |
309 | goto err2; | | 309 | goto err2; |
310 | rval = 0; | | 310 | rval = 0; |
311 | if (write(sc->sh_master, "\n", 1) != 1) { | | 311 | if (write(sc->sh_master, "\n", 1) != 1) { |
312 | err2: if (nw == 0) | | 312 | err2: if (nw == 0) |
313 | errno = EIO; | | 313 | errno = EIO; |
314 | msgq(sp, M_SYSERR, "shell"); | | 314 | msgq(sp, M_SYSERR, "shell"); |
315 | goto err1; | | 315 | goto err1; |
316 | } | | 316 | } |
317 | | | 317 | |
318 | if (matchprompt) { | | 318 | if (matchprompt) { |
319 | ADD_SPACE_GOTO(sp, char, bp, blen, last_len + len); | | 319 | ADD_SPACE_GOTO(sp, char, bp, blen, last_len + len); |
320 | memmove(bp + last_len, p, len); | | 320 | memmove(bp + last_len, p, len); |
321 | CHAR2INT(sp, bp, last_len + len, ip, ilen); | | 321 | CHAR2INT(sp, bp, last_len + len, wp, wlen); |
322 | if (db_set(sp, last_lno, ip, ilen)) | | 322 | if (db_set(sp, last_lno, wp, wlen)) |
323 | err1: rval = 1; | | 323 | err1: rval = 1; |
324 | } | | 324 | } |
325 | if (matchprompt) | | 325 | if (matchprompt) |
326 | alloc_err: FREE_SPACE(sp, bp, blen); | | 326 | alloc_err: FREE_SPACE(sp, bp, blen); |
327 | return (rval); | | 327 | return (rval); |
328 | } | | 328 | } |
329 | | | 329 | |
330 | /* | | 330 | /* |
331 | * sscr_check_input - | | 331 | * sscr_check_input - |
332 | * Check whether any input from shell or passed set. | | 332 | * Check whether any input from shell or passed set. |
333 | * | | 333 | * |
334 | * PUBLIC: int sscr_check_input __P((SCR *sp, fd_set *rdfd, int maxfd)); | | 334 | * PUBLIC: int sscr_check_input __P((SCR *sp, fd_set *rdfd, int maxfd)); |
335 | */ | | 335 | */ |
| @@ -422,95 +422,95 @@ loop: maxfd = 0; | | | @@ -422,95 +422,95 @@ loop: maxfd = 0; |
422 | * Take a line from the shell and insert it into the file. | | 422 | * Take a line from the shell and insert it into the file. |
423 | */ | | 423 | */ |
424 | static int | | 424 | static int |
425 | sscr_insert(SCR *sp) | | 425 | sscr_insert(SCR *sp) |
426 | { | | 426 | { |
427 | struct timeval tv; | | 427 | struct timeval tv; |
428 | char *endp, *p, *t; | | 428 | char *endp, *p, *t; |
429 | SCRIPT *sc; | | 429 | SCRIPT *sc; |
430 | fd_set rdfd; | | 430 | fd_set rdfd; |
431 | db_recno_t lno; | | 431 | db_recno_t lno; |
432 | size_t len; | | 432 | size_t len; |
433 | ssize_t nr; | | 433 | ssize_t nr; |
434 | char bp[1024]; | | 434 | char bp[1024]; |
435 | const CHAR_T *ip; | | 435 | const CHAR_T *wp; |
436 | size_t ilen = 0; | | 436 | size_t wlen = 0; |
437 | | | 437 | |
438 | /* Find out where the end of the file is. */ | | 438 | /* Find out where the end of the file is. */ |
439 | if (db_last(sp, &lno)) | | 439 | if (db_last(sp, &lno)) |
440 | return (1); | | 440 | return (1); |
441 | | | 441 | |
442 | endp = bp; | | 442 | endp = bp; |
443 | | | 443 | |
444 | /* Read the characters. */ | | 444 | /* Read the characters. */ |
445 | sc = sp->script; | | 445 | sc = sp->script; |
446 | more: switch (nr = read(sc->sh_master, endp, bp + sizeof(bp) - endp)) { | | 446 | more: switch (nr = read(sc->sh_master, endp, bp + sizeof(bp) - endp)) { |
447 | case 0: /* EOF; shell just exited. */ | | 447 | case 0: /* EOF; shell just exited. */ |
448 | sscr_end(sp); | | 448 | sscr_end(sp); |
449 | return (0); | | 449 | return (0); |
450 | case -1: /* Error or interrupt. */ | | 450 | case -1: /* Error or interrupt. */ |
451 | msgq(sp, M_SYSERR, "shell"); | | 451 | msgq(sp, M_SYSERR, "shell"); |
452 | return (1); | | 452 | return (1); |
453 | default: | | 453 | default: |
454 | endp += nr; | | 454 | endp += nr; |
455 | break; | | 455 | break; |
456 | } | | 456 | } |
457 | | | 457 | |
458 | /* Append the lines into the file. */ | | 458 | /* Append the lines into the file. */ |
459 | for (p = t = bp; p < endp; ++p) { | | 459 | for (p = t = bp; p < endp; ++p) { |
460 | if (*p == '\r' || *p == '\n') { | | 460 | if (*p == '\r' || *p == '\n') { |
461 | len = p - t; | | 461 | len = p - t; |
462 | if (CHAR2INT(sp, t, len, ip, ilen) || | | 462 | if (CHAR2INT(sp, t, len, wp, wlen) || |
463 | db_append(sp, 1, lno++, ip, ilen)) | | 463 | db_append(sp, 1, lno++, wp, wlen)) |
464 | return (1); | | 464 | return (1); |
465 | t = p + 1; | | 465 | t = p + 1; |
466 | } | | 466 | } |
467 | } | | 467 | } |
468 | /* | | 468 | /* |
469 | * If the last thing from the shell isn't another prompt, wait up to | | 469 | * If the last thing from the shell isn't another prompt, wait up to |
470 | * 1/10 of a second for more stuff to show up, so that we don't break | | 470 | * 1/10 of a second for more stuff to show up, so that we don't break |
471 | * the output into two separate lines. Don't want to hang indefinitely | | 471 | * the output into two separate lines. Don't want to hang indefinitely |
472 | * because some program is hanging, confused the shell, or whatever. | | 472 | * because some program is hanging, confused the shell, or whatever. |
473 | * Note that sc->sh_prompt can be NULL here. | | 473 | * Note that sc->sh_prompt can be NULL here. |
474 | */ | | 474 | */ |
475 | len = p - t; | | 475 | len = p - t; |
476 | if (sc->sh_prompt == NULL || len != sc->sh_prompt_len || | | 476 | if (sc->sh_prompt == NULL || len != sc->sh_prompt_len || |
477 | memcmp(t, sc->sh_prompt, len) != 0) { | | 477 | memcmp(t, sc->sh_prompt, len) != 0) { |
478 | tv.tv_sec = 0; | | 478 | tv.tv_sec = 0; |
479 | tv.tv_usec = 100000; | | 479 | tv.tv_usec = 100000; |
480 | FD_ZERO(&rdfd); | | 480 | FD_ZERO(&rdfd); |
481 | FD_SET(sc->sh_master, &rdfd); | | 481 | FD_SET(sc->sh_master, &rdfd); |
482 | if (select(sc->sh_master + 1, &rdfd, NULL, NULL, &tv) == 1) { | | 482 | if (select(sc->sh_master + 1, &rdfd, NULL, NULL, &tv) == 1) { |
483 | if (len == sizeof(bp)) { | | 483 | if (len == sizeof(bp)) { |
484 | if (CHAR2INT(sp, t, len, ip, ilen) || | | 484 | if (CHAR2INT(sp, t, len, wp, wlen) || |
485 | db_append(sp, 1, lno++, ip, ilen)) | | 485 | db_append(sp, 1, lno++, wp, wlen)) |
486 | return (1); | | 486 | return (1); |
487 | endp = bp; | | 487 | endp = bp; |
488 | } else { | | 488 | } else { |
489 | memmove(bp, t, len); | | 489 | memmove(bp, t, len); |
490 | endp = bp + len; | | 490 | endp = bp + len; |
491 | } | | 491 | } |
492 | goto more; | | 492 | goto more; |
493 | } | | 493 | } |
494 | if (sscr_setprompt(sp, t, len)) | | 494 | if (sscr_setprompt(sp, t, len)) |
495 | return (1); | | 495 | return (1); |
496 | } | | 496 | } |
497 | | | 497 | |
498 | /* Append the remains into the file, and the cursor moves to EOF. */ | | 498 | /* Append the remains into the file, and the cursor moves to EOF. */ |
499 | if (len > 0) { | | 499 | if (len > 0) { |
500 | if (CHAR2INT(sp, t, len, ip, ilen) || | | 500 | if (CHAR2INT(sp, t, len, wp, wlen) || |
501 | db_append(sp, 1, lno++, ip, ilen)) | | 501 | db_append(sp, 1, lno++, wp, wlen)) |
502 | return (1); | | 502 | return (1); |
503 | sp->cno = ilen - 1; | | 503 | sp->cno = wlen - 1; |
504 | } else | | 504 | } else |
505 | sp->cno = 0; | | 505 | sp->cno = 0; |
506 | sp->lno = lno; | | 506 | sp->lno = lno; |
507 | return (vs_refresh(sp, 1)); | | 507 | return (vs_refresh(sp, 1)); |
508 | } | | 508 | } |
509 | | | 509 | |
510 | /* | | 510 | /* |
511 | * sscr_setprompt -- | | 511 | * sscr_setprompt -- |
512 | * | | 512 | * |
513 | * Set the prompt in external ("char") encoding. | | 513 | * Set the prompt in external ("char") encoding. |
514 | * | | 514 | * |
515 | */ | | 515 | */ |
516 | static int | | 516 | static int |