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 408647
term_cursor(void *priv, const teken_pos_t *pos)
106
{
107 408647
        (void)priv;
108 408647
        (void)pos;
109 408647
}
110
111
static void
112 3134615
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 3134615
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
118 3134615
        (void)at;
119 3134615
        if (ch > 126 || ch < 32)
120 2248
                ch = '?';
121 3134615
        assert(pos->tp_row < pp->nlin);
122 3134615
        assert(pos->tp_col < pp->ncol);
123 3134615
        pp->vram[pos->tp_row][pos->tp_col] = ch;
124 3134615
}
125
126
static void
127 5872
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 36668
        for (p.tp_row = r->tr_begin.tp_row;
134 36668
            p.tp_row < r->tr_end.tp_row; p.tp_row++)
135 2798680
                for (p.tp_col = r->tr_begin.tp_col;
136 2798680
                    p.tp_col < r->tr_end.tp_col; p.tp_col++)
137 2798680
                        term_putchar(priv, &p, c, a);
138 5872
}
139
140
static void
141 5968
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 5968
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
151
152 5968
        nrow = r->tr_end.tp_row - r->tr_begin.tp_row;
153 5968
        ncol = r->tr_end.tp_col - r->tr_begin.tp_col;
154
155 5968
        if (p->tp_row < r->tr_begin.tp_row) {
156
                /* Copy from top to bottom. */
157 25328
                for (y = 0; y < nrow; y++)
158 47184
                        memmove(&pp->vram[p->tp_row + y][p->tp_col],
159 23592
                            &pp->vram[r->tr_begin.tp_row + y][r->tr_begin.tp_col], ncol);
160 1736
        } else {
161
                /* Copy from bottom to top. */
162 23640
                for (y = nrow - 1; y >= 0; y--)
163 38816
                        memmove(&pp->vram[p->tp_row + y][p->tp_col],
164 19408
                            &pp->vram[r->tr_begin.tp_row + y][r->tr_begin.tp_col], ncol);
165
        }
