/
unbuff.c
131 lines (118 loc) · 2.81 KB
/
unbuff.c
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
* Run a command with it's standard output and stderr hooked to a
* pseudo-tty which we pass on to our stdout. The point
* of all of this is so that the command's stdio will not
* buffer it's output.
*/
#include <termios.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
/*
* The following definitions make C more amenable to a purist.
*/
#define bool char /* boolean type */
#define uint unsigned int /* short names for unsigned types */
#define ulong unsigned long
#define ullong unsigned long long /* GCC extension */
#define llong long long /* GCC extension */
#define uchar unsigned char
#define ushort unsigned short int
#define not ! /* logical negation operator */
#define and && /* logical conjunction */
#define or || /* logical disjunction */
#define TRUE (0 == 0)
#define FALSE (not TRUE)
#define loop while (TRUE) /* loop until break */
#define EOS '\0' /* end-of-string char */
#ifndef NULL
#define NULL 0 /* invalid pointer */
#endif
#define unless(p) if (not (p))
#define until(p) while (not (p))
#define cardof(a) (sizeof(a) / sizeof(*(a)))
#define endof(a) ((a) + cardof(a))
#define bitsof(a) (sizeof(a) * 8)
#define STDOUT 1 /* standard output file descriptor */
#define STDERR 2 /* standard error file descriptor */
static bool pty();
/*
* Run a subsidiary command in such a way that it's standard output will
* not be buffered.
*/
int
main(argc, argv)
int argc;
char *argv[];
{
int mfd,
sfd,
len;
char buff[BUFSIZ];
struct termios tbuff;
if (*++argv == NULL) {
fprintf(stderr, "Usage: unbuff command ...\n");
exit(1);
}
unless (pty(&mfd, &sfd)) {
fprintf(stderr, "Can't make pty/tty pair\n");
exit(1);
}
switch (fork()) {
case -1:
fprintf(stderr, "Try again\n");
exit(1);
case 0:
close(mfd);
dup2(sfd, STDOUT);
dup2(sfd, STDERR);
close(sfd);
tcgetattr(STDOUT, &tbuff);
tbuff.c_oflag &= ~ OPOST;
tcsetattr(STDOUT, TCSANOW, &tbuff);
execvp(*argv, argv);
fprintf(stderr, "Can't find %s\n", *argv);
exit(1);
default:
close(sfd);
loop {
len = read(mfd, buff, BUFSIZ);
if (len <= 0)
break;
write(STDOUT, buff, len);
}
}
return (0);
}
/*
* This procedure assumes that pseudo-tty's are named
* /dev/pty[p-s][0-9a-f] master side
* /dev/tty[p-s][0-9a-f] slave side
*/
static bool
pty(mfdp, sfdp)
int *mfdp,
*sfdp;
{
char *first,
*second;
static char master[] = "/dev/pty??",
slave[] = "/dev/tty??";
for (first = "pqrs"; *first != EOS; ++first) {
endof(master)[-3] = *first;
endof(slave)[-3] = *first;
for (second = "0123456789abcdef"; *second != EOS; ++second) {
endof(master)[-2] = *second;
*mfdp = open(master, 2);
if (*mfdp >= 0) {
endof(slave)[-2] = *second;
*sfdp = open(slave, 2);
if (*sfdp >= 0)
return (TRUE);
close(*mfdp);
}
}
}
return (FALSE);
}