[comp.sources.d] Perl on Microport 286: can't find library routines

" Maynard) (09/05/89)

Environment: Microport System V/AT (286) v2.4.

I'm trying to build perl, despite the warning about small address space
machines. After adding an #include <signal.h> to util.c to get it to
compile, the link step fails trying to find dup2(), rename(), and
lstat(). I'm not sure what dup2() does. The Configure script found
rename(), but it's not documented in the manual. Looking at the code in
doio.c where lstat() is used, it looks like there's an attempt to avoid
calling it if it's not appropriate, but it flat doesn't exist here.

Help?

-- 
Jay Maynard, EMT-P, K5ZC, PP-ASEL   | Never ascribe to malice that which can
jay@splut.conmicro.com       (eieio)| adequately be explained by stupidity.
{attctc,bellcore}!texbell!splut!jay +----------------------------------------
"The unkindest thing you can do for a hungry man is to give him food." - RAH

chasm@attctc.Dallas.TX.US (Charles Marslett) (09/07/89)

In article <2869@splut.conmicro.com>, jay@splut.conmicro.com (Jay "you ignorant splut!" Maynard) writes:
> 
> I'm trying to build perl, despite the warning about small address space
> machines. After adding an #include <signal.h> to util.c to get it to
> compile, the link step fails trying to find dup2(), rename(), and
> lstat(). I'm not sure what dup2() does. The Configure script found
> rename(), but it's not documented in the manual. Looking at the code in
> doio.c where lstat() is used, it looks like there's an attempt to avoid
> calling it if it's not appropriate, but it flat doesn't exist here.

In bringing up the posted beta copy of perl 3.0 under Interactive's 386/ix
(Version 2.0.1), I ran into the following problems:

   1) Signal.h was required in the file "util.c".
   2) Interactive Unix does not understand "lstat()", so I just wrote a
      message to stderr, and invoked "stat()" instead (probably wrong --
      please correct my patch here!).
   3) Interactive Unix malloc()/realloc()/free() seems to have problems
      freeing the right stuff, so I used the included malloc.c file (and
      incidentally declared the saferealloc() and safemalloc() functions
      to be "char *" and safefree to be "void" in handy.h and util.c.
   4) The base Makefile deletes x2p/Makefile before it invokes it to
      clean x2p (using the "make realclean" option).

It now passes the test suite.

You may want to do the same or similar changes (and you may not)...

As far as dup2() and rename(), they may not be provided -- rename can be
built out of a link() and an unlink() call sequence, but I don't remember
the details about dup2().

> Help?

Maybe?

> -- 
> Jay Maynard, EMT-P, K5ZC, PP-ASEL   | Never ascribe to malice that which can
> jay@splut.conmicro.com       (eieio)| adequately be explained by stupidity.
> {attctc,bellcore}!texbell!splut!jay +----------------------------------------
===========================================================================
Charles Marslett
STB Systems, Inc.  <== Apply all standard disclaimers
Wordmark Systems   <== No disclaimers required -- that's just me
chasm@attctc.dallas.tx.us

guy@auspex.auspex.com (Guy Harris) (09/08/89)

>   2) Interactive Unix does not understand "lstat()", so I just wrote a
>      message to stderr, and invoked "stat()" instead (probably wrong --
>      please correct my patch here!).

Why bother with the message to "stderr"?  Elsewhere in "perl", the
#ifdef symbol SYMLINK is used to control code that is to be included
only on systems that understand standard symlinks, including support for
"lstat()".  It appears that it was omitted in one case in "doio.c".  Try
this:

