Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: support for BeOS



Well, I have zsh-3.1.6 in (at least some kind of) working state under BeOS
R4.5, and I'm attaching the patches I've done so far.

BeOS is supposed to be POSIX.1 compliant, but as of yet several features
are missing, and others have bugs.  In particular:

 - there is not sufficient support yet for job control; in particular,
   tcsetpgrp() is there, but does not work.

 - kill(pid, 0), where pid does not exist, sets errno to EINVAL rather than
   ESRCH.

 - sigsuspend() is broken, in some manner.  It looks like it does apply the
   temporary signal mask, and sets whatever internal flag to indicate a
   signal's arrival, but doesn't actually _deliver_ the signal.  The
   sigsuspend returns, but the handler wasn't called, nor was the internal
   flag cleared, so subsequent sigsuspend's still think there's a signal to
   deliver, but it can't, so it just loops.

 - getpwnam() is faked, so to speak.  Since the OS is not multiuser (yet),
   there's only one user, and only one corresponding passwd entry.  Calling
   getpwnam(), with as far as I can tell _any_ string, is always
   successful, returning that one/only passwd entry.

 - link() doesn't work, as the filesystem doesn't support hard links (yet).
   Similarly, ln doesn't work without -s.

 - select() and fd_set are defined in <sys/socket.h>


Here's what I did to try and work around them:

 - in signals.c, used sigprocmask/pause/sigprocmask to emulate the
   sigsuspend.

 - in signals.c and jobs.c, where it checked for errno=ESRCH, also checked
   for errno=EINVAL when sig=0.

 - in options.c, disabled option "monitor" if job control isn't supported,
   and disabled "cdablevars" if getpwnam() is faked (else it never reports
   "command not found", and instead just cds to $HOME).

 - in system.h, include <sys/socket.h> if necessary, and disable job
   control if a working tcsetpgrp() isn't found.

 - in hist.c, tried to handle history file locking when link() doesn't
   work.  I did what seemed to make sense at the time, but I'm really not
   sure it's sufficient for good locking.

 - in Makefile, used "cp" for "make install" when "ln" isn't available.

I added tests for the problems to configure.in (and the corresponding
defines to acconfig.h), rather than just #ifdef'ing for BEOS, so that the
workarounds are not used when the problems are fixed (assumedly) in later
releases.  I tried very hard to code the tests so that they won't fail
incorrecly under other OS's, and I've tested them successfully under SunOS
4.1.1, 5.4, and 5.6; AIX 4.1.5, 4.2.1, and 4.3.2; linux 2.2.3; and Irix
6.5, but that's all I have access to.  I also added an AC_PROG_LN macro to
aclocal.m4, for configure.in to test for Makefile's ln, as that seemed like
the easiest way to add it.

In any case, there it is.  I'm almost certain there are other POSIX
incompatibilities in BeOS, but those are the only ones I've come across so
far with zsh.  Unfortunately, as the makefile said, "zsh test suite not
available yet" so I couldn't do a big test.  At least I have _some_ of my
favorite shell now, and I'm not bitching at bash everytime I sit down at
Be. :)

-- 
Will Day     <PGP mail preferred>     OIT / O&E / Technical Support
willday@xxxxxxxxxxxxxxxxxx            Georgia Tech, Atlanta 30332-0715
  -> Opinions expressed are mine alone and do not reflect OIT policy <-
Those who would give up essential Liberty, to purchase a little temporary
Safety, deserve neither Liberty nor Safety.
    Benjamin Franklin, Pennsylvania Assembly, Nov. 11, 1755
diff -rC2 zsh-3.1.6.orig/Src/Makefile.in zsh-3.1.6/Src/Makefile.in
*** zsh-3.1.6.orig/Src/Makefile.in	Tue Jun 29 12:39:30 1999
--- zsh-3.1.6/Src/Makefile.in	Wed Aug  4 01:20:34 1999
***************
*** 36,39 ****
--- 36,40 ----
  sdir_top        = @top_srcdir@
  INSTALL         = @INSTALL@
+ LN		= @LN@
  
  @DEFS_MK@
***************
*** 164,171 ****
  	if test -f $(bindir)/zsh; then \
  	    rm -f $(bindir)/zsh.old; \
