int suidgetfd_required (str prog) { int fds[2]; if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0) fatal ("socketpair: %m\n"); close_on_exec (fds[0]); str path = fix_exec_path ("suidconnect"); char *av[] = { "suidconnect", const_cast<char *> (prog.cstr ()), NULL }; if (spawn (path, av, fds[1]) == -1) fatal << path << ": " << strerror (errno) << "\n"; close (fds[1]); int fd = recvfd (fds[0]); if (fd < 0) { struct stat sb; if (!runinplace && !stat (path, &sb) && (sb.st_gid != sfs_gid || !(sb.st_mode & 02000))) { if (struct group *gr = getgrgid (sfs_gid)) warn << path << " should be setgid to group " << gr->gr_name << "\n"; else warn << path << " should be setgid to group " << sfs_gid << "\n"; } else { warn << "have you launched the appropriate daemon (sfscd or sfssd)?\n"; warn << "have subsidiary daemons died (check your system logs)?\n"; } fatal ("could not suidconnect for %s\n", prog.cstr ()); } close (fds[0]); return fd; }
str find_program_plus_libsfs (const char *program) { str s = fix_exec_path (program); if (!s || !execok (s)) s = find_program (program); return s; }
static bool parse_service (vec<str> &av, extension *e, str errpref) { u_int32_t snum; str usage = strbuf () << errpref << ": usage: Service num prog [arg ...]\n" << errpref << ": Service num -u path\n" << errpref << ": Service num -t server [port]\n"; if (av.size () < 3 || !convertint (av[1], &snum)) { warn << usage; return false; } if (!e) { warn << errpref << ": Service must follow Release or Extensions\n"; return false; } if (e->srvtab[snum]) { warn << errpref << ": Service " << snum << " already defined\n"; return false; } av.pop_front (); av.pop_front (); if (av[0][0] != '-') { av[0] = fix_exec_path (av[0]); sfssrv *ss = exectab[av]; if (!ss) ss = New sfssrv_exec (av); e->srvtab.insert (snum, ss); return true; } else if (av[0] == "-u" && av.size () == 2) { sfssrv *ss = New sfssrv_sockpath (av[1]); e->srvtab.insert (snum, ss); return true; } else if (av[0] == "-t" && av.size () >= 2 && av.size () <= 3) { u_int16_t port = 0; if (av.size () == 2 || convertint (av[2], &port)) { sfssrv *ss = New sfssrv_proxy (av[1], port); e->srvtab.insert (snum, ss); return true; } } warn << usage; return false; }
str find_program (const char *program) { static rxx colonplus (":+"); str r; if (strchr (program, '/')) { r = program; if (execok (r)) return r; return NULL; } #ifdef MAINTAINER if (builddir) { r = fix_exec_path (program); if (execok (r)) return r; } #endif /* MAINTAINER */ if (progdir) { r = progdir << program; if (execok (r)) return r; } const char *p = getenv ("PATH"); if (!p) return NULL; vec<str> vs; split (&vs, colonplus, p); for (str *sp = vs.base (); sp < vs.lim (); sp++) { if (!*sp || !sp->len ()) continue; r = *sp << "/" << program; if (execok (r)) return r; } return NULL; }
int suidgetfd (str prog) { int fds[2]; if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0) return -1; close_on_exec (fds[0]); str path = fix_exec_path ("suidconnect"); char *av[] = { "suidconnect", "-q", const_cast<char *> (prog.cstr ()), NULL }; if (spawn (path, av, fds[1]) == -1) { close (fds[0]); close (fds[1]); return -1; } close (fds[1]); int fd = recvfd (fds[0]); close (fds[0]); return fd; }