Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
FileCommands.hxx
Go to the documentation of this file.
1
34#ifndef _CONSOLE_FILECOMMANDS_HXX_
35#define _CONSOLE_FILECOMMANDS_HXX_
36
37#include <dirent.h>
38
39#include "console/Console.hxx"
40
46{
47public:
51 {
52 console->add_command("cat", cat_command);
53 console->add_command("echo", echo_command);
54 console->add_command("rm", rm_command);
55 console->add_command("ls", ls_command);
56 }
57
58private:
59
66 static Console::CommandStatus cat_command(FILE *fp, int argc,
67 const char *argv[], void *context)
68 {
69 if (argc == 0)
70 {
71 fprintf(fp, "concatenate files and print on the standard output\n");
73 }
74
75 for (int i = 1; i < argc; ++i)
76 {
77 int fd = ::open(argv[i], O_RDONLY | O_NONBLOCK);
78 if (fd < 0)
79 {
80 fprintf(fp, "%s: %s: No such file or directory\n",
81 argv[0], argv[i]);
82 continue;
83 }
84 ssize_t result;
85 do
86 {
87 char buf[32];
88 result = ::read(fd, buf, sizeof(buf));
89 if (result > 0)
90 {
91 fprintf(fp, "%.*s", result, buf);
92 }
93 } while (result > 0);
94
95 close(fd);
96
97 fprintf(fp, "\n");
98 }
99
100 return Console::COMMAND_OK;
101 }
102
109 static Console::CommandStatus echo_command(FILE *fp, int argc,
110 const char *argv[],
111 void *context)
112 {
113 if (argc == 0)
114 {
115 fprintf(fp, "display a line of text\n");
116 return Console::COMMAND_OK;
117 }
118
119 if (argc == 2)
120 {
121 fprintf(fp, "%s\n", argv[1]);
122 return Console::COMMAND_OK;
123 }
124 else if (argc == 4)
125 {
126 if (!strcmp(argv[2], ">"))
127 {
128 int fd = ::open(argv[3], O_WRONLY | O_CREAT);
129 if (fd < 0)
130 {
131 fprintf(fp, "%s: No such file or directory\n", argv[3]);
132 }
133 else
134 {
135 ssize_t wr_size = strlen(argv[1]);
136 ssize_t result = ::write(fd, argv[1], wr_size);
137 close(fd);
138 return result == wr_size ? Console::COMMAND_OK :
140 }
141 }
142 }
143
145 }
146
153 static Console::CommandStatus rm_command(FILE *fp, int argc,
154 const char *argv[], void *context)
155 {
156 if (argc == 0)
157 {
158 fprintf(fp, "remove files or directories\n");
159 return Console::COMMAND_OK;
160 }
161
162 if (argc < 2)
163 {
165 }
166
167 for (int i = 1; i < argc; ++i)
168 {
169 if (::unlink(argv[i]) == 0)
170 {
171 continue;
172 }
173 if (errno == ENOENT)
174 {
175 fprintf(fp,
176 "%s: cannot remove '%s': No such file or directory\n",
177 argv[0], argv[i]);
178 }
179 }
180
181 return Console::COMMAND_OK;
182 }
183
190 static Console::CommandStatus ls_command(FILE *fp, int argc,
191 const char *argv[], void *context)
192 {
193 if (argc == 0)
194 {
195 fprintf(fp, "list directory contents\n");
196 return Console::COMMAND_OK;
197 }
198
199 if (argc != 2)
200 {
202 }
203
204 struct stat stat;
205 if (::stat(argv[1], &stat) != 0)
206 {
207 if (errno == ENOENT)
208 {
209 fprintf(fp,
210 "%s: cannot access '%s': No such file or directory\n",
211 argv[0], argv[1]);
212 }
214 }
215
216 if (S_ISDIR(stat.st_mode))
217 {
218 DIR *dir = opendir(argv[1]);
219 HASSERT(dir);
220 struct dirent *dirent;
221 do
222 {
223 dirent = readdir(dir);
224 if (dirent)
225 {
226 HASSERT(::stat(dirent->d_name, &stat) == 0);
227 ls_printline(fp, dirent->d_name, &stat);
228 }
229 } while (dirent);
230 closedir(dir);
231 }
232 else if (S_ISREG(stat.st_mode) || S_ISLNK(stat.st_mode))
233 {
234 ls_printline(fp, argv[1], &stat);
235 }
236
237 return Console::COMMAND_OK;
238 }
239
244 static void ls_printline(FILE *fp, const char *name, struct stat *stat)
245 {
246 char type;
247 type = S_ISDIR(stat->st_mode) ? 'd' : '-';
248 type = S_ISLNK(stat->st_mode) ? 'l' : type;
249
250 fprintf(fp, "%c%c%c%c%c%c%c%c%c%c %5ld %s\n", type,
251 stat->st_mode & S_IRUSR ? 'r' : '-',
252 stat->st_mode & S_IWUSR ? 'w' : '-',
253 stat->st_mode & S_IXUSR ? 'x' : '-',
254 stat->st_mode & S_IRGRP ? 'r' : '-',
255 stat->st_mode & S_IWGRP ? 'w' : '-',
256 stat->st_mode & S_IXGRP ? 'x' : '-',
257 stat->st_mode & S_IROTH ? 'r' : '-',
258 stat->st_mode & S_IWOTH ? 'w' : '-',
259 stat->st_mode & S_IXOTH ? 'x' : '-',
260 stat->st_size, name);
261 }
262
264};
265
266#endif // _CONSOLE_FILECOMMANDS_HXX_
DIR * opendir(const char *name)
Open a directory.
struct dirent * readdir(DIR *dirp)
Read the next entry in a directory.
int closedir(DIR *dirp)
Close a directory.
This class provides a console available from stdin/stdout as well as via telnet.
Definition Console.hxx:68
void add_command(const char *name, Callback callback, void *context=NULL)
Add a new command to the console.
Definition Console.cxx:94
CommandStatus
Enumeration of recognized command callback results.
Definition Console.hxx:80
@ COMMAND_ERROR
Command had some kind of error.
Definition Console.hxx:83
@ COMMAND_OK
Command executed successfully.
Definition Console.hxx:81
Container for all the file system operations.
static Console::CommandStatus rm_command(FILE *fp, int argc, const char *argv[], void *context)
Remove files or directories.
static void ls_printline(FILE *fp, const char *name, struct stat *stat)
Helper method to print a single "ls" line.
static Console::CommandStatus cat_command(FILE *fp, int argc, const char *argv[], void *context)
Concatinate files.
static Console::CommandStatus echo_command(FILE *fp, int argc, const char *argv[], void *context)
Echo string.
static Console::CommandStatus ls_command(FILE *fp, int argc, const char *argv[], void *context)
List directory contents.
FileCommands(Console *console)
Constructor.
uintptr_t DIR
DIR typedef.
Definition dirent.h:45
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171
Directory entry structure.
Definition dirent.h:49
char d_name[]
filename string of entry
Definition dirent.h:51