我有一个客户端和服务器程序,其中服务器是一个简单的shell。
客户端向服务器写入命令,服务器检查是否允许该命令,然后执行该命令
客户端代码就像......
while(1){
printf("rrsh> ");
Fgets(buf, MAXLINE, stdin);
if ((p3ret_val = p3parseline(buf, argv)) == 1)
printf("You didn't enter anything\n");
if (!strcmp(argv[0], "quit"))
break;
Rio_writen(clientfd, buf, strlen(buf));
Rio_readlineb(&rio, buf, MAXLINE);
if (!strcmp(buf, "Command not allowed\n")){
strcpy(buf, "Cannot execute '");
strcat(buf, argv[0]);
strcat(buf, "' on this server\n");
Fputs(buf, stdout);
}
memset(&buf[0], 0, sizeof(buf)); //flush the buffer
}
服务器代码...
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0){ //loop until connection has been terminated
if (n == 0)
flag1 = 0; //the user will need to login again
if (flag1 == 1){ //the user is loged in
printf("server received %zu Byte(s)\n", n);
bg = p3parseline(buf, argv);
strcat(argv[0], "\n");
//check if the command is allowed
flag2 = 0; //set command allowed? flag back to false
file = Fopen("rrshcommands.txt", "r");
while (Fgets(command, MAXLINE, file) != NULL){
if (!strcmp(argv[0], command)){
flag2 = 1;
strcpy(buf, "Command approved\n");
// break;
}
}
Fclose(file);
strtok(argv[0], "\n");
// Fputs(buf, stdout);
if (flag2 == 0){ //case where the command is not allowed
strcpy(buf, "Command not allowed\n");
Rio_writen(connfd, buf, strlen(buf));
}
else{
if ((pid = fork()) == 0) { /* Child runs user job */
Dup2(connfd, 1);
// Close(connfd);
if (execve(argv[0], argv, environ) < 0) {
printf("%s: Command not found.", argv[0]);
exit(0);
}
}
/* Parent waits for foreground job to terminate */
if (!bg) {
int status;
if (waitpid(pid, &status, 0) < 0)
unix_error("waitfg: waitpid error");
}
}
memset(&buf[0], 0, sizeof(buf)); //flush the buffer
}
}
调试我发现客户端上的buf以某种方式填充了ls应该显示的第一个文件。
这是一系列奇怪的事件。我输入了有效的/ bin / ls命令,然后在执行该命令后,我输入另一个垃圾命令。第二次客户端从服务器读取后,它返回我刚才说的内容 - 应该显示/ bin / ls的第一个文件
这是来自客户端..
rrsh> /bin/ls
Breakpoint 1, main (argc=3, argv=0x7fffffffe5d8) at rrsh-client.c:42
42 Rio_writen(clientfd, buf, strlen(buf));
(gdb) continue
Continuing.
rrsh> wprg
Breakpoint 1, main (argc=3, argv=0x7fffffffe5d8) at rrsh-client.c:42
42 Rio_writen(clientfd, buf, strlen(buf));
(gdb) p buf
$2 = "wprg\n", '\000' <repeats 8186 times>
(gdb) n
43 Rio_readlineb(&rio, buf, MAXLINE);
(gdb) n
44 if (!strcmp(buf, "Command not allowed\n")){
(gdb) p buf
$3 = "csapp.h\n", '\000' <repeats 8183 times>
您会注意到我从不从服务器写入客户端,除非不允许该命令
为什么客户端在重定向stdout时从服务器读取第一个文件名 - 不写?