I'm using execvp() to run some system calls. Program works great for valid commands, and fails for any command that doesn't exist, which is perfect.
The program is, when I use execvp() on a command that needs extra arguments(like cat) and I don't provide arguments, the program just infinitely reads from input.
I'm not sure how to get around this issue, as I don't know how to 'tell' if a command is incomplete. Any ideas?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
char command[1000];
printf("Enter command: ");
scanf("%[^\n]s", command);
char *temp = strtok(command, " ");
char *commandList[100];
int index = 0;
while (temp != NULL) {
commandList[index] = temp;
index++;
temp = strtok(NULL, " ");
}
commandList[index] = NULL;
execvp(commandList[0], commandList);
printf("Failed");
}
The ideal result would be a print of "Command incomplete" and the process ending.
One of the ideas from the comment completely answered my question (To the exact needs I had). Not sure how to give him credit on here, though.
The solution is to simply close stdin right before I use execvp(). If the command is not completed on the first scanf, the program throws an error, which is perfect.
Since I'm running the main program I'm using this on in a loop, I can use dup and dup2 to save and reload stdin later.
The code I used to test if it'll work:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
char command[1000];
int stdinput = dup(STDIN_FILENO);
close(STDIN_FILENO);
dup2(stdinput, STDIN_FILENO);
printf("Enter command: ");
scanf("%[^\n]s", command);
printf("%s\n", command);
}
Related
I am trying to create a cipher coder in C, so far I have the following code. The if statement doesn't work properly and pops up segmentation fault whenever something is inputted whether it be a digit or just a letter. The else statement which is supposed to print out how to use the cipher text only prints it out when there is a space.
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int main(int argc, string argv[]) //im certain the problem is on this line but I dont know where exactly nor do I know how to fix it
{
if (isdigit(argv[1]))
{
string s = get_string("Cipher Text: ");
}
else
{
printf("Usage: ./caesar key\n");
}
}
I'm certain the error has to deal with the string in the command line argument but I'm not to sure on what steps to take to fix it.
This is a very small program to show how you can access arguments of a C program.
It only uses standard C features (not CS50 or special string type).
#include <stdio.h>
int main(int argc, char **argv)
{
int i;
printf("argc=%d\n", argc);
for (i=0; i < argc; i++)
printf("argv[%d]=%s\n", i, argv[i]);
return 0;
}
I'm trying to create a simple shell program which execute the program specified in input. There are two main function: scanner() (use strtok to split the input in token) and execute() (fork the process and execute the program).
Unfortunately it doesn't work... I've tried to print string[0] at the end of scanner() and at the beginning of execute(). The first time the output is correct but the second time string[] seems to be modified in a sequence of random numbers so execvp() doesn't work...
I really can't figure out why the values of string[] changes, probably is a very stupid error but I can't see it. I really need your help! Thanks in advice.
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#define DIM 256
int scanner(char*[]);
int execute(char*[]);
int main()
{
char* string[DIM];
scanner(string);
execute(string);
}
/* scan: read the input in token*/
int scanner(char* string[])
{
char input[1024];
char delimit[]=" \t\r\n\v\f";
int i = 0;
if(fgets(input, sizeof input, stdin)) {
string[i] = strtok(input, delimit);
while(string[i]!=NULL){
i++;
string[i]=strtok(NULL,delimit);
}
return 0;
}
return 1;
}
/* execute: execute the command*/
int execute(char* string[])
{
int pid;
printf("%s\n", string[0]);
switch(pid = fork()){
case -1:
return 1;
case 0:
execvp(string[0], string);
return 1;
default:
wait((int*)0);
return 0;
}
}
The string variable input in scanner is a local variable, with storage class "auto". That means that when that function returns, that variable disappears, and the memory it occupied can be re-used for other things. That is unfortunate, since strtok returns pointers into that string variable.
I am writing a custom shell in c, and have encountered a strange little bug, which can be seen in the following testcase:
#include <stdio.h>
#include <stdbool.h>
#include <readline/readline.h>
#include <readline/history.h>
int main(int argc, char **argv, char **env) {
while(true) {
fprintf(stdout, "input: ");
char *line = readline(NULL);
if(line) {
add_history(line);
}
}
return 0;
}
The program spits out the prompt, and if I type something like this:
input: foo bar baz
And then go to erase the line, input: gets erased as well (once I hit the first character I inputted). Is there anyway to fix this? The only thing I could think to do was fflush(stdout) but that didn't work.
Tell readline() about the prompt:
#include <readline/readline.h>
#include <readline/history.h>
int main(void)
{
char *line;
while ((line = readline("input: ")) != 0)
add_history(line);
return 0;
}
When you do the prompting yourself, readline() doesn't know about the presence of the prompt, and therefore mishandles redrawing the line when you erase the last character you entered (moving the cursor back to the beginning of the line). When it knows about the prompt, it doesn't erase it.
My program reads and stores standard input into a char array cmd and then call system(cmd). I printed out cmd and its content is what I expected. But system(cmd) does not save the content in report.log. I tried with a literal string stored in cmd2, and this time it worked. So what is wrong with system(cmd)?
And I am using Windows 8.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#define MAXLEN 100
char *now(){
time_t t;
time(&t);
return asctime(localtime(&t));
}
int main(int argc, char *argv[])
{
char comment[80];
char cmd[120];
fgets(comment, 80, stdin);
sprintf(cmd, "echo '%s %s' >> report.log", comment, now());
printf("%s", cmd); // content of cmd is what I expect
system(cmd); // does not work, why?
char cmd2 = "echo 'Hello world' >> report.log";
system(cmd2); // work
return 0;
}
Your problem maybe with the excess \ns present in your inputs to sprintf().
fgets() scans and stores the \n from the stdin. You need to get rid of that \n and replace that with a null.
asctime() returns a ctime() return style string, again ended with a newline \n. You need to remove (replace) that too.
You can check the following code for your reference.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#define MAXLEN 100
char *now(){
time_t t;
time(&t);
return asctime(localtime(&t));
}
int main(int argc, char *argv[])
{
char comment[80] = {0};
char cmd[120] = {0};
char * timestring = NULL; //initialize local variables, good practice
fgets(comment, 80, stdin);
comment[ strlen(comment) -1] = 0; //reomve the trailing \n taken by fgtes(), replace by null
timestring = now();
timestring[strlen(timestring)-1] = 0; //remove the \n from ctime() return style string, replace b null
sprintf(cmd, "echo '%s %s' >> report.log", comment, timestring);
printf(">> The string is : %s\n", cmd);
system(cmd); // should work now.. :-)
return 0;
}
I'm making a very simple program code.
First, it has the option "-num" as 2nd argc. If you input anything in the 3rd argc, the program will simply say that the 3rd argc is entered.
Here are the examples of the inputs and outputs.
Input command line 1:
./test -num
Output 1
-num
Input command line 2:
./test -num AnythingHere
Output 2
-num 3rdArgcEntered
I also want the following command line with sticked argc (-num and AnythingHere are sticked together) to give the same output as Output 2:
./test -numAnythingHere
The output I wish to get is:
-num 3rdArgcEntered
But I obtained:
None
This is the source code I'm currently working on:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[])
{
if (!strcmp(argv[1], "-num"))
{
printf("-num ");
if(argc==3){
printf("3rdArgcEntered");
}
}
else
{
printf("None");
}
printf("\n");
return 0;
}
a little trash..
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[])
{
/* doesnt check when args are not entered */
char *tmp = argv[1];
char buff[5];
/* copy -num, doesnt check */
memcpy(buff, tmp, 4);
buff[4] = '\0';
if (!strcmp(buff, "-num"))
{
printf("-num ");
/* larger than -num */
if(argc==3 || strlen(tmp) > 4 ){
printf("3rdArgcEntered");
}
}
else
{
printf("None");
}
printf("\n");
return 0;
}
Your program can't affect how the arguments are passed; obviously main has already been called at the beginning of main. You need to parse each argument yourself, or use a library that does it for you. For parsing them yourself, you could look at strtok or sscanf, or iterate over the characters. But a more specific library, such as getopt, is generally preferable, since it makes it easy to get your program to behave in a manner consistent with other command-line utilities.