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
139
140
141
142
143
144
145
146
147
148
149
150
|
const std = @import("std");
const print = std.debug.print;
const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator;
const Thread = std.Thread;
const Mutex = std.Thread.Mutex;
const c = @cImport({
@cInclude("errno.h");
@cInclude("stdio.h");
if (@import("builtin").os.tag != .windows) {
@cInclude("sys/statvfs.h");
}
});
const cmd = @import("cmd.zig");
const Command = cmd.Command;
const BuiltinCommand = cmd.BuiltinCommand;
const syntax = @import("syntax.zig");
const FileSpec = syntax.FileSpec;
const RedirectType = syntax.RedirectType;
const Redirect = syntax.Redirect;
const cmdTypes = @import("cmd/lib/types.zig");
pub const CommandStatus = cmdTypes.CommandStatus;
const OutputCapture = cmdTypes.OutputCapture;
const StdoutOutputCapture = cmdTypes.StdoutOutputCapture;
const OutputWriter = cmdTypes.OutputWriter;
const InputSource = cmdTypes.InputSource;
const StdinInputReader = cmdTypes.StdinInputReader;
const InputReader = cmdTypes.InputReader;
const CommandContext = cmdTypes.CommandContext;
const STDOUT_BUFFER_SIZE: usize = 1024;
const STDERR_BUFFER_SIZE: usize = 1024;
pub fn executeCommand(command: Command, allocator: Allocator) !CommandStatus {
return executeCommandWithOutput(command, allocator, null, null);
}
pub fn executeCommandWithOutput(command: Command, allocator: Allocator, output_capture: ?*OutputCapture, input_source: ?*InputSource) !CommandStatus {
var stdout_capture = StdoutOutputCapture{};
const output_writer = if (output_capture) |capture|
OutputWriter{ .capture = capture }
else
OutputWriter{ .stdout = &stdout_capture };
var stdin_reader = StdinInputReader{};
const input_reader = if (input_source) |source|
InputReader{ .source = source }
else
InputReader{ .stdin = &stdin_reader };
const ctx = CommandContext.init(allocator, output_writer, input_reader, executeCommandWithOutput);
switch (command) {
.Empty => return CommandStatus{ .Code = 0 },
.Builtin => |builtin_cmd| {
switch (builtin_cmd) {
.EchoText => |echo_text| {
return echo_text.eval(ctx);
},
.Cls => |cls| {
return cls.eval(ctx);
},
.Exit => {
return CommandStatus.ExitShell;
},
.EchoPlain => |echo_plain| {
return echo_plain.eval(ctx);
},
.EchoOn => |echo_on| {
return echo_on.eval(ctx);
},
.EchoOff => |echo_off| {
return echo_off.eval(ctx);
},
.Ver => |ver| {
return ver.eval(ctx);
},
.Date => |date| {
return date.eval(ctx);
},
.Time => |time| {
return time.eval(ctx);
},
.Dir => |dir| {
return dir.eval(ctx);
},
.Type => |type_cmd| {
return type_cmd.eval(ctx);
},
.Sort => |sort| {
return sort.eval(ctx);
},
.Chdir => |chdir| {
return chdir.eval(ctx);
},
.Copy => |copy| {
return copy.eval(ctx);
},
.Remove => |remove| {
return remove.eval(ctx);
},
.Mkdir => |mkdir| {
return mkdir.eval(ctx);
},
.Rmdir => |rmdir| {
return rmdir.eval(ctx);
},
.Rename => |rename| {
return rename.eval(ctx);
},
.Move => |move| {
return move.eval(ctx);
},
.PathGet => |path_get| {
return path_get.eval(ctx);
},
.PathSet => |path_set| {
return path_set.eval(ctx);
},
.Help => |help| {
return help.eval(ctx);
},
else => {
const error_msg = try std.fmt.allocPrint(ctx.allocator, "Command not implemented: {any}\n", .{builtin_cmd});
defer ctx.allocator.free(error_msg);
var writer = ctx.output_writer;
try writer.write(error_msg);
return CommandStatus{ .Code = 1 };
},
}
},
.External => |external| {
return external.eval(ctx);
},
.Redirect => |redirect| {
return redirect.eval(ctx);
},
.Pipe => |pipe| {
return pipe.eval(ctx);
},
}
}
|