2 * $Id: pap_slinit.c,v 1.5 2002-01-04 04:45:48 sibaz Exp $
4 * Copyright (c) 1990,1996 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
14 #include <atalk/logger.h>
16 #include <sys/signal.h>
20 /* POSIX.1 sys/wait.h check */
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_WAIT_H
24 #endif /* HAVE_SYS_WAIT_H */
26 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
27 #endif /* ! WEXITSTATUS */
29 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
30 #endif /* ! WIFEXITED */
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>
39 #include <atalk/server_child.h>
40 #include "pap_child.h"
42 static PAP server_pap;
43 static struct server_child *children = NULL;
44 static struct pap_child **pap_ac = NULL;
46 /* send tickles and check tickle status of connections */
47 static void tickle_handler()
52 for (sid = 0; sid < children->nsessions; sid++) {
53 if (pap_ac[sid] == NULL || pap_ac[sid]->ac_state == ACSTATE_DEAD)
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 );
62 pap_ac[ sid ]->ac_state = ACSTATE_DEAD;
66 /* send off a tickle */
67 pap_tickle(server_pap, sid, &pap_ac[sid]->ac_sat);
71 static void child_cleanup(const pid_t pid)
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;
84 void pap_kill(int sig)
87 server_child_kill(children, CHILD_PAPFORK, sig);
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
97 PAP pap_slinit(PAP pap, server_child *server_children,
100 struct sigaction action;
101 struct itimerval timer;
102 struct sockaddr_at sat;
103 struct atp_block atpb;
105 struct iovec iov[ 8 ];
111 if (!(children = server_children))
114 if ((pap_ac = (struct pap_child **)
115 calloc(server_children->nsessions, sizeof(struct pap_child *)))
121 /* install cleanup pointer */
122 server_child_setup(children, CHILD_PAPFORK, child_cleanup);
124 /* install tickle handler */
125 action.sa_handler = tickle_handler;
126 sigemptyset(&action.sa_mask);
127 action.sa_flags = SA_RESTART;
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)) {
139 memset( &sat, 0, sizeof( struct sockaddr_at ));
141 sat.sat_len = sizeof( struct sockaddr_at );
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 ) {
157 switch ( pap->cmdbuf[ 0 ] ) {
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;
166 printf( "pap stat\n" );
168 if ( pap->pap_slen > 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 );
180 if (children->count < children->nsessions) {
183 for (sid = 0; sid < children->nsessions; sid++) {
184 if (pap_ac[sid] == NULL)
187 if (pap_ac[sid]->ac_state == ACSTATE_DEAD) {
194 if ((atp = atp_open(0)) == NULL)
197 switch (pid = fork()) {
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 )
208 server_child_free(children);
210 atp_close(pap->pap_atp);
215 pap->pap_wss = pap->cmdbuf[1];
218 pap->pap_flags = PAPFL_SSS;
221 case -1 : /* error */
222 pap->cmdbuf[ 0 ] = 0;
223 pap->cmdbuf[ 1 ] = 0;
224 paperr = PAPERR_SERVBUSY;
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];
237 pap->cmdbuf[0] = atp_sockaddr(atp)->sat_port;
238 pap->cmdbuf[1] = sid;
241 } /* fall through if malloc fails */
242 case -1: /* bad error */
245 default: /* non-fatal error */
253 pap->cmdbuf[0] = pap->cmdbuf[1] = 0;
254 paperr = PAPERR_SERVBUSY;
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 );
266 LOG(log_info, logtype_default, "PAPUnknown %d", pap->cmdbuf[0]);