I'm trying to solve a problem because I'm learning to use system calls in C. I used a Ubuntu 12.04 64bit.
The statement of the problem says that I need to implement a code that allows to execute a command (cmd2) after the correct end of other command (cmd1). Also says that user can specify both commands and all of the arguments that user wants.
At this point I create this little program:
#include <syscall.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int cmd1 = system("sleep 5");
if((cmd1 = (-1)))
{
write(1,"error in command 1",18);
}
if(cmd1=(0))
{
write(1, "hello world", 11);
}
return EXIT_SUCCESS;
}
Next, statement says that if the first command doesn't finish correctly the second will not execute, also, user can abort the execution of the cmd1 using Ctrl+\ or Ctrl+4 (SIGQUIT) and the second command (cmd2) using Ctrl+C (SIGINT). If second command is canceled the first must be completed normaly.
I have problems in this second part of the statement because I never used this kind of things in C and also I'm really noob in linux. I tried to read something about SIGQUIT and SIGINT but I don't understand all that I've read probably because there are a lot of things of linux that I've not learned yet.
Can anyone help me please?
Thanks!
I edit the code for this version using if functions. It doesn't work correctly, I'm finding how to check if the first command finishes correctly.
Just to get you started. Let me explain the question because I feel you haven't understood it.
The statement of the problem says that I need to implement a code that allows to execute a command (cmd2) after the correct end of other command (cmd1).
You will will be given two commands by the user cmd1 and cmd2. cmd1 should be executed first.
Next, statement says that if the first command doesn't finish correctly the second will not execute,
ONLY IF cmd1 finished executing normally should cmd2 be executed.
If second command is canceled the first must be completed normaly.
Execution of cmd1 is not dependent on cmd2.
user can abort the execution of the cmd1 using Ctrl+\ or Ctrl+4 (SIGQUIT)
You seem confused here. Here, they mean to say, cmd1 can be abnormally terminated by passing SIGQUIT to it(Ctrl+\ or Ctrl+4), in which case cmd2 should not be executed. You do NOT have to code the signals part. What you have to do is, check how cmd1 was terminated and then execute cmd2 if it was a normal termination else don't execute cmd2.
Note The code in the question was extremely different when the above part was posted.
This was your code on 5:02 AM Wednesday, 20 May 2015 GMT.(Had to include this because you are changing the code too often and too much)
int main(void)
{
int cmd1 = system("sleep 5");
if((cmd1 = (-1)))
{
write(1,"error in command 1",18);
}
if(cmd1=(0))
{
write(1, "hello world", 11);
}
return EXIT_SUCCESS;
}
Here you are using = for comparing. = is used for assignment and not equality compassion. == is used for equality compassion. So, if((cmd1 = (-1))) and if(cmd1=(0)) should have been if((cmd1 == (-1))) and if(cmd1 == (0))
You are checking if the returned value is -1 for failure. This is incorrect. Exit code for success is 0 for failure is any value other than 0. So, if((cmd1 = (-1))) should have been if(cmd1 != 0).
Related
I'm having trouble understanding how to do basic piping in C. I looked at a couple other questions on this topic, and either they were for subtly different issues, or I'm so far off the mark on this subject I couldn't understand why the answers are good for my problem.
This program below is just a simple test I made, where I'm trying to get behaviour equivalent to typing "ls | grep a" into my shell. (I have a homework assignment where I have to build a shell that can handle piping, but this is my first step towards understanding pipes to even attempt the homework). I get the correct output, but the terminal prompt ends up appearing before the output, making it look like it did not properly terminate. Since this is connected to a shell homework, I'm worried that will impact the grade (and it just feels wrong to let it look like that anyway). Any advice?
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
int main()
{
int fdpipe[2];
pipe(fdpipe);
int f1 = fork();
if(f1 == 0)
{
close(fdpipe[1]);
dup2(fdpipe[0],0);
close(fdpipe[0]);
execlp("/bin/grep","grep","a",NULL);
}
else
{
close(fdpipe[0]);
dup2(fdpipe[1],1);
close(fdpipe[1]);
execlp("/bin/ls","ls",NULL);
wait(NULL);
}
return 0;
}
Here's an example of my terminal output.
1067: ls
a.out test.c test.cc
NathanE: ~/Desktop/playground
1068: ./a.out
NathanE: ~/Desktop/playground
1069: a.out
(The beginning of this line is where my cursor is)
What I'm expecting would be:
1067: ls
a.out test.c test.cc
NathanE: ~/Desktop/playground
1068: ./a.out
a.out
NathanE: ~/Desktop/playground
1069: (my cursor would go here)
The child process runs grep, while the parent replaces itself with ls. The wait(NULL) does nothing, because successful exec*() never return.
Because the control returns to the shell immediately after ls completes, the shell can display the next prompt before grep completes.
There are two approaches you can use to avoid this:
fork() both child processes, and wait() for them
Replace the process itself with the last process in the pipe chain
Either will ensure that control is returned to the shell only after the last process in the pipe chain completes.
I have a problem with my C code, basically I need to send email via mutt program. It must be send when an interrupt comes up from GPIO pin. My sendMail function is listed below. I realized this by using system function. Main contains loop with logAlarm func which contains sendMail. The thing is when system(cmd) function finishes, the whole C program stops. For instance when i put sendMail function at the begining of the main it works and is sending email to my mailbox without stopping whole program, in the loop it manages to send it but it terminates program. I tried to using & sign to run it in background but it didnt help.
P.S i dont know if it matters but im also using system call from setitimer with 2 sec intervals to check few things but i guess it has no impact for this case.
Any ideas?
Thanks in advance :)
sendMail function:
void sendMail(char * msg, char * recipientMail){
char cmd[100];
char subject[30];
char body[60];
sprintf(body, "Intruder detected!!!\n%s", msg);
strcpy(subject, "\"ALARM - SECURITY BREACH\"");
sprintf(cmd,"echo \"%s\" | mutt -s %s %s &", body, subject, recipientMail);
printf("%s\n\n", cmd);
system(cmd);
}
Here is a piece of my main function:
while(1){
sleep(1);
if(prev_state == triggered && !emailDetach){
if(!logAlarm()){
printf("Error writing to log file!!!\n");
}
emailDetach = true;
}
//printf("Czas od poprzedniego alarmu: %d", millis() - alarmTriggeredTime);
if((prev_state == triggered) && (millis() - alarmTriggeredTime >= ALARM_TIME)){
digitalWrite(ALARM_ON_DIODE, LOW);
digitalWrite(ALARM_OFF_DIODE, HIGH);
//warunek czasowy osobno na syrene TODO
if(!silentMode && (millis() - alarmTriggeredTime >= siren_alarm_time)){
digitalWrite(SIREN, LOW);
}
prev_state = nottriggered;
}
}
Good question. As per description, I consider that sendMail function works properly. I've not worked with mutt. But i've worked with system().
What system does is, it forks a child process of your current process and executes the command using execve(). So the problem should be in the returning of the system.
So, first you should check the return status of system function. If you are able to make printf() below the system(), then you're not having problem with system(). If you are not able get printf below the system(), then system() is killing your process. (by sending sigkill or similer signals, but not sigint or sigquit, since it is ignored by system()). You are creating a child process in the cmd itself (echo output piping to mutt). May be this should be root cause.
If you find problem here, then the problem is critical, and you will find directions from the "NOTES" section of "man system", since you have implemented the same logic mentioned there. First just try to wait for conditions mentioned there. If you're still unable to do this, try to fork two new child process, run execl or any other exec family function ("man 3 exec") from that child process to run echo and mutt.
If system() is ok, then check logAlarm(). is it giving the right arguments to the sendMail? if you are getting "Error writing to log file!!!", then entire sequence is ok.
I have a very strange problem in C. A function from a proprietary library reduces sleep(n) to sleep(0).
My code looks like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /*sleep() */
int main(int argc, char** argv){
//...
AStreamEngine.init();
AStreamEngine.setCodec(3);
AStreamEngine.start(); //problematic function
printf("a");
sleep(100);
printf("b");
return 0;
}
If the problematic function is commented out, then printing "a" follows by printing "b" after 100 sec. But if isn't commented out, "ab" is printed. So the program ends very quickly and I cannot notice if the engine works.
I found that:
if I replace sleep() by getchar() the engine works correctly.
if I put active waiting by a for-loop then it also works.
Does anyone have any idea why happens? And how to fix (bypass) this feature/bug? I don't want use getchar and active waiting.
Update:
I don't have source of the library. I have only binary .so file.
Base on responces I add a below code add end:
struct timespec to_sleep = { 1, 0 };
int ret = nanosleep(&to_sleep,&to_sleep);
printf("%d\n",ret);
if(ret == -1){
printf(" break sleep : %d %s", errno,strerror(errno));
}
And I get output:
-1
break sleep : 4 Interrupted system callc
Now I try to bypass by thread.
"sleep" can be interrupted by signals - see http://man7.org/linux/man-pages/man3/sleep.3.html . My guess is that the "start" function started a thread which might have caused signals to be sent to your program. Put "sleep" in a loop like this:
unsigned int x = 100;
while (x > 0) { x = sleep (x); }
Another point: printf may be line-buffered. In that mode, the output is only seen if you print a "\n" character. Try using "a\n".
As rightly said by Jack, usleep and sleep can be interrupted by the delivery of signals (E.g presence of ioctl, read, write function calls).
One of the smart way to avoid this issue is to use nanosleep. Like sleep and usleep, nanosleep can also be interrupted by the delivery of signals but the difference is, its second argument tells you how much time is remaining.
You can use this argument to make sure your code sleeps for the specified amount of time. Replace your sleep and usleep function with a while loop containing nanosleep. Following is the example usage,
struct timespec to_sleep = { 1, 0 }; // Sleep for 1 second
while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR));
Off course this solutions is not suitable for the application where exact amount sleep is required but it is very useful in the cases where minimum delay is required before executing next function.
After examination, I think that the using of the sleep() function is useless on your case.
Indeed, the sleep function uses the pause() function, which wait for a signal and stops if your process receive a signal call.
In your case it's probably the problem, and it explains why the sleep() function stops when you call the AStreamEngine.start() function.
I think that the best solution is to use the usleep() function, which should not stops if your process receive a signal.
Try this :
usleep(VALUE_IN_MILISECONDS);
Good luck ! :)
I am writing a program in C in one of my systems classes. We write c code and run it in a unix environment. I have looked all over the internet, but can't seem to find any way to make the kill(int PID) command work. The code will compile and run fine, but if I use the
ps -u username
command in a unix command prompt (after execution has completed of course,) it says that the all of the processes I tried to kill in my c code are still running. I can kill them from the unix command prompt by manually entering their PIDs, but for the life of me, I cannot figure out how to do it inside of my program.
In this particular program, I am trying to kill process CC, which is a process that just infinitely calls usleep(100); until terminated.
I tried using kill(C3, -9); and variations of execlp("kill", "kill", C3, (char *)0); but still no luck. Does anyone have any idea what I am doing wrong here? My only guess is that the kill command is being passed the wrong PID parameter, but if that's the case, I have no idea how I would get the correct one.
EDIT: Also, the kill command returns a value of zero, which I believe means that it "succeeded" in executing the command.
EDIT: Just noticed that the solution to my problem was in the instructions for the assignment all along. Yup. I'm stupid.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int args, char* argv[])
{
//
//Step 7
//
//Create process C3
int C3=fork();
if (C3==0)
{
execlp("CC", "CC", (char *)0);
}
else
{
usleep(500000);
//
//Step 8
//
int ps=fork();
if (ps==0)
{
execlp("ps", "ps", "-u", "cooley", (char *)0);
}
else
{
wait(NULL);
kill(C3);
}
}
exit(0);
}
You're calling the kill system call with only one argument, when it takes two. This leads to undefined behavior since then the second argument can by anything. You should get a warning about this when compiling.
The second argument should be a value from <signal.h> (see the signal(7) manual page).
How can I execute shell from a C code?
My shell is placed in /bin/sh
Following didn't seem to work for me
system("/bin/sh");
exec("/bin/sh");
Maybe you need to tell the shell it should be interactive:
system("/bin/sh -i");
However, I believe that your original system() call should have produced a shell prompt too.
Both notations (with and without the '-i') in this program give me a shell prompt (return to the previous shell by typing 'exit' and RETURN or Control-D):
#include <stdlib.h>
int main(void)
{
system("/bin/sh -i");
return 0;
}
This program works as expected for me:
int main()
{
int ret = system("/bin/sh");
printf ("Shell returned %d\n", ret);
return 0;
}
using -i causes some sort of redirection issue and everything hangs as soon as I type a command that produces output.
There are important differences between system() and exec(). system() is effectively the same as /bin/sh -c yourCommand on the command line, so the system("/bin/sh") is the same as
/bin/sh -c /bin/sh
This is why it is rarely used, because the command you want is executed by first starting an unnecessary shell process.
exec() causes the entire process image to be replaced by the command specified so if I had written:
int main()
{
int ret = exec("/bin/sh");
printf ("Shell returned %d\n", ret);
return 0;
}
The printf() and everything after it would never have been executed because the whole process transforms into an instance of /bin/sh. The proper way to run a child command is to fork and then exec in the child and wait in the parent.