166 5968
}
167
168
static void
169 64
term_respond(void *priv, const void *p, size_t l)
170
{
171
        struct process *pp;
172
        int r;
173
174 64
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
175
176 64
        vtc_dump(pp->vl, 4, "term_response", p, l);
177 64
        if (pp->ansi_response) {
178 8
                r = write(pp->fd_term, p, l);
179 8
                if (r != l)
180 0
                        vtc_fatal(pp->vl, "Could not write to process: %s",
181 0
                            strerror(errno));
182 8
        }
183 64
}
184
185
static void
186 436
term_param(void *priv, int p, unsigned int v)
187
{
188
        struct process *pp;
189
190 436
        CAST_OBJ_NOTNULL(pp, priv, PROCESS_MAGIC);
191 436
        if (p == TP_132COLS && v)
192 48
                term_resize(pp, pp->nlin, 132);
193 436
        if (p == TP_132COLS && !v)
194 96
                term_resize(pp, pp->nlin, 80);
195 436
}
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 516
term_screen_dump(const struct process *pp)
208
{
209
        int i;
210
        const teken_pos_t *pos;
211
212 12976
        for (i = 0; i < pp->nlin; i++)
213 12460
                vtc_dump(pp->vl, 3, "screen", pp->vram[i], pp->ncol);
214 516
        pos = teken_get_cursor(pp->tek);
215 1032
        vtc_log(pp->vl, 3, "Cursor at line %d column %d",
216 516
            pos->tp_row + 1, pos->tp_col + 1);
217 516
}
218
219
static void
220 308
term_resize(struct process *pp, int lin, int col)
221
{
222
        teken_pos_t pos;
223
        char **vram;
224
        int i, j;
225
226 308
        vram = calloc(lin, sizeof *pp->vram);
227 308
        AN(vram);
228 7776
        for (i = 0; i < lin; i++) {
229 7468
                vram[i] = calloc(col + 1L, 1);
230 7468
                AN(vram[i]);
231 7468
                memset(vram[i], ' ', col);
232 7468
                vram[i][col] = '\0';
233 7468
        }
234 308
        if (pp->vram != NULL) {
235 4196
                for (i = 0; i < lin; i++) {
236 4048
                        if (i >= pp->nlin)
237 20
                                break;
238 4028
                        j = col;
239 4028
                        if (j > pp->ncol)
240 1344
                                j = pp->ncol;
241 4028
                        memcpy(vram[i], pp->vram[i], j);
242 4028
                }
243 4200
                for (i = 0; i < pp->nlin; i++)
244 4032
                        free(pp->vram[i]);
245 168
                free(pp->vram);
246 168
        }
247 308
        pp->vram = vram;
248 308
        pp->nlin = lin;
249 308
        pp->ncol = col;
250
251 308
        pos.tp_row = lin;
252 308
        pos.tp_col = col;
253 308
        teken_set_winsize(pp->tek, &pos);
254 308
}
255
256
static int
257 10135
term_match_textline(const struct process *pp, int *x, int y, const char *pat)
258
{
259
        const char *t;
260
261 10135
        if (*x == 0) {
262 7024
                t = strstr(pp->vram[y], pat);
263 7024
                if (t != NULL) {
264 192
                        *x = 1 + (t - pp->vram[y]);
265 192
                        return (1);
266
                }
267 9943
        } else if (*x <= pp->ncol) {
268 3096
                t = pp->vram[y] + *x - 1;
269 3096
                if (!memcmp(t, pat, strlen(pat)))
270 664
                        return (1);
271 2432
        }
272 9279
        return (0);
273 10135
}
274
275
static int
276 1739
term_match_text(const struct process *pp, int *x, int *y, const char *pat)
277
{
278
        int yy;
279
280 1739
        if (*y == 0) {
281 9136
                for (yy = 0; yy < pp->nlin; yy++) {
282 8860
                        if (term_match_textline(pp, x, yy, pat)) {
283 188
                                *y = yy + 1;
284 188
                                return (1);
285
                        }
286 8672
                }
287 1551
        } else if (*y <= pp->nlin) {
288 1275
                if (term_match_textline(pp, x, *y - 1, pat))
289 668
                        return (1);
290 607
        }
291 883
        return (0);
292 1739
}
293
294
static void
295 856
term_expect_text(struct process *pp,
296
    const char *lin, const char *col, const char *pat)
297
{
298 856
        int x, y, l, d = 10000;
299
        char *t;
300
301 856
        y = strtoul(lin, NULL, 0);
302 856
        x = strtoul(col, NULL, 0);
303 856
        l = strlen(pat);
304 856
        AZ(pthread_mutex_lock(&pp->mtx));
305 1739
        while (!term_match_text(pp, &x, &y, pat)) {
306 883
                if (x != 0 && y != 0) {
307 523
                        t = pp->vram[y - 1] + x - 1;
308 1046
                        vtc_log(pp->vl, 4,
309 523
                            "text at %d,%d: '%.*s'", y, x, l, t);
310 523
                }
311 883
                AZ(pthread_mutex_unlock(&pp->mtx));
312 883
                usleep(d);
313 883
                AZ(pthread_mutex_lock(&pp->mtx));
314 883
                if (d < 300000)
315 823
                        d += d;
316
        }
317 856
        AZ(pthread_mutex_unlock(&pp->mtx));
318 856
        vtc_log(pp->vl, 4, "found expected text at %d,%d: '%s'", y, x, pat);
319 856
}
320
321
static void
322 32
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 32
        pos = teken_get_cursor(pp->tek);
328 32
        y = strtoul(lin, NULL, 0);
329 32
        x = strtoul(col, NULL, 0);
330 32
        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 32
        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 32
}
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 140
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 140
        (void)teken_get_sequence(p->tek, TKEY_UP);
361 140
        (void)teken_get_sequence(p->tek, TKEY_F1);
