I have to make simple shell which read commands and execute them in order. condition is not changing the form of main function, and execute function should be recursive.
main problem is that it seems waitpid doesn't work. but I know, there are so many problem in my code. please let me know where I should start from..
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX 10
char cmmd[MAX][256];
int sp;
char *argv[10];
int size;
void ClearLineFromReadBuffer(void){
while(getchar() != '\n');
}
void printCommands(){
size = sp+1;
//print by moving stack pointer
while(1){
if (sp==-1) break;
printf("Command line : %s\n", cmmd[sp]);
sp--;
}
printf("print end\n");
}
void readCommandLines(){
int a = 0; //return of scanf
while (1){ //write commends to cmmd untill get ctrl+d
printf(">");
a = (scanf("%[^\n]s", cmmd[sp])); //take input to str untill get enter(scanf returns -1)
if (a==-1) {sp--; break;}
if (a==1) ClearLineFromReadBuffer();
if (a==0) {printf("error"); break;}
sp++;
}
printf("\n");
}
void readACommand(char *line){ //line takes string's name.
int i=0;
argv[i]=strtok(line," "); //i==0
while(strtok(line," ")!=NULL){
i++;
argv[i]=strtok(NULL," ");
}
printf("%s",argv[0]);
printf("%s",argv[1]);
}
void executeCommands(){ //Recursive function
int n = sp;
n++;
printf("%d",n);
printf("%s",cmmd[n]);
char *cmd_line = cmmd[n]; //command line which child process will execute
unsigned int child_pid; //fork() returns process id of child in parents process
int status; //status takes return of child's exit()
child_pid=fork();
if (child_pid != 0){ // Parents process
printf("parents access");
waitpid(child_pid,&status,0);
printf("***Process %d Child process %d DONE with status %x\n\n",getpid(),child_pid,status);
sp++;
if(sp<size)
executeCommands();
}
else if (child_pid == 0){ //fork() returns 0 in child process
printf("***Process %d Executing Command %s",getpid(),cmd_line);
readACommand(cmmd[n]);
execve(argv[0],argv,NULL);
printf("ERROR - not executing command \"%s\"\n",argv[0]); //can be printed because exec() failed
}
}
int main(){
readCommandLines();
printCommands();
executeCommands();
return(0);
}
this is outcome.
enter image description here
the way you're tokenizing the string is very wrong. There's a lot of strtok calls, and your loop can be an infinite loop since you're calling strtok in the loop with the initialization string, not NULL
Plus you're not setting to NULL after the last argument, which is required by execv to know when the arguments have run out (no size is passed)
Here's a standalone example and a proper readACommand routine:
#include <stdio.h>
#include <string.h>
char *argv[100];
void readACommand(char *line){ //line takes string's name.
int i=0;
argv[i]=strtok(line," "); //i==0
while(argv[i]!=NULL){
argv[++i]=strtok(NULL," ");
}
}
int main()
{
char line[] = "this is a command";
char **ptr=argv;
readACommand(line);
while(*ptr != NULL)
{
printf("Arg: %s\n",*ptr);
ptr++;
}
return 0;
}
executing (detecting the NULL pointer in the end):
Arg: this
Arg: is
Arg: a
Arg: command
Related
This a reverse string code but the loop cant be terminated and keeps taking input
How can I terminate it
#include <stdio.h>
#include <string.h>
#define len 100
int main() {
char str[len];
int i;
do {
gets(str);
for (i = (strlen(str) - 1); i > -1; i--) {
printf("%c", str[i]);
}
printf("\n");
} while (str[0] != '\0');
return 0;
add str[0]='\0'; before gets and its done. this is because making a loop termination and to get out of the loop after clicking enter.
#include <stdio.h>
#include <string.h>
#define len 100
int main() {
char str[len];
int i,lenh;
do{
str[0]='\0';
gets(str);
lenh=strlen(str);
for(i=lenh-1;i>=0;i--)
{
printf("%c",str[i]);
}
printf("\n");
}while(str[0]!='\0');
return 0;
}
now, there are a few points (answer code below)
Basically, you are printing hand-to-hand with input, while the question states of a multi line input. So, first you have to take all the inputs and then output will be shown.
Your original code does not keep taking input as you have said. Question says the last string is empty string. You press enter in empty string, your above code will terminate.
Remember Last Input String Should be Empty, that's termination condition
#include <stdio.h>
#include <string.h>
int main(){
char str[100];
char stringArray[50][100]={0};
int k,m,count=0,i=0,j=0;
do {
fgets(str,100,stdin);
k=strlen(str);
for(m=0;m<k-1;m++){
stringArray[count][k-m-2]=str[m];
}
count++;
}
while (str[0] != '\n');
for(i=0; i<count; i++){
for(j=0;stringArray[i][j]!=0;j++){
printf("%c",stringArray[i][j]);
}
if(i<count-1){
printf("\n");}
}
return 0;
}
sample input
Hello team Loop
Welcome
sample output
pooL maet olleH
emocleW
I have made this program to run n other c programs. Suppose I want to execute three c programs :
1. Half of a Number
2. Double of a Number
3. Square of a Number
I am taking these three file names as the arguments from the command line and a Digit
Suppose I give the arguments : half square double 10
then the program execution will be double(square(half(10)))
So the output should be 50
I have made these three programs in such a way that these accept the number from the command line.
Now I am clueless that How can I return the value from that c programs which I have calculated . I have tried exit() and WEXITSTATUS(status) function but not getting the correct output
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<wait.h>
char* concat(char *s1, char *s2)
{
char *result =(char *) malloc(strlen(s1)+strlen(s2)+1);
strcpy(result, s1);
strcat(result, s2);
return result;
}
int main(int arg, char** args)
{
int status,cpid;
int n=arg;
char* val = (args[n-1]);
char* path="/home/naman/"; //This is the path where I have my all C programs
if(arg<3)
printf("Too less arguments\n");
printf("Main program pid is : %d",(int)getpid());
printf("\n");
for(int i=1;i<n-1;i++)
{
if(fork())
{
wait(NULL);
printf("Value return is : %d\n",WEXITSTATUS(status)); \\Not getting to correct value from that executed program
}
else
{
char* result=concat(path,args[i]);
//printf("%s \n",result);
execl(result,args[i],val,(char*)0);
printf("I will never come here");
}
}
printf("Value is : %d",atoi(val));
}
If I execute the exec() function in another C program as a main function it works perfectly, while if I put it as a function called in the main menu it gives me some warning and the function does not run.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for fork */
#include <sys/types.h> /* for pid_t */
#include <sys/wait.h> /* for wait */
int exec (void) {
char array[100];
char character;
int i = 0;
char* point;
int j = 0;
printf ("Digita una stringa");
printf ("\n");
do {
character = getchar();
array[i] = character;
i++;
}
while (character != '\n');
array[i-1] = '\0';
i = 0;
char* string[100];
char *word = strtok(array, " .");
j = 0;
while (word != NULL) {
printf("%s\n", word);
string[j++] = word; // Increment j
word = strtok(NULL, " .");
}
string[j] = NULL; // Make sure the array is NULL term
printf ("\n");
pid_t pid;
pid = fork();
int status;
if (pid == -1) {
perror("");
}else if (pid == 0) {
execvp(string[0], string); /* execute the command */
fprintf(stderr, "Failed to exec");
exit(1);
}
else {
//.. wait until the child ends
waitpid(-1, &status, 0);
}
return;
}
int read_input (void) {
int choice;
printf("Seleziona una voce dal menu");
do {
printf("\n");
scanf ("%i", &choice);
if (choice > 8 || choice < 1)
printf ("Attenzione, inserisci un valore contemplato dal menu");
}
while ( choice > 8 || choice < 1);
return choice;
}
void main (int argc, char *argv[]) {
printf ("------------------------\n");
printf (" MENU \n");
printf ("------------------------\n");
printf (" \n");
printf ("1) Esecuzione in foreground di un processo\n");
printf ("2) Ctrl -C\n");
printf ("3) Exit\n");
printf ("4) Background\n");
printf ("5) Pipe\n");
printf ("6) Jobs\n");
printf ("7) fg\n");
printf ("8) kill\n");
int menu = read_input();
switch (menu) {
case '1' :
exec ();
break;
case '2' :
//ctrl();
break;
case '3' :
//exit_();
break;
case '4' :
//background();
break;
case '5' :
//pipe();
break;
case '6' :
//jobs();
break;
case '7' :
//fg();
break;
case '8' :
//kill();
break;
}
}
this is the warning:
elaborato.c:31:16: warning: initialization makes pointer from integer without a cast [enabled by default] char *word = strtok(array, " .");
Regarding the problem related to input,
do {
printf("\n");
scanf ("%i", &choice);
if (choice > 8 || choice < 1)
printf ("Attenzione, inserisci un valore contemplato dal menu");
}
while ( choice > 8 || choice < 1);
Once you type an integer and press enter, the scanf() consumes the number and a newline is left in stdin. Next time the loop goes around (assuming input <1 or >8 or something else) scanf gets that newline and it goes on.
add a getchar() after the scanf().
The answer is in the warnings, you should move them from the comment into the question.
elaborato.c:31:16: warning: initialization makes pointer from integer without a cast [enabled by default] char *word = strtok(array, " .");
That means that word, which is a char pointer is being initialized from an integer. Therefore, it seems strtok() is returning an integer... that doesn't sound right.
From the strtok() man page:
#include <string.h>
char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
That seems right, it returns a char *.... but it also says it's declared in <string.h>... which you aren't including. Since it's not defined, the compiler assumes it as int strtok().
Fix: add the #include <string.h> line.
The problem you are seeing is that of scanf getting skipped.
For more details you can refer here
The call to scanf() after the printf consumes the new-line character and continues without the user having to enter anything.
It reads the very next character from standard in, which is probably a newline character and thus not prompting you for any input.
I'm too tired to comment on the entire code (it is really bad), so I'll just write about the issue in question and how trivially it could be debugged.
First thing to do is to check if we get the number and return to main, hence:
int menu = read_input();
printf("got [%d]\n", menu);
Running this:
[snip]
1
got [1]
So we indeed get to this point.
As such now we check what is this compared to.
int menu = read_input();
printf("got [%d] '1'=[%d]\n", menu, '1');
Let's run:
1
got [1] '1'=[49]
So, menu stores an integer 1, while '1' is a character code for 1 in ascii, which, well, is not an integer 1.
In general I don't see what was the problem with narrowing it down.
I am trying to write an c program which get two float numbers from user and then calls another program with execv() command. But I can't do it , because of converting float to char or I don't know why.
The problem is execv() command is not working; the output must be like that
Enter first num: 5 Enter second num: 7
5.000000 + 7.000000 = 12.000000 parentPID: 9745 childPID: 9746 works now
but it is is like that now
Enter first num: 5 Enter second num: 7 parentPID: 9753
childPID: 9754 works now
my first c program sum.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
if(argc!=3)
printf("error...\n");
double a=atof(argv[1]);
double b=atof(argv[2]);
printf("%lf + %lf = %lf \n",a,b,a+b);
return 0;
}
and the second program calculate.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
float x,y;
pid_t pid;
printf("Enter first num: ");
scanf("%f",&x);
printf("Enter second num: ");
scanf("%f",&y);
if((pid=fork())== -1)
{
printf("can not fork..\n");
exit(1);
}
if(pid==0) //child
{
pid=getpid();
char *temp[] = {NULL,NULL,NULL,NULL};
temp[0]="sum";
sprintf(*temp[1],"%f",x); //here I want to convert float number to char but it doesn't work
sprintf(*temp[2],"%f",y);
execv("sum",temp);
}
else
{
wait(NULL);
printf("parentPID: %d childPID: %d works now.\n", getpid(), pid);
}
return 0;
}
char command1[50], command2[50]; // Added
char *temp[] = {NULL, command1, command2, NULL}; // Modified
temp[0]="sum";
sprintf(temp[1],"%f",x); // remove *
sprintf(temp[2],"%f",y); // remove *
You are not allocating to temp[1] and temp[2] and using those as destination buffer in sprintf and using incorrect * in sprint.
You can use malloc to allocate this memory or use other string as shown in above example to initialize the array.
From kind comment of Sourav Ghosh:
In sum.c, change below lines of code to:
if(argc!=3)
{
printf("error...\n");
return -1;
}
or else, it may lead to undefined behaviour.
I kind of have a basic question for you because it's driving me crazy. How do I go about writing my functions to specific strings? Like, if I was creating a while loop and wanted the program to end, how would I write it so that the program itself ends when I type in "end" when it asks for input?
EDIT: Alright, so I figured out pretty easily how to end my function by typing "end", but now for some reason depending on how many sentences I write, my program keeps repeating itself.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
int i;
char buf[10];
printf("Command? ");
scanf("%s", buf);
while(buf != "end")
{
if(strcmp(buf, "end")== 0){
break;
}
switch( buf[i] ){
//Where the cases will inevitably go
default:
puts("I'm sorry, but that's not a command.\n");
break;
}
printf("Command? ");
scanf("%s", buf);
}
puts("End of Program.");
getch();
}
char *myInputString = NULL;
while (1) {
/* read in myInputString from user input, and test... */
if (strcmp(myInputString, "foo") == 0)
break;
}
return EXIT_SUCCESS;