/*
- * $Id: afp_dsi.c,v 1.36 2009-04-16 06:17:14 franklahm Exp $
+ * $Id: afp_dsi.c,v 1.46 2009-10-25 06:12:51 didg Exp $
*
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
* Copyright (c) 1990,1993 Regents of The University of Michigan.
#include "uid.h"
#endif /* FORCE_UIDGID */
-extern struct oforks *writtenfork;
-
#define CHILD_DIE (1 << 0)
#define CHILD_RUNNING (1 << 1)
#define CHILD_SLEEPING (1 << 2)
+#define CHILD_DATA (1 << 3)
static struct {
AFPObj *obj;
{
DSI *dsi = obj->handle;
+ /* XXX we have to check we are not root here */
close_all_vol();
if (obj->logout)
(*obj->logout)();
}
/* ------------------- */
-static void afp_dsi_timedown()
+static void afp_dsi_timedown(int sig _U_)
{
struct sigaction sv;
struct itimerval it;
child.flags |= CHILD_DIE;
/* shutdown and don't reconnect. server going down in 5 minutes. */
setmessage("The server is going down for maintenance.");
- dsi_attention(child.obj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
- AFPATTN_MESG | AFPATTN_TIME(5));
+ if (dsi_attention(child.obj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
+ AFPATTN_MESG | AFPATTN_TIME(5)) < 0) {
+ DSI *dsi = (DSI *) child.obj->handle;
+ dsi->down_request = 1;
+ }
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
it.it_value.tv_sec = 300;
it.it_value.tv_usec = 0;
- if ( setitimer( ITIMER_REAL, &it, 0 ) < 0 ) {
+ if ( setitimer( ITIMER_REAL, &it, NULL ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_timedown: setitimer: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
}
sigaddset(&sv.sa_mask, SIGHUP);
sigaddset(&sv.sa_mask, SIGTERM);
sv.sa_flags = SA_RESTART;
- if ( sigaction( SIGALRM, &sv, 0 ) < 0 ) {
+ if ( sigaction( SIGALRM, &sv, NULL ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_timedown: sigaction: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
}
sv.sa_handler = SIG_IGN;
sigemptyset( &sv.sa_mask );
sv.sa_flags = SA_RESTART;
- if ( sigaction( SIGUSR1, &sv, 0 ) < 0 ) {
+ if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_timedown: sigaction SIGHUP: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
}
-
}
/* ---------------------------------
*/
volatile int reload_request = 0;
-static void afp_dsi_reload()
+static void afp_dsi_reload(int sig _U_)
{
reload_request = 1;
}
#ifdef SERVERTEXT
static void afp_dsi_getmesg (int sig _U_)
{
- readmessage(child.obj);
- dsi_attention(child.obj->handle, AFPATTN_MESG | AFPATTN_TIME(5));
+ DSI *dsi = (DSI *) child.obj->handle;
+
+ dsi->msg_request = 1;
+ if (dsi_attention(child.obj->handle, AFPATTN_MESG | AFPATTN_TIME(5)) < 0)
+ dsi->msg_request = 2;
}
#endif /* SERVERTEXT */
-static void alarm_handler()
+static void alarm_handler(int sig _U_)
{
int err;
+ DSI *dsi = (DSI *) child.obj->handle;
+
+ /* we have to restart the timer because some libraries
+ * may use alarm() */
+ setitimer(ITIMER_REAL, &dsi->timer, NULL);
+
+ /* we got some traffic from the client since the previous timer
+ * tick. */
+ if ((child.flags & CHILD_DATA)) {
+ child.flags &= ~CHILD_DATA;
+ return;
+ }
/* if we're in the midst of processing something,
don't die. */
if ((child.flags & CHILD_SLEEPING) && child.tickle++ < child.obj->options.sleep) {
return;
- } else if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
+ }
+
+ if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
if (!(err = pollvoltime(child.obj)))
err = dsi_tickle(child.obj->handle);
if (err <= 0)
}
}
-
-#ifdef DEBUG1
-/* ---------------------------------
- * old signal handler for SIGUSR1 - set the debug flag and
- * redirect stdout to <tmpdir>/afpd-debug-<pid>.
- */
-void afp_set_debug (int sig)
+/* -----------------
+ if dsi->in_write is set attention, tickle (and close?) msg
+ aren't sent. We don't care about tickle
+*/
+static void pending_request(DSI *dsi)
{
- char fname[MAXPATHLEN];
-
- snprintf(fname, MAXPATHLEN-1, "%safpd-debug-%d", P_tmpdir, getpid());
- freopen(fname, "w", stdout);
- child.obj->options.flags |= OPTION_DEBUG;
+ /* send pending attention */
- return;
+ /* read msg if any, it could be done in afp_getsrvrmesg */
+ if (dsi->msg_request) {
+ if (dsi->msg_request == 2) {
+ /* didn't send it in signal handler */
+ dsi_attention(child.obj->handle, AFPATTN_MESG | AFPATTN_TIME(5));
+ }
+ dsi->msg_request = 0;
+ readmessage(child.obj);
+ }
+ if (dsi->down_request) {
+ dsi->down_request = 0;
+ dsi_attention(child.obj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
+ AFPATTN_MESG | AFPATTN_TIME(5));
+ }
}
-#endif
/* -------------------------------------------
afp over dsi. this never returns.
u_int32_t err, cmd;
u_int8_t function;
struct sigaction action;
- char *afpcmpstr;
+ const char *afpcmpstr;
obj->exit = afp_dsi_die;
obj->reply = (int (*)()) dsi_cmdreply;
sigaddset(&action.sa_mask, SIGUSR2);
#endif
action.sa_flags = SA_RESTART;
- if ( sigaction( SIGHUP, &action, 0 ) < 0 ) {
+ if ( sigaction( SIGHUP, &action, NULL ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
}
sigaddset(&action.sa_mask, SIGUSR2);
#endif
action.sa_flags = SA_RESTART;
- if ( sigaction( SIGTERM, &action, 0 ) < 0 ) {
+ if ( sigaction( SIGTERM, &action, NULL ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
}
sigaddset(&action.sa_mask, SIGUSR1);
sigaddset(&action.sa_mask, SIGHUP);
action.sa_flags = SA_RESTART;
- if ( sigaction( SIGUSR2, &action, 0) < 0 ) {
+ if ( sigaction( SIGUSR2, &action, NULL) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
}
sigaddset(&action.sa_mask, SIGUSR2);
#endif
action.sa_flags = SA_RESTART;
- if ( sigaction( SIGUSR1, &action, 0) < 0 ) {
+ if ( sigaction( SIGUSR1, &action, NULL) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
}
}
#endif /* DEBUGGING */
-#ifdef DEBUG1
- fault_setup((void (*)(void *))afp_dsi_die);
-#endif
-
/* get stuck here until the end */
while ((cmd = dsi_receive(dsi))) {
child.tickle = 0;
/* timer is not every 30 seconds anymore, so we don't get killed on the client side. */
if ((child.flags & CHILD_DIE))
dsi_tickle(dsi);
+ pending_request(dsi);
continue;
- } else if (!(child.flags & CHILD_DIE)) { /* reset tickle timer */
-#ifndef DEBUGGING
- setitimer(ITIMER_REAL, &dsi->timer, NULL);
-#endif
- }
+ }
+
+ child.flags |= CHILD_DATA;
switch(cmd) {
case DSIFUNC_CLOSE:
afp_dsi_close(obj);
LOG(log_info, logtype_afpd, "done");
-#ifdef DEBUG1
- if (obj->options.flags & OPTION_DEBUG )
- printf("done\n");
-#endif
return;
break;
#endif /* AFS */
function = (u_char) dsi->commands[0];
-#ifdef DEBUG1
- if (obj->options.flags & OPTION_DEBUG ) {
- printf("command: %d (%s)\n", function, AfpNum2name(function));
- bprint((char *) dsi->commands, dsi->cmdlen);
- }
-#endif
/* send off an afp command. in a couple cases, we take advantage
* of the fact that we're a stream-based protocol. */
LOG(log_debug, logtype_afpd, "=> Start AFP command: %s", afpcmpstr);
err = (*afp_switch[function])(obj,
- dsi->commands, dsi->cmdlen,
- dsi->data, &dsi->datalen);
+ (char *)&dsi->commands, dsi->cmdlen,
+ (char *)&dsi->data, &dsi->datalen);
LOG(log_debug, logtype_afpd, "=> Finished AFP command: %s", afpcmpstr);
#ifdef FORCE_UIDGID
break;
}
-#ifdef DEBUG1
- if (obj->options.flags & OPTION_DEBUG ) {
- printf( "reply: %d, %d\n", err, dsi->clientID);
- bprint((char *) dsi->data, dsi->datalen);
- }
-#endif
if (!dsi_cmdreply(dsi, err)) {
LOG(log_error, logtype_afpd, "dsi_cmdreply(%d): %s", dsi->socket, strerror(errno) );
afp_dsi_die(EXITERR_CLNT);
case DSIFUNC_WRITE: /* FPWrite and FPAddIcon */
function = (u_char) dsi->commands[0];
-#ifdef DEBUG1
- if ( obj->options.flags & OPTION_DEBUG ) {
- printf("(write) command: %d, %d\n", function, dsi->cmdlen);
- bprint((char *) dsi->commands, dsi->cmdlen);
- }
-#endif
if ( afp_switch[ function ] != NULL ) {
dsi->datalen = DSI_DATASIZ;
child.flags |= CHILD_RUNNING;
- err = (*afp_switch[function])(obj, dsi->commands, dsi->cmdlen,
- dsi->data, &dsi->datalen);
+ err = (*afp_switch[function])(obj,
+ (char *)&dsi->commands, dsi->cmdlen,
+ (char *)&dsi->data, &dsi->datalen);
child.flags &= ~CHILD_RUNNING;
#ifdef FORCE_UIDGID
/* bring everything back to old euid, egid */
err = AFPERR_NOOP;
}
-#ifdef DEBUG1
- if (obj->options.flags & OPTION_DEBUG ) {
- printf( "(write) reply code: %d, %d\n", err, dsi->clientID);
- bprint((char *) dsi->data, dsi->datalen);
- }
-#endif
if (!dsi_wrtreply(dsi, err)) {
LOG(log_error, logtype_afpd, "dsi_wrtreply: %s", strerror(errno) );
afp_dsi_die(EXITERR_CLNT);
break;
case DSIFUNC_ATTN: /* attention replies */
- continue;
break;
/* error. this usually implies a mismatch of some kind
dsi_writeflush(dsi);
break;
}
-#ifdef DEBUG1
- if ( obj->options.flags & OPTION_DEBUG ) {
-#ifdef notdef
- pdesc( stdout );
-#endif /* notdef */
- of_pforkdesc( stdout );
- fflush( stdout );
- }
-#endif
+ pending_request(dsi);
}
/* error */