362 140
        (void)teken_256to8(0);
363 140
        (void)teken_256to16(0);
364 140
        a = teken_get_defattr(p->tek);
365 140
        teken_set_defattr(p->tek, a);
366 140
        a = teken_get_curattr(p->tek);
367 140
        teken_set_curattr(p->tek, a);
368 140
        (void)teken_get_winsize(p->tek);
369 140
        pos.tp_row = 0;
370 140
        pos.tp_col = 8;
371 140
        teken_set_cursor(p->tek, &pos);
372 140
        teken_get_defattr_cons25(p->tek, &fg, &bg);
373 140
}
374
375
static struct process *
376 140
process_new(const char *name)
377
{
378
        struct process *p;
379
        struct vsb *vsb;
380
        char buf[1024];
381
382 140
        ALLOC_OBJ(p, PROCESS_MAGIC);
383 140
        AN(p);
384 140
        REPLACE(p->name, name);
385 140
        AZ(pthread_mutex_init(&p->mtx, NULL));
386
387 140
        p->vl = vtc_logopen(name);
388 140
        AN(p->vl);
389
390 140
        PROCESS_EXPAND(dir, "${tmpdir}/%s", name);
391 140
        PROCESS_EXPAND(out, "${tmpdir}/%s/term", name);
392 140
        PROCESS_EXPAND(err, "${tmpdir}/%s/stderr", name);
393
394 140
        bprintf(buf, "rm -rf %s ; mkdir -p %s ; touch %s %s",
395
            p->dir, p->dir, p->out, p->err);
396 140
        AZ(system(buf));
397
398 140
        p->fd_term = -1;
399
400 140
        VTAILQ_INSERT_TAIL(&processes, p, list);
401 140
        teken_init(p->tek, &process_teken_func, p);
402 140
        term_resize(p, 24, 80);
403 140
        process_coverage(p);
404 140
        return (p);
405
}
406
407
#undef PROCESS_EXPAND
408
409
/**********************************************************************
410
 * Clean up process
411
 */
412
413
static void
414 140
process_delete(struct process *p)
415
{
416
        int i;
417
418 140
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
419 140
        AZ(pthread_mutex_destroy(&p->mtx));
420 140
        vtc_logclose(p->vl);
421 140
        free(p->name);
422 140
        free(p->dir);
423 140
        free(p->out);
424 140
        free(p->err);
425
426 3576
        for (i = 0; i < p->nlin; i++)
427 3436
                free(p->vram[i]);
428 140
        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 140
        FREE_OBJ(p);
438 140
}
439
440
static void
441 140
process_undef(const struct process *p)
442
{
443 140
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
444
445 140
        macro_undef(p->vl, p->name, "dir");
446 140
        macro_undef(p->vl, p->name, "out");
447 140
        macro_undef(p->vl, p->name, "err");
448 140
}
449
450
/**********************************************************************
451
 * Data stream handling
452
 */
