123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- /*
- * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- #include "includes.h"
- #include <sys/types.h>
- #ifdef HAVE_SYS_SELECT_H
- # include <sys/select.h>
- #endif
- #ifdef HAVE_SYS_TIME_H
- # include <sys/time.h>
- #endif
- #include <fcntl.h>
- #include <string.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <time.h>
- #include <unistd.h>
- #ifndef HAVE___PROGNAME
- char *__progname;
- #endif
- /*
- * NB. duplicate __progname in case it is an alias for argv[0]
- * Otherwise it may get clobbered by setproctitle()
- */
- char *ssh_get_progname(char *argv0)
- {
- char *p, *q;
- #ifdef HAVE___PROGNAME
- extern char *__progname;
- p = __progname;
- #else
- if (argv0 == NULL)
- return ("unknown"); /* XXX */
- p = strrchr(argv0, '/');
- if (p == NULL)
- p = argv0;
- else
- p++;
- #endif
- if ((q = strdup(p)) == NULL) {
- perror("strdup");
- exit(1);
- }
- return q;
- }
- #ifndef HAVE_SETLOGIN
- int setlogin(const char *name)
- {
- return (0);
- }
- #endif /* !HAVE_SETLOGIN */
- #ifndef HAVE_INNETGR
- int innetgr(const char *netgroup, const char *host,
- const char *user, const char *domain)
- {
- return (0);
- }
- #endif /* HAVE_INNETGR */
- #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID)
- int seteuid(uid_t euid)
- {
- return (setreuid(-1, euid));
- }
- #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */
- #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID)
- int setegid(uid_t egid)
- {
- return(setresgid(-1, egid, -1));
- }
- #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */
- #if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR)
- const char *strerror(int e)
- {
- extern int sys_nerr;
- extern char *sys_errlist[];
- if ((e >= 0) && (e < sys_nerr))
- return (sys_errlist[e]);
- return ("unlisted error");
- }
- #endif
- #ifndef HAVE_UTIMES
- int utimes(char *filename, struct timeval *tvp)
- {
- struct utimbuf ub;
- ub.actime = tvp[0].tv_sec;
- ub.modtime = tvp[1].tv_sec;
- return (utime(filename, &ub));
- }
- #endif
- #ifndef HAVE_UTIMENSAT
- /*
- * A limited implementation of utimensat() that only implements the
- * functionality used by OpenSSH, currently only AT_FDCWD and
- * AT_SYMLINK_NOFOLLOW.
- */
- int
- utimensat(int fd, const char *path, const struct timespec times[2],
- int flag)
- {
- struct timeval tv[2];
- # ifdef HAVE_FUTIMES
- int ret, oflags = O_WRONLY;
- # endif
- tv[0].tv_sec = times[0].tv_sec;
- tv[0].tv_usec = times[0].tv_nsec / 1000;
- tv[1].tv_sec = times[1].tv_sec;
- tv[1].tv_usec = times[1].tv_nsec / 1000;
- if (fd != AT_FDCWD) {
- errno = ENOSYS;
- return -1;
- }
- # ifndef HAVE_FUTIMES
- return utimes(path, tv);
- # else
- # ifdef O_NOFOLLOW
- if (flag & AT_SYMLINK_NOFOLLOW)
- oflags |= O_NOFOLLOW;
- # endif /* O_NOFOLLOW */
- if ((fd = open(path, oflags)) == -1)
- return -1;
- ret = futimes(fd, tv);
- close(fd);
- return ret;
- # endif
- }
- #endif
- #ifndef HAVE_FCHOWNAT
- /*
- * A limited implementation of fchownat() that only implements the
- * functionality used by OpenSSH, currently only AT_FDCWD and
- * AT_SYMLINK_NOFOLLOW.
- */
- int
- fchownat(int fd, const char *path, uid_t owner, gid_t group, int flag)
- {
- int ret, oflags = O_WRONLY;
- if (fd != AT_FDCWD) {
- errno = ENOSYS;
- return -1;
- }
- # ifndef HAVE_FCHOWN
- return chown(path, owner, group);
- # else
- # ifdef O_NOFOLLOW
- if (flag & AT_SYMLINK_NOFOLLOW)
- oflags |= O_NOFOLLOW;
- # endif /* O_NOFOLLOW */
- if ((fd = open(path, oflags)) == -1)
- return -1;
- ret = fchown(fd, owner, group);
- close(fd);
- return ret;
- # endif
- }
- #endif
- #ifndef HAVE_FCHMODAT
- /*
- * A limited implementation of fchmodat() that only implements the
- * functionality used by OpenSSH, currently only AT_FDCWD and
- * AT_SYMLINK_NOFOLLOW.
- */
- int
- fchmodat(int fd, const char *path, mode_t mode, int flag)
- {
- int ret, oflags = O_WRONLY;
- if (fd != AT_FDCWD) {
- errno = ENOSYS;
- return -1;
- }
- # ifndef HAVE_FCHMOD
- return chmod(path, mode);
- # else
- # ifdef O_NOFOLLOW
- if (flag & AT_SYMLINK_NOFOLLOW)
- oflags |= O_NOFOLLOW;
- # endif /* O_NOFOLLOW */
- if ((fd = open(path, oflags)) == -1)
- return -1;
- ret = fchmod(fd, mode);
- close(fd);
- return ret;
- # endif
- }
- #endif
- #ifndef HAVE_TRUNCATE
- int truncate(const char *path, off_t length)
- {
- int fd, ret, saverrno;
- fd = open(path, O_WRONLY);
- if (fd < 0)
- return (-1);
- ret = ftruncate(fd, length);
- saverrno = errno;
- close(fd);
- if (ret == -1)
- errno = saverrno;
- return(ret);
- }
- #endif /* HAVE_TRUNCATE */
- #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP)
- int nanosleep(const struct timespec *req, struct timespec *rem)
- {
- int rc, saverrno;
- extern int errno;
- struct timeval tstart, tstop, tremain, time2wait;
- TIMESPEC_TO_TIMEVAL(&time2wait, req)
- (void) gettimeofday(&tstart, NULL);
- rc = select(0, NULL, NULL, NULL, &time2wait);
- if (rc == -1) {
- saverrno = errno;
- (void) gettimeofday (&tstop, NULL);
- errno = saverrno;
- tremain.tv_sec = time2wait.tv_sec -
- (tstop.tv_sec - tstart.tv_sec);
- tremain.tv_usec = time2wait.tv_usec -
- (tstop.tv_usec - tstart.tv_usec);
- tremain.tv_sec += tremain.tv_usec / 1000000L;
- tremain.tv_usec %= 1000000L;
- } else {
- tremain.tv_sec = 0;
- tremain.tv_usec = 0;
- }
- if (rem != NULL)
- TIMEVAL_TO_TIMESPEC(&tremain, rem)
- return(rc);
- }
- #endif
- #if !defined(HAVE_USLEEP)
- int usleep(unsigned int useconds)
- {
- struct timespec ts;
- ts.tv_sec = useconds / 1000000;
- ts.tv_nsec = (useconds % 1000000) * 1000;
- return nanosleep(&ts, NULL);
- }
- #endif
- #ifndef HAVE_TCGETPGRP
- pid_t
- tcgetpgrp(int fd)
- {
- int ctty_pgrp;
- if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1)
- return(-1);
- else
- return(ctty_pgrp);
- }
- #endif /* HAVE_TCGETPGRP */
- #ifndef HAVE_TCSENDBREAK
- int
- tcsendbreak(int fd, int duration)
- {
- # if defined(TIOCSBRK) && defined(TIOCCBRK)
- struct timeval sleepytime;
- sleepytime.tv_sec = 0;
- sleepytime.tv_usec = 400000;
- if (ioctl(fd, TIOCSBRK, 0) == -1)
- return (-1);
- (void)select(0, 0, 0, 0, &sleepytime);
- if (ioctl(fd, TIOCCBRK, 0) == -1)
- return (-1);
- return (0);
- # else
- return -1;
- # endif
- }
- #endif /* HAVE_TCSENDBREAK */
- #ifndef HAVE_STRDUP
- char *
- strdup(const char *str)
- {
- size_t len;
- char *cp;
- len = strlen(str) + 1;
- cp = malloc(len);
- if (cp != NULL)
- return(memcpy(cp, str, len));
- return NULL;
- }
- #endif
- #ifndef HAVE_ISBLANK
- int
- isblank(int c)
- {
- return (c == ' ' || c == '\t');
- }
- #endif
- #ifndef HAVE_GETPGID
- pid_t
- getpgid(pid_t pid)
- {
- #if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) && GETPGRP_VOID == 0
- return getpgrp(pid);
- #elif defined(HAVE_GETPGRP)
- if (pid == 0)
- return getpgrp();
- #endif
- errno = ESRCH;
- return -1;
- }
- #endif
- #ifndef HAVE_PLEDGE
- int
- pledge(const char *promises, const char *paths[])
- {
- return 0;
- }
- #endif
- #ifndef HAVE_MBTOWC
- /* a mbtowc that only supports ASCII */
- int
- mbtowc(wchar_t *pwc, const char *s, size_t n)
- {
- if (s == NULL || *s == '\0')
- return 0; /* ASCII is not state-dependent */
- if (*s < 0 || *s > 0x7f || n < 1) {
- errno = EOPNOTSUPP;
- return -1;
- }
- if (pwc != NULL)
- *pwc = *s;
- return 1;
- }
- #endif
- #ifndef HAVE_LLABS
- long long
- llabs(long long j)
- {
- return (j < 0 ? -j : j);
- }
- #endif
- #ifndef HAVE_BZERO
- void
- bzero(void *b, size_t n)
- {
- (void)memset(b, 0, n);
- }
- #endif
- #ifndef HAVE_RAISE
- int
- raise(int sig)
- {
- kill(getpid(), sig);
- }
- #endif
- #ifndef HAVE_GETSID
- pid_t
- getsid(pid_t pid)
- {
- errno = ENOSYS;
- return -1;
- }
- #endif
- #ifdef FFLUSH_NULL_BUG
- #undef fflush
- int _ssh_compat_fflush(FILE *f)
- {
- int r1, r2;
- if (f == NULL) {
- r1 = fflush(stdout);
- r2 = fflush(stderr);
- if (r1 == -1 || r2 == -1)
- return -1;
- return 0;
- }
- return fflush(f);
- }
- #endif
- #ifndef HAVE_LOCALTIME_R
- struct tm *
- localtime_r(const time_t *timep, struct tm *result)
- {
- struct tm *tm = localtime(timep);
- *result = *tm;
- return result;
- }
- #endif
|