/*
- * $Id: cnid_metad.c,v 1.1.4.9 2004-01-04 21:36:20 didg Exp $
+ * $Id: cnid_metad.c,v 1.1.4.15.2.4 2009-03-06 14:53:04 didg Exp $
*
* Copyright (C) Joerg Lenneis 2003
- * All Rights Reserved. See COPYRIGHT.
+ * All Rights Reserved. See COPYING.
*
*/
#include <sys/socket.h>
#include <stdio.h>
#include <time.h>
-
+#include <sys/ioctl.h>
+
#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif /* ! WEXITSTATUS */
static int srvfd;
static int rqstfd;
+volatile sig_atomic_t alarmed = 0;
-#define MAXSRV 128
+#define MAXSRV 512
#define MAXSPAWN 3 /* Max times respawned in.. */
time_t tm; /* When respawned last */
int count; /* Times respawned in the last TESTTIME secondes */
int toofast;
- int sv[2];
+ int control_fd; /* file descriptor to child cnid_dbd process */
};
static struct server srv[MAXSRV +1];
-static struct server *test_usockfn(char *dir, char *fn)
+static struct server *test_usockfn(char *dir, char *fn _U_)
{
int i;
for (i = 1; i <= MAXSRV; i++) {
struct msghdr msgh;
struct iovec iov[1];
struct cmsghdr *cmsgp = NULL;
- char buf[CMSG_SPACE(sizeof fd)];
+ char *buf;
+ size_t size;
int er=0;
+ size = CMSG_SPACE(sizeof fd);
+ buf = malloc(size);
+ if (!buf) {
+ LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
+ return -1;
+ }
+
memset(&msgh,0,sizeof (msgh));
- memset(buf,0,sizeof (buf));
+ memset(buf,0, size);
msgh.msg_name = NULL;
msgh.msg_namelen = 0;
iov[0].iov_len = sizeof(er);
msgh.msg_control = buf;
- msgh.msg_controllen = sizeof(buf);
+ msgh.msg_controllen = size;
cmsgp = CMSG_FIRSTHDR(&msgh);
cmsgp->cmsg_level = SOL_SOCKET;
} while ( ret == -1 && errno == EINTR );
if (ret == -1) {
LOG(log_error, logtype_cnid, "error in sendmsg: %s", strerror(errno));
+ free(buf);
return -1;
}
+ free(buf);
return 0;
}
{
pid_t pid;
struct server *up;
+ int sv[2];
int i;
time_t t;
char buf1[8];
up = test_usockfn(dbdir, usockfn);
if (up && up->pid) {
/* we already have a process, send our fd */
- if (send_cred(up->sv[0], rqstfd) < 0) {
+ if (send_cred(up->control_fd, rqstfd) < 0) {
/* FIXME */
return -1;
}
/* create socketpair for comm between parent and child
* FIXME Do we really need a permanent pipe between them ?
*/
- if (socketpair(PF_UNIX, SOCK_STREAM, 0, up->sv) < 0) {
- LOG(log_error, logtype_cnid, "error in fork: %s", strerror(errno));
+ if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) {
+ LOG(log_error, logtype_cnid, "error in socketpair: %s", strerror(errno));
return -1;
}
*/
close(srvfd);
- close(up->sv[0]);
+ close(sv[0]);
for (i = 1; i <= MAXSRV; i++) {
if (srv[i].pid && up != &srv[i]) {
- close(srv[i].sv[0]);
- close(srv[i].sv[1]);
+ close(srv[i].control_fd);
}
}
- sprintf(buf1, "%i", up->sv[1]);
+ sprintf(buf1, "%i", sv[1]);
sprintf(buf2, "%i", rqstfd);
if (up->count == MAXSPAWN) {
* Parent.
*/
up->pid = pid;
- /* FIXME Any reason we do not close up->sv[1] here? Do we need both
- descriptors in the srv table? */
+ close(sv[1]);
+ up->control_fd = sv[0];
return 0;
}
}
+/* ------------------ */
+void catch_alarm(int sig) {
+ alarmed = 1;
+}
+
/* ------------------ */
int main(int argc, char *argv[])
{
char dbdir[MAXPATHLEN + 1];
- int len;
+ int len, actual_len;
pid_t pid;
int status;
char *dbdpn = _PATH_CNID_DBD;
char *host = DEFAULTHOST;
- int port = DEFAULTPORT;
+ u_int16_t port = DEFAULTPORT;
struct db_param *dbp;
int i;
int cc;
int err = 0;
int debug = 0;
int ret;
+
+ set_processname("cnid_metad");
while (( cc = getopt( argc, argv, "ds:p:h:u:g:")) != -1 ) {
switch (cc) {
}
signal(SIGPIPE, SIG_IGN);
+ signal(SIGALRM, catch_alarm);
while (1) {
rqstfd = usockfd_check(srvfd, 10000000);
#if 0
free(srv[i].name);
#endif
- close(srv[i].sv[0]);
- close(srv[i].sv[1]);
+ close(srv[i].control_fd);
break;
}
}
}
if (rqstfd <= 0)
continue;
+
/* TODO: Check out read errors, broken pipe etc. in libatalk. Is
SIGIPE ignored there? Answer: Ignored for dsi, but not for asp ... */
+ alarm(5); /* to prevent read from getting stuck */
ret = read(rqstfd, &len, sizeof(int));
+ alarm(0);
+ if (alarmed) {
+ alarmed = 0;
+ LOG(log_severe, logtype_cnid, "Read(1) bailed with alarm (timeout)");
+ goto loop_end;
+ }
+
if (!ret) {
/* already close */
goto loop_end;
LOG(log_error, logtype_cnid, "wrong len parameter: %d", len);
goto loop_end;
}
- if (read(rqstfd, dbdir, len) != len) {
+
+ alarm(5);
+ actual_len = read(rqstfd, dbdir, len);
+ alarm(0);
+ if (alarmed) {
+ alarmed = 0;
+ LOG(log_severe, logtype_cnid, "Read(2) bailed with alarm (timeout)");
+ goto loop_end;
+ }
+ if (actual_len != len) {
LOG(log_error, logtype_cnid, "error/short read (dir): %s", strerror(errno));
goto loop_end;
}