]> arthur.barton.de Git - netatalk.git/blob - libatalk/dsi/dsi_getsess.c
Warning fixes.
[netatalk.git] / libatalk / dsi / dsi_getsess.c
1 /*
2  * $Id: dsi_getsess.c,v 1.4 2001-08-15 02:18:57 srittau Exp $
3  *
4  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
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 <string.h>
15 #include <errno.h>
16 #ifdef HAVE_UNISTD_H
17 #include <unistd.h>
18 #endif /* HAVE_UNISTD_H */
19 #include <sys/types.h>
20 #include <signal.h>
21 #include <sys/wait.h>
22 #include <sys/time.h>
23 #include <syslog.h>
24
25 #include <atalk/dsi.h>
26 #include <atalk/server_child.h>
27
28 static server_child *children = NULL;
29
30 void dsi_kill(int sig)
31 {
32   if (children)
33     server_child_kill(children, CHILD_DSIFORK, sig);
34 }
35
36 /* hand off the command. return child connection to the main program */
37 DSI *dsi_getsession(DSI *dsi, server_child *serv_children, 
38                     const int tickleval)
39 {
40   pid_t pid;
41   
42   /* do a couple things on first entry */
43   if (!dsi->inited) {
44     if (!(children = serv_children))
45       return NULL;
46     dsi->inited = 1;
47   }
48   
49   switch (pid = dsi->proto_open(dsi)) {
50   case -1:
51     /* if we fail, just return. it might work later */
52     syslog(LOG_ERR, "dsi_getsess: %s", strerror(errno));
53     return dsi;
54
55   case 0: /* child. mostly handled below. */
56     dsi->child = 1;
57     break;
58
59   default: /* parent */
60     /* using SIGQUIT is hokey, but the child might not have
61      * re-established its signal handler for SIGTERM yet. */
62     if (server_child_add(children, CHILD_DSIFORK, pid) < 0) {
63       syslog(LOG_ERR, "dsi_getsess: %s", strerror(errno));
64       dsi->header.dsi_flags = DSIFL_REPLY;
65       dsi->header.dsi_code = DSIERR_SERVBUSY;
66       dsi_send(dsi);
67       dsi->header.dsi_code = DSIERR_OK;
68       kill(pid, SIGQUIT);
69     }
70
71     dsi->proto_close(dsi);
72     return dsi;
73   }
74   
75   /* child: check number of open connections. this is one off the
76    * actual count. */
77   if ((children->count >= children->nsessions) &&
78       (dsi->header.dsi_command == DSIFUNC_OPEN)) {
79     syslog(LOG_INFO, "dsi_getsess: too many connections");
80     dsi->header.dsi_flags = DSIFL_REPLY;
81     dsi->header.dsi_code = DSIERR_TOOMANY;
82     dsi_send(dsi);
83     exit(1);
84   }
85
86   /* get rid of some stuff */
87   close(dsi->serversock);
88   server_child_free(children); 
89   children = NULL;
90
91   switch (dsi->header.dsi_command) {
92   case DSIFUNC_STAT: /* send off status and return */
93     {
94       /* OpenTransport 1.1.2 bug workaround: 
95        *
96        * OT code doesn't currently handle close sockets well. urk.
97        * the workaround: wait for the client to close its
98        * side. timeouts prevent indefinite resource use. 
99        */
100       
101       static struct timeval timeout = {120, 0};
102       fd_set readfds;
103       
104       dsi_getstatus(dsi);
105
106       FD_ZERO(&readfds);
107       FD_SET(dsi->socket, &readfds);
108       free(dsi);
109       select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);    
110       exit(0);
111     }
112     break;
113     
114   case DSIFUNC_OPEN: /* setup session */
115     /* set up the tickle timer */
116     dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval;
117     dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
118     signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */
119     dsi_opensession(dsi);
120     return dsi;
121     break;
122
123   default: /* just close */
124     syslog(LOG_INFO, "DSIUnknown %d", dsi->header.dsi_command);
125     dsi->proto_close(dsi);
126     exit(1);
127   }
128 }