+
+#ifdef SERVERTEXT
+ /* Added for server message support */
+ action.sa_handler = afp_dsi_getmesg;
+ sigemptyset( &action.sa_mask );
+ sigaddset(&action.sa_mask, SIGALRM);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGUSR1);
+ sigaddset(&action.sa_mask, SIGHUP);
+ action.sa_flags = SA_RESTART;
+ if ( sigaction( SIGUSR2, &action, NULL) < 0 ) {
+ LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
+ afp_dsi_die(EXITERR_SYS);
+ }
+#endif /* SERVERTEXT */
+
+ /* SIGUSR1 - set down in 5 minutes */
+ action.sa_handler = afp_dsi_timedown;
+ sigemptyset( &action.sa_mask );
+ sigaddset(&action.sa_mask, SIGALRM);
+ sigaddset(&action.sa_mask, SIGHUP);
+ sigaddset(&action.sa_mask, SIGTERM);
+#ifdef SERVERTEXT
+ sigaddset(&action.sa_mask, SIGUSR2);
+#endif
+ action.sa_flags = SA_RESTART;
+ if ( sigaction( SIGUSR1, &action, NULL) < 0 ) {
+ LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
+ afp_dsi_die(EXITERR_SYS);
+ }
+
+#ifndef DEBUGGING
+ /* tickle handler */
+ action.sa_handler = alarm_handler;
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask, SIGHUP);
+ sigaddset(&action.sa_mask, SIGTERM);
+ sigaddset(&action.sa_mask, SIGUSR1);
+#ifdef SERVERTEXT
+ sigaddset(&action.sa_mask, SIGUSR2);
+#endif
+ action.sa_flags = SA_RESTART;
+ if ((sigaction(SIGALRM, &action, NULL) < 0) ||
+ (setitimer(ITIMER_REAL, &dsi->timer, NULL) < 0)) {
+ afp_dsi_die(EXITERR_SYS);
+ }
+#endif /* DEBUGGING */
+
+ /* get stuck here until the end */
+ while ((cmd = dsi_receive(dsi))) {
+ child.tickle = 0;
+ child.flags &= ~CHILD_SLEEPING;
+ dsi_sleep(dsi, 0); /* wake up */
+ if (reload_request) {
+ reload_request = 0;
+ load_volumes(child.obj);
+ }
+
+ if (cmd == DSIFUNC_TICKLE) {
+ /* 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;
+ }
+
+ child.flags |= CHILD_DATA;
+ switch(cmd) {
+ case DSIFUNC_CLOSE:
+ afp_dsi_close(obj);
+ LOG(log_info, logtype_afpd, "done");
+ return;
+ break;
+
+ case DSIFUNC_CMD:
+#ifdef AFS
+ if ( writtenfork ) {
+ if ( flushfork( writtenfork ) < 0 ) {
+ LOG(log_error, logtype_afpd, "main flushfork: %s", strerror(errno) );
+ }
+ writtenfork = NULL;
+ }
+#endif /* AFS */
+
+ function = (u_char) dsi->commands[0];
+
+ /* send off an afp command. in a couple cases, we take advantage
+ * of the fact that we're a stream-based protocol. */
+ if (afp_switch[function]) {
+ dsi->datalen = DSI_DATASIZ;
+ child.flags |= CHILD_RUNNING;
+
+ afpcmpstr = AfpNum2name(function);
+ LOG(log_debug, logtype_afpd, "=> Start AFP command: %s", afpcmpstr);
+
+ err = (*afp_switch[function])(obj,
+ (char *)&dsi->commands, dsi->cmdlen,
+ (char *)&dsi->data, &dsi->datalen);
+
+ LOG(log_debug, logtype_afpd, "=> Finished AFP command: %s", afpcmpstr);
+#ifdef FORCE_UIDGID
+ /* bring everything back to old euid, egid */
+ if (obj->force_uid)
+ restore_uidgid ( &obj->uidgid );
+#endif /* FORCE_UIDGID */
+ child.flags &= ~CHILD_RUNNING;
+ } else {
+ LOG(log_error, logtype_afpd, "bad function %X", function);
+ dsi->datalen = 0;
+ err = AFPERR_NOOP;
+ }
+
+ /* single shot toggle that gets set by dsi_readinit. */
+ if (dsi->noreply) {
+ dsi->noreply = 0;
+ break;
+ }
+
+ if (!dsi_cmdreply(dsi, err)) {
+ LOG(log_error, logtype_afpd, "dsi_cmdreply(%d): %s", dsi->socket, strerror(errno) );
+ afp_dsi_die(EXITERR_CLNT);
+ }
+ break;
+
+ case DSIFUNC_WRITE: /* FPWrite and FPAddIcon */
+ function = (u_char) dsi->commands[0];
+ if ( afp_switch[ function ] != NULL ) {
+ dsi->datalen = DSI_DATASIZ;
+ child.flags |= CHILD_RUNNING;
+ 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 */
+ if (obj->force_uid)
+ restore_uidgid ( &obj->uidgid );
+#endif /* FORCE_UIDGID */
+ } else {
+ LOG(log_error, logtype_afpd, "(write) bad function %x", function);
+ dsi->datalen = 0;
+ err = AFPERR_NOOP;
+ }
+
+ 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 */
+ break;
+
+ /* error. this usually implies a mismatch of some kind
+ * between server and client. if things are correct,
+ * we need to flush the rest of the packet if necessary. */
+ default:
+ LOG(log_info, logtype_afpd,"afp_dsi: spurious command %d", cmd);
+ dsi_writeinit(dsi, dsi->data, DSI_DATASIZ);
+ dsi_writeflush(dsi);
+ break;
+ }
+ pending_request(dsi);