df71eaea377a03cf133be5d1c23d9a84ee6cb1e0
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / sipoll.c
1 // vim: noet sw=4 ts=4:
2 /*
3 ==================================================================================
4     Copyright (c) 2020 Nokia
5     Copyright (c) 2020 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22 **************************************************************************
23 *  Mnemonic: SIpoll
24 *  Abstract: This routine will poll the sockets that are open for
25 *            an event and return after the delay period has expired, or
26 *            an event has been processed.
27 *  Parms:    gptr   - Pointer to the global information block
28 *            msdelay- 100ths of seconds to delay
29 *  Returns:  SI_OK if the caller can continue, SI_ERROR if all sessions have been
30 *            stopped, or the interface cannot proceed. When SI_ERROR is
31 *            returned the caller should cleanup and exit immediatly (we
32 *            have probably received a sigter or sigquit.
33 *  Date:     10 April 1995
34 *  Author:   E. Scott Daniels
35 *
36 **************************************************************************
37 */
38 #include  "sisetup.h"     //  get the setup stuff
39 #include "sitransport.h"
40 #include <wait.h>
41
42
43 extern int SIpoll( struct ginfo_blk *gptr, int msdelay )
44 {
45  //extern int deaths;       //  number of children that died and are zombies
46  //extern int sigflags;     //  flags set by the signal handler routine
47
48  int fd;                       //  file descriptor for use in this routine
49  int ((*cbptr)());             //  pointer to callback routine to call
50  int status = SI_OK;              //  return status
51  int addrlen;                  //  length of address from recvfrom call
52  char *buf;                    //  work buffer pointer
53  char ibuf[1025];
54  int i;                        //  loop index
55  struct tp_blk *tpptr;         //  pointer at tp stuff
56  struct tp_blk *nextone;        //  pointer at next block to process
57  int pstat;                    //  poll status
58  int kstat;                    //  keyboard status
59  struct timeval  delay;        //  delay to use on select call
60  struct sockaddr *uaddr;       //  pointer to udp address
61
62  gptr->sierr = SI_ERR_SHUTD;
63
64  if( gptr->flags & GIF_SHUTDOWN )     //  cannot do if we should shutdown
65   return( SI_ERROR );                    //  so just get out
66
67
68  gptr->sierr = SI_ERR_HANDLE;
69
70  if( gptr->magicnum != MAGICNUM )     //  if not a valid ginfo block
71   return( SI_ERROR );
72
73    delay.tv_sec = msdelay/100;                //  user submits 100ths, cvt to seconds and milliseconds
74    delay.tv_usec = (msdelay%100) * 10;
75
76
77    SIbldpoll( gptr );                 //  build the fdlist for poll
78    pstat = 0;                         //  ensure good code
79
80    if( gptr->fdcount > 0 )
81     pstat = select( gptr->fdcount, &gptr->readfds, &gptr->writefds,
82                                &gptr->execpfds, &delay );
83
84    if( (pstat < 0 && errno != EINTR)  )
85     {                             //  poll fail or termination signal rcvd
86      gptr->fdcount = 0;           //  prevent trying to look at a session
87      gptr->flags |= GIF_SHUTDOWN; //  cause cleanup and exit at end
88      //deaths = 0;                  //  dont need to issue waits on dead child
89      //sigflags = 0;                //  who cares about signals now too
90     }
91
92 /*
93    while( deaths > 0 )  //  there have been death(s) - keep the dead
94     {                   //  from being zombies - send them to heaven
95      wait( NULL );                       //  issue wait on child
96      deaths--;
97     }                   //  end while dead children to send to heaven
98 */
99
100 /*
101   if( sigflags &&        //  if signal received and processing them
102      (cbptr = gptr->cbtab[SI_CB_SIGNAL].cbrtn) != NULL )
103    {
104     while( sigflags != 0 )
105      {
106       i = sigflags;                  //  hold for call
107       sigflags = 0;                  //  incase we are interrupted while away
108       status = (*cbptr)( gptr->cbtab[SI_CB_SIGNAL].cbdata, i );
109       SIcbstat( gptr, status, SI_CB_SIGNAL );    //  handle status
110      }                                           //  end while
111    }
112 */
113
114    if( pstat > 0  &&  (! (gptr->flags & GIF_SHUTDOWN)) )
115     {
116      if( FD_ISSET( 0, &gptr->readfds ) )       //  check for keybd input
117       {
118        fgets( ibuf, 1024, stdin );   //  get the stuff from keyboard
119        if( (cbptr = gptr->cbtab[SI_CB_KDATA].cbrtn) != NULL )
120         {
121          status = (*cbptr)( gptr->cbtab[SI_CB_KDATA].cbdata, ibuf );
122          SIcbstat(  gptr, status, SI_CB_KDATA );    //  handle status
123         }                                 //  end if call back was defined
124       }
125
126      // for( tpptr = gptr->tplist; tpptr != NULL; tpptr = tpptr->next )
127      for( tpptr = gptr->tplist; tpptr != NULL; tpptr = nextone )
128       {
129         nextone = tpptr->next;                                  //  prevent coredump if we delete the session
130
131        if( tpptr->squeue != NULL && (FD_ISSET( tpptr->fd, &gptr->writefds )) )
132         SIsend( gptr, tpptr );              //  send if clear to send
133
134        if( FD_ISSET( tpptr->fd, &gptr->execpfds ) )
135         {
136          ; //  sunos seems to set except for unknown reasons; ignore
137         }
138        else
139        if( FD_ISSET( tpptr->fd, &gptr->readfds ) )  //  read event pending?
140         {
141          fd = tpptr->fd;                     //  quick ref to the fd
142
143          if( tpptr->flags & TPF_LISTENFD )     //  listen port setup by init?
144           {                                    //  yes-assume new session req
145            status = SInewsession( gptr, tpptr );    //  make new session
146           }
147          else                              //  data received on a regular port
148           if( tpptr->type == SOCK_DGRAM )          //  udp socket?
149            {
150             uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
151             status = RECVFROM( fd, gptr->rbuf, MAX_RBUF, 0, uaddr, &addrlen );
152             if( status >= 0 && ! (tpptr->flags & TPF_DRAIN) )
153              {                                                           //  if good status call cb routine
154               if( (cbptr = gptr->cbtab[SI_CB_RDATA].cbrtn) != NULL )
155                {
156                 SIaddress( uaddr, (void **) &buf, AC_TODOT );
157                 status = (*cbptr)( gptr->cbtab[SI_CB_RDATA].cbdata, gptr->rbuf, status, buf );
158                 SIcbstat( gptr, status, SI_CB_RDATA );    //  handle status
159                 free( buf );
160                }                              //  end if call back was defined
161              }                                //  end if status was ok
162             free( uaddr );
163            }                                  //  end if udp
164           else
165            {                                //  else receive on tcp session
166             status = RECV( fd, gptr->rbuf, MAX_RBUF, 0 );    //  read data
167
168             if( status > SI_OK  &&  ! (tpptr->flags & TPF_DRAIN) )
169              {
170               if( (cbptr = gptr->cbtab[SI_CB_CDATA].cbrtn) != NULL )
171                {
172                 status = (*cbptr)( gptr->cbtab[SI_CB_CDATA].cbdata, fd, gptr->rbuf, status );
173                 SIcbstat( gptr, status, SI_CB_CDATA );   //  handle cb status
174                }                            //  end if call back was defined
175              }                                     //  end if status was ok
176             else   //  sunos seems to send 0 bytes as indication of disc
177              {
178               if( (cbptr = gptr->cbtab[SI_CB_DISC].cbrtn) != NULL )
179                {
180                 status = (*cbptr)( gptr->cbtab[SI_CB_DISC].cbdata, tpptr->fd );
181                 SIcbstat( gptr, status, SI_CB_DISC );    //  handle status
182                }
183               SIterm( gptr, tpptr );
184             }
185            }                                                //  end tcp read
186         }                    //  end if event on this fd
187       }                      //  end for each fd in the list
188     }                        //  end if not in shutdown
189
190
191  if( gptr->flags & GIF_SHUTDOWN )      //  we need to stop for some reason
192   {
193    gptr->sierr = SI_ERR_SHUTD;        //  indicate error exit status
194    status = SI_ERROR;                //  status should indicate to user to die
195    SIshutdown( gptr );            //  clean things up
196   }
197  else
198   status = SI_OK;                    //  user can continue to process
199
200  return( status );                //  send status back to caller
201 }                                 //  SIwait