So i need to write an whileloop for a program that's supposed to prompt the user with this:
char vector[10];
while(????){
print("Write a number");
scanf("%s",vector);
}
printf("Goodbye");
The program is supposed to print goodbye and close when the user presses ctrl+c.
Im pretty sure I cant use putchar in this case?
#include <windows.h>
#include <stdio.h>
static end_flag = 0;
BOOL WINAPI controlHandler(DWORD type){
if(type == CTRL_C_EVENT){
end_flag = 1;
return TRUE;
}
return FALSE;
}
int main(){
char vector[10];
if (!SetConsoleCtrlHandler(controlHandler, TRUE)) {
fprintf(stderr, "Failed SetConsoleCtrlHandler");
return -1;
}
while(!end_flag){
printf("Write a number ");
scanf("%s",vector);
}
printf("Goodbye");
return 0;
}
CTRL+Z version
#include <stdio.h>
int main(){
char vector[10];
while(1){
printf("Write a number ");
if(scanf("%s", vector)==EOF)//press CTRL+Z
break;
}
printf("Goodbye");
return 0;
}
see https://superuser.com/questions/214239/whats-the-command-prompts-equivalent-to-cygwins-ctrlz:
Depends on what you mean by "quit something"; within Windows cmd:
Ctrl+Z sends the EOF character, which could terminate a process if
you're providing input, but otherwise will probably do nothing.
Ctrl+C normally sends SIGINT to the foreground process, which should
terminate it, but programs can respond however they like - ie, they
can catch the signal but then ignore it. The command can also be
remapped to other jobs (such that for a specific program it doesn't
really send a signal) or ignored entirely.
Ctrl+Break always sends SIGBREAK, which again should terminate the
process, but unlike Ctrl+C cannot be remapped, but can still be
ignored. This is probably what you need.
I think this might be what you're looking for:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683242%28v=vs.85%29.aspx
Post similar to this one on Stack Overflow:
Catch Ctrl-C in C
You might want to check it out. Cheers!
Related
I am trying to implement some of the features present in the shell including quitting only when a user enters quit and not on Ctrl+C. Below is a simplified version of the code that I am tried.
Code 1: without calling loop() in a signal handler.
void loop(){
while(1){
char a[20];
printf("Enter Command : " );
scanf("%s",a);
printf("%s\n", a);
}
}
void sigintHandler(int sig_num)
{
signal(SIGINT, sigintHandler);
printf("\n");
}
int main(int argc, char const *argv[]) {
signal(SIGINT, sigintHandler);
loop();
return 0;
}
The output of Code 1:
As can be seen on a third input, I go to a new line and continued right from where I left the loop. I want to instead start the loop again. So, I did the following modification by calling loop in signal handler itself.
void loop(){
while(1){
char a[20];
printf("Enter Command : " );
scanf("%s",a);
printf("%s\n", a);
}
}
void sigintHandler(int sig_num)
{
signal(SIGINT, sigintHandler);
printf("\n");
loop();
}
int main(int argc, char const *argv[]) {
signal(SIGINT, sigintHandler);
loop();
return 0;
}
Output for code 2:
As can be seen that when I clicked first-time Ctrl+C (on input line 3), it works properly and I can continue. But when I click Ctrl+C second time I don't go to a new line and I have to press enter for a program to execute.
I went through this question but it doesn't seem to apply for my case. This is my first time using signals and system calls so my question may come as silly. But it will be a great help if someone can help me to get to a proper way of implementing signals. Thank you.
Jonathan Leffler provided helpful hints (though not sufficient, at least on some popular operating system):
Look at what scanf() returns.
Don't use loop() in the signal handler
Don't use signal() — use sigaction(). In your case, this has two advantages:
Restoring the signal action to the default state on call of the signal handler can be avoided, so you don't have to change the action again in the handler.
Restarting the read() system call (inside scanf()) can be avoided, so that scanf() returns and you can react to the interrupt in the first place.
So, the signal handler can be just
void sigintHandler(int sig_num)
{
printf("\n"); // or perhaps better write(1, "\n", 1)
}
The signal(SIGINT, sigintHandler); in main() can be replaced with
sigaction(SIGINT, &(struct sigaction){ .sa_handler = sigintHandler }, NULL);
and the scanf("%s",a); with
if (scanf("%s", a) == EOF)
{
if (errno == EINTR) continue; // read operation interrupted by signal
return;
}
EOF is returned on interrupt as well as on end of file, so the cases are to be distinguished through errno. Besides, it's nice if your program provides a way to exit it, thus the return.
I'm a student new to C Programming and am not fully understanding how signal catching works, and in line with character device drivers. I'd appreciate some help but I need to state that this is for a project that is due in my first C Programming class. So I have not posted any direct code, only an example of my initial approach.
My project needs to accept a signal input and set that signal to a variable to pass to my character device driver. Another program I've written will need to access that variable's value such that when read, it performs a certain outcome. I've tried to run my control program (<name> &) but it quits immediately. I double check by entering ps into my command prompt and the process is gone.
Basically I need my control program to pause and wait for the signal to be received. Once received, if the signal matches it will set a variable to its value. Otherwise, if it is SIGTERM it will either end or pause(), where it will wait until another signal is received that meets another condition. Currently, when I compile and run it with & it simply runs and quits. Here is an example of my code:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
static int file_state; //variable to pass to the driver for recording
void sig_handler(int sig);
void sig_handler(int sig){
while(1){
if(sig == SIGRTMIN){
printf("SIG = SIGRTMIN\n");
file_state = 0;
}else if(sig == SIGRTMIN+1){
printf("SIG = SIGRTMIN1\n");
file_state = 1;
}else if(sig == SIGTERM){
printf("Exiting\n");
exit(0); //exit
}else{
printf("SIG = %i\n", sig);
pause(); //doesn't match, pause for next signal
}
}
}
int main(){
signal(SIGINT, sig_handler);
//return 0; //tried with and without
}
I'm waiting until this daemon receives a signal to put the device driver into a particular mode. I haven't entered any write() methods yet because I'm trying to take this one step at a time where I send a signal with kill() and the proper response is returned with printf().
My problem is that I can't seem to keep this in pause() mode while I'm waiting for a signal that breaks the if loop. What's worse (other than my lack of knowledge and programming) is that I can't even keep this daemon open long enough to attempt a signal send. Once I can get this to pause and receive the signal, I plan to use the system write() method to write my file_state variable to the /dev/<filename>, which will be cross-referenced in my executable.
How far off am I? This is the final part that (I believe) I'm stuck on and I can't figure out how this should be approached. I've looked online and about 95% of the examples that delve into this contain methods we haven't learned yet. And if not, the examples are more simplistic where they do not include passing a value to a character device driver for use when another program is using the driver.
Any help is greatly appreciated.
ETA
I've updated my code so now it stays open until a signal is received. Problem is that I want this to pause() and remain open until the SIGTERM signal is received, breaking the loop and ending the program. I can't seem to get the loop correct. Even entering a conditional int variable into the while() loop still is broken when any signal is received. Here is my updated code below:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
static int file_state; //variable to pass to the driver for recording
int keep_alive = 1; //added for conditional checking to keep the while
//loop open to receive more than one signal
void sig_handler(int sig);
void sig_handler(int sig){
if(sig == SIGRTMIN){
printf("SIG = SIGRTMIN\n");
file_state = 0;
}else if(sig == SIGRTMIN+1){
printf("SIG = SIGRTMIN1\n");
file_state = 1;
}else if(sig == SIGTERM){
keep_alive = 0;
}else{
}
}
int main(){
do{
signal(SIGINT, sig_handler);
pause(); //thought pausing here would help with waiting for a new signal
}while(keep_alive == 1); //keep looping until false
return 0; //tried with and without
}
I'm trying to figure out a method to keep this process and signal catching loop alive until a specific signal is received. I can't figure it out for the life of me.
ETA 2
Discovered my issue. I wasn't paying attention and fully understanding the signal() method. The first argument requires the exact signal you are attempting to catch. I was using SIGINT which I was understanding it to be a "class" of interrupts that you wanted to catch. And then in the signal_handler() function, you would specify which type of interrupt you were catching. But, it is actually looking to catch the exact signal you are interested in. So in my example code, I should have been using:
int main(){
if(signal(SIGRMIN, sig_handler) == SIG_ERR){
printf("can't catch SIGRMIN Signal.\n")
}
...
}
I'm going to update with my new script as an answer and if anyone thinks it should be done differently or have any constructive criticisms please let me know. Thanks again!
So I found my issue, and it is working now. Below is my fixed code that produces the correct response back to the terminal when caught. I've added a for() loop to catch any other signals I'm not worried about didn't stop my process, only SIGTERM will. Look forward to getting critiqued and why I would never want to do my approach.
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
static int file_state; //variable to pass to the driver for recording
void sig_handler(int sig);
void sig_handler(int sig){
if(sig == SIGRTMIN){
printf("SIG = SIGRTMIN\n");
file_state = 0;
}else if(sig == SIGRTMIN+1){
printf("SIG = SIGRTMIN1\n");
file_state = 1;
}else if(sig == SIGTERM){
exit(0);
EXIT_SUCCESS;
}else{
printf("SIGNAL CAUGHT #%d\n", sig);
}
}
int main(){
if(signal(SIGRTMIN, sig_handler)==SIG_ERR){
printf("Unable to catch SIGRTMIN\n");
}
if(signal(SIGRTMIN+1, sig_handler)==SIG_ERR){
printf("Unable to catch SIGRTMIN+1\n");
}
if(signal(SIGTERM, sig_handler)==SIG_ERR){
printf("Unable to terminate process.\n");
}
//This for loop will catch all other signals except the un-catchable and
//other user-specified above signal #31.
int s;
for(s = 0; s < 32; s++){
signal(s, sig_handler);
}
while(1);
pause();
return 0;
}
There are 2 parts, 1st user space where generation and catching of signals occurs. This has nothing to do with kernel driver. Your code seems okay about it.
2nd is interacting with driver when signal has been caught. For char driver have a look at this link. You can simply write a value write(fd, 1, &buf); from user space program and implement corresponding write() in char driver.
I'm experimenting with SIGINT. I basically want my program to start as soon as the user hits control-c. When this happens, I'm going to then get the program to make a pipe.
Now, I decided that when control-c is pressed in the signal handler it will call a function to create the pipe. Yet this is messing up. It's fine running a printf command but refuses to carry out the if statement until you press control-c again. Anyone able to assist?
Realistically, I want to disable control-C after it has been pressed once.
#include <stdio.h>
#include <signal.h>
void catchme(int signal);
void Setup();
int main()
{
if (signal(SIGINT, catchme) == SIG_ERR)
{
write(2, "Error catching signal C\n", 26);
}
printf("To begin, please press CTRL + C\n");
for(;;);
return 0;
}
void catchme(int signal)
{
write(1, "\n Caught Signal from Control C\n", 33);
Setup();
}
void Setup()
{
int firstPipe[2];
printf("Lets set up...\n");
if (pipe(firstPipe) < 0)
{
printf("Error creating pipe 1\n");
//abort program
}
else
{
printf("working so far");
}
}
You should get a debugger working. It would provide you with the answer to your question within seconds, and it's essential for trying to track down these kinds of problems. What seems very mystifying and unclear, when you're trying to interpret the output, will seem very easy when you're stepping through it, and you can see everything.
This will probably lead to pipe() not doing what you expect, you'll check errno, and presumably get a useful answer.
The commenter's advise about avoiding doing stuff in signal handlers is good, as it's not portable. However, most modern OSs are quite permissive, so I'm not sure if that's your problem in this case.
I am having a very confusing problem right now. I wrote a test program for myself, but sometimes after I input Crtl+C, which is what I assume to be the EOF, the program closes early without running through some more commands below the While Loop I wanted it to cancel from.
#include <stdio.h>
#include <string.h>
int main()
{
char message[140];
char* p = message;
int count;
int i = 0;
int charGT;
while((charGT=getchar()) != EOF)
{
message[i] = charGT;
i++;
printf("%d" , i);
}
printf("next");
count = strlen(p);
printf("%d", count);
printf("after");
return (0);
}
Inputting "asd\n^C" will cause my program to end early. "next" or "after" will not be printed
My theory is that somehow, the \n is causing the program to step out of the loop for a moment, and then Crtl+C is exiting the program, but I don't know how that would work.
Ctrl+C is the break command and will send an interrupt signal to your application. The default handler will cause this to exit the process.
Ctrl+D is the EOF command you are looking for.
For running on windows, to enter EOF press Ctrl+Z and then press ENTER. In UNIX systems it is Ctrl+D, in Windows Ctrl+Z.
When a program is running if you press Ctrl-c a signal is sent to abort the program and the program is aborted. However, if you want to use Ctrl-c as an input but not abort the program write one signal handler which catches the signal when you press Ctrl-c and perform the action you wanted to.
I'm practicing C programming for Linux for an exam.
I don't know how to exit the program when user press Ctrl + a ( not Ctrl+c )
For example, looping something until user press Ctrl+a
Could anyone tell me how to check Ctrl+a input?
Notes: I'm using 'gcc' and run output with './a.out'
Thanks in advance for everyone!
Turbo C and other implementations of C for Windows had a function call getch() which would read single characters from the keyboard; those would have done what you want.
In POSIX environments, such as are implemented by gcc-compiled programs under Unix/Linux, that functionality isn't directly there.
There's a library called curses which allows C programs to do full-screen output processing, and there is also getch() functionality in curses. This may end up being the simplest answer to your problem. You'll need to read the documentation on curses and link the header files and library into your program.
There is special support for Ctrl-C, which is translated into a signal by the system. If you want your program to stop as soon as another specific key combination is used, it will be much harder.
you will need to check the standard input of your program, and you will need to set the standard input so the inputs are not buffered (otherwise you won't see any input until it is validated by the user pressing "return"). The latter part would be done with a ioctl() call and would not be portable;
you will need either threads or polling, none of which is very palatable in C.
There are more interesting things to practice in C than these.
catching ctrl-c event
This post answers your question
did you looking for something like this ???
this program won't be stopped since you hit ctrl+A and Enter.
#include <stdio.h>
int main() {
char a;
while( a!=1 ) //Ascii code for ctrl + A == 1
{
a=getchar();
printf("still looping ...\n");
}
printf( "HA! You pressed CTRL+A\n" );
return 0;
}
But if you wanna terminate your program just after pressing ctrl+A (without hitting enter after that), here you are:
#include <stdio.h>
#include <ncurses.h>
int main() {
char a;
initscr();
raw();
while( a!=1 )
a=getch();
endwin();
return 0;
}
for compiling second code using GCC, try this command:
gcc -o program.o -lncurses program.cpp
This will do what you want:
stty intr ^a
./a.out
For extra credit, do the equivalent of "stty intr ^a" using the appropriate library function, e.g. "man termios".
Someone posted first with following code which works for me but I don't know why he deleted his answer.
Original Link : http://www.c.happycodings.com/Gnu-Linux/code18.html
#include <stdio.h>
#include <unistd.h> /* sleep(1) */
#include <signal.h>
void ex_program(int sig);
int main(void) {
(void) signal(SIGINT, ex_program);
while(1)
printf("sleeping .. ZZZzzzz ....\n"), sleep(1);
return 0;
}
void ex_program(int sig) {
printf("Wake up call ... !!! - Catched signal: %d ... !!\n", sig);
(void) signal(SIGINT, SIG_DFL);
}
This is how to set CTRL-A as interrupt to break the process. Notice too that CTRL-C doesn't break it after tcsetattr is called.
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
struct termios termios;
if ( tcgetattr(0, &termios) != -1 ) {
termios.c_cc[VINTR] = '\x01'; /* CTRL-A */
if ( tcsetattr(0, 0, &termios) != -1 ) {
printf("Ready. Press CTRL-A to break this program\n");
while ( 1 ) {
printf("*\n");
sleep(1);
}
}
}
}