/* Yes, that's right: of all the platforms supported by ppp, only Mach OpenStep 4.x doesn't support POSIX. Sheesh. Stranger still, the POSIX declatations are still in the 4.x header files, and the gcc -posix still defines _POSIX_SOURCE. So... we emulate (sometimes badly) the missing POSIX functions. This is by no means a complete or general POSIX emulation. Just enough to get us by for ppp, so we don't have to pollute the rest of the sources of every other (non-braindead) platform. Much of the code was snarfed from NeXT's 4.0 ppp port, the rest inspired by "POSIX Programmers Guide" by Donald Lewine. Maybe if we complain NeXT will upgrade to BSD4.4 libs like the rest of the free world (and maybe pink elephants will fly out of my... -KC) Update by Chris Zach 02/20/2001 to add getcwd parameter and everything after to get the damn bind 8.3.x working. What *fun* Maybe I'll port more of it later. Well, at least bind compiles cleanly now. Compile this file with cc -g -posix -O2 -c nextstep.c -o nextstep.o and include it in the build (I stuck it into the bind libs .a file over in src/lib Good luck! cz at alembic d-t crystel d-t com */ #import #import #import #include #include #include #include #include /* These are for POSIX emulation */ #include #include #include #include #include /* These are the orig includes. Note I am including everything under the sun. As they say: tough. */ #include #include #include #include #include #include #include int sigemptyset(sigset_t *set) /* [<][>][^][v][top][bottom][index][help] */ { *set = 0; return 0; } int sigaddset(sigset_t *set, int signo) /* [<][>][^][v][top][bottom][index][help] */ { *set |= 1<][^][v][top][bottom][index][help] */ { switch(how) { case SIG_BLOCK: *oset = sigblock(*set); break; case SIG_UNBLOCK: /* XXX How does one emulate this with ancient BSD? (KC) */ break; case SIG_SETMASK: *oset = sigsetmask(*set); break; } return 0; } int sigsuspend(const sigset_t *sigmask) /* [<][>][^][v][top][bottom][index][help] */ { sigpause(*sigmask); } int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) /* [<][>][^][v][top][bottom][index][help] */ { struct sigvec vec, ovec; int st; vec.sv_handler = act->sa_handler; vec.sv_mask = act->sa_mask; vec.sv_flags = act->sa_flags; st = sigvec(sig, &vec, &ovec); if (oact) { oact->sa_handler = ovec.sv_handler; oact->sa_mask = ovec.sv_mask; oact->sa_flags = ovec.sv_flags; } return st; } int tcgetattr(int fildes, struct termios *tp) /* [<][>][^][v][top][bottom][index][help] */ { return ioctl(fildes, TIOCGETA, tp); } int tcsetattr(int fd, int opt, const struct termios *t) /* [<][>][^][v][top][bottom][index][help] */ { int st; switch(opt) { case TCSANOW: st = ioctl(fd, TIOCSETA, t); break; case TCSADRAIN: st = ioctl(fd, TIOCSETAW, t); break; case TCSAFLUSH: st = ioctl(fd, TIOCSETAF, t); break; default: st = -1; errno = EINVAL; break; } return st; } /* XXX we ignore duration (which is 0 in chat.c anyway). */ int tcsendbreak(int fildes, int duration) /* [<][>][^][v][top][bottom][index][help] */ { struct timeval sleepytime; sleepytime.tv_sec = 0; sleepytime.tv_usec = 400000; if (ioctl(fildes, TIOCSBRK, 0) != -1) { select(0, 0, 0, 0, &sleepytime); (void) ioctl(fildes, TIOCCBRK, 0); } } /* XXX This is the implementation of cfgetospeed from NeXT's ppp-5 pppd/sys-NeXT.c. I don't know whether returning c_ispeed instead of c_ospeed is deliberate or a type-o. */ speed_t cfgetospeed(const struct termios *t) /* [<][>][^][v][top][bottom][index][help] */ { return t->c_ispeed; } int cfsetospeed(struct termios *t, int speed) /* [<][>][^][v][top][bottom][index][help] */ { t->c_ospeed = speed; return 0; } speed_t cfgetispeed(const struct termios *t) /* [<][>][^][v][top][bottom][index][help] */ { return t->c_ispeed; } int cfsetispeed(struct termios *t, int speed) /* [<][>][^][v][top][bottom][i ndex][help] */ { t->c_ispeed = speed; return 0; } int setsid(void) /* [<][>][^][v][top][bottom][index][help] */ { int fd; setpgrp(0, getpid()); if ( (fd = open("/dev/tty", O_RDWR | O_NDELAY)) < 0) return -1; ioctl(fd, TIOCNOTTY, NULL); close(fd); return 0; } int waitpid(pid_t pid, int *stat_loc, int options) /* [<][>][^][v][top][bottom][index][help] */ { if (pid == -1) pid = 0; return wait4(pid, (union wait *) stat_loc, options, NULL); } char *getcwd(char *buf, size_t size) { char pathname[MAXPATHLEN]; if (getwd(pathname) == NULL) { return NULL; } strncpy (buf, pathname, size); return buf; } /* _SC macros from unistd.h values from ** BUG: - the manpage for sysconf refers to a conf value _SC_STREAM_BUF ** but this is propably _SC_STREAM_MAX ** - Dunno how to get _SC_CLK_TCK's value, so it's zero for now. */ long sysconf(int name) { static int values[_SC_VERSION+1] = { /*_SC_ARG_MAX 0*/ ARG_MAX, /*_SC_CHILD_MAX 1*/ CHILD_MAX, /*_SC_CLK_TCK 2*/ 0, /* tick, hz, or phz?*/ /*_SC_JOB_CONTROL 3*/ _POSIX_JOB_CONTROL, /*_SC_NGROUPS_MAX 4*/ NGROUPS_MAX, /*_SC_OPEN_MAX 5*/ OPEN_MAX, /*_SC_SAVED_IDS 6*/ _POSIX_SAVED_IDS, /*_SC_STREAM_MAX 7*/ STREAM_MAX, /*_SC_TZNAME_MAX 8*/ TZNAME_MAX, /*_SC_VERSION 9*/ _POSIX_VERSION }; errno = 0; if (name > _SC_VERSION) { errno = EINVAL; return -1; } return values[name]; } /* Posix emulation functions */ int sigfillset(sigset_t *set) { memset(set, -1, sizeof(sigset_t)); return 0; } int sigdelset(sigset_t *set, int signo) { unsigned int sig; if (signo > NSIG) return EINVAL; sig = signo - 1; *set &= ~(((unsigned int)1) << sig); return 0; } int sigismember(const sigset_t *set, int signo) { unsigned int sig = signo - 1; return ((*set >> sig) & 1); } void siglongjmp (sigjmp_buf env, int val ) { struct sigcontext *ctx; ctx = (struct sigcontext*)(void*)env; if (ctx->sc_mask != 0) sigsetmask (ctx->sc_mask); longjmp ((void*)env, val); } int sigsetjmp (sigjmp_buf env, int savemask) { int retval; struct sigcontext *ctx; retval = setjmp ((void*)env); ctx = (struct sigcontext*)(void*)env; if (savemask) { struct sigcontext *ctx; /* Is there a better way to query the current signal mask? */ int mask = sigsetmask (0); sigsetmask (mask); ctx->sc_mask = mask; } else { ctx->sc_mask = 0; } return retval; }