1instance.c 2.76 KB
Newer Older
dscho's avatar
dscho committed
1 2 3 4 5 6
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
7
#include <stdio.h>
dscho's avatar
dscho committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

typedef struct {
  char* filename; /* this file is the pipe (set by user) */
  char is_server; /* this is set by open_control_file */
  int fd; /* this is set by open_control_file */
} single_instance_struct;

/* returns fd, is_server is set to -1 if server, 0 if client */
int open_control_file(single_instance_struct* str)
{
  struct stat buf;

  if(stat(str->filename,&buf)) {
    mkfifo(str->filename,128|256);
    str->is_server=-1;
    str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
  } else {
    str->fd=open(str->filename,O_NONBLOCK|O_WRONLY);
    if(errno==ENXIO) {
      str->is_server=-1;
      str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
    } else
      str->is_server=0;
  }

  return(str->fd);
}

void delete_control_file(single_instance_struct* str)
{
  remove(str->filename);
}

void close_control_file(single_instance_struct* str)
{
  close(str->fd);
}

typedef void (*event_dispatcher)(char* message);

int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs)
{
  struct timeval tv;
  fd_set fdset;
  int num_fds;

  FD_ZERO(&fdset);
  FD_SET(str->fd,&fdset);
  tv.tv_sec=0;
  tv.tv_usec=usecs;

  num_fds=select(str->fd+1,&fdset,NULL,NULL,&tv);
  if(num_fds) {
    int reallen;

    reallen=read(str->fd,buffer,len);
    if(reallen==0) {
      close(str->fd);
      str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
      num_fds--;
    }
    buffer[reallen]=0;
#ifdef DEBUG_1INSTANCE
71
    if(reallen!=0) rfbLog("message received: %s.\n",buffer);
dscho's avatar
dscho committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
#endif
  }

  return(num_fds);
}

int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs)
{
  char buffer[1024];
  int num_fds;

  if((num_fds=get_next_message(buffer,1024,str,usecs)) && buffer[0])
    dispatcher(buffer);

  return(num_fds);
}

int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher)
{
  open_control_file(str);
  if(str->is_server) {
    while(1)
      dispatch_event(str,dispatcher,50);
  }

  return(str->fd);
}

void send_message(single_instance_struct* str,char* message)
{
102
#ifdef DEBUG_1INSTANCE
dscho's avatar
dscho committed
103
  int i=
104
#endif
dscho's avatar
dscho committed
105 106
  write(str->fd,message,strlen(message));
#ifdef DEBUG_1INSTANCE
107
  rfbLog("send: %s => %d(%d)\n",message,i,strlen(message));
dscho's avatar
dscho committed
108 109 110 111 112 113 114 115 116 117 118 119 120
#endif
}

#ifdef DEBUG_MAIN

#include <stdio.h>
#include <stdlib.h>

single_instance_struct str1 = { "/tmp/1instance" };

void my_dispatcher(char* message)
{
#ifdef DEBUG_1INSTANCE
121
  rfbLog("Message arrived: %s.\n",message);
dscho's avatar
dscho committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
#endif
  if(!strcmp(message,"quit")) {
    delete_control_file(str1);
    exit(0);
  }
}

int main(int argc,char** argv)
{
  int i;

  loop_if_server(str1,my_dispatcher);

  for(i=1;i<argc;i++)
    send_event(str1,argv[i]);

  return(0);
}

#endif