*** doio.c.dist	Tue Sep  5 13:16:55 1989
--- doio.c	Tue Sep  5 13:23:38 1989
***************
*** 457,465 ****
--- 457,467 ----
      else {
  	str_sset(statname,ary->ary_array[sp]);
  	statstab = Nullstab;
+ #ifdef SYMLINK
  	if (arg->arg_type == O_LSTAT)
  	    i = lstat(str_get(statname),&statcache);
  	else
+ #endif
  	    i = stat(str_get(statname),&statcache);
  	if (i < 0)
  	    max = 0;

>As far as dup2() and rename(), they may not be provided -- rename can be
>built out of a link() and an unlink() call sequence,

And is, in fact, appears to be so built if the #ifdef symbol RENAME
isn't defined.  The Configure script should arrange to define this iff
"rename" appears in your "libc"; presumably, something went wrong.  Try
manually changing the "#define RENAME" line to "#undef RENAME" in
"config.h".

>but I don't remember the details about dup2().

The problem here is that "dup2()" came with V7 and was inherited by BSD,
but wasn't picked up by S3/S5.  It did end up in POSIX, though, and S5R3
picked it up from there.  If you have an 80386-based machine, you
presumably have S5R3, so this is not a problem; if you have an
80286-based machine, as I think the original poster did, your UNIX is
probably S5R2-based, so you lose.  You can consider this more of the
"this may not work on 16-bit machines" item, if you want....

However, if you don't have "dup2()", you probably have "fcntl()", and
you can use "close()" followed by "fcntl(..., F_DUPFD, ...)" to achieve
the same effect.  In fact, on all modern UNIXes (4.xBSD for x >= 2,
System V Release x for x >= 3), you have both.  Try the following patch:

*** util.c.dist	Tue Sep  5 13:17:27 1989
--- util.c	Thu Sep  7 10:37:09 1989
***************
*** 12,17 ****
--- 12,21 ----
  #include "perl.h"
  #include "errno.h"
  
+ #ifdef FCNTL
+ #  include <fcntl.h>
+ #endif
+ 
  #ifdef VARARGS
  #  include <varargs.h>
  #endif
***************
*** 1001,1008 ****
  	this = !this;	/* swap this and that */
  	that = !this;
  	close(p[that]);
! 	if (p[this] != (*mode == 'r')) {
! 	    dup2(p[this], *mode == 'r');
  	    close(p[this]);
  	}
  	if (doexec) {
--- 1005,1017 ----
  	this = !this;	/* swap this and that */
  	that = !this;
  	close(p[that]);
! 	if (p[this] != this) {
! #ifdef FCNTL
! 	    close(this);
! 	    fcntl(p[this], F_DUPFD, this);
! #else
! 	    dup2(p[this], this);
! #endif
  	    close(p[this]);
  	}
  	if (doexec) {

(untested, but I think it should work - it assumes that "*mode" is
either equal to 'r' or 'w', which appears to be the case for all calls
to "mypopen").

Note: "#include <fcntl.h>" is correct, even for 4.3BSD, and I think for
4.2BSD as well; ignore the manual page's insistence that you include
<sys/file.h>, it leads to less portable code which is no better than the
more-portable code.

allbery@NCoast.ORG (Brandon S. Allbery) (09/08/89)

dup2() under System V unixes:

	#include <fcntl.h>

	dup2(fd1, fd2)
		int fd1, fd2;
	{
		(void) close(fd2);
		return fcntl(fd1, F_DUPFD, fd2);
	}

++Brandon
-- 
Brandon S. Allbery, moderator of comp.sources.misc	     allbery@NCoast.ORG
uunet!hal.cwru.edu!ncoast!allbery		    ncoast!allbery@hal.cwru.edu
"Why do trans-atlantic transfers take so long?"
"Electrons don't swim very fast."  -john@minster.york.ac.uk and whh@PacBell.COM

guy@auspex.auspex.com (Guy Harris) (09/10/89)

>dup2() under System V unixes:

(System V prior to R3, anyway; "dup2()" under S5R3 and later is just
"dup2()", it's already in "libc".)

Actually, to be strictly correct, you should do a bit more (1003.1 says
that "dup2" shall be equivalent to the sequence you give, except for
some extra checks it lists, which are done here):

#include <fcntl.h>
#include <sys/param.h>
#include <errno.h>

int
dup2(fildes, fildes2)
	int fildes, fildes2;
{
	/*
	 * Check whether "fildes" is a valid file descriptor:
	 * "If 'fildes' is not a valid file descriptor, 'dup2()'
	 * shall fail and not close 'fildes2'."
	 */
	if (fcntl(fildes, F_GETFL, 0) == -1)
		return -1;	/* "fcntl" set "errno" correctly */

	/*
	 * Check whether "fildes2" is within the correct range:
	 * "If 'fildes2' is less than zero or greater than
	 * {OPEN_MAX}, the 'dup2()' function shall return -1 and
	 * 'errno' shall be set to [EBADF]."
	 * No, don't use "ulimit" to get the maximum valid file
	 * descriptor; that first appeared in S5R3, but S5R3
	 * already *has* a "dup2()".
	 */
	if (fildes2 < 0 || fildes2 >= NOFILE) {
		errno = EBADF;
		return -1;
	}

	/*
	 * Check whether "fildes" is equal to "fildes2":
	 * "If 'fildes' is a valid file descriptor and is equal
	 * to 'fildes2', the 'dup2()' function shall return
	 * 'fildes2' without closing it."
	 */
	if (fildes == fildes2)
		return 0;

	/*
	 * Now do the real work:
	 * "The call 'fid = dup2 (fildes, fildes2);' shall be equivalent
	 * to 'close (fildes2); fid = fcntl (fildes, F_DUPFD, fildes2);'
	 * except for the following:" where "the following" are the
	 * cases listed above.
	 */
	(void) close(fildes2);
	return fcntl(fildes, F_DUPFD, fildes2);
}

arnold@mathcs.emory.edu (Arnold D. Robbins {EUCC}) (09/12/89)

What do you know? Break out the champagne, I caught Guy in a mistake! :-)

In article <2432@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
>	/*
>	 * Check whether "fildes" is equal to "fildes2":
>	 * "If 'fildes' is a valid file descriptor and is equal
>	 * to 'fildes2', the 'dup2()' function shall return
>	 * 'fildes2' without closing it."
>	 */
>	if (fildes == fildes2)
>		return 0;

That should really be

	if (filedes == filedes2)
		return filedes2;

I guess this shows it pays to read the comments occasionally too. :-)

[inews fodder]
[inews fodder]
[inews fodder]
[inews fodder]
-- 
Arnold Robbins -- Emory University Computing Center | Laundry increases
DOMAIN: arnold@unix.cc.emory.edu		    | exponentially in the
UUCP: gatech!emoryu1!arnold  PHONE: +1 404 727-7636 | number of children.
BITNET: arnold@emoryu1	     FAX:   +1 404 727-2599 |     -- Miriam Hartholz