varnish-cache/bin/varnishtest/vtc_process.c
1
/*-
2
 * Copyright (c) 2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Dridi Boukelmoune <dridi@varnish-software.com>
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
20
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
 * SUCH DAMAGE.
27
 *
28
 * XXX:
29
 *      -ignore-stderr (otherwise output to stderr is fail)
30
 */
31
32
#include "config.h"
33
34
#include <sys/ioctl.h>          // Linux: struct winsize
35
36
#include <ctype.h>
37
#include <fcntl.h>
38
#include <inttypes.h>
39
#include <poll.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#ifdef __sun
44
#  include <stropts.h>
45
#endif
46
#include <termios.h>
47
#include <unistd.h>
48
49
#include "vtc.h"
50
51
#include "vev.h"
52
#include "vlu.h"
53
#include "vsb.h"
54
#include "vsub.h"
55
56
#include "teken.h"
57
58
struct process {
59
        unsigned                magic;
60
#define PROCESS_MAGIC           0x1617b43e
61
        char                    *name;
62
        struct vtclog           *vl;
63
        VTAILQ_ENTRY(process)   list;
64
65
        char                    *spec;
66
        char                    *dir;
67
        char                    *out;
68
        char                    *err;
69
        int                     fd_term;
70
        int                     fd_stderr;
71
        int                     f_stdout;
72
        int                     f_stderr;
73
        struct vlu              *vlu_stdout;
74
        struct vlu              *vlu_stderr;
75
        int                     log;
76
        pid_t                   pid;
77
        int                     expect_exit;
78
        int                     expect_signal;
79
        int                     allow_core;
80
81
        uintmax_t               stdout_bytes;
82
        uintmax_t               stderr_bytes;
83
84
        pthread_mutex_t         mtx;
85
        pthread_t               tp;
86
        unsigned                hasthread;
87
88
        int                     nlin;
89
        int                     ncol;
90
        int                     ansi_response;
91
        char                    **vram;
92
        teken_t                 tek[1];
93
};
94
95
static VTAILQ_HEAD(, process)   processes =
96
    VTAILQ_HEAD_INITIALIZER(processes);
97
98
static void term_resize(struct process *pp, int lin, int col);
99
100
/**********************************************************************
101
 * Terminal emulation
102
 */
103
104
static void
105 1535417
term_cursor(void *priv, const teken_pos_t *pos)
106
{
107 1535417
        (void)priv;
108 1535417
        (void)pos;
109 1535417
}
110
111
static void
112 11755292
term_putchar(void *priv, const teken_pos_t *pos, teken_char_t ch,
113
    const teken_attr_t *at)
114
{
115
        struct process *pp;
116
117 11755292
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
118 11755292
        (void)at;
119 11755292
        if (ch > 126 || ch < 32)
120 8430
                ch = '?';
121 11755292
        assert(pos->tp_row < pp->nlin);
122 11755292
        assert(pos->tp_col < pp->ncol);
123 11755292
        pp->vram[pos->tp_row][pos->tp_col] = ch;
124 11755292
}
125
126
static void
127 22004
term_fill(void *priv, const teken_rect_t *r, teken_char_t c,
128
    const teken_attr_t *a)
