/* -*-C-*- $Id: ux.c,v 1.20 2000/12/05 21:23:48 cph Exp $ Copyright (c) 1990-2000 Massachusetts Institute of Technology This program 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 (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ux.h" void DEFUN (UX_prim_check_errno, (name), enum syscall_names name) { if (errno != EINTR) error_system_call (errno, name); deliver_pending_interrupts (); } #ifdef HAVE_TERMIOS_H int DEFUN (UX_terminal_get_state, (fd, s), int fd AND Ttty_state * s) { return ((((tcgetattr (fd, (& (s -> tio)))) < 0) #ifdef __HPUX__ || ((UX_ioctl (fd, TIOCGLTC, (& (s -> ltc)))) < 0) #endif ) ? (-1) : 0); } int DEFUN (UX_terminal_set_state, (fd, s), int fd AND Ttty_state * s) { return ((((tcsetattr (fd, TCSANOW, (& (s -> tio)))) < 0) #ifdef __HPUX__ || ((UX_ioctl (fd, TIOCSLTC, (& (s -> ltc)))) < 0) #endif ) ? (-1) : 0); } #else /* not HAVE_TERMIOS_H */ #ifdef HAVE_TERMIO_H int DEFUN (UX_terminal_get_state, (fd, s), int fd AND Ttty_state * s) { return ((((UX_ioctl (fd, TCGETA, (& (s -> tio)))) < 0) #ifdef HAVE_STRUCT_LTCHARS || ((UX_ioctl (fd, TIOCGLTC, (& (s -> ltc)))) < 0) #endif ) ? (-1) : 0); } int DEFUN (UX_terminal_set_state, (fd, s), int fd AND Ttty_state * s) { return ((((UX_ioctl (fd, TCSETA, (& (s -> tio)))) < 0) #ifdef HAVE_STRUCT_LTCHARS || ((UX_ioctl (fd, TIOCSLTC, (& (s -> ltc)))) < 0) #endif ) ? (-1) : 0); } int DEFUN (UX_tcdrain, (fd), int fd) { return (UX_ioctl (fd, TCSBRK, 1)); } int DEFUN (UX_tcflush, (fd, queue_selector), int fd AND int queue_selector) { return (UX_ioctl (fd, TCFLSH, queue_selector)); } #else /* not HAVE_TERMIO_H */ #ifdef HAVE_SGTTY_H int DEFUN (UX_terminal_get_state, (fd, s), int fd AND Ttty_state * s) { return ((((UX_ioctl (fd, TIOCGETP, (& (s -> sg)))) < 0) || ((UX_ioctl (fd, TIOCGETC, (& (s -> tc)))) < 0) #ifdef HAVE_STRUCT_LTCHARS || ((UX_ioctl (fd, TIOCGLTC, (& (s -> ltc)))) < 0) #endif || ((UX_ioctl (fd, TIOCLGET, (& (s -> lmode)))) < 0)) ? (-1) : 0); } int DEFUN (UX_terminal_set_state, (fd, s), int fd AND Ttty_state * s) { return ((((UX_ioctl (fd, TIOCSETN, (& (s -> sg)))) < 0) || ((UX_ioctl (fd, TIOCSETC, (& (s -> tc)))) < 0) #ifdef HAVE_STRUCT_LTCHARS || ((UX_ioctl (fd, TIOCSLTC, (& (s -> ltc)))) < 0) #endif || ((UX_ioctl (fd, TIOCLSET, (& (s -> lmode)))) < 0)) ? (-1) : 0); } int DEFUN (UX_tcdrain, (fd), int fd) { /* BSD provides no such feature -- pretend it worked. */ return (0); } int DEFUN (UX_tcflush, (fd, queue_selector), int fd AND int queue_selector) { /* Losing BSD always flushes input and output together. */ int zero = 0; return (UX_ioctl (fd, TIOCFLUSH, (&zero))); } #endif /* HAVE_SGTTY_H */ #endif /* HAVE_TERMIO_H */ #endif /* HAVE_TERMIOS_H */ #ifdef SLAVE_PTY_P int DEFUN (UX_setup_slave_pty, (fd), int fd) { return (((ioctl (fd, I_PUSH, "ptem")) == 0) && ((ioctl (fd, I_PUSH, "ldterm")) == 0) #if !defined(sgi) && !defined(__sgi) && (((ioctl (fd, I_FIND, "ttcompat")) != 0) || ((ioctl (fd, I_PUSH, "ttcompat")) == 0)) #endif ); } #endif #ifdef EMULATE_GETPGRP pid_t DEFUN_VOID (UX_getpgrp) { return (getpgrp (getpid ())); } #endif #ifdef EMULATE_SETSID pid_t DEFUN_VOID (UX_setsid) { #ifdef TIOCNOTTY int fd = (UX_open ("/dev/tty", O_RDWR, 0)); if (fd >= 0) { UX_ioctl (fd, TIOCNOTTY, 0); UX_close (fd); } #endif return (setpgrp (0, 0)); } #endif #ifdef EMULATE_SETPGID int DEFUN (UX_setpgid, (pid, pgid), pid_t pid AND pid_t pgid) { errno = ENOSYS; return (-1); } #endif #ifdef EMULATE_CTERMID char * DEFUN (UX_ctermid, (s), char * s) { static char result [] = "/dev/tty"; if (s == 0) return (result); strcpy (s, result); return (s); } #endif #ifdef EMULATE_KILL int DEFUN (UX_kill, (pid, sig), pid_t pid AND int sig) { return ((pid >= 0) ? (kill (pid, sig)) : (killpg ((-pid), sig))); } #endif #ifdef EMULATE_TCGETPGRP pid_t DEFUN (UX_tcgetpgrp, (fd), int fd) { #ifdef TIOCGPGRP pid_t pgrp_id; return (((UX_ioctl (fd, TIOCGPGRP, (&pgrp_id))) < 0) ? (-1) : pgrp_id); #else errno = ENOSYS; return (-1); #endif } #endif #ifdef EMULATE_TCSETPGRP int DEFUN (UX_tcsetpgrp, (fd, pgrp_id), int fd AND pid_t pgrp_id) { #ifdef TIOCSPGRP return (UX_ioctl (fd, TIOCSPGRP, (&pgrp_id))); #else errno = ENOSYS; return (-1); #endif } #endif #ifdef EMULATE_GETCWD char * DEFUN (UX_getcwd, (buffer, length), char * buffer AND size_t length) { char internal_buffer [MAXPATHLEN + 2]; char * collection_buffer; size_t collection_length; if (length <= 0) { errno = EINVAL; return (0); } /* Allocate the buffer if needed. */ if (buffer == 0) { buffer = (UX_malloc (length)); if (buffer == 0) { errno = ENOMEM; return (0); } } if (length >= (sizeof (internal_buffer))) { collection_buffer = buffer; collection_length = length; } else { collection_buffer = internal_buffer; collection_length = (sizeof (internal_buffer)); } #ifdef HAVE_GETWD if ((getwd (collection_buffer)) == 0) { errno = EACCES; return (0); } #else /* not HAVE_GETWD */ { /* Invoke `pwd' and fill the buffer with its output. */ FILE * stream = (popen ("pwd", "r")); char * scan_buffer = collection_buffer; if (stream == 0) { errno = EACCES; return (0); } fgets (collection_buffer, collection_length, stream); pclose (stream); while (1) { int c = (*scan_buffer++); if (c == '\0') break; else if (c == '\n') { (*--scan_buffer) = '\0'; /* remove extraneous newline */ break; } } } #endif /* not HAVE_GETWD */ if (collection_buffer == internal_buffer) { if (length <= (strlen (internal_buffer))) { errno = ERANGE; return (0); } strcpy (buffer, internal_buffer); } return (buffer); } #endif /* EMULATE_GETCWD */ #ifdef EMULATE_WAITPID int DEFUN (UX_waitpid, (pid, stat_loc, options), pid_t pid AND int * stat_loc AND int options) { if (pid == (-1)) return (wait3 (stat_loc, options, 0)); #ifdef HAVE_WAIT4 else if (pid > 0) return (wait4 (pid, stat_loc, options, 0)); #endif errno = EINVAL; return (-1); } #endif #ifdef EMULATE_DUP2 int DEFUN (UX_dup2, (fd, fd2), int fd AND int fd2) { if (fd != fd2) UX_close (fd2); { int result = (UX_fcntl (fd, F_DUPFD, fd2)); if ((result < 0) && (errno == EINVAL)) errno = EBADF; return (result); } } #endif #ifdef EMULATE_RENAME int DEFUN (UX_rename, (from_name, to_name), CONST char * from_name AND CONST char * to_name) { int result; if ((result = (UX_access (from_name, 0))) < 0) return (result); { struct stat fs; struct stat ts; if (((UX_stat (from_name, (&fs))) == 0) && ((UX_lstat (to_name, (&ts))) == 0)) { if (((fs . st_dev) == (ts . st_dev)) && ((fs . st_ino) == (ts . st_ino))) return (0); UX_unlink (to_name); } } return (((result = (UX_link (from_name, to_name))) < 0) ? result : (UX_unlink (from_name))); } #endif #ifdef EMULATE_MKDIR int DEFUN (UX_mkdir, (name, mode), CONST char * name AND mode_t mode) { return (UX_mknod (name, ((mode & MODE_DIR) | S_IFDIR), ((dev_t) 0))); } #endif #ifdef _POSIX_VERSION cc_t DEFUN (UX_PC_VDISABLE, (fildes), int fildes) { #ifdef _POSIX_VDISABLE return ((cc_t) _POSIX_VDISABLE); #else long result = (fpathconf (fildes, _PC_VDISABLE)); return ((cc_t) ((result < 0) ? '\377' : result)); #endif } static clock_t memoized_clk_tck = 0; clock_t DEFUN_VOID (UX_SC_CLK_TCK) { if (memoized_clk_tck == 0) memoized_clk_tck = ((clock_t) (sysconf (_SC_CLK_TCK))); return (memoized_clk_tck); } #endif /* _POSIX_VERSION */ #ifndef HAVE_SIGACTION int DEFUN (UX_sigemptyset, (set), sigset_t * set) { (*set) = 0; return (0); } int DEFUN (UX_sigfillset, (set), sigset_t * set) { (*set) = (-1); return (0); } int DEFUN (UX_sigaddset, (set, signo), sigset_t * set AND int signo) { if (signo <= 0) return (-1); { int mask = (1 << (signo - 1)); if (mask == 0) return (-1); (*set) |= mask; return (0); } } int DEFUN (UX_sigdelset, (set, signo), sigset_t * set AND int signo) { if (signo <= 0) return (-1); { int mask = (1 << (signo - 1)); if (mask == 0) return (-1); (*set) &=~ mask; return (0); } } int DEFUN (UX_sigismember, (set, signo), CONST sigset_t * set AND int signo) { if (signo <= 0) return (-1); { int mask = (1 << (signo - 1)); if (mask == 0) return (-1); return (((*set) & mask) != 0); } } #ifdef HAVE_SIGVEC #ifndef SV_INTERRUPT # define SV_INTERRUPT 0 #endif int DEFUN (UX_sigaction, (signo, act, oact), int signo AND CONST struct sigaction * act AND struct sigaction * oact) { struct sigvec svec; struct sigvec sovec; struct sigvec * vec = ((act != 0) ? (&svec) : 0); struct sigvec * ovec = ((oact != 0) ? (&sovec) : 0); if (act != 0) { (vec -> sv_handler) = (act -> sa_handler); (vec -> sv_mask) = (act -> sa_mask); (vec -> sv_flags) = SV_INTERRUPT; } if ((UX_sigvec (signo, vec, ovec)) < 0) return (-1); if (oact != 0) { (oact -> sa_handler) = (ovec -> sv_handler); (oact -> sa_mask) = (ovec -> sv_mask); (oact -> sa_flags) = 0; } return (0); } int DEFUN (UX_sigprocmask, (how, set, oset), int how AND CONST sigset_t * set AND sigset_t * oset) { long omask; if (set == 0) omask = (sigblock (0)); else switch (how) { case SIG_BLOCK: omask = (sigblock (*set)); break; case SIG_UNBLOCK: omask = (sigblock (0)); if (omask < 0) return (-1); omask = (sigsetmask (omask &~ (*set))); break; case SIG_SETMASK: omask = (sigsetmask (*set)); break; default: errno = EINVAL; return (-1); } if (omask < 0) return (-1); if (oset != 0) (*oset) = omask; return (0); } int DEFUN (UX_sigsuspend, (set), CONST sigset_t * set) { return (sigpause (*set)); } #endif /* HAVE_SIGVEC */ #endif /* not _POSIX_VERSION */ #ifdef EMULATE_SYSCONF long DEFUN (sysconf, (parameter), int parameter) { switch (parameter) { case _SC_CLK_TCK: #ifdef CLK_TCK return ((long) (CLK_TCK)); #else #ifdef HZ return ((long) HZ); #else return (60); #endif /* HZ */ #endif /* CLK_TCK */ case _SC_OPEN_MAX: #ifdef OPEN_MAX return ((long) OPEN_MAX); #else #ifdef _NFILE return ((long) _NFILE); #else return ((long) 16); #endif /* _NFILE */ #endif /* OPEN_MAX */ case _SC_CHILD_MAX: #ifdef CHILD_MAX return ((long) CHILD_MAX); #else return ((long) 6); #endif /* CHILD_MAX */ case _SC_JOB_CONTROL: #ifdef TIOCGPGRP return ((long) 1); #else return ((long) 0); #endif default: errno = EINVAL; return ((long) (-1)); } } #endif /* EMULATE_SYSCONF */ #ifdef EMULATE_FPATHCONF long DEFUN (fpathconf, (filedes, parameter), int filedes AND int parameter) { switch (parameter) { case _PC_VDISABLE: return ((long) '\377'); default: errno = EINVAL; return ((long) (-1)); } } #endif /* EMULATE_FPATHCONF */ void * DEFUN (OS_malloc, (size), unsigned int size) { void * result = (UX_malloc (size)); if (result == 0) error_system_call (ENOMEM, syscall_malloc); return (result); } void * DEFUN (OS_realloc, (ptr, size), void * ptr AND unsigned int size) { void * result = (UX_realloc (ptr, size)); if (result == 0) error_system_call (ENOMEM, syscall_realloc); return (result); } void DEFUN (OS_free, (ptr), void * ptr) { UX_free (ptr); } #ifdef __linux__ #include void * linux_heap_malloc (unsigned long requested_length) { unsigned long ps = (getpagesize ()); void * addr = (mmap (((void *) ps), (((requested_length + (ps - 1)) / ps) * ps), (PROT_EXEC | PROT_READ | PROT_WRITE), (MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED), 0, 0)); return ((addr == ((void *) (-1))) ? 0 : addr); } #endif /* __linux__ */ #ifdef __FreeBSD__ #include void * freebsd_heap_malloc (unsigned long requested_length) { unsigned long ps = (getpagesize ()); void * addr = (mmap (((void *) ps), (((requested_length + (ps - 1)) / ps) * ps), (PROT_EXEC | PROT_READ | PROT_WRITE), (MAP_PRIVATE | MAP_ANON | MAP_FIXED), (-1), 0)); return ((addr == MAP_FAILED) ? 0 : addr); } #endif /* __FreeBSD__ */