close(p->socket);
free(p);
}
+
if (dsi) {
dsi->next = NULL;
obj->dsi = dsi;
} else {
afp_options_free(&obj->options);
}
-
}
/*!
status_init(obj, dsi);
*next = dsi;
next = &dsi->next;
+ dsi->AFPobj = obj;
LOG(log_note, logtype_afpd, "Netatalk AFP/TCP listening on %s:%d",
getip_string((struct sockaddr *)&dsi->server),
break;
}
- if (obj->dsi == NULL)
- EC_FAIL;
-
#ifdef HAVE_LDAP
/* Parse afp.conf */
acl_ldap_readconfig(obj->iniconfig);
fce_set_events(r);
}
-
EC_CLEANUP:
if (q)
free(q);
struct sigaction action;
AFPobj = obj;
- dsi->AFPobj = obj;
obj->exit = afp_dsi_die;
obj->reply = (int (*)()) dsi_cmdreply;
obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
(void)setlimits();
afp_child_t *child;
- int fd[2]; /* we only use one, but server_child_add expects [2] */
+ int recon_ipc_fd;
pid_t pid;
int saveerrno;
&polldata,
&fdset_used,
&fdset_size,
- child->ipc_fds[0],
+ child->ipc_fd,
IPC_FD,
child);
}
child = (afp_child_t *)polldata[i].data;
LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid);
- if (ipc_server_read(server_children, child->ipc_fds[0]) != 0) {
- fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0]);
- close(child->ipc_fds[0]);
- child->ipc_fds[0] = -1;
+ if (ipc_server_read(server_children, child->ipc_fd) != 0) {
+ fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd);
+ close(child->ipc_fd);
+ child->ipc_fd = -1;
if ((obj.options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
server_child_remove(server_children, CHILD_DSIFORK, child->pid);
case DISASOCIATED_IPC_FD:
LOG(log_debug, logtype_afpd, "main: IPC reconnect request");
- if ((fd[0] = accept(disasociated_ipc_fd, NULL, NULL)) == -1) {
+ if ((recon_ipc_fd = accept(disasociated_ipc_fd, NULL, NULL)) == -1) {
LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno));
break;
}
- if (readt(fd[0], &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
+ if (readt(recon_ipc_fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno));
- close(fd[0]);
+ close(recon_ipc_fd);
break;
}
LOG(log_note, logtype_afpd, "main: IPC reconnect from pid [%u]", pid);
- if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, fd)) == NULL) {
+
+ if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, recon_ipc_fd)) == NULL) {
LOG(log_error, logtype_afpd, "main: server_child_add");
- close(fd[0]);
+ close(recon_ipc_fd);
break;
}
child->disasociated = 1;
&polldata,
&fdset_used,
&fdset_size,
- fd[0],
+ recon_ipc_fd,
IPC_FD,
child);
break;
{
afp_child_t *child = NULL;
- if (!(child = dsi_getsession(dsi,
- server_children,
- obj->options.tickleval))) {
+ if (dsi_getsession(dsi, server_children, obj->options.tickleval, &child) != 0) {
LOG(log_error, logtype_afpd, "dsi_start: session error: %s", strerror(errno));
return NULL;
}
/* we've forked. */
- if (child->ipc_fds[0] == -1) {
+ if (child == NULL) {
configfree(obj, dsi);
- obj->ipc_fd = child->ipc_fds[1];
- free(child);
afp_over_dsi(obj); /* start a session */
exit (0);
}
extern int dsi_tcp_init(DSI *dsi, const char *hostname, const char *address, const char *port);
/* in dsi_getsess.c */
-extern afp_child_t *dsi_getsession (DSI *, server_child *, const int);
+extern int dsi_getsession (DSI *, server_child *, const int, afp_child_t **);
extern void dsi_kill (int);
uint32_t time; /* client boot time (from the mac client) */
uint32_t idlen; /* clientid len (from the Mac client) */
char *clientid; /* clientid (from the Mac client) */
- int ipc_fds[2]; /* socketpair for IPC bw */
+ int ipc_fd; /* socket for IPC bw afpd parent and childs */
struct server_child_data **prevp, *next;
} afp_child_t;
/* server_child.c */
extern server_child *server_child_alloc (const int, const int);
-extern afp_child_t *server_child_add (server_child *, int, pid_t, uint ipc_fds[2]);
+extern afp_child_t *server_child_add (server_child *, int, pid_t, int ipc_fd);
extern int server_child_remove (server_child *, const int, const pid_t);
extern void server_child_free (server_child *);
#include <atalk/dsi.h>
#include <atalk/server_child.h>
-/* hand off the command. return child connection to the main program */
-afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval)
+/*!
+ * Start a DSI session, fork an afpd process
+ *
+ * @param childp (w) after fork: parent return pointer to child, child returns NULL
+ * @returns 0 on sucess, any other value denotes failure
+ */
+int dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval, afp_child_t **childp)
{
pid_t pid;
unsigned int ipc_fds[2];
if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
- exit( EXITERR_CLNT );
+ return -1;
}
if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) {
LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno));
- exit(EXITERR_CLNT);
+ return -1;
}
switch (pid = dsi->proto_open(dsi)) { /* in libatalk/dsi/dsi_tcp.c */
case -1:
/* if we fail, just return. it might work later */
LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
- return NULL;
+ return -1;
case 0: /* child. mostly handled below. */
break;
default: /* parent */
- /* using SIGQUIT is hokey, but the child might not have
+ /* using SIGKILL is hokey, but the child might not have
* re-established its signal handler for SIGTERM yet. */
- if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds)) == NULL) {
+ close(ipc_fds[1]);
+ if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds[0])) == NULL) {
LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
+ close(ipc_fds[0]);
dsi->header.dsi_flags = DSIFL_REPLY;
dsi->header.dsi_code = DSIERR_SERVBUSY;
dsi_send(dsi);
dsi->header.dsi_code = DSIERR_OK;
- kill(pid, SIGQUIT);
+ kill(pid, SIGKILL);
}
- close(ipc_fds[1]);
dsi->proto_close(dsi);
- return child;
+ *childp = child;
+ return 0;
}
/* child: check number of open connections. this is one off the
}
/* get rid of some stuff */
+ dsi->AFPobj->ipc_fd = ipc_fds[1];
close(ipc_fds[0]);
close(dsi->serversock);
dsi->serversock = -1;
dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
signal(SIGPIPE, SIG_IGN); /* we catch these ourselves */
dsi_opensession(dsi);
- if ((child = calloc(1, sizeof(afp_child_t))) == NULL)
- exit(EXITERR_SYS);
-
- child->ipc_fds[0] = -1;
- child->ipc_fds[1] = ipc_fds[1];
- close(ipc_fds[0]);
- return child;
+ *childp = NULL;
+ return 0;
default: /* just close */
LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command);
* add a child
* @return pointer to struct server_child_data on success, NULL on error
*/
-afp_child_t *server_child_add(server_child *children, int forkid, pid_t pid, uint ipc_fds[2])
+afp_child_t *server_child_add(server_child *children, int forkid, pid_t pid, int ipc_fd)
{
server_child_fork *fork;
afp_child_t *child = NULL;
child->pid = pid;
child->valid = 0;
child->killed = 0;
- child->ipc_fds[0] = ipc_fds[0];
- child->ipc_fds[1] = ipc_fds[1];
+ child->ipc_fd = ipc_fd;
hash_child(fork->table, child);
children->count++;
}
/* In main:child_handler() we need the fd in order to remove it from the pollfd set */
- fd = child->ipc_fds[0];
- if (child->ipc_fds[0] != -1) {
- close(child->ipc_fds[0]);
- child->ipc_fds[0] = -1;
- }
- if (child->ipc_fds[1] != -1) {
- close(child->ipc_fds[1]);
- child->ipc_fds[1] = -1;
- }
+ fd = child->ipc_fd;
+ if (fd != -1)
+ close(fd);
free(child);
children->count--;
child = fork->table[j]; /* start at the beginning */
while (child) {
tmp = child->next;
-
- if (child->ipc_fds[0] != -1)
- close(child->ipc_fds[0]);
+ close(child->ipc_fd);
if (child->clientid) {
free(child->clientid);
}
LOG(log_note, logtype_default, "Reconnect: transfering session to child[%u]", pid);
- if (writet(child->ipc_fds[0], &DSI_requestID, 2, 0, 2) != 2) {
+ if (writet(child->ipc_fd, &DSI_requestID, 2, 0, 2) != 2) {
LOG(log_error, logtype_default, "Reconnect: error sending DSI id to child[%u]", pid);
EC_STATUS(-1);
goto EC_CLEANUP;
}
- EC_ZERO_LOG(send_fd(child->ipc_fds[0], afp_socket));
+ EC_ZERO_LOG(send_fd(child->ipc_fd, afp_socket));
EC_ZERO_LOG(kill(pid, SIGURG));
EC_STATUS(1);