$treeview $search $mathjax
00001 00006 #ifndef __AIRINV_READLINE_AUTOCOMP_HPP 00007 #define __AIRINV_READLINE_AUTOCOMP_HPP 00008 00009 // STL 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 /* The names of functions that actually do the manipulation. */ 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 // Forward declarations 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 /* Isolate the command word. */ 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 /* Get argument to command, if any. */ 00122 while (whitespace (line[i])) { 00123 i++; 00124 } 00125 00126 word = line + i; 00127 00128 /* Call the function. */ 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 /* Interface to Readline Completion */ 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 /* Allow conditional parsing of the ~/.inputrc file. */ 00187 rl_readline_name = "airinv"; 00188 00189 /* Tell the completer that we want a crack first. */ 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 /* Return the next name which partially matches from the command list. */ 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 /* If no names matched, then return NULL. */ 00246 return (char*) NULL; 00247 } 00248 00249 /* **************************************************************** */ 00250 /* */ 00251 /* airinv Commands */ 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 /* Print in six columns. */ 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 /* Change to the directory ARG. */ 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 /* Print out the current working directory. */ 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 /* The user wishes to quit using this program. Just set DONE non-zero. */ 00381 int com_quit (char* arg) { 00382 done = 1; 00383 return 0; 00384 } 00385 00386 /* Function which tells you that you can't do this. */ 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 /* Return non-zero if ARG is a valid argument for CALLER, else print 00394 * an error message and return zero. */ 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