129
{
130
        teken_pos_t p;
131
132
        /* Braindead implementation of fill() - just call putchar(). */
133 137459
        for (p.tp_row = r->tr_begin.tp_row;
134 137459
            p.tp_row < r->tr_end.tp_row; p.tp_row++)
135 10492620
                for (p.tp_col = r->tr_begin.tp_col;
136 10492620
                    p.tp_col < r->tr_end.tp_col; p.tp_col++)
137 10492620
                        term_putchar(priv, &p, c, a);
138 22004
}
139
140
static void
141 22380
term_copy(void *priv, const teken_rect_t *r, const teken_pos_t *p)
142
{
143
        struct process *pp;
144
        int nrow, ncol, y; /* Has to be signed - >= 0 comparison */
145
146
        /*
147
         * Copying is a little tricky. We must make sure we do it in
148
         * correct order, to make sure we don't overwrite our own data.
149
         */
150 22380
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
151
152 22380
        nrow = r->tr_end.tp_row - r->tr_begin.tp_row;
153 22380
        ncol = r->tr_end.tp_col - r->tr_begin.tp_col;
154
155 22380
        if (p->tp_row < r->tr_begin.tp_row) {
156
                /* Copy from top to bottom. */
157 94980
                for (y = 0; y < nrow; y++)
158 176940
                        memmove(&pp->vram[p->tp_row + y][p->tp_col],
159 88470
                            &pp->vram[r->tr_begin.tp_row + y][r->tr_begin.tp_col], ncol);
160 6510
        } else {
161
                /* Copy from bottom to top. */
162 88650
                for (y = nrow - 1; y >= 0; y--)
163 145560
                        memmove(&pp->vram[p->tp_row + y][p->tp_col],
164 72780
                            &pp->vram[r->tr_begin.tp_row + y][r->tr_begin.tp_col], ncol);
165
        }
166 22380
}
167
168
static void
169 240
term_respond(void *priv, const void *p, size_t l)
170
{
171
        struct process *pp;
172
        int r;
173
174 240
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
175
176 240
        vtc_dump(pp->vl, 4, "term_response", p, l);
177 240
        if (pp->ansi_response) {
178 30
                r = write(pp->fd_term, p, l);
179 30
                if (r != l)
180 0
                        vtc_fatal(pp->vl, "Could not write to process: %s",
181 0
                            strerror(errno));
182 30
        }
183 240
}
184
185
static void
186 1635
term_param(void *priv, int p, unsigned int v)
187
{
188
        struct process *pp;
189
190 1635
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
191 1635
        if (p == TP_132COLS && v)
192 180
                term_resize(pp, pp->nlin, 132);
193 1635
        if (p == TP_132COLS && !v)
194 360
                term_resize(pp, pp->nlin, 80);
195 1635
}
196
197
static const teken_funcs_t process_teken_func = {
198
        .tf_cursor      =       term_cursor,
199
        .tf_putchar     =       term_putchar,
200
        .tf_fill        =       term_fill,
201
        .tf_copy        =       term_copy,
202
        .tf_respond     =       term_respond,
203
        .tf_param       =       term_param,
204
};
205
206
static void
207 1920
term_screen_dump(const struct process *pp)
208
{
209
        int i;
210
        const teken_pos_t *pos;
211
212 48285
        for (i = 0; i < pp->nlin; i++)
213 46365
                vtc_dump(pp->vl, 3, "screen", pp->vram[i], pp->ncol);
214 1920
        pos = teken_get_cursor(pp->tek);
215 3840
        vtc_log(pp->vl, 3, "Cursor at line %d column %d",
216 1920
            pos->tp_row + 1, pos->tp_col + 1);
217 1920
}
218
219
static void
220 1170
term_resize(struct process *pp, int lin, int col)
221
{
222
        teken_pos_t pos;
223
        char **vram;
224
        int i, j;
225
226 1170
        vram = calloc(lin, sizeof *pp->vram);
227 1170
        AN(vram);
228 29535
        for (i = 0; i < lin; i++) {
229 28365
                vram[i] = calloc(col + 1L, 1);
230 28365
                AN(vram[i]);
231 28365
                memset(vram[i], ' ', col);
232 28365
                vram[i][col] = '\0';
233 28365
        }
234 1170
        if (pp->vram != NULL) {
235 15735
                for (i = 0; i < lin; i++) {
236 15180
                        if (i >= pp->nlin)
237 75
                                break;
238 15105
                        j = col;
239 15105
                        if (j > pp->ncol)
240 5040
                                j = pp->ncol;
241 15105
                        memcpy(vram[i], pp->vram[i], j);
242 15105
                }
243 15750
                for (i = 0; i < pp->nlin; i++)
244 15120
                        free(pp->vram[i]);
245 630
                free(pp->vram);
246 630
        }
247 1170
        pp->vram = vram;
248 1170
        pp->nlin = lin;
249 1170
        pp->ncol = col;
250
251 1170
        pos.tp_row = lin;
252 1170
        pos.tp_col = col;
253 1170
        teken_set_winsize(pp->tek, &pos);
254 1170
}
255
256
static int
257 37873
term_match_textline(const struct process *pp, int *x, int y, const char *pat)
258
{
259
        const char *t;
260
261 37873
        if (*x == 0) {
262 26383
                t = strstr(pp->vram[y], pat);
263 26383
                if (t != NULL) {
264 720
                        *x = 1 + (t - pp->vram[y]);
265 720
                        return (1);
266
                }
267 37153
        } else if (*x <= pp->ncol) {
268 11431
                t = pp->vram[y] + *x - 1;
269 11431
                if (!memcmp(t, pat, strlen(pat)))
270 2475
                        return (1);
271 8956
        }
272 34678
        return (0);
273 37873
}
274
275
static int
276 6411
term_match_text(const struct process *pp, int *x, int *y, const char *pat)
277
{
278
        int yy;
279
280 6411
        if (*y == 0) {
281 34235
                for (yy = 0; yy < pp->nlin; yy++) {
282 33201
                        if (term_match_textline(pp, x, yy, pat)) {
283 705
                                *y = yy + 1;
284 705
                                return (1);
285
                        }
286 32496
                }
287 5706
        } else if (*y <= pp->nlin) {
288 4672
                if (term_match_textline(pp, x, *y - 1, pat))
289 2490
                        return (1);
290 2182
        }
291 3216
        return (0);
292 6411
}
293
294
static void
295 3195
term_expect_text(struct process *pp,
296
    const char *lin, const char *col, const char *pat)
