编写解释器或更像是命令提示程序

我应该编写一个更像是命令提示符的解释程序。 这是一些背景信息:

General flow of basic interpreter 1. Prompt for user request. 2. Carry out the user request. 3. Unless user terminates the program, go to step 1. Run a command. Format: R command_path [arg1 to arg4] //a single character 'R' which stands for 'Run', followed by the path of the command //the user can supply up to 4 command line arguments Behavior: a. If command exist, run the command in a child process with the supplied command line arguments  Wait until the child process is done b. Else print error message “XXXX not found”, where XXXX is the user entered command 

例如

 YWIMC > R /bin/ls a.out ex2.c ...... //output from the “ls” command YWIMC > R /bin/ls –l //same as executing “ls –l” total 144 -rwx------ 1 sooyj compsc 8548 Aug 13 12:06 a.out -rwx------ 1 sooyj compsc 6388 Aug 13 11:36 alarmClock .................... //other files not shown 

我到目前为止的想法是,在文件路径中读取,读入参数,使用execv(filePath,args)。 但是,我无法得到循环和语法。

 while(scanf("%s", args[i]) !=0) { //read in arguments i++; } execv(filePath,args); 

这读取了无数个参数。 正如我所说,我不能正确的语法。 处理C中的字符串是这样的痛苦:(

重新编辑。 这是我目前的代码,相当不完整

 #include  #include  //For stat() #include  #include  #include  //for fork(), wait() int main() { char request, filePath[100]; int result, pathExist, childID, status; struct stat buf; //read user input printf("YWIMC > "); scanf("%c", &request); while (request != 'Q'){ //if 'Q' then just exit program // Handle 'R' request scanf("%s", &filePath); //Read the filePath/program name pathExist = stat(filePath, &buf); if(pathExist  "); scanf("%c", &request); } printf("Goodbye!\n"); return 0; } 

好吧,我想我终于明白你想做什么了。 要创建YWIMC解释器环境并能够使用传递给execv的命令处理执行中的命令和错误,以及在成功命令后返回到YWIMC ,您必须将对execv的调用fork到一个单独的进程防止execv终止程序。

基本上,您使用外部while循环创建YWIMC shell,在每次迭代while显示提示并读取命令行( cmdline )。 在循环中,分离命令行的最简单方法是使用下面使用的strtokstrsepstrtok )。 您可以通过在for循环中调用strtok来简化该过程:

  for (p = strtok (line, " \n"); p && i < MAXA - 1; p = strtok (NULL, " \n")) cmdline[i++] = strdup (p); 

注意: strtok会修改原始字符串,因此您必须复制该字符串才能提供包含原始命令行的error消息。

如果用户输入请求R作为第一个令牌并且它至少有一个附加参数,那么您将fork该过程。 在子( pid == 0 )中,您将正确的/path/to/command和参数传递给execv 。 传递正确命令和参数的最简单方法是创建指向cmdline的第二个元素的指针args (以便从传递给execv的数组中有效地丢弃R )。 如果将错误的命令传递给execv您还需要为子进程提供一种退出方式(否则用户会想知道为什么在传递错误命令后必须输入q两次才能退出。)

此时,执行命令execv执行,或者在失败时提供错误。 当用户输入q ,shell将需要释放strdup分配的所有内存,然后退出。

尝试以下内容,让我知道我是否终于理解了您的尝试。 如果您有任何疑问,请告诉我。

 #include  #include  #include  #include  #include  #include  /* MAXC - maximum characters that can be entered by user at prompt MAXA - maximum arguments to read (R + path + 1 2 3 4 + NULL) */ #define MAXC 256 #define MAXA 7 void trimcrnl (char *s); int main (void) { char line[MAXC] = {0}; printf ("\n Entering 'YWIMC' environment\n" " usage: R command_path [arg1 to arg4]\n" " ('q' to quit).\n\n"); while (printf ("YWIMC > ") && fgets (line, MAXC, stdin)) { if (*line == 'q') break; if (*line != 'R') continue; trimcrnl (line); /* strip newline from end of line */ char *p = line; char *cmdline[MAXA] = {NULL}; char **args = &cmdline[1]; char *err = strdup (line); int i = 0, nargs = 0, status = 0; pid_t pid; /* parse line into separate tokens (arguments) */ for (p = strtok (line, " \n"); p && i < MAXA - 1; p = strtok (NULL, " \n")) cmdline[i++] = strdup (p); nargs = i; /* save the number of arguments found */ if (nargs < 2) continue; #ifdef DEBUG /* output command line & arguments read */ for (i = 0; i < nargs; i++) printf (" cmdline[%d] = %s\n", i, cmdline[i]); for (i = 0; i < nargs - 1; i++) printf (" args[%d] = %s\n", i, args[i]); #endif if ((pid = fork ()) == -1) { fprintf (stderr, "error: fork failed returning -1.\n"); exit (EXIT_FAILURE); } if (pid == 0) { /* child process */ /* call execv (NOTE: you must provide a full-path to the program being executed, eg /usr/bin/ls) */ if (execv (args[0], args) == -1) fprintf (stderr, "error: '%s' not found.\n", err); _exit (EXIT_FAILURE); } waitpid (pid, &status, 0); } return 0; } /* strip newline or carriage return from string 's' */ void trimcrnl (char *s) { if (!s) return; size_t len = strlen (s); while (len > 0 && (s[len-1] == '\n' || s[len-1] == '\r')) s[--len] = 0; } 

 $ gcc -Wall -Wextra -o bin/execvargs execvargs.c 

或者在启用调试输出的情况下编译:

 $ gcc -Wall -Wextra -o bin/execvargs execvargs.c -DDEBUG 

使用/输出

 $ ./bin/execvargsfile Entering 'YWIMC' environment usage: R command_path [arg1 to arg4] ('q' to quit). YWIMC > anything not starting with 'R' YWIMC > R badpath badcommand error: 'R badpath badcommand' not found. YWIMC > R /bin/ls /home/david/cnf/LVM Lvm.pdf YWIMC > R /bin/ls -al /home/david/cnf/LVM total 380 drwxr-xr-x 2 david david 4096 May 21 22:22 . drwxr-xr-x 41 david david 4096 Aug 27 17:58 .. -rw-r--r-- 1 david david 380862 May 21 22:22 Lvm.pdf YWIMC > q