453
454
static int
455 444
process_vlu_func(void *priv, const char *l)
456
{
457
        struct process *p;
458
459 444
        CAST_OBJ_NOTNULL(p, priv, PROCESS_MAGIC);
460 444
        vtc_dump(p->vl, 4, "output", l, -1);
461 444
        return (0);
462
}
463
464
static int v_matchproto_(vev_cb_f)
465 2076
process_stdout(const struct vev *ev, int what)
466
{
467
        struct process *p;
468
        char buf[BUFSIZ];
469
        int i;
470
471 2076
        CAST_OBJ_NOTNULL(p, ev->priv, PROCESS_MAGIC);
472 2076
        (void)what;
473 2076
        i = read(p->fd_term, buf, sizeof buf);
474 2076
        if (i <= 0) {
475 140
                vtc_log(p->vl, 4, "stdout read %d", i);
476 140
                return (1);
477
        }
478 1936
        AZ(pthread_mutex_lock(&p->mtx));
479 1936
        p->stdout_bytes += i;
480 1936
        AZ(pthread_mutex_unlock(&p->mtx));
481 1936
        if (p->log == 1)
482 147
                (void)VLU_Feed(p->vlu_stdout, buf, i);
483 1789
        else if (p->log == 2)
484 273
                vtc_dump(p->vl, 4, "stdout", buf, i);
485 1516
        else if (p->log == 3)
486 176
                vtc_hexdump(p->vl, 4, "stdout", buf, i);
487 1936
        assert(write(p->f_stdout, buf, i) == i);
488 1936
        AZ(pthread_mutex_lock(&p->mtx));
489 1936
        teken_input(p->tek, buf, i);
490 1936
        AZ(pthread_mutex_unlock(&p->mtx));
491 1936
        return (0);
492 2076
}
493
494
static int v_matchproto_(vev_cb_f)
495 193
process_stderr(const struct vev *ev, int what)
496
{
497
        struct process *p;
498
        char buf[BUFSIZ];
499
        int i;
500
501 193
        CAST_OBJ_NOTNULL(p, ev->priv, PROCESS_MAGIC);
502 193
        (void)what;
503 193
        i = read(p->fd_stderr, buf, sizeof buf);
504 193
        if (i <= 0) {
505 140
                vtc_log(p->vl, 4, "stderr read %d", i);
506 140
                return (1);
507
        }
508 53
        AZ(pthread_mutex_lock(&p->mtx));
509 53
        p->stderr_bytes += i;
510 53
        AZ(pthread_mutex_unlock(&p->mtx));
511 53
        vtc_dump(p->vl, 4, "stderr", buf, i);
512 53
        assert(write(p->f_stderr, buf, i) == i);
513 53
        return (0);
514 193
}
515
516
static void *
517 140
process_thread(void *priv)
518
{
519
        struct process *p;
520
        struct vev_root *evb;
521
        struct vev *ev;
522
        int r;
523
524 140
        CAST_OBJ_NOTNULL(p, priv, PROCESS_MAGIC);
525
526 140
        p->f_stdout = open(p->out, O_WRONLY|O_APPEND);
527 140
        assert(p->f_stdout >= 0);
528 140
        p->f_stderr = open(p->err, O_WRONLY|O_APPEND);
529 140
        assert(p->f_stderr >= 0);
530
531 140
        evb = VEV_New();
532 140
        AN(evb);
533
534 140
        ev = VEV_Alloc();
535 140
        AN(ev);
536 140
        ev->fd = p->fd_term;
537 140
        ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
538 140
        ev->callback = process_stdout;
539 140
        ev->priv = p;
540 140
        AZ(VEV_Start(evb, ev));
541
542 140
        ev = VEV_Alloc();
543 140
        AN(ev);
544 140
        ev->fd = p->fd_stderr;
545 140
        ev->fd_flags = VEV__RD | VEV__HUP | VEV__ERR;
546 140
        ev->callback = process_stderr;
547 140
        ev->priv = p;
548 140
        AZ(VEV_Start(evb, ev));
549
550 140
        if (p->log == 1) {
551 20
                p->vlu_stdout = VLU_New(process_vlu_func, p, 1024);
552 20
                AN(p->vlu_stdout);
553 20
                p->vlu_stderr = VLU_New(process_vlu_func, p, 1024);
554 20
                AN(p->vlu_stderr);
555 20
        }
556
557 140
        do {
558 2369
                r = VEV_Once(evb);
559 2369
        } while (r == 1);
560
561 140
        if (r < 0)
562 0
                vtc_fatal(p->vl, "VEV_Once() = %d, error %s", r,
563 0
                    strerror(errno));
564
565 280
        vtc_wait4(p->vl, p->pid,
566 140
            p->expect_exit, p->expect_signal, p->allow_core);
567 140
        closefd(&p->f_stdout);
568 140
        closefd(&p->f_stderr);
569
570 140
        AZ(pthread_mutex_lock(&p->mtx));
571
572
        /* NB: We keep the other macros around */
573 140
        macro_undef(p->vl, p->name, "pid");
574 140
        p->pid = -1;
575
576 140
        AZ(pthread_mutex_unlock(&p->mtx));
577
578 140
        VEV_Destroy(&evb);
579 140
        if (p->log == 1) {
580 20
                VLU_Destroy(&p->vlu_stdout);
581 20
                VLU_Destroy(&p->vlu_stderr);
582 20
        }
583 140
        return (NULL);
584
}
585
586
static void
587 164
process_winsz(struct process *p, int fd)
588
{
589
        struct winsize ws;
590
        int i;
591
592 164
        memset(&ws, 0, sizeof ws);
593 164
        ws.ws_row = (short)p->nlin;
594 164
        ws.ws_col = (short)p->ncol;
595 164
        i = ioctl(fd, TIOCSWINSZ, &ws);
596 164
        if (i)
597 4
                vtc_log(p->vl, 4, "TIOCWINSZ %d %s", i, strerror(errno));
598 164
}
599
600
static void
601 140
process_init_term(struct process *p, int fd)
602
{
603
        struct termios tt;
604
        int i;
605
606 140
        process_winsz(p, fd);
607
608 140
        memset(&tt, 0, sizeof tt);
609 140
        tt.c_cflag = CREAD | CS8 | HUPCL;
610 140
        tt.c_iflag = BRKINT | ICRNL | IMAXBEL | IXON | IXANY;
611 140
        tt.c_lflag = ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOKE | ECHOCTL;
612 140
        tt.c_oflag = OPOST | ONLCR;
613 140
        i = cfsetispeed(&tt, B9600);
614 140
        if (i)
615 0
                vtc_log(p->vl, 4, "cfsetispeed %d %s", i, strerror(errno));
616 140
        i = cfsetospeed(&tt, B9600);
617 140
        if (i)
618 0
                vtc_log(p->vl, 4, "cfsetospeed %d %s", i, strerror(errno));
619 140
        tt.c_cc[VEOF] = '\x04';                 // CTRL-D
620 140
        tt.c_cc[VERASE] = '\x08';               // CTRL-H (Backspace)
621 140
        tt.c_cc[VKILL] = '\x15';                // CTRL-U
622 140
        tt.c_cc[VINTR] = '\x03';                // CTRL-C
623 140
        tt.c_cc[VQUIT] = '\x1c';                // CTRL-backslash
624
625 140
        i = tcsetattr(fd, TCSAFLUSH, &tt);
626 140
        if (i)
627 0
                vtc_log(p->vl, 4, "TCSAFLUSH %d %s", i, strerror(errno));
628 140
}
629
630
/**********************************************************************
631
 * Start the process thread
632
 */