297
{
298 3195
        int x, y, l, d = 10000;
299
        char *t;
300
301 3195
        y = strtoul(lin, NULL, 0);
302 3195
        x = strtoul(col, NULL, 0);
303 3195
        l = strlen(pat);
304 3195
        AZ(pthread_mutex_lock(&pp->mtx));
305 6411
        while (!term_match_text(pp, &x, &y, pat)) {
306 3216
                if (x != 0 && y != 0) {
307 1872
                        t = pp->vram[y - 1] + x - 1;
308 3744
                        vtc_log(pp->vl, 4,
309 1872
                            "text at %d,%d: '%.*s'", y, x, l, t);
310 1872
                }
311 3216
                AZ(pthread_mutex_unlock(&pp->mtx));
312 3216
                usleep(d);
313 3216
                AZ(pthread_mutex_lock(&pp->mtx));
314 3216
                if (d < 300000)
315 3007
                        d += d;
316
        }
317 3195
        AZ(pthread_mutex_unlock(&pp->mtx));
318 3195
        vtc_log(pp->vl, 4, "found expected text at %d,%d: '%s'", y, x, pat);
319 3195
}
320
321
static void
322 120
term_expect_cursor(const struct process *pp, const char *lin, const char *col)
323
{
324
        int x, y;
325
        const teken_pos_t *pos;
326
327 120
        pos = teken_get_cursor(pp->tek);
328 120
        y = strtoul(lin, NULL, 0);
329 120
        x = strtoul(col, NULL, 0);
330 120
        if (y != 0 && (y-1) != pos->tp_row)
331 0
                vtc_fatal(pp->vl, "Cursor on line %d (expected %d)",
332 0
                    pos->tp_row + 1, y);
333 120
        if (x != 0 && (x-1) != pos->tp_col)
334 0
                vtc_fatal(pp->vl, "Cursor in column %d (expected %d)",
335 0
                    pos->tp_col + 1, y);
336 120
}
337
338
/**********************************************************************
339
 * Allocate and initialize a process
340
 */
341
342
#define PROCESS_EXPAND(field, format, ...)                              \
343
        do {                                                            \
344
                vsb = macro_expandf(p->vl, format, __VA_ARGS__);        \
345
                AN(vsb);                                                \
346
                p->field = strdup(VSB_data(vsb));                       \
347
                AN(p->field);                                           \
348
                VSB_destroy(&vsb);                                      \
349
        } while (0)
350
351
static void
352 540
process_coverage(struct process *p)
353
{
354
        const teken_attr_t *a;
355
        teken_pos_t pos;
356
        int fg, bg;
357
358
        // Code-Coverage of Teken
359
360 540
        (void)teken_get_sequence(p->tek, TKEY_UP);
361 540
        (void)teken_get_sequence(p->tek, TKEY_F1);
362 540
        (void)teken_256to8(0);
363 540
        (void)teken_256to16(0);
364 540
        a = teken_get_defattr(p->tek);
365 540
        teken_set_defattr(p->tek, a);
366 540
        a = teken_get_curattr(p->tek);
367 540
        teken_set_curattr(p->tek, a);
368 540
        (void)teken_get_winsize(p->tek);
369 540
        pos.tp_row = 0;
370 540
        pos.tp_col = 8;
371 540
        teken_set_cursor(p->tek, &pos);
372 540
        teken_get_defattr_cons25(p->tek, &fg, &bg);
373 540
}
374
375
static struct process *
376 540
process_new(const char *name)
377
{
378
        struct process *p;
379
        struct vsb *vsb;
380
        char buf[1024];
381
382 540
        ALLOC_OBJ(p, PROCESS_MAGIC);
383 540
        AN(p);
384 540
        REPLACE(p->name, name);
385 540
        AZ(pthread_mutex_init(&p->mtx, NULL));
386
387 540
        p->vl = vtc_logopen(name);
388 540
        AN(p->vl);
389
390 540
        PROCESS_EXPAND(dir, "${tmpdir}/%s", name);
391 540
        PROCESS_EXPAND(out, "${tmpdir}/%s/term", name);
392 540
        PROCESS_EXPAND(err, "${tmpdir}/%s/stderr", name);
393
394 540
        bprintf(buf, "rm -rf %s ; mkdir -p %s ; touch %s %s",
395
            p->dir, p->dir, p->out, p->err);
396 540
        AZ(system(buf));
397
398 540
        p->fd_term = -1;
399
400 540
        VTAILQ_INSERT_TAIL(&processes, p, list);
401 540
        teken_init(p->tek, &process_teken_func, p);
402 540
        term_resize(p, 24, 80);
403 540
        process_coverage(p);
404 540
        return (p);
405
}
406
407
#undef PROCESS_EXPAND
408
409
/**********************************************************************
410
 * Clean up process
411
 */
412
413
static void
414 540
process_delete(struct process *p)
415
{
416
        int i;
417
418 540
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
419 540
        AZ(pthread_mutex_destroy(&p->mtx));
420 540
        vtc_logclose(p->vl);
421 540
        free(p->name);
422 540
        free(p->dir);
423 540
        free(p->out);
424 540
        free(p->err);
425
426 13785
        for (i = 0; i < p->nlin; i++)
427 13245
                free(p->vram[i]);
428 540
        free(p->vram);
429
430
        /*
431
         * We do not delete the directory, it may contain useful stdout
432
         * and stderr files. They will be deleted on account of belonging
433
         * to the test's tmpdir.
434
         */
435
436
        /* XXX: MEMLEAK (?) */
437 540
        FREE_OBJ(p);
438 540
}
439
440
static void
441 540
process_undef(const struct process *p)
442
{
443 540
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
444
445 540
        macro_undef(p->vl, p->name, "dir");
446 540
        macro_undef(p->vl, p->name, "out");
447 540
        macro_undef(p->vl, p->name, "err");
448 540
}
449
450
/**********************************************************************
451
 * Data stream handling
452
 */
