2012-11-28 40 views
2

我需要一个程序,它像lsdate等,并检查一些系统命令,如果有包括该指令(文件)的路径。我有变量commandandparameters,开始在最后while循环中更改,我不知道为什么。为什么我的var在while循环中被更改?

我把puts(commandandparameters);表明,如果要运行它的输出是不好的。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
void main() 
{ 
    char *arr[5];//for the command and his parameter 
    char command[10]; 
    int i,j; 
    char *path=NULL,*tempath,*finalpath,*commandandparameters; 
    do 
    { 
     i=0; 
     printf("enter new command:"); 
     gets(command); 
     arr[i]=strtok(command," "); 
     while(arr[i]!=NULL)//save the command and also the parametrs 
     { 
      i++; 
      arr[i]=strtok(NULL," "); 
     } 
     strcpy(commandandparameters,arr[0]);//add first command 
     for(j=1;j<i;j++)//add the parameters 
      { 
       strcat(commandandparameters," "); 
       strcat(commandandparameters,arr[j]); 
      } 
     //now we check if the command in every path 
     path = getenv("PATH"); 
     tempath = strtok(path,":"); 
     while (tempath != NULL) 
     { 
      strcpy(finalpath,tempath);//get the current path 
      puts(commandandparameters); 
      strcat(finalpath,"/");//we add '/' 
      execl(finalpath,commandandparameters,NULL); 
      tempath = strtok(NULL, ":");//get next path 
     } 
    }while(command!="leave"); 
} 
+2

不使用'得到()'这可能会导致溢出,喜欢'函数getline()'或'与fgets()' – Aif

+1

显示1)方面,2)的努力,3)预期的行为,4)结果(或错误消息),你会得到。然后它将有可能帮助... – ppeterka

+2

请注意,它应该是'int main(void)';在Unix系统上,根据C标准,'main()'返回一个'int'。返回的值是程序的退出状态,报告给启动该程序的shell或其他程序。 –

回答

1

你只存储由strtok()返回指针,他们会点进去command。循环的每次迭代都会覆盖command,从而导致“旧”指针指向的数据发生更改。

必须复制出令牌出command,无论是到动态分配的内存(查找malloc())或具有如一个静态大小的字符串数组。在这种情况下,请注意缓冲区溢出。

4

您还没有定义commandandparameters点的空间:

char *path=NULL,*tempath,*finalpath,*commandandparameters; 
... 
    strcpy(commandandparameters,arr[0]); 

你有一个指针指向随机空间;你复制那个随机空间。你会得到有趣的结果。如果你幸运的话,该程序将崩溃。如果你不走运,它会变得不合时宜。

您也有类似的问题,finalpath

path = getenv("PATH"); 
    tempath = strtok(path,":"); 
    while (tempath != NULL) 
    { 
     strcpy(finalpath,tempath); 

更糟的是,你还屠宰环境。除非您打算修改PATH的值,否则getenv()返回的字符串应视为只读。实际上,在循环之后,您将不会留下太多PATH(如果第一个元素为:),则不会执行PATH。

确保您知道每个指针指向的位置。

你的代码有很多潜在的缓冲区溢出,它是令人毛骨悚然的。千万不要使用gets();假设它会将你的电脑炸成碎片。


如果您解决了这些问题,则do { ... } while (command != "leave");循环等于无限循环。你不能像这样有用地比较字符串;你需要使用strcmp()


我尝试做一个简单的程序,我看到execl()无法正常工作;有人能告诉我为什么“ls”命令不起作用吗?

这里是你的代码注释的稍作修改的版本。我添加了两个标题和换行符,但关键的改变是在execl()行。你的原稿在评论中;工作版本不是评论。我无法决定这是您的主要问题还是评论中的拼写错误。修改后的代码编译并运行。

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(void) 
{ 
    int pid, stat; 

    if ((pid = fork()) == 0) 
    { 
     execl("/bin/ls", "ls", NULL); 
     //execl("/bin/", "ls", NULL); 
     printf("1\n"); 
     exit(1); 
    } 
    else 
    { 
     wait(&stat); 
     printf("2\n"); 
    } 
} 

在你的程序中的代码拆除PATH;如果您未能执行第一个程序,此后它只会在原始PATH的第一个目录中查找。您正尝试使用execl()来处理可变数量的参数;这是工作的错误工具。例如,您必须使用execv()或其亲属之一(execvp()将执行PATH搜索,而不会搞乱PATH)。原因是execl()需要一组由null指针终止的参数,但只有当您知道有多少个参数时才能写出该参数。你可以写:

execl("/bin/ls", "ls", "-l", (char *)0); 

,但除非你强迫每个命令有最多4个参数(给出char *arr[5];),并使用一个模板,如:

execl(finalpath, arr[0], arr[1], arr[2], arr[3], arr[4]); 

不能使用execl()执行命令。但是这限制了用户最多N个参数,这是不可接受的。 (例如,*壳膨胀,可产生的30个或更多参数的列表

您的代码还没有附加命令名添加到路径分量;的第一个参数execl()是程序可执行文件的路径

因此,使用execv()(或execvp()execve()甚至,如果你有的话,execvpe())这是你的程序的或多或少稍加修改,如果你执行命令,发现工程确定;它是一个小灾难,如果它不是,它是一个一次性的外壳;它不像fork()execv(),它应该是这样的 - 如果你在分割路径之前分叉,路径mangli ng会更少,尽管流程运行对于不存在的路径是最小的。

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(void) 
{ 
    char *arr[5];//for the command and his parameter 
    char command[100]; // Not 10 
    int i; 
    int j; 
    char *path=NULL; 
    char *tempath; 
    char finalpath[200]; 
    char commandandparameters[200]; 

    do 
    { 
     i = 0; 
     printf("enter new command: "); 
     if (fgets(command, sizeof(command), stdin) == 0) 
     { 
      fprintf(stderr, "EOF or error\n"); 
      break; 
     } 
     arr[i]=strtok(command, " "); 
     while (i < (5-1) && arr[i]!=NULL)//save the command and also the parameters 
     { 
      printf("arr[%d] = %s\n", i, arr[i]); 
      i++; 
      arr[i]=strtok(NULL, " \n"); 
     } 
     arr[4] = 0; 

     strcpy(commandandparameters, arr[0]);//add first command 
     for (j=1;j<i;j++)//add the parameters 
      { 
       strcat(commandandparameters, " "); 
       strcat(commandandparameters, arr[j]); 
      } 
     printf("Cmd&Params: %s\n", commandandparameters); 

     //now we check if the command in every path 
     path = getenv("PATH"); 
     tempath = strtok(path, ":"); 
     while (tempath != NULL) 
     { 
      puts(commandandparameters); 
      strcpy(finalpath, tempath);//get the current path 
      strcat(finalpath, "/");//we add '/' 
      strcat(finalpath, arr[0]); 
      puts(finalpath); 
      execv(finalpath, arr); 
      tempath = strtok(NULL, ":");//get next path 
     } 
    } while (strcmp(command, "leave") != 0); 
    return(0); 
} 
+0

我修复了很多事情,但stil程序没有做这项工作,并且比我尝试做简单的程序,我发现execl不工作,有人可以告诉我为什么“ls”命令不工作 #inc main() int pid,stat; ((pid = fork())== 0) execl(“/ bin /”,“ls”,NULL); 012fprintf(“1”); \t exit(1); } 其他 { 等待(&stat); 的printf( “2”);} } –

+0

@AsafShay:见我修改(扩展)的答案。 –

相关问题