/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1990-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
*
* /dev/<type>/<host>/<service>[/<qualifier>][/<perm>][/#option][/#/path]
*
* type: {fdp,tcp,udp}
* host: open={<hostname>}, create={share,local}
* qualifier: optional service qualifier
* perm: {user[=euid],group[=egid],other(default)}
*/
#include "cslib.h"
#include <error.h>
#include <proc.h>
#include <hashkey.h>
/*
* create the state->mount <type>/<host>/<service>/<perm> subdirs
* state->mount modified, possibly destroyed on error
*/
static int
mkmount(register Cs_t* state, int mode, int uid, int gid, char* endserv, char* endhost, char* endtype)
{
{
goto bad;
goto bad;
*endserv = 0;
{
goto bad;
*endhost = 0;
{
goto bad;
*endtype = 0;
if (eaccess(state->mount, X_OK) && (mkdir(state->mount, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(state->mount, S_IRWXU|S_IRWXG|S_IRWXO)))
goto bad;
*endtype = '/';
goto bad;
}
*endhost = '/';
goto bad;
}
*endserv = '/';
goto bad;
if (mode != (S_IRWXU|S_IRWXG|S_IRWXO) && (uid >= 0 || gid >= 0 && (mode |= S_ISGID)) && (chown(state->mount, uid, gid) || chmod(state->mount, mode)))
{
goto bad;
}
}
return 0;
bad:
*endtype = '/';
*endhost = '/';
*endserv = '/';
messagef((state->id, NiL, -1, "mkmount: %s: cannot access physical mount directory", state->mount));
return -1;
}
/*
* generate CS_REMOTE_CONTROL argv
*/
static void
remote(register Cs_t* state, const char* host, const char* user, const char* path, int agent, register char** av, register char* fv)
{
register char* t;
*av++ = CS_REMOTE_SHELL;
{
*av++ = "-l";
}
*av++ = CS_REMOTE_PROFILE;
*av++ = ";";
*av++ = CS_REMOTE_CONTROL;
*av = 0;
*fv++ = '-';
if (error_info.trace < 0)
*fv++ = CS_REMOTE_OPEN;
t = fv;
if (agent)
*fv++ = CS_REMOTE_OPEN_AGENT;
*fv++ = CS_REMOTE_OPEN_LOCAL;
*fv++ = CS_REMOTE_OPEN_NOW;
*fv++ = CS_REMOTE_OPEN_SHARE;
*fv++ = CS_REMOTE_OPEN_TEST;
*fv++ = CS_REMOTE_OPEN_TRUST;
if (fv == t)
*fv++ = CS_REMOTE_OPEN_READ;
*fv = 0;
}
/*
* service is modified in place
* 0 returned on success
*/
static int
{
register char* s;
char* on;
char* local;
int n;
*s++ = '/';
{
return -1;
}
{
return -1;
}
else
{
strcpy(s, CS_SVC_HOSTS);
{
else
return -1;
}
}
{
{
av[2] = 0;
}
{
ov[0] = PROC_FD_DUP(n, 0, 0);
ov[2] = 0;
{
n = 1;
for (;;)
{
{
{
return 0;
}
break;
}
/*
* sleep() and MNT_TMP
* hack around remote
* fs cache delays
*/
if (n >= CS_REMOTE_DELAY)
{
break;
}
if (n == 1)
{
{
}
}
sleep(n);
n <<= 1;
}
}
}
}
return -1;
}
/*
* recursive csopen(state,path,CS_OPEN_TEST)
* previous side effects preserved
*/
static int
{
int ret;
static int level;
if (level >= 8)
return -1;
level++;
level--;
return ret;
}
/*
* use remote agent to initiate and authenticate service on path
*/
static int
{
register int n;
register int m;
register char* s;
goto sorry;
goto sorry;
buf[--m] = 0;
if (buf[--m] == 'A')
buf[--m] = 0;
else
m = 0;
goto sorry;
if (m)
{
goto sorry;
goto sorry;
goto sorry;
if (*num != '\n')
{
buf[m - 1] = 0;
num[n - 1] = 0;
goto sorry;
goto sorry;
goto sorry;
goto sorry;
goto sorry;
}
}
return fd;
if (fd >= 0)
if (proc)
return -1;
}
/*
* csattach() helper
*/
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
if (op & CS_OPEN_CREATE)
{
n = errno;
{
{
return -1;
}
}
errno = n;
{
return -1;
}
#if CS_LIB_V10
#else
#endif
{
messagef((state->id, NiL, -1, "open: %s: %s: %s error", state->path, path, n ? "connld" : "fattach"));
return -1;
}
}
else
for (;;)
{
{
break;
}
{
return -1;
}
{
return -1;
}
op = CS_OPEN_TEST;
}
#else
#if CS_LIB_SOCKET_UN
int pid;
int namlen;
char c;
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));
for (n = 0;; n++)
{
if (n >= 10)
{
return -1;
}
{
return -1;
}
{
if (op & CS_OPEN_CREATE)
{
goto badcon;
}
break;
#else
break;
#endif
}
else
{
goto badcon;
{
c = 0;
for (;;)
{
*b = CS_MNT_PROCESS;
*b = CS_MNT_STREAM;
if (pid > 0 || ++c >= 5)
break;
sleep(1);
}
{
{
if (op & CS_OPEN_CREATE)
{
goto badcon;
}
if (n)
sleep(1);
continue;
}
*b = CS_MNT_PROCESS;
*b = CS_MNT_STREAM;
}
}
}
if (op & CS_OPEN_CREATE)
{
{
return -1;
}
{
{
n = errno;
errno = n;
goto badcon;
}
break;
}
else
goto badcon;
}
else if (op & CS_OPEN_TEST)
return -1;
{
return -1;
}
else
sleep(2);
}
#else
fd = -1;
#endif
#endif
#endif
return fd;
}
/*
* return connect stream to fdp path
* if (op & CS_) then path is created
* and server connect stream is returned
* otherwise client connect stream returned
*/
int
{
}
int
{
}
/*
*/
int
{
register char* b;
register char* s;
register int n;
int fd;
char* t;
char* u;
char* type;
char* endtype;
char* host;
char* endhost;
char* serv;
char* endserv;
char* qual;
char* endqual;
char* opath;
char* user = 0;
char* group = 0;
char* trust = 0;
char* arg = 0;
int mode;
unsigned long addr;
unsigned long port = 0;
if (!path)
{
return -1;
}
if (op < 0)
op = CS_OPEN_TEST;
/*
* blast out the parts
*/
{
return -1;
}
{
/*
* dynamic ip assignment can change the addr
* underfoot in some implementations so we
* double check the local ip here
*/
}
b = path;
return -1;
*s++ = 0;
if (!streq(b, "dev"))
return -1;
if (b = strchr(s, '/'))
*b++ = 0;
if (streq(s, "fdp"))
{
{
return -1;
}
#endif
}
{
return -1;
}
else
{
return -1;
}
#endif
type = s;
if (!b)
else
{
host = b;
if (!(s = strchr(b, '/')))
serv = 0;
else
{
*s++ = 0;
serv = s;
/*
* grab the next fd to preserve open semantics
*/
for (n = 0; n < 10; n++)
break;
/*
* get qual, perm and arg
*/
if (b = strchr(s, '/'))
{
*b++ = 0;
do
{
if (*b == '#')
{
arg = b + 1;
break;
}
if (u = strchr(b, '/'))
*u++ = 0;
if (s = strchr(b, '='))
*s++ = 0;
for (n = 0, t = b; *t; n = HASHKEYPART(n, *t++));
switch (n)
{
group = s ? s : "";
break;
op |= CS_OPEN_LOCAL;
break;
op |= CS_OPEN_NOW;
break;
auth = 0;
break;
op |= CS_OPEN_REMOTE;
break;
op |= CS_OPEN_SHARE;
break;
op |= CS_OPEN_SLAVE;
break;
op |= CS_OPEN_TEST;
break;
op |= CS_OPEN_TRUST;
trust = s;
break;
user = s ? s : "";
break;
default:
qual += sfsprintf(qual, sizeof(state->qual) - (qual - state->qual) - 1, "%s%s", qual == state->qual ? "" : "-", b);
if (s)
*(s - 1) = '=';
break;
}
} while (b = u);
}
}
}
if (*type != 't')
auth = 0;
if (host)
{
/*
* validate host
*/
{
if (serv && !(op & CS_OPEN_CREATE) && *type == 't' && (port = csport(state, type, serv)) >= CS_PORT_MIN && port <= CS_PORT_MAX)
{
/*
* attempt proxy connection
*/
if (nfd >= 0)
{
nfd = -1;
}
if ((fd = state->proxy.addr ? csbind(state, type, state->proxy.addr, state->proxy.port, 0L) : reopen(state, csvar(state, CS_VAR_PROXY, 0))) >= 0)
{
n = sfsprintf(tmp, sizeof(tmp), "\n%s!%s!%d\n\n%s\n%s\n0\n-1\n-1\n", type, host, port, csname(state, 0), error_info.id ? error_info.id : state->id);
{
return fd;
{
s = tmp;
s[n - 1] = 0;
while (*s && *s++ != '\n');
}
}
}
}
#ifdef EADDRNOTAVAIL
#else
#endif
goto bad;
}
if (op & CS_OPEN_LOCAL)
{
}
if (op & CS_OPEN_NOW)
{
}
if (op & CS_OPEN_SHARE)
if (op & CS_OPEN_SLAVE)
if (op & CS_OPEN_TEST)
if (op & CS_OPEN_TRUST)
if ((state->flags & CS_ADDR_REMOTE) && (!serv || !strneq(serv, CS_SVC_INET, sizeof(CS_SVC_INET) - 1) && (strtol(serv, &t, 0), *t)))
if (s = user)
{
n = geteuid();
if (*s)
{
{
if (*t)
{
goto bad;
}
}
if (n && uid != n)
{
goto bad;
}
}
else
uid = n;
}
if (s = group)
{
n = getegid();
if (*s)
{
{
if (*t)
{
goto bad;
}
}
{
break;
if (n < 0)
{
goto bad;
}
}
}
else
gid = n;
}
if (s = trust)
{
if (!*s)
{
if (*t)
{
goto bad;
}
}
}
else
{
{
if (*type == 'f')
{
goto bad;
}
if (op & CS_OPEN_CREATE)
{
goto bad;
}
}
{
if (op & CS_OPEN_CREATE)
addr = 0;
goto bad;
if (nfd >= 0)
{
nfd = -1;
}
{
{
return -1;
}
return fd;
}
}
}
}
/*
* get the mount dir prefix
*/
{
#ifdef ELOOP
#else
#endif
goto bad;
}
if (*type == 'f')
{
{
goto bad;
}
if ((op & CS_OPEN_CREATE) && eaccess(path, X_OK) && (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)))
goto bad;
}
else
{
if (op & CS_OPEN_TRUST)
{
if (!pathaccess(csvar(state, CS_VAR_TRUST, 1), csvar(state, CS_VAR_SHARE, 1), NiL, PATH_EXECUTE, b, sizeof(state->mount) - (b - state->mount)))
goto bad;
}
else if (!pathpath(csvar(state, CS_VAR_SHARE, 0), "", PATH_EXECUTE, b, sizeof(state->mount) - (b - state->mount)))
goto bad;
b += strlen(b);
}
/*
* add the type
*/
if (!host)
{
if (nfd >= 0)
{
}
if (fd < 0)
return fd;
}
endtype = b;
/*
* add the host
*/
else
{
if (strlen(s) <= CS_MNT_MAX)
else
{
unsigned char* a = (unsigned char*)&addr;
}
}
if (!serv)
{
if (nfd >= 0)
return fd;
}
endhost = b;
/*
* add the service
*/
sfsprintf(b, sizeof(state->mount) - (b - path), "%s/%s/%s/%s%s", CS_SVC_DIR, type, serv, serv, CS_SVC_SUFFIX);
op |= CS_OPEN_TEST;
else
{
if (!(op & CS_OPEN_TRUST))
op |= CS_OPEN_TEST;
}
endserv = b;
/*
* add the qualifier and perm
*/
if (sid >= 0)
else
if (uid >= 0)
else if (gid >= 0)
else
#else
#endif
if (qual)
{
if (b < endqual)
*b++ = '-';
*b++ = *qual++;
}
{
if (b >= endqual)
b--;
*b++ = CS_MNT_OTHER;
}
/*
* add in the connect stream control
*/
*b++ = '/';
*b = CS_MNT_STREAM;
/*
* create the mount subdirs if necessary
*/
goto bad;
if (nfd >= 0)
{
nfd = -1;
}
if (op & CS_OPEN_MOUNT)
{
return 0;
}
if (*type == 'f')
{
/*
* {fdp}
*/
return -1;
}
else
{
/*
* {tcp,udp}
*/
{
/*
* check for old single char cs mount
*/
}
if (op & CS_OPEN_CREATE)
{
if (fd >= 0)
{
return -1;
}
return -1;
sigcritical(1);
{
{
goto unblock;
}
{
goto unblock;
}
{
goto unblock;
}
{
goto unblock;
}
}
port = n;
else if (geteuid())
else
port = CS_RESERVED;
{
{
fd = -1;
}
}
sigcritical(0);
if (fd < 0)
return -1;
}
else if (fd < 0 && ((op & CS_OPEN_TEST) || initiate(state, user, opath, tmp, serv) || (fd = reopen(state, path)) < 0))
{
return -1;
}
else if (!(op & CS_OPEN_AGENT))
{
if (n)
{
return -1;
}
}
}
/*
* fd is open at this point
* make sure its not a bogus mount
*/
{
if (n)
{
return -1;
}
{
return -1;
}
}
return fd;
bad:
if (nfd >= 0)
return -1;
}
int
{
}