453
454
static int
455 1665
process_vlu_func(void *priv, const char *l)
456
{
457
        struct process *p;
458
459 1665
        CAST_OBJ_NOTNULL(p, priv, PROCESS_MAGIC);
460 1665
        vtc_dump(p->vl, 4, "output", l, -1);
461 1665
        return (0);
462
}
463
464
static int v_matchproto_(vev_cb_f)
465 7923
process_stdout(const struct vev *ev, int what)
466
{
467
        struct process *p;
468
        char buf[BUFSIZ];
469
        int i;
470
471 7923
        CAST_OBJ_NOTNULL(p, ev->priv, PROCESS_MAGIC);
472 7923
        (void)what;
473 7923
        i = read(p->fd_term, buf, sizeof buf);
474 7923
        if (i <= 0) {
475 645
                vtc_log(p->vl, 4, "stdout read %d", i);
476 645
                return (1);
477
        }
478 7278
        AZ(pthread_mutex_lock(&p->mtx));
479 7278
        p->stdout_bytes += i;
480 7278
        AZ(pthread_mutex_unlock(&p->mtx));
481 7278
        if (p->log == 1)
482 528
                (void)VLU_Feed(p->vlu_stdout, buf, i);
483 6750
        else if (p->log == 2)
484 1107
                vtc_dump(p->vl, 4, "stdout", buf, i);
485 5643
        else if (p->log == 3)
486 645
                vtc_hexdump(p->vl, 4, "stdout", buf, i);
487 7278
        assert(write(p->f_stdout, buf, i) == i);
488 7278
        AZ(pthread_mutex_lock(&p->mtx));
489 7278
        teken_input(p->tek, buf, i);
490 7278
        AZ(pthread_mutex_unlock(&p->mtx));
491 7278
        return (0);
492 7923
}
493
494
static int v_matchproto_(vev_cb_f)
495 841
process_stderr(const struct vev *ev, int what)
496
{
497
        struct process *p;
498
        char buf[BUFSIZ];
499
        int i;
500
501 841
        CAST_OBJ_NOTNULL(p, ev->priv, PROCESS_MAGIC);
502 841
        (void)what;
503 841
        i = read(p->fd_stderr, buf, sizeof buf);
504 841
        if (i <= 0) {
505 645
                vtc_log(p->vl, 4, "stderr read %d", i);
506 645
                return (1);
507
        }
508 196
        AZ(pthread_mutex_lock(&p->mtx));
509 196
        p->stderr_bytes += i;
510 196
        AZ(pthread_mutex_unlock(&p->mtx));
511 196
        vtc_dump(p->vl, 4, "stderr", buf, i);
512 196
        assert(write(p->f_stderr, buf, i) == i);
513 196
        return (0);
514 841
}
515
516
static void *
517 645
process_thread(void *priv)
518
{
519
        struct process *p;
520
        struct vev_root *evb;
521
        struct vev *ev;
522
        int r;
523
524 645
        CAST_OBJ_NOTNULL(p, priv, PROCESS_MAGIC);
525
526 645
        p->f_stdout = open(p->out, O_WRONLY|O_APPEND);
527 645
        assert(p->f_stdout >= 0);
528 645
        p->f_stderr = open(p->err, O_WRONLY|O_APPEND);
529 645
        assert(p->f_stderr >= 0);
530
531 645
        evb = VEV_New();
532 645
        AN(evb);
533
534 645
        ev = VEV_Alloc();
535 645
        AN(ev);
536 645
        ev->fd = p->fd_term;
537 645
        ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
538 645
        ev->callback = process_stdout;
539 645
        ev->priv = p;
540 645
        AZ(VEV_Start(evb, ev));
541
542 645
        ev = VEV_Alloc();
543 645
        AN(ev);
544 645
        ev->fd = p->fd_stderr;
545 645
        ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
546 645
        ev->callback = process_stderr;
547 645
        ev->priv = p;
548 645
        AZ(VEV_Start(evb, ev));
549
550 645
        if (p->log == 1) {
551 75
                p->vlu_stdout = VLU_New(process_vlu_func, p, 1024);
552 75
                AN(p->vlu_stdout);
553 75
                p->vlu_stderr = VLU_New(process_vlu_func, p, 1024);
554 75
                AN(p->vlu_stderr);
555 75
        }
556
557 645
        do {
558 9125
                r = VEV_Once(evb);
559 9125
        } while (r == 1);
560
561 645
        if (r < 0)
562 0
                vtc_fatal(p->vl, "VEV_Once() = %d, error %s", r,
563 0
                    strerror(errno));
564
565 1290
        vtc_wait4(p->vl, p->pid,
566 645
            p->expect_exit, p->expect_signal, p->allow_core);
567 645
        closefd(&p->f_stdout);
568 645
        closefd(&p->f_stderr);
569
570 645
        AZ(pthread_mutex_lock(&p->mtx));
571
572
        /* NB: We keep the other macros around */
573 645
        macro_undef(p->vl, p->name, "pid");
574 645
        p->pid = -1;
575
576 645
        AZ(pthread_mutex_unlock(&p->mtx));
577
578 645
        VEV_Destroy(&evb);
579 645
        if (p->log == 1) {
580 75
                VLU_Destroy(&p->vlu_stdout);
581 75
                VLU_Destroy(&p->vlu_stderr);
582 75
        }
583 645
        return (NULL);
584
}
585
586
static void
587 735
process_winsz(struct process *p, int fd)
588
{
589
        struct winsize ws;
590
        int i;
591
592 735
        memset(&ws, 0, sizeof ws);
593 735
        ws.ws_row = (short)p->nlin;
594 735
        ws.ws_col = (short)p->ncol;
595 735
        i = ioctl(fd, TIOCSWINSZ, &ws);
596 735
        if (i)
597 15
                vtc_log(p->vl, 4, "TIOCWINSZ %d %s", i, strerror(errno));
598 735
}
599
600
static void
601 645
process_init_term(struct process *p, int fd)
602
{
603
        struct termios tt;
604
        int i;
605
606 645
        process_winsz(p, fd);
607
608 645
        memset(&tt, 0, sizeof tt);
609 645
        tt.c_cflag = CREAD | CS8 | HUPCL;
610 645
        tt.c_iflag = BRKINT | ICRNL | IMAXBEL | IXON | IXANY;
611 645
        tt.c_lflag = ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOKE | ECHOCTL;
612 645
        tt.c_oflag = OPOST | ONLCR;
613 645
        i = cfsetispeed(&tt, B9600);
614 645
        if (i)
615 0
                vtc_log(p->vl, 4, "cfsetispeed %d %s", i, strerror(errno));
616 645
        i = cfsetospeed(&tt, B9600);
617 645
        if (i)
618 0
                vtc_log(p->vl, 4, "cfsetospeed %d %s", i, strerror(errno));
619 645
        tt.c_cc[VEOF] = '\x04';                 // CTRL-D
620 645
        tt.c_cc[VERASE] = '\x08';               // CTRL-H (Backspace)
621 645
        tt.c_cc[VKILL] = '\x15';                // CTRL-U
622 645
        tt.c_cc[VINTR] = '\x03';                // CTRL-C
623 645
        tt.c_cc[VQUIT] = '\x1c';                // CTRL-backslash
624
625 645
        i = tcsetattr(fd, TCSAFLUSH, &tt);
626 645
        if (i)
627 0
                vtc_log(p->vl, 4, "TCSAFLUSH %d %s", i, strerror(errno));
628 645
}
629
630
/**********************************************************************
631
 * Start the process thread
632
 */
