00001
00006 #ifndef __AIRINV_READLINE_AUTOCOMP_HPP
00007 #define __AIRINV_READLINE_AUTOCOMP_HPP
00008
00009
00010 #include <string>
00011 #include <iosfwd>
00012 #include <cstdio>
00013 #include <sys/types.h>
00014 #include <sys/file.h>
00015 #include <sys/stat.h>
00016 #include <sys/errno.h>
00017
00018 #include <readline/readline.h>
00019 #include <readline/history.h>
00020
00021 extern char* getwd();
00022 extern char* xmalloc (size_t);
00023
00024
00025 int com_list (char*);
00026 int com_view (char*);
00027 int com_rename (char*);
00028 int com_stat (char*);
00029 int com_pwd (char*);
00030 int com_delete (char*);
00031 int com_help (char*);
00032 int com_cd (char*);
00033 int com_quit (char*);
00034
00035 typedef int (*pt2Func) (char*);
00036
00041 typedef struct {
00045 char const* name;
00046
00050 pt2Func *func;
00051
00055 char *doc;
00056 } COMMAND;
00057
00058 COMMAND commands[] = {
00059 { "cd", (*com_cd)(), "Change to directory DIR" },
00060 { "delete", com_delete, "Delete FILE" },
00061 { "help", com_help, "Display this text" },
00062 { "?", com_help, "Synonym for `help'" },
00063 { "list", com_list, "List files in DIR" },
00064 { "ls", com_list, "Synonym for `list'" },
00065 { "pwd", com_pwd, "Print the current working directory" },
00066 { "quit", com_quit, "Quit using airinv" },
00067 { "rename", com_rename, "Rename FILE to NEWNAME" },
00068 { "stat", com_stat, "Print out statistics on FILE" },
00069 { "view", com_view, "View the contents of FILE" },
00070 { (char*) NULL, (pt2Func) NULL, (char*) NULL }
00071 };
00072
00073
00074 char* stripwhite (char* iString);
00075 COMMAND* find_command (char* iString);
00076
00080 int done;
00081
00085 char* dupstr (char* iString) {
00086 char* r = xmalloc (std::strlen (iString) + 1);
00087 strcpy (r, iString);
00088 return r;
00089 }
00090
00094 int execute_line (char* line) {
00095 register int i;
00096 COMMAND* command;
00097 char* word;
00098
00099
00100 i = 0;
00101 while (line[i] && whitespace (line[i])) {
00102 i++;
00103 }
00104 word = line + i;
00105
00106 while (line[i] && !whitespace (line[i])) {
00107 i++;
00108 }
00109
00110 if (line[i]) {
00111 line[i++] = '\0';
00112 }
00113
00114 command = find_command (word);
00115
00116 if (!command) {
00117 std::cerr << word << ": No such command for airinv." << std::endl;
00118 return -1;
00119 }
00120
00121
00122 while (whitespace (line[i])) {
00123 i++;
00124 }
00125
00126 word = line + i;
00127
00128
00129 return (*(command->func)) (word);
00130 }
00131
00136 COMMAND* find_command (char* name) {
00137 register int i;
00138
00139 for (i = 0; commands[i].name; i++) {
00140 if (strcmp (name, commands[i].name) == 0) {
00141 return (&commands[i]);
00142 }
00143 }
00144
00145 return (COMMAND*) NULL;
00146 }
00147
00152 char* stripwhite (char* string) {
00153 register char *s, *t;
00154
00155 for (s = string; whitespace (*s); s++) {
00156 }
00157
00158 if (*s == 0) {
00159 return s;
00160 }
00161
00162 t = s + strlen (s) - 1;
00163 while (t > s && whitespace (*t)) {
00164 t--;
00165 }
00166 *++t = '\0';
00167
00168 return s;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 char* command_generator (char* text, int state);
00178 char** fileman_completion (char* text, int start, int end);
00179
00185 void initialize_readline() {
00186
00187 rl_readline_name = "airinv";
00188
00189
00190 rl_attempted_completion_function = (rl_completion_func_t*) fileman_completion;
00191 }
00192
00200 char** fileman_completion (char* text, int start, int end) {
00201 char **matches;
00202
00203 matches = (char**) NULL;
00204
00210 if (start == 0) {
00211 matches = completion_matches (text, command_generator);
00212 }
00213
00214 return matches;
00215 }
00216
00222 char* command_generator (char* text, int state) {
00223 static int list_index, len;
00224 char* name;
00225
00231 if (!state) {
00232 list_index = 0;
00233 len = strlen (text);
00234 }
00235
00236
00237 while (name = commands[list_index].name) {
00238 ++list_index;
00239
00240 if (strncmp (name, text, len) == 0) {
00241 return dupstr (name);
00242 }
00243 }
00244
00245
00246 return (char*) NULL;
00247 }
00248
00249
00250
00251
00252
00253
00254
00259 static char syscom[1024];
00260
00264 void com_list (char* arg) {
00265 if (!arg) {
00266 arg = "";
00267 }
00268
00269 std::ostringstream oStr;
00270 oStr << "ls -FClg " << arg;
00271 return system (oStr.c_str());
00272 }
00273
00274 int com_view (char* arg) {
00275 if (!valid_argument ("view", arg)) {
00276 return 1;
00277 }
00278
00279 std::ostringstream oStr;
00280 oStr << "more " << arg;
00281 return system (syscom);
00282 }
00283
00284 int com_rename (char* arg) {
00285 too_dangerous ("rename");
00286 return 1;
00287 }
00288
00289 int com_stat (char* arg) {
00290 struct stat finfo;
00291
00292 if (!valid_argument ("stat", arg)) {
00293 return 1;
00294 }
00295
00296 if (stat (arg, &finfo) == -1) {
00297 perror (arg);
00298 return 1;
00299 }
00300
00301 std::cout << "Statistics for `" << arg << "':" << std::endl;
00302
00303 const std::string lPluralEnd1 = (finfo.st_nlink == 1) ? "" : "s";
00304 const std::string lPluralEnd2 = (finfo.st_size == 1) ? "" : "s";
00305 std::cout << arg << " has "
00306 << finfo.st_nlink << " link" << lPluralEnd1 << ", and is "
00307 << finfo.st_size << " byte" << lPluralEnd2 << " in length."
00308 << std::endl;
00309 std::cout << " Inode Last Change at: " << ctime (&finfo.st_ctime) << std::endl;
00310 std::cout << " Last access at: " << ctime (&finfo.st_atime) << std::endl;
00311 std::cout << " Last modified at: " << ctime (&finfo.st_mtime) << std::endl;
00312 return 0;
00313 }
00314
00315 int com_delete (char* arg) {
00316 too_dangerous ("delete");
00317 return 1;
00318 }
00319
00324 int com_help (char* arg) {
00325 register int i;
00326 int printed = 0;
00327
00328 for (i = 0; commands[i].name; i++) {
00329 if (!*arg || (strcmp (arg, commands[i].name) == 0)) {
00330 printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
00331 printed++;
00332 }
00333 }
00334
00335 if (!printed) {
00336 printf ("No commands match `%s'. Possibilties are:\n", arg);
00337
00338 for (i = 0; commands[i].name; i++) {
00339
00340 if (printed == 6) {
00341 printed = 0;
00342 printf ("\n");
00343 }
00344
00345 printf ("%s\t", commands[i].name);
00346 printed++;
00347 }
00348
00349 if (printed)
00350 printf ("\n");
00351 }
00352 return 0;
00353 }
00354
00355
00356 int com_cd (char* arg) {
00357 if (chdir (arg) == -1) {
00358 perror (arg);
00359 return 1;
00360 }
00361
00362 com_pwd ("");
00363 return 0;
00364 }
00365
00366
00367 int com_pwd (char* ignore) {
00368 char dir[1024], *s;
00369
00370 s = getwd (dir);
00371 if (s == 0) {
00372 printf ("Error getting pwd: %s\n", dir);
00373 return 1;
00374 }
00375
00376 printf ("Current directory is %s\n", dir);
00377 return 0;
00378 }
00379
00380
00381 int com_quit (char* arg) {
00382 done = 1;
00383 return 0;
00384 }
00385
00386
00387 void too_dangerous (char* caller) {
00388 fprintf (stderr,
00389 "%s: Too dangerous for me to distribute. Write it yourself.\n",
00390 caller);
00391 }
00392
00393
00394
00395 int valid_argument (char* caller, char* arg) {
00396 if (!arg || !*arg) {
00397 fprintf (stderr, "%s: Argument required.\n", caller);
00398 return 0;
00399 }
00400
00401 return 1;
00402 }
00403
00404 #endif // _AIRINV_READLINE_AUTOCOMP_HPP