[英]How to run a program from terminal input(linux)?
雖然我認為我已經掌握了fork()
, exec()
, wait()
和pid
在C中工作,但我還沒有找到一種如何在程序中運行個人程序的方法。
這是我的代碼:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h> /* for fork() */
#include<sys/types.h> /* for pid_t */
#include<sys/wait.h> /* fpr wait() */
int main(int argc, char* argv[])
{
char fileName[255];
pid_t pid;
switch (pid = fork()) {
case -1: //Did not fork properly
perror("fork");
break;
case 0: //child
execv(fileName[0],fileName);
puts("Oh my. If this prints, execv() must have failed");
exit(EXIT_FAILURE);
break;
default: //parent
//Infinite Loop
while (1) {
printf(" %s > ", argv[0]);
scanf("%s", fileName); // gets filename
if (fileName[0] == '\0') continue;
printf("\n Entered file: %s",fileName); // prints the fileName
waitpid(pid,0,0); /* wait for child to exit() */
break;
}
}
return 0;
}
我的問題如下:
我想把一個字符串作為輸入,我想將其范圍限制為255個字符。 是char fileName[255]
然后是scanf("%s", fileName);
要走的路? 我應該使用getLine()
或其他功能嗎?
假設輸入正確。 如何執行說現有的hello world程序。 輸入是否會存儲在*argv[]
? 我發現在我可以使用的其他程序中
static char *argv[] = { "echo", "Foo is my name." , NULL }; execv("/bin/echo", argv);
為了回應“Foo是我的名字”。 我可以用helloWorld程序做類似的事情嗎?
您將一個字符作為命令名稱傳遞,並將名稱字符串作為參數列表的開頭傳遞 - 就好像execv()
的原型是 。 int execv(char cmd, char *args)
實際的原型是: int execv(char *cmd, char **args)
,所以你需要:
char *args[2] = { fileName, 0 };
execv(args[0], args);
我假設您將fileName
設置為某個有意義的值 - 未顯示。 例如,它可能是"./local_program"
。 它將被視為可執行文件的路徑名。
如果要讀取名稱,則可以使用fgets()
或getline()
,但是您需要刪除換行符:
if (fgets(fileName, sizeof(fileName), stdin) != 0)
{
fileName[strcspn(fileName, "\n")] = '\0';
…as before…
}
要么:
char *fileName = 0;
size_t length = 0;
if (getline(&fileName, &length, stdin) != -1) /* Not EOF! */
{
fileName[strcspn(fileName, "\n")] = '\0';
…as before…
}
free(fileName);
strcspn()
的使用避免了特殊情況下過長的命令行,因此fileName
沒有換行符。 請注意,這不會嘗試將輸入行拆分為命令名和空格中的參數或類似的任何東西。 這是shell實現的下一個級別:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
char fileName[256];
if (fgets(fileName, sizeof(fileName), stdin) != 0)
{
fileName[strcspn(fileName, "\n")] = '\0';
char *args[129];
char **argv = args;
char *cmd = fileName;
const char *whisp = " \t\f\r\b\n";
/* Ugh — strtok()? OK while only handling white space separators */
char *token;
while ((token = strtok(cmd, whisp)) != 0)
{
*argv++ = token;
cmd = 0;
}
*argv = 0;
execv(args[0], args);
fprintf(stderr, "Oops!\n");
}
return 1;
}
我不需要檢查args
數組的溢出,因為輸入的256個字符減去終止null,不能被分割以產生超過128個單字符參數,每個參數與相鄰的一個空格字符分開。 使用strtok()
是一個臨時的創可貼。 一旦你需要處理真正的shell語法(管道,I / O重定向,引用帶空格的字符串等), strtok()
就是錯誤的工具。 (它 - strtok()
- 也是在任何庫函數中使用的錯誤函數。如果必須在庫代碼中使用類似strtok()
的函數,請在Unix上使用POSIX strtok_r()
或在Windows上使用Microsoft的strtok_s()
。)
就目前而言,您需要修復代碼中的編譯錯誤:
g++ -std=c++11 -g -Wall -Wextra -Wwrite-strings 36501711.cpp -o 36501711
36501711.cpp: In function ‘int main(int, char**)’:
36501711.cpp:18:25: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
execv(fileName[0],fileName);
^
36501711.cpp:18:35: error: cannot convert ‘char*’ to ‘char* const*’ for argument ‘2’ to ‘int execv(const char*, char* const*)’
execv(fileName[0],fileName);
^
36501711.cpp: At global scope:
36501711.cpp:7:5: warning: unused parameter ‘argc’ [-Wunused-parameter]
int main(int argc, char* argv[])
^
警告(關於未使用的argc
)是無害的,但錯誤是真實的,需要修復。
您需要在 fork 之前初始化fileName
,否則子fileName
將不會有任何有效數據:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h> /* for fork() */
#include<sys/types.h> /* for pid_t */
#include<sys/wait.h> /* fpr wait() */
int main(int argc, char* argv[])
{
char fileName[255];
pid_t pid;
//Infinite Loop
while (1) {
printf(" %s > ", argv[0]);
scanf("%s", fileName);
if (fileName[0] == '\0')
break;
printf("\n Entered file: %s\n", fileName);
pid = fork();
switch (pid) {
case -1: //Did not fork properly
perror("fork");
break;
case 0: //child
execl(fileName, fileName, 0);
perror("exec");
exit(EXIT_FAILURE);
break;
default: //parent
waitpid(pid,0,0); /* wait for child to exit() */
break;
}
}
return EXIT_SUCCESS;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.