633
634
static void
635 645
process_start(struct process *p)
636
{
637
        struct vsb *cl;
638
        int fd2[2];
639
        int master, slave;
640
        const char *slavename;
641
        char c;
642
643 645
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
644 645
        if (p->hasthread)
645 0
                vtc_fatal(p->vl, "Already running, -wait first");
646
647 645
        vtc_log(p->vl, 4, "CMD: %s", p->spec);
648
649 645
        cl = macro_expand(p->vl, p->spec);
650 645
        AN(cl);
651
652 645
        master = posix_openpt(O_RDWR|O_NOCTTY);
653 645
        assert(master >= 0);
654 645
        AZ(grantpt(master));
655 645
        AZ(unlockpt(master));
656 645
        slavename = ptsname(master);
657 645
        AN(slavename);
658
659 645
        AZ(pipe(fd2));
660
661 645
        p->pid = fork();
662 1290
        assert(p->pid >= 0);
663 1290
        if (p->pid == 0) {
664 645
                assert(setsid() == getpid());
665 645
                assert(dup2(fd2[1], STDERR_FILENO) == STDERR_FILENO);
666 645
                AZ(close(STDIN_FILENO));
667 645
                slave = open(slavename, O_RDWR);
668 645
                assert(slave == STDIN_FILENO);
669
#ifdef __sun
670
                if (ioctl(slave, I_PUSH, "ptem"))
671
                        vtc_log(p->vl, 4, "PUSH ptem: %s", strerror(errno));
672
                if (ioctl(slave, I_PUSH, "ldterm"))
673
                        vtc_log(p->vl, 4, "PUSH ldterm: %s", strerror(errno));
674
                (void)ioctl(STDIN_FILENO, TIOCSCTTY, NULL);
675
#else
676 645
                AZ(ioctl(STDIN_FILENO, TIOCSCTTY, NULL));
677
#endif
678 645
                AZ(close(STDOUT_FILENO));
679 645
                assert(dup2(slave, STDOUT_FILENO) == STDOUT_FILENO);
680 645
                VSUB_closefrom(STDERR_FILENO + 1);
681 645
                process_init_term(p, slave);
682
683 645
                AZ(setenv("TERM", "xterm", 1));
684 645
                AZ(unsetenv("TERMCAP"));
685
                // Not using NULL because GCC is now even more demented...
686 645
                assert(write(STDERR_FILENO, "+", 1) == 1);
687 645
                AZ(execl("/bin/sh", "/bin/sh", "-c", VSB_data(cl), (char*)0));
688 0
                exit(1);
689
        }
690 645
        vtc_log(p->vl, 3, "PID: %ld", (long)p->pid);
691 645
        VSB_destroy(&cl);
692
693 645
        assert(read(fd2[0], &c, 1) == 1);
694 645
        p->fd_term = master;
695 645
        closefd(&fd2[1]);
696 645
        p->fd_stderr = fd2[0];
697 645
        macro_def(p->vl, p->name, "pid", "%ld", (long)p->pid);
698 645
        macro_def(p->vl, p->name, "dir", "%s", p->dir);
699 645
        macro_def(p->vl, p->name, "out", "%s", p->out);
700 645
        macro_def(p->vl, p->name, "err", "%s", p->err);
701 645
        p->hasthread = 1;
702 645
        AZ(pthread_create(&p->tp, NULL, process_thread, p));
703 645
}
704
705
/**********************************************************************
706
 * Wait for process thread to stop
707
 */
