summaryrefslogtreecommitdiff
path: root/appl/cmd/plumb.b
blob: 8887971568e5145ab2c33f8403d67a396b471ba4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
implement Plumb;

include "sys.m";
	sys: Sys;

include "draw.m";

include "arg.m";
	arg: Arg;

include "plumbmsg.m";
	plumbmsg: Plumbmsg;
	Msg, Attr: import plumbmsg;

include "workdir.m";
	workdir: Workdir;

Plumb: module
{
	init:	fn(nil: ref Draw->Context, nil: list of string);
};

usage()
{
	sys->fprint(stderr(), "Usage: plumb [-s src] [-d dest] [-D dir] [-k kind] [-a name val] ... data ...\n");
	raise "fail:usage";
}

init(nil: ref Draw->Context, args: list of string)
{
	sys = load Sys Sys->PATH;
	arg = load Arg Arg->PATH;
	if(arg == nil)
		nomod(Arg->PATH);
	plumbmsg = load Plumbmsg Plumbmsg->PATH;
	if(plumbmsg == nil)
		nomod(Plumbmsg->PATH);
	workdir = load Workdir Workdir->PATH;
	if(workdir == nil)
		nomod(Workdir->PATH);

	if(plumbmsg->init(1, nil, 0) < 0)
		err(sys->sprint("can't connect to plumb: %r"));

	attrs: list of ref Attr;
	m := ref Msg("plumb", nil, workdir->init(), "text", nil, nil);
	arg->init(args);
	while((c := arg->opt()) != 0)
		case c {
		's' =>
			m.src = use(arg->arg(), c);
		'd' =>
			m.dst = use(arg->arg(), c);
		'D' =>
			m.dir = use(arg->arg(), c);
		'k' =>
			m.kind = use(arg->arg(), c);
		'a' =>
			name := use(arg->arg(), c);
			val := use(arg->arg(), c);
			attrs = tack(attrs, ref Attr(name, val));
		* =>
			usage();
		}
	args = arg->argv();
	if(args == nil)
		usage();
	nb := 0;
	for(a := args; a != nil; a = tl a)
		nb += len array of byte hd a;
	nb += len args;
	buf := array[nb] of byte;
	nb = 0;
	for(a = args; a != nil; a = tl a){
		b := array of byte hd a;
		buf[nb++] = byte ' ';
		buf[nb:] = b;
		nb += len b;
	}
	m.data = buf[1:];
	m.attr = plumbmsg->attrs2string(attrs);
	if(m.send() < 0)
		err(sys->sprint("can't plumb message: %r"));
}

tack(l: list of ref Attr, v: ref Attr): list of ref Attr
{
	if(l == nil)
		return v :: nil;
	return hd l :: tack(tl l, v);
}

use(s: string, c: int): string
{
	if(s == nil)
		err(sys->sprint("missing value for -%c", c));
	return s;
}

nomod(m: string)
{
	err(sys->sprint("can't load %s: %r\n", m));
}

err(s: string)
{
	sys->fprint(stderr(), "plumb: %s\n", s);
	raise "fail:error";
}

stderr(): ref Sys->FD
{
	return sys->fildes(2);
}