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
132
133
134
135
136
137
138
|
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#ifdef _MSC_VER
#include <Windows.h>
#define usleep(usecs) Sleep(usecs/1000)
#else
#include <unistd.h>
#endif
static void flush_wait(void)
{
fflush(NULL);
usleep(10*1000); // Wait 10 ms.
}
static void help(void)
{
puts("A simple implementation of a shell for testing termopen().");
puts("");
puts("Usage:");
puts(" shell-test --help");
puts(" Prints this help to stdout.");
puts(" shell-test");
puts(" shell-test EXE");
puts(" Prints \"ready $ \" to stderr.");
puts(" shell-test -t {prompt text}");
puts(" Prints \"{prompt text} $ \" to stderr.");
puts(" shell-test EXE \"prog args...\"");
puts(" Prints \"ready $ prog args...\\n\" to stderr.");
puts(" shell-test -t {prompt text} EXE \"prog args...\"");
puts(" Prints \"{prompt text} $ progs args...\" to stderr.");
puts(" shell-test REP N {text}");
puts(" Prints \"{lnr}: {text}\\n\" to stdout N times, taking N milliseconds.");
puts(" Example:");
puts(" shell-test REP 97 \"foo bar\"");
puts(" 0: foo bar");
puts(" ...");
puts(" 96: foo bar");
puts(" shell-test INTERACT");
puts(" Prints \"interact $ \" to stderr, and waits for \"exit\" input.");
}
int main(int argc, char **argv)
{
if (argc == 2 && strcmp(argv[1], "--help") == 0) {
help();
}
if (argc >= 2) {
if (strcmp(argv[1], "-t") == 0) {
if (argc < 3) {
fprintf(stderr,"Missing prompt text for -t option\n");
return 5;
} else {
fprintf(stderr, "%s $ ", argv[2]);
if (argc >= 5 && (strcmp(argv[3], "EXE") == 0)) {
fprintf(stderr, "%s\n", argv[4]);
}
}
} else if (strcmp(argv[1], "EXE") == 0) {
fprintf(stderr, "ready $ ");
if (argc >= 3) {
fprintf(stderr, "%s\n", argv[2]);
}
} else if (strcmp(argv[1], "REP") == 0) {
if (argc != 4) {
fprintf(stderr, "REP expects exactly 3 arguments\n");
return 4;
}
int count = 0;
if (sscanf(argv[2], "%d", &count) != 1) {
fprintf(stderr, "Invalid count: %s\n", argv[2]);
return 4;
}
for (int i = 0; i < count; i++) {
printf("%d: %s\n", i, argv[3]);
if (i % 100 == 0) {
usleep(1000); // Wait 1 ms (simulate typical output).
}
fflush(NULL);
}
} else if (strcmp(argv[1], "UTF-8") == 0) {
// test split-up UTF-8 sequence
printf("\xc3"); flush_wait();
printf("\xa5\n"); flush_wait();
// split up a 2+2 grapheme clusters all possible ways
printf("ref: \xc3\xa5\xcc\xb2\n"); flush_wait();
printf("1: \xc3"); flush_wait();
printf("\xa5\xcc\xb2\n"); flush_wait();
printf("2: \xc3\xa5"); flush_wait();
printf("\xcc\xb2\n"); flush_wait();
printf("3: \xc3\xa5\xcc"); flush_wait();
printf("\xb2\n"); flush_wait();
} else if (strcmp(argv[1], "INTERACT") == 0) {
char input[256];
char cmd[100];
int arg;
int input_argc;
while (1) {
fprintf(stderr, "interact $ ");
if (fgets(input, sizeof(input), stdin) == NULL) {
break; // EOF
}
input_argc = sscanf(input, "%99s %d", cmd, &arg);
if(1 == input_argc) {
arg = 0;
}
if (strcmp(cmd, "exit") == 0) {
return arg;
} else {
fprintf(stderr, "command not found: %s\n", cmd);
}
}
} else {
fprintf(stderr, "Unknown first argument: %s\n", argv[1]);
return 3;
}
fflush(NULL);
return 0;
} else if (argc == 1) {
fprintf(stderr, "ready $ ");
return 0;
} else {
fprintf(stderr, "Missing first argument\n");
return 2;
}
}
|