708
709
static void
710 645
process_wait(struct process *p)
711
{
712
        void *v;
713
714 645
        if (p->hasthread) {
715 645
                AZ(pthread_join(p->tp, &v));
716 645
                p->hasthread = 0;
717 645
        }
718 1290
        vtc_log(p->vl, 4, "stdout %ju bytes, stderr %ju bytes",
719 645
            p->stdout_bytes, p->stderr_bytes);
720 645
}
721
722
/**********************************************************************
723
 * Send a signal to a process
724
 */
725
726
static void
727 225
process_kill(struct process *p, const char *sig)
728
{
729 225
        int j = 0;
730
        pid_t pid;
731
732 225
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
733 225
        AN(sig);
734
735 225
        AZ(pthread_mutex_lock(&p->mtx));
736 225
        pid = p->pid;
737 225
        AZ(pthread_mutex_unlock(&p->mtx));
738
739 225
        if (pid <= 0)
740 0
                vtc_fatal(p->vl, "Cannot signal a non-running process");
741
742 225
        if (!strcmp(sig, "TERM"))
743 165
                j = SIGTERM;
744 60
        else if (!strcmp(sig, "INT"))
745 15
                j = SIGINT;
746 45
        else if (!strcmp(sig, "KILL"))
747 30
                j = SIGKILL;
748 15
        else if (!strcmp(sig, "HUP"))
749 15
                j = SIGHUP;
750 0
        else if (*sig == '-')
751 0
                j = strtoul(sig + 1, NULL, 10);
752
        else
753 0
                vtc_fatal(p->vl, "Could not grok signal (%s)", sig);
754
755 225
        if (p->expect_signal == 0)
756 225
                p->expect_signal = -j;
757 225
        if (kill(-pid, j) < 0)
758 0
                vtc_fatal(p->vl, "Failed to send signal %d (%s)",
759 0
                    j, strerror(errno));
760
        else
761 225
                vtc_log(p->vl, 4, "Sent signal %d", j);
762 225
}
763
764
/**********************************************************************
765
 * Write to a process' stdin
766
 */