633
634
static void
635 140
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 140
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
644 140
        if (p->hasthread)
645 0
                vtc_fatal(p->vl, "Already running, -wait first");
646
647 140
        vtc_log(p->vl, 4, "CMD: %s", p->spec);
648
649 140
        cl = macro_expand(p->vl, p->spec);
650 140
        AN(cl);
651
652 140
        master = posix_openpt(O_RDWR|O_NOCTTY);
653 140
        assert(master >= 0);
654 140
        AZ(grantpt(master));
655 140
        AZ(unlockpt(master));
656 140
        slavename = ptsname(master);
657 140
        AN(slavename);
658
659 140
        AZ(pipe(fd2));
660
661 140
        p->pid = fork();
662 280
        assert(p->pid >= 0);
663 280
        if (p->pid == 0) {
664 140
                assert(setsid() == getpid());
665 140
                assert(dup2(fd2[1], STDERR_FILENO) == STDERR_FILENO);
666 140
                AZ(close(STDIN_FILENO));
667 140
                slave = open(slavename, O_RDWR);
668 140
                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 140
                AZ(ioctl(STDIN_FILENO, TIOCSCTTY, NULL));
677
#endif
678 140
                AZ(close(STDOUT_FILENO));
679 140
                assert(dup2(slave, STDOUT_FILENO) == STDOUT_FILENO);
680 140
                VSUB_closefrom(STDERR_FILENO + 1);
681 140
                process_init_term(p, slave);
682
683 140
                AZ(setenv("TERM", "xterm", 1));
684 140
                AZ(unsetenv("TERMCAP"));
685
                // Not using NULL because GCC is now even more demented...
686 140
                assert(write(STDERR_FILENO, "+", 1) == 1);
687 140
                AZ(execl("/bin/sh", "/bin/sh", "-c", VSB_data(cl), (char*)0));
688 0
                exit(1);
689
        }
