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