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