]> arthur.barton.de Git - netatalk.git/blob - libatalk/pap/pap_slinit.c
Removed an unused file.
[netatalk.git] / libatalk / pap / pap_slinit.c
1 /*
2  * $Id: pap_slinit.c,v 1.5 2002-01-04 04:45:48 sibaz Exp $
3  *
4  * Copyright (c) 1990,1996 Regents of The University of Michigan.
5  * All Rights Reserved.  See COPYRIGHT.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif /* HAVE_CONFIG_H */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <atalk/logger.h>
15 #include <errno.h>
16 #include <sys/signal.h>
17 #include <sys/time.h>
18 #include <sys/uio.h>
19
20 /* POSIX.1 sys/wait.h check */
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_WAIT_H
23 #include <sys/wait.h>
24 #endif /* HAVE_SYS_WAIT_H */
25 #ifndef WEXITSTATUS
26 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
27 #endif /* ! WEXITSTATUS */
28 #ifndef WIFEXITED
29 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
30 #endif /* ! WIFEXITED */
31
32 #include <sys/socket.h>
33 #include <sys/param.h>
34 #include <netatalk/at.h>
35 #include <atalk/compat.h>
36 #include <atalk/atp.h>
37 #include <atalk/pap.h>
38
39 #include <atalk/server_child.h>
40 #include "pap_child.h"
41
42 static PAP server_pap;
43 static struct server_child *children = NULL;
44 static struct pap_child    **pap_ac = NULL;
45
46 /* send tickles and check tickle status of connections */
47 static void tickle_handler()
48 {
49   int sid;
50   
51   /* check status */
52   for (sid = 0; sid < children->nsessions; sid++) {
53     if (pap_ac[sid] == NULL || pap_ac[sid]->ac_state == ACSTATE_DEAD) 
54       continue;
55     
56     if (++pap_ac[sid]->ac_state >= ACSTATE_BAD) {
57       /* kill. if already dead, just continue */
58       if (kill( pap_ac[ sid ]->ac_pid, SIGTERM) == 0)
59         LOG(log_info, logtype_default, "pap_alrm: %d timed out",
60                 pap_ac[ sid ]->ac_pid );
61
62       pap_ac[ sid ]->ac_state = ACSTATE_DEAD;
63       continue;
64     }
65
66     /* send off a tickle */
67     pap_tickle(server_pap, sid, &pap_ac[sid]->ac_sat);
68   }
69 }
70
71 static void child_cleanup(const pid_t pid)
72 {
73   int i;
74
75   for (i = 0; i < children->nsessions; i++)
76     if (pap_ac[i] && (pap_ac[i]->ac_pid == pid)) {
77       pap_ac[i]->ac_state = ACSTATE_DEAD;
78       break;
79     }
80 }
81
82
83 /* kill children */
84 void pap_kill(int sig)
85 {
86   if (children) 
87     server_child_kill(children, CHILD_PAPFORK, sig);
88 }
89
90
91 /*
92  * This call handles open, tickle, and getstatus requests. On a
93  * successful open, it forks a child process. 
94  * It returns an PAP to the child and parent and NULL if there is
95  * an error.
96  */
97 PAP pap_slinit(PAP pap, server_child *server_children, 
98                const int tickleval)
99 {
100     struct sigaction action;
101     struct itimerval timer;
102     struct sockaddr_at  sat;
103     struct atp_block    atpb;
104     ATP                 atp;
105     struct iovec        iov[ 8 ];
106     pid_t               pid;
107     int                 i, sid;
108     u_short             paperr;
109
110     if (!pap->inited) {
111       if (!(children = server_children))
112         return NULL;
113
114       if ((pap_ac = (struct pap_child **) 
115            calloc(server_children->nsessions, sizeof(struct pap_child *)))
116            == NULL)
117         return NULL;
118
119       server_pap = pap;
120
121       /* install cleanup pointer */
122       server_child_setup(children, CHILD_PAPFORK, child_cleanup);
123
124       /* install tickle handler */
125       action.sa_handler = tickle_handler;
126       sigemptyset(&action.sa_mask);
127       action.sa_flags = SA_RESTART;
128
129       timer.it_interval.tv_sec = timer.it_value.tv_sec = tickleval;
130       timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
131       if ((setitimer(ITIMER_REAL, &timer, NULL) < 0) ||
132           (sigaction(SIGALRM, &action, NULL) < 0)) {
133         exit(1);
134       }
135
136       pap->inited = 1;
137     }
138                     
139     memset( &sat, 0, sizeof( struct sockaddr_at ));
140 #ifdef BSD4_4
141     sat.sat_len = sizeof( struct sockaddr_at );
142 #endif /* BSD4_4 */
143     sat.sat_family = AF_APPLETALK;
144     sat.sat_addr.s_net = ATADDR_ANYNET;
145     sat.sat_addr.s_node = ATADDR_ANYNODE;
146     sat.sat_port = ATADDR_ANYPORT;
147     atpb.atp_saddr = &sat;
148     atpb.atp_rreqdata = pap->cmdbuf;
149     atpb.atp_rreqdlen = sizeof( pap->cmdbuf );
150     while ( atp_rreq( pap->pap_atp, &atpb ) < 0 ) {
151       if ( errno == EINTR || errno == EAGAIN ) {
152         continue;
153       }
154       return( NULL );
155     }
156     
157     switch ( pap->cmdbuf[ 0 ] ) {
158     case PAPFUNC_TICKLE:
159       sid = pap->cmdbuf[1];
160       if ((pap_ac[sid] != NULL) && (pap_ac[sid]->ac_state != ACSTATE_DEAD))
161         pap_ac[sid]->ac_state = ACSTATE_OK;
162       break;
163
164     case PAPFUNC_STAT:
165 #ifdef EBUG
166       printf( "pap stat\n" );
167 #endif /* EBUG */
168       if ( pap->pap_slen > 0 ) {
169         pap->cmdbuf[0] = 0;
170         bcopy( pap->pap_status, pap->cmdbuf + 4, pap->pap_slen );
171         iov[ 0 ].iov_base = pap->cmdbuf;
172         iov[ 0 ].iov_len = 4 + pap->pap_slen;
173         atpb.atp_sresiov = iov;
174         atpb.atp_sresiovcnt = 1;
175         atp_sresp( pap->pap_atp, &atpb );
176       }
177       break;
178
179     case PAPFUNC_OPEN :
180       if (children->count < children->nsessions) {
181
182         /* find a slot */
183         for (sid = 0; sid < children->nsessions; sid++) {
184           if (pap_ac[sid] == NULL)
185             break;
186
187           if (pap_ac[sid]->ac_state == ACSTATE_DEAD) {
188             free(pap_ac[sid]);
189             pap_ac[sid] = NULL;
190             break;
191           }
192         }
193
194         if ((atp = atp_open(0)) == NULL) 
195           return NULL;
196
197         switch (pid = fork()) {
198         case 0 : /* child */
199           signal(SIGTERM, SIG_DFL);
200           signal(SIGHUP, SIG_DFL);
201           /* free/close some things */
202           for (i = 0; i < children->nsessions; i++ ) {
203             if ( pap_ac[i] != NULL )
204               free( pap_ac[i] );
205           }
206           free(pap_ac);
207           
208           server_child_free(children);
209           children = NULL;
210           atp_close(pap->pap_atp);
211
212           pap->child = 1;
213           pap->pap_atp = atp;
214           pap->pap_sat = sat;
215           pap->pap_wss = pap->cmdbuf[1];
216           pap->pap_seq = 0;
217           pap->pap_sid = sid;
218           pap->pap_flags = PAPFL_SSS;
219           return pap;
220           
221         case -1 : /* error */
222           pap->cmdbuf[ 0 ] = 0;
223           pap->cmdbuf[ 1 ] = 0;
224           paperr = PAPERR_SERVBUSY;
225           break;
226           
227         default : /* parent process */
228           switch (server_child_add(children, CHILD_PAPFORK, pid)) {
229           case 0: /* added child */
230             if (pap_ac[sid] = (struct pap_child *) 
231                 malloc(sizeof(struct pap_child))) {
232               pap_ac[sid]->ac_pid = pid;
233               pap_ac[sid]->ac_state = ACSTATE_OK;
234               pap_ac[sid]->ac_sat = sat;
235               pap_ac[sid]->ac_sat.sat_port = pap->cmdbuf[1];
236               
237               pap->cmdbuf[0] = atp_sockaddr(atp)->sat_port;
238               pap->cmdbuf[1] = sid;
239               paperr = PAPERR_OK;
240               break;
241             } /* fall through if malloc fails */
242           case -1: /* bad error */
243             kill(pid, SIGQUIT); 
244             break;
245           default: /* non-fatal error */
246             break;
247           }
248           atp_close(atp);
249           break;
250         }
251         
252       } else {
253         pap->cmdbuf[0] = pap->cmdbuf[1] = 0;
254         paperr = PAPERR_SERVBUSY;
255       }
256
257       bcopy( &paperr, pap->cmdbuf + 2, sizeof( u_short ));
258       iov[ 0 ].iov_base = pap->cmdbuf;
259       iov[ 0 ].iov_len = 4;
260       atpb.atp_sresiov = iov;
261       atpb.atp_sresiovcnt = 1;
262       atp_sresp( pap->pap_atp, &atpb );
263       break;
264
265     default:
266       LOG(log_info, logtype_default, "PAPUnknown %d", pap->cmdbuf[0]);
267       break;
268     }
269
270     return pap;
271 }