};
enum signalsexitspecials { se_number=-100, se_numbernocore, se_highbit, se_stdout };
-enum overridetypes { ot_none, ot_string, ot_file };
+enum overridetypes { ot_none, ot_string, ot_file, ot_builtin };
-static const char *serviceuser=0;
+struct constkeyvaluepair { const char *key, *value; };
+
+static const char *serviceuser;
static uid_t serviceuid, myuid;
-static struct fdsetupstate *fdsetup=0;
-static int fdsetupsize=0;
-static const char *(*defvarsarray)[2];
-static int defvarsavail=0, defvarsused=0;
-static unsigned long timeout=0;
+static struct fdsetupstate *fdsetup;
+static int fdsetupsize;
+static struct constkeyvaluepair *defvararray;
+static int defvaravail, defvarused;
+static unsigned long timeout;
static int signalsexit=254;
-static int sigpipeok=0, hidecwd=0;
+static int sigpipeok, hidecwd;
static int overridetype= ot_none;
static const char *overridevalue, *spoofuser=0;
static void usage(void) {
if (fprintf(stderr,
"usage: userv <options> [--] <service-user> <service-name> [<argument> ...]\n"
+ "usage: userv <options> -B|--builtin [--] <builtin-service> [<info-argument> ...]\n"
"options: -f|--file <fd>[<fdmodifiers>]=<filename>\n"
" -D|--defvar <name>=<value>\n"
" -t|--timeout <seconds>\n"
static void of_defvar(const struct optioninfo *oip, const char *value, char *key) {
int i;
+ if (!key[0])
+ usageerror("empty string not allowed as variable name");
if (strlen(key)>MAX_GENERAL_STRING)
usageerror("variable name `%s' is far too long",key);
if (strlen(value)>MAX_GENERAL_STRING)
usageerror("variable `%s' has value `%s' which is far too long",key,value);
- for (i=0; i<defvarsused && strcmp(defvarsarray[i][0],key); i++);
- if (defvarsused >= MAX_ARGSDEFVARS) usageerror("far too many --defvar or -D options");
- if (i>=defvarsavail) {
- defvarsavail+=10; defvarsavail<<=1;
- defvarsarray= xrealloc(defvarsarray,sizeof(const char*)*2*defvarsavail);
+ for (i=0; i<defvarused && strcmp(defvararray[i].key,key); i++);
+ if (defvarused >= MAX_ARGSDEFVAR) usageerror("far too many --defvar or -D options");
+ if (i>=defvaravail) {
+ defvaravail+=10; defvaravail<<=1;
+ defvararray= xrealloc(defvararray,sizeof(struct constkeyvaluepair)*defvaravail);
}
- if (i==defvarsused) defvarsused++;
- defvarsarray[i][0]= key;
- defvarsarray[i][1]= value;
+ if (i==defvarused) defvarused++;
+ defvararray[i].key= key;
+ defvararray[i].value= value;
}
static void of_timeout(const struct optioninfo *oip, const char *value, char *key) {
exit(0);
}
+static void of_builtin(const struct optioninfo *oip, const char *value, char *key) {
+ overridetype= ot_builtin;
+}
+
static void of_override(const struct optioninfo *oip, const char *value, char *key) {
overridetype= ot_string;
overridevalue= value;
{ 'S', "signals", 1, of_signals },
{ 'P', "sigpipe", 0, of_sigpipe },
{ 'H', "hidecwd", 0, of_hidecwd },
+ { 'B', "builtin", 0, of_builtin },
{ 'h', "help", 0, of_help },
{ 0, "copyright", 0, of_copyright },
{ 0, "override", 1, of_override },
char *argp;
const struct optioninfo *oip;
struct sockaddr_un ssockname;
- int sfd, ngids, i, j, tempfd, l, c, reading, fd, r, status, ngidssize;
+ int sfd, ngids, i, tempfd, l, c, reading, fd, r, status, ngidssize;
sigset_t sset;
unsigned long ul;
size_t cwdbufsize;
of_file(0,"stderr",fd2key);
for (argpp= argv+1;
- (argp= *argpp) && *argp == '-';
+ (argp= *argpp) && *argp == '-' && argp[1];
argpp++) {
if (!*++argp) usageerror("unknown option/argument `%s'",*argpp);
if (*argp == '-') { /* Two hyphens */
}
}
}
- if (!*argpp) usageerror("no service user given after options");
- serviceuser= *argpp++;
- if (!*argpp) usageerror("no service name given after options and service user");
+ if (overridetype == ot_builtin) {
+ serviceuser= "-";
+ } else {
+ if (!*argpp) usageerror("no service user given after options");
+ serviceuser= *argpp++;
+ }
+ if (!*argpp) usageerror(overridetype == ot_builtin ?
+ "no service name given after options and service user" :
+ "no builtin service given after options");
for (fd=0; fd<fdsetupsize; fd++) {
if (!fdsetup[fd].filename) continue;
argc-= (argpp-argv);
argv= argpp;
- if (argc > MAX_ARGSDEFVARS) usageerror("far too many arguments");
+ if (argc > MAX_ARGSDEFVAR) usageerror("far too many arguments");
if (ngids > MAX_GIDS) miscerror("caller is in far too many gids");
+ spoofuid= myuid;
+ spoofgid= mygid;
+ logname= getenv("LOGNAME");
+ if (!logname) logname= getenv("USER");
+ if (logname) {
+ pw= getpwnam(logname);
+ if (!pw || pw->pw_uid != myuid) logname= 0;
+ }
+ if (!logname) {
+ pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
+ logname= pw->pw_name;
+ }
+
+ if (!strcmp(serviceuser,"-")) serviceuser= logname;
pw= getpwnam(serviceuser);
if (!pw) miscerror("requested service user `%s' is not a user",serviceuser);
serviceuid= pw->pw_uid;
}
gidarray[ngids++]= gr->gr_gid;
}
- } else {
- spoofuid= myuid;
- spoofgid= mygid;
- logname= getenv("LOGNAME");
- if (!logname) logname= getenv("USER");
- if (logname) {
- pw= getpwnam(logname);
- if (!pw || pw->pw_uid != myuid) logname= 0;
- }
- if (!logname) {
- pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
- logname= pw->pw_name;
- }
}
cwdbufsize= 0; cwdbuf= 0;
ovused= -1;
ovbuf= 0;
break;
+ case ot_builtin:
+ l= strlen(argv[0]);
+ if (l >= MAX_OVERRIDE_LEN-20)
+ miscerror("builtin service string is too long (%d, max is %d)",
+ l,MAX_OVERRIDE_LEN-21);
+ l+= 20;
+ ovbuf= xmalloc(l);
+ snprintf(ovbuf,l,"execute-builtin %s\n",argv[0]);
+ ovused= strlen(ovbuf);
+ break;
case ot_string:
l= strlen(overridevalue);
if (l >= MAX_OVERRIDE_LEN)
miscerror("override string is too long (%d, max is %d)",l,MAX_OVERRIDE_LEN-1);
ovbuf= xmalloc(l+2);
- strcpy(ovbuf,overridevalue);
- strcat(ovbuf,"\n");
+ snprintf(ovbuf,l+2,"%s\n",overridevalue);
ovused= l+1;
break;
case ot_file:
else request_mbuf.nreadfds++;
}
request_mbuf.nargs= argc-1;
- request_mbuf.nvars= defvarsused;
+ request_mbuf.nvars= defvarused;
request_mbuf.overridelen= ovused;
xfwrite(&request_mbuf,sizeof(request_mbuf),swfile);
xfwrite(serviceuser,sizeof(*serviceuser)*request_mbuf.serviceuserlen,swfile);
xfwritefds(fdm_write,request_mbuf.nwritefds,swfile);
for (i=1; i<argc; i++)
xfwritestring(argv[i],swfile);
- for (i=0; i<defvarsused; i++)
- for (j=0; j<2; j++)
- xfwritestring(defvarsarray[i][j],swfile);
+ for (i=0; i<defvarused; i++) {
+ xfwritestring(defvararray[i].key,swfile);
+ xfwritestring(defvararray[i].value,swfile);
+ }
ul= REQUEST_END_MAGIC; xfwrite(&ul,sizeof(ul),swfile);
xfflush(swfile);