Ejemplo n.º 1
0
static int
doattach(register Cs_t* state, const char* path, int op, int mode, char* user, char* opath, char* tmp, char* serv, char*b)
{
	register int	n;
	int		fd;
	char*		s;

#if CS_LIB_STREAM || CS_LIB_V10

	int		fds[2];
	struct stat	st;

	if (op & CS_OPEN_CREATE)
	{
		n = errno;
		if (chmod(path, mode))
		{
			remove(path);
			if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0)
			{
				messagef((state->id, NiL, -1, "open: %s: %s: creat %o error", state->path, path, mode));
				return -1;
			}
			close(fd);
			chmod(path, mode);
		}
		errno = n;
		if (pipe(fds))
		{
			messagef((state->id, NiL, -1, "open: %s: pipe error", state->path, path));
			return -1;
		}

#if CS_LIB_V10

		if ((n = ioctl(fds[1], FIOPUSHLD, &conn_ld)) || fmount(3, fds[1], path, 0))

#else

		if ((n = ioctl(fds[1], I_PUSH, "connld")) || fattach(fds[1], path))

#endif

		{
			messagef((state->id, NiL, -1, "open: %s: %s: %s error", state->path, path, n ? "connld" : "fattach"));
			close(fds[0]);
			close(fds[1]);
			errno = ENXIO;
			return -1;
		}
		close(fds[1]);
		fd = fds[0];
	}
	else
		for (;;)
		{
			if ((fd = open(path, O_RDWR)) >= 0)
			{
				if (!fstat(fd, &st) && !S_ISREG(st.st_mode))
					break;
				close(fd);
				remove(path);
			}
			else if ((op & CS_OPEN_TEST) || errno == EACCES)
			{
				messagef((state->id, NiL, -1, "open: %s: %s: open error", state->path, path));
				return -1;
			}
			if (initiate(state, user, opath, tmp, serv))
			{
				messagef((state->id, NiL, -1, "open: %s: %s: service initiate error", state->path, path));
				return -1;
			}
			op = CS_OPEN_TEST;
		}

#else

#if CS_LIB_SOCKET_UN

	int			pid;
	int			namlen;
	char			c;
	struct sockaddr_un	nam;

	messagef((state->id, NiL, -8, "%s:%d state.path=`%s' state.mount=`%s' path=`%s' opath=`%s' user=`%s' serv=`%s'", __FILE__, __LINE__, state->path, state->mount, path, opath, user, serv));
	nam.sun_family = AF_UNIX;
	strcpy(nam.sun_path, path);
	namlen = sizeof(nam.sun_family) + strlen(path) + 1;
	for (n = 0;; n++)
	{
		if (n >= 10)
		{
			errno = ENXIO;
		badcon:
			close(fd);
			return -1;
		}
		if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
		{
			messagef((state->id, NiL, -1, "open: %s: %s: AF_UNIX socket error", state->path, path));
			return -1;
		}
		if (!connect(fd, (struct sockaddr*)&nam, namlen))
		{
			if (op & CS_OPEN_CREATE)
			{
				errno = EEXIST;
				goto badcon;
			}
#if CS_LIB_SOCKET_RIGHTS
			if (read(fd, &c, 1) == 1 && !cssend(state, fd, NiL, 0))
				break;
#else
			break;
#endif
		}
		else
		{
			messagef((state->id, NiL, -1, "open: %s: %s: connect error", state->path, path));
			if (errno == EACCES)
				goto badcon;
			else if (errno == EADDRNOTAVAIL || errno == ECONNREFUSED)
			{
				c = 0;
				for (;;)
				{
					*b = CS_MNT_PROCESS;
					pid = pathgetlink(path, state->temp, sizeof(state->temp));
					*b = CS_MNT_STREAM;
					if (pid > 0 || ++c >= 5)
						break;
					sleep(1);
				}
				if (pid > 0 && (s = strrchr(state->temp, '/')) && (pid = strtol(s + 1, NiL, 0)) > 0)
				{
					if (!kill(pid, 0) || errno != ESRCH)
					{
						if (op & CS_OPEN_CREATE)
						{
							errno = EEXIST;
							goto badcon;
						}
						close(fd);
						if (n)
							sleep(1);
						continue;
					}
					*b = CS_MNT_PROCESS;
					remove(path);
					*b = CS_MNT_STREAM;
				}
			}
		}
		close(fd);
		errno = ENOENT;
		if (op & CS_OPEN_CREATE)
		{
			if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
			{
				messagef((state->id, NiL, -1, "open: %s: %s: AF_UNIX socket error", state->path, path));
				return -1;
			}
			if (!bind(fd, (struct sockaddr*)&nam, namlen))
			{
				chmod(path, mode);
				if (listen(fd, 32))
				{
					messagef((state->id, NiL, -1, "open: %s: %s: listen error", state->path, path));
					n = errno;
					remove(path);
					errno = n;
					goto badcon;
				}
				break;
			}
			else
				messagef((state->id, NiL, -1, "open: %s: %s: bind error", state->path, path));
			if (errno != EADDRINUSE || n && remove(path) && errno != ENOENT)
				goto badcon;
			close(fd);
		}
		else if (op & CS_OPEN_TEST)
			return -1;
		else if (!n && initiate(state, user, opath, tmp, serv))
		{
			messagef((state->id, NiL, -1, "open: %s: %s: service initiate error", state->path, path));
			return -1;
		}
		else
			sleep(2);
	}

