need xterm to log to a file

Thomas Dickey dickey@his.com
Fri Dec 10 16:26:00 GMT 2004


On Fri, 10 Dec 2004, Christopher Faylor wrote:

> On Fri, Dec 10, 2004 at 06:50:11AM -0500, Thomas Dickey wrote:
>> I see it's a (usually minor) error in xterm, which runs into a cygwin bug.
>> The function creat_as() does a fork/wait, assuming that it has to strip
>> off the setuid/setgid privilges.  That's not needed in cygwin, but the
>> fork/wait doesn't work (looks like a cygwin bug).  I'll add a fix in #198
>> so it will work for cygwin.
>
> How about saying "cygwin bug" a few more times?  I love it when people sling
> that term around while providing no details.

hmm - saying it twice was redundant.

I did point to the particular function which is hanging (creat_as, in 
xterm's misc.c).  It does a fork, setuid/getuid and then an open.  (The
imake configuration doesn't give enough detail to ensure that I can 
determine at that point if the setuid is needed, and it hasn't been an 
issue before now).

Now bear in mind that xterm normally runs as two processes.  This fork
is a third process, used to ensure that a file is created as the original
user (just in case xterm was running setuid).

> If fork/wait didsn't work it would be a serious problem with repercussions
> for every package in the cygwin distribution and it would certainly be
> one that we'd want to fix.

;-)

> Can you be more precise in detailing this problem?

Not much.   gdb's of no use here, so I added some traces to see which
lines are executed.  It doesn't appear to return from the waitpid, but
on the child side is last seen heading into the _exit(0).  Here's the
relevant section of code (with the unused ifdef's removed):

int
creat_as(int uid, int gid, Boolean append, char *pathname, int mode)
{
     int fd;
     int pid;
     int retval = 0;
     int childstat = 0;

     pid = fork();
     switch (pid) {
     case 0:			/* child */
 	setgid(gid);
 	setuid(uid);
 	fd = open(pathname,
 		  O_WRONLY | O_CREAT | (append ? O_APPEND : O_EXCL),
 		  mode);
 	if (fd >= 0) {
 	    close(fd);
 	    _exit(0);		<==== child gets here
 	} else
 	    _exit(1);
 	/* NOTREACHED */
     case -1:			/* error */
 	return retval;
     default:			/* parent */
 				<==== parent gets here
 	while (waitpid(pid, &childstat, 0) < 0) {
 	    if (errno == EINTR)
 		continue;
 	    break;
 	}
 	if (WIFEXITED(childstat))
 	    retval = 1;
 	return retval;
     }
}

As for why it's hanging, I suppose your guess might be better than mine.

-- 
Thomas E. Dickey
http://invisible-island.net
ftp://invisible-island.net



More information about the Cygwin-xfree mailing list