Bug Summary

File:daq/slc/nsm2/corelib/nsmlib2.c
Warning:line 492, column 10
Dereference of null pointer (loaded from variable 'q')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -O3 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsmlib2.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/data/b2soft/buildbot/development/build -fcoverage-compilation-dir=/data/b2soft/buildbot/development/build -resource-dir /cvmfs/belle.cern.ch/el9/externals/v02-04-00/Linux_x86_64/common/lib/clang/21 -isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/include -isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/Linux_x86_64/common/include/python3.12 -isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/include/CLHEP -isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/Linux_x86_64/common/include/Geant4 -isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/Linux_x86_64/common/include -isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/include/root -isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/include/belle_legacy -I include/ -D _PACKAGE_="daq" -D G4UI_USE_TCSH -D RaveDllExport= -D HAS_SQLITE -D HAS_CALLGRIND -I daq/slc/nsm2/include -I /cvmfs/belle.cern.ch/el9/externals/v02-04-00/Linux_x86_64/common/include/libxml2 -internal-isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/Linux_x86_64/common/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /cvmfs/belle.cern.ch/el9/externals/v02-04-00/Linux_x86_64/common/bin/../lib64/gcc/x86_64-redhat-linux/15.2.0/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-missing-braces -Wno-unused-command-line-argument -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /scan_build/2026-05-31-004316-385593-1 -x c daq/slc/nsm2/corelib/nsmlib2.c
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9/* ---------------------------------------------------------------------- *\
10 nsmlib2.c
11
12 NSM client library
13 core part, independent of general usage
14
15 All external library functions have prefix "nsmlib_".
16
17 20131216 1912 sa_flags fix (work works with gcc 4.1.2)
18 20131230 1918 strerror fix, initnet fix, stdint fix, bridge fix
19 20140104 1919 strerror rearranged
20 20140105 1921 fix for incorrect errc in register_request
21 20140108 1922 initcli error message fix
22 20140124 1925 anonymous node
23 20140304 1926 abort when new revision data is started elsewhere
24 20140305 1929 maxrecursive and checkpoints, no fprintf
25 20140306 1930 logfp again, but write instead of fwrite/fprintf
26 20140516 1931 ip address from shm if not specified
27 20140614 1932 sprintf ip address if host is missing
28 20140614 1933 use nodhash for nsmlib_nodeid
29 20140902 1935 memset fix
30 20140903 1937 nsmparse fix (see nsmparse.c)
31 20140917 1939 skip revision check for -1
32 20140921 1940 flushmem
33 20180709 1974 free unused parse results, memory leak fix in nsm_init2
34 20180802 1977 free pipe in nsmlib_shutdown
35 20180913 1990 error message update for unknown reqid
36 20181126 1994 nsmlib_nodeproc is added
37 20190415 1994 add: nsmc->errno
38 20190419 1994 add: NSMENODEST on send error
39 20190529 1994 fix: nsmlib_nodeid/proc null sysp handling
40 20190725 1997 add: library version at init / in shm
41 20190909 1999 fix: unnecessary printf
42 20190913 1999 nsmlib_logging returns previous value
43 20190918 1999 mod: nsmlib_call log message for unregistered request
44 20191002 1999 mod: nsmsys2.h is no more included in nsmlib2.h
45 20200123 1999 mod: error code for read/write timeout
46 20200423 2003 mod: implement read(init)/write timeout
47 20200423 2003 mod: 1 second penalty when sending non-existing req
48 20200603 2006 fix: nnod in ntohs
49 20210315 2007 fix: nsmlib_parsefree fix for nsmlib_allocmem
50 20220425 2008 fix: uint16_t to int conversion fix for nnod
51\* ---------------------------------------------------------------------- */
52
53const char *nsmlib2_version = "nsmlib2 2.0.08";
54
55/* -- includes -- */
56#include <stdio.h>
57#include <stdlib.h>
58#include <stdint.h>
59#include <stdarg.h>
60#include <unistd.h>
61#include <string.h>
62#include <ctype.h>
63#include <signal.h>
64#include <errno(*__errno_location ()).h>
65#include <netdb.h> /* for struct hostent */
66#include <net/if.h> /* for struct ifconf, ifreq */
67#include <sys/socket.h> /* for ntoha etc */
68#include <netinet/in.h> /* for ntoha etc */
69#include <arpa/inet.h> /* for ntoha etc */
70#include <sys/types.h>
71#include <sys/time.h>
72#include <sys/ioctl.h>
73#include <sys/select.h>
74#include <sys/stat.h>
75#include <sys/shm.h>
76
77#include "nsm2/nsm2.h"
78#include "nsm2/nsmsys2.h"
79#include "nsm2/nsmlib2.h"
80#include "nsm2/nsmparse.h"
81
82/* -- default constants -- */
83#define NSM2_PORT8120 8120 /* chosen as it corresponds to 0x2012
84 (2012 is the year started writing NSM2) */
85#define NSMENV_HOST"NSM2_HOST" "NSM2_HOST"
86#define NSMENV_PORT"NSM2_PORT" "NSM2_PORT"
87#define NSMENV_SHMKEY"NSM2_SHMKEY" "NSM2_SHMKEY"
88
89#define NSMLIB_MAXRECURSIVE256 256 /* default value */
90
91/* -- global variables -- */
92static NSMcontext *nsmlib_context = 0; /* top of the chain */
93static FILE *nsmlib_logfp = 0;
94static int nsmlib_loglen = 0;
95static char nsmlib_logbuf[4096];
96static char *nsmlib_incpath = 0;
97static char nsmlib_errs[1024]; /* error string in case of NSMEUNEXPECTED */
98static int nsmlib_errc = 0; /* context independent error code */
99static int nsmlib_port = 0; /* error port without context */
100
101static int nsmlib_debugflag = 0; /* context independent error code */
102static sigset_t nsmlib_sigmask;
103static int nsmlib_sig;
104
105static int nsmlib_maxrecursive;
106int nsmlib_currecursive;
107static int *nsmlib_checkpoints;
108static int nsmlib_nskipped;
109static NSMtcphead nsmlib_lastskipped;
110/* static int nsmlib_alloccnt = 0; /* (2018.0709.0934 memory leak search) */
111
112typedef struct NSMrecvqueue_struct {
113 struct NSMrecvqueue_struct *next;
114 NSMtcphead h;
115} NSMrecvqueue;
116
117/* -- macros -- */
118#define ADDR_N(a)((uint32_t)((a).sin_addr.s_addr)) ((uint32_t)((a).sin_addr.s_addr))
119#define LOGEND(nsmlib_logbuf + nsmlib_loglen) (nsmlib_logbuf + nsmlib_loglen)
120#define LOGCLRnsmlib_loglen = 0 nsmlib_loglen = 0
121#define LOGSIZ(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1) (sizeof(nsmlib_logbuf) - nsmlib_loglen - 1)
122#define LOGFWDnsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen)) nsmlib_loglen += strlen(LOGEND(nsmlib_logbuf + nsmlib_loglen))
123#define LOGCAT(s)strcpy((nsmlib_logbuf + nsmlib_loglen), s); nsmlib_loglen += strlen
((nsmlib_logbuf + nsmlib_loglen))
strcpy(LOGEND(nsmlib_logbuf + nsmlib_loglen), s); LOGFWDnsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen))
124
125#define VSNPRINTF(buf,s,f,ap)__builtin_va_start(ap, f);vsnprintf(buf,s,f,ap);__builtin_va_end
(ap)
va_start(ap,f)__builtin_va_start(ap, f);vsnprintf(buf,s,f,ap);va_end(ap)__builtin_va_end(ap)
126#define SOCKOPT(s,o,v)setsockopt(s,1,o,(char *)&(v),sizeof(v)) setsockopt(s,SOL_SOCKET1,o,(char *)&(v),sizeof(v))
127
128#define MEMPOS(base,ptr)((char *)(ptr) - (char *)(base)) ((char *)(ptr) - (char *)(base))
129#define MEMPTR(base,off)((char *)(base) + off) ((char *)(base) + off)
130
131#define ASSERTnsmlib_assert nsmlib_assert
132#define ERRORnsmlib_error nsmlib_error
133#define DBGnsmlib_debug nsmlib_debug
134#define LOGnsmlib_lognl nsmlib_lognl
135
136/* checkpoint of signal handler to be studied with gdb
137 0: never called, -1: done, 1..1000 user checkpoint, 1001.. corelib/b2lib
138 */
139#define DBS(nsmc,val)nsmlib_checkpoints[nsmlib_currecursive] = (val) nsmlib_checkpoints[nsmlib_currecursive] = (val)
140
141/* -- extern functions -- */
142/* implemented in nsmhash.c */
143int nsmlib_hash(NSMsys *, int32_t *hashtable, int hashmax,
144 const char *key, int create);
145
146
147/* -- free ------------------------------------------------------------ */
148static void
149nsmlib_free(void *ptr)
150{
151 if (! ptr) {
152 printf("nsmlib_free: freeing null pointer\n");
153 exit(1);
154 }
155 int32_t siz = *(int32_t *)((char *)ptr - 4);
156 if (siz == 0) {
157 printf("nsmlib_free: possible double free attempt\n");
158 exit(1);
159 }
160
161 /* -- 2018.0709.0435 memory leak search
162 nsmlib_alloccnt--;
163 {
164 static int callcnt = 0;
165 callcnt++;
166 if (callcnt < 20) {
167 printf("nsmlib_free siz=%d\n", siz);
168 }
169 }
170 */
171
172 *(int32_t *)((char *)ptr - 4) = 0;
173 free((char *)ptr-4);
174}
175/* -- malloc ---------------------------------------------------------- */
176static void *
177nsmlib_malloc(size_t siz, const char *where, const char *text)
178{
179 char *p = (char *)malloc(siz+4);
180 if (! p) {
181 printf("nsmlib_malloc: can't malloc %d bytes%s%s%s%s\n",
182 (int)siz,
183 where ? " in " : "", where ? where : "",
184 text ? ": " : "", text ? text : "");
185 exit(1);
186 }
187 memset(p, 0, siz+4);
188
189 /* -- 2018.0709.0936 memory leak search
190 {
191 static int callcnt = 0;
192 nsmlib_alloccnt++;
193 callcnt++;
194 if (callcnt < 20) {
195 printf("nsmlib_malloc where=%s text=%s\n",
196 where ? where : "(nowhere?)",
197 text ? text : "(notext)");
198 }
199 if ((callcnt % 100) == 0) {
200 printf("nsmlib_malloc +%d / %d\n", nsmlib_alloccnt, callcnt);
201 }
202 }
203 */
204
205 *(int32_t *)p = (int32_t)siz;
206 return p+4;
207}
208/* -- time1ms -------------------------------------------------------- */
209static uint64
210time1ms()
211{
212 struct timeval tv;
213 gettimeofday(&tv, 0);
214 return (uint64)tv.tv_sec * 1000 + tv.tv_usec / 1000; /* in 1msec unit */
215}
216/* -- htonll --------------------------------------------------------- */
217static uint64
218htonll(uint64 h)
219{
220 static int n42 = 0;
221 if (n42 == 0) n42 = htons(42)__bswap_16 (42); /* 42 is the answer */
222 if (n42 == 42) {
223 return h;
224 } else {
225 uint64 n;
226 int32_t *hp = (int32_t *)&h;
227 int32_t *np = (int32_t *)&n;
228 np[0] = htonl(hp[1])__bswap_32 (hp[1]);
229 np[1] = htonl(hp[0])__bswap_32 (hp[0]);
230 return n;
231 }
232}
233/* -- nsmlib_logflush ------------------------------------------------ */
234void
235nsmlib_logflush()
236{
237 /*
238 (fwrite version does not properly work at 1.9.30)
239 fwrite(nsmlib_logbuf, nsmlib_loglen, 1, nsmlib_logfp);
240 fflush(nsmlib_logfp);
241 */
242 if (nsmlib_loglen) {
243 write(fileno(nsmlib_logfp), nsmlib_logbuf, nsmlib_loglen);
244 LOGCLRnsmlib_loglen = 0;
245 }
246}
247/* -- nsmlib_assert -------------------------------------------------- */
248static void
249nsmlib_assert(const char *fmt, ...)
250{
251 va_list ap;
252 if (! nsmlib_logfp) return;
253
254 if (LOGSIZ(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1) < 256) {
255 LOGCLRnsmlib_loglen = 0;
256 LOGCAT("(output buffer shrinked)\n")strcpy((nsmlib_logbuf + nsmlib_loglen), "(output buffer shrinked)\n"
); nsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen))
;
257 }
258
259 LOGCAT("ASSERT: ")strcpy((nsmlib_logbuf + nsmlib_loglen), "ASSERT: "); nsmlib_loglen
+= strlen((nsmlib_logbuf + nsmlib_loglen))
;
260 VSNPRINTF(LOGEND, LOGSIZ, fmt, ap)__builtin_va_start(ap, fmt);vsnprintf((nsmlib_logbuf + nsmlib_loglen
),(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1),fmt,ap);__builtin_va_end
(ap)
;
261 LOGFWDnsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen));
262 LOGCAT("\n")strcpy((nsmlib_logbuf + nsmlib_loglen), "\n"); nsmlib_loglen +=
strlen((nsmlib_logbuf + nsmlib_loglen))
;
263 nsmlib_logflush();
264 exit(1);
265}
266/* -- nsmlib_error --------------------------------------------------- */
267static void
268nsmlib_error(const char *fmt, ...)
269{
270 va_list ap;
271
272 if (! nsmlib_logfp) return;
273
274 if (LOGSIZ(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1) < 256) {
275 LOGCLRnsmlib_loglen = 0;
276 LOGCAT("(output buffer shrinked)\n")strcpy((nsmlib_logbuf + nsmlib_loglen), "(output buffer shrinked)\n"
); nsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen))
;
277 }
278
279 LOGCAT("ERROR: ")strcpy((nsmlib_logbuf + nsmlib_loglen), "ERROR: "); nsmlib_loglen
+= strlen((nsmlib_logbuf + nsmlib_loglen))
;
280 VSNPRINTF(LOGEND, LOGSIZ, fmt, ap)__builtin_va_start(ap, fmt);vsnprintf((nsmlib_logbuf + nsmlib_loglen
),(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1),fmt,ap);__builtin_va_end
(ap)
;
281 LOGFWDnsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen));
282 LOGCAT("\n")strcpy((nsmlib_logbuf + nsmlib_loglen), "\n"); nsmlib_loglen +=
strlen((nsmlib_logbuf + nsmlib_loglen))
;
283 nsmlib_logflush();
284}
285/* -- nsmlib_debuglevel ---------------------------------------------- */
286int
287nsmlib_debuglevel(int val)
288{
289 int prev = nsmlib_debugflag;
290 nsmlib_debugflag = val;
291 return prev;
292}
293/* -- nsmlib_debug --------------------------------------------------- */
294static void
295nsmlib_debug(const char *fmt, ...)
296{
297 va_list ap;
298 if (! nsmlib_logfp) return;
299 if (! nsmlib_debugflag) return;
300
301 if (LOGSIZ(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1) > 256) {
302 LOGCAT("[DBG] ")strcpy((nsmlib_logbuf + nsmlib_loglen), "[DBG] "); nsmlib_loglen
+= strlen((nsmlib_logbuf + nsmlib_loglen))
;
303 VSNPRINTF(LOGEND, LOGSIZ, fmt, ap)__builtin_va_start(ap, fmt);vsnprintf((nsmlib_logbuf + nsmlib_loglen
),(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1),fmt,ap);__builtin_va_end
(ap)
;
304 LOGFWDnsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen));
305 LOGCAT("\n")strcpy((nsmlib_logbuf + nsmlib_loglen), "\n"); nsmlib_loglen +=
strlen((nsmlib_logbuf + nsmlib_loglen))
;
306 }
307}
308/* -- nsmlib_lognl --------------------------------------------------- */
309void
310nsmlib_lognl(const char *fmt, ...)
311{
312 va_list ap;
313 if (! nsmlib_logfp) return;
314 if (LOGSIZ(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1) > 256) {
315 VSNPRINTF(LOGEND, LOGSIZ, fmt, ap)__builtin_va_start(ap, fmt);vsnprintf((nsmlib_logbuf + nsmlib_loglen
),(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1),fmt,ap);__builtin_va_end
(ap)
;
316 LOGFWDnsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen));
317 LOGCAT("\n")strcpy((nsmlib_logbuf + nsmlib_loglen), "\n"); nsmlib_loglen +=
strlen((nsmlib_logbuf + nsmlib_loglen))
;
318 }
319}
320/* -- nsmlib_log ----------------------------------------------------- */
321void
322nsmlib_log(const char *fmt, ...)
323{
324 va_list ap;
325 if (! nsmlib_logfp) return;
326 if (LOGSIZ(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1) > 256) {
327 VSNPRINTF(LOGEND, LOGSIZ, fmt, ap)__builtin_va_start(ap, fmt);vsnprintf((nsmlib_logbuf + nsmlib_loglen
),(sizeof(nsmlib_logbuf) - nsmlib_loglen - 1),fmt,ap);__builtin_va_end
(ap)
;
328 LOGFWDnsmlib_loglen += strlen((nsmlib_logbuf + nsmlib_loglen));
329 }
330}
331/* -- nsmlib_logging ------------------------------------------------- */
332FILE *
333nsmlib_logging(FILE *logfp)
334{
335 FILE *prevfp = nsmlib_logfp;
336 nsmlib_logfp = logfp;
337 return prevfp;
338}
339
340/* -- nsmlib_checkpoint ---------------------------------------------- *\
341 for user function, between 1 and 999 (outside range becomes 1000)
342\* ------------------------------------------------------------------- */
343void
344nsmlib_checkpoint(NSMcontext *nsm, int val)
345{
346 DBS(nsm, val)nsmlib_checkpoints[nsmlib_currecursive] = (val);
347}
348/* -- nsmlib_strerror ------------------------------------------------ */
349const char *
350nsmlib_strerror(NSMcontext *nsmc)
351{
352 static char buf[256];
353 char *syserr = 0;
354 int errc = nsmc ? nsmc->errc : nsmlib_errc;
355 const char *errs = nsmc ? nsmc->errs : nsmlib_errs;
356 int errn = nsmc ? nsmc->errn : errno(*__errno_location ());
357 int shmkey = nsmc ? nsmc->shmkey : nsmlib_port;
358
359 switch (errc) {
360 case NSMENOERR(0): return nsmc ? "no error" : "NSM is not initialized";
361 case NSMEALLOC(-101): syserr = "malloc"; break;
362 case NSMESOCKET(-102): syserr = "socket"; break;
363 case NSMESOCKDGRAM(-103): syserr = "socket(sock_dgram)"; break;
364 case NSMEGIFCONF(-104): syserr = "ioctl(SIOCGIFCONF)"; break;
365 case NSMEGIFFLAGS(-105): syserr = "ioctl(SIOCGIFFLAGS)"; break;
366 case NSMESOCKREUSE(-106): syserr = "so_sockreuse"; break;
367 case NSMESOCKSNDBUF(-107): syserr = "so_sndbuf"; break;
368 case NSMESOCKRCVBUF(-108): syserr = "so_rcvbuf"; break;
369 case NSMERDSELECT(-109): syserr = "select(read)"; break;
370 case NSMERDUID(-110): syserr = "uid read error"; break;
371 case NSMENOPIPE(-111): syserr = "pipe"; break;
372 case NSMESELECT(-112): syserr = "select"; break;
373 case NSMETIMEOUT(-113): return "select timeout"; /* until 1998 */
374 case NSMETIMEOUTW(-41): return "timeout in sending to nsmd2";
375 case NSMETIMEOUTR(-42): return "timeout in receiving from nsmd2";
376 case NSMEWRITE(-114): syserr = "write(socket)"; break;
377 case NSMEUNEXPECTED(-119): return errs;
378 case NSMECLOSED(-115): return "NSMD connection closed";
379 case NSMEPIPEREAD(-116): syserr = "read(pipe)"; break;
380 case NSMEPIPEWRITE(-117): syserr = "write(pipe)"; break;
381 case NSMEDATID(-118): return errs;
382 /* possible errors by user parameters */
383 case NSMENOMASTER(-1): return "no master nsmd2";
384 case NSMENGMASTER(-40): return "master nsmd2 temporarily unreachable";
385 case NSMEINVNAME(-2): return "invalid name"; /* from nsmd2, shouldn't happen */
386 case NSMEINVPAR(-3): return "invalid parameter";
387 case NSMENODEEXIST(-4): return errs; /* "node already exist" from nsmd2 */
388 case NSMENODEHERE(-45): return errs; /* "node already exist here" from nsmd2 */
389 case NSMEFULNODE(-5): return errs; /* "no more NSM node" from nsmd2 */
390 case NSMENODEST(-6): return "destination node does not exist";
391 case NSMEINVFMT(-7): return "invalid data format"; /* from nsmd2 */
392 case NSMEMEMEXIST(-8): return "data alraedy exists"; /* why unused? */
393 case NSMENOMOREMEM(-9): return "no more data area"; /* why unused? */
394 case NSMEOPENED(-10): return "already opened"; /* from nsmd2 */
395 case NSMENODENAME(-11): return "invalid node name";
396 case NSMENODELONG(-12): return "node name too long"; /* why unused? */
397 case NSMEHOSTNAME(-13): return "invalid hostname";
398 case NSMEALREADYP(-14): return "host:port already in use";
399 case NSMEALREADYS(-15): return "shm key already in use";
400 case NSMEALREADYH(-16): return "host:port already in use"; /* deprecated */
401 case NSMENOIF(-17): return "network interface not found";
402 case NSMENONSMD(-18): return "orphan shared memory with no nsmd2 running";
403 case NSMECONNECT(-35): syserr = "cannot connect to nsmd2"; break;
404 case NSMENOUID(-19): return "uid not received";
405 /* case NSMERDCLOSE: return "uid not fully received"; */
406 case NSMERDCLOSE(-20): return "cannot communicate with nsmd2";
407 case NSMEACCESS(-21): return "nsmd2 is running under different uid";
408 case NSMESHMNOSYS(-37):
409 sprintf(buf, "no shared memory with port/shmkey=%d", shmkey);
410 return buf;
411 case NSMESHMGETSYS(-22): syserr = "cannot open NSMsys shared memory"; break;
412 case NSMESHMACCES(-38):
413 return "nsmd2 shared memory must have either the same uid or gid";
414 case NSMESHMGETMEM(-24):
415 syserr = "cannot open NSMmem shared memory"; break;
416 case NSMESHMATSYS(-23): syserr = "shmat(NSMsys)"; break;
417 case NSMESHMATMEM(-25): syserr = "shmat(NSMmem)"; break;
418 case NSMENOINIT(-26): return "NSM2 is not initialized yet";
419 case NSMEPERM(-27): return "operation not allowed for anonymous node";
420 case NSMEINVDATA(-28): return "invalid send data parameter";
421 case NSMEINVFUNC(-29): return "invalid callback function type";
422 case NSMEMAXFUNC(-30): return "no more callback functions";
423 case NSMENOMEM(-31): return errs; /* openmem */
424 case NSMEBADFMT(-32): return errs; /* openmem */
425 case NSMEBADREV(-33): return errs; /* openmem/allocmem */
426 case NSMEPARSE(-34): return errs; /* openmem/allocmem */
427 case NSMEINVPTR(-36): return "invalid pointer";
428 case NSMEEMPTYDEST(-39): return "empty destination";
429 case NSMENOSUCHREQ(-43): return "no such registered request";
430 case NSMEBADHASH(-44): return "broken internal hash";
431
432 default:
433 if (*errs) return errs;
434 if (! nsmc) {
435 sprintf(buf, "NSM is not initialized (errcode=%d)", errc);
436 } else {
437 sprintf(buf, "undefined error code (errcode=%d)", errc);
438 }
439 return buf;
440 }
441
442 if (syserr) {
443 sprintf(buf, "%s: %s", syserr, strerror(errn));
444 }
445 return buf;
446}
447/* -- nsmlib_atoi ---------------------------------------------------- */
448static int
449nsmlib_atoi(const char *a, int def)
450{
451 if (! a || ! *a) return def;
452 if (! (isdigit(*a)((*__ctype_b_loc ())[(int) ((*a))] & (unsigned short int)
_ISdigit)
|| (*a == '-' && isdigit(*(a+1))((*__ctype_b_loc ())[(int) ((*(a+1)))] & (unsigned short int
) _ISdigit)
))) {
453 return def;
454 } else {
455 return (int)strtol(a,0,0);
456 }
457}
458
459/* -- nsmlib_addincpath ---------------------------------------------- */
460int
461nsmlib_addincpath(const char *path)
462{
463 if (! path) {
1
Assuming 'path' is non-null
2
Taking false branch
464 if (nsmlib_incpath) nsmlib_free(nsmlib_incpath);
465 nsmlib_incpath = 0;
466 return 0;
467 } else {
468 /*
469 If "path" is not a directory, take the string up to the last '/'.
470 This is the way to easily add the path of the program, by
471 nsmlib_addincpath(argv[0])
472 */
473 const char *p;
474 int len = nsmlib_incpath ? strlen(nsmlib_incpath) + 1 : 0;
3
Assuming 'nsmlib_incpath' is null
4
'?' condition is false
475 struct stat statbuf;
476 while (stat(path, &statbuf) < 0) {
5
Loop condition is false. Execution continues on line 480
477 if (errno(*__errno_location ()) != EINTR4) return -1;
478 }
479
480 if (S_ISDIR(statbuf.st_mode)((((statbuf.st_mode)) & 0170000) == (0040000))) {
6
Assuming the condition is true
7
Taking true branch
481 len += strlen(path) + 1;
482 p = path + len;
483 } else {
484 if (! (p = strrchr(path, '/'))) return -1;
485 len += (p - path) + 1;
486 }
487 char *q = (char *)nsmlib_malloc(len, "incpath", path);
8
'q' initialized here
488 if (! q) ASSERTnsmlib_assert("nsmlib_addincpath can't malloc %d byte", len);
9
Assuming 'q' is null
10
Taking true branch
489 if (nsmlib_incpath) {
11
Assuming 'nsmlib_incpath' is null
12
Taking false branch
490 sprintf(q, "%s:", nsmlib_incpath);
491 } else {
492 *q = 0;
13
Dereference of null pointer (loaded from variable 'q')
493 }
494 strncat(q, path, p - path);
495 q[len-1] = 0;
496 if (nsmlib_incpath) nsmlib_free(nsmlib_incpath);
497 nsmlib_incpath = q;
498 }
499}
500
501/* -- nsmlib_nodename ------------------------------------------------ */
502const char *
503nsmlib_nodename(NSMcontext *nsmc, int nodeid)
504{
505 int i;
506 NSMsys *sysp;
507 const char *namep;
508 if (! nsmc || ! (sysp = nsmc->sysp)) return 0;
509
510 if (nodeid == NSMSYS_MAX_NOD1024) return "(no-name)";
511 if (nodeid < 0 || nodeid > NSMSYS_MAX_NOD1024) return "(invalid)";
512 namep = sysp->nod[nodeid].name;
513 if (! namep[0]) return 0;
514 for (i=0; i <= NSMSYS_NAME_SIZ31; i++) {
515 if (namep[i] == 0) break;
516 if (! isalnum(namep[i])((*__ctype_b_loc ())[(int) ((namep[i]))] & (unsigned short
int) _ISalnum)
&& namep[i] != '_') return "(broken)";
517 }
518 if (i > NSMSYS_NAME_SIZ31) return "(broken)";
519 return namep;
520}
521
522/* -- nsmlib_nodeid -------------------------------------------------- */
523int
524nsmlib_nodeid(NSMcontext *nsmc, const char *nodename)
525{
526 int i;
527 NSMsys *sysp;
528 const char *namep;
529 int hash;
530 NSMnod *nodp;
531
532 if (! nsmc || ! (sysp = nsmc->sysp)) return -1;
533 if (! nodename || ! *nodename || *nodename == '(') return -1;
534
535 hash = nsmlib_hash(sysp, sysp->nodhash, NSMSYS_MAX_HASH2039, nodename, 0);
536 if (hash < 0) return -1;
537
538 nodp = (NSMnod *)MEMPTR(sysp, ntohl(sysp->nodhash[hash]))((char *)(sysp) + __bswap_32 (sysp->nodhash[hash]));
539 return (int)(nodp - sysp->nod);
540}
541
542/* -- nsmlib_nodepid ------------------------------------------------- */
543int
544nsmlib_nodepid(NSMcontext *nsmc, const char *nodename)
545{
546 int inod = nsmlib_nodeid(nsmc, nodename);
547 if (inod < 0) return -1;
548 return ntohl(nsmc->sysp->nod[inod].nodpid)__bswap_32 (nsmc->sysp->nod[inod].nodpid);
549}
550
551/* -- nsmlib_nodeproc ------------------------------------------------ */
552/*
553 ipaddress for a remote node, or nodepid for a local node.
554 (local if the return value < NSMSYS_MAX_NOD, assuming no ip address
555 0.0.0.0/22 is used)
556*/
557int
558nsmlib_nodeproc(NSMcontext *nsmc, const char *nodename)
559{
560 int i;
561 NSMsys *sysp;
562 if (! nsmc || ! (sysp = nsmc->sysp)) return -1;
563
564 int nodeid = nsmlib_nodeid(nsmc, nodename);
565 if (nodeid < 0) return nodeid;
566
567 if (sysp->nod[nodeid].ipaddr == -1) return 0;
568 if (sysp->nod[nodeid].ipaddr != sysp->ipaddr)
569 return sysp->nod[nodeid].ipaddr;
570
571 if (sysp->nod[nodeid].nodpid == -1) return 0;
572 return ntohl(sysp->nod[nodeid].nodpid)__bswap_32 (sysp->nod[nodeid].nodpid);
573}
574
575/* -- nsmlib_checkif ------------------------------------------------- */
576/*
577 Check the ethernet interface and determine the IP address to use.
578*/
579static int
580nsmlib_checkif(NSMcontext *nsmc, SOCKAD_IN *sap)
581{
582 int sock; // use only inside this function, close before return
583 struct ifconf ifc;
584 struct ifreq *ifr;
585 char buf[4096];
586 int ifrgap;
587
588 /* -- open socket -- */
589 if ((sock = socket(AF_INET2, SOCK_DGRAMSOCK_DGRAM, 0)) < 0) {
590 ERRORnsmlib_error("nsmlib_checkif: socket");
591 nsmc->errn = errno(*__errno_location ());
592 return NSMESOCKDGRAM(-103);
593 }
594
595 /* -- broadcast address (only for the first, except localhost) -- */
596 memset(buf, 0, sizeof(buf));
597 ifc.ifc_len = sizeof(buf);
598 ifc.ifc_bufifc_ifcu.ifcu_buf = buf;
599 if (ioctl(sock, SIOCGIFCONF0x8912, (char *)&ifc) < 0) {
600 ERRORnsmlib_error("nsmlib_checkif: ioctl getconf");
601 nsmc->errn = errno(*__errno_location ());
602 close(sock);
603 return NSMEGIFCONF(-104);
604 }
605
606 for (ifr = ifc.ifc_reqifc_ifcu.ifcu_req;
607 (char *)ifr < (char *)ifc.ifc_reqifc_ifcu.ifcu_req + ifc.ifc_len;
608 ifr = (struct ifreq *)((char *)ifr + ifrgap)) {
609
610#if defined(__FreeBSD__) || defined(MVME5100)
611 /* This ugly code is taken from bind 4.8.x for FreeBSD */
612 /* VxWorks on MVME5100 requires this, too */
613#define xxx_max(a,b) ((a)>(b)?(a):(b))
614#define xxx_size(p) xxx_max((p).sa_len,sizeof(p))
615 ifrgap = sizeof(ifr->ifr_nameifr_ifrn.ifrn_name) + xxx_size(ifr->ifr_addrifr_ifru.ifru_addr);
616#else
617 ifrgap = sizeof(*ifr);
618#endif
619
620 if (! ifr->ifr_nameifr_ifrn.ifrn_name[0]) break;
621 DBGnsmlib_debug("nsmlib_checkif: checking interface <%s>", ifr->ifr_nameifr_ifrn.ifrn_name);
622
623 if (ioctl(sock, SIOCGIFFLAGS0x8913, (char *)ifr) < 0) {
624 ERRORnsmlib_error("nsmlib_checkif: ioctl getflags");
625 nsmc->errn = errno(*__errno_location ());
626 close(sock);
627 return NSMEGIFFLAGS(-105);
628
629 } else if ((ifr->ifr_flagsifr_ifru.ifru_flags & IFF_UPIFF_UP) == 0) {
630 DBGnsmlib_debug("nsmlib_checkif: interface <%s> is down", ifr->ifr_nameifr_ifrn.ifrn_name);
631
632 } else if ((ifr->ifr_flagsifr_ifru.ifru_flags & IFF_BROADCASTIFF_BROADCAST) == 0 &&
633 (ifr->ifr_flagsifr_ifru.ifru_flags & IFF_LOOPBACKIFF_LOOPBACK) == 0) {
634 DBGnsmlib_debug("nsmlib_checkif: interface <%s> does not support broadcast",
635 ifr->ifr_nameifr_ifrn.ifrn_name);
636
637 } else if (ioctl(sock, SIOCGIFADDR0x8915, (char *)ifr) < 0) {
638 DBGnsmlib_debug("nsmlib_checkif: interface <%s> has no address", ifr->ifr_nameifr_ifrn.ifrn_name);
639
640 } else {
641 SOCKAD_IN sa;
642 memcpy(&sa, (SOCKAD_IN *)&ifr->ifr_addrifr_ifru.ifru_addr, sizeof(sa));
643
644 if (sa.sin_addr.s_addr != sap->sin_addr.s_addr) {
645 DBGnsmlib_debug("nsmlib_checkif: address does not match for interface <%s>",
646 ifr->ifr_nameifr_ifrn.ifrn_name);
647 } else {
648 close(sock);
649 return 0;
650 }
651 }
652 }
653
654 DBGnsmlib_debug("nsmlib_checkif: cannot find network interface for %s",
655 inet_ntoa(sap->sin_addr));
656
657 close(sock);
658 return NSMENOIF(-17);
659}
660/* -- nsmlib_initnet ------------------------------------------------- */
661/*
662 since nsm-1931 second argument is unused.
663 */
664int
665nsmlib_initnet(NSMcontext *nsmc, const char *unused, int port)
666{
667 struct hostent *hp;
668 NSMcontext *nsmcp;
669 int ret;
670 int TRUE = 1;
671 int size = NSM_TCPBUFSIZ(256*4 + 65536);
672 uid_t nsmd_euid;
673 fd_set fdset;
674 struct timeval tv;
675
676 /* -- check process -- */
677 if (kill(nsmc->sysp->pid, 0) < 0 && errno(*__errno_location ()) == ESRCH3) {
678 return NSMENONSMD(-18);
679 }
680
681 /* -- port and host -- */
682 memset(nsmc->hostname, 0, sizeof(nsmc->hostname));
683 memset(&nsmc->sa, 0, sizeof(nsmc->sa));
684
685 memcpy(&nsmc->sa.sin_addr, &nsmc->sysp->ipaddr, 4);
686 hp = gethostbyaddr(&nsmc->sa.sin_addr, 4, AF_INET2);
687 if (hp) {
688 strcpy(nsmc->hostname, hp->h_name);
689 } else {
690 sprintf(nsmc->hostname, "%d.%d.%d.%d",
691 ((const char *)&nsmc->sysp->ipaddr)[0],
692 ((const char *)&nsmc->sysp->ipaddr)[1],
693 ((const char *)&nsmc->sysp->ipaddr)[2],
694 ((const char *)&nsmc->sysp->ipaddr)[3]);
695 }
696
697 nsmc->sa.sin_family = AF_INET2;
698 nsmc->sa.sin_port = htons((short)nsmc->port)__bswap_16 ((short)nsmc->port);
699
700 /* -- check if this port is already used -- */
701 for (nsmcp = nsmlib_context; nsmcp; nsmcp = nsmcp->next) {
702 if (nsmc == nsmcp) continue;
703 if (nsmc->shmkey == nsmcp->shmkey) return NSMEALREADYS(-15);
704 if (nsmc->port == nsmcp->port &&
705 ADDR_N(nsmc->sa)((uint32_t)((nsmc->sa).sin_addr.s_addr)) == ADDR_N(nsmcp->sa)((uint32_t)((nsmcp->sa).sin_addr.s_addr))) return NSMEALREADYP(-14);
706 }
707
708 /* -- open a socket -- */
709 if ((nsmc->sock = socket(AF_INET2, SOCK_STREAMSOCK_STREAM, 0)) < 0) return NSMESOCKET(-102);
710
711 /* -- check interface -- */
712 if ((ret = nsmlib_checkif(nsmc, &nsmc->sa)) < 0) return ret;
713
714 /* -- socket options -- */
715 if (SOCKOPT(nsmc->sock, SO_REUSEADDR, TRUE)setsockopt(nsmc->sock,1,2,(char *)&(TRUE),sizeof(TRUE)
)
< 0) {
716 nsmc->errn = errno(*__errno_location ());
717 return NSMESOCKREUSE(-106);
718 }
719 if (SOCKOPT(nsmc->sock, SO_SNDBUF, size)setsockopt(nsmc->sock,1,7,(char *)&(size),sizeof(size)
)
< 0) {
720 nsmc->errn = errno(*__errno_location ());
721 return NSMESOCKSNDBUF(-107);
722 }
723 if (SOCKOPT(nsmc->sock, SO_RCVBUF, size)setsockopt(nsmc->sock,1,8,(char *)&(size),sizeof(size)
)
< 0) {
724 nsmc->errn = errno(*__errno_location ());
725 return NSMESOCKRCVBUF(-108);
726 }
727
728 /* -- connect -- */
729 if (connect(nsmc->sock, (SOCKAD *)&nsmc->sa, sizeof(nsmc->sa)) < 0) {
730 nsmc->errn = errno(*__errno_location ());
731 return NSMECONNECT(-35);
732 }
733
734 /* -- should receive 4 bytes -- */
735 FD_ZERO(&fdset)do { unsigned int __i; fd_set *__arr = (&fdset); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
736 FD_SET(nsmc->sock, &fdset)((void) (((&fdset)->__fds_bits)[((nsmc->sock) / (8 *
(int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((
nsmc->sock) % (8 * (int) sizeof (__fd_mask)))))))
;
737 tv.tv_sec = 5;
738 tv.tv_usec = 0;
739 while (1) {
740 ret = select(nsmc->sock+1, &fdset, 0, 0, &tv);
741 if (ret < 0 && errno(*__errno_location ()) == EINTR4) continue;
742 if (ret < 0) {
743 nsmc->errn = errno(*__errno_location ());
744 return NSMERDSELECT(-109);
745 }
746 if (ret == 0) return NSMENOUID(-19);
747 break;
748 }
749
750 /* -- check whether the nsmd belongs to the same uid -- */
751 while (1) {
752 ret = read(nsmc->sock, &nsmd_euid, sizeof(nsmd_euid));
753 if (ret < 0 && errno(*__errno_location ()) == EINTR4) continue;
754 if (ret < 0) {
755 nsmc->errn = errno(*__errno_location ());
756 return NSMERDUID(-110);
757 }
758 if (ret < sizeof(nsmd_euid)) return NSMERDCLOSE(-20);
759 break;
760 }
761
762 if (nsmd_euid != 0 && nsmd_euid != getuid())
763 return NSMEACCESS(-21);
764
765 nsmc->initnet_done = 1;
766
767 return 0;
768}
769/* -- nsmlib_initshm ------------------------------------------------- */
770/*
771 initshm has to be called before initnet
772 */
773int
774nsmlib_initshm(NSMcontext *nsmc, int shmkey, int port)
775{
776 /* -- initshm is called before inetnet --*/
777 nsmc->port = port;
778
779 /* -- environment variables for shmkey -- */
780 if (! shmkey) shmkey = nsmlib_atoi(getenv(NSMENV_SHMKEY"NSM2_SHMKEY"), port);
781 nsmc->shmkey = shmkey;
782
783 /* -- system shared memory (read-only) -- */
784 DBGnsmlib_debug("nsmlib_initshm: key=%d size=%d", shmkey, sizeof(NSMsys));
785 nsmc->sysid = shmget(shmkey, sizeof(NSMsys), 0444);
786 if (nsmc->sysid < 0) {
787 /* -- most likely nsmd is not running,
788 -- further check is made in initnet -- */
789 nsmc->errn = errno(*__errno_location ());
790 return errno(*__errno_location ()) == ENOENT2 ? NSMESHMNOSYS(-37) : NSMESHMGETSYS(-22);
791 }
792
793 nsmc->sysp = (NSMsys *)shmat(nsmc->sysid, 0, SHM_RDONLY010000);
794 if (nsmc->sysp == (NSMsys *)-1) {
795 nsmc->errn = errno(*__errno_location ());
796 return NSMESHMATSYS(-23);
797 }
798
799 /* -- data shared memory (read/write) -- */
800 nsmc->memid = shmget(shmkey+1, sizeof(NSMmem), 0664);
801 if (nsmc->memid < 0) {
802 nsmc->errn = errno(*__errno_location ());
803 return errno(*__errno_location ()) == EACCES13 ? NSMESHMACCES(-38) : NSMESHMGETMEM(-24);
804 }
805
806 nsmc->memp = (NSMmem *)shmat(nsmc->memid, 0, 0);
807 if (nsmc->memp == (NSMmem *)-1) {
808 nsmc->errn = errno(*__errno_location ());
809 return NSMESHMATMEM(-25);
810 }
811
812 /* -- done -- */
813 nsmc->initshm_done = 1;
814 return 0;
815}
816/* -- nsmlib_select -------------------------------------------------- */
817int
818nsmlib_select(int fdr, int fdw, unsigned int msec)
819{
820 struct timeval tv;
821 fd_set fdset;
822 int ret;
823 if (fdr) fdw = 0;
824 FD_ZERO(&fdset)do { unsigned int __i; fd_set *__arr = (&fdset); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
825 FD_SET(fdr + fdw, &fdset)((void) (((&fdset)->__fds_bits)[((fdr + fdw) / (8 * (int
) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((fdr +
fdw) % (8 * (int) sizeof (__fd_mask)))))))
;
826 tv.tv_sec = msec / 1000;
827 tv.tv_usec = (msec % 1000) * 1000;
828 while (1) {
829 ret = select(fdr+fdw+1, fdr ? &fdset : 0, fdr ? 0 : &fdset, 0, &tv);
830 if (ret != -1 || (errno(*__errno_location ()) != EINTR4 && errno(*__errno_location ()) != EAGAIN11)) break;
831 }
832 if (ret < 0) {
833 ASSERTnsmlib_assert("nsmlib_select should not reach here - ret=%d", ret);
834 }
835 return ret;
836}
837/* -- nsmlib_selectc ------------------------------------------------- */
838/*
839 usesig = 1 when called from signal handler
840 then nsmc->usesig=1 is taken
841 usesig = 0 when called from the user program
842 then nsmc->usesig<1 is taken
843 */
844NSMcontext *
845nsmlib_selectc(int usesig, unsigned int msec)
846{
847 fd_set fdset;
848 struct timeval tv;
849 int ret;
850 int highest = -1;
851 NSMcontext *nsmc;
852
853 FD_ZERO(&fdset)do { unsigned int __i; fd_set *__arr = (&fdset); for (__i
= 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) (
(__arr)->__fds_bits)[__i] = 0; } while (0)
;
854 for (nsmc = nsmlib_context; nsmc; nsmc = nsmc->next) {
855 if (usesig != 0 && nsmc->usesig < 1) continue;
856 if (usesig == 0 && nsmc->usesig > 0) continue;
857 FD_SET(nsmc->sock, &fdset)((void) (((&fdset)->__fds_bits)[((nsmc->sock) / (8 *
(int) sizeof (__fd_mask)))] |= ((__fd_mask) (1UL << ((
nsmc->sock) % (8 * (int) sizeof (__fd_mask)))))))
;
858 if (highest < nsmc->sock + 1) highest = nsmc->sock + 1;
859 }
860 if (highest == -1) return 0;
861
862 tv.tv_sec = msec / 1000;
863 tv.tv_usec = (msec % 1000) * 1000;
864 while (1) {
865 ret = select(highest, &fdset, 0, 0, &tv);
866 if (ret != -1 || (errno(*__errno_location ()) != EINTR4 && errno(*__errno_location ()) != EAGAIN11)) break;
867 }
868 if (ret > 0) {
869 for (nsmc = nsmlib_context; nsmc; nsmc = nsmc->next) {
870 if (FD_ISSET(nsmc->sock, &fdset)((((&fdset)->__fds_bits)[((nsmc->sock) / (8 * (int)
sizeof (__fd_mask)))] & ((__fd_mask) (1UL << ((nsmc
->sock) % (8 * (int) sizeof (__fd_mask)))))) != 0)
) return nsmc;
871 }
872 ASSERTnsmlib_assert("nsmlib_selectc should not reach here - no fd");
873 return 0;
874 }
875 if (usesig > 0 && msec > 0 && ret <= 0) {
876 LOGnsmlib_lognl("nsmlib_selectc should not reach here - ret=%d msec=%d usesig=%d",
877 ret, msec, nsmc->usesig);
878 }
879 return 0;
880}
881/* -- nsmlib_pipewrite ----------------------------------------------- */
882/*
883 write one int32_t from pipe, to synchronize and get the result
884 */
885static int
886nsmlib_pipewrite(NSMcontext *nsmc, int32_t val)
887{
888 while (1) {
889 int ret = write(nsmc->pipe_wr, &val, sizeof(int32_t));
890 if (ret < 0 && errno(*__errno_location ()) == EINTR4) continue;
891 if (ret < 0) ASSERTnsmlib_assert("nsmlib_pipewrite %s", strerror(errno(*__errno_location ())));
892 break;
893 }
894 return 0;
895}
896/* -- nsmlib_piperead ------------------------------------------------ */
897/*
898 read one int32_t from pipe, to synchronize and get the result
899 */
900static int
901nsmlib_piperead(NSMcontext *nsmc, int32_t *valp)
902{
903 DBGnsmlib_debug("piperead 1");
904 while (1) {
905 int ret = read(nsmc->pipe_rd, valp, sizeof(int32_t));
906 if (ret < 0 && errno(*__errno_location ()) == EINTR4) continue;
907 if (ret < 0) {
908 nsmc->errn = errno(*__errno_location ());
909 return NSMEPIPEREAD(-116);
910 }
911 break;
912 }
913 DBGnsmlib_debug("piperead done");
914 return 0;
915}
916/* -- nsmlib_queue --------------------------------------------------- */
917int
918nsmlib_queue(NSMcontext *nsmc, NSMtcphead *hp)
919{
920 int len = sizeof(NSMtcphead) + sizeof(int32_t)*hp->npar + htons(hp->len)__bswap_16 (hp->len);
921 NSMrecvqueue *p = nsmlib_malloc(sizeof(struct NSMtcpqueue *) + len,
922 "queue", 0);
923 if (! p) return 0;
924
925 NSMrecvqueue *q = nsmc->recvqueue;
926 if (! q) {
927 nsmc->recvqueue = p;
928 } else {
929 while (q->next) q = q->next;
930 q->next = p;
931 }
932 p->next = 0;
933 memcpy((char *)&p->h, (char *)hp, len);
934 return 0;
935}
936/* -- nsmlib_recv ---------------------------------------------------- */
937int
938nsmlib_recv(NSMcontext *nsmc, NSMtcphead *hp, int wait_msec)
939{
940 int sock = nsmc->sock;
941 int ret;
942 int i;
943 int recvlen = 0;
944 int datalen = sizeof(NSMtcphead);
945 char *bufp = (char *)hp;
946
947 DBGnsmlib_debug("recv 1");
948 ret = nsmlib_select(sock, 0, wait_msec);
949 DBGnsmlib_debug("recv 2");
950 if (ret < 0) ASSERTnsmlib_assert("nsmlib_recv: should not reach here (1)");
951 if (ret == 0) return 0; /* time out */
952
953 for (i=0; i<2; i++) { /* i=0 for header / i=1 for data */
954 DBGnsmlib_debug("recv 3 bufp=%x", bufp);
955 while (recvlen < datalen) {
956 DBGnsmlib_debug("recv 4");
957 if (recvlen > 0) ret = nsmlib_select(sock, 0, 100); /* 1 msec */
958 if (ret < 0) ASSERTnsmlib_assert("nsmlib_recv: should not reach here (2)");
959 if (ret == 0) ASSERTnsmlib_assert("nsmlib_recv: should not reach here (3)");
960 if ((ret = read(sock, bufp+recvlen, datalen)) <= 0) {
961 if (ret == -1 && errno(*__errno_location ()) == EINTR4) continue;
962 if (ret < 0) ASSERTnsmlib_assert("nsmlib_recv read error (1) %s", strerror(errno(*__errno_location ())));
963 return (nsmlib_errc = NSMECLOSED(-115));
964 }
965 datalen -= ret;
966 recvlen += ret;
967 }
968
969 DBGnsmlib_debug("recv 5 recvlen=%d", recvlen);
970 /* for data */
971 bufp += recvlen;
972 recvlen = 0;
973 datalen = hp->npar * sizeof(int32_t) + ntohs(hp->len)__bswap_16 (hp->len);
974 }
975 DBGnsmlib_debug("recv 6 datalen=%d npar=%d len=%d", datalen, hp->npar, ntohs(hp->len)__bswap_16 (hp->len));
976 return sizeof(NSMtcphead) + datalen;
977}
978/* -- nsmlib_recvpar ------------------------------------------------- */
979int
980nsmlib_recvpar(NSMcontext *nsmc)
981{
982 char buf[NSM_TCPMSGSIZ(16 + (256*4 + 65536))];
983 NSMtcphead *hp = (NSMtcphead *)buf;
984 int32_t *hp_pars = (int32_t *)(buf + sizeof(NSMtcphead));
985 int ret = 0;
986 int val;
987
988 DBGnsmlib_debug("recvpar 1");
989 if (nsmc->usesig > 0) {
990 DBGnsmlib_debug("recvpar 2");
991 ret = nsmlib_piperead(nsmc, &val);
992 } else {
993 DBGnsmlib_debug("recvpar 3");
994 int64 tlimit = time1ms() + 5000; /* 5 seconds */
995 int wait_msec = 5000;
996 while (1) {
997 DBGnsmlib_debug("recvpar 4");
998 if ((ret = nsmlib_recv(nsmc, hp, wait_msec)) <= 0) {
999 if (ret == 0) {
1000 sprintf(nsmc->errs, "recvpar: timeout");
1001 ret = NSMETIMEOUTR(-42);
1002 }
1003 break;
1004 }
1005 DBGnsmlib_debug("recvpar 5");
1006
1007 if (ntohs(hp->req)__bswap_16 (hp->req) != nsmc->reqwait) {
1008 DBGnsmlib_debug("recvpar 6 req=%x wait=%x", ntohs(hp->req)__bswap_16 (hp->req), nsmc->reqwait);
1009 if (nsmlib_queue(nsmc, hp) < 0) return -1;
1010 } else if (hp->npar < 1) {
1011 DBGnsmlib_debug("recvpar 7");
1012 sprintf(nsmc->errs, "recvpar: npar=0 for req=%x", nsmc->reqwait);
1013 ret = NSMEUNEXPECTED(-119);
1014 break;
1015 } else {
1016 DBGnsmlib_debug("recvpar 8");
1017 val = htonl(hp_pars[0])__bswap_32 (hp_pars[0]);
1018 break;
1019 }
1020 wait_msec = (tlimit - time1ms());
1021 }
1022 }
1023 DBGnsmlib_debug("recvpar 9");
1024 nsmc->reqwait = 0;
1025 if (ret < 0) return nsmc->errc = ret;
1026 if (val < 0) nsmc->errc = val;
1027 return val;
1028}
1029/* -- nsmlib_call ---------------------------------------------------- */
1030void
1031nsmlib_call(NSMcontext *nsmc, NSMtcphead *hp)
1032{
1033 int i;
1034 NSMmsg msg;
1035 const char *recvbuf = (char *)hp + sizeof(NSMtcphead);
1036 NSMrequest *reqp = nsmc->req;
1037 NSMrequest *reqlast = reqp + nsmc->nreq;
1038
1039 DBS(nsmc,1002)nsmlib_checkpoints[nsmlib_currecursive] = (1002);
1040
1041 /* search request */
1042 msg.req = ntohs(hp->req)__bswap_16 (hp->req);
1043 while (reqp < reqlast) {
1044 if (reqp->functype != NSMLIB_FNNON && reqp->req == msg.req) break;
1045 reqp++;
1046 }
1047 if (reqp == reqlast) {
1048 NSMreq *rp = nsmc->sysp->req;
1049 for (i=0; i<NSMSYS_MAX_REQ1024 && rp[i].name[0]; i++) {
1050 if (rp[i].code == hp->req) break; // compare without ntohs
1051 }
1052 if (i < NSMSYS_MAX_REQ1024 && rp[i].name[0]) {
1053 LOGnsmlib_lognl("Received request (%s) is not registered", rp[i].name);
1054 } else {
1055 LOGnsmlib_lognl("nsmlib_call unknown req=%04x", msg.req);
1056 }
1057 for (reqp = nsmc->req; reqp < reqlast; reqp++) {
1058 DBGnsmlib_debug("reqp[%d] %02x %04x", reqp-nsmc->req, reqp->functype, reqp->req);
1059 }
1060 return;
1061 }
1062 if (! reqp->callback && reqp->functype != NSMLIB_FNSYS) {
1063 DBGnsmlib_debug("nsmlib_call no callback for req=%s", reqp->name);
1064 return;
1065 }
1066 DBGnsmlib_debug("nsmlib_call req=%s", reqp->name);
1067
1068 DBS(nsmc,1003)nsmlib_checkpoints[nsmlib_currecursive] = (1003);
1069
1070 /* fill other msg entries */
1071 msg.req = ntohs(hp->req)__bswap_16 (hp->req);
1072 msg.seq = ntohs(hp->seq)__bswap_16 (hp->seq);
1073 msg.node = ntohs(hp->src)__bswap_16 (hp->src);
1074 msg.npar = hp->npar;
1075 msg.len = ntohs(hp->len)__bswap_16 (hp->len);
1076 msg.pars[0] = msg.pars[1] = 0; /* to be compatible with NSM1 */
1077 for (i=0; i < msg.npar; i++) {
1078 msg.pars[i] = ntohl(*(int32_t *)(recvbuf + i*sizeof(int32_t)))__bswap_32 (*(int32_t *)(recvbuf + i*sizeof(int32_t)));
1079 }
1080 msg.datap = msg.len ? recvbuf + msg.npar*sizeof(int32_t) : 0;
1081
1082 DBS(nsmc,1004)nsmlib_checkpoints[nsmlib_currecursive] = (1004);
1083
1084 switch (reqp->functype) {
1085 case NSMLIB_FNSYS:
1086 if (! reqp->callback) {
1087 if (nsmc->reqwait != msg.req) {
1088 ASSERTnsmlib_assert("unexpected call %x, waiting for %x", msg.req, nsmc->reqwait);
1089 }
1090 nsmc->reqwait = 0;
1091 DBGnsmlib_debug("pipewrite pars0=%d", msg.pars[0]);
1092 DBS(nsmc,1006)nsmlib_checkpoints[nsmlib_currecursive] = (1006);
1093 nsmlib_pipewrite(nsmc, msg.pars[0]);
1094 DBS(nsmc,1008)nsmlib_checkpoints[nsmlib_currecursive] = (1008);
1095 break;
1096 }
1097 /* no break */
1098
1099 case NSMLIB_FNSTD:
1100 DBS(nsmc,1010)nsmlib_checkpoints[nsmlib_currecursive] = (1010);
1101 if (! nsmc->hook) {
1102 DBGnsmlib_debug("nsmlib_call calling callback without hook");
1103 DBS(nsmc,1012)nsmlib_checkpoints[nsmlib_currecursive] = (1012);
1104 reqp->callback(&msg, nsmc);
1105 } else if (! nsmc->hook(&msg, nsmc)) {
1106 DBGnsmlib_debug("nsmlib_call calling callback");
1107 DBS(nsmc,1014)nsmlib_checkpoints[nsmlib_currecursive] = (1014);
1108 reqp->callback(&msg, nsmc);
1109 } else {
1110 DBGnsmlib_debug("nsmlib_call hook error");
1111 }
1112 break;
1113
1114 default:
1115 DBGnsmlib_debug("nsmlib_call functype=%d", reqp->functype);
1116 }
1117 DBS(nsmc,1016)nsmlib_checkpoints[nsmlib_currecursive] = (1016);
1118}
1119/* -- nsmlib_handler ------------------------------------------------- */
1120static void
1121#ifdef SIGRTMIN(__libc_current_sigrtmin ())
1122nsmlib_handler(int sig, siginfo_t *info, void *ignored)
1123#else
1124nsmlib_handler(int sig)
1125#endif
1126{
1127 sigset_t mask;
1128 int wait_msec = 1000; /* 1 sec only for the first time */
1129
1130 /* DBG("nsmlib_handler sig=%d", sig); */
1131
1132 /* sigset */
1133 if (! sig) return; /* this should not be directly called */
1134
1135 /* in the signal handler mode, it can handle more than one signals */
1136 while (1) {
1137 char buf[NSM_TCPMSGSIZ(16 + (256*4 + 65536))]; /* should not be static */
1138 NSMcontext *nsmc = nsmlib_selectc(1, wait_msec); /* usesig = 1 */
1139 wait_msec = 0; /* no wait at the later tries */
1140
1141 if (! nsmc) break;
1142
1143 /* receive */
1144 if (nsmlib_recv(nsmc, (NSMtcphead *)buf, 1000) <= 0) { /* 1 sec */
1145 break;
1146 }
1147
1148 /* callback function */
1149 if (nsmlib_currecursive >= nsmlib_maxrecursive) {
1150 nsmlib_nskipped++;
1151 nsmlib_lastskipped = *(NSMtcphead *)buf;
1152 } else {
1153 nsmlib_currecursive++;
1154 DBS(nsmc,1001)nsmlib_checkpoints[nsmlib_currecursive] = (1001);
1155 sigemptyset(&mask);
1156 sigaddset(&mask, sig);
1157 sigprocmask(SIG_UNBLOCK1, &mask, 0);
1158 nsmlib_call(nsmc, (NSMtcphead *)buf);
1159 /*sigprocmask(SIG_BLOCK, &mask, 0);*/
1160 DBS(nsmc,-1)nsmlib_checkpoints[nsmlib_currecursive] = (-1);
1161 nsmlib_currecursive--;
1162 }
1163 };
1164
1165 if (nsmlib_logfp && nsmlib_loglen && ! nsmlib_currecursive) {
1166 nsmlib_logflush();
1167 }
1168
1169 return;
1170}
1171/* -- nsmlib_callbackid ---------------------------------------------- */
1172/*
1173 Calling with callback == 0 will disable the function,
1174 except for NSMLIB_FNSYS which has no callback.
1175 Even with callback == 0, it can be used in the non-signal mode.
1176 Calling with existing req will replace the function in the list.
1177 Calling with NSMLIB_FNNON will remove the function from the list.
1178 System callback functions are protected from removing/replacing.
1179 */
1180int
1181nsmlib_callbackid(NSMcontext *nsmc, int req, const char *name,
1182 NSMcallback_t callback, NSMfunctype functype)
1183{
1184 NSMrequest *reqp = nsmc->req;
1185 NSMrequest *reqlast = reqp + nsmc->nreq;
1186 NSMrequest *reqfound = 0;
1187 NSMrequest *reqfree = 0;
1188 int sigfound = 0;
1189
1190 /* basic checks */
1191 if (! nsmc || ! nsmc->memp) return NSMENOINIT(-26);
1192 if (nsmc->nodeid == NSMSYS_MAX_NOD1024) return NSMEPERM(-27); /* anonymous */
1193
1194 /* search for existing and free-space */
1195 while (reqp < reqlast) {
1196 if (! reqfree && reqp->functype == NSMLIB_FNNON) {
1197 reqfree = reqp; /* first free place, but still need to search for req */
1198 }
1199 if (reqp->req == req) {
1200 reqfree = reqfound = reqp;
1201 if (sigfound) break;
1202 } else if (reqp->callback) {
1203 sigfound = 1;
1204 if (reqfound) break;
1205 }
1206 reqp++;
1207 }
1208
1209 /* system function check */
1210 if (nsmc->initsig_done && functype == NSMLIB_FNSYS) return NSMEINVFUNC(-29);
1211 if (! nsmc->initsig_done && functype != NSMLIB_FNSYS) return NSMEINVFUNC(-29);
1212 if (reqfound && reqfound->functype == NSMLIB_FNSYS) return NSMEINVFUNC(-29);
1213
1214 /* attach to the end if not found */
1215 if (! reqfree) {
1216 if (nsmc->nreq >= NSMLIB_MAX_CALLBACK1024) return NSMEMAXFUNC(-30);
1217 reqfree = reqlast;
1218 nsmc->nreq++;
1219 }
1220
1221 /* update request table */
1222 reqfree->req = req;
1223 reqfree->functype = functype;
1224 reqfree->callback = callback;
1225 if (name) {
1226 strcpy(reqfree->name, name);
1227 } else {
1228 sprintf(reqfree->name, "#%04x", req);
1229 }
1230 return 0;
1231}
1232/* -- nsmlib_callback ------------------------------------------------ */
1233int
1234nsmlib_callback(NSMcontext *nsmc, const char *name,
1235 NSMcallback_t callback, NSMfunctype functype)
1236{
1237 NSMsys *sysp = nsmc->sysp;
1238 int hash = nsmlib_hash(sysp, sysp->reqhash, NSMSYS_MAX_HASH2039, name, 0);
1239 NSMreq *reqp = (NSMreq *)MEMPTR(sysp, ntohl(sysp->reqhash[hash]))((char *)(sysp) + __bswap_32 (sysp->reqhash[hash]));
1240
1241 if (hash < 0) {
1242 nsmc->errc = NSMEUNEXPECTED(-119);
1243 sprintf(nsmc->errs, "hash error for %s", name);
1244 return -1;
1245 }
1246
1247 if (strcmp(reqp->name, name)) {
1248 nsmc->errc = NSMEUNEXPECTED(-119);
1249 sprintf(nsmc->errs, "wrong hash? name %s %s\n", reqp->name, name);
1250 return -1;
1251 }
1252 return nsmlib_callbackid(nsmc, ntohs(reqp->code)__bswap_16 (reqp->code), name,
1253 callback, functype);
1254}
1255/* -- nsmlib_usesig -------------------------------------------------- */
1256void
1257nsmlib_usesig(NSMcontext *nsmc, int usesig)
1258{
1259 if (nsmc) nsmc->usesig = usesig;
1260}
1261/* -- nsmlib_delclient ----------------------------------------------- */
1262void
1263nsmlib_delclient(NSMmsg *msg, NSMcontext *nsmc)
1264{
1265 LOGnsmlib_lognl("killed by nsmd2");
1266 exit(1);
1267}
1268/* -- nsmlib_initsig ------------------------------------------------- */
1269int
1270nsmlib_initsig(NSMcontext *nsmc)
1271{
1272 struct sigaction action;
1273 int pipes[2];
1274#ifdef SIGRTMIN(__libc_current_sigrtmin ())
1275 void nsmlib_handler(int signo, siginfo_t *info, void *ignored);
1276 nsmlib_sig = SIGRTMIN(__libc_current_sigrtmin ());
1277#define NSMLIB_SETHANDLER(s,h)(s).__sigaction_handler.sa_sigaction=(h); (s).sa_flags = 4|0x10000000 \
1278 (s).sa_sigaction__sigaction_handler.sa_sigaction=(h); (s).sa_flags = SA_SIGINFO4|SA_RESTART0x10000000
1279#else
1280 void nsmlib_handler(int);
1281 nsmlib_sig = SIGUSR110;
1282#define NSMLIB_SETHANDLER(a,h)(a).__sigaction_handler.sa_sigaction=(h); (a).sa_flags = 4|0x10000000 (a).sa_sighandler=(h)
1283#endif
1284
1285 sigemptyset(&nsmlib_sigmask);
1286 sigaddset(&nsmlib_sigmask, nsmlib_sig);
1287
1288 if (! nsmlib_checkpoints) {
1289 nsmlib_currecursive = 0;
1290 nsmlib_maxrecursive = NSMLIB_MAXRECURSIVE256;
1291 nsmlib_nskipped = 0;
1292 memset(&nsmlib_lastskipped, 0, sizeof(nsmlib_lastskipped));
1293 nsmlib_checkpoints = nsmlib_malloc(sizeof(int) * nsmlib_maxrecursive,
1294 "initsig", "checkp");
1295 if (! nsmlib_checkpoints) {
1296 ASSERTnsmlib_assert("can't alloc %d bytes", sizeof(int) * nsmlib_maxrecursive);
1297 }
1298 memset(nsmlib_checkpoints, 0, sizeof(int) * nsmlib_maxrecursive);
1299 }
1300
1301 /* create pipes */
1302 if (pipe(pipes) < 0) {
1303 nsmc->errn = errno(*__errno_location ());
1304 return NSMENOPIPE(-111);
1305 }
1306 nsmc->pipe_rd = pipes[0];
1307 nsmc->pipe_wr = pipes[1];
1308
1309 /* setup callback handlers */
1310 nsmlib_callbackid(nsmc, NSMCMD_NEWCLIENT((0xff00) + 0x00), "cmd_newclient", 0, NSMLIB_FNSYS);
1311 nsmlib_callbackid(nsmc, NSMCMD_ALLOCMEM((0xff00) + 0x04), "cmd_allocmem", 0, NSMLIB_FNSYS);
1312 nsmlib_callbackid(nsmc, NSMCMD_OPENMEM((0xff00) + 0x09), "cmd_openmem", 0, NSMLIB_FNSYS);
1313 nsmlib_callbackid(nsmc, NSMCMD_FLUSHMEM((0xff00) + 0x06), "cmd_flushmem", 0, NSMLIB_FNSYS);
1314 nsmlib_callbackid(nsmc, NSMCMD_NEWREQ((0xff00) + 0x18), "cmd_newreq", 0, NSMLIB_FNSYS);
1315 /* implement delclient as FNSTD */
1316 nsmlib_callbackid(nsmc, NSMCMD_DELCLIENT((0xff00) + 0x03), "cmd_delclient",
1317 nsmlib_delclient, NSMLIB_FNSYS);
1318 /* ... and many more to follow ----> */
1319
1320 /* setup signals */
1321 memset(&action, 0, sizeof(action));
1322 sigemptyset(&action.sa_mask);
1323 sigaddset(&action.sa_mask, nsmlib_sig);
1324 NSMLIB_SETHANDLER(action, nsmlib_handler)(action).__sigaction_handler.sa_sigaction=(nsmlib_handler); (
action).sa_flags = 4|0x10000000
;
1325 /*
1326 Don't do: action.sa_flags |= SA_RESTART;
1327 Adding SA_RESTART is not a good idea: a blocking read should
1328 return with EINTR upon NSM signal, because this NSM signal may be
1329 the one to clear the blocking condition.
1330 */
1331 sigaction(nsmlib_sig, &action, 0);
1332
1333 nsmc->usesig = -1; /* undecided */
1334 nsmc->initsig_done = 1;
1335 return 0;
1336}
1337/* -- nsmlib_send ---------------------------------------------------- */
1338int
1339nsmlib_send(NSMcontext *nsmc, NSMmsg *msgp)
1340{
1341 static char buf[NSM_TCPMSGSIZ(16 + (256*4 + 65536))];
1342 NSMtcphead *hp = (NSMtcphead *)buf;
1343 char *datap = buf + sizeof(NSMtcphead);
1344 const char *writep;
1345 int writelen;
1346 int err = 0;
1347 int i;
1348 int oldsig;
1349
1350 DBS(nsmc,1100)nsmlib_checkpoints[nsmlib_currecursive] = (1100);
1351
1352 if (! nsmc) return NSMENOINIT(-26);
1353 if (nsmc->sock < 0) return NSMENOINIT(-26);
1354 if (nsmc->nodeid == NSMSYS_MAX_NOD1024) return NSMEPERM(-27); /* anonymous */
1355
1356 if (msgp->len == 0 && msgp->datap != 0) return NSMEINVDATA(-28);
1357 if (msgp->len == 0 && msgp->datap != 0) return NSMEINVDATA(-28);
1358
1359 DBS(nsmc,1102)nsmlib_checkpoints[nsmlib_currecursive] = (1102);
1360
1361 DBGnsmlib_debug("nsmlib_send nodeid=%d, req=%04x", msgp->node, msgp->req);
1362
1363 hp->src = htons(nsmc->nodeid)__bswap_16 (nsmc->nodeid);
1364 hp->dest = htons(msgp->node)__bswap_16 (msgp->node);
1365 hp->req = htons(msgp->req)__bswap_16 (msgp->req);
1366 hp->seq = htons(msgp->seq)__bswap_16 (msgp->seq);
1367 hp->npar = msgp->npar;
1368 hp->len = htons(msgp->len)__bswap_16 (msgp->len);
1369 hp->from = 0;
1370 for (i=0; i<hp->npar; i++) {
1371 *(int32_t *)datap = htonl(msgp->pars[i])__bswap_32 (msgp->pars[i]);
1372 datap += sizeof(int32_t);
1373 }
1374 if (msgp->len && msgp->len <= NSM_TCPTHRESHOLD(16 + 256*4)) {
1375 memcpy(datap, msgp->datap, msgp->len);
1376 writelen = sizeof(NSMtcphead) + msgp->npar*sizeof(int32_t) + msgp->len;
1377 } else {
1378 writelen = sizeof(NSMtcphead) + msgp->npar*sizeof(int32_t);
1379 }
1380 writep = buf;
1381
1382 DBS(nsmc,1104)nsmlib_checkpoints[nsmlib_currecursive] = (1104);
1383 DBGnsmlib_debug("writep = %x", writep);
1384
1385 while (writelen > 0) {
1386 int ret = nsmlib_select(0, nsmc->sock, 1000); /* 1 sec */
1387 if (ret < 0) { nsmc->errn = errno(*__errno_location ());
1388 err = NSMESELECT(-112); goto nsmlib_send_error; }
1389 if (ret == 0) { err = NSMETIMEOUTW(-41); goto nsmlib_send_error; }
1390
1391 ret = write(nsmc->sock, writep, writelen);
1392 if (ret < 0 && (errno(*__errno_location ()) == EINTR4 || errno(*__errno_location ()) == EAGAIN11)) continue;
1393 if (ret < 0) { nsmc->errn = errno(*__errno_location ());
1394 err = NSMEWRITE(-114); goto nsmlib_send_error; }
1395 if (ret == 0) { err = NSMECLOSED(-115); goto nsmlib_send_error; }
1396
1397 writelen -= ret;
1398 writep += ret;
1399 }
1400
1401 if (msgp->len > NSM_TCPTHRESHOLD(16 + 256*4)) {
1402 writelen = msgp->len;
1403 writep = msgp->datap;
1404 }
1405
1406 while (writelen > 0) {
1407 int ret = nsmlib_select(0, nsmc->sock, 1000); /* 1 sec */
1408 if (ret < 0) { nsmc->errn = errno(*__errno_location ());
1409 err = NSMESELECT(-112); goto nsmlib_send_error; }
1410 if (ret == 0) { err = NSMETIMEOUTW(-41); goto nsmlib_send_error; }
1411
1412 ret = write(nsmc->sock, writep, writelen);
1413 if (ret < 0 && (errno(*__errno_location ()) == EINTR4 || errno(*__errno_location ()) == EAGAIN11)) continue;
1414 if (ret < 0) { nsmc->errn = errno(*__errno_location ());
1415 err = NSMEWRITE(-114); goto nsmlib_send_error; }
1416 if (ret == 0) { err = NSMECLOSED(-115); goto nsmlib_send_error; }
1417
1418 writelen -= ret;
1419 writep += ret;
1420 }
1421 DBS(nsmc,1106)nsmlib_checkpoints[nsmlib_currecursive] = (1106);
1422 return 0;
1423
1424 nsmlib_send_error:
1425 DBS(nsmc,1199)nsmlib_checkpoints[nsmlib_currecursive] = (1199);
1426 shutdown(nsmc->sock, SHUT_RDWRSHUT_RDWR);
1427 close(nsmc->sock);
1428 nsmc->sock = -1;
1429 return err; /* nsmc->errc or nsmlib_errc is set in the caller */
1430}
1431/* -- nsmlib_initcli ------------------------------------------------- */
1432static int
1433nsmlib_initcli(NSMcontext *nsmc, const char *nodename)
1434{
1435 NSMsys *sysp = nsmc->sysp;
1436 NSMmsg msg;
1437 int ret;
1438 int inod;
1439 int force_newclient = 0;
1440
1441 /* check if the node is already there */
1442 int nnod = (int16_t)ntohs(sysp->nnod)__bswap_16 (sysp->nnod);
1443 for (inod = 0; inod <= nnod; inod++) {
1444 NSMnod *nodp = &sysp->nod[inod];
1445 if (strcmp(nodp->name, nodename) != 0) continue;
1446 if (nodp->ipaddr != sysp->ipaddr) continue;
1447 if (kill(ntohl(nodp->nodpid)__bswap_32 (nodp->nodpid), 0) == 0 || errno(*__errno_location ()) != ESRCH3) {
1448 sprintf(nsmlib_errs, "node %s already exists", nodename);
1449 return nsmlib_errc = NSMENODEEXIST(-4);
1450 }
1451 force_newclient = 1;
1452 break;
1453 }
1454
1455 /* request setup */
1456 memset(&msg, 0, sizeof(msg));
1457 msg.node = -1;
1458 msg.pars[0] = geteuid();
1459 msg.pars[1] = getpid();
1460 msg.pars[2] = NSM_LIBRARY_VERSION2008;
1461 msg.npar = 3;
1462 if (force_newclient) {
1463 msg.npar = 4;
1464 msg.pars[3] = 0; /* value itself is unused */
1465 }
1466 msg.datap = nodename;
1467 if (nodename) msg.len = strlen(nodename) + 1;
1468#ifdef SIGRTMIN(__libc_current_sigrtmin ())
1469 msg.req = NSMCMD_NEWCLIENT((0xff00) + 0x00);
1470#else
1471 msg.req = NSMCMD_NEWCLIENTOB((0xff00) + 0x01); /* obsolete */
1472#endif
1473
1474 /* send request */
1475 nsmc->reqwait = msg.req;
1476 if ((ret = nsmlib_send(nsmc, &msg)) < 0) {
1477 nsmc->reqwait = 0;
1478 return nsmlib_errc = ret;
1479 }
1480
1481 /* receive request */
1482 ret = nsmlib_recvpar(nsmc);
1483 DBGnsmlib_debug("initcli: recvpar=%d", ret);
1484 if (ret < 0) {
1485 switch (ret) {
1486 case NSMENODEEXIST(-4):
1487 case NSMENODEHERE(-45):
1488 sprintf(nsmlib_errs, "node %s already exists", nodename);
1489 break;
1490 case NSMEFULNODE(-5):
1491 sprintf(nsmlib_errs, "no more place for node %s", nodename);
1492 break;
1493 default:
1494 /* errs just in case when errc is unknown */
1495 sprintf(nsmlib_errs, "initcli: recvpar error=%d", ret);
1496 }
1497 return nsmlib_errc = ret;
1498 }
1499 if (ret > NSMSYS_MAX_NOD1024) {
1500 sprintf(nsmlib_errs, "invalid nodeid=%d returned from nsmd2", ret);
1501 return nsmlib_errc = NSMEUNEXPECTED(-119);
1502 }
1503 nsmc->nodeid = ret;
1504 return 0;
1505}
1506/* -- nsmlib_sendreqid ----------------------------------------------- */
1507int
1508nsmlib_sendreqid(NSMcontext *nsmc,
1509 const char *node, uint16_t req, uint npar, int *pars,
1510 int len, const char *datap)
1511{
1512 NSMmsg msg;
1513 int i;
1514 int nodeid;
1515
1516 if (! nsmc || ! nsmc->memp) return NSMENOINIT(-26);
1517
1518 if (! node || ! *node) return nsmc->errc = NSMEEMPTYDEST(-39);
1519 nodeid = nsmlib_nodeid(nsmc, node);
1520 if (nodeid < 0) return nsmc->errc = NSMENODEST(-6);
1521
1522 msg.req = req;
1523 msg.seq = nsmc->seq++;
1524 msg.node = (uint16_t)nodeid;
1525 msg.npar = npar > 256 ? 0 : npar;
1526 for (i=0; i<msg.npar; i++) msg.pars[i] = pars[i];
1527 msg.len = len;
1528 msg.datap = datap;
1529 return (nsmc->errc = nsmlib_send(nsmc, &msg));
1530}
1531/* -- nsmlib_reqid --------------------------------------------------- */
1532int
1533nsmlib_reqid(NSMcontext *nsmc, const char *reqname)
1534{
1535 NSMsys *sysp = nsmc->sysp;
1536 int hash = nsmlib_hash(sysp, sysp->reqhash, NSMSYS_MAX_HASH2039, reqname, 0);
1537 NSMreq *reqp = (NSMreq *)MEMPTR(sysp, ntohl(sysp->reqhash[hash]))((char *)(sysp) + __bswap_32 (sysp->reqhash[hash]));
1538
1539 if (hash < 0) {
1540 sprintf(nsmlib_errs, "reqid: req %s is unknown", reqname);
1541 return NSMENOSUCHREQ(-43);
1542 }
1543
1544 if (strcmp(reqp->name, reqname)) {
1545 sprintf(nsmlib_errs,
1546 "broken hash-table for req %s => %s\n", reqname, reqp->name);
1547 return NSMEBADHASH(-44);
1548 }
1549 return ntohs(reqp->code)__bswap_16 (reqp->code);
1550}
1551/* -- nsmlib_reqname ------------------------------------------------- */
1552const char *
1553nsmlib_reqname(NSMcontext *nsmc, int reqid)
1554{
1555 NSMsys *sysp = nsmc->sysp;
1556 reqid -= NSMREQ_FIRST(0x1000);
1557 if (reqid < 0 || reqid >= NSMSYS_MAX_REQ1024) return "(invalid)";
1558 if (! sysp->req[reqid].name[0]) return "(undef)";
1559 return sysp->req[reqid].name;
1560}
1561/* -- nsmlib_sendreq ------------------------------------------------- */
1562int
1563nsmlib_sendreq(NSMcontext *nsmc, const char *node, const char *req,
1564 uint npar, int *pars, int len, const char *datap)
1565{
1566 int reqid = nsmlib_reqid(nsmc, req);
1567 if (reqid < 0) {
1568 sleep(1); /* one second penalty */
1569 return reqid;
1570 }
1571 return nsmlib_sendreqid(nsmc, node, reqid, npar, pars, len, datap);
1572}
1573/* -- nsmlib_register_request ---------------------------------------- */
1574int
1575nsmlib_register_request(NSMcontext *nsmc, const char *name)
1576{
1577 NSMmsg msg;
1578 int ret;
1579 int reqid;
1580 memset(&msg, 0, sizeof(msg));
1581 msg.req = NSMCMD_NEWREQ((0xff00) + 0x18);
1582 msg.node = -1;
1583 msg.len = strlen(name) + 1;
1584 msg.datap = name;
1585 nsmc->reqwait = msg.req;
1586
1587 /* send request */
1588 DBGnsmlib_debug("register_request: before send");
1589 nsmc->errc = nsmlib_send(nsmc, &msg);
1590 DBGnsmlib_debug("register_request: after send");
1591 if (nsmc->errc < 0) { nsmc->reqwait = 0; return nsmc->errc; }
1592
1593 /* receive request */
1594 DBGnsmlib_debug("register_request: before recvpar");
1595 ret = nsmlib_recvpar(nsmc);
1596 DBGnsmlib_debug("register_request: after recvpar");
1597 if (ret < 0) return ret;
1598 return 0;
1599}
1600/* -- nsmlib_readmem ------------------------------------------------- */
1601int
1602nsmlib_readmem(NSMcontext *nsmc, void *buf,
1603 const char *datname, const char *fmtname, int revision)
1604{
1605 char fmtstr[256];
1606 NSMsys *sysp = nsmc->sysp;
1607 NSMmem *memp = nsmc->memp;
1608 NSMmsg msg;
1609 int ret;
1610 int datid;
1611 NSMdat *datp;
1612 int newrevision = -1;
1613
1614 if (! fmtname) fmtname = datname;
1615
1616 if (revision <= 0 && revision != -1) {
1617 sprintf(nsmc->errs, "invalid revision %d for data %s", revision, datname);
1618 return nsmc->errc = NSMEINVPAR(-3);
1619 }
1620 NSMparse *parsep = nsmlib_parsefile(fmtname, revision, nsmlib_incpath,
1621 fmtstr, &newrevision);
1622 if (! parsep) {
1623 int errcode;
1624 const char *errstr = nsmlib_parseerr(&errcode);
1625 sprintf(nsmc->errs, "cannot read data %s, %s", datname, errstr);
1626 return nsmc->errc = NSMEPARSE(-34);
1627 }
1628 nsmlib_parsefree(parsep);
1629 parsep = 0;
1630
1631 if (revision == -1) {
1632 revision = newrevision;
1633 }
1634
1635 /* linear search, to be replaced with a hash version */
1636 for (datid = 0; datid < NSMSYS_MAX_DAT1024; datid++) {
1637 datp = sysp->dat + datid;
1638 if (strcmp(datp->dtnam, datname) == 0) break;
1639 }
1640 if (datid == NSMSYS_MAX_DAT1024) {
1641 sprintf(nsmc->errs, "data %s not found", datname);
1642 return nsmc->errc = NSMENOMEM(-31);
1643 }
1644 if (strcmp(datp->dtfmt, fmtstr) != 0) {
1645 sprintf(nsmc->errs, "data %s format mismatch %s %s",
1646 datname, fmtstr, datp->dtfmt);
1647 return nsmc->errc = NSMEBADFMT(-32);
1648 }
1649 if (ntohs(datp->dtrev)__bswap_16 (datp->dtrev) != revision) {
1650 sprintf(nsmc->errs, "data %s revision mismatch %d %d",
1651 datname, revision, datp->dtrev);
1652 return nsmc->errc = NSMEBADREV(-33);
1653 }
1654
1655 memcpy((char *)buf,
1656 (char *)memp + ntohl(datp->dtpos)__bswap_32 (datp->dtpos), ntohs(datp->dtsiz)__bswap_16 (datp->dtsiz));
1657
1658 return 0;
1659}
1660/* -- nsmlib_statmem ------------------------------------------------ */
1661/*
1662 return value: size of data if > 0
1663 fmtbuf is set with name of struct
1664*/
1665int
1666nsmlib_statmem(NSMcontext *nsmc,
1667 const char *datname, char *fmtbuf, int bufsiz)
1668{
1669 NSMsys *sysp = nsmc->sysp;
1670 NSMdat *datp;
1671 int datid;
1672 int dtfmtlen;
1673
1674 if (! fmtbuf) return 0;
1675
1676 /* linear search, to be replaced with a hash version */
1677 for (datid = 0; datid < NSMSYS_MAX_DAT1024; datid++) {
1678 datp = sysp->dat + datid;
1679 if (strcmp(datp->dtnam, datname) == 0) break;
1680 }
1681 if (datid == NSMSYS_MAX_DAT1024) {
1682 sprintf(nsmc->errs, "data %s not found", datname);
1683 return (nsmc->errc = NSMENOMEM(-31));
1684 }
1685
1686 dtfmtlen = strlen(datp->dtfmt);
1687 *fmtbuf = 0;
1688 if (datp->dtfmt[dtfmtlen + 1]) {
1689 int dtstrlen = strlen(datp->dtfmt + dtfmtlen + 1);
1690 if (dtstrlen < bufsiz) {
1691 strcpy(fmtbuf, datp->dtfmt + dtfmtlen + 1);
1692 }
1693 }
1694 return (int)ntohs(datp->dtsiz)__bswap_16 (datp->dtsiz);
1695}
1696/* -- nsmlib_openmem ------------------------------------------------- */
1697void *
1698nsmlib_openmem(NSMcontext *nsmc,
1699 const char *datname, const char *fmtname, int revision)
1700{
1701 char fmtstr[256];
1702 NSMsys *sysp = nsmc->sysp;
1703 NSMmem *memp = nsmc->memp;
1704 NSMmsg msg;
1705 int ret;
1706 int datid;
1707 NSMdat *datp;
1708 int refid;
1709 NSMref *refp;
1710 int newrevision = -1;
1711
1712 if (! fmtname) fmtname = datname;
1713
1714 if (revision <= 0 && revision != -1) {
1715 sprintf(nsmc->errs, "invalid revision %d for data %s", revision, datname);
1716 nsmc->errc = NSMEINVPAR(-3);
1717 return 0;
1718 }
1719 NSMparse *parsep = nsmlib_parsefile(fmtname, revision, nsmlib_incpath,
1720 fmtstr, &newrevision);
1721 if (! parsep) {
1722 int errcode;
1723 const char *errstr = nsmlib_parseerr(&errcode);
1724 sprintf(nsmc->errs, "cannot open data %s, %s", datname, errstr);
1725 nsmc->errc = NSMEPARSE(-34);
1726 return 0;
1727 }
1728 nsmlib_parsefree(parsep);
1729
1730 if (revision == -1) {
1731 revision = newrevision;
1732 }
1733
1734 /* linear search, to be replaced with a hash version */
1735 for (datid = 0; datid < NSMSYS_MAX_DAT1024; datid++) {
1736 datp = sysp->dat + datid;
1737 if (strcmp(datp->dtnam, datname) == 0) break;
1738 }
1739 if (datid == NSMSYS_MAX_DAT1024) {
1740 sprintf(nsmc->errs, "data %s not found", datname);
1741 nsmc->errc = NSMENOMEM(-31);
1742 return 0;
1743 }
1744 if (strcmp(datp->dtfmt, fmtstr) != 0) {
1745 sprintf(nsmc->errs, "data %s format mismatch %s %s",
1746 datname, fmtstr, datp->dtfmt);
1747 nsmc->errc = NSMEBADFMT(-32);
1748 return 0;
1749 }
1750 if (ntohs(datp->dtrev)__bswap_16 (datp->dtrev) != revision) {
1751 sprintf(nsmc->errs, "data %s revision mismatch %d %d\n",
1752 datname, revision, datp->dtrev);
1753 nsmc->errc = NSMEBADREV(-33);
1754 return 0;
1755 }
1756
1757 /* check locally before asking nsmd2 */
1758 for (refid = 0; refid < NSMSYS_MAX_REF4096; refid++) {
1759 NSMref *refp = sysp->ref + refid;
1760 if (ntohs(refp->refdat)__bswap_16 (refp->refdat) == datid &&
1761 ntohs(refp->refnod)__bswap_16 (refp->refnod) == nsmc->nodeid) {
1762 /* 2018.0709.0438 local check newly added -- test to check if works
1763 printf("nsmlib_openmem: already opened at %p\n",
1764 (char *)memp + ntohl(datp->dtpos));
1765 */
1766 sleep(1); /* one second penalty */
1767 nsmc->errc = NSMEOPENED(-10);
1768 return 0;
1769 }
1770 }
1771
1772 /* ask nsmd2 to open */
1773 memset(&msg, 0, sizeof(msg));
1774 msg.req = NSMCMD_OPENMEM((0xff00) + 0x09);
1775 msg.node = -1;
1776 msg.npar = 1;
1777 msg.pars[0] = datid;
1778 nsmc->reqwait = msg.req;
1779 if ((nsmc->errc = nsmlib_send(nsmc, &msg)) < 0) {
1780 nsmc->reqwait = 0;
1781 return 0;
1782 }
1783 if ((ret = nsmlib_recvpar(nsmc)) < 0) {
1784 sleep(1); /* one second penalty */
1785 return 0;
1786 }
1787 if (ret != datp - sysp->dat) {
1788 sprintf(nsmc->errs, "datid mismatch %d %d", ret, (int)(datp - sysp->dat));
1789 nsmc->errc = NSMEDATID(-118);
1790 return 0;
1791 }
1792 return (char *)memp + ntohl(datp->dtpos)__bswap_32 (datp->dtpos);
1793}
1794/* -- nsmlib_flushmem ------------------------------------------------ */
1795int
1796nsmlib_flushmem(NSMcontext *nsmc, const void *ptr, int psiz)
1797{
1798 NSMmsg msg;
1799 NSMsys *sysp;
1800 size_t ppos;
1801 size_t dpos = 0;
1802 size_t dsiz = 0;
1803 int nnext;
1804 int n = 0; /* to check inf-loop */
1805 int ret;
1806
1807 if (! nsmc || nsmc->nodeid < 0 || nsmc->nodeid >= NSMSYS_MAX_NOD1024) {
1808 return NSMENOINIT(-26);
1809 }
1810
1811 if (! (sysp = nsmc->sysp) || ! nsmc->memp) {
1812 return nsmc->errc = NSMENOINIT(-26);
1813 }
1814
1815 ppos = MEMPOS(nsmc->memp, ptr)((char *)(ptr) - (char *)(nsmc->memp));
1816 if (psiz < 0 || ppos < 0 || ppos >= NSM2_MEMSIZ(4096*1024) || ppos+psiz > NSM2_MEMSIZ(4096*1024)) {
1817 DBGnsmlib_debug("flushmem(invptr): psiz=%d ppos=%d", (int)psiz, (int)ppos);
1818 return nsmc->errc = NSMEINVPTR(-36);
1819 }
1820
1821 /* linked list search (only through owned data) */
1822 nnext = (int16_t)ntohs(sysp->nod[nsmc->nodeid].noddat)__bswap_16 (sysp->nod[nsmc->nodeid].noddat);
1823 while (nnext >= 0 && nnext < NSMSYS_MAX_DAT1024) {
1824 NSMdat *datp = sysp->dat + nnext;
1825 dpos = (int32_t)ntohl(datp->dtpos)__bswap_32 (datp->dtpos);
1826 dsiz = (int16_t)ntohs(datp->dtsiz)__bswap_16 (datp->dtsiz);
1827 DBGnsmlib_debug("flushmem: ppos=%d dpos=%d ppos+psiz=%d dpos+dsiz=%d",
1828 (int)ppos, (int)dpos, (int)(ppos+psiz), (int)(dpos+dsiz));
1829 if (ppos == dpos && psiz == 0) psiz = dsiz;
1830 if (ppos >= dpos && ppos+psiz <= dpos+dsiz) break;
1831
1832 nnext = (int16_t)ntohs(datp->nnext)__bswap_16 (datp->nnext);
1833 if (++n > NSMSYS_MAX_DAT1024) nnext = -1; /* avoid inf-loop by broken nnext */
1834 }
1835 if (nnext < 0 || nnext >= NSMSYS_MAX_DAT1024) {
1836 sprintf(nsmc->errs, "data not found for pos=%d siz=%d",
1837 (int)ppos, (int)psiz);
1838 return nsmc->errc = NSMENOMEM(-31); /* end of linked list or error */
1839 }
1840
1841 /* send it */
1842 memset(&msg, 0, sizeof(msg));
1843 msg.req = NSMCMD_FLUSHMEM((0xff00) + 0x06);
1844 msg.node = -1; /* no particular destination */
1845 msg.npar = 2;
1846 msg.pars[0] = ppos;
1847 msg.pars[1] = psiz;
1848 DBGnsmlib_debug("flushmem: psiz=%d ppos=%d", (int)psiz, (int)ppos);
1849 nsmc->reqwait = msg.req;
1850 nsmc->errc = nsmlib_send(nsmc, &msg);
1851 if (nsmc->errc < 0) {
1852 nsmc->reqwait = 0;
1853 return 0;
1854 }
1855
1856 /* receive response */
1857 ret = nsmlib_recvpar(nsmc);
1858 nsmc->reqwait = 0;
1859 return ret;
1860}
1861/* -- nsmlib_allocmem ------------------------------------------------ */
1862void *
1863nsmlib_allocmem(NSMcontext *nsmc, const char *datname, const char *fmtname,
1864 int revision, float cycle)
1865{
1866 NSMmsg msg;
1867 int ret;
1868 int reqid;
1869 char fmtstr[256];
1870 char *p;
1871 NSMsys *sysp = nsmc->sysp;
1872 NSMmem *memp = nsmc->memp;
1873 int newrevision = -1;
1874
1875 DBGnsmlib_debug("allocmem 1");
1876
1877 if (! fmtname) fmtname = datname;
1878 if (! nsmc) { nsmlib_errc = NSMENOINIT(-26); return 0; }
1879 if (! datname) { nsmc->errc = NSMEINVPAR(-3); return 0; }
1880 if (revision <= 0) { nsmc->errc = NSMEINVPAR(-3); return 0; }
1881 if (strlen(datname) > NSMSYS_DNAM_SIZ31) { nsmc->errc = NSMEINVPAR(-3); return 0; }
1882
1883 NSMparse *parsep = nsmlib_parsefile(fmtname, revision, nsmlib_incpath,
1884 fmtstr, &newrevision);
1885 if (! (parsep)) {
1886 int errcode;
1887 const char *errstr = nsmlib_parseerr(&errcode);
1888 sprintf(nsmc->errs, "cannot allocate data %s, %s", datname, errstr);
1889 nsmc->errc = NSMEPARSE(-34);
1890 return 0;
1891 }
1892 nsmlib_parsefree(parsep);
1893
1894 if (revision != newrevision) {
1895 sprintf(nsmc->errs, "data revision mismatch for %s, %d != %d",
1896 datname, revision, newrevision);
1897 nsmc->errc = NSMEPARSE(-34);
1898 return 0;
1899 }
1900 if (strlen(fmtstr) + strlen(fmtname) + 1 > NSMSYS_DFMT_SIZ63) {
1901 nsmc->errc = NSMEINVPAR(-3);
1902 return 0;
1903 }
1904 if (! (p = nsmlib_malloc(strlen(datname) + strlen(fmtstr) +
1905 strlen(fmtname) + 3, "allocmem", datname))) {
1906 nsmc->errc = NSMEALLOC(-101);
1907 return 0;
1908 }
1909
1910 sprintf(p, "%s %s %s", datname, fmtstr, fmtname);
1911
1912 memset(&msg, 0, sizeof(msg));
1913 msg.req = NSMCMD_ALLOCMEM((0xff00) + 0x04);
1914 msg.node = -1;
1915 msg.npar = 2;
1916 msg.pars[0] = (cycle != 0) ? (int)(cycle * 100) : 500; /* in 10ms unit */
1917 msg.pars[1] = revision;
1918 msg.len = strlen(p) + 1;
1919 msg.datap = p;
1920 DBGnsmlib_debug("datap=%s\n", p);
1921 nsmc->reqwait = msg.req;
1922 nsmc->errc = nsmlib_send(nsmc, &msg);
1923 nsmlib_free(p);
1924 if (nsmc->errc < 0) {
1925 nsmc->reqwait = 0;
1926 return 0;
1927 }
1928 DBGnsmlib_debug("allocmem 2");
1929 ret = nsmlib_recvpar(nsmc);
1930 DBGnsmlib_debug("allocmem 3");
1931 nsmc->reqwait = 0;
1932 if (ret < 0) return 0;
1933 DBGnsmlib_debug("allocmem: ret=%d dtpos=%d\n", ret, ntohl(sysp->dat[ret].dtpos)__bswap_32 (sysp->dat[ret].dtpos));
1934 p = (char *)memp + ntohl(sysp->dat[ret].dtpos)__bswap_32 (sysp->dat[ret].dtpos);
1935 return p;
1936}
1937/* -- nsmlib_shutdown --------------------------------------------------- */
1938static int
1939nsmlib_shutdown(NSMcontext *nsmc, int ret, int port)
1940{
1941 if (! nsmlib_context && nsmlib_checkpoints) {
1942 nsmlib_free(nsmlib_checkpoints);
1943 nsmlib_checkpoints = 0;
1944 }
1945 if (nsmc->sock >= 0) {
1946 shutdown(nsmc->sock, SHUT_RDWRSHUT_RDWR);
1947 close(nsmc->sock);
1948 }
1949 if (nsmc->pipe_rd >= 0) close(nsmc->pipe_rd);
1950 if (nsmc->pipe_wr >= 0) close(nsmc->pipe_wr);
1951 if (nsmc->sysp) shmdt(nsmc->sysp);
1952 if (nsmc->memp) shmdt(nsmc->memp);
1953
1954 nsmlib_errc = ret;
1955 nsmlib_port = port;
1956 nsmlib_free(nsmc);
1957 nsmc = 0;
1958 sleep(1); /* one second penalty */
1959}
1960/* -- nsmlib_init ------------------------------------------------------- */
1961/* node is anonymous when nodename = 0 */
1962/* */
1963/* since nsm-1931 IP address for TCP connection is taken from the */
1964/* shared memory and there is no use for the "host" variable nor */
1965/* NSM2_HOST environment variable. */
1966/* */
1967/* ---------------------------------------------------------------------- */
1968NSMcontext *
1969nsmlib_init(const char *nodename, const char *unused, int port, int shmkey)
1970{
1971 NSMcontext *nsmc;
1972 int ret = 0;
1973 int i;
1974
1975 if (! nsmlib_logfp) nsmlib_logfp = stdoutstdout;
1976
1977 /* if (! nodename || strlen(nodename) > NSMSYS_NAME_SIZ) ret = -1; */
1978 if (nodename) {
1979 if (! *nodename) ret = -1;
1980 if (strlen(nodename) > NSMSYS_NAME_SIZ31) ret = -1;
1981 for (i=0; ret == 0 && nodename[i]; i++) {
1982 if (! isalnum(nodename[i])((*__ctype_b_loc ())[(int) ((nodename[i]))] & (unsigned short
int) _ISalnum)
&& nodename[i] != '_') ret = -1;
1983 }
1984 }
1985 if (ret < 0) {
1986 nsmlib_errc = NSMENODENAME(-11);
1987 sleep(1); /* one second penalty */
1988 return 0;
1989 }
1990
1991 if (! (nsmc = nsmlib_malloc(sizeof(*nsmc), "init", "nsmc"))) {
1992 nsmlib_errc = NSMEALLOC(-101);
1993 sleep(1); /* one second penalty */
1994 return 0;
1995 }
1996
1997 /* -- set up nsm context -- */
1998 memset(nsmc, 0, sizeof(*nsmc));
1999 strcpy(nsmc->nodename, nodename ? nodename : "(anonymous)");
2000 nsmc->pipe_rd = -1;
2001 nsmc->pipe_wr = -1;
2002 nsmc->sock = -1;
2003
2004 /* -- environment variables -- */
2005 if (! port) port = nsmlib_atoi(getenv(NSMENV_PORT"NSM2_PORT"), NSM2_PORT8120);
2006
2007 /* -- shared memory initialization -- */
2008 if (ret == 0) ret = nsmlib_initshm(nsmc, shmkey, port);
2009
2010 /* -- network initialization -- */
2011 if (ret == 0) ret = nsmlib_initnet(nsmc, 0, port);
2012
2013 /* -- signal handler initialization -- */
2014 if (ret == 0) ret = nsmlib_initsig(nsmc);
2015
2016 /* -- client initialization -- */
2017 if (ret == 0) ret = nsmlib_initcli(nsmc, nodename);
2018
2019 /* -- nsm context -- */
2020 if (ret == 0) {
2021 nsmc->next = nsmlib_context;
2022 nsmlib_context = nsmc; /* -- insert at the top -- */
2023 } else {
2024 nsmlib_shutdown(nsmc, ret, port);
2025 nsmc = 0;
2026 }
2027
2028 return nsmc;
2029}
2030/* -- nsmlib_term ------------------------------------------------------- */
2031int
2032nsmlib_term(NSMcontext *nsmc)
2033{
2034 NSMcontext *c = nsmlib_context;
2035 if (! nsmc) return 0;
2036 if (! c) return NSMEUNEXPECTED(-119);
2037
2038 /* -- remove nsmc from linked-list of contexts -- */
2039 if (nsmc == c) {
2040 nsmlib_context = c->next;
2041 } else {
2042 int found = 0;
2043 while (c->next) {
2044 if (nsmc == c->next) {
2045 c->next = c->next->next;
2046 found = 1;
2047 break;
2048 }
2049 c = c->next;
2050 }
2051 if (! found) return NSMEUNEXPECTED(-119);
2052 }
2053
2054 nsmlib_shutdown(nsmc, 0, 0);
2055 return 0;
2056}
2057/* -- (emacs outline mode setup) ------------------------------------- */
2058/*
2059// Local Variables: ***
2060// mode:outline-minor ***
2061// outline-regexp:"^/\\* --[+ ]" ***
2062// End: ***
2063*/