xref: /freebsd/crypto/openssl/apps/lib/vms_term_sock.c (revision 0d0c8621fd181e507f0fb50ffcca606faf66a8c2)
1b077aed3SPierre Pronchery /*
2b077aed3SPierre Pronchery  * Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  * Copyright 2016 VMS Software, Inc. All Rights Reserved.
4b077aed3SPierre Pronchery  *
5b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
6b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
7b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
8b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
9b077aed3SPierre Pronchery  */
10b077aed3SPierre Pronchery 
11b077aed3SPierre Pronchery #ifdef __VMS
12b077aed3SPierre Pronchery # define OPENSSL_SYS_VMS
13b077aed3SPierre Pronchery # pragma message disable DOLLARID
14b077aed3SPierre Pronchery 
15b077aed3SPierre Pronchery 
16b077aed3SPierre Pronchery # include <openssl/opensslconf.h>
17b077aed3SPierre Pronchery 
18b077aed3SPierre Pronchery # if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
19b077aed3SPierre Pronchery /*
20b077aed3SPierre Pronchery  * On VMS, you need to define this to get the declaration of fileno().  The
21b077aed3SPierre Pronchery  * value 2 is to make sure no function defined in POSIX-2 is left undefined.
22b077aed3SPierre Pronchery  */
23b077aed3SPierre Pronchery #  define _POSIX_C_SOURCE 2
24b077aed3SPierre Pronchery # endif
25b077aed3SPierre Pronchery 
26b077aed3SPierre Pronchery # include <stdio.h>
27b077aed3SPierre Pronchery 
28b077aed3SPierre Pronchery # undef _POSIX_C_SOURCE
29b077aed3SPierre Pronchery 
30b077aed3SPierre Pronchery # include <sys/types.h>
31b077aed3SPierre Pronchery # include <sys/socket.h>
32b077aed3SPierre Pronchery # include <netinet/in.h>
33b077aed3SPierre Pronchery # include <inet.h>
34b077aed3SPierre Pronchery # include <unistd.h>
35b077aed3SPierre Pronchery # include <string.h>
36b077aed3SPierre Pronchery # include <errno.h>
37b077aed3SPierre Pronchery # include <starlet.h>
38b077aed3SPierre Pronchery # include <iodef.h>
39b077aed3SPierre Pronchery # ifdef __alpha
40b077aed3SPierre Pronchery #  include <iosbdef.h>
41b077aed3SPierre Pronchery # else
42b077aed3SPierre Pronchery typedef struct _iosb {           /* Copied from IOSBDEF.H for Alpha  */
43b077aed3SPierre Pronchery #  pragma __nomember_alignment
44b077aed3SPierre Pronchery     __union  {
45b077aed3SPierre Pronchery         __struct  {
46b077aed3SPierre Pronchery             unsigned short int iosb$w_status; /* Final I/O status           */
47b077aed3SPierre Pronchery             __union  {
48b077aed3SPierre Pronchery                 __struct  {             /* 16-bit byte count variant        */
49b077aed3SPierre Pronchery                     unsigned short int iosb$w_bcnt; /* 16-bit byte count    */
50b077aed3SPierre Pronchery                     __union  {
51b077aed3SPierre Pronchery                         unsigned int iosb$l_dev_depend; /* 32-bit device dependent info */
52b077aed3SPierre Pronchery                         unsigned int iosb$l_pid; /* 32-bit pid              */
53b077aed3SPierre Pronchery                     } iosb$r_l;
54b077aed3SPierre Pronchery                 } iosb$r_bcnt_16;
55b077aed3SPierre Pronchery                 __struct  {             /* 32-bit byte count variant        */
56b077aed3SPierre Pronchery                     unsigned int iosb$l_bcnt; /* 32-bit byte count (unaligned) */
57b077aed3SPierre Pronchery                     unsigned short int iosb$w_dev_depend_high; /* 16-bit device dependent info */
58b077aed3SPierre Pronchery                 } iosb$r_bcnt_32;
59b077aed3SPierre Pronchery             } iosb$r_devdepend;
60b077aed3SPierre Pronchery         } iosb$r_io_64;
61b077aed3SPierre Pronchery         __struct  {
62b077aed3SPierre Pronchery             __union  {
63b077aed3SPierre Pronchery                 unsigned int iosb$l_getxxi_status; /* Final GETxxI status   */
64b077aed3SPierre Pronchery                 unsigned int iosb$l_reg_status; /* Final $Registry status   */
65b077aed3SPierre Pronchery             } iosb$r_l_status;
66b077aed3SPierre Pronchery             unsigned int iosb$l_reserved; /* Reserved field                 */
67b077aed3SPierre Pronchery         } iosb$r_get_64;
68b077aed3SPierre Pronchery     } iosb$r_io_get;
69b077aed3SPierre Pronchery } IOSB;
70b077aed3SPierre Pronchery 
71b077aed3SPierre Pronchery #  if !defined(__VAXC)
72b077aed3SPierre Pronchery #   define iosb$w_status iosb$r_io_get.iosb$r_io_64.iosb$w_status
73b077aed3SPierre Pronchery #   define iosb$w_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$w_bcnt
74b077aed3SPierre Pronchery #   define iosb$r_l        iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_16.iosb$r_l
75b077aed3SPierre Pronchery #   define iosb$l_dev_depend iosb$r_l.iosb$l_dev_depend
76b077aed3SPierre Pronchery #   define iosb$l_pid iosb$r_l.iosb$l_pid
77b077aed3SPierre Pronchery #   define iosb$l_bcnt iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$l_bcnt
78b077aed3SPierre Pronchery #   define iosb$w_dev_depend_high iosb$r_io_get.iosb$r_io_64.iosb$r_devdepend.iosb$r_bcnt_32.iosb$w_dev_depend_high
79b077aed3SPierre Pronchery #   define iosb$l_getxxi_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_getxxi_status
80b077aed3SPierre Pronchery #   define iosb$l_reg_status iosb$r_io_get.iosb$r_get_64.iosb$r_l_status.iosb$l_reg_status
81b077aed3SPierre Pronchery #  endif          /* #if !defined(__VAXC) */
82b077aed3SPierre Pronchery 
83b077aed3SPierre Pronchery # endif  /* End of IOSBDEF */
84b077aed3SPierre Pronchery 
85b077aed3SPierre Pronchery # include <efndef.h>
86b077aed3SPierre Pronchery # include <stdlib.h>
87b077aed3SPierre Pronchery # include <ssdef.h>
88b077aed3SPierre Pronchery # include <time.h>
89b077aed3SPierre Pronchery # include <stdarg.h>
90b077aed3SPierre Pronchery # include <descrip.h>
91b077aed3SPierre Pronchery 
92b077aed3SPierre Pronchery # include "vms_term_sock.h"
93b077aed3SPierre Pronchery 
94b077aed3SPierre Pronchery # ifdef __alpha
95b077aed3SPierre Pronchery static struct _iosb TerminalDeviceIosb;
96b077aed3SPierre Pronchery # else
97b077aed3SPierre Pronchery IOSB TerminalDeviceIosb;
98b077aed3SPierre Pronchery # endif
99b077aed3SPierre Pronchery 
100b077aed3SPierre Pronchery static char TerminalDeviceBuff[255 + 2];
101b077aed3SPierre Pronchery static int TerminalSocketPair[2] = {0, 0};
102b077aed3SPierre Pronchery static unsigned short TerminalDeviceChan = 0;
103b077aed3SPierre Pronchery 
104b077aed3SPierre Pronchery static int CreateSocketPair (int, int, int, int *);
105b077aed3SPierre Pronchery static void SocketPairTimeoutAst (int);
106b077aed3SPierre Pronchery static int TerminalDeviceAst (int);
107b077aed3SPierre Pronchery static void LogMessage (char *, ...);
108b077aed3SPierre Pronchery 
109b077aed3SPierre Pronchery /*
110b077aed3SPierre Pronchery ** Socket Pair Timeout Value (must be 0-59 seconds)
111b077aed3SPierre Pronchery */
112b077aed3SPierre Pronchery # define SOCKET_PAIR_TIMEOUT_VALUE 20
113b077aed3SPierre Pronchery 
114b077aed3SPierre Pronchery /*
115b077aed3SPierre Pronchery ** Socket Pair Timeout Block which is passed to timeout AST
116b077aed3SPierre Pronchery */
117b077aed3SPierre Pronchery typedef struct _SocketPairTimeoutBlock {
118b077aed3SPierre Pronchery     unsigned short SockChan1;
119b077aed3SPierre Pronchery     unsigned short SockChan2;
120b077aed3SPierre Pronchery } SPTB;
121b077aed3SPierre Pronchery 
122b077aed3SPierre Pronchery # ifdef TERM_SOCK_TEST
123b077aed3SPierre Pronchery 
124b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
125b077aed3SPierre Pronchery /*                                                                            */
126b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
main(int argc,char * argv[],char * envp[])127b077aed3SPierre Pronchery int main (int argc, char *argv[], char *envp[])
128b077aed3SPierre Pronchery {
129b077aed3SPierre Pronchery     char TermBuff[80];
130b077aed3SPierre Pronchery     int TermSock,
131b077aed3SPierre Pronchery         status,
132b077aed3SPierre Pronchery         len;
133b077aed3SPierre Pronchery 
134b077aed3SPierre Pronchery     LogMessage ("Enter 'q' or 'Q' to quit ...");
135b077aed3SPierre Pronchery     while (OPENSSL_strcasecmp (TermBuff, "Q")) {
136b077aed3SPierre Pronchery         /*
137b077aed3SPierre Pronchery         ** Create the terminal socket
138b077aed3SPierre Pronchery         */
139b077aed3SPierre Pronchery         status = TerminalSocket (TERM_SOCK_CREATE, &TermSock);
140b077aed3SPierre Pronchery         if (status != TERM_SOCK_SUCCESS)
141b077aed3SPierre Pronchery             exit (1);
142b077aed3SPierre Pronchery 
143b077aed3SPierre Pronchery         /*
144b077aed3SPierre Pronchery         ** Process the terminal input
145b077aed3SPierre Pronchery         */
146b077aed3SPierre Pronchery         LogMessage ("Waiting on terminal I/O ...\n");
147b077aed3SPierre Pronchery         len = recv (TermSock, TermBuff, sizeof(TermBuff), 0) ;
148b077aed3SPierre Pronchery         TermBuff[len] = '\0';
149b077aed3SPierre Pronchery         LogMessage ("Received terminal I/O [%s]", TermBuff);
150b077aed3SPierre Pronchery 
151b077aed3SPierre Pronchery         /*
152b077aed3SPierre Pronchery         ** Delete the terminal socket
153b077aed3SPierre Pronchery         */
154b077aed3SPierre Pronchery         status = TerminalSocket (TERM_SOCK_DELETE, &TermSock);
155b077aed3SPierre Pronchery         if (status != TERM_SOCK_SUCCESS)
156b077aed3SPierre Pronchery             exit (1);
157b077aed3SPierre Pronchery     }
158b077aed3SPierre Pronchery 
159b077aed3SPierre Pronchery     return 1;
160b077aed3SPierre Pronchery 
161b077aed3SPierre Pronchery }
162b077aed3SPierre Pronchery # endif
163b077aed3SPierre Pronchery 
164b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
165b077aed3SPierre Pronchery /*                                                                            */
166b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
TerminalSocket(int FunctionCode,int * ReturnSocket)167b077aed3SPierre Pronchery int TerminalSocket (int FunctionCode, int *ReturnSocket)
168b077aed3SPierre Pronchery {
169b077aed3SPierre Pronchery     int status;
170b077aed3SPierre Pronchery     $DESCRIPTOR (TerminalDeviceDesc, "SYS$COMMAND");
171b077aed3SPierre Pronchery 
172b077aed3SPierre Pronchery     /*
173b077aed3SPierre Pronchery     ** Process the requested function code
174b077aed3SPierre Pronchery     */
175b077aed3SPierre Pronchery     switch (FunctionCode) {
176b077aed3SPierre Pronchery     case TERM_SOCK_CREATE:
177b077aed3SPierre Pronchery         /*
178b077aed3SPierre Pronchery         ** Create a socket pair
179b077aed3SPierre Pronchery         */
180b077aed3SPierre Pronchery         status = CreateSocketPair (AF_INET, SOCK_STREAM, 0, TerminalSocketPair);
181b077aed3SPierre Pronchery         if (status == -1) {
182b077aed3SPierre Pronchery             LogMessage ("TerminalSocket: CreateSocketPair () - %08X", status);
183b077aed3SPierre Pronchery             if (TerminalSocketPair[0])
184b077aed3SPierre Pronchery                 close (TerminalSocketPair[0]);
185b077aed3SPierre Pronchery             if (TerminalSocketPair[1])
186b077aed3SPierre Pronchery                 close (TerminalSocketPair[1]);
187b077aed3SPierre Pronchery             return TERM_SOCK_FAILURE;
188b077aed3SPierre Pronchery         }
189b077aed3SPierre Pronchery 
190b077aed3SPierre Pronchery         /*
191b077aed3SPierre Pronchery         ** Assign a channel to the terminal device
192b077aed3SPierre Pronchery         */
193b077aed3SPierre Pronchery         status = sys$assign (&TerminalDeviceDesc,
194b077aed3SPierre Pronchery                              &TerminalDeviceChan,
195b077aed3SPierre Pronchery                              0, 0, 0);
196b077aed3SPierre Pronchery         if (! (status & 1)) {
197b077aed3SPierre Pronchery             LogMessage ("TerminalSocket: SYS$ASSIGN () - %08X", status);
198b077aed3SPierre Pronchery             close (TerminalSocketPair[0]);
199b077aed3SPierre Pronchery             close (TerminalSocketPair[1]);
200b077aed3SPierre Pronchery             return TERM_SOCK_FAILURE;
201b077aed3SPierre Pronchery         }
202b077aed3SPierre Pronchery 
203b077aed3SPierre Pronchery         /*
204b077aed3SPierre Pronchery         ** Queue an async IO to the terminal device
205b077aed3SPierre Pronchery         */
206b077aed3SPierre Pronchery         status = sys$qio (EFN$C_ENF,
207b077aed3SPierre Pronchery                           TerminalDeviceChan,
208b077aed3SPierre Pronchery                           IO$_READVBLK,
209b077aed3SPierre Pronchery                           &TerminalDeviceIosb,
210b077aed3SPierre Pronchery                           TerminalDeviceAst,
211b077aed3SPierre Pronchery                           0,
212b077aed3SPierre Pronchery                           TerminalDeviceBuff,
213b077aed3SPierre Pronchery                           sizeof(TerminalDeviceBuff) - 2,
214b077aed3SPierre Pronchery                           0, 0, 0, 0);
215b077aed3SPierre Pronchery         if (! (status & 1)) {
216b077aed3SPierre Pronchery             LogMessage ("TerminalSocket: SYS$QIO () - %08X", status);
217b077aed3SPierre Pronchery             close (TerminalSocketPair[0]);
218b077aed3SPierre Pronchery             close (TerminalSocketPair[1]);
219b077aed3SPierre Pronchery             return TERM_SOCK_FAILURE;
220b077aed3SPierre Pronchery         }
221b077aed3SPierre Pronchery 
222b077aed3SPierre Pronchery         /*
223b077aed3SPierre Pronchery         ** Return the input side of the socket pair
224b077aed3SPierre Pronchery         */
225b077aed3SPierre Pronchery         *ReturnSocket = TerminalSocketPair[1];
226b077aed3SPierre Pronchery         break;
227b077aed3SPierre Pronchery 
228b077aed3SPierre Pronchery     case TERM_SOCK_DELETE:
229b077aed3SPierre Pronchery         /*
230b077aed3SPierre Pronchery         ** Cancel any pending IO on the terminal channel
231b077aed3SPierre Pronchery         */
232b077aed3SPierre Pronchery         status = sys$cancel (TerminalDeviceChan);
233b077aed3SPierre Pronchery         if (! (status & 1)) {
234b077aed3SPierre Pronchery             LogMessage ("TerminalSocket: SYS$CANCEL () - %08X", status);
235b077aed3SPierre Pronchery             close (TerminalSocketPair[0]);
236b077aed3SPierre Pronchery             close (TerminalSocketPair[1]);
237b077aed3SPierre Pronchery             return TERM_SOCK_FAILURE;
238b077aed3SPierre Pronchery         }
239b077aed3SPierre Pronchery 
240b077aed3SPierre Pronchery         /*
241b077aed3SPierre Pronchery         ** Deassign the terminal channel
242b077aed3SPierre Pronchery         */
243b077aed3SPierre Pronchery         status = sys$dassgn (TerminalDeviceChan);
244b077aed3SPierre Pronchery         if (! (status & 1)) {
245b077aed3SPierre Pronchery             LogMessage ("TerminalSocket: SYS$DASSGN () - %08X", status);
246b077aed3SPierre Pronchery             close (TerminalSocketPair[0]);
247b077aed3SPierre Pronchery             close (TerminalSocketPair[1]);
248b077aed3SPierre Pronchery             return TERM_SOCK_FAILURE;
249b077aed3SPierre Pronchery         }
250b077aed3SPierre Pronchery 
251b077aed3SPierre Pronchery         /*
252b077aed3SPierre Pronchery         ** Close the terminal socket pair
253b077aed3SPierre Pronchery         */
254b077aed3SPierre Pronchery         close (TerminalSocketPair[0]);
255b077aed3SPierre Pronchery         close (TerminalSocketPair[1]);
256b077aed3SPierre Pronchery 
257b077aed3SPierre Pronchery         /*
258b077aed3SPierre Pronchery         ** Return the initialized socket
259b077aed3SPierre Pronchery         */
260b077aed3SPierre Pronchery         *ReturnSocket = 0;
261b077aed3SPierre Pronchery         break;
262b077aed3SPierre Pronchery 
263b077aed3SPierre Pronchery     default:
264b077aed3SPierre Pronchery         /*
265b077aed3SPierre Pronchery         ** Invalid function code
266b077aed3SPierre Pronchery         */
267b077aed3SPierre Pronchery         LogMessage ("TerminalSocket: Invalid Function Code - %d", FunctionCode);
268b077aed3SPierre Pronchery         return TERM_SOCK_FAILURE;
269b077aed3SPierre Pronchery         break;
270b077aed3SPierre Pronchery     }
271b077aed3SPierre Pronchery 
272b077aed3SPierre Pronchery     /*
273b077aed3SPierre Pronchery     ** Return success
274b077aed3SPierre Pronchery     */
275b077aed3SPierre Pronchery     return TERM_SOCK_SUCCESS;
276b077aed3SPierre Pronchery 
277b077aed3SPierre Pronchery }
278b077aed3SPierre Pronchery 
279b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
280b077aed3SPierre Pronchery /*                                                                            */
281b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
CreateSocketPair(int SocketFamily,int SocketType,int SocketProtocol,int * SocketPair)282b077aed3SPierre Pronchery static int CreateSocketPair (int SocketFamily,
283b077aed3SPierre Pronchery                              int SocketType,
284b077aed3SPierre Pronchery                              int SocketProtocol,
285b077aed3SPierre Pronchery                              int *SocketPair)
286b077aed3SPierre Pronchery {
287b077aed3SPierre Pronchery     struct dsc$descriptor AscTimeDesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
288b077aed3SPierre Pronchery     static const char* LocalHostAddr = {"127.0.0.1"};
289b077aed3SPierre Pronchery     unsigned short TcpAcceptChan = 0,
290b077aed3SPierre Pronchery         TcpDeviceChan = 0;
291b077aed3SPierre Pronchery     unsigned long BinTimeBuff[2];
292b077aed3SPierre Pronchery     struct sockaddr_in sin;
293b077aed3SPierre Pronchery     char AscTimeBuff[32];
294b077aed3SPierre Pronchery     short LocalHostPort;
295b077aed3SPierre Pronchery     int status;
296b077aed3SPierre Pronchery     unsigned int slen;
297b077aed3SPierre Pronchery 
298b077aed3SPierre Pronchery # ifdef __alpha
299b077aed3SPierre Pronchery     struct _iosb iosb;
300b077aed3SPierre Pronchery # else
301b077aed3SPierre Pronchery     IOSB iosb;
302b077aed3SPierre Pronchery # endif
303b077aed3SPierre Pronchery 
304b077aed3SPierre Pronchery     int SockDesc1 = 0,
305b077aed3SPierre Pronchery         SockDesc2 = 0;
306b077aed3SPierre Pronchery     SPTB sptb;
307b077aed3SPierre Pronchery     $DESCRIPTOR (TcpDeviceDesc, "TCPIP$DEVICE");
308b077aed3SPierre Pronchery 
309b077aed3SPierre Pronchery     /*
310b077aed3SPierre Pronchery     ** Create a socket
311b077aed3SPierre Pronchery     */
312b077aed3SPierre Pronchery     SockDesc1 = socket (SocketFamily, SocketType, 0);
313b077aed3SPierre Pronchery     if (SockDesc1 < 0) {
314b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: socket () - %d", errno);
315b077aed3SPierre Pronchery         return -1;
316b077aed3SPierre Pronchery     }
317b077aed3SPierre Pronchery 
318b077aed3SPierre Pronchery     /*
319b077aed3SPierre Pronchery     ** Initialize the socket information
320b077aed3SPierre Pronchery     */
321b077aed3SPierre Pronchery     slen = sizeof(sin);
322b077aed3SPierre Pronchery     memset ((char *) &sin, 0, slen);
323b077aed3SPierre Pronchery     sin.sin_family = SocketFamily;
324b077aed3SPierre Pronchery     sin.sin_addr.s_addr = inet_addr (LocalHostAddr);
325b077aed3SPierre Pronchery     sin.sin_port = 0;
326b077aed3SPierre Pronchery 
327b077aed3SPierre Pronchery     /*
328b077aed3SPierre Pronchery     ** Bind the socket to the local IP
329b077aed3SPierre Pronchery     */
330b077aed3SPierre Pronchery     status = bind (SockDesc1, (struct sockaddr *) &sin, slen);
331b077aed3SPierre Pronchery     if (status < 0) {
332b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: bind () - %d", errno);
333b077aed3SPierre Pronchery         close (SockDesc1);
334b077aed3SPierre Pronchery         return -1;
335b077aed3SPierre Pronchery     }
336b077aed3SPierre Pronchery 
337b077aed3SPierre Pronchery     /*
338b077aed3SPierre Pronchery     ** Get the socket name so we can save the port number
339b077aed3SPierre Pronchery     */
340b077aed3SPierre Pronchery     status = getsockname (SockDesc1, (struct sockaddr *) &sin, &slen);
341b077aed3SPierre Pronchery     if (status < 0) {
342b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: getsockname () - %d", errno);
343b077aed3SPierre Pronchery         close (SockDesc1);
344b077aed3SPierre Pronchery         return -1;
345b077aed3SPierre Pronchery     } else
346b077aed3SPierre Pronchery         LocalHostPort = sin.sin_port;
347b077aed3SPierre Pronchery 
348b077aed3SPierre Pronchery     /*
349b077aed3SPierre Pronchery     ** Setup a listen for the socket
350b077aed3SPierre Pronchery     */
351b077aed3SPierre Pronchery     listen (SockDesc1, 5);
352b077aed3SPierre Pronchery 
353b077aed3SPierre Pronchery     /*
354b077aed3SPierre Pronchery     ** Get the binary (64-bit) time of the specified timeout value
355b077aed3SPierre Pronchery     */
356*0d0c8621SEnji Cooper     BIO_snprintf(AscTimeBuff, sizeof(AscTimeBuff), "0 0:0:%02d.00", SOCKET_PAIR_TIMEOUT_VALUE);
357b077aed3SPierre Pronchery     AscTimeDesc.dsc$w_length = strlen (AscTimeBuff);
358b077aed3SPierre Pronchery     AscTimeDesc.dsc$a_pointer = AscTimeBuff;
359b077aed3SPierre Pronchery     status = sys$bintim (&AscTimeDesc, BinTimeBuff);
360b077aed3SPierre Pronchery     if (! (status & 1)) {
361b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: SYS$BINTIM () - %08X", status);
362b077aed3SPierre Pronchery         close (SockDesc1);
363b077aed3SPierre Pronchery         return -1;
364b077aed3SPierre Pronchery     }
365b077aed3SPierre Pronchery 
366b077aed3SPierre Pronchery     /*
367b077aed3SPierre Pronchery     ** Assign another channel to the TCP/IP device for the accept.
368b077aed3SPierre Pronchery     ** This is the channel that ends up being connected to.
369b077aed3SPierre Pronchery     */
370b077aed3SPierre Pronchery     status = sys$assign (&TcpDeviceDesc, &TcpDeviceChan, 0, 0, 0);
371b077aed3SPierre Pronchery     if (! (status & 1)) {
372b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: SYS$ASSIGN () - %08X", status);
373b077aed3SPierre Pronchery         close (SockDesc1);
374b077aed3SPierre Pronchery         return -1;
375b077aed3SPierre Pronchery     }
376b077aed3SPierre Pronchery 
377b077aed3SPierre Pronchery     /*
378b077aed3SPierre Pronchery     ** Get the channel of the first socket for the accept
379b077aed3SPierre Pronchery     */
380b077aed3SPierre Pronchery     TcpAcceptChan = decc$get_sdc (SockDesc1);
381b077aed3SPierre Pronchery 
382b077aed3SPierre Pronchery     /*
383b077aed3SPierre Pronchery     ** Perform the accept using $QIO so we can do this asynchronously
384b077aed3SPierre Pronchery     */
385b077aed3SPierre Pronchery     status = sys$qio (EFN$C_ENF,
386b077aed3SPierre Pronchery                       TcpAcceptChan,
387b077aed3SPierre Pronchery                       IO$_ACCESS | IO$M_ACCEPT,
388b077aed3SPierre Pronchery                       &iosb,
389b077aed3SPierre Pronchery                       0, 0, 0, 0, 0,
390b077aed3SPierre Pronchery                       &TcpDeviceChan,
391b077aed3SPierre Pronchery                       0, 0);
392b077aed3SPierre Pronchery     if (! (status & 1)) {
393b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: SYS$QIO () - %08X", status);
394b077aed3SPierre Pronchery         close (SockDesc1);
395b077aed3SPierre Pronchery         sys$dassgn (TcpDeviceChan);
396b077aed3SPierre Pronchery         return -1;
397b077aed3SPierre Pronchery     }
398b077aed3SPierre Pronchery 
399b077aed3SPierre Pronchery     /*
400b077aed3SPierre Pronchery     ** Create the second socket to do the connect
401b077aed3SPierre Pronchery     */
402b077aed3SPierre Pronchery     SockDesc2 = socket (SocketFamily, SocketType, 0);
403b077aed3SPierre Pronchery     if (SockDesc2 < 0) {
404b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: socket () - %d", errno);
405b077aed3SPierre Pronchery         sys$cancel (TcpAcceptChan);
406b077aed3SPierre Pronchery         close (SockDesc1);
407b077aed3SPierre Pronchery         sys$dassgn (TcpDeviceChan);
408b077aed3SPierre Pronchery         return (-1) ;
409b077aed3SPierre Pronchery     }
410b077aed3SPierre Pronchery 
411b077aed3SPierre Pronchery     /*
412b077aed3SPierre Pronchery     ** Setup the Socket Pair Timeout Block
413b077aed3SPierre Pronchery     */
414b077aed3SPierre Pronchery     sptb.SockChan1 = TcpAcceptChan;
415b077aed3SPierre Pronchery     sptb.SockChan2 = decc$get_sdc (SockDesc2);
416b077aed3SPierre Pronchery 
417b077aed3SPierre Pronchery     /*
418b077aed3SPierre Pronchery     ** Before we block on the connect, set a timer that can cancel I/O on our
419b077aed3SPierre Pronchery     ** two sockets if it never connects.
420b077aed3SPierre Pronchery     */
421b077aed3SPierre Pronchery     status = sys$setimr (EFN$C_ENF,
422b077aed3SPierre Pronchery                          BinTimeBuff,
423b077aed3SPierre Pronchery                          SocketPairTimeoutAst,
424b077aed3SPierre Pronchery                          &sptb,
425b077aed3SPierre Pronchery                          0);
426b077aed3SPierre Pronchery     if (! (status & 1)) {
427b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: SYS$SETIMR () - %08X", status);
428b077aed3SPierre Pronchery         sys$cancel (TcpAcceptChan);
429b077aed3SPierre Pronchery         close (SockDesc1);
430b077aed3SPierre Pronchery         close (SockDesc2);
431b077aed3SPierre Pronchery         sys$dassgn (TcpDeviceChan);
432b077aed3SPierre Pronchery         return -1;
433b077aed3SPierre Pronchery     }
434b077aed3SPierre Pronchery 
435b077aed3SPierre Pronchery     /*
436b077aed3SPierre Pronchery     ** Now issue the connect
437b077aed3SPierre Pronchery     */
438b077aed3SPierre Pronchery     memset ((char *) &sin, 0, sizeof(sin)) ;
439b077aed3SPierre Pronchery     sin.sin_family = SocketFamily;
440b077aed3SPierre Pronchery     sin.sin_addr.s_addr = inet_addr (LocalHostAddr) ;
441b077aed3SPierre Pronchery     sin.sin_port = LocalHostPort ;
442b077aed3SPierre Pronchery 
443b077aed3SPierre Pronchery     status = connect (SockDesc2, (struct sockaddr *) &sin, sizeof(sin));
444b077aed3SPierre Pronchery     if (status < 0 ) {
445b077aed3SPierre Pronchery         LogMessage ("CreateSocketPair: connect () - %d", errno);
446b077aed3SPierre Pronchery         sys$cantim (&sptb, 0);
447b077aed3SPierre Pronchery         sys$cancel (TcpAcceptChan);
448b077aed3SPierre Pronchery         close (SockDesc1);
449b077aed3SPierre Pronchery         close (SockDesc2);
450b077aed3SPierre Pronchery         sys$dassgn (TcpDeviceChan);
451b077aed3SPierre Pronchery         return -1;
452b077aed3SPierre Pronchery     }
453b077aed3SPierre Pronchery 
454b077aed3SPierre Pronchery     /*
455b077aed3SPierre Pronchery     ** Wait for the asynch $QIO to finish.  Note that if the I/O was aborted
456b077aed3SPierre Pronchery     ** (SS$_ABORT), then we probably canceled it from the AST routine - so log
457b077aed3SPierre Pronchery     ** a timeout.
458b077aed3SPierre Pronchery     */
459b077aed3SPierre Pronchery     status = sys$synch (EFN$C_ENF, &iosb);
460b077aed3SPierre Pronchery     if (! (iosb.iosb$w_status & 1)) {
461b077aed3SPierre Pronchery         if (iosb.iosb$w_status == SS$_ABORT)
462b077aed3SPierre Pronchery             LogMessage ("CreateSocketPair: SYS$QIO(iosb) timeout");
463b077aed3SPierre Pronchery         else {
464b077aed3SPierre Pronchery             LogMessage ("CreateSocketPair: SYS$QIO(iosb) - %d",
465b077aed3SPierre Pronchery                         iosb.iosb$w_status);
466b077aed3SPierre Pronchery             sys$cantim (&sptb, 0);
467b077aed3SPierre Pronchery         }
468b077aed3SPierre Pronchery         close (SockDesc1);
469b077aed3SPierre Pronchery         close (SockDesc2);
470b077aed3SPierre Pronchery         sys$dassgn (TcpDeviceChan);
471b077aed3SPierre Pronchery         return -1;
472b077aed3SPierre Pronchery     }
473b077aed3SPierre Pronchery 
474b077aed3SPierre Pronchery     /*
475b077aed3SPierre Pronchery     ** Here we're successfully connected, so cancel the timer, convert the
476b077aed3SPierre Pronchery     ** I/O channel to a socket fd, close the listener socket and return the
477b077aed3SPierre Pronchery     ** connected pair.
478b077aed3SPierre Pronchery     */
479b077aed3SPierre Pronchery     sys$cantim (&sptb, 0);
480b077aed3SPierre Pronchery 
481b077aed3SPierre Pronchery     close (SockDesc1) ;
482b077aed3SPierre Pronchery     SocketPair[0] = SockDesc2 ;
483b077aed3SPierre Pronchery     SocketPair[1] = socket_fd (TcpDeviceChan);
484b077aed3SPierre Pronchery 
485b077aed3SPierre Pronchery     return (0) ;
486b077aed3SPierre Pronchery 
487b077aed3SPierre Pronchery }
488b077aed3SPierre Pronchery 
489b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
490b077aed3SPierre Pronchery /*                                                                            */
491b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
SocketPairTimeoutAst(int astparm)492b077aed3SPierre Pronchery static void SocketPairTimeoutAst (int astparm)
493b077aed3SPierre Pronchery {
494b077aed3SPierre Pronchery     SPTB *sptb = (SPTB *) astparm;
495b077aed3SPierre Pronchery 
496b077aed3SPierre Pronchery     sys$cancel (sptb->SockChan2); /* Cancel the connect() */
497b077aed3SPierre Pronchery     sys$cancel (sptb->SockChan1); /* Cancel the accept() */
498b077aed3SPierre Pronchery 
499b077aed3SPierre Pronchery     return;
500b077aed3SPierre Pronchery 
501b077aed3SPierre Pronchery }
502b077aed3SPierre Pronchery 
503b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
504b077aed3SPierre Pronchery /*                                                                            */
505b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
TerminalDeviceAst(int astparm)506b077aed3SPierre Pronchery static int TerminalDeviceAst (int astparm)
507b077aed3SPierre Pronchery {
508b077aed3SPierre Pronchery     int status;
509b077aed3SPierre Pronchery 
510b077aed3SPierre Pronchery     /*
511b077aed3SPierre Pronchery     ** Terminate the terminal buffer
512b077aed3SPierre Pronchery     */
513b077aed3SPierre Pronchery     TerminalDeviceBuff[TerminalDeviceIosb.iosb$w_bcnt] = '\0';
514b077aed3SPierre Pronchery     strcat (TerminalDeviceBuff, "\n");
515b077aed3SPierre Pronchery 
516b077aed3SPierre Pronchery     /*
517b077aed3SPierre Pronchery     ** Send the data read from the terminal device through the socket pair
518b077aed3SPierre Pronchery     */
519b077aed3SPierre Pronchery     send (TerminalSocketPair[0], TerminalDeviceBuff,
520b077aed3SPierre Pronchery           TerminalDeviceIosb.iosb$w_bcnt + 1, 0);
521b077aed3SPierre Pronchery 
522b077aed3SPierre Pronchery     /*
523b077aed3SPierre Pronchery     ** Queue another async IO to the terminal device
524b077aed3SPierre Pronchery     */
525b077aed3SPierre Pronchery     status = sys$qio (EFN$C_ENF,
526b077aed3SPierre Pronchery                       TerminalDeviceChan,
527b077aed3SPierre Pronchery                       IO$_READVBLK,
528b077aed3SPierre Pronchery                       &TerminalDeviceIosb,
529b077aed3SPierre Pronchery                       TerminalDeviceAst,
530b077aed3SPierre Pronchery                       0,
531b077aed3SPierre Pronchery                       TerminalDeviceBuff,
532b077aed3SPierre Pronchery                       sizeof(TerminalDeviceBuff) - 1,
533b077aed3SPierre Pronchery                       0, 0, 0, 0);
534b077aed3SPierre Pronchery 
535b077aed3SPierre Pronchery     /*
536b077aed3SPierre Pronchery     ** Return status
537b077aed3SPierre Pronchery     */
538b077aed3SPierre Pronchery     return status;
539b077aed3SPierre Pronchery 
540b077aed3SPierre Pronchery }
541b077aed3SPierre Pronchery 
542b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
543b077aed3SPierre Pronchery /*                                                                            */
544b077aed3SPierre Pronchery /*----------------------------------------------------------------------------*/
LogMessage(char * msg,...)545b077aed3SPierre Pronchery static void LogMessage (char *msg, ...)
546b077aed3SPierre Pronchery {
547b077aed3SPierre Pronchery     char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
548b077aed3SPierre Pronchery                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
549b077aed3SPierre Pronchery     static unsigned int pid = 0;
550b077aed3SPierre Pronchery     va_list args;
551b077aed3SPierre Pronchery     time_t CurTime;
552b077aed3SPierre Pronchery     struct tm *LocTime;
553b077aed3SPierre Pronchery     char MsgBuff[256];
554b077aed3SPierre Pronchery 
555b077aed3SPierre Pronchery     /*
556b077aed3SPierre Pronchery     ** Get the process pid
557b077aed3SPierre Pronchery     */
558b077aed3SPierre Pronchery     if (pid == 0)
559b077aed3SPierre Pronchery         pid = getpid ();
560b077aed3SPierre Pronchery 
561b077aed3SPierre Pronchery     /*
562b077aed3SPierre Pronchery     ** Convert the current time into local time
563b077aed3SPierre Pronchery     */
564b077aed3SPierre Pronchery     CurTime = time (NULL);
565b077aed3SPierre Pronchery     LocTime = localtime (&CurTime);
566b077aed3SPierre Pronchery 
567b077aed3SPierre Pronchery     /*
568b077aed3SPierre Pronchery     ** Format the message buffer
569b077aed3SPierre Pronchery     */
570*0d0c8621SEnji Cooper     BIO_snprintf(MsgBuff, sizeof(MsgBuff), "%02d-%s-%04d %02d:%02d:%02d [%08X] %s\n",
571b077aed3SPierre Pronchery                  LocTime->tm_mday, Month[LocTime->tm_mon],
572b077aed3SPierre Pronchery                  (LocTime->tm_year + 1900), LocTime->tm_hour, LocTime->tm_min,
573b077aed3SPierre Pronchery                  LocTime->tm_sec, pid, msg);
574b077aed3SPierre Pronchery 
575b077aed3SPierre Pronchery     /*
576b077aed3SPierre Pronchery     ** Get any variable arguments and add them to the print of the message
577b077aed3SPierre Pronchery     ** buffer
578b077aed3SPierre Pronchery     */
579b077aed3SPierre Pronchery     va_start (args, msg);
580b077aed3SPierre Pronchery     vfprintf (stderr, MsgBuff, args);
581b077aed3SPierre Pronchery     va_end (args);
582b077aed3SPierre Pronchery 
583b077aed3SPierre Pronchery     /*
584b077aed3SPierre Pronchery     ** Flush standard error output
585b077aed3SPierre Pronchery     */
586b077aed3SPierre Pronchery     fsync (fileno (stderr));
587b077aed3SPierre Pronchery 
588b077aed3SPierre Pronchery     return;
589b077aed3SPierre Pronchery 
590b077aed3SPierre Pronchery }
591b077aed3SPierre Pronchery #endif
592