! 	    ln $(bindir)/zsh $(bindir)/zsh.old; \
  	else :; fi
  	rm -f $(bindir)/zsh.new
! 	ln $(bindir)/zsh-$(VERSION) $(bindir)/zsh.new
  	mv $(bindir)/zsh.new $(bindir)/zsh
  
--- 165,172 ----
  	if test -f $(bindir)/zsh; then \
  	    rm -f $(bindir)/zsh.old; \
! 	    $(LN) $(bindir)/zsh $(bindir)/zsh.old; \
  	else :; fi
  	rm -f $(bindir)/zsh.new
! 	$(LN) $(bindir)/zsh-$(VERSION) $(bindir)/zsh.new
  	mv $(bindir)/zsh.new $(bindir)/zsh
  
diff -rC2 zsh-3.1.6.orig/Src/hist.c zsh-3.1.6/Src/hist.c
*** zsh-3.1.6.orig/Src/hist.c	Sat Jul 31 07:53:28 1999
--- zsh-3.1.6/Src/hist.c	Wed Aug  4 01:20:34 1999
***************
*** 1948,1951 ****
--- 1948,1952 ----
  	char *tmpfile, *lockfile;
  
+ #ifdef HAVE_LINK
  	tmpfile = zalloc(len + 10 + 1);
  	sprintf(tmpfile, "%s.%ld", fn, (long)mypid);
***************
*** 1974,1977 ****
--- 1975,1993 ----
  	unlink(tmpfile);
  	free(tmpfile);
+ #else /* not HAVE_LINK */
+ 	lockfile = zalloc(len + 5 + 1);
+ 	sprintf(lockfile, "%s.LOCK", fn);
+ 	while ((fd = open(lockfile, O_CREAT|O_EXCL, 0644)) < 0) {
+ 		if (errno == EEXIST) continue;
+ 		else if (keep_trying) {
+ 		    if (time(NULL) - sb.st_mtime < 10)
+ 			sleep(1);
+ 		    continue;
+ 		}
+ 		lockhistct--;
+ 		break;
+ 	}
+ 	free(lockfile);
+ #endif /* HAVE_LINK */
      }
      return ct != lockhistct;
diff -rC2 zsh-3.1.6.orig/Src/jobs.c zsh-3.1.6/Src/jobs.c
*** zsh-3.1.6.orig/Src/jobs.c	Mon Jul  5 05:36:37 1999
--- zsh-3.1.6/Src/jobs.c	Wed Aug  4 01:20:35 1999
***************
*** 836,840 ****
--- 836,844 ----
      /* child_block() around this loop in case #ifndef WNOHANG */
      child_block();		/* unblocked in child_suspend() */
+ #ifdef BROKEN_KILL_ESRCH
+     while (!errflag && (kill(pid, 0) >= 0 || (errno != ESRCH && errno != EINVAL))) {
+ #else /* not BROKEN_KILL_ESRCH */
      while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) {
+ #endif /* BROKEN_KILL_ESRCH */
  	if (first)
  	    first = 0;
diff -rC2 zsh-3.1.6.orig/Src/options.c zsh-3.1.6/Src/options.c
*** options.c.orig	Fri Jul 16 03:47:19 1999
--- options.c	Thu Aug  5 00:44:59 1999
***************
*** 654,657 ****
--- 654,665 ----
  	setgid(getgid());
  #endif /* HAVE_SETUID */
+ #ifndef JOB_CONTROL
+     } else if(optno == MONITOR && value) {
+ 	    return -1;
+ #endif /* not JOB_CONTROL */
+ #ifdef GETPWNAM_FAKED
+     } else if(optno == CDABLEVARS && value) {
+ 	    return -1;
+ #endif /* GETPWNAM_FAKED */
      }
      opts[optno] = value;
diff -rC2 zsh-3.1.6.orig/Src/signals.c zsh-3.1.6/Src/signals.c
*** zsh-3.1.6.orig/Src/signals.c	Thu Jul  1 07:37:16 1999
--- zsh-3.1.6/Src/signals.c	Wed Aug  4 16:40:37 1999
***************
*** 327,330 ****
--- 327,333 ----
  #ifdef POSIX_SIGNALS
      sigset_t set;
