}
}
+__attribute__((format (printf, 1, 2)))
static void logerror(const char *err, ...)
{
va_list params;
va_end(params);
}
+__attribute__((format (printf, 1, 2)))
static void loginfo(const char *err, ...)
{
va_list params;
exit(1);
}
-static int avoid_alias(char *p)
-{
- int sl, ndot;
-
- /*
- * This resurrects the belts and suspenders paranoia check by HPA
- * done in <435560F7.4080006@zytor.com> thread, now enter_repo()
- * does not do getcwd() based path canonicalizations.
- *
- * sl becomes true immediately after seeing '/' and continues to
- * be true as long as dots continue after that without intervening
- * non-dot character.
- */
- if (!p || (*p != '/' && *p != '~'))
- return -1;
- sl = 1; ndot = 0;
- p++;
-
- while (1) {
- char ch = *p++;
- if (sl) {
- if (ch == '.')
- ndot++;
- else if (ch == '/') {
- if (ndot < 3)
- /* reject //, /./ and /../ */
- return -1;
- ndot = 0;
- }
- else if (ch == 0) {
- if (0 < ndot && ndot < 3)
- /* reject /.$ and /..$ */
- return -1;
- return 0;
- }
- else
- sl = ndot = 0;
- }
- else if (ch == 0)
- return 0;
- else if (ch == '/') {
- sl = 1;
- ndot = 0;
- }
- }
-}
-
static char *path_ok(char *directory)
{
static char rpath[PATH_MAX];
dir = directory;
- if (avoid_alias(dir)) {
+ if (daemon_avoid_alias(dir)) {
logerror("'%s': aliased", dir);
return NULL;
}
{ "IP", ip_address },
{ "P", tcp_port },
{ "D", directory },
- { "%", "%" },
{ NULL }
};
return -1;
}
+static int addrcmp(const struct sockaddr_storage *s1,
+ const struct sockaddr_storage *s2)
+{
+ if (s1->ss_family != s2->ss_family)
+ return s1->ss_family - s2->ss_family;
+ if (s1->ss_family == AF_INET)
+ return memcmp(&((struct sockaddr_in *)s1)->sin_addr,
+ &((struct sockaddr_in *)s2)->sin_addr,
+ sizeof(struct in_addr));
+#ifndef NO_IPV6
+ if (s1->ss_family == AF_INET6)
+ return memcmp(&((struct sockaddr_in6 *)s1)->sin6_addr,
+ &((struct sockaddr_in6 *)s2)->sin6_addr,
+ sizeof(struct in6_addr));
+#endif
+ return 0;
+}
+
static int max_connections = 32;
static unsigned int live_children;
{
struct child *newborn, **cradle;
- /*
- * This must be xcalloc() -- we'll compare the whole sockaddr_storage
- * but individual address may be shorter.
- */
newborn = xcalloc(1, sizeof(*newborn));
live_children++;
newborn->pid = pid;
memcpy(&newborn->address, addr, addrlen);
for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
- if (!memcmp(&(*cradle)->address, &newborn->address,
- sizeof(newborn->address)))
+ if (!addrcmp(&(*cradle)->address, &newborn->address))
break;
newborn->next = *cradle;
*cradle = newborn;
return;
for (; (next = blanket->next); blanket = next)
- if (!memcmp(&blanket->address, &next->address,
- sizeof(next->address))) {
+ if (!addrcmp(&blanket->address, &next->address)) {
kill(blanket->pid, SIGTERM);
break;
}
case ECONNABORTED:
continue;
default:
- die("accept returned %s", strerror(errno));
+ die_errno("accept returned");
}
}
handle(incoming, (struct sockaddr *)&ss, sslen);
while (fd != -1 && fd < 2)
fd = dup(fd);
if (fd == -1)
- die("open /dev/null or dup failed: %s", strerror(errno));
+ die_errno("open /dev/null or dup failed");
if (fd > 2)
close(fd);
}
case 0:
break;
case -1:
- die("fork failed: %s", strerror(errno));
+ die_errno("fork failed");
default:
exit(0);
}
if (setsid() == -1)
- die("setsid failed: %s", strerror(errno));
+ die_errno("setsid failed");
close(0);
close(1);
close(2);
{
FILE *f = fopen(path, "w");
if (!f)
- die("cannot open pid file %s: %s", path, strerror(errno));
+ die_errno("cannot open pid file '%s'", path);
if (fprintf(f, "%"PRIuMAX"\n", (uintmax_t) getpid()) < 0 || fclose(f) != 0)
- die("failed to write pid file %s: %s", path, strerror(errno));
+ die_errno("failed to write pid file '%s'", path);
}
static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t gid)
socklen_t slen = sizeof(ss);
if (!freopen("/dev/null", "w", stderr))
- die("failed to redirect stderr to /dev/null: %s",
- strerror(errno));
+ die_errno("failed to redirect stderr to /dev/null");
if (getpeername(0, peer, &slen))
peer = NULL;