767
768
static void
769 1800
process_write(const struct process *p, const char *text)
770
{
771
        int r, len;
772
773 1800
        if (!p->hasthread)
774 0
                vtc_fatal(p->vl, "Cannot write to a non-running process");
775
776 1800
        len = strlen(text);
777 1800
        vtc_log(p->vl, 4, "Writing %d bytes", len);
778 1800
        r = write(p->fd_term, text, len);
779 1800
        if (r != len)
780 0
                vtc_fatal(p->vl, "Failed to write: len=%d %s (%d)",
781 0
                    len, strerror(errno), errno);
782 1800
}
783
784
static void
785 1875
process_write_hex(const struct process *p, const char *text)
786
{
787
        struct vsb *vsb;
788
789 1875
        if (!p->hasthread)
790 0
                vtc_fatal(p->vl, "Cannot write to a non-running process");
791
792 1875
        vsb = vtc_hex_to_bin(p->vl, text);
793 1875
        assert(VSB_len(vsb) >= 0);
794 1875
        vtc_hexdump(p->vl, 4, "sendhex", VSB_data(vsb), VSB_len(vsb));
795 1875
        AZ(VSB_tofile(p->fd_term, vsb));
796 1875
        VSB_destroy(&vsb);
797 1875
}
798
799
static void
800 0
process_close(struct process *p)
801
{
802
803 0
        if (!p->hasthread)
804 0
                vtc_fatal(p->vl, "Cannot close a non-running process");
805
806 0
        process_kill(p, "HUP");
807 0
}
808
809
/* SECTION: process process
810
 *
811
 * Run a process with stdin+stdout on a pseudo-terminal and stderr on a pipe.
812
 *
813
 * Output from the pseudo-terminal is copied verbatim to ${pNAME_out},
814
 * and the -log/-dump/-hexdump flags will also put it in the vtc-log.
815
 *
816
 * The pseudo-terminal is not in ECHO mode, but if the programs run set
817
 * it to ECHO mode ("stty sane") any input sent to the process will also
818
 * appear in this stream because of the ECHO.
819
 *
820
 * Output from the stderr-pipe is copied verbatim to ${pNAME_err}, and
821
 * is always included in the vtc_log.
822
 *
823
 *      process pNAME SPEC [-log] [-dump] [-hexdump] [-expect-exit N]
824
 *              [-start] [-run]
825
 *              [-write STRING] [-writeln STRING]
826
 *              [-kill STRING] [-stop] [-wait] [-close]
827
 *
828
 * pNAME
829
 *      Name of the process. It must start with 'p'.
830
 *
831
 * SPEC
832
 *      The command(s) to run in this process.
833
 *
834
 * \-hexdump
835
 *      Log output with vtc_hexdump(). Must be before -start/-run.
836
 *
837
 * \-dump
838
 *      Log output with vtc_dump(). Must be before -start/-run.
839
 *
840
 * \-log
841
 *      Log output with VLU/vtc_log(). Must be before -start/-run.
842
 *
843
 * \-start
844
 *      Start the process.
845
 *
846
 * \-expect-exit N
847
 *      Expect exit status N
848
 *
849
 * \-wait
850
 *      Wait for the process to finish.
851
 *
852
 * \-run
853
 *      Shorthand for -start -wait.
854
 *
855
 *      In most cases, if you just want to start a process and wait for it
856
 *      to finish, you can use the ``shell`` command instead.
857
 *      The following commands are equivalent::
858
 *
859
 *          shell "do --something"
860
 *
861
 *          process p1 "do --something" -run
862
 *
863
 *      However, you may use the the ``process`` variant to conveniently
864
 *      collect the standard input and output without dealing with shell
865
 *      redirections yourself. The ``shell`` command can also expect an
866
 *      expression from either output, consider using it if you only need
867
 *      to match one.
868
 *
869
 * \-kill STRING
870
 *      Send a signal to the process. The argument can be either
871
 *      the string "TERM", "INT", or "KILL" for SIGTERM, SIGINT or SIGKILL
872
 *      signals, respectively, or a hyphen (-) followed by the signal
873
 *      number.
874
 *
875
 *      If you need to use other signal names, you can use the ``kill``\(1)
876
 *      command directly::
877
 *
878
 *          shell "kill -USR1 ${pNAME_pid}"
879
 *
880
 *      Note that SIGHUP usage is discouraged in test cases.
881
 *
882
 * \-stop
883
 *      Shorthand for -kill TERM.
884
 *
885
 * \-write STRING
886
 *      Write a string to the process' stdin.
887
 *
888
 * \-writeln STRING
889
 *      Same as -write followed by a newline (\\n).
890
 *
891
 * \-writehex HEXSTRING
892
 *      Same as -write but interpreted as hexadecimal bytes.
893
 *
894
 * \-need-bytes [+]NUMBER
895
 *      Wait until at least NUMBER bytes have been received in total.
896
 *      If '+' is prefixed, NUMBER new bytes must be received.
897
 *
898
 * \-expect-text LIN COL PAT
899
 *      Wait for PAT to appear at LIN,COL on the virtual screen.
900
 *      Lines and columns are numbered 1...N
901
 *      LIN==0 means "on any line"
902
 *      COL==0 means "anywhere on the line"
903
 *
904
 * \-close
905
 *      Alias for "-kill HUP"
906
 *
907
 * \-screen_dump
908
 *      Dump the virtual screen into vtc_log
909
 *
910
 */
