+ PARA_ERROR_LOG("%s init: %s\n", afs_tables[i].name,
+ para_strerror(-ret));
+ break;
+ }
+ if (ret >= 0)
+ return ret;
+ while (i)
+ afs_tables[--i].close();
+ return ret;
+}
+
+static int afs_signal_post_select(struct sched *s, __a_unused void *context)
+{
+ int signum, ret;
+
+ if (getppid() == 1) {
+ PARA_EMERG_LOG("para_server died\n");
+ goto shutdown;
+ }
+ signum = para_next_signal(&s->rfds);
+ if (signum == 0)
+ return 0;
+ if (signum == SIGHUP) {
+ close_afs_tables();
+ parse_config_or_die(1);
+ ret = open_afs_tables();
+ if (ret < 0)
+ return ret;
+ init_admissible_files(current_mop);
+ return 0;
+ }
+ PARA_EMERG_LOG("terminating on signal %d\n", signum);
+shutdown:
+ task_notify_all(s, E_AFS_SIGNAL);
+ return -E_AFS_SIGNAL;
+}
+
+static void register_signal_task(struct sched *s)
+{
+ para_sigaction(SIGPIPE, SIG_IGN);
+ signal_task = signal_init_or_die();
+ para_install_sighandler(SIGINT);
+ para_install_sighandler(SIGTERM);
+ para_install_sighandler(SIGHUP);
+
+ signal_task->task = task_register(&(struct task_info) {
+ .name = "signal",
+ .pre_select = signal_pre_select,
+ .post_select = afs_signal_post_select,
+ .context = signal_task,
+
+ }, s);
+}
+
+static struct list_head afs_client_list;
+
+/** Describes one connected afs client. */
+struct afs_client {
+ /** Position in the afs client list. */
+ struct list_head node;
+ /** The socket file descriptor for this client. */
+ int fd;
+ /** The time the client connected. */
+ struct timeval connect_time;
+};
+
+static void command_pre_select(struct sched *s, void *context)
+{
+ struct command_task *ct = context;
+ struct afs_client *client;
+
+ para_fd_set(server_socket, &s->rfds, &s->max_fileno);
+ para_fd_set(ct->fd, &s->rfds, &s->max_fileno);
+ list_for_each_entry(client, &afs_client_list, node)
+ para_fd_set(client->fd, &s->rfds, &s->max_fileno);
+}
+
+/**
+ * Send data as shared memory to a file descriptor.
+ *
+ * \param fd File descriptor to send the shmid to.
+ * \param band The band designator for this data.
+ * \param buf The buffer holding the data to be sent.
+ * \param size The size of \a buf.
+ *
+ * This function creates a shared memory area large enough to hold
+ * the content given by \a buf and \a size and sends the identifier
+ * of this area to the file descriptor \a fd.
+ *
+ * It is called by the AFS max_size handler as well as directly by the AFS
+ * command callbacks to send command output to the command handlers.
+ *
+ * \return Zero if \a buf is \p NULL or \a size is zero. Negative on errors,
+ * and positive on success.
+ */
+int pass_buffer_as_shm(int fd, uint8_t band, const char *buf, size_t size)
+{
+ int ret, shmid;
+ void *shm;
+ struct callback_result *cr;
+
+ if (size == 0)
+ assert(band != SBD_OUTPUT);
+ ret = shm_new(size + sizeof(*cr));
+ if (ret < 0)
+ return ret;
+ shmid = ret;
+ ret = shm_attach(shmid, ATTACH_RW, &shm);
+ if (ret < 0)
+ goto err;
+ cr = shm;
+ cr->result_size = size;
+ cr->band = band;
+ if (size > 0)
+ memcpy(shm + sizeof(*cr), buf, size);
+ ret = shm_detach(shm);
+ if (ret < 0)
+ goto err;
+ ret = write_all(fd, (char *)&shmid, sizeof(int));
+ if (ret >= 0)
+ return ret;
+err:
+ if (shm_destroy(shmid) < 0)
+ PARA_ERROR_LOG("destroy result failed\n");
+ return ret;
+}
+
+static int call_callback(int fd, int query_shmid)
+{
+ void *query_shm;
+ struct callback_query *cq;
+ int ret, ret2;
+ struct afs_callback_arg aca = {.fd = fd};