NEURON
nrnbbs.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 // bug in the osx 10.2 environment
3 #if defined(__POWERPC__) && defined(__APPLE__)
4 #undef HAVE_LOCKF
5 #endif
6 
7 #include <stdio.h>
8 #include <fcntl.h>
9 #include <ctype.h>
10 #include <signal.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <sys/stat.h>
16 
17 #include <OS/list.h>
18 #include <OS/string.h>
19 #include "nrnbbs.h"
20 
21 #if !defined(HAVE_LOCKF)
22 #include <sys/file.h>
23 #endif
24 
25 #define HISTORY 0
26 
27 #define NRNBBSTMP "nrnbbs"
28 #define NOTIFY "notify"
29 #define NRNBBS "nrnbbs"
30 #define LOCKFILE "lock"
31 #define TMPFILE "temp"
32 #define NOTIFY_SIGNAL SIGUSR1
33 
35 public:
36  NrnBBSCallbackItem(const char*, NrnBBSCallback);
37  virtual ~NrnBBSCallbackItem();
38  bool equal(const char*);
39  void execute();
40 private:
43 };
44 
45 static const char* fname(const char* name);
46 
47 static void history(const char* s1, const char* s2, const char* s3) {
48 #if HISTORY
49  FILE*f;
50  if ((f = fopen(fname("history"), "a")) != (FILE*)0) {
51  fprintf(f, "%5d %s |%s| |%s|\n", getpid(), s1, s2, s3);
52  fclose(f);
53  }
54 #endif
55 }
56 
57 static void history(const char* s1) { history(s1, "", ""); }
58 static void history(const char* s1, const char* s2) { history (s1, s2, ""); }
59 static void history(const char* s1, int i) {
60  char buf[20];
61  sprintf(buf, "%d", i);
62  history(s1, buf, "");
63 }
64 
65 declarePtrList(NrnBBSCallbackList, NrnBBSCallbackItem)
66 implementPtrList(NrnBBSCallbackList, NrnBBSCallbackItem)
67 
68 static NrnBBSCallbackList* cblist_;
69 static FILE* lockfile_;
70 
71 static void get_lock() {
72 #if !defined(HAVE_LOCKF)
73  while (flock(fileno(lockfile_), LOCK_EX) != 0) {
74 #else
75  while (lockf(fileno(lockfile_), F_LOCK, 0) != 0) {
76 #endif
77  history("lockf returned non zero");
78  }
79 //printf("got lock for %d\n", getpid());
80 }
81 
82 static void release_lock() {
83 #if !defined(HAVE_LOCKF)
84  flock(fileno(lockfile_), LOCK_UN);
85 #else
86  lockf(fileno(lockfile_), F_ULOCK, 0);
87 #endif
88 //printf("released lock for %d\n", getpid());
89 }
90 
91 static const char* nrnbbsdir() {
92  static char* d ;
93  if (!d) {
94  char buf[256];
95  char* tmpdir;
96  tmpdir = getenv("TMPDIR");
97  if (!tmpdir) {
98  tmpdir = "/tmp";
99  }
100  sprintf(buf, "%s/%s_%s", tmpdir, getenv("USER"), NRNBBSTMP);
101  d = new char[strlen(buf)+1];
102  strcpy(d, buf);
103  mkdir(d, 0777);
104  }
105  return d;
106 }
107 
108 static const char* fname(const char* name) {
109  static char buf[2][256];
110  static int i = 0;
111  i = (i+1)%2;
112  sprintf(buf[i], "%s/%s", nrnbbsdir(), name);
113  return buf[i];
114 }
115 
116 static bool connected_;
117 
119  if (!lockfile_) {
120  const char* lfile = fname(LOCKFILE);
121  lockfile_ = fopen(lfile, "w");
122  if (!lockfile_) {
123  connected_ = false;
124  return connected_;
125  }
126  }
127  connected_ = true;
128  history("connect");
129  return connected_;
130 }
131 
133  connected_ = false;
134  history("disconnect");
135  if (cblist_) {
136  get_lock();
137  int pid = getpid();
138  FILE* f = fopen(fname(NOTIFY), "r");
139  if (f) {
140  char buf[256];
141  int id;
142  FILE* f2 = fopen(fname(TMPFILE), "w");
143  if (!f2) {
144  fprintf(stderr, "can't open %s\n", fname(TMPFILE));
145  }
146  while (fgets(buf, 256, f)) {
147  buf[strlen(buf) - 1] = '\0';
148  fscanf(f, "%d\n", &id);
149  if (id != pid) {
150  fprintf(f2, "%s\n%d\n", buf, id);
151  }
152  }
153  fclose(f2);
154  fclose(f);
155  rename(fname(TMPFILE), fname(NOTIFY));
156  }
157  release_lock();
158  for (long i=0; i < cblist_->count(); ++i) {
159  delete cblist_->item(i);
160  }
161  delete cblist_;
162  cblist_ = nil;
163  }
164  if (lockfile_) {
165  fclose(lockfile_);
166  lockfile_ = (FILE*)0;
167  }
168 }
169 
171  return connected_;
172 }
173 
174 
175 void nrnbbs_wait(bool* pflag) {
176  bool f = false;
177  bool *pf;
178  pf = (pflag) ? pflag : &f;
179  while (!(*pf) && nrnbbs_connected()) {
180  f = true; // once only if no arg
181  pause();
182  }
183 }
184 
185 void nrnbbs_post(const char* key) {
186  nrnbbs_post_string(key, "");
187 }
188 
189 void nrnbbs_post_int(const char* key, int ival) {
190  char buf[30];
191  sprintf(buf, "%d", ival);
192  nrnbbs_post_string(key, buf);
193 }
194 
195 void nrnbbs_post_string(const char* key, const char* sval) {
196  history("post", key, sval);
197  get_lock();
198  FILE* f = fopen(fname(NRNBBS), "a");
199  fprintf(f, "%s\n%s\n", key, sval);
200  FILE* f2 = fopen(fname(NOTIFY), "r");
201  char name[256];
202  int i, n, id[10];
203  n = 0;
204  if (f2) {
205  while( fgets(name, 256, f2) && n < 10) {
206  name[strlen(name) - 1] = '\0';
207  fscanf(f2, "%d\n", &i);
208  if (strcmp(name, key) == 0) {
209  id[n++] = i;
210  fprintf(f, "nrnbbs_notifying %s\n\n", key);
211  }
212  }
213  fclose(f2);
214  }
215  fclose(f);
216  release_lock();
217  for (i=0; i < n; ++i) {
218  history(" notify", id[i]);
219  kill(id[i], NOTIFY_SIGNAL);
220  }
221 }
222 
223 
224 bool nrnbbs_take(const char* key) {
225  char buf[256];
226  return nrnbbs_take_string(key, buf);
227 }
228 
229 bool nrnbbs_take_int(const char* key, int* ipval) {
230  char buf[256];
231  bool b = nrnbbs_take_string(key, buf);
232  if (b) {
233  b = (sscanf(buf, "%d\n", ipval) == 1) ? true : false;
234  }
235  return b;
236 }
237 
238 bool nrnbbs_take_string(const char* key, char* sval) {
239  history("take", key);
240  get_lock();
241  bool b = false;
242  FILE* f = fopen(fname(NRNBBS), "r");
243  if (f != (FILE*)0) {
244  char name[256], val[256];
245  FILE* f2 = fopen(fname(TMPFILE), "w");
246  while (fgets(name, 256, f)) {
247  name[strlen(name) -1] = '\0';
248  if (name[0] == '\0') {
249  continue;
250  }
251  fgets(val, 256, f);
252  val[strlen(val) - 1] = '\0';
253  if (!b && strcmp(name, key) == 0) {
254  history(" found", val);
255  b = true;
256  strcpy(sval, val);
257  continue;
258  }
259  fprintf(f2, "%s\n%s\n", name, val);
260  }
261  fclose(f2);
262  fclose(f);
263  if (b) {
264  rename(fname(TMPFILE), fname(NRNBBS));
265  }
266  }else{
267  b = false;
268  }
269  release_lock();
270  return b;
271 }
272 
273 
274 bool nrnbbs_look(const char* key) {
275  history("look", key);
276  get_lock();
277  bool b = false;
278  FILE* f = fopen(fname(NRNBBS), "r");
279  if (f != (FILE*)0) {
280  char name[256], val[256];
281  while (fgets(name, 256, f)) {
282  name[strlen(name) - 1] = '\0';
283  fgets(val, 256, f);
284  if (strcmp(name, key) == 0) {
285  history(" found");
286  b = true;
287  break;
288  }
289  }
290  fclose(f);
291  }else{
292  b = false;
293  }
294  release_lock();
295  return b;
296 }
297 
298 
299 void nrnbbs_exec(const char* cmd) {
300  history("exec", cmd);
301  char buf[256];
302  sprintf(buf,"%s&", cmd);
303  system(buf);
304 }
305 
306 
307 static
310  long i;
311 #if defined(SIGNAL_CAST)
312  signal(NOTIFY_SIGNAL, (SIGNAL_CAST)nrnbbs_handler);
313 #else
314  signal(NOTIFY_SIGNAL, nrnbbs_handler);
315 #endif
316  for (i = 0; i < cblist_->count(); ++i) {
317  cblist_->item(i)->execute();
318  }
319 }
320 
321 void nrnbbs_notify(const char* key, NrnBBSCallback cb){
322  history("nrnbbs_notify", key);
323  if (!cblist_) {
324  cblist_ = new NrnBBSCallbackList();
325  }
326  cblist_->append(new NrnBBSCallbackItem(key, cb));
327  get_lock();
328  FILE* f = fopen(fname(NOTIFY), "a");
329  if (!f) {
330  fprintf(stderr, "can't open %s\n", fname(NOTIFY));
331  return;
332  }
333  fprintf(f, "%s\n%d\n", key, getpid());
334  fclose(f);
335  release_lock();
336 #if defined(SIGNAL_CAST)
337  signal(NOTIFY_SIGNAL, (SIGNAL_CAST)nrnbbs_handler);
338 #else
339  signal(NOTIFY_SIGNAL, nrnbbs_handler);
340 #endif
341 }
342 
344  cb_ = cb;
345  s_ = s;
346 }
347 
349 
350 bool NrnBBSCallbackItem::equal(const char* s) {
351  return (strcmp(s_.string(), s) == 0) ? true : false;
352 }
353 
355  char buf[256];
356  sprintf(buf, "nrnbbs_notifying %s", s_.string());
357  if (nrnbbs_take(buf)) {
358  (*cb_)(s_.string());
359  }
360 }
return true
Definition: savstate.cpp:357
bool nrnbbs_connect()
Definition: nrnbbs.cpp:45
#define RETSIGTYPE
Definition: nrnconf.h:5
void nrnbbs_wait(bool *pflag)
Definition: nrnbbs.cpp:175
static NrnBBSCallbackItem NrnBBSCallbackList * cblist_
Definition: nrnbbs.cpp:68
void nrnbbs_exec(const char *cmd)
Definition: nrnbbs.cpp:299
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
int system(const char *s)
Definition: mswinprt.cpp:281
bool nrnbbs_take(const char *key)
Definition: nrnbbs.cpp:224
static bool connected_
Definition: nrnbbs.cpp:116
static FILE * lockfile_
Definition: nrnbbs.cpp:69
const char * string() const
Definition: string.h:139
#define implementPtrList(PtrList, T)
void nrnbbs_post_string(const char *key, const char *sval)
Definition: nrnbbs.cpp:195
bool nrnbbs_look(const char *key)
Definition: nrnbbs.cpp:274
int const size_t const size_t n
Definition: nrngsl.h:12
_CONST char * s
Definition: system.cpp:74
NrnBBSCallbackItem(const char *, NrnBBSCallback)
Definition: nrnbbs.cpp:343
bool nrnbbs_take_int(const char *key, int *ipval)
Definition: nrnbbs.cpp:229
int val
Definition: dll.cpp:167
bool nrnbbs_take_string(const char *key, char *sval)
Definition: nrnbbs.cpp:238
#define NRNBBSTMP
Definition: nrnbbs.cpp:27
static const char * fname(const char *name)
Definition: nrnbbs.cpp:108
static void get_lock()
Definition: nrnbbs.cpp:71
NrnBBSCallback cb_
Definition: nrnbbs.cpp:42
#define key
Definition: spt2queue.cpp:20
char * getenv(const char *s)
Definition: macprt.cpp:67
void nrnbbs_post(const char *key)
Definition: nrnbbs.cpp:185
fprintf(stderr, "Don't know the location of params at %p\, pp)
#define NOTIFY_SIGNAL
Definition: nrnbbs.cpp:32
void cb(const char *s)
Definition: bbstest.cpp:5
char * name
Definition: init.cpp:16
#define nil
Definition: enter-scope.h:36
static void release_lock()
Definition: nrnbbs.cpp:82
#define TMPFILE
Definition: nrnbbs.cpp:31
void nrnbbs_disconnect()
Definition: nrnbbs.cpp:51
void(* NrnBBSCallback)(const char *)
Definition: ivocmac.cpp:23
static const char * nrnbbsdir()
Definition: nrnbbs.cpp:91
void nrnbbs_post_int(const char *key, int ival)
Definition: nrnbbs.cpp:189
static RETSIGTYPE nrnbbs_handler(int)
Definition: nrnbbs.cpp:309
bool nrnbbs_connected()
Definition: nrnbbs.cpp:170
CopyString s_
Definition: nrnbbs.cpp:41
#define i
Definition: md1redef.h:12
#define id
Definition: md1redef.h:33
static void history(const char *s1, const char *s2, const char *s3)
Definition: nrnbbs.cpp:47
#define NOTIFY
Definition: nrnbbs.cpp:28
char buf[512]
Definition: init.cpp:13
bool equal(const char *)
Definition: nrnbbs.cpp:350
#define NRNBBS
Definition: nrnbbs.cpp:29
int getpid()
Definition: mswinprt.cpp:355
FILE * fopen()
virtual ~NrnBBSCallbackItem()
Definition: nrnbbs.cpp:348
declarePtrList(NrnMessageList, NrnMessage) implementPtrList(NrnMessageList
#define LOCKFILE
Definition: nrnbbs.cpp:30
void nrnbbs_notify(const char *key, NrnBBSCallback cb)
Definition: nrnbbs.cpp:321