X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=client.c;h=17fa6cec0dbef2fe6052738cdf4a782cc285f986;hb=refs%2Fheads%2Fmaster;hp=bc554128cff66cadc40098d6d4e2566edd2a2428;hpb=f7dd4f74d0a6b3399fe694f80911657aec351ffd;p=userv.git
diff --git a/client.c b/client.c
index bc55412..17fa6ce 100644
--- a/client.c
+++ b/client.c
@@ -2,11 +2,12 @@
* userv - client.c
* client code
*
- * Copyright (C)1996-1997 Ian Jackson
+ * userv is copyright Ian Jackson and other contributors.
+ * See README for full authorship information.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
@@ -15,8 +16,7 @@
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with userv; if not, write to the Free Software
- * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * along with userv; if not, see .
*/
/*
@@ -72,6 +72,7 @@
#include "config.h"
#include "common.h"
+#include "both.h"
#include "version.h"
enum fdmodifiervalues {
@@ -127,25 +128,27 @@ static uid_t myuid, spoofuid;
static gid_t mygid, spoofgid, *gidarray;
static int ngids;
static struct opening_msg opening_mbuf;
-static const char *logname;
+static const char *loginname;
static char *cwdbuf;
static size_t cwdbufsize;
static char *ovbuf;
-static int ovused, systemerror;
+static int ovused, systemerror, socketfd;
static void blocksignals(int how) {
sigset_t set;
static const char blockerrmsg[]= "userv: failed to [un]block signals: ";
const char *str;
+ int unused;
sigemptyset(&set);
sigaddset(&set,SIGCHLD);
sigaddset(&set,SIGALRM);
if (sigprocmask(how,&set,0)) {
str= strerror(errno);
- write(2,blockerrmsg,sizeof(blockerrmsg)-1);
- write(2,str,strlen(str));
- write(2,"\n",1);
+ unused= write(2,blockerrmsg,sizeof(blockerrmsg)-1);
+ unused= write(2,str,strlen(str));
+ unused= write(2,"\n",1);
+ (void)unused;
exit(-1);
}
}
@@ -167,7 +170,7 @@ static void NONRETURNPRINTFFORMAT(1,2) miscerror(const char *fmt, ...) {
exit(-1);
}
-static void NONRETURNPRINTFFORMAT(1,2) syscallerror(const char *fmt, ...) {
+static void NONRETURNPRINTFFORMAT(1,2) fsyscallerror(const char *fmt, ...) {
va_list al;
int e;
@@ -180,6 +183,10 @@ static void NONRETURNPRINTFFORMAT(1,2) syscallerror(const char *fmt, ...) {
exit(-1);
}
+void syscallerror(const char *what) {
+ fsyscallerror("%s",what);
+}
+
static void NONRETURNING protoreaderror(FILE *file, const char *where) {
int e;
@@ -213,7 +220,7 @@ static void NONRETURNPRINTFFORMAT(1,2) protoerror(const char *fmt, ...) {
static void xfread(void *p, size_t sz, FILE *file) {
size_t nr;
- nr= fread(p,1,sz,file);
+ nr= working_fread(p,sz,file);
if (nr != sz) protoreaderror(file,"in data");
}
@@ -277,8 +284,9 @@ static void getprogress(struct progress_msg *progress_r, FILE *file) {
protoerror("stderr message length %d is far too long",
progress_r->data.errmsg.messagelen);
for (i=0; idata.errmsg.messagelen; i++) {
- c= getc(file); if (c==EOF) protoreaderror(file,"in error message");
- if (isprint(c)) putc(c,stderr);
+ c= working_getc(file);
+ if (c==EOF) protoreaderror(file,"in error message");
+ if (ISCHAR(isprint,c)) putc(c,stderr);
else fprintf(stderr,"\\x%02x",(unsigned char)c);
}
putc('\n',stderr);
@@ -298,18 +306,7 @@ static void getprogress(struct progress_msg *progress_r, FILE *file) {
* the signal asynchronicity starts. They can do anything they like.
*/
-static void *xmalloc(size_t s) {
- void *p;
- p= malloc(s?s:1);
- if (!p) syscallerror("malloc (%lu bytes)",(unsigned long)s);
- return p;
-}
-
-static void *xrealloc(void *p, size_t s) {
- p= realloc(p,s);
- if (!p) syscallerror("realloc (%lu bytes)",(unsigned long)s);
- return p;
-}
+/* This includes xmalloc and xrealloc from both.c */
static void xfwritestring(const char *s, FILE *file) {
int l;
@@ -346,7 +343,7 @@ static void disconnect(void) /* DOES return, unlike in daemon */ {
event_mbuf.type= et_disconnect;
r= fwrite(&event_mbuf,1,sizeof(event_mbuf),swfile);
if ((r != sizeof(event_mbuf) || fflush(swfile)) && errno != EPIPE)
- syscallerror("write to server when disconnecting\n");
+ syscallerror("write to server when disconnecting");
}
systemerror= 1;
}
@@ -378,6 +375,7 @@ static void sighandler_chld(int ignored) /* DOES return, unlike in daemon */ {
memset(&event_mbuf,0,sizeof(event_mbuf));
event_mbuf.magic= EVENT_MAGIC;
event_mbuf.type= et_closereadfd;
+ event_mbuf.data.closereadfd.fd= fd;
r= fwrite(&event_mbuf,1,sizeof(event_mbuf),swfile);
if (r != sizeof(event_mbuf) || fflush(swfile))
if (errno != EPIPE) syscallerror("inform service of closed read fd");
@@ -419,7 +417,7 @@ struct optioninfo {
optionfunction *fn;
};
-static void usage(void) {
+static void usage(FILE *stream) {
if (fputs(
"usage: userv [--] [ ...]\n"
"usage: userv -B|--builtin [--] [ ...]\n"
@@ -428,16 +426,18 @@ static void usage(void) {
" -t|--timeout \n"
" -S|--signals |number|number-nocore|highbit|stdout\n"
" -w|--fdwait =wait|nowait|close\n"
- " -P|--sigpipe -H|--hidecwd -h|--help --copyright\n"
+ " -P|--sigpipe -H|--hidecwd -h|--help|--version --copyright\n"
" --override } available only\n"
" --override-file } to root\n"
" --spoof-user } or same user\n"
"fdmodifiers: read write overwrite trunc[ate]\n"
- "(separate with commas) append sync excl[usive] creat[e] fd\n\n"
- "userv and uservd version " VERSION VEREXT "; copyright (C)1996-1997 Ian Jackson.\n"
- "there is NO WARRANTY; type `userv --copyright' for details.\n",
- stderr) < 0)
- syscallerror("write usage to stderr");
+ "(separate with commas) append sync excl[usive] creat[e] fd\n"
+ "userv -B 'X' ... is same as userv --override 'execute-builtin X' - 'X' ...\n"
+ " for help, type `userv -B help'; remember to quote multi-word X\n"
+ "userv and uservd version " VERSION VEREXT ".\n"
+ COPYRIGHT("","\n"),
+ stream) < 0)
+ syscallerror("write usage message");
}
static void NONRETURNPRINTFFORMAT(1,2) usageerror(const char *fmt, ...) {
@@ -446,7 +446,7 @@ static void NONRETURNPRINTFFORMAT(1,2) usageerror(const char *fmt, ...) {
fputs("userv: ",stderr);
vfprintf(stderr,fmt,al);
fputs("\n\n",stderr);
- usage();
+ usage(stderr);
exit(-1);
}
@@ -499,43 +499,99 @@ static const struct fdmodifierinfo fdmodifierinfos[]= {
{ 0 }
};
-static void addfdmodifier(int fd, const char *key) {
+static void addfdmodifier(int fd, const char *key, size_t key_len) {
const struct fdmodifierinfo *fdmip;
if (!*key) return;
- for (fdmip= fdmodifierinfos; fdmip->string && strcmp(fdmip->string,key); fdmip++);
- if (!fdmip->string) usageerror("unknown fdmodifer `%s' for fd %d",key,fd);
+ for (fdmip= fdmodifierinfos;
+ fdmip->string &&
+ !(strlen(fdmip->string) == key_len &&
+ !memcmp(fdmip->string,key,key_len));
+ fdmip++);
+ if (!fdmip->string) usageerror("unknown fdmodifer `%.*s' for fd %d",
+ (int)key_len,key,fd);
if (fdmip->conflicts & fdsetup[fd].mods)
- usageerror("fdmodifier `%s' conflicts with another for fd %d",key,fd);
+ usageerror("fdmodifier `%.*s' conflicts with another for fd %d",
+ (int)key_len,key,fd);
fdsetup[fd].mods |= fdmip->implies;
fdsetup[fd].oflags |= fdmip->oflags;
}
-static int fdstdnumber(const char *string) {
- if (!strcmp(string,"stdin")) return 0;
- else if (!strcmp(string,"stdout")) return 1;
- else if (!strcmp(string,"stderr")) return 2;
- else return -1;
+static void addfdmodifier_fixed(int fd, const char *key) {
+ addfdmodifier(fd, key, strlen(key));
+}
+
+static int fdstdnumber(const char *string, const char **delim_r) {
+#define FN(v,s) do{ \
+ if (!memcmp(string,s,sizeof(s)-1)) { \
+ *delim_r= string+sizeof(s)-1; \
+ return v; \
+ } \
+ }while(0)
+
+ FN(0,"stdin");
+ FN(1,"stdout");
+ FN(2,"stderr");
+
+ return -1;
}
+static int strtofd(const char *string,
+ const char **mods_r /* 0: no modifiers, must go to end */,
+ const char *what) {
+ int fd;
+ unsigned long ul;
+ char *delim_v;
+ const char *mods;
+
+ fd= fdstdnumber(string,&mods);
+ if (fd>=0) {
+ if (*mods && *mods != ',')
+ usageerror("%s, when it is `stdin', `stdout' or `stderr',"
+ " must be delimited with a comma from any following"
+ " modifiers - `%s' is not permitted",
+ what, mods);
+ goto parsed;
+ }
+
+ errno= 0;
+ ul= strtoul(string,&delim_v,10);
+ if (errno || delim_v == string || ul > INT_MAX)
+ usageerror("%s must be must be numeric file descriptor"
+ " or `stdin', `stdout' or `stderr'"
+ " - `%s' is not recognized",
+ what, string);
+ mods= delim_v;
+ fd= ul;
+
+ parsed:
+ if (*mods==',')
+ mods++;
+
+ if (mods_r)
+ *mods_r= mods;
+ else if (*mods)
+ usageerror("%s must be must be only file descriptor"
+ " - trailing portion or modifiers `%s' not permitted",
+ what, mods);
+
+ if (fd > MAX_ALLOW_FD)
+ usageerror("%s file descriptor specified (%d)"
+ " is larger than maximum allowed (%d)",
+ what, fd, MAX_ALLOW_FD);
+
+ return fd;
+}
+
static void of_file(const struct optioninfo *oip, const char *value, char *key) {
unsigned long fd, copyfd;
struct stat stab;
int oldarraysize, r;
- char *delim;
-
- fd= strtoul(key,&delim,10);
- if (delim == key) {
- delim= strchr(key,',');
- if (delim) *delim++= 0;
- fd= fdstdnumber(key);
- if (fd<0) usageerror("first part of argument to -f or --file must be numeric "
- "file descriptor or `stdin', `stdout' or `stderr' - `%s' "
- "is not recognized",key);
- }
- if (fd > MAX_ALLOW_FD)
- usageerror("file descriptor specified (%lu) is larger than maximum allowed (%d)",
- fd,MAX_ALLOW_FD);
+ size_t mod_len;
+ const char *mods, *delim;
+
+ fd= strtofd(key,&mods,"first part of argument to -f or --file");
+
if (fd >= fdsetupsize) {
oldarraysize= fdsetupsize;
fdsetupsize+=2; fdsetupsize<<=1;
@@ -556,38 +612,29 @@ static void of_file(const struct optioninfo *oip, const char *value, char *key)
fdsetup[fd].oflags= 0;
fdsetup[fd].mods= 0;
fdsetup[fd].copyfd= -1;
- while (delim && *delim) {
- key= delim;
- delim= strchr(key,',');
- if (delim) *delim++= 0;
- addfdmodifier(fd,key);
+ while (mods && *mods) {
+ delim= strchr(mods,',');
+ mod_len= delim ? delim-mods : strlen(mods);
+ addfdmodifier(fd,mods,mod_len);
+ mods= delim ? delim+1 : 0;
}
if (!(fdsetup[fd].mods & (fdm_read|fdm_write))) {
if (fd == 0) {
- addfdmodifier(fd,"read");
+ addfdmodifier_fixed(fd,"read");
} else if (fdsetup[fd].mods & fdm_fd) {
- addfdmodifier(fd,"write");
+ addfdmodifier_fixed(fd,"write");
} else {
- addfdmodifier(fd,"overwrite");
+ addfdmodifier_fixed(fd,"overwrite");
}
}
if (fdsetup[fd].mods & fdm_fd) {
- copyfd= fdstdnumber(value);
- if (copyfd<0) {
- copyfd= strtoul(value,&delim,0);
- if (*delim)
- usageerror("value part of argument to --file with fd modifier must be "
- "numeric or fd name - `%s' is not recognised",value);
- else if (copyfd > MAX_ALLOW_FD)
- usageerror("file descriptor %lu named as target of file descriptor redirection"
- " (for file descriptor %lu) is larger than maximum allowed (%d)",
- copyfd,fd,MAX_ALLOW_FD);
- }
+ copyfd= strtofd(value,0,
+ "value part of argument to --file with fd modifier");
r= fstat(copyfd,&stab);
if (r) {
- if (oip) syscallerror("check filedescriptor %lu (named as target of file "
- "descriptor redirection for %lu)",copyfd,fd);
- else syscallerror("check basic filedescriptor %lu at program start",copyfd);
+ if (oip) fsyscallerror("check filedescriptor %lu (named as target of file "
+ "descriptor redirection for %lu)",copyfd,fd);
+ else fsyscallerror("check basic filedescriptor %lu at program start",copyfd);
}
fdsetup[fd].copyfd= copyfd;
}
@@ -595,18 +642,9 @@ static void of_file(const struct optioninfo *oip, const char *value, char *key)
static void of_fdwait(const struct optioninfo *oip, const char *value, char *key) {
const struct fdmodifierinfo *fdmip;
- unsigned long ul;
int fd;
- char *delim;
- fd= fdstdnumber(key);
- if (fd<0) {
- ul= strtoul(key,&delim,0);
- if (*delim) usageerror("first part of argument to --fdwait must be "
- "numeric or fd name - `%s' is not recognised",key);
- if (ul>MAX_ALLOW_FD) usageerror("first part of argument to --fdwait is too large");
- fd= ul;
- }
+ fd= strtofd(key,0,"first part of argument to --fdwait");
if (fd >= fdsetupsize || !fdsetup[fd].filename)
usageerror("file descriptor %d specified in --fdwait option is not open",fd);
for (fdmip= fdmodifierinfos; fdmip->string && strcmp(fdmip->string,value); fdmip++);
@@ -639,9 +677,11 @@ static void of_defvar(const struct optioninfo *oip, const char *value, char *key
static void of_timeout(const struct optioninfo *oip, const char *value, char *key) {
char *endp;
unsigned long ul;
-
- ul= strtoul(value,&endp,0);
- if (*endp) usageerror("timeout value `%s' must be a plain decimal string",value);
+
+ errno= 0;
+ ul= strtoul(value,&endp,10);
+ if (errno || *endp)
+ usageerror("timeout value `%s' must be a plain decimal string",value);
if (ul>INT_MAX) usageerror("timeout value %lu too large",ul);
timeout= ul;
}
@@ -649,9 +689,10 @@ static void of_timeout(const struct optioninfo *oip, const char *value, char *ke
static void of_signals(const struct optioninfo *oip, const char *value, char *key) {
unsigned long numvalue;
char *endp;
-
- numvalue= strtoul(value,&endp,0);
- if (*endp) {
+
+ errno= 0;
+ numvalue= strtoul(value,&endp,10);
+ if (errno || *endp) {
if (!strcmp(value,"number")) signalsexit= se_number;
else if (!strcmp(value,"number-nocore")) signalsexit= se_numbernocore;
else if (!strcmp(value,"highbit")) signalsexit= se_highbit;
@@ -673,25 +714,32 @@ static void of_hidecwd(const struct optioninfo *oip, const char *value, char *ke
}
static void of_help(const struct optioninfo *oip, const char *value, char *key) {
- usage();
+ usage(stdout);
+ if (fclose(stdout)) syscallerror("fclose stdout after writing usage message");
+ exit(0);
+}
+
+static void of_version(const struct optioninfo *oip, const char *value, char *key) {
+ if (puts(VERSION VEREXT) == EOF || fclose(stdout))
+ syscallerror("write version number");
exit(0);
}
static void of_copyright(const struct optioninfo *oip, const char *value, char *key) {
if (fputs(
-" userv - user service daemon and client; copyright (C)1996-1997 Ian Jackson\n\n"
+" userv - user service daemon and client\n\n"
+COPYRIGHT(" ","\n")
+"\n"
" This is free software; you can redistribute it and/or modify it under the\n"
" terms of the GNU General Public License as published by the Free Software\n"
-" Foundation; either version 2 of the License, or (at your option) any\n"
+" Foundation; either version 3 of the License, or (at your option) any\n"
" later version.\n\n"
" This program is distributed in the hope that it will be useful, but\n"
" WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General\n"
" Public License for more details.\n\n"
" You should have received a copy of the GNU General Public License along\n"
-" with userv; if not, write to Ian Jackson or\n"
-" to the Free Software Foundation, 59 Temple Place - Suite 330, Boston,\n"
-" MA 02111-1307, USA.\n",
+" with userv; if not, see .\n",
stdout) < 0) syscallerror("write usage to stderr");
exit(0);
}
@@ -726,6 +774,7 @@ const struct optioninfo optioninfos[]= {
{ 'H', "hidecwd", 0, of_hidecwd },
{ 'B', "builtin", 0, of_builtin },
{ 'h', "help", 0, of_help },
+ { 0, "version", 0, of_version },
{ 0, "copyright", 0, of_copyright },
{ 0, "override", 1, of_override },
{ 0, "override-file", 1, of_overridefile },
@@ -737,13 +786,14 @@ static void callvalueoption(const struct optioninfo *oip, char *arg) {
char *equals;
if (oip->values == 2) {
equals= strchr(arg,'=');
- if (!equals)
+ if (!equals) {
if (oip->abbrev)
usageerror("option --%s (-%c) passed argument `%s' with no `='",
oip->full,oip->abbrev,arg);
else
usageerror("option --%s passed argument `%s' with no `='",
oip->full,arg);
+ }
*equals++= 0;
(oip->fn)(oip,equals,arg);
} else {
@@ -761,7 +811,7 @@ static void security_init(void) {
mypid= getpid(); if (mypid == (pid_t)-1) syscallerror("getpid");
myuid= getuid(); if (myuid == (uid_t)-1) syscallerror("getuid");
mygid= getgid(); if (mygid == (gid_t)-1) syscallerror("getgid");
- ngids= getgroups(0,0); if (ngids == (gid_t)-1) syscallerror("getgroups(0,0)");
+ ngids= getgroups(0,0); if (ngids == -1) syscallerror("getgroups(0,0)");
gidarray= xmalloc(sizeof(gid_t)*ngids);
if (getgroups(ngids,gidarray) != ngids) syscallerror("getgroups(ngids,)");
@@ -851,18 +901,18 @@ static void determine_users(void) {
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;
+ loginname= getenv("LOGNAME");
+ if (!loginname) loginname= getenv("USER");
+ if (loginname) {
+ pw= getpwnam(loginname);
+ if (!pw || pw->pw_uid != myuid) loginname= 0;
}
- if (!logname) {
+ if (!loginname) {
pw= getpwuid(myuid); if (!pw) miscerror("cannot determine your login name");
- logname= pw->pw_name;
+ loginname= xstrsave(pw->pw_name);
}
- if (!strcmp(serviceuser,"-")) serviceuser= logname;
+ if (!strcmp(serviceuser,"-")) serviceuser= loginname;
pw= getpwnam(serviceuser);
if (!pw) miscerror("requested service user `%s' is not a user",serviceuser);
serviceuid= pw->pw_uid;
@@ -872,9 +922,9 @@ static void determine_users(void) {
" the user who will be providing the service");
if (spoofuser) {
- logname= spoofuser;
- pw= getpwnam(logname);
- if (!pw) miscerror("spoofed login name `%s' is not valid",logname);
+ loginname= spoofuser;
+ pw= getpwnam(loginname);
+ if (!pw) miscerror("spoofed login name `%s' is not valid",loginname);
spoofuid= pw->pw_uid;
spoofgid= pw->pw_gid;
ngidssize= ngids; ngids= 0;
@@ -884,7 +934,7 @@ static void determine_users(void) {
}
gidarray[ngids++]= spoofgid;
while ((gr= getgrent())) { /* ouch! getgrent has no error behaviour! */
- for (mem= gr->gr_mem; *mem && strcmp(*mem,logname); mem++);
+ for (mem= gr->gr_mem; *mem && strcmp(*mem,loginname); mem++);
if (!*mem) continue;
if (ngids>=ngidssize) {
if (ngids>=MAX_GIDS) miscerror("spoofed user is member of too many groups");
@@ -940,7 +990,7 @@ static void process_override(const char *servicename) {
break;
case ot_file:
ovfile= fopen(overridevalue,"r");
- if (!ovfile) syscallerror("open overriding configuration file `%s'",overridevalue);
+ if (!ovfile) fsyscallerror("open overriding configuration file `%s'",overridevalue);
ovbuf= 0; ovavail= ovused= 0;
while ((c= getc(ovfile)) != EOF) {
if (!c) miscerror("overriding config file `%s' contains null(s)",overridevalue);
@@ -952,7 +1002,7 @@ static void process_override(const char *servicename) {
ovbuf[ovused++]= c;
}
if (ferror(ovfile) || fclose(ovfile))
- syscallerror("read overriding configuration file `%s'",overridevalue);
+ fsyscallerror("read overriding configuration file `%s'",overridevalue);
ovbuf= xrealloc(ovbuf,ovused+1);
ovbuf[ovused]= 0;
break;
@@ -989,7 +1039,7 @@ static int server_connect(void) {
if (errno == ECONNREFUSED || errno == ENOENT)
syscallerror("uservd daemon is not running - service not available");
if (errno != EINTR)
- syscallerror("unable to connect to uservd daemon: %m");
+ fsyscallerror("unable to connect to uservd daemon: %m");
}
return sfd;
@@ -1022,16 +1072,16 @@ static void server_preparepipes(void) {
assert(!pipepathbuf[PIPEPATHMAXLEN]);
priv_resume();
if (unlink(pipepathbuf) && errno != ENOENT)
- syscallerror("remove any old pipe `%s'",pipepathbuf);
+ fsyscallerror("remove any old pipe `%s'",pipepathbuf);
if (mkfifo(pipepathbuf,0600)) /* permissions are irrelevant */
- syscallerror("create pipe `%s'",pipepathbuf);
+ fsyscallerror("create pipe `%s'",pipepathbuf);
tempfd= open(pipepathbuf,O_RDWR);
- if (tempfd<0) syscallerror("prelim open pipe `%s' for read+write",pipepathbuf);
+ if (tempfd<0) fsyscallerror("prelim open pipe `%s' for read+write",pipepathbuf);
assert(fdsetup[fd].mods & (fdm_read|fdm_write));
fdsetup[fd].pipefd=
open(pipepathbuf, (fdsetup[fd].mods & fdm_read) ? O_WRONLY : O_RDONLY);
- if (fdsetup[fd].pipefd<0) syscallerror("real open pipe `%s'",pipepathbuf);
- if (close(tempfd)) syscallerror("close prelim fd onto pipe `%s'",pipepathbuf);
+ if (fdsetup[fd].pipefd<0) fsyscallerror("real open pipe `%s'",pipepathbuf);
+ if (close(tempfd)) fsyscallerror("close prelim fd onto pipe `%s'",pipepathbuf);
priv_suspend();
}
}
@@ -1046,7 +1096,7 @@ static void server_sendrequest(int argc, char *const *argv) {
request_mbuf.clientpid= getpid();
request_mbuf.serviceuserlen= strlen(serviceuser);
request_mbuf.servicelen= strlen(argv[0]);
- request_mbuf.lognamelen= strlen(logname);
+ request_mbuf.loginnamelen= strlen(loginname);
request_mbuf.spoofed= spoofuser ? 1 : 0;
request_mbuf.cwdlen= cwdbufsize;
request_mbuf.callinguid= spoofuid;
@@ -1065,7 +1115,7 @@ static void server_sendrequest(int argc, char *const *argv) {
xfwrite(&request_mbuf,sizeof(request_mbuf),swfile);
xfwrite(serviceuser,sizeof(*serviceuser)*request_mbuf.serviceuserlen,swfile);
xfwrite(argv[0],sizeof(*argv[0])*request_mbuf.servicelen,swfile);
- xfwrite(logname,sizeof(*logname)*request_mbuf.lognamelen,swfile);
+ xfwrite(loginname,sizeof(*loginname)*request_mbuf.loginnamelen,swfile);
xfwrite(cwdbuf,sizeof(*cwdbuf)*request_mbuf.cwdlen,swfile);
if (ovused>=0) xfwrite(ovbuf,sizeof(*ovbuf)*ovused,swfile);
xfwrite(&spoofgid,sizeof(gid_t),swfile);
@@ -1112,7 +1162,22 @@ static void prepare_asynchsignals(void) {
if (sigaction(SIGALRM,&sig,0)) syscallerror("set up sigalrm handler");
if (!timeout) return;
- if (alarm(timeout)<0) syscallerror("set up timeout alarm");
+ alarm(timeout);
+}
+
+
+static void close_unwanted_pipes(void) {
+ int fd;
+
+ for (fd=0; fd2)
+ if (close(fdsetup[fd].copyfd))
+ if (errno != EBADF)
+ /* EBADF can be induced if cmd line specifies same fd twice */
+ fsyscallerror("close real fd for %d",fd);
+ }
}
static void catdup(const char *which, int from, int to) {
@@ -1128,6 +1193,7 @@ static void connect_pipes(void) {
struct sigaction sig;
char catnamebuf[sizeof(int)*3+30];
int fd, reading;
+ pid_t child;
for (fd=0; fd2)
- if (close(fdsetup[fd].copyfd)) syscallerror("close real fd for %d",fd);
- if (close(fdsetup[fd].pipefd)) syscallerror("close pipe fd for %d",fd);
}
+ close_unwanted_pipes();
}
static void server_sendconfirm(void) {
@@ -1194,7 +1264,7 @@ static void dispose_remaining_pipes(void) {
blocksignals(SIG_BLOCK);
for (fd=0; fd