home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / distributed-c-2.1 / part17 < prev    next >
Text File  |  1993-12-22  |  64KB  |  1,740 lines

  1. Newsgroups: comp.sources.unix
  2. From: pleierc@informatik.tu-muenchen.de (Christoph Pleier)
  3. Subject: v27i191: distributed-c-2.1 - Distributed C Development Environment, V2.1, Part17/18
  4. References: <1.756634932.28500@gw.home.vix.com>
  5. Sender: unix-sources-moderator@gw.home.vix.com
  6. Approved: vixie@gw.home.vix.com
  7.  
  8. Submitted-By: pleierc@informatik.tu-muenchen.de (Christoph Pleier)
  9. Posting-Number: Volume 27, Issue 191
  10. Archive-Name: distributed-c-2.1/part17
  11.  
  12. #! /bin/sh
  13. # This is a shell archive.  Remove anything before this line, then unpack
  14. # it by saving it into a file and typing "sh file".  To overwrite existing
  15. # files, type "sh file -c".  You can also feed this as standard input via
  16. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  17. # will see the following message at the end:
  18. #        "End of archive 17 (of 18)."
  19. # Contents:  lib/ipc_socket.c
  20. # Wrapped by vixie@gw.home.vix.com on Thu Dec 23 00:12:07 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'lib/ipc_socket.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'lib/ipc_socket.c'\"
  24. else
  25. echo shar: Extracting \"'lib/ipc_socket.c'\" \(60451 characters\)
  26. sed "s/^X//" >'lib/ipc_socket.c' <<'END_OF_FILE'
  27. X/***************************************************************************
  28. X *                                                                         *
  29. X * @@@@  @@@ @@@@@ @@@@@ @@@@@ @@@ @@@@  @   @ @@@@@ @@@@@ @@@@       @@@  *
  30. X * @   @  @  @       @   @   @  @  @   @ @   @   @   @     @   @     @   @ *
  31. X * @   @  @  @@@@@   @   @@@@@  @  @@@@@ @   @   @   @@@@@ @   @     @     *
  32. X * @   @  @      @   @   @ @    @  @   @ @   @   @   @     @   @     @   @ *
  33. X * @@@@  @@@ @@@@@   @   @  @  @@@ @@@@  @@@@@   @   @@@@@ @@@@       @@@  *
  34. X *                                                                         *
  35. X *              A compiler for distributed programming with C              *
  36. X *                                                                         *
  37. X *                         i p c _ s o c k e t . c                         *
  38. X *                                                                         *
  39. X *                            Package : Runtime Library                    *
  40. X *                            Version : 1.1                                *
  41. X *                       CreationDate : 10.07.90                           *
  42. X *                         LastUpDate : 06.12.93                           *
  43. X *                                                                         *
  44. X * This file contains the hardware dependent routines building the message *
  45. X * passing layer based on stream sockets for use on operating system BSD   *
  46. X * Unix Version 4.3 or other compatible operating systems like Sun Os 4.1, *
  47. X * ConvexOs, HP-UX, UNICOS, AIX or Ultrix.                                 *
  48. X *                                                                         *
  49. X *               Copyright (C) 1990-1994 by Christoph Pleier               *
  50. X *                          All rights reserved!                           *
  51. X ***************************************************************************/
  52. X
  53. X/*
  54. X * This file is part of the Distributed C Development Environment (DCDE).
  55. X * DCDE is free software; you can redistribute it and/or modify
  56. X * it under the terms written in the README-file. 
  57. X * DCDE is distributed in the hope that it will be useful,
  58. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  59. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  60. X * See the file README for more details.
  61. X */
  62. X
  63. X#include <stdio.h>
  64. X#include <sys/types.h>
  65. X#include <sys/socket.h>
  66. X#ifdef UNICOS
  67. X# include <sys/param.h>
  68. X#endif
  69. X#include <sys/time.h>
  70. X#include <netinet/in.h>
  71. X#ifdef HPUX
  72. X# include <codelibs/nap.h>
  73. X#endif
  74. X#ifdef AIX
  75. X# include <sys/select.h>
  76. X# include <isode/isoaddrs.h>
  77. X# include <isode/manifest.h>
  78. X#endif
  79. X#include <netdb.h>
  80. X#include <signal.h>
  81. X#include <errno.h>
  82. X#include "ipc_socket.h"
  83. X#include "run_Errno.h"
  84. X
  85. X#define DEBUG_IPC /**/
  86. X
  87. X/* To avoid that processes whose connection attempt is refused several times
  88. X * (e.g. if the called process tries itself to connect to the calling process)
  89. X * let grow the load of the computer nodes because of the busy waiting
  90. X * character, we raise each time a connection attempt is refused the delay 
  91. X * until the connecting process is allowed to retry the attempt.
  92. X * The delay starts at MCON_RETRY_DELAY_MIN and is raised in steps of
  93. X * MCON_RETRY_DELAY_STEP until MCON_RETRY_DELAY_MAX. After the connection
  94. X * attempt succeeded or the operation is timed out the delay is reset to the 
  95. X * minimal value. 
  96. X *
  97. X * Note: the values specify different unities on different machines! 
  98. X */
  99. X#ifdef SPARC
  100. X        /* the values specify microseconds */
  101. X# define MCON_RETRY_DELAY_MIN   5000
  102. X# define MCON_RETRY_DELAY_MAX   100000
  103. X# define MCON_RETRY_DELAY_STEP  5000
  104. X#else
  105. X# ifdef HPUX
  106. X        /* the values specify milliseconds */
  107. X#  define MCON_RETRY_DELAY_MIN   10
  108. X#  define MCON_RETRY_DELAY_MAX   1000
  109. X#  define MCON_RETRY_DELAY_STEP  50
  110. X# else
  111. X        /* the values specify seconds */
  112. X#  define MCON_RETRY_DELAY_MIN   0
  113. X#  define MCON_RETRY_DELAY_MAX   5
  114. X#  define MCON_RETRY_DELAY_STEP  1
  115. X# endif /* HPUX /**/
  116. X#endif /* SPARC /**/
  117. X
  118. X#ifdef SYSTEM_V
  119. X# define bzero(s, n)            memset((char *)(s), 0, (n))
  120. X# define bcopy(src, dst, num)   memcpy((dst), (src), (num))
  121. X#endif /* SYSTEM_V /**/
  122. X
  123. X/* this variable is used to store the actual retry delay */
  124. Xint mcon_retry_delay = MCON_RETRY_DELAY_MIN;
  125. X
  126. X/* the array _con_socks is used to store all established TCP/IP connections. */
  127. Xint          _con_num = 0;
  128. Xstruct _con  *_con_socks_first = NULL, *_con_socks_last = NULL; 
  129. X/* struct _con  _con_socks[FD_SETSIZE]; */
  130. X
  131. X/* the used external global variables */
  132. Xextern int        errno,        /* system error code */
  133. X                  Errno,        /* function error code */
  134. X                  _debugflush;        /* flush debug messages or not */
  135. Xextern char      *sys_errlist[],    /* system error messages */
  136. X                 *_programname,        /* name of program */
  137. X                 *_processname,        /* name of process */
  138. X                  _processprefix[];    /* process specifying string */
  139. Xextern FILE      *_debugout;        /* where to write the debug messages */
  140. Xextern PORTDESCR  _own_port;        /* own port */
  141. X
  142. X#ifdef DEBUG_IPC
  143. X/* the flag to control the debug messages output */
  144. Xint _debug_ipc = 0;
  145. X#endif /* DEBUG_IPC /**/
  146. X
  147. X/* the timeout flag */
  148. Xstatic int timeout;
  149. X
  150. X/* caught signal SIGPIPE or not */
  151. Xstatic int sigpipe;
  152. X
  153. X/* set timer, if time equals 0 clear timer */
  154. X#ifdef BSD
  155. X# define SETTIMER(time)        timeout = FALSE; \
  156. X                { \
  157. X                       struct sigvec vec; \
  158. X                   \
  159. X                       vec.sv_handler = timeout_proc; \
  160. X                       vec.sv_mask    = SIGALRM; \
  161. X                       vec.sv_flags   = SV_INTERRUPT; \
  162. X                       sigvec(SIGALRM,&vec,(struct sigvec *) NULL);\
  163. X                } \
  164. X                (void) alarm(time);
  165. X# define CATCHSIGPIPE        sigpipe = FALSE; \
  166. X                { \
  167. X                       struct sigvec vec; \
  168. X                   \
  169. X                       vec.sv_handler = catch_SIGPIPE; \
  170. X                       vec.sv_mask    = SIGPIPE; \
  171. X                       vec.sv_flags   = SV_INTERRUPT; \
  172. X                       sigvec(SIGPIPE,&vec,(struct sigvec *) NULL);\
  173. X                }
  174. X#else /* SYSTEM_V */
  175. X# define SETTIMER(time)        timeout = FALSE; \
  176. X                    signal(SIGALRM, timeout_proc);\
  177. X                (void) alarm(time);
  178. X# define CATCHSIGPIPE        sigpipe = FALSE; \
  179. X                    signal(SIGPIPE, catch_SIGPIPE);
  180. X#endif /* BSD /**/
  181. X
  182. X/* if timeout is set, return ERROR */
  183. X#define RETURN_IF_TIMEOUT    if (timeout) { \
  184. X                    Errno = ETIMEOUT; \
  185. X                    return(ERROR); \
  186. X                }
  187. X
  188. X#ifdef DEBUG_IPC
  189. X# define DEBUGPUTS(msg)        if (_debug_ipc) { \
  190. X                    fprintf(_debugout, "[ipc] %s %s\n", \
  191. X                        _processprefix, msg); \
  192. X                    if (_debugflush) \
  193. X                        fflush(_debugout); \
  194. X                }
  195. X#else
  196. X# define DEBUGPUTS(msg)        { /* nothing */ }
  197. X#endif
  198. X
  199. X/* The parameter types for the select() system call are different 
  200. X * on HPUX systems. We handle this problem by a special cast macro.
  201. X */
  202. X#ifdef HPUX
  203. X#define SELECT_CAST        (int *)
  204. X#else
  205. X#define SELECT_CAST        (fd_set *)
  206. X#endif
  207. X
  208. X/******************************************************************************
  209. X * print_system_error()                                                       *
  210. X *                                                                            *
  211. X * Writes a message of the last error consisting of a the appropriate system  *
  212. X * error string and the appropriate error name to the file specified by 'fd'. *
  213. X *                                                                            *
  214. X * Return values: none!                                                       *
  215. X ******************************************************************************/
  216. Xstatic int
  217. Xprint_system_error(fd)
  218. XFILE *fd;
  219. X{
  220. X    register char *tmpptr;
  221. X
  222. X    switch(errno) {
  223. X    case EADDRINUSE:
  224. X    tmpptr = "EADDRINUSE";
  225. X    break;
  226. X    case EADDRNOTAVAIL:
  227. X    tmpptr = "EADDRNOTAVAIL";
  228. X    break;
  229. X    case EAFNOSUPPORT:
  230. X    tmpptr = "EAFNOSUPPORT";
  231. X    break;
  232. X    case EALREADY:
  233. X    tmpptr = "EALREADY";
  234. X    break;
  235. X    case EBADF:
  236. X    tmpptr = "EBADF";
  237. X    break;
  238. X    case ECONNREFUSED:
  239. X    tmpptr = "ECONNREFUSED";
  240. X    break;
  241. X    case EFAULT:
  242. X    tmpptr = "EFAULT";
  243. X    break;
  244. X    case EINPROGRESS:
  245. X    tmpptr = "EINPROGRESS";
  246. X    break;
  247. X    case EINTR:
  248. X    tmpptr = "EINTR";
  249. X    break;
  250. X    case EINVAL:
  251. X    tmpptr = "EINVAL";
  252. X    break;
  253. X    case EISCONN:
  254. X    tmpptr = "EISCONN";
  255. X    break;
  256. X    case EMSGSIZE:
  257. X    tmpptr = "EMSGSIZE";
  258. X    break;
  259. X    case ENETUNREACH:
  260. X    tmpptr = "ENETUNREACH";
  261. X    break;
  262. X    case ENOBUFS:
  263. X    tmpptr = "ENOBUFS";
  264. X    break;
  265. X    case ENOTSOCK:
  266. X    tmpptr = "ENOTSOCK";
  267. X    break;
  268. X    case EOPNOTSUPP:
  269. X    tmpptr = "EOPNOTSUPP";
  270. X    break;
  271. X    case ETIMEDOUT:
  272. X    tmpptr = "ETIMEDOUT";
  273. X    break;
  274. X    case EWOULDBLOCK:
  275. X    tmpptr = "EWOULDBLOCK";
  276. X    break;
  277. X    default:
  278. X    tmpptr = NULL;
  279. X    } /* switch */
  280. X    if (tmpptr)
  281. X        fprintf(fd, "Reason: %s (%s)\n", sys_errlist[errno], tmpptr);
  282. X    else
  283. X        fprintf(fd, "Reason: %s\n", sys_errlist[errno]);
  284. X    fflush(fd);
  285. X} /* print_system_error */
  286. X
  287. X/******************************************************************************
  288. X * ipc_error()                                                                *
  289. X *                                                                            *
  290. X * Writes a error message indicating the last error occured in the communica- *
  291. X * tion primitives to stderr.                                                 *
  292. X *                                                                            *
  293. X * Return values: none!                                                       *
  294. X ******************************************************************************/
  295. Xstatic int
  296. Xipc_error(msg)
  297. Xchar *msg;
  298. X{
  299. X    fprintf(stderr, "***** ERROR IN COMMUNICATION PRIMITIVES *****\n");
  300. X    fprintf(stderr, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
  301. X        _programname, _processname, _own_port.hostname, getpid());
  302. X    fprintf(stderr, "Error: %s\n", msg);
  303. X    if (errno != 0)
  304. X    print_system_error(stderr);
  305. X    fflush(stderr);
  306. X#ifdef DEBUG_IPC
  307. X    if (_debug_ipc) {
  308. X        fprintf(_debugout, "***** ERROR IN COMMUNICATION PRIMITIVES *****\n");
  309. X        fprintf(_debugout, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
  310. X            _programname, _processname, _own_port.hostname, getpid());
  311. X        fprintf(_debugout, "Error: %s\n", msg);
  312. X        if (errno != 0)
  313. X        print_system_error(_debugout);
  314. X        if (_debugflush)
  315. X            fflush(_debugout);
  316. X    }
  317. X#endif /* DEBUG_IPC /**/
  318. X} /* ipc_error */
  319. X
  320. X/******************************************************************************
  321. X * ipc_fatal_error()                                                          *
  322. X *                                                                            *
  323. X * Writes a error message indicating the last error occured in the communica- *
  324. X * tion primitives to stderr and forces the termination of the program with   *
  325. X * a core dump.                                                               *
  326. X *                                                                            *
  327. X * Return values: this function returns never!                                *
  328. X ******************************************************************************/
  329. Xstatic int
  330. Xipc_fatal_error(loc, msg)
  331. Xchar *loc, *msg;
  332. X{
  333. X    fprintf(stderr, "***** FATAL ERROR IN COMMUNICATION PRIMITIVES *****\n");
  334. X    fprintf(stderr, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
  335. X        _programname, _processname, _own_port.hostname, getpid());
  336. X    fprintf(stderr, "Function: %s Error: %s\n", loc, msg);
  337. X    if (errno != 0)
  338. X        print_system_error(stderr);
  339. X#ifdef DEBUG_IPC
  340. X    if (_debug_ipc) {
  341. X        fprintf(_debugout, "***** FATAL ERROR IN COMMUNICATION PRIMITIVES *****\n");
  342. X        fprintf(_debugout, "PROGRAM: %s, PROCESS: %s, HOST: %s, PID: %d\n",
  343. X            _programname, _processname, _own_port.hostname, getpid());
  344. X        fprintf(_debugout, "Function: %s Error: %s\n", loc, msg);
  345. X        if (errno != 0)
  346. X            print_system_error(_debugout);
  347. X        if (_debugflush)
  348. X        fflush(_debugout);
  349. X    }
  350. X#endif /* DEBUG_IPC /**/
  351. X    signal(SIGIOT, SIG_DFL);
  352. X    abort();
  353. X} /* ipc_fatal_error */
  354. X
  355. X/******************************************************************************
  356. X * display_connection_list()                                                  *
  357. X *                                                                            *
  358. X * Displays the list of established TCP/IP connections.                       **
  359. X *                                                                            *
  360. X * Return values: none!                                                       *
  361. X ******************************************************************************/
  362. Xstatic int
  363. Xdisplay_connection_list()
  364. X{
  365. X    int i;
  366. X    register struct _con *_con_socks;
  367. X
  368. X#ifdef DEBUG_IPC 
  369. X    if (!_debug_ipc)
  370. X    return;
  371. X    fprintf(_debugout, "[ipc] %s connection list:\n", _processprefix);
  372. X    for(_con_socks = _con_socks_first, i = 0; _con_socks; _con_socks = _con_socks->next, i++) {
  373. X    fprintf(_debugout, "[ipc] %s    entry %d:\n", _processprefix, i);
  374. X    fprintf(_debugout, "[ipc] %s      con_sock = %d\n",
  375. X        _processprefix, _con_socks->con_sock);
  376. X    fprintf(_debugout, "[ipc] %s      port1:\n", _processprefix);
  377. X    fprintf(_debugout, "[ipc] %s        portnum  = %d\n",
  378. X        _processprefix, _con_socks->own_port.portnum);
  379. X    fprintf(_debugout, "[ipc] %s        hostname = %s\n",
  380. X        _processprefix, _con_socks->own_port.hostname);
  381. X    fprintf(_debugout, "[ipc] %s      port2:\n", _processprefix);
  382. X    fprintf(_debugout, "[ipc] %s        portnum  = %d\n",
  383. X        _processprefix, _con_socks->other_port.portnum);
  384. X    fprintf(_debugout, "[ipc] %s        hostname = %s\n",
  385. X        _processprefix, _con_socks->other_port.hostname);
  386. X    } /* for */
  387. X#endif /* DEBUG_IPC /**/
  388. X} /* display_connection_list */
  389. X
  390. X/******************************************************************************
  391. X * store_connection_in_list()                                                 *
  392. X *                                                                            *
  393. X * Stores the connection specified by the socket 'con_sock' in the list of    *
  394. X * established TCP/IP connections.                                            *
  395. X *                                                                            *
  396. X * Return values: OK upon success / ERROR upon error                           *
  397. X ******************************************************************************/
  398. Xstatic int
  399. Xstore_connection_in_list(con_sock, own_port, other_port)
  400. Xint con_sock;
  401. XPORTDESCR own_port, other_port;
  402. X{
  403. X    register struct _con *ptr;
  404. X#ifdef CONVEX
  405. X    int close_connections();
  406. X#else
  407. X    static int close_connections();
  408. X#endif
  409. X
  410. X#ifdef DEBUG_IPC
  411. X    if (_debug_ipc) {
  412. X        fprintf(_debugout, "[ipc] %s storing connection in list:\n", _processprefix);
  413. X            fflush(_debugout);
  414. X    fprintf(_debugout, "[ipc] %s      con_sock = %d\n",
  415. X        _processprefix, con_sock);
  416. X    fprintf(_debugout, "[ipc] %s      port1:\n", _processprefix);
  417. X    fprintf(_debugout, "[ipc] %s        portnum  = %d\n",
  418. X        _processprefix, own_port.portnum);
  419. X    fprintf(_debugout, "[ipc] %s        hostname = %s\n",
  420. X        _processprefix, own_port.hostname);
  421. X    fprintf(_debugout, "[ipc] %s      port2:\n", _processprefix);
  422. X    fprintf(_debugout, "[ipc] %s        portnum  = %d\n",
  423. X        _processprefix, other_port.portnum);
  424. X    fprintf(_debugout, "[ipc] %s        hostname = %s\n",
  425. X        _processprefix, other_port.hostname);
  426. X        if (_debugflush)
  427. X            fflush(_debugout);
  428. X    } 
  429. X#endif /* DEBUG_IPC /**/
  430. X    if (!(ptr = (struct _con *) malloc(sizeof(struct _con))))
  431. X        ipc_fatal_error("store_connection_in_list", "out of heap space");
  432. X    ptr->con_sock   = con_sock;
  433. X    ptr->own_port   = own_port;
  434. X    ptr->other_port = other_port;
  435. X    ptr->next       = NULL;
  436. X    if (!_con_socks_first)
  437. X    _con_socks_first = _con_socks_last = ptr;
  438. X    else {
  439. X        _con_socks_last->next = ptr;
  440. X        _con_socks_last = ptr;
  441. X    }
  442. X    /* check if too many connections are open */
  443. X    if (++_con_num > MAXOPENCONS)
  444. X    close_connections(con_sock);
  445. X    return(OK);
  446. X} /* store_connection_in_list */
  447. X
  448. X/******************************************************************************
  449. X * delete_connection_from_list()                                              *
  450. X *                                                                            *
  451. X * Deletes the connection specified by the socket 'con_sock' from the list of *
  452. X * established TCP/IP connections.                                            *
  453. X *                                                                            *
  454. X * Return values: OK upon success                                             *
  455. X ******************************************************************************/
  456. Xstatic int
  457. Xdelete_connection_from_list(con_sock)
  458. Xint con_sock;
  459. X{
  460. X    register struct _con *_con_socks, *last;
  461. X
  462. X#ifdef DEBUG_IPC
  463. X    if (_debug_ipc) {
  464. X        fprintf(_debugout, "[ipc] %s deleting connection:\n",
  465. X            _processprefix);
  466. X        fprintf(_debugout, "[ipc] %s      con_sock = %d\n",
  467. X            _processprefix, _con_socks->con_sock);
  468. X        fprintf(_debugout, "[ipc] %s    port1:\n", _processprefix);
  469. X        fprintf(_debugout, "[ipc] %s      portnum  = %d\n",
  470. X            _processprefix, _con_socks->own_port.portnum);
  471. X        fprintf(_debugout, "[ipc] %s      hostname = %s\n",
  472. X            _processprefix, _con_socks->own_port.hostname);
  473. X        fprintf(_debugout, "[ipc] %s    port2:\n", _processprefix);
  474. X        fprintf(_debugout, "[ipc] %s      portnum  = %d\n",
  475. X            _processprefix, _con_socks->other_port.portnum);
  476. X        fprintf(_debugout, "[ipc] %s      hostname = %s\n",
  477. X            _processprefix, _con_socks->other_port.hostname);
  478. X        if (_debugflush)
  479. X            fflush(_debugout);
  480. X    }
  481. X#endif /* DEBUG_IPC /**/
  482. X    last = NULL;
  483. X    for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
  484. X    if (_con_socks->con_sock == con_sock) {
  485. X        if (!last) {
  486. X        _con_socks_first = _con_socks->next;
  487. X        free(_con_socks);
  488. X        } else {
  489. X        last->next = _con_socks->next;
  490. X        free(_con_socks);
  491. X        }
  492. X        _con_num--;
  493. X        return(OK);
  494. X    } 
  495. X    last = _con_socks;
  496. X    } /* for */
  497. X    ipc_fatal_error("delete_connection_from_list", "connection not found in list");
  498. X} /* delete_connection_from_list */
  499. X
  500. X/******************************************************************************
  501. X * close_connections()                                                        *
  502. X *                                                                            *
  503. X * Closes CLOSECONNUM stored connections from the list of established TCP/IP  *
  504. X * connections except the connection specified by 'con_sock'.                  *
  505. X *                                                                            *
  506. X * Return values: OK upon success                                             *
  507. X ******************************************************************************/
  508. Xstatic int
  509. Xclose_connections(con_sock)
  510. Xint con_sock;
  511. X{
  512. X    register struct _con *_con_socks, *next;
  513. X    int num, act_con_sock;
  514. X
  515. X#ifdef DEBUG_IPC
  516. X    if (_debug_ipc) {
  517. X        fprintf(_debugout, "[ipc] %s closing %d connections\n",
  518. X        _processprefix, CLOSECONNUM);
  519. X        if (_debugflush)
  520. X            fflush(_debugout);
  521. X    }
  522. X#endif /* DEBUG_IPC /**/
  523. X    num = CLOSECONNUM;
  524. X    _con_socks = _con_socks_first; 
  525. X    while(_con_socks && num) {
  526. X    act_con_sock = _con_socks->con_sock;
  527. X        next = _con_socks->next;
  528. X    if (_con_socks->con_sock != con_sock) {
  529. X#ifdef DEBUG_IPC
  530. X        if (_debug_ipc) {
  531. X            fprintf(_debugout, "[ipc] %s deleting and closing socket %d\n",
  532. X            _processprefix, act_con_sock);
  533. X                if (_debugflush)
  534. X                    fflush(_debugout);
  535. X        }
  536. X#endif /* DEBUG_IPC /**/
  537. X        (void) close(act_con_sock);
  538. X        delete_connection_from_list(act_con_sock);
  539. X        num--;
  540. X    }
  541. X    _con_socks = next;
  542. X    } /* while */
  543. X    DEBUGPUTS("connections closed");
  544. X    display_connection_list();
  545. X    return(OK);
  546. X} /* close_connections */
  547. X
  548. X/******************************************************************************
  549. X * timeout_proc()                                                             *
  550. X *                                                                            *
  551. X * Sets the timeout flag 'timeout' to indicate a timeout error.               *
  552. X *                                                                            *
  553. X * Return values: none!                                                       *
  554. X ******************************************************************************/
  555. X#ifdef UNICOS
  556. Xstatic void
  557. Xtimeout_proc(sig)
  558. Xint sig;
  559. X#else
  560. Xstatic void
  561. Xtimeout_proc(sig, code, scp)
  562. Xint sig, code;
  563. Xstruct sigcontext *scp;
  564. X#endif
  565. X{
  566. X    DEBUGPUTS("***** timeout_proc():");
  567. X    timeout = TRUE;
  568. X#ifdef HPUX
  569. X    scp->sc_syscall_action = SIG_RETURN; /* abort interrupted system call! */
  570. X#endif
  571. X} /* timeout_proc */
  572. X
  573. X/******************************************************************************
  574. X * catch_SIGPIPE()                                                            *
  575. X *                                                                            *
  576. X * Catches the signal SIGPIPE and stores TRUE in 'sigpipe'.                   *
  577. X *                                                                            *
  578. X * Return values: none!                                                       *
  579. X ******************************************************************************/
  580. X#ifdef UNICOS
  581. Xstatic void
  582. Xcatch_SIGPIPE(sig)
  583. Xint sig;
  584. X#else
  585. Xstatic void
  586. Xcatch_SIGPIPE(sig, code, scp)
  587. Xint sig, code;
  588. Xstruct sigcontext *scp;
  589. X#endif
  590. X{
  591. X    DEBUGPUTS("***** catch_SIGPIPE():");
  592. Xputs("SIGPIPE"); fflush(stdout);
  593. X    sigpipe = TRUE;
  594. X#ifdef HPUX
  595. X    scp->sc_syscall_action = SIG_RETURN; /* abort interrupted system call! */
  596. X#endif
  597. X} /* catch_SIGPIPE */
  598. X
  599. X/******************************************************************************
  600. X * _create_port()                                                             *
  601. X *                                                                            *
  602. X * Creates a new communication endpoint.                                      *
  603. X *                                                                            *
  604. X * Return values: OK = success / ERROR = error                                *
  605. X ******************************************************************************/
  606. Xint
  607. X_create_port(port)
  608. XPORTDESCR *port;
  609. X{
  610. X    int                sock,
  611. X                       res;
  612. X    u_short            portnum;
  613. X    struct sockaddr_in so_addr;
  614. X
  615. X#ifdef DEBUG_IPC
  616. X    if (_debug_ipc) {
  617. X        fprintf(_debugout, "[ipc] %s ***** _create_port():\n", _processprefix);
  618. X        fprintf(_debugout, "[ipc] %s &port = %d\n", _processprefix, port);
  619. X    }
  620. X#endif /* DEBUG_IPC /**/
  621. X    /* set Errno */
  622. X    Errno = ECREATEPORT;
  623. X    /* create a TCP socket */
  624. X    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  625. X        ipc_error("system call: socket()");
  626. X        return(ERROR);
  627. X    }
  628. X    /* initialize components of internet address */
  629. X    bzero(&so_addr, sizeof(so_addr));
  630. X    so_addr.sin_family = AF_INET;
  631. X    so_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  632. X    /* bind socket to an unused address (port number) */
  633. X    for (portnum = STARTPORT; portnum <= ENDPORT; portnum++) {
  634. X#ifdef DEBUG_IPC
  635. X    if (_debug_ipc) 
  636. X            fprintf(_debugout,"[ipc] %s trying to bind socket to portnum %d\n", 
  637. X                _processprefix, htons(portnum));
  638. X#endif /* DEBUG_IPC /**/
  639. X        so_addr.sin_port = portnum;
  640. X        if (!(res = bind(sock, (struct sockaddr *) &so_addr, sizeof(so_addr)))){
  641. X            if (listen(sock, 1)) {
  642. X                ipc_error("system call: listen()");
  643. X                return(ERROR);
  644. X            }
  645. X        /* 
  646. X         * Initialize port and return 
  647. X         */
  648. X            bzero((char *) port, sizeof(PORTDESCR));
  649. X        port->state    = CONNECTIONLESS;
  650. X        port->acc_sock = sock;
  651. X        port->portnum  = portnum;
  652. X            if (gethostname(port->hostname, MAXHOSTNAMELEN)) {
  653. X            ipc_error("gethostname()");
  654. X            return(ERROR);
  655. X            }
  656. X        port->con_sock = 0;
  657. X            DEBUGPUTS("port successfully created");
  658. X            /* clear Errno and return */
  659. X        Errno = OK;
  660. X            return(OK);
  661. X        }
  662. X        if ((res < 0) && (errno == EACCES)) {
  663. X            ipc_error("can't access socket");
  664. X            return (ERROR);
  665. X    }
  666. X        if (portnum > ENDPORT)
  667. X            portnum = STARTPORT;
  668. X    } /* for */
  669. X    ipc_fatal_error("_create_port()", "no portnum found");
  670. X} /* _create_port */
  671. X
  672. X/******************************************************************************
  673. X * _delete_port()                                                             *
  674. X *                                                                            *
  675. X * Deletes the communication endpoint specified by 'port'.                     *
  676. X *                                                                            *
  677. X * Return values: OK = success / ERROR = error                                *
  678. X ******************************************************************************/
  679. Xint
  680. X_delete_port(port)
  681. XPORTDESCR *port;
  682. X{
  683. X    register struct _con *_con_socks;
  684. X#ifdef DEBUG_IPC
  685. X    if (_debug_ipc) {
  686. X        fprintf(_debugout, "[ipc] %s ***** _delete_port():\n", _processprefix);
  687. X        _display_port_info("[ipc]", "port", *port);
  688. X    }
  689. X#endif /* DEBUG_IPC /**/
  690. X    /* set Errno */
  691. X    Errno = EDELETEPORT;
  692. X    /* check port state */
  693. X    if (port->state != CONNECTIONLESS)
  694. X    ipc_fatal_error("_delete_port()", "port state is not CONNECTIONLESS");
  695. X    /* close connection if there's any */
  696. X    if (port->con_sock)
  697. X    (void) close(port->con_sock);
  698. X    /* close socket */
  699. X    if (close(port->acc_sock)) {
  700. X           ipc_error("system call: close()");
  701. X           return(ERROR);
  702. X    }
  703. X    /* shut down all open connections */
  704. X    for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
  705. X    (void) close(_con_socks->con_sock);
  706. X    }
  707. X    /* clear Errno and return */
  708. X    Errno = OK;
  709. X    return(OK);
  710. X} /* _delete_port */
  711. X
  712. X/******************************************************************************
  713. X * _accept_connection()                                                       *
  714. X *                                                                            *
  715. X * Communication endpoint 'port' waits 'time' real time seconds for a          *
  716. X * connection request (if 'time' equals 0 then the operation is unlimited).   *
  717. X *                                                                            *
  718. X * Return values: OK = success / ERROR = error                                *
  719. X ******************************************************************************/
  720. Xint
  721. X_accept_connection(con_port, port, time)
  722. XCONNECTIONDESCR *con_port;
  723. XPORTDESCR       *port;
  724. Xunsigned         time;
  725. X{
  726. X    static int    i,
  727. X                  num,
  728. X                  con_sock,
  729. X                  con_addr_len,
  730. X                  connector_portnum,
  731. X                  newconnection,
  732. X                  setsoptarg;
  733. X    char          connector_hostname[MAXHOSTNAMELEN],
  734. X                  address[MAXHOSTNAMELEN+20],
  735. X                  buffer[CON_MSGLEN+5];
  736. X    PORTDESCR other_port;
  737. X    register struct _con *_con_socks;
  738. X    struct timeval timevalarg;
  739. X    static fd_set readfds;
  740. X    static struct sockaddr_in con_addr;
  741. X
  742. X#ifdef DEBUG_IPC
  743. X    if (_debug_ipc) {
  744. X        fprintf(_debugout, "[ipc] %s ***** _accept_connection():\n",
  745. X        _processprefix);
  746. X        fprintf(_debugout, "[ipc] %s &con_port = %d\n", _processprefix,
  747. X        con_port);
  748. X        _display_port_info("[ipc]", "port", *port);
  749. X        fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
  750. Xdisplay_connection_list();
  751. X    }
  752. X#endif /* DEBUG_IPC /**/
  753. X    /* set Errno */
  754. X    Errno = EACPTCON;
  755. X    /* set timer, if time equals 0 clear timer */
  756. X    SETTIMER(time);
  757. X    while(!timeout) {
  758. X    /* check port state */
  759. X    if (port->state != CONNECTIONLESS)
  760. X        ipc_fatal_error("_accept_connection()", "port state is not CONNECTIONLESS");
  761. X    DEBUGPUTS("state: CONNECTIONLESS");
  762. Xdisplay_connection_list();
  763. X    /* initialize readfds */
  764. X    FD_ZERO(&readfds);
  765. X    FD_SET(port->acc_sock, &readfds);
  766. X        for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
  767. X        FD_SET(_con_socks->con_sock, &readfds);
  768. X    }
  769. X    /* First we wait until one or more process(es) want(s) to connect to us
  770. X     * (connect() to port->acc_sock) or one or more process(es) want(s) to
  771. X     * send some data to us using an existing connection.
  772. X     */
  773. X    port->state = SELECTING;
  774. X    DEBUGPUTS("state: SELECTING");
  775. X    if (select(FD_SETSIZE, SELECT_CAST &readfds, SELECT_CAST NULL, SELECT_CAST NULL,
  776. X                                             (struct timeval *) NULL) < 0) {
  777. X        if (errno == EINTR && timeout) {
  778. X            /* return TIMEOUT error to caller */
  779. X            continue; 
  780. X        }
  781. X            switch(errno) {
  782. X        case EBADF:
  783. X        case EFAULT:
  784. X        /* remove connections that have been closed */
  785. X        timevalarg.tv_sec  = 0;
  786. X        timevalarg.tv_usec = 1;
  787. X        for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
  788. X            FD_ZERO(&readfds);
  789. X            FD_SET(_con_socks->con_sock, &readfds);
  790. X            if (select(FD_SETSIZE, SELECT_CAST &readfds, SELECT_CAST NULL, SELECT_CAST NULL,
  791. X                                                         &timevalarg) < 0) {
  792. X#ifdef DEBUG_IPC
  793. X                if (_debug_ipc) {
  794. X                fprintf(_debugout, "[ipc] %s closed connection found! socket is %d\n", 
  795. X                _processprefix, _con_socks->con_sock);
  796. X            if (_debugflush)
  797. X                fflush(_debugout);
  798. X            }
  799. X#endif /* DEBUG_IPC /**/
  800. X                delete_connection_from_list(_con_socks->con_sock);
  801. X            }
  802. X        } /* for */
  803. X        break;
  804. X        default:
  805. X            ipc_error("system call: select()");
  806. X            return(ERROR);
  807. X        } /* switch */
  808. X        port->state = CONNECTIONLESS;
  809. X        DEBUGPUTS("state: CONNECTIONLESS");
  810. X            (void) close(con_sock); 
  811. X            continue;
  812. X    }
  813. X    /* Upon completion of select(), we look first if one or more process 
  814. X     * want(s) to establish a new connection (CASE 1) (Note: new connections
  815. X     * are prefered!) Otherwise we choose one of the process(es) that 
  816. X     * want(s) to send data to us (CASE 2)!
  817. X     */
  818. X    /* clear connection descriptor */
  819. X    con_sock = 0;
  820. X    /* clear new connection flag */
  821. X    newconnection = 0;
  822. X    /* set connection descriptor */
  823. X    if (FD_ISSET(port->acc_sock, &readfds)) {
  824. X        /* CASE 1: accept a new connection */
  825. X        port->state = ACCEPTING;
  826. X        DEBUGPUTS("state: ACCEPTING");
  827. X            con_addr_len = sizeof(con_addr);
  828. X            if ((con_sock = accept(port->acc_sock, (struct sockaddr *) &con_addr,
  829. X                                                      &con_addr_len)) < 0) {
  830. X                switch(errno) {
  831. X            case EMFILE:
  832. X            /* ipc_fatal_error("accept()", "too many open connections or files"); */
  833. X            fprintf(stderr, "%s too many connections open\n", _processprefix);
  834. X            fprintf(stderr, "%s closing %d connections\n", _processprefix, CLOSECONNUM);
  835. X            fflush(stderr);
  836. X            close_connections(0);
  837. X            fprintf(stderr, "%s sleeping 15 seconds to get connections closed\n", _processprefix);
  838. X            fflush(stderr);
  839. X            sleep(15);
  840. X            fprintf(stderr, "%s ok - trying again\n", _processprefix);
  841. X            fflush(stderr);
  842. X            break;
  843. X            case ECONNRESET:
  844. X            DEBUGPUTS("connection reset by peer");
  845. X            break;
  846. X            default:
  847. X                ipc_error("system call: accept()");
  848. X            return(ERROR);
  849. X            } /* switch */
  850. X            DEBUGPUTS("trying again");
  851. X        (void) close(con_sock);
  852. X            port->state = CONNECTIONLESS;
  853. X            DEBUGPUTS("state: CONNECTIONLESS");
  854. X            continue;
  855. X            }
  856. X        newconnection = 1;
  857. X    } else {
  858. X        /* CASE 2: reuse old, already existing connection */
  859. X            for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
  860. X            if (FD_ISSET(_con_socks->con_sock, &readfds)) {
  861. X                DEBUGPUTS("reusing old connection");
  862. X            con_sock = _con_socks->con_sock;
  863. X            break;
  864. X        }
  865. X        }
  866. X    }
  867. X    /* If con_port equals zero at this point, select() returned indicating
  868. X     * an ending connection. Unfortunately we don't know which connection
  869. X     * it was! So we can't delete it from the list at this point.
  870. X     */
  871. X    if (!con_sock) {
  872. X        DEBUGPUTS("a connection was closed (1)");
  873. X        DEBUGPUTS("trying again");
  874. X        port->state = CONNECTIONLESS;
  875. X        DEBUGPUTS("state: CONNECTIONLESS");
  876. X        continue;
  877. X    }
  878. X        /* Well! We have a correct connection, specified by con_sock.
  879. X     * A request message of length zero indicates again the ending of 
  880. X     * a connection. We consider this aspect.
  881. X     * Now let's look for a correct request message.
  882. X     */
  883. X    port->state = RECV_REQ;
  884. X    DEBUGPUTS("state: RECV_REQ");
  885. X        if ((num = read(con_sock, buffer, CON_MSGLEN + 5)) < 0) {
  886. X        if (errno == EINTR && timeout) {
  887. X        /* return TIMEOUT error to caller */
  888. X        continue; 
  889. X        }
  890. X            switch(errno) {
  891. X        case EBADF:
  892. X        DEBUGPUTS("bad file number, trying again");
  893. X        break;
  894. X        case ECONNRESET:
  895. X        DEBUGPUTS("connection reset by peer, trying again");
  896. X        break;
  897. X        default:
  898. X            ipc_error("system call: read() - 1");
  899. X        return(ERROR);
  900. X        } /* switch */
  901. X        port->state = CONNECTIONLESS;
  902. X        DEBUGPUTS("state: CONNECTIONLESS");
  903. X            (void) close(con_sock); 
  904. X            continue;
  905. X    }
  906. X    if (num == 0) {
  907. X        DEBUGPUTS("a connection was closed (2)");
  908. X        DEBUGPUTS("trying again");
  909. X        (void) close(con_sock);
  910. X        port->state = CONNECTIONLESS;
  911. X        DEBUGPUTS("state: CONNECTIONLESS");
  912. X        continue;
  913. X    }
  914. X        if (num != CON_MSGLEN || strcmp(buffer, CON_REQUEST)) {
  915. X            DEBUGPUTS("bad request message received");
  916. X        DEBUGPUTS("trying again");
  917. X        port->state = CONNECTIONLESS;
  918. X        DEBUGPUTS("state: CONNECTIONLESS");
  919. X        continue;
  920. X        }
  921. X    /* The request message was o.k. as well. Therefore we send back 
  922. X     * the reply message.
  923. X     */
  924. X    port->state = SEND_REP;
  925. X    DEBUGPUTS("state: SEND_REP");
  926. X    CATCHSIGPIPE;
  927. X        if ((num = write(con_sock, CON_ACCEPTED, CON_MSGLEN)) < 0) {
  928. X        if (errno == EINTR && timeout) {
  929. X        /* return TIMEOUT error to caller */
  930. X        continue; 
  931. X        }
  932. X        if (sigpipe) {
  933. X        /* connection was closed by foreign host */
  934. X        errno = EPIPE;
  935. X        sigpipe = FALSE;
  936. X        }
  937. X            switch(errno) {
  938. X        case EBADF:
  939. X        DEBUGPUTS("bad file number, trying again");
  940. X        break;
  941. X        case EPIPE:
  942. X        DEBUGPUTS("broken pipe, trying again");
  943. X        break;
  944. X        case ECONNRESET:
  945. X        DEBUGPUTS("connection reset by peer, trying again");
  946. X        break;
  947. X        default:
  948. X            ipc_error("system call: write() - 1");
  949. X        return(ERROR);
  950. X        } /* switch */
  951. X            (void) close(con_sock); 
  952. X        port->state = CONNECTIONLESS;
  953. X        DEBUGPUTS("state: CONNECTIONLESS");
  954. X            continue;
  955. X    }
  956. X        if (num != CON_MSGLEN) {
  957. X        errno = 0;
  958. X            ipc_error("sending reply message");
  959. X            return(ERROR);
  960. X    }
  961. X    /* After correct handshaking of request and reply, we receive
  962. X     * the address of the process connecting to us.
  963. X     * We also check if the TCP/IP connection was ending!
  964. X     */
  965. X    port->state = RECV_ADDR;
  966. X    DEBUGPUTS("state: RECV_ADDR");
  967. X    if ((num = read(con_sock, address, sizeof(address))) < 0) {
  968. X        if (errno == EINTR && timeout) {
  969. X        /* return TIMEOUT error to caller */
  970. X        continue; 
  971. X        }
  972. X            switch(errno) {
  973. X        case EBADF:
  974. X        DEBUGPUTS("bad file number, trying again");
  975. X        break;
  976. X        case ECONNRESET:
  977. X        DEBUGPUTS("connection reset by peer, trying again");
  978. X        break;
  979. X        default:
  980. X            ipc_error("system call: read() - 2");
  981. X        return(ERROR);
  982. X        } /* switch */
  983. X            (void) close(con_sock); 
  984. X        port->state = CONNECTIONLESS;
  985. X        DEBUGPUTS("state: CONNECTIONLESS");
  986. X            continue;
  987. X    }
  988. X    if (num == 0) {
  989. X        DEBUGPUTS("connection was closed");
  990. X        if (!newconnection)
  991. X            delete_connection_from_list(con_sock);
  992. X        DEBUGPUTS("trying again");
  993. X            (void) close(con_sock); 
  994. X        port->state = CONNECTIONLESS;
  995. X        DEBUGPUTS("state: CONNECTIONLESS");
  996. X        continue;
  997. X    }
  998. X    if (num != sizeof(address)) {
  999. X        DEBUGPUTS("bad address received");
  1000. X        DEBUGPUTS("trying again");
  1001. X            (void) close(con_sock); 
  1002. X        port->state = CONNECTIONLESS;
  1003. X        DEBUGPUTS("state: CONNECTIONLESS");
  1004. X        continue;
  1005. X    }
  1006. X    sscanf(address, "%d|%s", &connector_portnum, connector_hostname);
  1007. X    /* Connection establishment completed!
  1008. X     * Initialize variables and return to calling program.
  1009. X     */
  1010. X    port->state = CONNECTED;
  1011. X    DEBUGPUTS("state: CONNECTED");
  1012. X    /* Initialize connection port */
  1013. X    con_port->state    = CONNECTED;
  1014. X    con_port->con_sock = con_sock;
  1015. X    con_port->own_port = port;
  1016. X    con_port->other_port = NULL;
  1017. X    /* If we have accepted a new TCP/IP connection, we store it
  1018. X     * in the connection list.
  1019. X     */
  1020. X    if (newconnection) {
  1021. X        other_port.state    = -1;
  1022. X        other_port.acc_sock = -1;;
  1023. X        other_port.con_sock = -1;;
  1024. X        other_port.portnum  = connector_portnum;
  1025. X        strcpy(other_port.hostname, connector_hostname);
  1026. X        store_connection_in_list(con_sock, *port, other_port);
  1027. X    }
  1028. X#ifdef DEBUG_IPC
  1029. X    if (_debug_ipc) {
  1030. X        fprintf(_debugout, "[ipc] %s address of connector:\n",
  1031. X        _processprefix);
  1032. X        fprintf(_debugout, "[ipc] %s    portnum  = %d\n", 
  1033. X        _processprefix, connector_portnum);
  1034. X        fprintf(_debugout, "[ipc] %s    hostname = %s\n", 
  1035. X        _processprefix, connector_hostname);
  1036. X        display_connection_list();
  1037. X    }
  1038. X#endif /* DEBUG_IPC /**/
  1039. X    /* check periodically if connection is still alive */
  1040. X    setsoptarg = 1;
  1041. X    if (setsockopt(con_sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &setsoptarg, sizeof(int)) < 0) {
  1042. X        ipc_error("system_call: setsockopt(SO_KEEPALIVE)");
  1043. X        return(ERROR);
  1044. X    }
  1045. X        /* clear timer and return */
  1046. X        (void) alarm(0);
  1047. X    DEBUGPUTS("connection accepted");
  1048. X    Errno = OK;
  1049. X        return(OK);
  1050. X    } /* while */
  1051. X    DEBUGPUTS("TIMEOUT");
  1052. X    port->state = CONNECTIONLESS;
  1053. X    DEBUGPUTS("state: CONNECTIONLESS");
  1054. X    Errno = ETIMEOUT;
  1055. X    return(ERROR);
  1056. X} /* _accept_connection */
  1057. X
  1058. X/******************************************************************************
  1059. X * _make_connection()                                                         *
  1060. X *                                                                            *
  1061. X * Communication enpoint 'port1' tries 'time' real time seconds to connect    *
  1062. X * to 'port2' (if 'time' equals 0 then the operation is unlimited).            *
  1063. X *                                                                            *
  1064. X * Return values: OK = success / ERROR = error                                *
  1065. X ******************************************************************************/
  1066. Xint
  1067. X_make_connection(con_port, port1, port2, time)
  1068. XCONNECTIONDESCR *con_port;
  1069. XPORTDESCR       *port1;
  1070. XPORTDESCR       *port2;
  1071. Xunsigned         time;
  1072. X{
  1073. X    int  i,
  1074. X         num,
  1075. X         con_sock,
  1076. X         con_addr_len,
  1077. X         setsoptarg;
  1078. X    char buffer[CON_MSGLEN+5],
  1079. X         address[MAXHOSTNAMELEN+20];
  1080. X    static struct sockaddr_in con_addr;
  1081. X    static struct hostent *hostinfo;
  1082. X    register struct _con *_con_socks;
  1083. X    struct timeval timevalarg;
  1084. X    static fd_set writefds;
  1085. X
  1086. X#ifdef DEBUG_IPC
  1087. X    if (_debug_ipc) {
  1088. X        fprintf(_debugout, "[ipc] %s ***** _make_connection():\n",
  1089. X        _processprefix);
  1090. X        fprintf(_debugout, "[ipc] %s &con_port = %d\n", _processprefix, 
  1091. X        con_port);
  1092. X        _display_port_info("[ipc]", "port1", *port1);
  1093. X        _display_port_info("[ipc]", "port2", *port2);
  1094. X        fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
  1095. Xdisplay_connection_list();
  1096. X    }
  1097. X#endif /* DEBUG_IPC /**/
  1098. X    /* set Errno */
  1099. X    Errno = EMAKECON;
  1100. X    /* set timer, if time equals 0 clear timer */
  1101. X    SETTIMER(time);
  1102. X    while(!timeout) {
  1103. X    /* check port state */
  1104. X    if (port1->state != CONNECTIONLESS)
  1105. X        ipc_fatal_error("_make_connection()", "port state is not CONNECTIONLESS");
  1106. X    /* clear connection descriptor */
  1107. X    con_sock = 0;
  1108. X    /* If there's already an existing TCP/IP connection we use it (CASE 1).
  1109. X     * Otherwise we try to connect to the other port (CASE 2).
  1110. X     */
  1111. X    if (port2->con_sock) {
  1112. X        /* CASE 1a: connection exists! */
  1113. X        con_sock = port2->con_sock;
  1114. X    } else {
  1115. X        /* look if connection was already accepted! */
  1116. X        DEBUGPUTS("searching in connection list");
  1117. X            for(_con_socks = _con_socks_first; _con_socks; _con_socks = _con_socks->next) {
  1118. X        if (port2->portnum == _con_socks->other_port.portnum 
  1119. X           && !strcmp(port2->hostname, _con_socks->other_port.hostname)) {
  1120. X                /* CASE 1b: connection exists! */
  1121. X            DEBUGPUTS("using old connection");
  1122. X            con_sock = _con_socks->con_sock;
  1123. X            /* check if connection is still alive! */
  1124. X            FD_ZERO(&writefds);
  1125. X            FD_SET(con_sock, &writefds);
  1126. X            if (select(FD_SETSIZE, SELECT_CAST NULL, SELECT_CAST &writefds, 
  1127. X                              SELECT_CAST NULL, &timevalarg) < 0) {
  1128. X#ifdef DEBUG_IPC
  1129. X                    if (_debug_ipc) {
  1130. X                        fprintf(_debugout, "[ipc] %s closed connection found! socket is %d\n",
  1131. X                                _processprefix, _con_socks->con_sock);
  1132. X                        if (_debugflush)
  1133. X                            fflush(_debugout);
  1134. X#endif /* DEBUG_IPC /**/
  1135. X                        delete_connection_from_list(_con_socks->con_sock);
  1136. X                    con_sock = 0;
  1137. X                    }
  1138. X            }
  1139. X            break;
  1140. X        }
  1141. X        } /* for */
  1142. X        /* If con_sock equals zero, there was no connection found in
  1143. X         * the array storing established TCP/IP connections. 
  1144. X         * Because of that, we establish a new connection
  1145. X         */
  1146. X        if (con_sock == 0) {
  1147. X            /* CASE 2: establish a new TCP/IP connection! */
  1148. X        port1->state = CONNECTING;
  1149. X        DEBUGPUTS("state: CONNECTING");
  1150. X                /* create a new TCP socket 
  1151. X         * NOTE: a new socket is used instead of port1
  1152. X         */
  1153. X                if ((con_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  1154. X                    ipc_error("system call: socket()");
  1155. X                    return(ERROR);
  1156. X                }
  1157. X                /* clear calling address */
  1158. X                bzero(&con_addr, sizeof(con_addr));
  1159. X                /* set address family of called host */
  1160. X                con_addr.sin_family = AF_INET;
  1161. X            /* get host information of called host */
  1162. X        hostinfo = NULL;
  1163. X        while(!timeout && !hostinfo)
  1164. X                hostinfo = gethostbyname(port2->hostname);
  1165. X            if (errno == EINTR && timeout) {
  1166. X            /* return TIMEOUT error to caller */
  1167. X            fputs("timeout caused by gethostbyname()!\n", stderr);
  1168. X                Errno = ETIMEOUT;
  1169. X                return(ERROR);
  1170. X            }
  1171. X                /* set address of called host */
  1172. X                bcopy(hostinfo->h_addr, &con_addr.sin_addr, hostinfo->h_length);
  1173. X                /* set portnum of called host */
  1174. X                con_addr.sin_port = port2->portnum;
  1175. X                /* try to connect */
  1176. X                if (connect(con_sock, (struct sockaddr *) &con_addr, sizeof(con_addr)) < 0){
  1177. X                    switch(errno) {
  1178. X            case ETIMEDOUT:
  1179. X                DEBUGPUTS("attempt timed out by system, trying again");
  1180. X            break;
  1181. X            case EISCONN:
  1182. X                DEBUGPUTS("port is connected, trying again");
  1183. X            break;
  1184. X            case ECONNREFUSED:
  1185. X                DEBUGPUTS("connection refused, trying again");
  1186. X            break;
  1187. X            default:
  1188. X                    ipc_error("system call: connect()");
  1189. X            } /* switch */
  1190. X            port1->state = CONNECTIONLESS;
  1191. X            DEBUGPUTS("state: CONNECTIONLESS");
  1192. X                    (void) close(con_sock); 
  1193. X                    continue;
  1194. X                }
  1195. X        /* TCP/IP connection established! Store connection information
  1196. X         * in connection list.
  1197. X         */
  1198. X        store_connection_in_list(con_sock, *port1, *port2);
  1199. X#ifdef DEBUG_IPC
  1200. X        if (_debug_ipc) 
  1201. X            display_connection_list();
  1202. X#endif /* DEBUG_IPC /**/
  1203. X        }
  1204. X    }
  1205. X    /* At this point, con_sock specifies a network connection to the called
  1206. X     * port. If the stored connection was closed at the other side we will
  1207. X     * get an EBADF, EPIPE or ECONNRESET error or receive signal SIGPIPE. 
  1208. X     * In this case we delete the stored connection and try it again. 
  1209. X     * Now we send a request message.
  1210. X     */
  1211. X    port1->state = SEND_REQ;
  1212. X    DEBUGPUTS("state: SEND_REQ");
  1213. X    CATCHSIGPIPE;
  1214. X        if ((num = write(con_sock, CON_REQUEST, CON_MSGLEN)) < 0) {
  1215. X        if (errno == EINTR && timeout) {
  1216. X        /* return TIMEOUT error to caller */
  1217. X        continue; 
  1218. X        }
  1219. X        if (sigpipe) {
  1220. X        /* connection was closed by foreign host */
  1221. X        errno = EPIPE;
  1222. X        sigpipe = FALSE;
  1223. X        }
  1224. X            switch(errno) {
  1225. X        case EBADF:
  1226. X        DEBUGPUTS("bad file number, trying again");
  1227. X        break;
  1228. X        case EPIPE:
  1229. X        DEBUGPUTS("broken pipe, trying again");
  1230. X        break;
  1231. X        case ECONNRESET:
  1232. X        DEBUGPUTS("connection reset by peer, trying again");
  1233. X        break;
  1234. X        default:
  1235. X            ipc_error("system call: write() - 2");
  1236. X        return(ERROR);
  1237. X        } /* switch */
  1238. X        DEBUGPUTS("stored connection not longer valid");
  1239. X        delete_connection_from_list(con_sock);
  1240. X            (void) close(con_sock); 
  1241. X        port1->state = CONNECTIONLESS;
  1242. X        DEBUGPUTS("state: CONNECTIONLESS");
  1243. X            continue;
  1244. X    }
  1245. X        if (num != CON_MSGLEN) {
  1246. X        errno = 0;
  1247. X            ipc_error("sending request");
  1248. X            return(ERROR);
  1249. X    }
  1250. X    /* Well! The request message was successfully sent to the called 
  1251. X     * process. Now receive the reply message. We must also take care
  1252. X     * if the connection is ending during our handshaking!
  1253. X     */
  1254. X    port1->state = RECV_REP;
  1255. X    DEBUGPUTS("state: RECV_REP");
  1256. X        if ((num = read(con_sock, buffer, CON_MSGLEN + 5)) < 0) {
  1257. X        if (errno == EINTR && timeout) {
  1258. X        /* return TIMEOUT error to caller */
  1259. X        continue; 
  1260. X        }
  1261. X            switch(errno) {
  1262. X        case EBADF:
  1263. X        DEBUGPUTS("bad file number, trying again");
  1264. X        break;
  1265. X        case ECONNRESET:
  1266. X        DEBUGPUTS("connection reset by peer, trying again");
  1267. X        break;
  1268. X        default:
  1269. X            ipc_error("system call: read() - 3");
  1270. X        return(ERROR);
  1271. X        } /* switch */
  1272. X        DEBUGPUTS("stored connection not longer valid");
  1273. X        delete_connection_from_list(con_sock);
  1274. X            (void) close(con_sock); 
  1275. X        port1->state = CONNECTIONLESS;
  1276. X        DEBUGPUTS("state: CONNECTIONLESS");
  1277. X            continue;
  1278. X    }
  1279. X    if (num == 0) {
  1280. X        DEBUGPUTS("connection was closed");
  1281. X        delete_connection_from_list(con_sock);
  1282. X        DEBUGPUTS("trying again");
  1283. X            (void) close(con_sock); 
  1284. X        port1->state = CONNECTIONLESS;
  1285. X        DEBUGPUTS("state: CONNECTIONLESS");
  1286. X        continue;
  1287. X    }
  1288. X        if (num != CON_MSGLEN) {
  1289. X            DEBUGPUTS("bad reply message received");
  1290. X        DEBUGPUTS("trying again");
  1291. X        port1->state = CONNECTIONLESS;
  1292. X        DEBUGPUTS("state: CONNECTIONLESS");
  1293. X        continue;
  1294. X    }
  1295. X    /* After correct handshaking of request and reply, send the own
  1296. X     * address to the called process, initialize the variables and
  1297. X     * return to the calling program.
  1298. X     */
  1299. X        if (!strcmp(buffer, CON_ACCEPTED)) {
  1300. X        port1->state = SEND_ADDR;
  1301. X        DEBUGPUTS("state: SEND_ADDR");
  1302. X        /* send address */
  1303. X        sprintf(address, "%d|%s", port1->portnum, port1->hostname);
  1304. X        CATCHSIGPIPE;
  1305. X        if ((num = write(con_sock, address, sizeof(address))) < 0) {
  1306. X            if (errno == EINTR && timeout) {
  1307. X            /* return TIMEOUT error to caller */
  1308. X            continue; 
  1309. X            }
  1310. X            if (sigpipe) {
  1311. X            /* connection was closed by foreign host */
  1312. X            errno = EPIPE;
  1313. X            sigpipe = FALSE;
  1314. X            }
  1315. X                switch(errno) {
  1316. X            case EBADF:
  1317. X            DEBUGPUTS("bad file number, trying again");
  1318. X            break;
  1319. X            case EPIPE:
  1320. X            DEBUGPUTS("broken pipe, trying again");
  1321. X            break;
  1322. X            case ECONNRESET:
  1323. X            DEBUGPUTS("connection reset by peer, trying again");
  1324. X            break;
  1325. X            default:
  1326. X                ipc_error("system call: write() - 3");
  1327. X            return(ERROR);
  1328. X            } /* switch */
  1329. X            DEBUGPUTS("stored connection not longer valid");
  1330. X            delete_connection_from_list(con_sock);
  1331. X            port1->state = CONNECTIONLESS;
  1332. X            DEBUGPUTS("state: CONNECTIONLESS");
  1333. X                (void) close(con_sock); 
  1334. X                continue;
  1335. X        }
  1336. X            if (num != sizeof(address)) {
  1337. X        errno = 0;
  1338. X                ipc_error("sending adress");
  1339. X                return(ERROR);
  1340. X        }
  1341. X        port1->state = CONNECTED;
  1342. X        DEBUGPUTS("state: CONNECTED");
  1343. X        /* Initialize connection port */
  1344. X        con_port->state      = CONNECTED;
  1345. X        con_port->con_sock   = con_sock;
  1346. X        con_port->own_port   = port1;
  1347. X        con_port->other_port = port2;
  1348. X            /* clear timer and return */
  1349. X            (void) alarm(0);
  1350. X        DEBUGPUTS("connection established!");
  1351. X        mcon_retry_delay = MCON_RETRY_DELAY_MIN;
  1352. X#ifdef DEBUG_IPC
  1353. X            if (_debug_ipc) {
  1354. X                fprintf(_debugout, "[ipc] %s retry delay now %d\n",
  1355. X                    _processprefix, mcon_retry_delay);
  1356. X                if (_debugflush)
  1357. X                    fflush(_debugout);
  1358. X            }
  1359. X#endif /* DEBUG_IPC /**/
  1360. X        /* check periodically if connection is still alive */
  1361. X        setsoptarg = 1;
  1362. X        if (setsockopt(con_sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &setsoptarg, 
  1363. X                                 sizeof(int)) < 0) {
  1364. X        ipc_error("system_call: setsockopt(SO_KEEPALIVE)");
  1365. X        return(ERROR);
  1366. X        }
  1367. X            return(OK);
  1368. X        } else {
  1369. X        /* If two processes have already an established TCP/IP connection
  1370. X         * and try to make a connection using _make_connection() at the
  1371. X         * same time, each process receives as reply message the request
  1372. X         * message of the other process! In this case we try it again! 
  1373. X         */
  1374. X        DEBUGPUTS("wrong reply message");
  1375. X#ifdef SPARC
  1376. X        usleep(mcon_retry_delay);
  1377. X#else
  1378. X# ifdef HPUX
  1379. X            nap(mcon_retry_delay);
  1380. X# else
  1381. X        sleep(mcon_retry_delay);
  1382. X# endif /* HPUX /**/
  1383. X#endif /* SPARC /**/
  1384. X        if (mcon_retry_delay < MCON_RETRY_DELAY_MAX)
  1385. X        mcon_retry_delay += MCON_RETRY_DELAY_STEP;
  1386. X#ifdef DEBUG_IPC
  1387. X            if (_debug_ipc) {
  1388. X                fprintf(_debugout, "[ipc] %s retry delay now %d\n",
  1389. X                    _processprefix, mcon_retry_delay);
  1390. X                if (_debugflush)
  1391. X                    fflush(_debugout);
  1392. X            }
  1393. X#endif /* DEBUG_IPC /**/
  1394. X        DEBUGPUTS("trying again");
  1395. X        port1->state = CONNECTIONLESS;
  1396. X        DEBUGPUTS("state: CONNECTIONLESS");
  1397. X        continue;
  1398. X    }
  1399. X    } /* while */
  1400. X    DEBUGPUTS("TIMEOUT");
  1401. X    port1->state = CONNECTIONLESS;
  1402. X    DEBUGPUTS("state: CONNECTIONLESS");
  1403. X#ifdef DEBUG_IPC
  1404. X    if (_debug_ipc) {
  1405. X        fprintf(_debugout, "[ipc] %s retry delay now %d\n",
  1406. X            _processprefix, mcon_retry_delay);
  1407. X        if (_debugflush)
  1408. X            fflush(_debugout);
  1409. X    }
  1410. X#endif /* DEBUG_IPC /**/
  1411. X    Errno = ETIMEOUT;
  1412. X    return(ERROR);
  1413. X} /* _make_connection */
  1414. X
  1415. X/******************************************************************************
  1416. X * _close_connection()                                                        *
  1417. X *                                                                            *
  1418. X * The connection associated to connection port 'con_port' is closed.          *
  1419. X *                                                                            *
  1420. X * Return values: OK = success / ERROR = error                                *
  1421. X ******************************************************************************/
  1422. Xint
  1423. X_close_connection(con_port)
  1424. XCONNECTIONDESCR *con_port;
  1425. X{
  1426. X#ifdef DEBUG_IPC
  1427. X    if (_debug_ipc) {
  1428. X        fprintf(_debugout, "[ipc] %s ***** _close_connection():\n", 
  1429. X        _processprefix);
  1430. X        _display_connection_port_info("[ipc]", "con_port", *con_port);
  1431. X    }
  1432. X#endif /* DEBUG_IPC /**/
  1433. X    /* set Errno */
  1434. X    Errno = ECLOSECON;
  1435. X    /* check port state */
  1436. X    if (con_port->state != CONNECTED)
  1437. X    ipc_fatal_error("_close_connection()", "con_port state is not CONNECTED");
  1438. X    con_port->own_port->state = CLOSING;
  1439. X    DEBUGPUTS("state: CLOSING");
  1440. X    con_port->own_port->state = CONNECTIONLESS;
  1441. X    con_port->state = CONNECTIONLESS;
  1442. X    DEBUGPUTS("state: CONNECTIONLESS");
  1443. X    return(OK);
  1444. X} /* _close_connection */
  1445. X
  1446. X
  1447. X/******************************************************************************
  1448. X *                                                                            *
  1449. X * 'number' bytes are received from connection port 'con_port' and stored      *
  1450. X * into 'buffer'. 'time' is the maximum real time in seconds to wait for a    *
  1451. X * message to arrive (if 'time' equals 0 the waiting is unlimited).            * 
  1452. X *                                                                            *
  1453. X * Return values: number of received bytes upon success / ERROR = error        *
  1454. X ******************************************************************************/
  1455. Xint
  1456. X_recv_data(con_port, buffer, number, time)
  1457. XCONNECTIONDESCR *con_port;
  1458. Xchar            *buffer;
  1459. Xint              number;
  1460. Xunsigned         time;
  1461. X{
  1462. X    int num, nleft, nread;
  1463. X
  1464. X#ifdef DEBUG_IPC
  1465. X    if (_debug_ipc) {
  1466. X        fprintf(_debugout, "[ipc] %s ***** _recv_data():\n", _processprefix);
  1467. X        _display_connection_port_info("[ipc]", "con_port", *con_port);
  1468. X        fprintf(_debugout, "[ipc] %s buffer = %d, number = %d\n",
  1469. X        _processprefix, buffer, number);
  1470. X        fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
  1471. X    }
  1472. X#endif /* DEBUG_IPC /**/
  1473. X    /* set Errno */
  1474. X    Errno = ERECVDATA;
  1475. X    /* check connection port state */
  1476. X    if (con_port->state != CONNECTED)
  1477. X    ipc_fatal_error("_recv_data()", "con_port state is not CONNECTED");
  1478. X    /* check port state */
  1479. X    if (con_port->own_port->state != CONNECTED)
  1480. X    ipc_fatal_error("_recv_data()", "port state is not CONNECTED");
  1481. X    /* set timer, if time equals 0 clear timer */
  1482. X    SETTIMER(time);
  1483. X    con_port->state = con_port->own_port->state = RECEIVING;
  1484. X    DEBUGPUTS("state: RECEIVING");
  1485. X    nleft = number;
  1486. X    while(nleft > 0) {
  1487. X        nread = read(con_port->con_sock, buffer, nleft);
  1488. X    if (nread < 0) {
  1489. X        /* ERROR! */
  1490. X        if (errno == EINTR && timeout) {
  1491. X        /* return TIMEOUT error to caller */
  1492. X            Errno = ETIMEOUT;
  1493. X        } else
  1494. X                ipc_error("system call: read() - 4");
  1495. X            con_port->state = con_port->own_port->state = CONNECTED;
  1496. X            DEBUGPUTS("state: CONNECTED");
  1497. X            return(ERROR);
  1498. X        } else if (nread == 0) {
  1499. X        /* EOF! */
  1500. X        break;
  1501. X        }
  1502. X    nleft  -= nread;
  1503. X    buffer += nread;
  1504. X    } /* while */
  1505. X    con_port->state = con_port->own_port->state = CONNECTED;
  1506. X    DEBUGPUTS("state: CONNECTED");
  1507. X    /* clear timer and return */
  1508. X    (void) alarm(0);
  1509. X    return(number - nleft);
  1510. X} /* _recv_data */
  1511. X
  1512. X/******************************************************************************
  1513. X * _send_data()                                                               *
  1514. X *                                                                            *
  1515. X * 'number' bytes, stored in 'buffer', are send to connection port 'con_port'.*
  1516. X * 'time' is the maximum real time in seconds to retry sending upon error (if *
  1517. X * 'time' equals 0 the waiting is unlimited).                                 *
  1518. X *                                                                            *
  1519. X * Return values: number of sent bytes upon success / ERROR = error            *
  1520. X ******************************************************************************/
  1521. Xint
  1522. X_send_data(con_port, buffer, number, time)
  1523. XCONNECTIONDESCR *con_port;
  1524. Xchar            *buffer;
  1525. Xint              number;
  1526. Xunsigned         time;
  1527. X{
  1528. X    int num, nleft, nwritten;
  1529. X
  1530. X#ifdef DEBUG_IPC
  1531. X    if (_debug_ipc) {
  1532. X        fprintf(_debugout, "[ipc] %s ***** _send_data():\n", _processprefix);
  1533. X        _display_connection_port_info("[ipc]", "con_port", *con_port);
  1534. X        fprintf(_debugout, "[ipc] %s buffer = %d, number = %d\n", 
  1535. X        _processprefix, buffer, number);
  1536. X        fprintf(_debugout, "[ipc] %s time = %d\n", _processprefix, time);
  1537. X    }
  1538. X#endif /* DEBUG_IPC /**/
  1539. X    /* set Errno */
  1540. X    Errno = ESENDDATA;
  1541. X    /* check connection port state */
  1542. X    if (con_port->state != CONNECTED)
  1543. X    ipc_fatal_error("_send_data()", "con_port state is not CONNECTED");
  1544. X    /* check port state */
  1545. X    if (con_port->own_port->state != CONNECTED)
  1546. X    ipc_fatal_error("_send_data()", "port state is not CONNECTED");
  1547. X    /* set timer, if time equals 0 clear timer */
  1548. X    SETTIMER(time);
  1549. X    con_port->state = con_port->own_port->state = SENDING;
  1550. X    DEBUGPUTS("state: SENDING");
  1551. X    nleft = number;
  1552. X    while(nleft > 0) {
  1553. X        nwritten = write(con_port->con_sock, buffer, nleft);
  1554. X    if (nwritten <= 0) {
  1555. X        /* ERROR! */
  1556. X        if (errno == EINTR && timeout) {
  1557. X        /* return TIMEOUT error to caller */
  1558. X            Errno = ETIMEOUT;
  1559. X        } else
  1560. X                ipc_error("system call: write() - 4");
  1561. X            con_port->state = con_port->own_port->state = CONNECTED;
  1562. X            DEBUGPUTS("state: CONNECTED");
  1563. X            return(ERROR);    
  1564. X        }
  1565. X    nleft  -= nwritten;
  1566. X    buffer += nwritten;
  1567. X    } /* while */
  1568. X    con_port->state = con_port->own_port->state = CONNECTED;
  1569. X    DEBUGPUTS("state: CONNECTED");
  1570. X    /* clear timer and return */
  1571. X    (void) alarm(0);
  1572. X    return(number - nleft);
  1573. X} /* _send_data */
  1574. X
  1575. X/* ============================ DEBUG Routines ============================== */
  1576. X
  1577. X/******************************************************************************
  1578. X * _display_port_info()                                                       *
  1579. X *                                                                            *
  1580. X * Displays the components of the structure PORTDESCR specified by 'port'.    *
  1581. X *                                                                            *
  1582. X * Return values: always OK for success                                       *
  1583. X ******************************************************************************/
  1584. Xint
  1585. X_display_port_info(prefix, msg, port)
  1586. Xchar *prefix, *msg;
  1587. XPORTDESCR port;
  1588. X{
  1589. X    char *tmpptr;
  1590. X
  1591. X    switch(port.state) {
  1592. X    case CONNECTIONLESS:
  1593. X        tmpptr = "CONNECTIONLESS";
  1594. X        break;
  1595. X    case CONNECTED:
  1596. X        tmpptr = "CONNECTED";
  1597. X        break;
  1598. X    case SELECTING:
  1599. X        tmpptr = "SELECTING";
  1600. X        break;
  1601. X    case ACCEPTING:
  1602. X        tmpptr = "ACCEPTING";
  1603. X        break;
  1604. X    case CONNECTING:
  1605. X        tmpptr = "CONNECTING";
  1606. X        break;
  1607. X    case SEND_REQ:
  1608. X        tmpptr = "SEND_REQ";
  1609. X        break;
  1610. X    case RECV_REQ:
  1611. X        tmpptr = "RECV_REQ";
  1612. X        break;
  1613. X    case SEND_REP:
  1614. X        tmpptr = "SEND_REP";
  1615. X        break;
  1616. X    case RECV_REP:
  1617. X        tmpptr = "RECV_REP";
  1618. X        break;
  1619. X    case SEND_ADDR:
  1620. X        tmpptr = "SEND_ADDR";
  1621. X        break;
  1622. X    case RECV_ADDR:
  1623. X        tmpptr = "RECV_ADDR";
  1624. X        break;
  1625. X    case SENDING:
  1626. X        tmpptr = "SENDING";
  1627. X        break;
  1628. X    case RECEIVING:
  1629. X        tmpptr = "RECEIVING";
  1630. X        break;
  1631. X    default:
  1632. X        tmpptr = "UNKNOWN";
  1633. X    } /* switch */
  1634. X    fprintf(_debugout, "%s %s %s: port information:\n", prefix, 
  1635. X        _processprefix, msg);
  1636. X    fprintf(_debugout, "%s %s    state: %s\n", prefix, _processprefix, 
  1637. X        tmpptr);
  1638. X    fprintf(_debugout, "%s %s    acc_sock = %d\n", prefix, _processprefix, 
  1639. X        port.acc_sock);
  1640. X    fprintf(_debugout, "%s %s    portnum  = %d\n", prefix, _processprefix,
  1641. X        ntohs(port.portnum));
  1642. X    fprintf(_debugout, "%s %s    hostname = %s\n", prefix, _processprefix,
  1643. X        port.hostname);
  1644. X    fprintf(_debugout, "%s %s    con_sock = %d\n", prefix, _processprefix,
  1645. X        port.con_sock);
  1646. X    if (_debugflush)
  1647. X        fflush(_debugout);
  1648. X    return(OK);
  1649. X} /* _display_port_info */
  1650. X
  1651. X/******************************************************************************
  1652. X * _display_connection_port_info()                                            *
  1653. X *                                                                            *
  1654. X * Displays the components of the structure CONNECTIONDESCR specified by       *
  1655. X * 'con_port'.                                                                *
  1656. X *                                                                            *
  1657. X * Return values: always OK for success                                       *
  1658. X ******************************************************************************/
  1659. Xint
  1660. X_display_connection_port_info(prefix, msg, con_port)
  1661. Xchar *prefix, *msg;
  1662. XCONNECTIONDESCR con_port;
  1663. X{
  1664. X    char *tmpptr;
  1665. X
  1666. X    switch(con_port.state) {
  1667. X    case CONNECTIONLESS:
  1668. X        tmpptr = "CONNECTIONLESS";
  1669. X        break;
  1670. X    case CONNECTED:
  1671. X        tmpptr = "CONNECTED";
  1672. X        break;
  1673. X    case SENDING:
  1674. X        tmpptr = "SENDING";
  1675. X        break;
  1676. X    case RECEIVING:
  1677. X        tmpptr = "RECEIVING";
  1678. X        break;
  1679. X    default:
  1680. X        tmpptr = "UNKNOWN";
  1681. X    } /* switch */
  1682. X    fprintf(_debugout, "%s %s %s: connection port info:\n", prefix, 
  1683. X        _processprefix, msg);
  1684. X    fprintf(_debugout, "%s %s    state: %s\n", prefix, _processprefix, 
  1685. X        tmpptr);
  1686. X    fprintf(_debugout, "%s %s    con_sock = %d\n", prefix, _processprefix,
  1687. X        con_port.con_sock);
  1688. X    if (_debugflush)
  1689. X        fflush(_debugout);
  1690. X    return(OK);
  1691. X} /* _display_connection_port_info */
  1692. X
  1693. X/******************************************************************************
  1694. X * _input_port_info()                                                         *
  1695. X *                                                                            *
  1696. X * Input the port information for 'port'.                                     *
  1697. X *                                                                            *
  1698. X * Return values: none                                                        *
  1699. X ******************************************************************************/
  1700. Xint
  1701. X_input_port_info(port)
  1702. XPORTDESCR *port;
  1703. X{
  1704. X    int dummy;
  1705. X    u_short dummy2;
  1706. X
  1707. X    bzero((char *) port, sizeof(PORTDESCR));
  1708. X    printf("socket   = "); 
  1709. X    scanf("%d", &(port->acc_sock));
  1710. X    printf("portnum  = "); 
  1711. X    scanf("%d", &dummy);
  1712. X        dummy2 = (u_short) dummy;
  1713. X        port->portnum = htons(dummy2);
  1714. X    printf("hostname = "); 
  1715. X    scanf("%s", port->hostname);
  1716. X} /* _input_port_info */
  1717. END_OF_FILE
  1718. if test 60451 -ne `wc -c <'lib/ipc_socket.c'`; then
  1719.     echo shar: \"'lib/ipc_socket.c'\" unpacked with wrong size!
  1720. fi
  1721. # end of 'lib/ipc_socket.c'
  1722. fi
  1723. echo shar: End of archive 17 \(of 18\).
  1724. cp /dev/null ark17isdone
  1725. MISSING=""
  1726. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1727.     if test ! -f ark${I}isdone ; then
  1728.     MISSING="${MISSING} ${I}"
  1729.     fi
  1730. done
  1731. if test "${MISSING}" = "" ; then
  1732.     echo You have unpacked all 18 archives.
  1733.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1734. else
  1735.     echo You still need to unpack the following archives:
  1736.     echo "        " ${MISSING}
  1737. fi
  1738. ##  End of shell archive.
  1739. exit 0
  1740.