690 140
        vtc_log(p->vl, 3, "PID: %ld", (long)p->pid);
691 140
        VSB_destroy(&cl);
692
693 140
        assert(read(fd2[0], &c, 1) == 1);
694 140
        p->fd_term = master;
695 140
        closefd(&fd2[1]);
696 140
        p->fd_stderr = fd2[0];
697 140
        macro_def(p->vl, p->name, "pid", "%ld", (long)p->pid);
698 140
        macro_def(p->vl, p->name, "dir", "%s", p->dir);
699 140
        macro_def(p->vl, p->name, "out", "%s", p->out);
700 140
        macro_def(p->vl, p->name, "err", "%s", p->err);
701 140
        p->hasthread = 1;
702 140
        AZ(pthread_create(&p->tp, NULL, process_thread, p));
703 140
}
704
705
/**********************************************************************
706
 * Wait for process thread to stop
707
 */
708
709
static void
710 140
process_wait(struct process *p)
711
{
712
        void *v;
713
714 140
        if (p->hasthread) {
715 140
                AZ(pthread_join(p->tp, &v));
716 140
                p->hasthread = 0;
717 140
        }
718 280
        vtc_log(p->vl, 4, "stdout %ju bytes, stderr %ju bytes",
719 140
            p->stdout_bytes, p->stderr_bytes);
720 140
}
721
722
/**********************************************************************
723
 * Send a signal to a process
724
 */
725
726
static void
727 60
process_kill(struct process *p, const char *sig)
728
{
729 60
        int j = 0;
730
        pid_t pid;
731
732 60
        CHECK_OBJ_NOTNULL(p, PROCESS_MAGIC);
733 60
        AN(sig);
734
735 60
        AZ(pthread_mutex_lock(&p->mtx));
736 60
        pid = p->pid;
737 60
        AZ(pthread_mutex_unlock(&p->mtx));
738
739 60
        if (pid <= 0)
740 0
                vtc_fatal(p->vl, "Cannot signal a non-running process");
741
742 60
        if (!strcmp(sig, "TERM"))
743 44
                j = SIGTERM;
744 16
        else if (!strcmp(sig, "INT"))
745 4
                j = SIGINT;
746 12
        else if (!strcmp(sig, "KILL"))
747 8
                j = SIGKILL;
748 4
        else if (!strcmp(sig, "HUP"))
749 4
                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 60
        if (p->expect_signal == 0)
756 60
                p->expect_signal = -j;
757 60
        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 60
                vtc_log(p->vl, 4, "Sent signal %d", j);
762 60
}
763
764
/**********************************************************************
765
 * Write to a process' stdin
766
 */