#else

	errno = (op & CS_OPEN_CREATE) ? ENXIO : ENOENT;
	messagef((state->id, NiL, -1, "open: %s: %s: not supported", state->path, path));
	fd = -1;

#endif

#endif

#if CS_LIB_SOCKET_UN || CS_LIB_STREAM || CS_LIB_V10

	touch(path, (time_t)0, (time_t)0, 0);
	strcpy(state->path, path);

#endif

	return fd;
}
Ejemplo n.º 2
0
int
cslocal(register Cs_t* state, const char* path)
{
	register char*	s;
	register char*	p;
	register char*	t;
	register char*	v;
	struct stat	st;
	char		cmd[PATH_MAX / 8];
	char		exe[PATH_MAX + 1];
	char		tmp[PATH_MAX + 1];
#if CS_LIB_STREAM || CS_LIB_V10 || CS_LIB_SOCKET_UN
	int		fd;
	int		n;
#endif

	messagef((state->id, NiL, -8, "local(%s) call", path));

	/*
	 * validate the path
	 */

	p = (char*)path;
	if (strncmp(p, DEVLOCAL, sizeof(DEVLOCAL) - 1))
	{
		messagef((state->id, NiL, -1, "local: %s: %s* expected", path, DEVLOCAL));
		goto sorry;
	}
	p += sizeof(DEVLOCAL) - 1;
	for (t = p; *t && *t != '/'; t++);
	if (!streq(t + 1, "user"))
	{
		messagef((state->id, NiL, -1, "local: %s: %s*/user expected", path, DEVLOCAL));
		goto sorry;
	}

	/*
	 * locate the service
	 */

	s = cmd;
	for (v = p; p <= t; *s++ = *p++);
	t = s - 1;
	for (p = v; p <= t; *s++ = *p++);
	for (p = CS_SVC_SUFFIX; *s++ = *p++;);
	p = pathbin();
	for (;;)
	{
		p = pathcat(p, ':', "../lib/cs/fdp", cmd, exe, PATH_MAX + 1);
		if (!eaccess(exe, X_OK) && !stat(exe, &st)) break;
		if (!p)
		{
			messagef((state->id, NiL, -1, "local: %s: %s: cannot locate service on ../lib/cs/fdp", path, cmd));
			goto sorry;
		}
	}
	*t = 0;
	sfsprintf(tmp, sizeof(tmp), "%s/fdp/%s/%s/%d-%d-/%c%s", csvar(state, CS_VAR_LOCAL, 0), csname(state, 0), cmd, st.st_uid, geteuid(), CS_MNT_STREAM, CS_MNT_TAIL);

#if CS_LIB_STREAM || CS_LIB_V10

	for (n = 0; (fd = open(tmp, O_RDWR)) < 0; n++)
		if (n || errno == EACCES)
		{
			messagef((state->id, NiL, -1, "local: %s: %s: cannot open service", path, tmp));
			return -1;
		}
		else if (initiate(state, path, exe) < 0)
		{
			messagef((state->id, NiL, -1, "local: %s: %s: cannot initiate service %s", path, tmp, exe));
			return -1;
		}
	messagef((state->id, NiL, -8, "local(%s) fd=%d server=%s stream=%s", path, fd, exe, tmp));
	return fd;

#else

#if CS_LIB_SOCKET_UN

	{
		int			namlen;
		struct sockaddr_un	nam;

		nam.sun_family = AF_UNIX;
		strcpy(nam.sun_path, tmp);
		namlen = sizeof(nam.sun_family) + strlen(tmp);
		n = 0;
		fd = -1;
		for (;;)
		{
			if (fd < 0 && (fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
			{
				messagef((state->id, NiL, -1, "local: %s: AF_UNIX socket error", path));
				return -1;
			}
			if (!connect(fd, (struct sockaddr*)&nam, namlen))
			{
#if CS_LIB_SOCKET_RIGHTS
				if (read(fd, cmd, 1) != 1)
					messagef((state->id, NiL, -1, "local: %s: connect ack read error", path));
				else if (cssend(state, fd, NiL, 0))
					messagef((state->id, NiL, -1, "local: %s: connect authentication send error", path));
				else
#endif
				return fd;
#if CS_LIB_SOCKET_RIGHTS
				close(fd);
				fd = -1;
#endif
			}
			else messagef((state->id, NiL, -1, "local: %s: connect error", path));
			if (errno != EACCES) errno = ENOENT;
			if (n || errno == EACCES || initiate(state, path, exe) < 0)
			{
				if (fd >= 0) close(fd);
				return -1;
			}
			n = 1;
			messagef((state->id, NiL, -1, "local: %s: connect retry", path));
		}
	}

#endif

#endif

 sorry:
	errno = ENOENT;
	return -1;
}