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