1137015Sdes 298937Sdes/* 3126274Sdes * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org> 498937Sdes * 5126274Sdes * Permission to use, copy, modify, and distribute this software for any 6126274Sdes * purpose with or without fee is hereby granted, provided that the above 7126274Sdes * copyright notice and this permission notice appear in all copies. 898937Sdes * 9126274Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10126274Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11126274Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12126274Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13126274Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14126274Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15126274Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1698937Sdes */ 1798937Sdes 1898937Sdes#include "includes.h" 19162852Sdes 20181111Sdes#include <sys/types.h> 21162852Sdes#ifdef HAVE_SYS_SELECT_H 22162852Sdes# include <sys/select.h> 23162852Sdes#endif 24162852Sdes#ifdef HAVE_SYS_TIME_H 25162852Sdes# include <sys/time.h> 26162852Sdes#endif 27162852Sdes 28162852Sdes#include <string.h> 29162852Sdes#include <signal.h> 30162852Sdes#include <stdlib.h> 31262566Sdes#include <time.h> 32181111Sdes#include <unistd.h> 33162852Sdes 34137015Sdes#ifndef HAVE___PROGNAME 35137015Sdeschar *__progname; 36137015Sdes#endif 37137015Sdes 38113908Sdes/* 39113908Sdes * NB. duplicate __progname in case it is an alias for argv[0] 40113908Sdes * Otherwise it may get clobbered by setproctitle() 41113908Sdes */ 42124208Sdeschar *ssh_get_progname(char *argv0) 4398937Sdes{ 44295367Sdes char *p, *q; 4598937Sdes#ifdef HAVE___PROGNAME 4698937Sdes extern char *__progname; 4798937Sdes 48295367Sdes p = __progname; 4998937Sdes#else 5098937Sdes if (argv0 == NULL) 51124208Sdes return ("unknown"); /* XXX */ 5298937Sdes p = strrchr(argv0, '/'); 5398937Sdes if (p == NULL) 5498937Sdes p = argv0; 5598937Sdes else 5698937Sdes p++; 5798937Sdes#endif 58295367Sdes if ((q = strdup(p)) == NULL) { 59295367Sdes perror("strdup"); 60295367Sdes exit(1); 61295367Sdes } 62295367Sdes return q; 6398937Sdes} 6498937Sdes 6598937Sdes#ifndef HAVE_SETLOGIN 6698937Sdesint setlogin(const char *name) 6798937Sdes{ 68124208Sdes return (0); 6998937Sdes} 7098937Sdes#endif /* !HAVE_SETLOGIN */ 7198937Sdes 7298937Sdes#ifndef HAVE_INNETGR 7398937Sdesint innetgr(const char *netgroup, const char *host, 7498937Sdes const char *user, const char *domain) 7598937Sdes{ 76124208Sdes return (0); 7798937Sdes} 7898937Sdes#endif /* HAVE_INNETGR */ 7998937Sdes 8098937Sdes#if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) 8198937Sdesint seteuid(uid_t euid) 8298937Sdes{ 83124208Sdes return (setreuid(-1, euid)); 8498937Sdes} 8598937Sdes#endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ 8698937Sdes 8798937Sdes#if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) 8898937Sdesint setegid(uid_t egid) 8998937Sdes{ 90124208Sdes return(setresgid(-1, egid, -1)); 9198937Sdes} 9298937Sdes#endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ 9398937Sdes 9498937Sdes#if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) 9598937Sdesconst char *strerror(int e) 9698937Sdes{ 9798937Sdes extern int sys_nerr; 9898937Sdes extern char *sys_errlist[]; 9998937Sdes 10098937Sdes if ((e >= 0) && (e < sys_nerr)) 101124208Sdes return (sys_errlist[e]); 102124208Sdes 103124208Sdes return ("unlisted error"); 10498937Sdes} 10598937Sdes#endif 10698937Sdes 10798937Sdes#ifndef HAVE_UTIMES 10898937Sdesint utimes(char *filename, struct timeval *tvp) 10998937Sdes{ 11098937Sdes struct utimbuf ub; 11198937Sdes 112106121Sdes ub.actime = tvp[0].tv_sec; 113106121Sdes ub.modtime = tvp[1].tv_sec; 11498937Sdes 115124208Sdes return (utime(filename, &ub)); 11698937Sdes} 11798937Sdes#endif 11898937Sdes 11998937Sdes#ifndef HAVE_TRUNCATE 120124208Sdesint truncate(const char *path, off_t length) 12198937Sdes{ 12298937Sdes int fd, ret, saverrno; 12398937Sdes 12498937Sdes fd = open(path, O_WRONLY); 12598937Sdes if (fd < 0) 126124208Sdes return (-1); 12798937Sdes 12898937Sdes ret = ftruncate(fd, length); 12998937Sdes saverrno = errno; 130124208Sdes close(fd); 13198937Sdes if (ret == -1) 13298937Sdes errno = saverrno; 133124208Sdes 13498937Sdes return(ret); 13598937Sdes} 13698937Sdes#endif /* HAVE_TRUNCATE */ 13798937Sdes 138113908Sdes#if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) 139113908Sdesint nanosleep(const struct timespec *req, struct timespec *rem) 140113908Sdes{ 141113908Sdes int rc, saverrno; 142113908Sdes extern int errno; 143113908Sdes struct timeval tstart, tstop, tremain, time2wait; 144113908Sdes 145113908Sdes TIMESPEC_TO_TIMEVAL(&time2wait, req) 146113908Sdes (void) gettimeofday(&tstart, NULL); 147113908Sdes rc = select(0, NULL, NULL, NULL, &time2wait); 148113908Sdes if (rc == -1) { 149113908Sdes saverrno = errno; 150113908Sdes (void) gettimeofday (&tstop, NULL); 151113908Sdes errno = saverrno; 152113908Sdes tremain.tv_sec = time2wait.tv_sec - 153113908Sdes (tstop.tv_sec - tstart.tv_sec); 154113908Sdes tremain.tv_usec = time2wait.tv_usec - 155113908Sdes (tstop.tv_usec - tstart.tv_usec); 156113908Sdes tremain.tv_sec += tremain.tv_usec / 1000000L; 157113908Sdes tremain.tv_usec %= 1000000L; 158113908Sdes } else { 159113908Sdes tremain.tv_sec = 0; 160113908Sdes tremain.tv_usec = 0; 161113908Sdes } 162181111Sdes if (rem != NULL) 163181111Sdes TIMEVAL_TO_TIMESPEC(&tremain, rem) 164113908Sdes 165113908Sdes return(rc); 166113908Sdes} 167113908Sdes#endif 168113908Sdes 169248619Sdes#if !defined(HAVE_USLEEP) 170248619Sdesint usleep(unsigned int useconds) 171248619Sdes{ 172248619Sdes struct timespec ts; 173248619Sdes 174248619Sdes ts.tv_sec = useconds / 1000000; 175248619Sdes ts.tv_nsec = (useconds % 1000000) * 1000; 176248619Sdes return nanosleep(&ts, NULL); 177248619Sdes} 178248619Sdes#endif 179248619Sdes 180124208Sdes#ifndef HAVE_TCGETPGRP 181124208Sdespid_t 182124208Sdestcgetpgrp(int fd) 183124208Sdes{ 184124208Sdes int ctty_pgrp; 185124208Sdes 186124208Sdes if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) 187124208Sdes return(-1); 188124208Sdes else 189124208Sdes return(ctty_pgrp); 190124208Sdes} 191124208Sdes#endif /* HAVE_TCGETPGRP */ 192124208Sdes 193124208Sdes#ifndef HAVE_TCSENDBREAK 194124208Sdesint 195124208Sdestcsendbreak(int fd, int duration) 196124208Sdes{ 197124208Sdes# if defined(TIOCSBRK) && defined(TIOCCBRK) 198124208Sdes struct timeval sleepytime; 199124208Sdes 200124208Sdes sleepytime.tv_sec = 0; 201124208Sdes sleepytime.tv_usec = 400000; 202124208Sdes if (ioctl(fd, TIOCSBRK, 0) == -1) 203124208Sdes return (-1); 204124208Sdes (void)select(0, 0, 0, 0, &sleepytime); 205124208Sdes if (ioctl(fd, TIOCCBRK, 0) == -1) 206124208Sdes return (-1); 207124208Sdes return (0); 208124208Sdes# else 209124208Sdes return -1; 210124208Sdes# endif 211124208Sdes} 212124208Sdes#endif /* HAVE_TCSENDBREAK */ 213124208Sdes 214124208Sdesmysig_t 215124208Sdesmysignal(int sig, mysig_t act) 216124208Sdes{ 217124208Sdes#ifdef HAVE_SIGACTION 218124208Sdes struct sigaction sa, osa; 219124208Sdes 220124208Sdes if (sigaction(sig, NULL, &osa) == -1) 221124208Sdes return (mysig_t) -1; 222124208Sdes if (osa.sa_handler != act) { 223124208Sdes memset(&sa, 0, sizeof(sa)); 224124208Sdes sigemptyset(&sa.sa_mask); 225124208Sdes sa.sa_flags = 0; 226124208Sdes#ifdef SA_INTERRUPT 227124208Sdes if (sig == SIGALRM) 228124208Sdes sa.sa_flags |= SA_INTERRUPT; 229124208Sdes#endif 230124208Sdes sa.sa_handler = act; 231124208Sdes if (sigaction(sig, &sa, NULL) == -1) 232124208Sdes return (mysig_t) -1; 233124208Sdes } 234124208Sdes return (osa.sa_handler); 235124208Sdes#else 236126274Sdes #undef signal 237124208Sdes return (signal(sig, act)); 238124208Sdes#endif 239124208Sdes} 240149749Sdes 241149749Sdes#ifndef HAVE_STRDUP 242149749Sdeschar * 243149749Sdesstrdup(const char *str) 244149749Sdes{ 245149749Sdes size_t len; 246149749Sdes char *cp; 247149749Sdes 248149749Sdes len = strlen(str) + 1; 249149749Sdes cp = malloc(len); 250149749Sdes if (cp != NULL) 251157016Sdes return(memcpy(cp, str, len)); 252157016Sdes return NULL; 253149749Sdes} 254149749Sdes#endif 255221420Sdes 256221420Sdes#ifndef HAVE_ISBLANK 257248619Sdesint 258248619Sdesisblank(int c) 259221420Sdes{ 260221420Sdes return (c == ' ' || c == '\t'); 261221420Sdes} 262221420Sdes#endif 263248619Sdes 264248619Sdes#ifndef HAVE_GETPGID 265248619Sdespid_t 266248619Sdesgetpgid(pid_t pid) 267248619Sdes{ 268248619Sdes#if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) 269248619Sdes return getpgrp(pid); 270248619Sdes#elif defined(HAVE_GETPGRP) 271248619Sdes if (pid == 0) 272248619Sdes return getpgrp(); 273248619Sdes#endif 274248619Sdes 275248619Sdes errno = ESRCH; 276248619Sdes return -1; 277248619Sdes} 278248619Sdes#endif 279296781Sdes 280296781Sdes#ifndef HAVE_PLEDGE 281296781Sdesint 282296781Sdespledge(const char *promises, const char *paths[]) 283296781Sdes{ 284296781Sdes return 0; 285296781Sdes} 286296781Sdes#endif 287323124Sdes 288323124Sdes#ifndef HAVE_MBTOWC 289323124Sdes/* a mbtowc that only supports ASCII */ 290323124Sdesint 291323124Sdesmbtowc(wchar_t *pwc, const char *s, size_t n) 292323124Sdes{ 293323124Sdes if (s == NULL || *s == '\0') 294323124Sdes return 0; /* ASCII is not state-dependent */ 295323124Sdes if (*s < 0 || *s > 0x7f || n < 1) { 296323124Sdes errno = EOPNOTSUPP; 297323124Sdes return -1; 298323124Sdes } 299323124Sdes if (pwc != NULL) 300323124Sdes *pwc = *s; 301323124Sdes return 1; 302323124Sdes} 303323124Sdes#endif 304