BRL-CAD
pkg.c
Go to the documentation of this file.
1 /* P K G . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 /** @file libpkg/pkg.c
21  *
22  * LIBPKG provides routines to manage multiplexing and de-multiplexing
23  * synchronous and asynchronous messages across stream connections.
24  *
25  */
26 
27 #include "common.h"
28 
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <ctype.h> /* used by inet_addr() routine, below */
32 #include <time.h>
33 #include <string.h>
34 
35 #ifdef HAVE_SYS_PARAM_H
36 # include <sys/param.h>
37 #endif
38 #ifdef HAVE_SYS_TIME_H
39 # include <sys/time.h>
40 #endif
41 #ifdef HAVE_SYS_TYPES_H
42 # include <sys/types.h>
43 #endif
44 #ifdef HAVE_SYS_STAT_H
45 # include <sys/stat.h>
46 #endif
47 
48 #ifdef HAVE_WINSOCK_H
49 # include <process.h>
50 # include <winsock.h>
51 #else
52 # include <sys/socket.h>
53 # include <sys/ioctl.h> /* for FIONBIO */
54 # include <netinet/in.h> /* for htons(), etc. */
55 # include <netdb.h>
56 # include <netinet/tcp.h> /* for TCP_NODELAY sockopt */
57 # include <arpa/inet.h> /* for inet_addr() */
58 # undef LITTLE_ENDIAN /* defined in netinet/{ip.h, tcp.h} */
59 #endif
60 
61 #ifdef HAVE_UNISTD_H
62 # include <unistd.h>
63 #else
64 # include <windows.h>
65 # include <io.h>
66 # include <fcntl.h>
67 #endif
68 
69 
70 /* Not all systems with "BSD Networking" include UNIX Domain sockets */
71 #ifdef HAVE_SYS_UN_H
72 # include <sys/un.h> /* UNIX Domain sockets */
73 #endif
74 
75 #ifdef n16
76 /* Encore multimax */
77 # include <sys/h/socket.h>
78 # include <sys/ioctl.h>
79 # include <sys/netinet/in.h>
80 # include <sys/aux/netdb.h>
81 # include <sys/netinet/tcp.h>
82 #endif
83 
84 #ifdef HAVE_WRITEV
85 # include <sys/uio.h> /* for struct iovec (writev) */
86 #endif
87 
88 #include <errno.h>
89 #include "pkg.h"
90 
91 
92 /* compatibility for pedantic bug/limitation in gcc 4.6.2, need to
93  * mark macros as extensions else they may emit "ISO C forbids
94  * braced-groups within expressions" warnings.
95  */
96 #if defined(__extension__) && GCC_PREREQ(4, 6) && !GCC_PREREQ(4, 7)
97 
98 # if defined(FD_SET) && defined(__FD_SET)
99 # undef FD_SET
100 # define FD_SET(x, y) __extension__ __FD_SET((x), (y))
101 # endif
102 
103 # if defined(FD_ISSET) && defined(__FD_ISSET)
104 # undef FD_ISSET
105 # define FD_ISSET(x, y) __extension__ __FD_ISSET((x), (y))
106 # endif
107 
108 #endif /* __extension__ */
109 
110 
111 /* XXX is this really necessary? the _read() and _write()
112  * compatibility macros should take care of this.
113  */
114 #ifdef HAVE_WINSOCK_H
115 # define PKG_READ(d, buf, nbytes) recv((d), (buf), (int)(nbytes), 0)
116 # define PKG_SEND(d, buf, nbytes) send((d), (buf), (int)(nbytes), 0)
117 #else
118 # define PKG_READ(d, buf, nbytes) read((d), (buf), (nbytes))
119 # define PKG_SEND(d, buf, nbytes) write((d), (buf), (nbytes))
120 #endif
121 
122 #define PKG_CK(p) { \
123  if (p==PKC_NULL||p->pkc_magic!=PKG_MAGIC) { \
124  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "%s: bad pointer %p line %d\n", __FILE__, (void *)(p), __LINE__); \
125  _pkg_errlog(_pkg_errbuf);abort(); \
126  } \
127 }
128 
129 #define MAXQLEN 512 /* largest packet we will queue on stream */
130 
131 /* A macro for logging a string message when the debug file is open */
132 #ifndef NO_DEBUG_CHECKING
133 # define DMSG(s) if (_pkg_debug) { _pkg_timestamp(); fprintf(_pkg_debug, "%s", s); fflush(_pkg_debug); }
134 #else
135 # define DMSG(s) /**/
136 #endif
137 
138 #if !defined(_WIN32) || defined(__CYGWIN__)
139 #include <errno.h>
140 #endif
141 
142 int pkg_nochecking = 0; /* set to disable extra checking for input */
143 int pkg_permport = 0; /* TCP port that pkg_permserver() is listening on XXX */
144 
145 #define MAX_PKG_ERRBUF_SIZE 80
146 static char _pkg_errbuf[MAX_PKG_ERRBUF_SIZE] = {0};
147 static FILE *_pkg_debug = (FILE*)NULL;
148 
149 
150 /*
151  * Routines to insert/extract short/long's into char arrays,
152  * independent of machine byte order and word-alignment.
153  */
154 
155 
156 unsigned short
157 pkg_gshort(char *buf)
158 {
159  unsigned char *p = (unsigned char *)buf;
160  unsigned short u;
161 
162  u = *p++ << 8;
163  return (unsigned short)(u | *p);
164 }
165 
166 
167 unsigned long
168 pkg_glong(char *buf)
169 {
170  unsigned char *p = (unsigned char *)buf;
171  unsigned long u;
172 
173  u = *p++; u <<= 8;
174  u |= *p++; u <<= 8;
175  u |= *p++; u <<= 8;
176  return (u | *p);
177 }
178 
179 
180 char *
181 pkg_pshort(char *buf, unsigned short s)
182 {
183  buf[1] = s;
184  buf[0] = s >> 8;
185  return (char *)buf+2;
186 }
187 
188 
189 char *
190 pkg_plong(char *buf, unsigned long l)
191 {
192  buf[3] = l;
193  buf[2] = (l >>= 8);
194  buf[1] = (l >>= 8);
195  buf[0] = l >> 8;
196  return (char *)buf+4;
197 }
198 
199 
200 /**
201  * Output a timestamp to the log, suitable for starting each line
202  * with.
203  *
204  * This is a private implementation function.
205  */
206 static void
207 _pkg_timestamp(void)
208 {
209  time_t now;
210  struct tm *tmp;
211  int pid;
212 
213  if (!_pkg_debug)
214  return;
215  (void)time(&now);
216  tmp = localtime(&now);
217 
218  /* avoid libbu dependency */
219 #ifdef HAVE_UNISTD_H
220  pid = (int)getpid();
221 #else
222  pid = (int)GetCurrentProcessId();
223 #endif
224 
225  fprintf(_pkg_debug, "%2.2d/%2.2d %2.2d:%2.2d:%2.2d [%5d] ",
226  tmp->tm_mon+1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec, pid);
227  /* Don't fflush here, wait for rest of line */
228 }
229 
230 
231 /**
232  * Default error logger. Writes to stderr.
233  *
234  * This is a private implementation function.
235  */
236 static void
237 _pkg_errlog(const char *s)
238 {
239  if (_pkg_debug) {
240  _pkg_timestamp();
241  fputs(s, _pkg_debug);
242  fflush(_pkg_debug);
243  }
244  fputs(s, stderr);
245 }
246 
247 
248 /**
249  * Produce a perror on the error logging output.
250  *
251  * This is a private implementation function.
252  */
253 static void
254 _pkg_perror(void (*errlog)(const char *msg), const char *s)
255 {
256  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "%s: ", s);
257 
258  if (errno >= 0 || strlen(_pkg_errbuf) >= MAX_PKG_ERRBUF_SIZE) {
259  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "%s: errno=%d\n", s, errno);
260  errlog(_pkg_errbuf);
261  return;
262  }
263 
264  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "%s: %s\n", s, strerror(errno));
265  errlog(_pkg_errbuf);
266 }
267 
268 
269 /**
270  * Malloc and initialize a pkg_conn structure. We have already
271  * connected to a client or server on the given file descriptor.
272  *
273  * Returns >0 ptr to pkg_conn block of new connection or PKC_ERROR
274  * fatal error.
275  *
276  * This is a private implementation function.
277  */
278 static
279 struct pkg_conn *
280 _pkg_makeconn(int fd, const struct pkg_switch *switchp, void (*errlog)(const char *msg))
281 {
282  struct pkg_conn *pc;
283 
284  if (_pkg_debug) {
285  _pkg_timestamp();
286  fprintf(_pkg_debug,
287  "_pkg_makeconn(fd=%d, switchp=%p, errlog=x%llx)\n",
288  fd, (void *)switchp, (unsigned long long)((uintptr_t)errlog));
289  fflush(_pkg_debug);
290  }
291 
292  /* Check for default error handler */
293  if (errlog == NULL)
294  errlog = _pkg_errlog;
295 
296  if ((pc = (struct pkg_conn *)malloc(sizeof(struct pkg_conn)))==PKC_NULL) {
297  _pkg_perror(errlog, "_pkg_makeconn: malloc failure\n");
298  return PKC_ERROR;
299  }
300  memset((char *)pc, 0, sizeof(struct pkg_conn));
301  pc->pkc_magic = PKG_MAGIC;
302  pc->pkc_fd = fd;
303  pc->pkc_switch = switchp;
304  pc->pkc_errlog = errlog;
305  pc->pkc_left = -1;
306  pc->pkc_buf = (char *)0;
307  pc->pkc_curpos = (char *)0;
308  pc->pkc_strpos = 0;
309  pc->pkc_incur = pc->pkc_inend = 0;
310  return pc;
311 }
312 
313 
314 /**
315  * This is a private implementation function.
316  */
317 static void
318 _pkg_ck_debug(void)
319 {
320  char *place;
321  char buf[128] = {0};
322  struct stat sbuf;
323 
324  if (_pkg_debug)
325  return;
326  if ((place = (char *)getenv("LIB_PKG_DEBUG")) == (char *)0) {
327  snprintf(buf, 128, "/tmp/pkg.log");
328  place = buf;
329  }
330  /* Named file must exist and be writeable */
331  if ((_pkg_debug = fopen(place, "a")) == NULL)
332  return;
333  if (fstat(fileno(_pkg_debug), &sbuf) < 0)
334  return;
335 
336  /* Log version number of this code */
337  _pkg_timestamp();
338  fprintf(_pkg_debug, "_pkg_ck_debug %s\n", pkg_version());
339 }
340 
341 
342 struct pkg_conn *
343 pkg_open(const char *host, const char *service, const char *protocol, const char *uname, const char *UNUSED(passwd), const struct pkg_switch *switchp, void (*errlog)(const char *msg))
344 {
345 #ifdef HAVE_WINSOCK_H
346  LPHOSTENT lpHostEntry;
347  SOCKET netfd;
348  SOCKADDR_IN saServer;
349  WORD wVersionRequested; /* initialize Windows socket networking, increment reference count */
350  WSADATA wsaData;
351 #else
352  struct sockaddr_in sinme; /* Client */
353  struct sockaddr_in sinhim; /* Server */
354 #ifdef HAVE_SYS_UN_H
355  struct sockaddr_un sunhim; /* Server, UNIX Domain */
356 #endif
357  struct hostent *hp;
358  int netfd;
359  struct sockaddr *addr; /* UNIX or INET addr */
360  size_t addrlen; /* length of address */
361 #endif
362 
363  _pkg_ck_debug();
364  if (_pkg_debug) {
365  _pkg_timestamp();
366  fprintf(_pkg_debug,
367  "pkg_open(%s, %s, %s, %s, (passwd), switchp=%p, errlog=x%llx)\n",
368  host, service, protocol, uname,
369  (void *)switchp, (unsigned long long)((uintptr_t)errlog));
370  fflush(_pkg_debug);
371  }
372 
373  /* Check for default error handler */
374  if (errlog == NULL)
375  errlog = _pkg_errlog;
376 
377 #ifdef HAVE_WINSOCK_H
378  wVersionRequested = MAKEWORD(1, 1);
379  if (WSAStartup(wVersionRequested, &wsaData) != 0) {
380  _pkg_perror(errlog, "pkg_open: could not find a usable WinSock DLL");
381  return PKC_ERROR;
382  }
383 
384  if ((lpHostEntry = gethostbyname(host)) == NULL) {
385  _pkg_perror(errlog, "pkg_open: gethostbyname");
386  return PKC_ERROR;
387  }
388 
389  if ((netfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
390  _pkg_perror(errlog, "pkg_open: socket");
391  return PKC_ERROR;
392  }
393 
394  memset((char *)&saServer, 0, sizeof(saServer));
395 
396  if (atoi(service) > 0) {
397  saServer.sin_port = htons((unsigned short)atoi(service));
398  } else {
399  struct servent *sp;
400  if ((sp = getservbyname(service, "tcp")) == NULL) {
401  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_open(%s, %s): unknown service\n",
402  host, service);
403  errlog(_pkg_errbuf);
404  return PKC_ERROR;
405  }
406  saServer.sin_port = sp->s_port;
407  }
408  saServer.sin_family = AF_INET;
409  saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list);
410 
411  if (connect(netfd, (LPSOCKADDR)&saServer, sizeof(struct sockaddr)) == SOCKET_ERROR) {
412  _pkg_perror(errlog, "pkg_open: client connect");
413  closesocket(netfd);
414  return PKC_ERROR;
415  }
416 
417  return _pkg_makeconn(netfd, switchp, errlog);
418 #else
419  memset((char *)&sinhim, 0, sizeof(sinhim));
420  memset((char *)&sinme, 0, sizeof(sinme));
421 
422 #ifdef HAVE_SYS_UN_H
423  if (host == NULL || strlen(host) == 0 || strcmp(host, "unix")==0) {
424  /* UNIX Domain socket, port = pathname */
425  sunhim.sun_family = AF_UNIX;
426  strncpy(sunhim.sun_path, service, sizeof(sunhim.sun_path));
427  sunhim.sun_path[sizeof(sunhim.sun_path) - 1] = '\0';
428  addr = (struct sockaddr *) &sunhim;
429  addrlen = strlen(sunhim.sun_path) + 2;
430  goto ready;
431  }
432 #endif
433 
434  /* Determine port for service */
435  if (atoi(service) > 0) {
436  sinhim.sin_port = htons((unsigned short)atoi(service));
437  } else {
438  struct servent *sp;
439  if ((sp = getservbyname(service, "tcp")) == NULL) {
440  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_open(%s, %s): unknown service\n",
441  host, service);
442  errlog(_pkg_errbuf);
443  return PKC_ERROR;
444  }
445  sinhim.sin_port = sp->s_port;
446  }
447 
448  /* Get InterNet address */
449  if (atoi(host) > 0) {
450  /* Numeric */
451  sinhim.sin_family = AF_INET;
452  sinhim.sin_addr.s_addr = inet_addr(host);
453  } else {
454  if ((hp = gethostbyname(host)) == NULL) {
455  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_open(%s, %s): unknown host\n",
456  host, service);
457  errlog(_pkg_errbuf);
458  return PKC_ERROR;
459  }
460  sinhim.sin_family = hp->h_addrtype;
461  memcpy((char *)&sinhim.sin_addr, hp->h_addr_list[0], (size_t)hp->h_length);
462  }
463  addr = (struct sockaddr *) &sinhim;
464  addrlen = sizeof(struct sockaddr_in);
465 
466 #ifdef HAVE_SYS_UN_H
467  ready:
468 #endif
469 
470  if ((netfd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) {
471  _pkg_perror(errlog, "pkg_open: client socket");
472  return PKC_ERROR;
473  }
474 
475 #if defined(TCP_NODELAY)
476  /* SunOS 3.x defines it but doesn't support it! */
477  if (addr->sa_family == AF_INET) {
478  int on = 1;
479  if (setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY,
480  (char *)&on, sizeof(on)) < 0) {
481  _pkg_perror(errlog, "pkg_open: setsockopt TCP_NODELAY");
482  }
483  }
484 #endif
485 
486  if (connect(netfd, addr, addrlen) < 0) {
487  _pkg_perror(errlog, "pkg_open: client connect");
488 #ifdef HAVE_WINSOCK_H
489  (void)closesocket(netfd);
490 #else
491  (void)close(netfd);
492 #endif
493  return PKC_ERROR;
494  }
495  return _pkg_makeconn(netfd, switchp, errlog);
496 #endif
497 }
498 
499 
500 struct pkg_conn *
501 pkg_transerver(const struct pkg_switch *switchp, void (*errlog)(const char *))
502 {
503  struct pkg_conn *conn;
504 
505  _pkg_ck_debug();
506  if (_pkg_debug) {
507  _pkg_timestamp();
508  fprintf(_pkg_debug,
509  "pkg_transerver(switchp=%p, errlog=x%llx)\n",
510  (void *)switchp, (unsigned long long)((uintptr_t)errlog));
511  fflush(_pkg_debug);
512  }
513 
514  /*
515  * XXX - Somehow the system has to know what connection was
516  * accepted, its protocol, etc. For UNIX/inetd we use stdin.
517  */
518  conn = _pkg_makeconn(STDIN_FILENO, switchp, errlog);
519  return conn;
520 }
521 
522 
523 /**
524  * This is a private implementation function.
525  */
526 static int
527 _pkg_permserver_impl(struct in_addr iface, const char *service, const char *protocol, int backlog, void (*errlog)(const char *msg))
528 {
529  struct servent *sp;
530  int pkg_listenfd;
531 #ifdef HAVE_WINSOCK_H
532  SOCKADDR_IN saServer;
533  WORD wVersionRequested; /* initialize Windows socket networking, increment reference count */
534  WSADATA wsaData;
535 #else
536  struct sockaddr_in sinme;
537 # ifdef HAVE_SYS_UN_H
538  struct sockaddr_un sunme; /* UNIX Domain */
539 # endif
540  struct sockaddr *addr; /* UNIX or INET addr */
541  size_t addrlen; /* length of address */
542  int on = 1;
543 #endif
544 
545  if (service == NULL)
546  return -1;
547 
548  _pkg_ck_debug();
549  if (_pkg_debug) {
550  _pkg_timestamp();
551  fprintf(_pkg_debug,
552  "pkg_permserver(%s, %s, backlog=%d, errlog=x%llx\n",
553  service, protocol, backlog, (unsigned long long)((uintptr_t)errlog));
554  fflush(_pkg_debug);
555  }
556 
557  /* Check for default error handler */
558  if (errlog == NULL)
559  errlog = _pkg_errlog;
560 
561 #ifdef HAVE_WINSOCK_H
562  wVersionRequested = MAKEWORD(1, 1);
563  if (WSAStartup(wVersionRequested, &wsaData) != 0) {
564  _pkg_perror(errlog, "pkg_open: could not find a usable WinSock DLL");
565  return (int)PKC_ERROR;
566  }
567 
568  memset((char *)&saServer, 0, sizeof(saServer));
569 
570  if (atoi(service) > 0) {
571  saServer.sin_port = htons((unsigned short)atoi(service));
572  } else {
573  if ((sp = getservbyname(service, "tcp")) == NULL) {
574  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
575  "pkg_permserver(%s, %d): unknown service\n",
576  service, backlog);
577  errlog(_pkg_errbuf);
578  return (int)PKC_ERROR;
579  }
580  saServer.sin_port = sp->s_port;
581  }
582 
583  if ((pkg_listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
584  _pkg_perror(errlog, "pkg_permserver: socket");
585  return (int)PKC_ERROR;
586  }
587 
588  saServer.sin_family = AF_INET;
589  saServer.sin_addr = iface;
590 
591  if (bind(pkg_listenfd, (LPSOCKADDR)&saServer, sizeof(struct sockaddr)) == SOCKET_ERROR) {
592  _pkg_perror(errlog, "pkg_permserver: bind");
593  closesocket(pkg_listenfd);
594 
595  return (int)PKC_ERROR;
596  }
597 
598  if (backlog > 5)
599  backlog = 5;
600 
601  if (listen(pkg_listenfd, backlog) == SOCKET_ERROR) {
602  _pkg_perror(errlog, "pkg_permserver: listen");
603  closesocket(pkg_listenfd);
604 
605  return (int)(PKC_ERROR);
606  }
607 
608  return pkg_listenfd;
609 
610 #else /* !HAVE_WINSOCK_H */
611 
612  memset((char *)&sinme, 0, sizeof(sinme));
613 
614 # ifdef HAVE_SYS_UN_H
615  if (service[0] == '/') {
616  /* UNIX Domain socket */
617  strncpy(sunme.sun_path, service, sizeof(sunme.sun_path));
618  sunme.sun_path[sizeof(sunme.sun_path) - 1] = '\0';
619  sunme.sun_family = AF_UNIX;
620  addr = (struct sockaddr *) &sunme;
621  addrlen = strlen(sunme.sun_path) + 2;
622  goto ready;
623  }
624 # endif /* HAVE_SYS_UN_H */
625  /* Determine port for service */
626  if (atoi(service) > 0) {
627  sinme.sin_port = htons((unsigned short)atoi(service));
628  } else {
629  if ((sp = getservbyname(service, "tcp")) == NULL) {
630  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
631  "pkg_permserver(%s, %d): unknown service\n",
632  service, backlog);
633  errlog(_pkg_errbuf);
634  return -1;
635  }
636  sinme.sin_port = sp->s_port;
637  }
638  pkg_permport = sinme.sin_port; /* XXX -- needs formal I/F */
639  sinme.sin_family = AF_INET;
640  sinme.sin_addr = iface;
641  addr = (struct sockaddr *) &sinme;
642  addrlen = sizeof(struct sockaddr_in);
643 
644 # ifdef HAVE_SYS_UN_H
645  ready:
646 # endif
647 
648  if ((pkg_listenfd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) {
649  _pkg_perror(errlog, "pkg_permserver: socket");
650  return -1;
651  }
652 
653  if (addr->sa_family == AF_INET) {
654  if (setsockopt(pkg_listenfd, SOL_SOCKET, SO_REUSEADDR,
655  (char *)&on, sizeof(on)) < 0) {
656  _pkg_perror(errlog, "pkg_permserver: setsockopt SO_REUSEADDR");
657  }
658 # if defined(TCP_NODELAY)
659  /* SunOS 3.x defines it but doesn't support it! */
660  if (setsockopt(pkg_listenfd, IPPROTO_TCP, TCP_NODELAY,
661  (char *)&on, sizeof(on)) < 0) {
662  _pkg_perror(errlog, "pkg_permserver: setsockopt TCP_NODELAY");
663  }
664 # endif
665  }
666 
667  if (bind(pkg_listenfd, addr, addrlen) < 0) {
668  _pkg_perror(errlog, "pkg_permserver: bind");
669 # ifdef HAVE_WINSOCK_H
670  (void)closesocket(pkg_listenfd);
671 # else
672  close(pkg_listenfd);
673 # endif
674  return -1;
675  }
676 
677  if (backlog > 5) backlog = 5;
678  if (listen(pkg_listenfd, backlog) < 0) {
679  _pkg_perror(errlog, "pkg_permserver: listen");
680 # ifdef HAVE_WINSOCK_H
681  (void)closesocket(pkg_listenfd);
682 # else
683  close(pkg_listenfd);
684 # endif
685  return -1;
686  }
687  return pkg_listenfd;
688 #endif /* HAVE_WINSOCK_H */
689 }
690 
691 
692 int
693 pkg_permserver(const char *service, const char *protocol, int backlog, void (*errlog)(const char *msg))
694 {
695  struct in_addr iface;
696  iface.s_addr = INADDR_ANY;
697  return _pkg_permserver_impl(iface, service, protocol, backlog, errlog);
698 }
699 
700 
701 int
702 pkg_permserver_ip(const char *ipOrHostname, const char *service, const char *protocol, int backlog, void (*errlog)(const char *msg))
703 {
704  struct hostent* host;
705  struct in_addr iface;
706  /* if ipOrHostname starts with a number, it's an IP */
707  if (ipOrHostname) {
708  if (ipOrHostname[0] >= '0' && ipOrHostname[0] <= '9') {
709  iface.s_addr = inet_addr(ipOrHostname);
710  } else {
711  /* XXX gethostbyname is deprecated on Windows */
712  host = gethostbyname(ipOrHostname);
713  iface = *(struct in_addr*)host->h_addr_list[0];
714  }
715  return _pkg_permserver_impl(iface, service, protocol, backlog, errlog);
716  } else {
717  _pkg_perror(errlog, "pkg: ipOrHostname cannot be NULL");
718  return -1;
719  }
720 }
721 
722 
723 struct pkg_conn *
724 pkg_getclient(int fd, const struct pkg_switch *switchp, void (*errlog)(const char *msg), int nodelay)
725 {
726  int s2;
727 #ifdef HAVE_WINSOCK_H
728  WORD wVersionRequested; /* initialize Windows socket networking, increment reference count */
729  WSADATA wsaData;
730 #else
731  struct sockaddr_in from;
732  unsigned int fromlen = sizeof (from);
733 #endif
734 
735  if (_pkg_debug) {
736  _pkg_timestamp();
737  fprintf(_pkg_debug,
738  "pkg_getclient(fd=%d, switchp=%p, errlog=x%llx, nodelay=%d)\n",
739  fd, (void *)switchp, (unsigned long long)((uintptr_t)errlog), nodelay);
740  fflush(_pkg_debug);
741  }
742 
743  /* Check for default error handler */
744  if (errlog == NULL)
745  errlog = _pkg_errlog;
746 
747 #ifdef FIONBIO
748  if (nodelay) {
749  int onoff;
750  onoff = 1;
751  if (ioctl(fd, FIONBIO, &onoff) < 0)
752  _pkg_perror(errlog, "pkg_getclient: FIONBIO 1");
753  }
754 #endif
755 
756 #ifdef HAVE_WINSOCK_H
757  wVersionRequested = MAKEWORD(1, 1);
758  if (WSAStartup(wVersionRequested, &wsaData) != 0) {
759  _pkg_perror(errlog, "pkg_open: could not find a usable WinSock DLL");
760  return PKC_ERROR;
761  }
762 #endif
763 
764  do {
765 #ifdef HAVE_WINSOCK_H
766  s2 = accept(fd, (struct sockaddr *)NULL, NULL);
767 #else
768  s2 = accept(fd, (struct sockaddr *)&from, &fromlen);
769 #endif
770  if (s2 < 0) {
771  if (errno == EINTR)
772  continue;
773 #ifdef HAVE_WINSOCK_H
774  if (errno == WSAEWOULDBLOCK)
775  return PKC_NULL;
776 #else
777  if (errno == EWOULDBLOCK)
778  return PKC_NULL;
779 #endif
780  _pkg_perror(errlog, "pkg_getclient: accept");
781  return PKC_ERROR;
782  }
783  } while (s2 < 0);
784 #ifdef FIONBIO
785  if (nodelay) {
786  int onoff2;
787  onoff2 = 0;
788  if (ioctl(fd, FIONBIO, &onoff2) < 0)
789  _pkg_perror(errlog, "pkg_getclient: FIONBIO 2");
790  if (ioctl(s2, FIONBIO, &onoff2) < 0)
791  _pkg_perror(errlog, "pkg_getclient: FIONBIO 3");
792  }
793 #endif
794 
795  return _pkg_makeconn(s2, switchp, errlog);
796 }
797 
798 
799 void
800 pkg_close(struct pkg_conn *pc)
801 {
802  PKG_CK(pc);
803  if (_pkg_debug) {
804  _pkg_timestamp();
805  fprintf(_pkg_debug,
806  "pkg_close(pc=%p) fd=%d\n",
807  (void *)pc, pc->pkc_fd);
808  fflush(_pkg_debug);
809  }
810 
811  /* Flush any queued stream output first. */
812  if (pc->pkc_strpos > 0) {
813  (void)pkg_flush(pc);
814  }
815 
816  if (pc->pkc_buf != (char *)0) {
817  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_close(%p): partial input pkg discarded, buf=%p\n",
818  (void *)pc, (void *)(pc->pkc_buf));
819  pc->pkc_errlog(_pkg_errbuf);
820  (void)free(pc->pkc_buf);
821  }
822  if (pc->pkc_inbuf != (char *)0) {
823  (void)free(pc->pkc_inbuf);
824  pc->pkc_inbuf = (char *)0;
825  pc->pkc_inlen = 0;
826  }
827 #ifdef HAVE_WINSOCK_H
828  (void)closesocket(pc->pkc_fd);
829 #else
830  (void)close(pc->pkc_fd);
831 #endif
832 
833 #ifdef HAVE_WINSOCK_H
834  /* deinitialize Windows socket networking, decrements ref count */
835  WSACleanup();
836 #endif
837 
838  pc->pkc_fd = -1; /* safety */
839  pc->pkc_buf = (char *)0; /* safety */
840  pc->pkc_magic = 0; /* safety */
841  (void)free((char *)pc);
842 }
843 
844 
845 /**
846  * A functional replacement for bu_mread() through the first level
847  * input buffer.
848  *
849  * This will block if the required number of bytes are not available.
850  * The number of bytes actually transferred is returned.
851  *
852  * This is a private implementation function.
853  */
854 static size_t
855 _pkg_inget(struct pkg_conn *pc, char *buf, size_t count)
856 {
857  size_t len = 0;
858  int todo = (int)count;
859 
860  while (todo > 0) {
861 
862  while ((len = pc->pkc_inend - pc->pkc_incur) <= 0) {
863  /* This can block */
864  if (pkg_suckin(pc) < 1)
865  return count - todo;
866  }
867  /* Input Buffer has some data in it, move to caller's buffer */
868  if ((int)len > todo) len = todo;
869  memcpy(buf, &pc->pkc_inbuf[pc->pkc_incur], len);
870  pc->pkc_incur += (int)len;
871  buf += len;
872  todo -= (int)len;
873  }
874  return count;
875 }
876 
877 
878 /**
879  * This routine is called whenever it is necessary to see if there is
880  * more input that can be read. If input is available, it is read
881  * into pkc_inbuf[]. If nodelay is set, poll without waiting.
882  *
883  * This is a private implementation function.
884  */
885 static void
886 _pkg_checkin(struct pkg_conn *pc, int nodelay)
887 {
888  struct timeval tv;
889  fd_set bits;
890  ssize_t i;
891  unsigned int j;
892 
893  /* Check socket for unexpected input */
894  tv.tv_sec = 0;
895  if (nodelay)
896  tv.tv_usec = 0; /* poll -- no waiting */
897  else
898  tv.tv_usec = 20000; /* 20 ms */
899 
900  FD_ZERO(&bits);
901  FD_SET(pc->pkc_fd, &bits);
902  i = select(pc->pkc_fd+1, &bits, (fd_set *)0, (fd_set *)0, &tv);
903  if (_pkg_debug) {
904  _pkg_timestamp();
905  fprintf(_pkg_debug,
906  "_pkg_checkin: select on fd %d returned %ld\n",
907  pc->pkc_fd,
908  (long int)i);
909  fflush(_pkg_debug);
910  }
911  if (i > 0) {
912  for (j = 0; j < FD_SETSIZE; j++)
913  if (FD_ISSET(j, &bits)) break;
914 
915  if (j < FD_SETSIZE) {
916  /* Some fd is ready for I/O */
917  (void)pkg_suckin(pc);
918  } else {
919  /* Odd condition, bits! */
920  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
921  "_pkg_checkin: select returned %ld, bits=0\n",
922  (long int)i);
923  (pc->pkc_errlog)(_pkg_errbuf);
924  }
925  } else if (i < 0) {
926  /* Error condition */
927  if (errno != EINTR && errno != EBADF)
928  _pkg_perror(pc->pkc_errlog, "_pkg_checkin: select");
929  }
930 }
931 
932 
933 int
934 pkg_send(int type, const char *buf, size_t len, struct pkg_conn *pc)
935 {
936 #ifdef HAVE_WRITEV
937  static struct iovec cmdvec[2];
938 #endif
939  static struct pkg_header hdr;
940  ssize_t i;
941 
942  PKG_CK(pc);
943 
944  if (_pkg_debug) {
945  _pkg_timestamp();
946  fprintf(_pkg_debug,
947  "pkg_send(type=%d, buf=%p, len=%llu, pc=%p)\n",
948  type, (void *)buf, (unsigned long long)len, (void *)pc);
949  fflush(_pkg_debug);
950  }
951 
952  /* Check for any pending input, no delay */
953  /* Input may be read, but not acted upon, to prevent deep recursion */
954  _pkg_checkin(pc, 1);
955 
956  /* Flush any queued stream output first. */
957  if (pc->pkc_strpos > 0) {
958  /*
959  * Buffered output is already queued, and needs to be flushed
960  * before sending this one. If this pkg will also fit in the
961  * buffer, add it to the stream, and then send the whole thing
962  * with one flush. Otherwise, just flush, and proceed.
963  */
964  if (len <= MAXQLEN && len <= PKG_STREAMLEN -
965  sizeof(struct pkg_header) - pc->pkc_strpos) {
966  (void)pkg_stream(type, buf, len, pc);
967  return (pkg_flush(pc) < 0) ? -1 : (int)len;
968  }
969  if (pkg_flush(pc) < 0)
970  return -1; /* assumes 2nd write would fail too */
971  }
972 
973  pkg_pshort((char *)hdr.pkh_magic, (unsigned long)PKG_MAGIC);
974  pkg_pshort((char *)hdr.pkh_type, (unsigned short)type); /* should see if valid type */
975  pkg_plong((char *)hdr.pkh_len, (unsigned long)len);
976 
977 #ifdef HAVE_WRITEV
978  cmdvec[0].iov_base = (void *)&hdr;
979  cmdvec[0].iov_len = sizeof(hdr);
980  cmdvec[1].iov_base = (void *)buf;
981  cmdvec[1].iov_len = len;
982 
983  /*
984  * TODO: set this FD to NONBIO. If not all output got sent, loop
985  * in select() waiting for capacity to go out, and reading input
986  * as well. Prevents deadlocking.
987  */
988  i = writev(pc->pkc_fd, cmdvec, (len>0)?2:1);
989  if (i != (ssize_t)(len+sizeof(hdr))) {
990  if (i < 0) {
991  _pkg_perror(pc->pkc_errlog, "pkg_send: writev");
992  return -1;
993  }
994  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_send of %llu+%llu, wrote %d\n",
995  (unsigned long long)sizeof(hdr), (unsigned long long)len, (int)i);
996  (pc->pkc_errlog)(_pkg_errbuf);
997  return i-sizeof(hdr); /* amount of user data sent */
998  }
999 #else
1000  /*
1001  * On the assumption that buffer copying is less expensive than
1002  * having this transmission broken into two network packets (with
1003  * TCP, each with a "push" bit set), merge it all into one buffer
1004  * here, unless size is enormous.
1005  */
1006  if (len + sizeof(hdr) <= 16*1024) {
1007  char tbuf[16*1024] = {0};
1008 
1009  memcpy(tbuf, (char *)&hdr, sizeof(hdr));
1010  if (len > 0)
1011  memcpy(tbuf+sizeof(hdr), buf, len);
1012 
1013  i = PKG_SEND(pc->pkc_fd, tbuf, len+sizeof(hdr));
1014  if ((size_t)i != len+sizeof(hdr)) {
1015  if (i < 0) {
1016  if (errno == EBADF)
1017  return -1;
1018  _pkg_perror(pc->pkc_errlog, "pkg_send: tbuf write");
1019  return -1;
1020  }
1021  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_send of %d, wrote %d\n",
1022  len, i-(int)sizeof(hdr));
1023  (pc->pkc_errlog)(_pkg_errbuf);
1024  return i-sizeof(hdr); /* amount of user data sent */
1025  }
1026  return (int)len;
1027  }
1028  /* Send them separately */
1029  if ((i = PKG_SEND(pc->pkc_fd, (char *)&hdr, sizeof(hdr))) != sizeof(hdr)) {
1030  if (i < 0) {
1031  if (errno == EBADF)
1032  return -1;
1033  _pkg_perror(pc->pkc_errlog, "pkg_send: header write");
1034  return -1;
1035  }
1036  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_send header of %llu, wrote %d\n",
1037  (unsigned long long)sizeof(hdr), i);
1038  (pc->pkc_errlog)(_pkg_errbuf);
1039  return -1; /* amount of user data sent */
1040  }
1041  if (len <= 0)
1042  return 0;
1043  i = PKG_SEND(pc->pkc_fd, buf, len);
1044  if ((size_t)i != len) {
1045  if (i < 0) {
1046  if (errno == EBADF)
1047  return -1;
1048  _pkg_perror(pc->pkc_errlog, "pkg_send: write");
1049  return -1;
1050  }
1051  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_send of %d, wrote %d\n", len, i);
1052  (pc->pkc_errlog)(_pkg_errbuf);
1053  return i; /* amount of user data sent */
1054  }
1055 #endif
1056  return (int)len;
1057 }
1058 
1059 
1060 int
1061 pkg_2send(int type, const char *buf1, size_t len1, const char *buf2, size_t len2, struct pkg_conn *pc)
1062 {
1063 #ifdef HAVE_WRITEV
1064  static struct iovec cmdvec[3];
1065 #endif
1066  static struct pkg_header hdr;
1067  ssize_t i;
1068 
1069  PKG_CK(pc);
1070 
1071  if (_pkg_debug) {
1072  _pkg_timestamp();
1073  fprintf(_pkg_debug,
1074  "pkg_send2(type=%d, buf1=%p, len1=%llu, buf2=%p, len2=%llu, pc=%p)\n",
1075  type, (void *)buf1, (unsigned long long)len1, (void *)buf2, (unsigned long long)len2, (void *)pc);
1076  fflush(_pkg_debug);
1077  }
1078 
1079  /* Check for any pending input, no delay */
1080  /* Input may be read, but not acted upon, to prevent deep recursion */
1081  _pkg_checkin(pc, 1);
1082 
1083  /* Flush any queued stream output first. */
1084  if (pc->pkc_strpos > 0) {
1085  if (pkg_flush(pc) < 0)
1086  return -1; /* assumes 2nd write would fail too */
1087  }
1088 
1089  pkg_pshort((char *)hdr.pkh_magic, (unsigned short)PKG_MAGIC);
1090  pkg_pshort((char *)hdr.pkh_type, (unsigned short)type); /* should see if valid type */
1091  pkg_plong((char *)hdr.pkh_len, (unsigned long)(len1+len2));
1092 
1093 #ifdef HAVE_WRITEV
1094  cmdvec[0].iov_base = (void *)&hdr;
1095  cmdvec[0].iov_len = sizeof(hdr);
1096  cmdvec[1].iov_base = (void *)buf1;
1097  cmdvec[1].iov_len = len1;
1098  cmdvec[2].iov_base = (void *)buf2;
1099  cmdvec[2].iov_len = len2;
1100 
1101  /*
1102  * TODO: set this FD to NONBIO. If not all output got sent, loop
1103  * in select() waiting for capacity to go out, and reading input
1104  * as well. Prevents deadlocking.
1105  */
1106  i = writev(pc->pkc_fd, cmdvec, 3);
1107  if (i != (ssize_t)(len1+len2+sizeof(hdr))) {
1108  if (i < 0) {
1109  _pkg_perror(pc->pkc_errlog, "pkg_2send: writev");
1110  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1111  "pkg_send2(type=%d, buf1=x%lx, len1=%ld, buf2=x%lx, len2=%ld, pc=x%lx)\n",
1112  type, (unsigned long int)buf1, (long)len1,
1113  (unsigned long int)buf2, (long)len2, (unsigned long int)pc);
1114  (pc->pkc_errlog)(_pkg_errbuf);
1115  return -1;
1116  }
1117  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send of %llu+%llu+%llu, wrote %ld\n",
1118  (unsigned long long)sizeof(hdr), (unsigned long long)len1, (unsigned long long)len2, (long int)i);
1119  (pc->pkc_errlog)(_pkg_errbuf);
1120  return i-sizeof(hdr); /* amount of user data sent */
1121  }
1122 #else
1123  /*
1124  * On the assumption that buffer copying is less expensive than
1125  * having this transmission broken into two network packets (with
1126  * TCP, each with a "push" bit set), merge it all into one buffer
1127  * here, unless size is enormous.
1128  */
1129  if (len1 + len2 + sizeof(hdr) <= 16*1024) {
1130  char tbuf[16*1024] = {0};
1131 
1132  memcpy(tbuf, (char *)&hdr, sizeof(hdr));
1133  if (len1 > 0)
1134  memcpy(tbuf+sizeof(hdr), buf1, len1);
1135  if (len2 > 0)
1136  memcpy(tbuf+sizeof(hdr)+len1, buf2, len2);
1137  i = PKG_SEND(pc->pkc_fd, tbuf, len1+len2+sizeof(hdr));
1138  if ((size_t)i != len1+len2+sizeof(hdr)) {
1139  if (i < 0) {
1140  if (errno == EBADF)
1141  return -1;
1142  _pkg_perror(pc->pkc_errlog, "pkg_2send: tbuf write");
1143  return -1;
1144  }
1145  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send of %llu+%llu, wrote %d\n",
1146  (unsigned long long)len1, (unsigned long long)len2, i-(int)sizeof(hdr));
1147  (pc->pkc_errlog)(_pkg_errbuf);
1148  return i-sizeof(hdr); /* amount of user data sent */
1149  }
1150  return (int)(len1+len2);
1151  }
1152  /* Send it in three pieces */
1153  if ((i = (ssize_t)PKG_SEND(pc->pkc_fd, (char *)&hdr, sizeof(hdr))) != sizeof(hdr)) {
1154  if (i < 0) {
1155  if (errno == EBADF)
1156  return -1;
1157  _pkg_perror(pc->pkc_errlog, "pkg_2send: header write");
1158  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send write(%d, %p, %llu) ret=%d\n",
1159  pc->pkc_fd, (void *)&hdr, (unsigned long long)sizeof(hdr), i);
1160  (pc->pkc_errlog)(_pkg_errbuf);
1161  return -1;
1162  }
1163  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send of %d+%d+%d, wrote header=%d\n",
1164  (int)sizeof(hdr), len1, len2, i);
1165  (pc->pkc_errlog)(_pkg_errbuf);
1166  return -1; /* amount of user data sent */
1167  }
1168 
1169  i = PKG_SEND(pc->pkc_fd, buf1, len1);
1170  if ((size_t)i != len1) {
1171  if (i < 0) {
1172  if (errno == EBADF)
1173  return -1;
1174  _pkg_perror(pc->pkc_errlog, "pkg_2send: write buf1");
1175  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send write(%d, %p, %llu) ret=%d\n",
1176  pc->pkc_fd, (void *)buf1, (unsigned long long)len1, i);
1177  (pc->pkc_errlog)(_pkg_errbuf);
1178  return -1;
1179  }
1180  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send of %llu+%llu+%llu, wrote len1=%d\n",
1181  (unsigned long long)sizeof(hdr), (unsigned long long)len1, (unsigned long long)len2, i);
1182  (pc->pkc_errlog)(_pkg_errbuf);
1183  return i; /* amount of user data sent */
1184  }
1185  if (len2 <= (size_t)0)
1186  return i;
1187 
1188  i = PKG_SEND(pc->pkc_fd, buf2, len2);
1189  if (i != (ssize_t)len2) {
1190  if (i < 0) {
1191  if (errno == EBADF)
1192  return -1;
1193  _pkg_perror(pc->pkc_errlog, "pkg_2send: write buf2");
1194  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send write(%d, %p, %llu) ret=%d\n",
1195  pc->pkc_fd, (void *)buf2, (unsigned long long)len2, i);
1196  (pc->pkc_errlog)(_pkg_errbuf);
1197  return -1;
1198  }
1199  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_2send of %llu+%llu+%llu, wrote len2=%d\n",
1200  (unsigned long long)sizeof(hdr), (unsigned long long)len1, (unsigned long long)len2, i);
1201  (pc->pkc_errlog)(_pkg_errbuf);
1202  return (int)(len1+i); /* amount of user data sent */
1203  }
1204 #endif
1205  return (int)(len1+len2);
1206 }
1207 
1208 
1209 int
1210 pkg_stream(int type, const char *buf, size_t len, struct pkg_conn *pc)
1211 {
1212  static struct pkg_header hdr;
1213 
1214  if (_pkg_debug) {
1215  _pkg_timestamp();
1216  fprintf(_pkg_debug,
1217  "pkg_stream(type=%d, buf=%p, len=%llu, pc=%p)\n",
1218  type, (void *)buf, (unsigned long long)len, (void *)pc);
1219  fflush(_pkg_debug);
1220  }
1221 
1222  if (len > MAXQLEN)
1223  return pkg_send(type, buf, len, pc);
1224 
1225  if (len > PKG_STREAMLEN - sizeof(struct pkg_header) - pc->pkc_strpos)
1226  pkg_flush(pc);
1227 
1228  /* Queue it */
1229  pkg_pshort((char *)hdr.pkh_magic, (unsigned short)PKG_MAGIC);
1230  pkg_pshort((char *)hdr.pkh_type, (unsigned short)type); /* should see if valid type */
1231  pkg_plong((char *)hdr.pkh_len, (unsigned long)len);
1232 
1233  memcpy(&(pc->pkc_stream[pc->pkc_strpos]), (char *)&hdr, sizeof(struct pkg_header));
1234  pc->pkc_strpos += sizeof(struct pkg_header);
1235  memcpy(&(pc->pkc_stream[pc->pkc_strpos]), buf, len);
1236  pc->pkc_strpos += (int)len;
1237 
1238  return (int)(len + sizeof(struct pkg_header));
1239 }
1240 
1241 
1242 int
1243 pkg_flush(struct pkg_conn *pc)
1244 {
1245  int i;
1246 
1247  if (_pkg_debug) {
1248  _pkg_timestamp();
1249  fprintf(_pkg_debug,
1250  "pkg_flush(pc=%p)\n",
1251  (void *)pc);
1252  fflush(_pkg_debug);
1253  }
1254 
1255  if (pc->pkc_strpos <= 0) {
1256  pc->pkc_strpos = 0; /* sanity for < 0 */
1257  return 0;
1258  }
1259 
1260  i = write(pc->pkc_fd, pc->pkc_stream, (size_t)pc->pkc_strpos);
1261  if (i != pc->pkc_strpos) {
1262  if (i < 0) {
1263  if (errno == EBADF)
1264  return -1;
1265  _pkg_perror(pc->pkc_errlog, "pkg_flush: write");
1266  return -1;
1267  }
1268  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_flush of %d, wrote %d\n",
1269  pc->pkc_strpos, i);
1270  (pc->pkc_errlog)(_pkg_errbuf);
1271  pc->pkc_strpos -= i;
1272  /* copy leftovers to front of stream */
1273  memmove(pc->pkc_stream, pc->pkc_stream + i, (size_t)pc->pkc_strpos);
1274  return i; /* amount of user data sent */
1275  }
1276  pc->pkc_strpos = 0;
1277  return i;
1278 }
1279 
1280 
1281 /**
1282  * Get header from a new message.
1283  *
1284  * Returns 1 when there is some message to go look at and -1 on fatal
1285  * errors.
1286  *
1287  * This is a private implementation function.
1288  */
1289 static int
1290 _pkg_gethdr(struct pkg_conn *pc, char *buf)
1291 {
1292  size_t i;
1293 
1294  PKG_CK(pc);
1295  if (pc->pkc_left >= 0)
1296  return 1; /* go get it! */
1297 
1298  /*
1299  * At message boundary, read new header. This will block until
1300  * the new header arrives (feature).
1301  */
1302  if ((i = _pkg_inget(pc, (char *)&(pc->pkc_hdr),
1303  sizeof(struct pkg_header))) != sizeof(struct pkg_header)) {
1304  if (i > 0) {
1305  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "_pkg_gethdr: header read of %ld?\n", (long)i);
1306  (pc->pkc_errlog)(_pkg_errbuf);
1307  }
1308  return -1;
1309  }
1310  while (pkg_gshort((char *)pc->pkc_hdr.pkh_magic) != PKG_MAGIC) {
1311  int c;
1312  c = *((unsigned char *)&pc->pkc_hdr);
1313  if (isprint(c)) {
1314  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1315  "_pkg_gethdr: skipping noise x%x %c\n",
1316  c, c);
1317  } else {
1318  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1319  "_pkg_gethdr: skipping noise x%x\n",
1320  c);
1321  }
1322  (pc->pkc_errlog)(_pkg_errbuf);
1323  /* Slide over one byte and try again */
1324  memmove((char *)&pc->pkc_hdr, ((char *)&pc->pkc_hdr)+1, sizeof(struct pkg_header)-1);
1325  if ((i = _pkg_inget(pc,
1326  ((char *)&pc->pkc_hdr)+sizeof(struct pkg_header)-1,
1327  1)) != 1) {
1328  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "_pkg_gethdr: hdr read=%ld?\n", (long)i);
1329  (pc->pkc_errlog)(_pkg_errbuf);
1330  return -1;
1331  }
1332  }
1333  pc->pkc_type = pkg_gshort((char *)pc->pkc_hdr.pkh_type); /* host order */
1334  pc->pkc_len = pkg_glong((char *)pc->pkc_hdr.pkh_len);
1335  pc->pkc_buf = (char *)0;
1336  pc->pkc_left = (int)pc->pkc_len;
1337  if (pc->pkc_left == 0)
1338  return 1; /* msg here, no data */
1339 
1340  if (buf) {
1341  pc->pkc_buf = buf;
1342  } else {
1343  /* Prepare to read message into dynamic buffer */
1344  if ((pc->pkc_buf = (char *)malloc(pc->pkc_len+2)) == NULL) {
1345  _pkg_perror(pc->pkc_errlog, "_pkg_gethdr: malloc fail");
1346  return -1;
1347  }
1348  }
1349  pc->pkc_curpos = pc->pkc_buf;
1350  return 1; /* something ready */
1351 }
1352 
1353 
1354 int
1355 pkg_waitfor (int type, char *buf, size_t len, struct pkg_conn *pc)
1356 {
1357  size_t i;
1358 
1359  PKG_CK(pc);
1360  if (_pkg_debug) {
1361  _pkg_timestamp();
1362  fprintf(_pkg_debug,
1363  "pkg_waitfor (type=%d, buf=%p, len=%llu, pc=%p)\n",
1364  type, (void *)buf, (unsigned long long)len, (void *)pc);
1365  fflush(_pkg_debug);
1366  }
1367  again:
1368  if (pc->pkc_left >= 0) {
1369  /* Finish up remainder of partially received message */
1370  if (pkg_block(pc) < 0)
1371  return -1;
1372  }
1373 
1374  if (pc->pkc_buf != (char *)0) {
1375  pc->pkc_errlog("pkg_waitfor: buffer clash\n");
1376  return -1;
1377  }
1378  if (_pkg_gethdr(pc, buf) < 0)
1379  return -1;
1380  if (pc->pkc_type != type) {
1381  /* A message of some other type has unexpectedly arrived. */
1382  if (pc->pkc_len > 0) {
1383  if ((pc->pkc_buf = (char *)malloc(pc->pkc_len+2)) == NULL) {
1384  _pkg_perror(pc->pkc_errlog, "pkg_waitfor: malloc failed");
1385  return -1;
1386  }
1387  pc->pkc_curpos = pc->pkc_buf;
1388  }
1389  goto again;
1390  }
1391  pc->pkc_left = -1;
1392  if (pc->pkc_len == 0)
1393  return 0;
1394 
1395  /* See if incoming message is larger than user's buffer */
1396  if (pc->pkc_len > len) {
1397  char *bp;
1398  size_t excess;
1399  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1400  "pkg_waitfor: message %ld exceeds buffer %ld\n",
1401  (long)pc->pkc_len, (long)len);
1402  (pc->pkc_errlog)(_pkg_errbuf);
1403  if ((i = _pkg_inget(pc, buf, len)) != len) {
1404  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1405  "pkg_waitfor: _pkg_inget %ld gave %ld\n", (long)len, (long)i);
1406  (pc->pkc_errlog)(_pkg_errbuf);
1407  return -1;
1408  }
1409  excess = pc->pkc_len - len; /* size of excess message */
1410  if ((bp = (char *)malloc(excess)) == NULL) {
1411  _pkg_perror(pc->pkc_errlog, "pkg_waitfor: excess message, malloc failed");
1412  return -1;
1413  }
1414  if ((i = _pkg_inget(pc, bp, excess)) != excess) {
1415  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1416  "pkg_waitfor: _pkg_inget of excess, %ld gave %ld\n",
1417  (long)excess, (long)i);
1418  (pc->pkc_errlog)(_pkg_errbuf);
1419  (void)free(bp);
1420  return -1;
1421  }
1422  (void)free(bp);
1423  return (int)len; /* potentially truncated, but OK */
1424  }
1425 
1426  /* Read the whole message into the users buffer */
1427  if ((i = _pkg_inget(pc, buf, pc->pkc_len)) != pc->pkc_len) {
1428  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1429  "pkg_waitfor: _pkg_inget %ld gave %ld\n",
1430  (long)pc->pkc_len, (long)i);
1431  (pc->pkc_errlog)(_pkg_errbuf);
1432  return -1;
1433  }
1434  if (_pkg_debug) {
1435  _pkg_timestamp();
1436  fprintf(_pkg_debug,
1437  "pkg_waitfor () message type=%d arrived\n", type);
1438  fflush(_pkg_debug);
1439  }
1440  pc->pkc_buf = (char *)0;
1441  pc->pkc_curpos = (char *)0;
1442  pc->pkc_left = -1; /* safety */
1443  return (int)pc->pkc_len;
1444 }
1445 
1446 
1447 char *
1448 pkg_bwaitfor (int type, struct pkg_conn *pc)
1449 {
1450  size_t i;
1451  char *tmpbuf;
1452 
1453  PKG_CK(pc);
1454  if (_pkg_debug) {
1455  _pkg_timestamp();
1456  fprintf(_pkg_debug,
1457  "pkg_bwaitfor (type=%d, pc=%p)\n",
1458  type, (void *)pc);
1459  fflush(_pkg_debug);
1460  }
1461  do {
1462  /* Finish any unsolicited msg */
1463  if (pc->pkc_left >= 0)
1464  if (pkg_block(pc) < 0)
1465  return (char *)0;
1466  if (pc->pkc_buf != (char *)0) {
1467  pc->pkc_errlog("pkg_bwaitfor: buffer clash\n");
1468  return (char *)0;
1469  }
1470  if (_pkg_gethdr(pc, (char *)0) < 0)
1471  return (char *)0;
1472  } while (pc->pkc_type != type);
1473 
1474  pc->pkc_left = -1;
1475  if (pc->pkc_len == 0)
1476  return (char *)0;
1477 
1478  /* Read the whole message into the dynamic buffer */
1479  if (pc->pkc_buf != (char *)0) {
1480  if ((i = _pkg_inget(pc, pc->pkc_buf, pc->pkc_len)) != pc->pkc_len) {
1481  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE,
1482  "pkg_bwaitfor: _pkg_inget %ld gave %ld\n", (long)pc->pkc_len, (long)i);
1483  (pc->pkc_errlog)(_pkg_errbuf);
1484  }
1485  } else {
1486  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_bwaitfor: tried to read from null pc->pkc_buf!\n");
1487  return (char *)0;
1488  }
1489  tmpbuf = pc->pkc_buf;
1490  pc->pkc_buf = (char *)0;
1491  pc->pkc_curpos = (char *)0;
1492  pc->pkc_left = -1; /* safety */
1493  /* User must free the buffer */
1494  return tmpbuf;
1495 }
1496 
1497 
1498 /**
1499  * Given that a whole message has arrived, send it to the appropriate
1500  * User Handler, or else grouse. Returns -1 on fatal error, 0 on no
1501  * handler, 1 if all's well.
1502  *
1503  * This is a private implementation function.
1504  */
1505 static int
1506 _pkg_dispatch(struct pkg_conn *pc)
1507 {
1508  int i;
1509 
1510  PKG_CK(pc);
1511  if (_pkg_debug) {
1512  _pkg_timestamp();
1513  fprintf(_pkg_debug,
1514  "_pkg_dispatch(pc=%p) type=%d, buf=%p, len=%llu\n",
1515  (void *)pc, pc->pkc_type, (void *)(pc->pkc_buf), (unsigned long long)(pc->pkc_len));
1516  fflush(_pkg_debug);
1517  }
1518  if (pc->pkc_left != 0)
1519  return -1;
1520 
1521  /* Whole message received, process it via switchout table */
1522  for (i = 0; pc->pkc_switch[i].pks_handler != NULL; i++) {
1523  char *tempbuf;
1524 
1525  if (pc->pkc_switch[i].pks_type != pc->pkc_type)
1526  continue;
1527  /*
1528  * NOTICE: User Handler must free() message buffer!
1529  * WARNING: Handler may recurse back to pkg_suckin() --
1530  * reset all connection state variables first!
1531  */
1532  tempbuf = pc->pkc_buf;
1533  pc->pkc_buf = (char *)0;
1534  pc->pkc_curpos = (char *)0;
1535  pc->pkc_left = -1; /* safety */
1536 
1537  /* copy the user_data from the current pkg_switch into the pkg_conn */
1538  pc->pkc_user_data = pc->pkc_switch[i].pks_user_data;
1539 
1540  /* pc->pkc_type, pc->pkc_len are preserved for handler */
1541  pc->pkc_switch[i].pks_handler(pc, tempbuf);
1542 
1543  /* sanity */
1544  pc->pkc_user_data = (void *)NULL;
1545  return 1;
1546  }
1547  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "_pkg_dispatch: no handler for message type %d, len %ld\n",
1548  pc->pkc_type, (long)pc->pkc_len);
1549  (pc->pkc_errlog)(_pkg_errbuf);
1550  (void)free(pc->pkc_buf);
1551  pc->pkc_buf = (char *)0;
1552  pc->pkc_curpos = (char *)0;
1553  pc->pkc_left = -1; /* safety */
1554  pc->pkc_user_data = (void *)NULL;
1555  return 0;
1556 }
1557 
1558 
1559 int
1561 {
1562  size_t len;
1563  int available;
1564  int errcnt;
1565  int ret;
1566  int goodcnt;
1567 
1568  goodcnt = 0;
1569 
1570  PKG_CK(pc);
1571  /* This loop exists only to cut off "hard" errors */
1572  for (errcnt=0; errcnt < 500;) {
1573  available = pc->pkc_inend - pc->pkc_incur; /* amt in input buf */
1574  if (_pkg_debug) {
1575  if (pc->pkc_left < 0) {
1576  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "awaiting new header");
1577  } else if (pc->pkc_left > 0) {
1578  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "need more data");
1579  } else {
1580  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg is all here");
1581  }
1582  _pkg_timestamp();
1583  fprintf(_pkg_debug,
1584  "pkg_process(pc=%p) pkc_left=%d %s (avail=%d)\n",
1585  (void *)pc, pc->pkc_left, _pkg_errbuf, available);
1586  fflush(_pkg_debug);
1587  }
1588  if (pc->pkc_left < 0) {
1589  /*
1590  * Need to get a new PKG header. Do so ONLY if the full
1591  * header is already in the internal buffer, to prevent
1592  * blocking in _pkg_gethdr().
1593  */
1594  if ((size_t)available < sizeof(struct pkg_header))
1595  break;
1596 
1597  if (_pkg_gethdr(pc, (char *)0) < 0) {
1598  DMSG("_pkg_gethdr < 0\n");
1599  errcnt++;
1600  continue;
1601  }
1602 
1603  if (pc->pkc_left < 0) {
1604  /* _pkg_gethdr() didn't get a header */
1605  DMSG("pkc_left still < 0 after _pkg_gethdr()\n");
1606  errcnt++;
1607  continue;
1608  }
1609  }
1610  /*
1611  * Now pkc_left >= 0, implying header has been obtained. Find
1612  * amount still available in input buffer.
1613  */
1614  available = pc->pkc_inend - pc->pkc_incur;
1615 
1616  /* copy what is here already, and dispatch when all here */
1617  if (pc->pkc_left > 0) {
1618  if (available <= 0) break;
1619 
1620  /* Sanity check -- buffer must be allocated by now */
1621  if (pc->pkc_curpos == 0) {
1622  DMSG("curpos=0\n");
1623  errcnt++;
1624  continue;
1625  }
1626 
1627  if (available > pc->pkc_left) {
1628  /* There is more in input buf than just this pkg */
1629  len = pc->pkc_left; /* trim to amt needed */
1630  } else {
1631  /* Take all that there is */
1632  len = available;
1633  }
1634  len = _pkg_inget(pc, pc->pkc_curpos, len);
1635  pc->pkc_curpos += len;
1636  pc->pkc_left -= (int)len;
1637  if (pc->pkc_left > 0) {
1638  /*
1639  * Input buffer is exhausted, but more data is needed
1640  * to finish this package.
1641  */
1642  break;
1643  }
1644  }
1645 
1646  if (pc->pkc_left != 0) {
1647  /* Somehow, a full PKG has not yet been obtained */
1648  DMSG("pkc_left != 0\n");
1649  errcnt++;
1650  continue;
1651  }
1652 
1653  /* Now, pkc_left == 0, dispatch the message */
1654  if (_pkg_dispatch(pc) <= 0) {
1655  /* something bad happened */
1656  DMSG("_pkg_dispatch failed\n");
1657  errcnt++;
1658  } else {
1659  /* it worked */
1660  goodcnt++;
1661  }
1662  }
1663 
1664  if (errcnt > 0) {
1665  ret = -errcnt;
1666  } else {
1667  ret = goodcnt;
1668  }
1669 
1670  if (_pkg_debug) {
1671  _pkg_timestamp();
1672  fprintf(_pkg_debug,
1673  "pkg_process() ret=%d, pkc_left=%d, errcnt=%d, goodcnt=%d\n",
1674  ret, pc->pkc_left, errcnt, goodcnt);
1675  fflush(_pkg_debug);
1676  }
1677  return ret;
1678 }
1679 
1680 
1681 int
1682 pkg_block(struct pkg_conn *pc)
1683 {
1684  PKG_CK(pc);
1685  if (_pkg_debug) {
1686  _pkg_timestamp();
1687  fprintf(_pkg_debug,
1688  "pkg_block(pc=%p)\n",
1689  (void *)pc);
1690  fflush(_pkg_debug);
1691  }
1692 
1693  /* If no read operation going now, start one. */
1694  if (pc->pkc_left < 0) {
1695  if (_pkg_gethdr(pc, (char *)0) < 0)
1696  return -1;
1697  /* Now pkc_left >= 0 */
1698  }
1699 
1700  /* Read the rest of the message, blocking if necessary */
1701  if (pc->pkc_left > 0) {
1702  if (_pkg_inget(pc, pc->pkc_curpos, (size_t)pc->pkc_left) != (size_t)pc->pkc_left) {
1703  pc->pkc_left = -1;
1704  return -1;
1705  }
1706  pc->pkc_left = 0;
1707  }
1708 
1709  /* Now, pkc_left == 0, dispatch the message */
1710  return _pkg_dispatch(pc);
1711 }
1712 
1713 
1714 int
1716 {
1717  size_t avail;
1718  int got;
1719  int ret;
1720 
1721  got = 0;
1722  PKG_CK(pc);
1723 
1724  if (_pkg_debug) {
1725  _pkg_timestamp();
1726  fprintf(_pkg_debug,
1727  "pkg_suckin() incur=%d, inend=%d, inlen=%d\n",
1728  pc->pkc_incur, pc->pkc_inend, pc->pkc_inlen);
1729  fflush(_pkg_debug);
1730  }
1731 
1732  /* If no buffer allocated yet, get one */
1733  if (pc->pkc_inbuf == (char *)0 || pc->pkc_inlen <= 0) {
1734  pc->pkc_inlen = PKG_STREAMLEN;
1735  if ((pc->pkc_inbuf = (char *)malloc((size_t)pc->pkc_inlen)) == (char *)0) {
1736  pc->pkc_errlog("pkg_suckin malloc failure\n");
1737  pc->pkc_inlen = 0;
1738  ret = -1;
1739  goto out;
1740  }
1741  pc->pkc_incur = pc->pkc_inend = 0;
1742  }
1743 
1744  if (pc->pkc_incur >= pc->pkc_inend) {
1745  /* Reset to beginning of buffer */
1746  pc->pkc_incur = pc->pkc_inend = 0;
1747  }
1748 
1749  /* If cur point is near end of buffer, recopy data to buffer front */
1750  if (pc->pkc_incur >= (pc->pkc_inlen * 7) / 8) {
1751  size_t amount;
1752 
1753  amount = pc->pkc_inend - pc->pkc_incur;
1754  /* This copy can not overlap itself, because of 7/8 above */
1755  memcpy(pc->pkc_inbuf, &pc->pkc_inbuf[pc->pkc_incur], amount);
1756  pc->pkc_incur = 0;
1757  pc->pkc_inend = (int)amount;
1758  }
1759 
1760  /* If remaining buffer space is small, make buffer bigger */
1761  avail = pc->pkc_inlen - pc->pkc_inend;
1762  if (avail < 10 * sizeof(struct pkg_header)) {
1763  pc->pkc_inlen <<= 1;
1764  if (_pkg_debug) {
1765  _pkg_timestamp();
1766  fprintf(_pkg_debug,
1767  "pkg_suckin: realloc inbuf to %d\n",
1768  pc->pkc_inlen);
1769  fflush(_pkg_debug);
1770  }
1771  if ((pc->pkc_inbuf = (char *)realloc(pc->pkc_inbuf, (size_t)pc->pkc_inlen)) == (char *)0) {
1772  pc->pkc_errlog("pkg_suckin realloc failure\n");
1773  pc->pkc_inlen = 0;
1774  ret = -1;
1775  goto out;
1776  }
1777  /* since the input buffer has grown, lets update avail */
1778  avail = (size_t)pc->pkc_inlen - (size_t)pc->pkc_inend;
1779  }
1780 
1781  /* Take as much as the system will give us, up to buffer size */
1782  got = PKG_READ(pc->pkc_fd, &pc->pkc_inbuf[pc->pkc_inend], avail);
1783  if (got <= 0) {
1784  if (got == 0) {
1785  if (_pkg_debug) {
1786  _pkg_timestamp();
1787  fprintf(_pkg_debug,
1788  "pkg_suckin: fd=%d, read for %ld bytes returned 0\n",
1789  pc->pkc_fd, (long)avail);
1790  fflush(_pkg_debug);
1791  }
1792  ret = 0; /* EOF */
1793  goto out;
1794  }
1795 #ifndef HAVE_WINSOCK_H
1796  _pkg_perror(pc->pkc_errlog, "pkg_suckin: read");
1797  snprintf(_pkg_errbuf, MAX_PKG_ERRBUF_SIZE, "pkg_suckin: read(%d, x%lx, %ld) ret=%d inbuf=x%lx, inend=%d\n",
1798  pc->pkc_fd, (long)(&pc->pkc_inbuf[pc->pkc_inend]), (long)avail,
1799  got,
1800  (long)(pc->pkc_inbuf), pc->pkc_inend);
1801  (pc->pkc_errlog)(_pkg_errbuf);
1802 #endif
1803  ret = -1;
1804  goto out;
1805  }
1806  if (got > (int)avail) {
1807  pc->pkc_errlog("pkg_suckin: read more bytes than desired\n");
1808  got = (int)avail;
1809  }
1810  pc->pkc_inend += got;
1811  ret = 1;
1812  out:
1813  if (_pkg_debug) {
1814  _pkg_timestamp();
1815  fprintf(_pkg_debug,
1816  "pkg_suckin() ret=%d, got %d, total=%d\n",
1817  ret, got, pc->pkc_inend - pc->pkc_incur);
1818  fflush(_pkg_debug);
1819  }
1820  return ret;
1821 }
1822 
1823 
1824 /*
1825  * Local Variables:
1826  * mode: C
1827  * tab-width: 8
1828  * indent-tabs-mode: t
1829  * c-file-style: "stroustrup"
1830  * End:
1831  * ex: shiftwidth=4 tabstop=8
1832  */
const struct pkg_switch * pkc_switch
Array of message handlers.
Definition: pkg.h:81
ptrdiff_t ssize_t
Definition: common.h:119
char * pkc_inbuf
input stream buffer
Definition: pkg.h:92
#define MAX_PKG_ERRBUF_SIZE
Definition: pkg.c:145
int pkc_incur
current pos in inbuf
Definition: pkg.h:93
char * pkg_plong(char *buf, unsigned long l)
Definition: pkg.c:190
void pkg_close(struct pkg_conn *pc)
Definition: pkg.c:800
#define PKG_CK(p)
Definition: pkg.c:122
struct pkg_header pkc_hdr
hdr of cur msg
Definition: pkg.h:83
unsigned short pks_type
Type code.
Definition: pkg.h:58
if lu s
Definition: nmg_mod.c:3860
unsigned char pkh_len[4]
Byte count of remainder.
Definition: pkg.h:75
pkg_errlog pkc_errlog
Error message logger.
Definition: pkg.h:82
#define PKG_READ(d, buf, nbytes)
Definition: pkg.c:118
#define MAXQLEN
Definition: pkg.c:129
struct pkg_conn * pkg_getclient(int fd, const struct pkg_switch *switchp, void(*errlog)(const char *msg), int nodelay)
Definition: pkg.c:724
Header file for the BRL-CAD common definitions.
long time(time_t *)
int pkc_inend
first unused pos in inbuf
Definition: pkg.h:94
int pkg_process(struct pkg_conn *pc)
Definition: pkg.c:1560
int pkc_fd
TCP connection fd.
Definition: pkg.h:80
int pkg_permport
Definition: pkg.c:143
unsigned short pkc_type
pkg_type, in host order
Definition: pkg.h:85
struct pkg_conn * pkg_transerver(const struct pkg_switch *switchp, void(*errlog)(const char *))
Definition: pkg.c:501
if(share_geom)
Definition: nmg_mod.c:3829
int pkg_flush(struct pkg_conn *pc)
Definition: pkg.c:1243
void * memset(void *s, int c, size_t n)
#define PKG_MAGIC
Definition: pkg.h:71
int pkg_send(int type, const char *buf, size_t len, struct pkg_conn *pc)
Definition: pkg.c:934
void * pks_user_data
User defined pointer to data.
Definition: pkg.h:61
unsigned int pkc_magic
for validating pointers
Definition: pkg.h:89
int pkc_left
bytes pkg_get expects
Definition: pkg.h:97
unsigned char * bp
Definition: rot.c:56
char * pkg_pshort(char *buf, unsigned short s)
Definition: pkg.c:181
int pkg_permserver_ip(const char *ipOrHostname, const char *service, const char *protocol, int backlog, void(*errlog)(const char *msg))
Definition: pkg.c:702
unsigned char pkh_magic[2]
Ident.
Definition: pkg.h:73
#define PKC_NULL
Definition: pkg.h:103
Definition: pkg.h:72
int pkc_inlen
length of pkc_inbuf
Definition: pkg.h:95
#define UNUSED(parameter)
Definition: common.h:239
goto out
Definition: nmg_mod.c:3846
unsigned char pkh_type[2]
Message Type.
Definition: pkg.h:74
int pkc_strpos
index into stream buffer
Definition: pkg.h:90
#define PKG_SEND(d, buf, nbytes)
Definition: pkg.c:119
int pkg_waitfor(int type, char *buf, size_t len, struct pkg_conn *pc)
Definition: pkg.c:1355
#define PKG_STREAMLEN
Definition: pkg.h:78
Definition: pkg.h:57
const char * pkg_version(void)
Definition: vers.c:31
char * pkc_curpos
current position in pkg_buf
Definition: pkg.h:100
size_t pkc_len
pkg_len, in host order
Definition: pkg.h:84
char * pkg_bwaitfor(int type, struct pkg_conn *pc)
Definition: pkg.c:1448
unsigned short pkg_gshort(char *buf)
Definition: pkg.c:157
void * pkc_user_data
User defined pointer to data for the current pkg_type.
Definition: pkg.h:86
unsigned long pkg_glong(char *buf)
Definition: pkg.c:168
struct pkg_conn * pkg_open(const char *host, const char *service, const char *protocol, const char *uname, const char *passwd, const struct pkg_switch *switchp, void(*errlog)(const char *msg))
Definition: pkg.c:343
Definition: pkg.h:79
int pkg_block(struct pkg_conn *pc)
Definition: pkg.c:1682
int pkg_suckin(struct pkg_conn *pc)
Definition: pkg.c:1715
int pkg_permserver(const char *service, const char *protocol, int backlog, void(*errlog)(const char *msg))
Definition: pkg.c:693
#define DMSG(s)
Definition: pkg.c:133
int pkg_2send(int type, const char *buf1, size_t len1, const char *buf2, size_t len2, struct pkg_conn *pc)
Definition: pkg.c:1061
pkg_callback pks_handler
Message Handler.
Definition: pkg.h:59
char * pkc_buf
start of dynamic buf
Definition: pkg.h:99
int pkg_nochecking
Definition: pkg.c:142
int pkg_stream(int type, const char *buf, size_t len, struct pkg_conn *pc)
Definition: pkg.c:1210
char pkc_stream[PKG_STREAMLEN]
output stream
Definition: pkg.h:88
#define PKC_ERROR
Definition: pkg.h:104