+ #ifdef BROKEN_POSIX_SIGSUSPEND
+     sigset_t oset;
+ #endif /* BROKEN_POSIX_SIGSUSPEND */
  
      sigfillset(&set);
***************
*** 333,338 ****
      if (sig2)
          sigdelset(&set, sig2);
      ret = sigsuspend(&set);
! #else
  # ifdef BSD_SIGNALS
      sigset_t set;
--- 336,347 ----
      if (sig2)
          sigdelset(&set, sig2);
+ #ifdef BROKEN_POSIX_SIGSUSPEND
+     sigprocmask(SIG_SETMASK, &set, &oset);
+     pause();
+     sigprocmask(SIG_SETMASK, &oset, NULL);
+ #else /* not BROKEN_POSIX_SIGSUSPEND */
      ret = sigsuspend(&set);
! #endif /* BROKEN_POSIX_SIGSUSPEND */
! #else /* not POSIX_SIGNALS */
  # ifdef BSD_SIGNALS
      sigset_t set;
***************
*** 602,605 ****
--- 611,617 ----
      for (pn = jn->procs; pn; pn = pn->next)
          if ((err = kill(pn->pid, sig)) == -1 && errno != ESRCH)
+ #ifdef BROKEN_KILL_ESRCH
+           if(errno != EINVAL || sig != 0)
+ #endif /* BROKEN_KILL_ESRCH */
              return -1;
      return err;
diff -rC2 zsh-3.1.6.orig/Src/system.h zsh-3.1.6/Src/system.h
*** zsh-3.1.6.orig/Src/system.h	Sun May 16 11:20:52 1999
--- zsh-3.1.6/Src/system.h	Wed Aug  4 01:20:35 1999
***************
*** 268,271 ****
--- 268,273 ----
  #  include <sys/select.h>
  # endif
+ #elif defined(SELECT_IN_SYS_SOCKET_H)
+ # include <sys/socket.h>
  #endif
  
***************
*** 614,615 ****
--- 616,622 ----
  #endif
  #endif
+ 
+ /* Can't support job control without working tcsetgrp() */
+ #ifdef BROKEN_TCSETPGRP
+ #undef JOB_CONTROL
+ #endif /* BROKEN_TCSETPGRP */
diff -rC2 zsh-3.1.6.orig/acconfig.h zsh-3.1.6/acconfig.h
*** zsh-3.1.6.orig/acconfig.h	Mon Jun 14 10:08:10 1999
--- zsh-3.1.6/acconfig.h	Wed Aug  4 01:22:54 1999
***************
*** 199,202 ****
--- 199,205 ----
  #undef HAVE_IOCTL_PROTO
  
+ /* Define to 1 if select() is defined in <sys/socket.h>, ie BeOS R4.51*/
+ #undef SELECT_IN_SYS_SOCKET_H
+ 
  /* Define to 1 if system has working FIFO's */
  #undef HAVE_FIFOS
***************
*** 216,219 ****
--- 219,237 ----
  /* Define to 1 if /bin/sh does not interpret \ escape sequences */
  #undef SH_USE_BSD_ECHO
+ 
+ /* Define to 1 if system has working link() */
+ #undef HAVE_LINK
+ 
+ /* Define to 1 if kill(pid, 0) doesn't return ESRCH, ie BeOS R4.51 */
+ #undef BROKEN_KILL_ESRCH
+ 
+ /* Define to 1 if sigsuspend() is broken, ie BeOS R4.51 */
+ #undef BROKEN_POSIX_SIGSUSPEND
+ 
+ /* Define to 1 if getpwnam() is faked, ie BeOS R4.51 */
+ #undef GETPWNAM_FAKED
+ 
+ /* Define to 1 if tcsetpgrp() doesn't work, ie BeOS R4.51 */
+ #undef BROKEN_TCSETPGRP
  
  /* Define to 1 if an underscore has to be prepended to dlsym() argument */
diff -rC2 zsh-3.1.6.orig/aclocal.m4 zsh-3.1.6/aclocal.m4
*** zsh-3.1.6.orig/aclocal.m4	Tue Jul 27 12:13:42 1999
--- zsh-3.1.6/aclocal.m4	Wed Aug  4 01:22:54 1999
***************
*** 53,55 ****
--- 53,77 ----
  ])
  