911
912
void
913 21645
cmd_process(CMD_ARGS)
914
{
915
        struct process *p, *p2;
916
        uintmax_t u, v, bsnap;
917
        unsigned lin,col;
918 21645
        int spec_set = 0;
919
920 21645
        (void)priv;
921 21645
        (void)cmd;
922
923 21645
        if (av == NULL) {
924
                /* Reset and free */
925 12540
                VTAILQ_FOREACH_SAFE(p, &processes, list, p2) {
926 540
                        if (p->pid > 0) {
927 30
                                process_kill(p, "TERM");
928 30
                                sleep(1);
929 30
                                if (p->pid > 0)
930 0
                                        process_kill(p, "KILL");
931 30
                        }
932 540
                        if (p->hasthread)
933 60
                                process_wait(p);
934 540
                        VTAILQ_REMOVE(&processes, p, list);
935 540
                        process_undef(p);
936 540
                        process_delete(p);
937 540
                }
938 12000
                return;
939
        }
940
941 9645
        AZ(strcmp(av[0], "process"));
942 9645
        av++;
943
944 9645
        VTC_CHECK_NAME(vl, av[0], "Process", 'p');
945 24690
        VTAILQ_FOREACH(p, &processes, list)
946 24150
                if (!strcmp(p->name, av[0]))
947 9105
                        break;
948 9645
        if (p == NULL)
949 540
                p = process_new(av[0]);
950 9645
        av++;
951
952 9645
        bsnap = p->stdout_bytes;
953
954 20880
        for (; *av != NULL; av++) {
955 11235
                if (vtc_error)
956 0
                        break;
957
958 11235
                if (!strcmp(*av, "-allow-core")) {
959 0
                        p->allow_core = 1;
960 0
                        continue;
961
                }
962 11235
                if (!strcmp(*av, "-close")) {
963 0
                        process_close(p);
964 0
                        continue;
965
                }
966 11235
                if (!strcmp(*av, "-dump")) {
967 150
                        if (p->hasthread)
968 0
                                vtc_fatal(p->vl,
969
                                    "Cannot dump a running process");
970 150
                        p->log = 2;
971 150
                        continue;
972
                }
973 11085
                if (!strcmp(*av, "-expect-exit")) {
974 45
                        p->expect_exit = strtoul(av[1], NULL, 0);
975 45
                        av++;
976 45
                        continue;
977
                }
978 11040
                if (!strcmp(*av, "-expect-signal")) {
979 0
                        p->expect_signal = strtoul(av[1], NULL, 0);
980 0
                        av++;
981 0
                        continue;
982
                }
983 11040
                if (!strcmp(*av, "-hexdump")) {
984 60
                        if (p->hasthread)
985 0
                                vtc_fatal(p->vl,
986
                                    "Cannot dump a running process");
987 60
                        p->log = 3;
988 60
                        continue;
989
                }
990 10980
                if (!strcmp(*av, "-kill")) {
991 90
                        process_kill(p, av[1]);
992 90
                        av++;
993 90
                        continue;
994
                }
995 10890
                if (!strcmp(*av, "-log")) {
996 75
                        if (p->hasthread)
997 0
                                vtc_fatal(p->vl,
998
                                    "Cannot log a running process");
999 75
                        p->log = 1;
1000 75
                        continue;
1001
                }
1002 10815
                if (!strcmp(*av, "-need-bytes")) {
1003 135
                        u = strtoumax(av[1], NULL, 0);
1004 135
                        if (av[1][0] == '+')
1005 105
                                u += bsnap;
1006 135
                        av++;
1007 135
                        do {
1008 263
                                AZ(pthread_mutex_lock(&p->mtx));
1009 263
                                v = p->stdout_bytes;
1010 263
                                AZ(pthread_mutex_unlock(&p->mtx));
1011 263
                                vtc_log(p->vl, 4, "Have %ju bytes", v);
1012 263
                                usleep(500000);
1013 263
                        } while(v < u);
1014 135
                        continue;
1015
                }
1016 10680
                if (!strcmp(*av, "-run")) {
1017 150
                        process_start(p);
1018 150
                        process_wait(p);
1019 150
                        continue;
1020
                }
1021 10530
                if (!strcmp(*av, "-ansi-response")) {
1022 30
                        p->ansi_response = 1;
1023 30
                        continue;
1024
                }
1025 10500
                if (!strcmp(*av, "-expect-text")) {
1026 3195
                        AN(av[1]);
1027 3195
                        AN(av[2]);
1028 3195
                        AN(av[3]);
1029 3195
                        term_expect_text(p, av[1], av[2], av[3]);
1030 3195
                        av += 3;
1031 3195
                        continue;
1032
                }
1033 7305
                if (!strcmp(*av, "-expect-cursor")) {
1034 120
                        AN(av[1]);
1035 120
                        AN(av[2]);
1036 120
                        term_expect_cursor(p, av[1], av[2]);
1037 120
                        av += 2;
1038 120
                        continue;
1039
                }
1040 7185
                if (!strcmp(*av, "-screen_dump") ||
1041 5370
                    !strcmp(*av, "-screen-dump")) {
1042 1920
                        term_screen_dump(p);
1043 1920
                        continue;
1044
                }
1045 5265
                if (!strcmp(*av, "-start")) {
1046 495
                        process_start(p);
1047 495
                        continue;
1048
                }
1049 4770
                if (!strcmp(*av, "-stop")) {
1050 105
                        process_kill(p, "TERM");
1051 105
                        sleep(1);
1052 105
                        continue;
1053
                }
1054 4665
                if (!strcmp(*av, "-wait")) {
1055 435
                        process_wait(p);
1056 435
                        continue;
1057
                }
1058 4230
                if (!strcmp(*av, "-winsz")) {
1059 90
                        lin = atoi(av[1]);
1060 90
                        assert(lin > 1);
1061 90
                        col = atoi(av[2]);
1062 90
                        assert(col > 1);
1063 90
                        av += 2;
1064 90
                        AZ(pthread_mutex_lock(&p->mtx));
1065 90
                        term_resize(p, lin, col);
1066 90
                        AZ(pthread_mutex_unlock(&p->mtx));
1067 90
                        process_winsz(p, p->fd_term);
1068 90
                        continue;
1069
                }
1070 4140
                if (!strcmp(*av, "-write")) {
1071 1560
                        process_write(p, av[1]);
1072 1560
                        av++;
1073 1560
                        continue;
1074
                }
1075 2580
                if (!strcmp(*av, "-writehex")) {
1076 1875
                        process_write_hex(p, av[1]);
1077 1875
                        av++;
1078 1875
                        continue;
1079
                }
1080 705
                if (!strcmp(*av, "-writeln")) {
1081 120
                        process_write(p, av[1]);
1082 120
                        process_write(p, "\n");
1083 120
                        av++;
1084 120
                        continue;
1085
                }
1086 585
                if (**av == '-' || spec_set)
1087 0
                        vtc_fatal(p->vl, "Unknown process argument: %s", *av);
1088 585
                REPLACE(p->spec, *av);
1089 585
                spec_set = 1;
1090 585
        }
1091 21645
}