1 /*
2  *  The Regina Rexx Interpreter
3  *  Copyright (C) 2000  Mark Hessling <M.Hessling@qut.edu.au>
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Library General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Library General Public
16  *  License along with this library; if not, write to the Free
17  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include "rexxbif.h"            /* C functions that mimic REXX BIFs */
20 
21 #define FIFO_LINE(buf,line) {                                            \
22       /* This macro adds a line to a buffer in FIFO manner.              \
23        * The line's higher/lower elements will be overwritten both.      \
24        */                                                                \
25       (line)->lower = NULL ;                                             \
26       (line)->higher = (buf)->bottom ;                                   \
27       (buf)->bottom = line ;                                             \
28       if ( (line)->higher != NULL )                                      \
29          (line)->higher->lower = (line) ;                                \
30       else                                                               \
31       {                                                                  \
32          (buf)->top = (line) ;         /* buffer was empty previously */ \
33          assert( (buf)->elements == 0 ) ;                                \
34       }                                                                  \
35       (buf)->elements++ ;                                                \
36    }
37 
38 #define LIFO_LINE(buf,line) {                                            \
39       /* This macro adds a line to a buffer in LIFO manner.              \
40        * The line's higher/lower elements will be overwritten both.      \
41        */                                                                \
42       (line)->higher = NULL ;                                            \
43       (line)->lower = (buf)->top ;                                       \
44       (buf)->top = line ;                                                \
45       if ( (line)->lower != NULL )                                       \
46          (line)->lower->higher = (line) ;                                \
47       else                                                               \
48       {                                                                  \
49          (buf)->bottom = (line) ;      /* buffer was empty previously */ \
50          assert( (buf)->elements == 0 ) ;                                \
51       }                                                                  \
52       (buf)->elements++ ;                                                \
53    }
54 
55 #define POP_LINE(buf,line) {                                             \
56       /* This macro removes a line from a buffer. The argument "line"    \
57        * will be overwritten. The higher/older elements of that value    \
58        * won't be overwritten.                                           \
59        */                                                                \
60       if ( ( (line) = (buf)->top ) != NULL )                             \
61       {                                                                  \
62          (buf)->elements-- ;                                             \
63          if ( ( (buf)->top = (line)->lower ) == NULL )                   \
64          {                                                               \
65             (buf)->bottom = NULL ;                                       \
66             assert( (buf)->elements == 0 ) ;                             \
67             (buf)->elements = 0 ;         /* if assert is defined out */ \
68          }                                                               \
69          else                                                            \
70          {                                                               \
71             (buf)->top->higher = NULL ;                                  \
72          }                                                               \
73       }                                                                  \
74    }
75 
76 #define GLUE_BUFFER1(buf1,buf2) {                                              \
77       /* This macro glues buf2 at the top of buf1 and writes the result        \
78        * to buf1. buf2's top/bottom/elements fields are reset.                 \
79        */                                                                      \
80       if ( (buf2)->bottom != NULL )                                            \
81       {                                                                        \
82          if ( (buf1)->top == NULL )                                            \
83          {                                                                     \
84             assert( ( (buf1)->bottom == NULL ) && ( (buf1)->elements == 0 ) ) ;\
85             (buf1)->top = (buf2)->top ;                                        \
86             (buf1)->bottom = (buf2)->bottom ;                                  \
87             (buf1)->elements = (buf2)->elements ;                              \
88          }                                                                     \
89          else                                                                  \
90          {                                                                     \
91             (buf1)->top->higher = (buf2)->bottom ;                             \
92             (buf2)->bottom->lower = (buf1)->top ;                              \
93             (buf1)->top = (buf2)->top ;                                        \
94             (buf1)->elements += (buf2)->elements ;                             \
95          }                                                                     \
96       }                                                                        \
97       else                                                                     \
98       {                                                                        \
99          assert( ( (buf2)->top == NULL ) && ( (buf2)->elements == 0 ) ) ;      \
100       }                                                                        \
101       (buf2)->top = NULL ;                                                       \
102       (buf2)->bottom = NULL ;                                                    \
103       (buf2)->elements = 0 ;                                                     \
104    }
105 
106 #define GLUE_BUFFER2(buf1,buf2) {                                              \
107       /* This macro glues buf2 at the top of buf1 and writes the result        \
108        * to buf2. buf1's top/bottom/elements fields are reset.                 \
109        */                                                                      \
110       if ( (buf1)->bottom != NULL )                                            \
111       {                                                                        \
112          if ( (buf2)->top == NULL )                                            \
113          {                                                                     \
114             assert( ( (buf2)->bottom == NULL ) && ( (buf2)->elements == 0 ) ) ;\
115             (buf2)->top = (buf1)->top ;                                        \
116             (buf2)->bottom = (buf1)->bottom ;                                  \
117             (buf2)->elements = (buf1)->elements ;                              \
118          }                                                                     \
119          else                                                                  \
120          {                                                                     \
121             (buf1)->top->higher = (buf2)->bottom ;                             \
122             (buf2)->bottom->lower = (buf1)->top ;                              \
123             (buf2)->bottom = (buf1)->bottom ;                                  \
124             (buf2)->elements += (buf2)->elements ;                             \
125          }                                                                     \
126       }                                                                        \
127       else                                                                     \
128       {                                                                        \
129          assert( ( (buf1)->top == NULL ) && ( (buf1)->elements == 0 ) ) ;      \
130       }                                                                        \
131       (buf1)->top = NULL ;                                                       \
132       (buf1)->bottom = NULL ;                                                    \
133       (buf1)->elements = 0 ;                                                     \
134    }
135 
136 void showerror( int err, int suberr, char *tmpl, ...);
137 int init_external_queue( const tsd_t *TSD );
138 void term_external_queue( void );
139 int default_port_number( void ) ;
140 int default_external_address( void ) ;
141 streng *default_external_name( const tsd_t *TSD ) ;
142 int connect_to_rxstack( tsd_t *TSD, Queue *q ) ;
143 int disconnect_from_rxstack( const tsd_t *TSD, Queue *q ) ;
144 int parse_queue( tsd_t *TSD, streng *queue, Queue *q ) ;
145 int send_command_to_rxstack( const tsd_t *TSD, int sock, const char *action, const char *str, int len );
146 streng *read_result_from_rxstack( const tsd_t *TSD, int sock, int result_size );
147 int delete_queue_from_rxstack( const tsd_t *TSD, int sock, const streng *queue_name );
148 int set_queue_in_rxstack( const tsd_t *TSD, int sock, const streng *queue_name );
149 int get_number_in_queue_from_rxstack( const tsd_t *TSD, int sock, int *errcode );
150 int get_queues_from_rxstack( const tsd_t *TSD, int sock, int *errcode, streng **results );
151 int clear_queue_on_rxstack( const tsd_t *TSD, int sock ) ;
152 int get_queue_from_rxstack( const tsd_t *TSD, const Queue *q, streng **result );
153 int create_queue_on_rxstack( const tsd_t *TSD, const Queue *q, const streng *queue, streng **result );
154 int timeout_queue_on_rxstack( const tsd_t *TSD, int sock, long timeout );
155 int get_line_from_rxstack( const tsd_t *TSD, int sock, streng **result, int nowait );
156 int queue_line_lifo_to_rxstack( const tsd_t *TSD, int sock, const streng *line );
157 int queue_line_fifo_to_rxstack( const tsd_t *TSD, int sock, const streng *line );
158 int get_length_from_header( const tsd_t *TSD, const streng *header );
159 
160 #define RXSTACK_EXIT                'X'
161 #define RXSTACK_EXIT_STR            "X"
162 #define RXSTACK_KILL                'Z'
163 #define RXSTACK_KILL_STR            "Z"
164 #define RXSTACK_QUEUE_FIFO          'F'
165 #define RXSTACK_QUEUE_FIFO_STR      "F"
166 #define RXSTACK_QUEUE_LIFO          'L'
167 #define RXSTACK_QUEUE_LIFO_STR      "L"
168 #define RXSTACK_CREATE_QUEUE        'C'
169 #define RXSTACK_CREATE_QUEUE_STR    "C"
170 #define RXSTACK_DELETE_QUEUE        'D'
171 #define RXSTACK_DELETE_QUEUE_STR    "D"
172 #define RXSTACK_EMPTY_QUEUE         'E'
173 #define RXSTACK_EMPTY_QUEUE_STR     "E"
174 #define RXSTACK_PULL                'P'
175 #define RXSTACK_PULL_STR            "P"
176 #define RXSTACK_FETCH               'p'
177 #define RXSTACK_FETCH_STR           "p"
178 #define RXSTACK_SET_QUEUE           'S'
179 #define RXSTACK_SET_QUEUE_STR       "S"
180 #define RXSTACK_GET_QUEUE           'G'
181 #define RXSTACK_GET_QUEUE_STR       "G"
182 #define RXSTACK_NUMBER_IN_QUEUE     'N'
183 #define RXSTACK_NUMBER_IN_QUEUE_STR "N"
184 #define RXSTACK_SHOW_QUEUES         'Q'
185 #define RXSTACK_SHOW_QUEUES_STR     "Q"
186 #define RXSTACK_TIMEOUT_QUEUE       'T'
187 #define RXSTACK_TIMEOUT_QUEUE_STR   "T"
188 #define RXSTACK_UNKNOWN             '?'
189 #define RXSTACK_UNKNOWN_STR         "?"
190 #define RXSTACK_HEADER_SIZE         7
191 #define RXSTACK_PEEK_HEADER_SIZE    2
192 #define RXSTACK_TIMEOUT_SIZE        6
193 
194 #ifndef RXSOCKET
195 # define RXSOCKET 5757
196 #endif
197 
198 #define ERR_RXSTACK_CANT_CONNECT       101
199 #define ERR_RXSTACK_CANT_CONNECT_TMPL    "Error connecting to %s on port %d: \"%s\""
200 #define ERR_RXSTACK_NO_IP              102
201 #define ERR_RXSTACK_NO_IP_TMPL           "Unable to obtain IP address for %s"
202 #define ERR_RXSTACK_INVALID_SERVER     103
203 #define ERR_RXSTACK_INVALID_SERVER_TMPL  "Invalid format for server in specified queue name: \"%s\""
204 #define ERR_RXSTACK_INVALID_QUEUE      104
205 #define ERR_RXSTACK_INVALID_QUEUE_TMPL   "Invalid format for queue name: \"%s\""
206 #define ERR_RXSTACK_NO_WINSOCK         105
207 #define ERR_RXSTACK_NO_WINSOCK_TMPL      "Unable to start Windows Socket interface: %s"
208 #define ERR_RXSTACK_TOO_MANY_QUEUES    106
209 #define ERR_RXSTACK_TOO_MANY_QUEUES_TMPL "Maximum number of external queues exceeded: %d"
210 #define ERR_RXSTACK_READING_SOCKET     107
211 #define ERR_RXSTACK_READING_SOCKET_TMPL  "Error occured reading socket: %s"
212 #define ERR_RXSTACK_INVALID_SWITCH     108
213 #define ERR_RXSTACK_INVALID_SWITCH_TMPL  "Invalid switch passed. Must be one of \"%s\""
214 #define ERR_RXSTACK_ACTION_SESSION     112
215 #define ERR_RXSTACK_ACTION_SESSION_TMPL  "Unable to %s SESSION queue"
216 
217 #define ERR_RXSTACK_INTERNAL            99
218 #define ERR_RXSTACK_INTERNAL_TMPL        "Internal error with external queue interface: %d \"%s\""
219 #define ERR_RXSTACK_GENERAL            100
220 #define ERR_RXSTACK_GENERAL_TMPL         "General system error with external queue interface. %s. %s"
221 
222 #define ERR_STORAGE_EXHAUSTED_TMPL       "System resources exhausted"
223 
224 /*
225  * Return codes from interacting with rxstack
226  */
227 #define RXSTACK_OK      0
228 #define RXSTACK_EMPTY   1
229 #define RXSTACK_ERROR   2
230 #define RXSTACK_WAITING 3
231 #define RXSTACK_TIMEOUT 4
232