2

I have follow situation I have an program make an set of operations on a file continuously and I want, when a specific key is pressed, to stop and do another set of operations.

For this I tryed use scanf of an character with

fcntl(0, F_SETFL, O_NONBLOCK);

and

while(feof(stdin))

but it doesn't work as expected.

I have searched and in some places someone says to use select but I can't find how to use it.

Anyone can advice me somehow?

my main function to provide more information:

int main(int argc, char *argv[])
{


 if(argc>1){
  char* password;
  char* password2;

  printf("Password? ");
  password = get_password();
  printf("Repita a password? ");
  password2 = get_password();

  if(strcmp(password,password2)!=0){
   printf("Passwords diferentes!\n");
   exit(1);
  }

  FILE *fptr;
  fptr = fopen("./regist", "r");
  if(fptr == NULL) //if file does not exist, create it
  {
   fptr = fopen("./regist", "w");
  }
  fclose(fptr);

  if(find_username(argv[1])){
   printf("Utilizador ja existe\n");
   exit(1);
  }
  add_user_regist(argv[1],password);
  printf("Utilizador %s adicionado.\n",argv[1]);
  exit(0);
 }


 char readbuf[250];

 /* Create the FIFO if it does not exist */
 umask(0);
 mknod(FIFO_FILE, S_IFIFO|0666, 0);
 printf("Servidor iniciado.\nEm modo de espera de mensagens\n");

 fcntl(0, F_SETFL, O_NONBLOCK);
 while(1){


  char c = getchar();
  if(c=='q' || c=='Q')
    exit(0);//by now only goes out


  fp = fopen(FIFO_FILE, "r");
  fgets(readbuf, 250, fp);
  fclose(fp);

  if(readbuf[0]=='U')
    user_access(readbuf);
  else if(readbuf[0]=='W')
    who_online(readbuf);
  else if(readbuf[0]=='R'){
    char* tmp;
    strtok(readbuf,":");
    tmp = strtok(NULL,";");
    remove_online(tmp);
    printf("# %s fez logout\n",tmp);
  }
  else if(readbuf[0]=='F'){
    process_msg(readbuf);
  }

 }
 return(0);
}
warwcat
  • 309
  • 3
  • 5
  • 13
  • 3
    On what OS ? That changes the answer – Boiethios May 18 '16 at 07:09
  • Post your code. Why using `fcntl` is not working? – LPs May 18 '16 at 07:16
  • linux , the fcntl I used but when I pressed 'Q' what is my key the scanf maybe don't nocice that continued make first operation's – warwcat May 18 '16 at 07:46
  • If you are on linux perhaps using a signal like SIGINT might be interesting. When you hit ctrl-c you will receive this signal. – Dave Kok May 18 '16 at 07:55
  • what do you expect `while(feof(stdin))` to do? If you need a `getch` function, see [my answer here](http://stackoverflow.com/questions/7410447/why-getch-returns-before-press-any-key/7411735?s=2|2.5036#7411735). – luser droog May 18 '16 at 08:12
  • I know about SIGINT but I need to use specific key – warwcat May 18 '16 at 11:41

2 Answers2

2

Check out NCurses, the go-to library for any kind of advanced terminal software.

Among other things, it provides you with the tools to do "raw" terminal I/O -- using int getch( void ), made a non-blocking call via int nodelay( WINDOWS * win, bool bf ).

This blocks:

#include <ncurses.h>

int main()
{
    initscr();
    printw( "Press a key:\n" );
    int c = getch();
    endwin();
}

This doesn't (returning ERR if there is no input pending):

#include <ncurses.h>

int main()
{
    initscr();
    printw( "Press a key:\n" );
    nodelay( stdscr, TRUE );
    int c = getch();
    endwin();
}

Note that NCurses comes with its own set of I/O functions, which you will have to use instead of the <stdio.h> ones (check the printw() above).

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • Yes, that's the answer. And use fork to create a sub-process that do the job, while in the main process you check for input. If the user press a key, just kill the other process. – Boiethios May 18 '16 at 08:05
2

An alternative to termios/ncurses using GNU Readline:

#include <readline/readline.h>
#include <stdio.h>

static int func(int count, int key)
{
    printf ("key pressed: %c\n", key); /* exec your function */
    return 0;
}

int main(void)
{
    char *line;

    rl_bind_key('x', func); /* 'x' is the specific key */
    line = readline ("> ");
    printf("%s\n", line);
    return 0;
}

Compile using -lreadline

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • almost solve my problem but if I use Exit(0) on func , after program execution console input is blocked – warwcat May 18 '16 at 17:38