767
768
static void
769 480
process_write(const struct process *p, const char *text)
770
{
771
        int r, len;
772
773 480
        if (!p->hasthread)
774 0
                vtc_fatal(p->vl, "Cannot write to a non-running process");
775
776 480
        len = strlen(text);
777 480
        vtc_log(p->vl, 4, "Writing %d bytes", len);
778 480
        r = write(p->fd_term, text, len);
779 480
        if (r != len)
780 0
                vtc_fatal(p->vl, "Failed to write: len=%d %s (%d)",
781 0
                    len, strerror(errno), errno);
782 480
}
783
784
static void
785 500
process_write_hex(const struct process *p, const char *text)
786
{
787
        struct vsb *vsb;
788
789 500
        if (!p->hasthread)
790 0
                vtc_fatal(p->vl, "Cannot write to a non-running process");
791
792 500
        vsb = vtc_hex_to_bin(p->vl, text);
793 500
        assert(VSB_len(vsb) >= 0);
794 500
        vtc_hexdump(p->vl, 4, "sendhex", VSB_data(vsb), VSB_len(vsb));
795 500
        AZ(VSB_tofile(p->fd_term, vsb));
796 500
        VSB_destroy(&vsb);
797 500
}
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 5732
cmd_process(CMD_ARGS)
914
{
915
        struct process *p, *p2;
916
        uintmax_t u, v, bsnap;
917
        unsigned lin,col;
918 5732
        int spec_set = 0;
919
920 5732
        (void)priv;
921 5732
        (void)cmd;
922
923 5732
        if (av == NULL) {
924
                /* Reset and free */
925 3324
                VTAILQ_FOREACH_SAFE(p, &processes, list, p2) {
926 140
                        if (p->pid > 0) {
927 8
                                process_kill(p, "TERM");
928 8
                                sleep(1);
929 8
                                if (p->pid > 0)
930 0
                                        process_kill(p, "KILL");
931 8
                        }
932 140
                        if (p->hasthread)
933 16
                                process_wait(p);
934 140
                        VTAILQ_REMOVE(&processes, p, list);
935 140
                        process_undef(p);
936 140
                        process_delete(p);
937 140
                }
938 3184
                return;
939
        }
940
941 2548
        AZ(strcmp(av[0], "process"));
942 2548
        av++;
943
944 2548
        VTC_CHECK_NAME(vl, av[0], "Process", 'p');
945 6560
        VTAILQ_FOREACH(p, &processes, list)
946 6420
                if (!strcmp(p->name, av[0]))
947 2408
                        break;
948 2548
        if (p == NULL)
949 140
                p = process_new(av[0]);
950 2548
        av++;
951
952 2548
        bsnap = p->stdout_bytes;
953
954 5500
        for (; *av != NULL; av++) {
955 2952
                if (vtc_error)
956 0
                        break;
957
958 2952
                if (!strcmp(*av, "-allow-core")) {
959 0
                        p->allow_core = 1;
960 0
                        continue;
961
                }
962 2952
                if (!strcmp(*av, "-close")) {
963 0
                        process_close(p);
964 0
                        continue;
965
                }
966 2952
                if (!strcmp(*av, "-dump")) {
967 36
                        if (p->hasthread)
968 0
                                vtc_fatal(p->vl,
969
                                    "Cannot dump a running process");
970 36
                        p->log = 2;
971 36
                        continue;
972
                }
973 2916
                if (!strcmp(*av, "-expect-exit")) {
974 12
                        p->expect_exit = strtoul(av[1], NULL, 0);
975 12
                        av++;
976 12
                        continue;
977
                }
978 2904
                if (!strcmp(*av, "-expect-signal")) {
979 0
                        p->expect_signal = strtoul(av[1], NULL, 0);
980 0
                        av++;
981 0
                        continue;
982
                }
983 2904
                if (!strcmp(*av, "-hexdump")) {
984 16
                        if (p->hasthread)
985 0
                                vtc_fatal(p->vl,
986
                                    "Cannot dump a running process");
987 16
                        p->log = 3;
988 16
                        continue;
989
                }
990 2888
                if (!strcmp(*av, "-kill")) {
991 24
                        process_kill(p, av[1]);
992 24
                        av++;
993 24
                        continue;
994
                }
995 2864
                if (!strcmp(*av, "-log")) {
996 20
                        if (p->hasthread)
997 0
                                vtc_fatal(p->vl,
998
                                    "Cannot log a running process");
999 20
                        p->log = 1;
1000 20
                        continue;
1001
                }
1002 2844
                if (!strcmp(*av, "-need-bytes")) {
1003 36
                        u = strtoumax(av[1], NULL, 0);
1004 36
                        if (av[1][0] == '+')
1005 28
                                u += bsnap;
1006 36
                        av++;
1007 36
                        do {
1008 70
                                AZ(pthread_mutex_lock(&p->mtx));
1009 70
                                v = p->stdout_bytes;
1010 70
                                AZ(pthread_mutex_unlock(&p->mtx));
1011 70
                                vtc_log(p->vl, 4, "Have %ju bytes", v);
1012 70
                                usleep(500000);
1013 70
                        } while(v < u);
1014 36
                        continue;
1015
                }
1016 2808
                if (!strcmp(*av, "-run")) {
1017 8
                        process_start(p);
1018 8
                        process_wait(p);
1019 8
                        continue;
1020
                }
1021 2800
                if (!strcmp(*av, "-ansi-response")) {
1022 8
                        p->ansi_response = 1;
1023 8
                        continue;
1024
                }
1025 2792
                if (!strcmp(*av, "-expect-text")) {
1026 856
                        AN(av[1]);
1027 856
                        AN(av[2]);
1028 856
                        AN(av[3]);
1029 856
                        term_expect_text(p, av[1], av[2], av[3]);
1030 856
                        av += 3;
1031 856
                        continue;
1032
                }
1033 1936
                if (!strcmp(*av, "-expect-cursor")) {
1034 32
                        AN(av[1]);
1035 32
                        AN(av[2]);
1036 32
                        term_expect_cursor(p, av[1], av[2]);
1037 32
                        av += 2;
1038 32
                        continue;
1039
                }
1040 1904
                if (!strcmp(*av, "-screen_dump") ||
1041 1416
                    !strcmp(*av, "-screen-dump")) {
1042 516
                        term_screen_dump(p);
1043 516
                        continue;
1044
                }
1045 1388
                if (!strcmp(*av, "-start")) {
1046 132
                        process_start(p);
1047 132
                        continue;
1048
                }
1049 1256
                if (!strcmp(*av, "-stop")) {
1050 28
                        process_kill(p, "TERM");
1051 28
                        sleep(1);
1052 28
                        continue;
1053
                }
1054 1228
                if (!strcmp(*av, "-wait")) {
1055 116
                        process_wait(p);
1056 116
                        continue;
1057
                }
1058 1112
                if (!strcmp(*av, "-winsz")) {
1059 24
                        lin = atoi(av[1]);
1060 24
                        assert(lin > 1);
1061 24
                        col = atoi(av[2]);
1062 24
                        assert(col > 1);
1063 24
                        av += 2;
1064 24
                        AZ(pthread_mutex_lock(&p->mtx));
1065 24
                        term_resize(p, lin, col);
1066 24
                        AZ(pthread_mutex_unlock(&p->mtx));
1067 24
                        process_winsz(p, p->fd_term);
1068 24
                        continue;
1069
                }
1070 1088
                if (!strcmp(*av, "-write")) {
1071 416
                        process_write(p, av[1]);
1072 416
                        av++;
1073 416
                        continue;
1074
                }
1075 672
                if (!strcmp(*av, "-writehex")) {
1076 500
                        process_write_hex(p, av[1]);
1077 500
                        av++;
1078 500
                        continue;
1079
                }
1080 172
                if (!strcmp(*av, "-writeln")) {
1081 32
                        process_write(p, av[1]);
1082 32
                        process_write(p, "\n");
1083 32
                        av++;
1084 32
                        continue;
1085
                }
1086 140
                if (**av == '-' || spec_set)
1087 0
                        vtc_fatal(p->vl, "Unknown process argument: %s", *av);
1088 140
                REPLACE(p->spec, *av);
1089 140
                spec_set = 1;
1090 140
        }
1091 5732
}