static int initiate(register Cs_t* state, char* user, char* path, char* service, char* name) { register char* s; char* on; char* local; Sfio_t* sp; Sfio_t* np; int n; char* av[REMOTE_ARGC]; char buf[PATH_MAX / 4]; local = csname(state, 0); s = service + strlen(service); *s++ = '/'; if (!(state->flags & CS_ADDR_SHARE)) { sfsprintf(buf, sizeof(buf), "%s\n", state->host); if (!(sp = tokline(buf, SF_STRING, NiL))) return -1; } else if (state->flags & CS_ADDR_LOCAL) { sfsprintf(buf, sizeof(buf), "%s\n", CS_HOST_LOCAL); if (!(sp = tokline(buf, SF_STRING, NiL))) return -1; } else { strcpy(s, CS_SVC_HOSTS); if (!(sp = tokline(service, SF_READ, NiL))) { if (streq(state->host, CS_HOST_SHARE)) sfsprintf(buf, sizeof(buf), "%s\n%s\n", CS_HOST_SHARE, CS_HOST_LOCAL); else sfsprintf(buf, sizeof(buf), "%s\n%s\n%s\n", state->host, CS_HOST_SHARE, CS_HOST_LOCAL); if (!(sp = tokline(buf, SF_STRING, NiL))) return -1; } } sfsprintf(s, PATH_MAX - (s - service) - 1, "%s%s", name, CS_SVC_SUFFIX); while (s = sfgetr(sp, '\n', 1)) if (tokscan(s, NiL, " %s ", &on) == 1) { if (streq(on, CS_HOST_LOCAL) || streq(on, local)) { sfclose(sp); av[0] = service; av[1] = path; av[2] = 0; return procclose(procopen(av[0], av, NiL, NiL, PROC_PRIVELEGED|PROC_ZOMBIE)) < 0 ? -1 : 0; } else if (!streq(on, CS_HOST_SHARE)) { Proc_t* proc; time_t otime; struct stat st; char fv[REMOTE_FLAGC]; long ov[3]; remote(state, on, user, path, 0, av, fv); otime = lstat(state->mount, &st) ? 0 : st.st_ctime; n = open("/dev/null", O_RDWR); ov[0] = PROC_FD_DUP(n, 0, 0); ov[1] = PROC_FD_DUP(n, 1, PROC_FD_PARENT|PROC_FD_CHILD); ov[2] = 0; if (proc = procopen(av[0], av, NiL, ov, PROC_PRIVELEGED|PROC_ZOMBIE)) { n = 1; for (;;) { if (!lstat(state->mount, &st) && st.st_ctime != otime) { if (!procclose(proc)) { sfclose(sp); return 0; } break; } /* * sleep() and MNT_TMP * hack around remote * fs cache delays */ if (n >= CS_REMOTE_DELAY) { procclose(proc); break; } if (n == 1) { *state->control = CS_MNT_TMP; if (remove(state->mount)) { close(open(state->mount, O_WRONLY|O_CREAT|O_TRUNC, 0)); remove(state->mount); } *state->control = CS_MNT_STREAM; } sleep(n); n <<= 1; } } } else if (!sfstacked(sp) && (np = csinfo(state, on, NiL))) sfstack(sp, np); } sfclose(sp); return -1; }
unsigned long csaddr(register Cs_t* state, const char* aname) { register char* name = (char*)aname; register char* s; register unsigned long addr; register Sfio_t* sp = 0; int userlen = 0; int dot = 0; long flags = 0; char* user; messagef((state->id, NiL, -8, "addr(%s) call", name)); if (!local) { #if CS_LIB_SOCKET if (!state->db) state->db = -1; #endif local = CS_LOCAL; if (addr = realaddr(state, csname(state, 0))) local = addr; } if (!name) { addr = local; goto ok; } if (s = strchr(name, '@')) { userlen = s - name; user = name; name = s + 1; } if (strneq(name, CS_HOST_SHARE, sizeof(CS_HOST_SHARE) - 1)) switch (name[sizeof(CS_HOST_SHARE) - 1]) { case 0: flags |= CS_ADDR_SHARE; if (sp = csinfo(state, name, NiL)) { while (name = sfgetr(sp, '\n', 1)) if (addr = realaddr(state, name)) goto ok; sfclose(sp); sp = 0; } if (!(addr = realaddr(state, name = CS_HOST_GATEWAY))) addr = local; goto ok; case '.': flags |= CS_ADDR_SHARE; name += sizeof(CS_HOST_SHARE); break; } if (addr = realaddr(state, name)) goto ok; if ((flags & CS_ADDR_SHARE) && !(state->flags & CS_ADDR_NUMERIC) && (s = strchr(name, '.'))) { char* sb; char* se; char* sx; char* t; char* te; dot = s - name; s = state->temp; sx = &state->temp[sizeof(state->temp) - 1]; s += sfsprintf(s, sx - s, "%s/", CS_SVC_REMOTE); sb = s; se = 0; t = name; while (*t && s < sx) { if (s - sb >= CS_MNT_MAX) { if (se) { s = se - 1; t = te; } else { if (s >= sx) break; if (*t == '.') t++; } *s++ = '/'; sb = s; se = 0; } if ((*s++ = *t++) == '.') { se = s; te = t; } } *s = 0; if (sp = csinfo(state, state->temp, NiL)) { while (t = sfgetr(sp, '\n', 1)) { if (s = strchr(t, '@')) s++; else s = t; if (addr = realaddr(state, s)) { name = s; if (!userlen && s != t) { userlen = s - t - 1; user = t; } goto ok; } } sfclose(sp); sp = 0; } sfsprintf(state->temp, sizeof(state->temp), "%s.%s", CS_HOST_GATEWAY, name); if (addr = realaddr(state, state->temp)) { name = state->temp; goto ok; } sfsprintf(state->temp, sizeof(state->temp), "%-.*s.%s", dot, name, name); if (addr = realaddr(state, state->temp)) { name = state->temp; goto ok; } } messagef((state->id, NiL, -1, "addr: %s: not found", aname)); return 0; ok: if (state->flags & CS_ADDR_NUMERIC) flags &= ~CS_ADDR_SHARE; if (addr == local) { flags |= CS_ADDR_LOCAL; name = csname(state, 0); } else if (!(state->flags & CS_ADDR_NUMERIC)) { if (s = strchr(name, '.')) { sfsprintf(state->temp, sizeof(state->temp), "%-.*s", s - name, name); if (realaddr(state, state->temp) == addr) name = state->temp; else flags |= CS_ADDR_REMOTE; } if (!(flags & CS_ADDR_REMOTE) && !streq(name, CS_HOST_PROXY) && !csattr(state, name, "*")) flags |= CS_ADDR_REMOTE; } /* * cache host name and user for possible CS_REMOTE_SHELL */ strncpy(state->host, name, sizeof(state->host) - 1); if (userlen) { if (userlen >= sizeof(state->user)) userlen = sizeof(state->user) - 1; strncpy(state->user, user, userlen); } state->user[userlen] = 0; if (sp) sfclose(sp); state->flags &= ~(CS_ADDR_LOCAL|CS_ADDR_NOW|CS_ADDR_REMOTE|CS_ADDR_SHARE|CS_DAEMON_SLAVE|CS_ADDR_TEST|CS_ADDR_TRUST); state->flags |= flags; messagef((state->id, NiL, -8, "addr(%s) = %s, flags = |%s%s%s", aname, csntoa(state, addr), (state->flags & CS_ADDR_LOCAL) ? "LOCAL|" : "", (state->flags & CS_ADDR_REMOTE) ? "REMOTE|" : "", (state->flags & CS_ADDR_SHARE) ? "SHARE|" : "")); return addr; }