+ AC_DEFUN(AC_PROG_LN,
+ [AC_MSG_CHECKING(whether ln works)
+ AC_CACHE_VAL(ac_cv_prog_LN,
+ [rm -f conftestdata conftestlink
+ echo > conftestdata
+ if ln conftestdata conftestlink 2>/dev/null
+ then
+   rm -f conftestdata conftestlink
+   ac_cv_prog_LN="ln"
+ else
+   rm -f conftestdata
+   ac_cv_prog_LN="cp"
+ fi])dnl
+ LN="$ac_cv_prog_LN"
+ if test "$ac_cv_prog_LN" = "ln"; then
+   AC_MSG_RESULT(yes)
+ else
+   AC_MSG_RESULT(no)
+ fi
+ AC_SUBST(LN)dnl
+ ])
+ 
  builtin(include, aczsh.m4)
diff -rC2 zsh-3.1.6.orig/configure.in zsh-3.1.6/configure.in
*** configure.in.orig	Tue Jul 27 11:09:40 1999
--- configure.in	Wed Aug  4 20:47:27 1999
***************
*** 381,384 ****
--- 381,385 ----
  AC_PROG_INSTALL             dnl Check for BSD compatible `install'
  AC_PROG_AWK                 dnl Check for mawk,gawk,nawk, then awk.
+ AC_PROG_LN                  dnl Check for working ln, for "make install"
  AC_CHECK_PROGS([YODL], [yodl], [:])
  
***************
*** 1047,1050 ****
--- 1048,1065 ----
  fi
  
+ dnl -------------------
+ dnl select() defined in <sys/socket.h>, ie BeOS R4.51
+ dnl -------------------
+ if test $ac_cv_header_sys_select_h != yes; then
+   AC_CACHE_CHECK(for select() in <sys/socket.h>,
+   zsh_cv_header_socket_h_select_proto,
+   [AC_TRY_COMPILE([#include <sys/socket.h>], [fd_set fd;],
+   zsh_cv_header_socket_h_select_proto=yes, 
+   zsh_cv_header_socket_h_select_proto=no)])
+   if test $zsh_cv_header_socket_h_select_proto = yes; then
+     AC_DEFINE(SELECT_IN_SYS_SOCKET_H)
+   fi
+ fi
+ 
  dnl -----------
  dnl named FIFOs
***************
*** 1098,1101 ****
--- 1113,1266 ----
  if test $zsh_cv_prog_sh_echo_escape = no; then
    AC_DEFINE(SH_USE_BSD_ECHO)
+ fi
+ 
+ dnl -----------
+ dnl test for whether link() works
+ dnl for instance, BeOS R4.51 doesn't support hard links yet
+ dnl -----------
+ AC_CACHE_CHECK(if link() works,
+ zsh_cv_sys_link,
+ [AC_TRY_RUN([
+ #include <unistd.h>
+ #include <fcntl.h>
+ main()
+ {
+     int ret;
+     char *tmpfile, *newfile;
+     tmpfile="/tmp/zsh.linktest$$";
+     newfile="/tmp/zsh.linktest2$$";
+     unlink(tmpfile);
+     unlink(newfile);
+     if(creat(tmpfile, 0644) < 0)
+ 	exit(1);
+     ret = link(tmpfile, newfile);
+     unlink(tmpfile);
+     unlink(newfile);
+     exit(ret<0);
+ }
+ ],
+   zsh_cv_sys_link=yes,
+   zsh_cv_sys_link=no,
+   zsh_cv_sys_link=yes)])
+ if test $zsh_cv_sys_link = yes; then
+   AC_DEFINE(HAVE_LINK)
+ fi
+ 
+ dnl -----------
+ dnl test for whether kill(pid, 0) where pid doesn't exit
+ dnl should set errno to ESRCH, but some like BeOS R4.51 set to EINVAL
+ dnl -----------
+ AC_CACHE_CHECK(if kill(pid, 0) returns ESRCH correctly,
+ zsh_cv_sys_killesrch,
+ [AC_TRY_RUN([
+ #include <unistd.h>
+ #include <signal.h>
+ #include <errno.h>
+ main()
+ {
+     int pid, ret;
+     pid=getpid() + 10000;
+     ret=kill(pid, 0);
+     exit(ret<0 && errno!=ESRCH);
+ }
+ ],
+   zsh_cv_sys_killesrch=yes,
+   zsh_cv_sys_killesrch=no,
+   zsh_cv_sys_killesrch=yes)])
+ if test $zsh_cv_sys_killesrch = no; then
+   AC_DEFINE(BROKEN_KILL_ESRCH)
+ fi
+ 
+ dnl -----------
+ dnl if POSIX, test for working sigsuspend().
+ dnl for instance, BeOS R4.51 is broken.
+ dnl -----------
+ if test $signals_style=POSIX_SIGNALS; then
+     AC_CACHE_CHECK(if POSIX sigsuspend() works,
+     zsh_cv_sys_sigsuspend,
+     [AC_TRY_RUN([
+ #include <signal.h>
+ #include <unistd.h>
+ int child=0;
+ void handler(sig)
+     int sig;
+ {if(sig==SIGCHLD) child=1;}
+ main() {
+     struct sigaction act;
+     sigset_t set;
+     int pid, ret;
+     act.sa_handler = &handler;
+     sigfillset(&act.sa_mask);
+     act.sa_flags = 0;
+     sigaction(SIGCHLD, &act, 0);
+     sigfillset(&set);
+     sigprocmask(SIG_SETMASK, &set, 0);
+     pid=fork();
+     if(pid==0) return 0;
+     if(pid>0) {
+     sigemptyset(&set);
+         ret=sigsuspend(&set);
+         exit(child==0);
+     }
+ }
+ ],
+       zsh_cv_sys_sigsuspend=yes,
+       zsh_cv_sys_sigsuspend=no,
+       zsh_cv_sys_sigsuspend=yes)])
+     if test $zsh_cv_sys_sigsuspend = no; then
+       AC_DEFINE(BROKEN_POSIX_SIGSUSPEND)
+     fi
+ fi
+ 
+ dnl -----------
+ dnl if found tcsetpgrp, test to see if it actually works
+ dnl for instance, BeOS R4.51 does not support it yet
+ dnl -----------
+ if test $ac_cv_func_tcsetpgrp=yes; then
+     AC_CACHE_CHECK(if tcsetpgrp() actually works,
+     zsh_cv_sys_tcsetpgrp,
+     [AC_TRY_RUN([
+ #include <sys/types.h>
+ #include <unistd.h>
+ main() {
+     int ret;
+     ret=tcsetpgrp(0, tcgetpgrp(0));
+     exit(ret<0);
+ }
+ ],
+       zsh_cv_sys_tcsetpgrp=yes,
+       zsh_cv_sys_tcsetpgrp=no,
+       zsh_cv_sys_tcsetpgrp=yes)])
+     if test $zsh_cv_sys_tcsetpgrp = no; then
+       AC_DEFINE(BROKEN_TCSETPGRP)
+     fi
+ fi
+ 
+ dnl -----------
+ dnl test for faked getpwnam() entry, ie a single entry returned for any username
+ dnl for instance, BeOS R4.51 is not multiuser yet, and fakes getpwnam()
+ dnl test by looking up two usernames that shouldn't succeed, and compare entry
+ dnl -----------
+ if test $ac_cv_func_getpwnam=yes; then
+     AC_CACHE_CHECK(if getpwnam() is faked,
+     zsh_cv_sys_getpwnam_faked,
+     [AC_TRY_RUN([
+ #include <pwd.h>
+ main() {
+     struct passwd *pw1, *pw2;
+     char buf[1024];
+     sprintf(buf, "%d:%d", getpid(), rand());
+     pw1=getpwnam(buf);
+     sprintf(buf, "%d:%d", rand(), getpid());
+     pw2=getpwnam(buf);
+     exit(pw1!=0 && pw2!=0 && !strcmp(pw1->pw_name, pw2->pw_name));
+ }
+ ],
+       zsh_cv_sys_getpwnam_faked=no,
+       zsh_cv_sys_getpwnam_faked=yes,
+       zsh_cv_sys_getpwnam_faked=no)])
+     if test $zsh_cv_sys_getpwnam_faked = yes; then
+       AC_DEFINE(GETPWNAM_FAKED)
+     fi
  fi
  

Attachment: pgp7WMJpW5vHk.pgp
Description: PGP signature



Messages sorted by: Reverse Date, Date, Thread, Author