1 #include "sig.h"
2 #include "buffer.h"
3 #include "strerr.h"
4 #include "byte.h"
5 #include "readwrite.h"
6 #include "exit.h"
7 #include "iopause.h"
8 #include "pathexec.h"
9
10 #define FATAL "fixcrio: fatal: "
11
12 char prebuf[256];
13
14 int leftstatus = 0;
15 char leftbuf[512];
16 int leftlen;
17 int leftpos;
18 int leftflagcr = 0;
19
20 int rightstatus = 0;
21 char rightbuf[512];
22 int rightlen;
23 int rightpos;
24 int rightflagcr = 0;
25
doit(int fdleft,int fdright)26 void doit(int fdleft,int fdright)
27 {
28 struct taia stamp;
29 struct taia deadline;
30 iopause_fd x[4];
31 int xlen;
32 iopause_fd *io0;
33 iopause_fd *ioleft;
34 iopause_fd *io1;
35 iopause_fd *ioright;
36 int r;
37 int i;
38 char ch;
39
40 for (;;) {
41 xlen = 0;
42
43 io0 = 0;
44 if (leftstatus == 0) {
45 io0 = &x[xlen++];
46 io0->fd = 0;
47 io0->events = IOPAUSE_READ;
48 }
49 ioleft = 0;
50 if (leftstatus == 1) {
51 ioleft = &x[xlen++];
52 ioleft->fd = fdleft;
53 ioleft->events = IOPAUSE_WRITE;
54 }
55
56 ioright = 0;
57 if (rightstatus == 0) {
58 ioright = &x[xlen++];
59 ioright->fd = fdright;
60 ioright->events = IOPAUSE_READ;
61 }
62 io1 = 0;
63 if (rightstatus == 1) {
64 io1 = &x[xlen++];
65 io1->fd = 1;
66 io1->events = IOPAUSE_WRITE;
67 }
68
69 taia_now(&stamp);
70 taia_uint(&deadline,3600);
71 taia_add(&deadline,&stamp,&deadline);
72 iopause(x,xlen,&deadline,&stamp);
73
74 if (io0 && io0->revents) {
75 r = read(0,prebuf,sizeof prebuf);
76 if (r <= 0) {
77 leftstatus = -1;
78 close(fdleft);
79 }
80 else {
81 leftstatus = 1;
82 leftpos = 0;
83 leftlen = 0;
84 for (i = 0;i < r;++i) {
85 ch = prebuf[i];
86 if (ch == '\n')
87 if (!leftflagcr)
88 leftbuf[leftlen++] = '\r';
89 leftbuf[leftlen++] = ch;
90 leftflagcr = (ch == '\r');
91 }
92 }
93 }
94
95 if (ioleft && ioleft->revents) {
96 r = write(fdleft,leftbuf + leftpos,leftlen - leftpos);
97 if (r == -1) break;
98 leftpos += r;
99 if (leftpos == leftlen) leftstatus = 0;
100 }
101
102 if (ioright && ioright->revents) {
103 r = read(fdright,prebuf,sizeof prebuf);
104 if (r <= 0) break;
105 rightstatus = 1;
106 rightpos = 0;
107 rightlen = 0;
108 for (i = 0;i < r;++i) {
109 ch = prebuf[i];
110 if (ch == '\n')
111 if (!rightflagcr)
112 rightbuf[rightlen++] = '\r';
113 rightbuf[rightlen++] = ch;
114 rightflagcr = (ch == '\r');
115 }
116 }
117
118 if (io1 && io1->revents) {
119 r = write(1,rightbuf + rightpos,rightlen - rightpos);
120 if (r == -1) break;
121 rightpos += r;
122 if (rightpos == rightlen) rightstatus = 0;
123 }
124 }
125
126 _exit(0);
127 }
128
main(int argc,char ** argv,char ** envp)129 main(int argc,char **argv,char **envp)
130 {
131 int piin[2];
132 int piout[2];
133
134 if (argc < 2)
135 strerr_die1x(100,"fixcrio: usage: fixcrio program [ arg ... ]");
136
137 if (pipe(piin) == -1)
138 strerr_die2sys(111,FATAL,"unable to create pipe: ");
139 if (pipe(piout) == -1)
140 strerr_die2sys(111,FATAL,"unable to create pipe: ");
141
142 switch(fork()) {
143 case -1:
144 strerr_die2sys(111,FATAL,"unable to fork: ");
145 case 0:
146 sig_ignore(sig_pipe);
147 close(piin[0]);
148 close(piout[1]);
149 doit(piin[1],piout[0]);
150 }
151
152 close(piin[1]);
153 close(piout[0]);
154 if (fd_move(0,piin[0]) == -1)
155 strerr_die2sys(111,FATAL,"unable to move descriptors: ");
156 if (fd_move(1,piout[1]) == -1)
157 strerr_die2sys(111,FATAL,"unable to move descriptors: ");
158
159 pathexec_run(argv[1],argv + 1,envp);
160 strerr_die4sys(111,FATAL,"unable to run ",argv[1],": ");
161 }
162