1 2 /* 3 * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "includes.h" 19 20 #ifdef HAVE_SYS_SELECT_H 21 # include <sys/select.h> 22 #endif 23 #ifdef HAVE_SYS_TIME_H 24 # include <sys/time.h> 25 #endif 26 27 #include <string.h> 28 #include <signal.h> 29 #include <stdlib.h> 30 31 #include "xmalloc.h" 32 33 #ifndef HAVE___PROGNAME 34 char *__progname; 35 #endif 36 37 /* 38 * NB. duplicate __progname in case it is an alias for argv[0] 39 * Otherwise it may get clobbered by setproctitle() 40 */ 41 char *ssh_get_progname(char *argv0) 42 { 43 #ifdef HAVE___PROGNAME 44 extern char *__progname; 45 46 return xstrdup(__progname); 47 #else 48 char *p; 49 50 if (argv0 == NULL) 51 return ("unknown"); /* XXX */ 52 p = strrchr(argv0, '/'); 53 if (p == NULL) 54 p = argv0; 55 else 56 p++; 57 58 return (xstrdup(p)); 59 #endif 60 } 61 62 #ifndef HAVE_SETLOGIN 63 int setlogin(const char *name) 64 { 65 return (0); 66 } 67 #endif /* !HAVE_SETLOGIN */ 68 69 #ifndef HAVE_INNETGR 70 int innetgr(const char *netgroup, const char *host, 71 const char *user, const char *domain) 72 { 73 return (0); 74 } 75 #endif /* HAVE_INNETGR */ 76 77 #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) 78 int seteuid(uid_t euid) 79 { 80 return (setreuid(-1, euid)); 81 } 82 #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ 83 84 #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) 85 int setegid(uid_t egid) 86 { 87 return(setresgid(-1, egid, -1)); 88 } 89 #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ 90 91 #if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) 92 const char *strerror(int e) 93 { 94 extern int sys_nerr; 95 extern char *sys_errlist[]; 96 97 if ((e >= 0) && (e < sys_nerr)) 98 return (sys_errlist[e]); 99 100 return ("unlisted error"); 101 } 102 #endif 103 104 #ifndef HAVE_UTIMES 105 int utimes(char *filename, struct timeval *tvp) 106 { 107 struct utimbuf ub; 108 109 ub.actime = tvp[0].tv_sec; 110 ub.modtime = tvp[1].tv_sec; 111 112 return (utime(filename, &ub)); 113 } 114 #endif 115 116 #ifndef HAVE_TRUNCATE 117 int truncate(const char *path, off_t length) 118 { 119 int fd, ret, saverrno; 120 121 fd = open(path, O_WRONLY); 122 if (fd < 0) 123 return (-1); 124 125 ret = ftruncate(fd, length); 126 saverrno = errno; 127 close(fd); 128 if (ret == -1) 129 errno = saverrno; 130 131 return(ret); 132 } 133 #endif /* HAVE_TRUNCATE */ 134 135 #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) 136 int nanosleep(const struct timespec *req, struct timespec *rem) 137 { 138 int rc, saverrno; 139 extern int errno; 140 struct timeval tstart, tstop, tremain, time2wait; 141 142 TIMESPEC_TO_TIMEVAL(&time2wait, req) 143 (void) gettimeofday(&tstart, NULL); 144 rc = select(0, NULL, NULL, NULL, &time2wait); 145 if (rc == -1) { 146 saverrno = errno; 147 (void) gettimeofday (&tstop, NULL); 148 errno = saverrno; 149 tremain.tv_sec = time2wait.tv_sec - 150 (tstop.tv_sec - tstart.tv_sec); 151 tremain.tv_usec = time2wait.tv_usec - 152 (tstop.tv_usec - tstart.tv_usec); 153 tremain.tv_sec += tremain.tv_usec / 1000000L; 154 tremain.tv_usec %= 1000000L; 155 } else { 156 tremain.tv_sec = 0; 157 tremain.tv_usec = 0; 158 } 159 TIMEVAL_TO_TIMESPEC(&tremain, rem) 160 161 return(rc); 162 } 163 #endif 164 165 #ifndef HAVE_TCGETPGRP 166 pid_t 167 tcgetpgrp(int fd) 168 { 169 int ctty_pgrp; 170 171 if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) 172 return(-1); 173 else 174 return(ctty_pgrp); 175 } 176 #endif /* HAVE_TCGETPGRP */ 177 178 #ifndef HAVE_TCSENDBREAK 179 int 180 tcsendbreak(int fd, int duration) 181 { 182 # if defined(TIOCSBRK) && defined(TIOCCBRK) 183 struct timeval sleepytime; 184 185 sleepytime.tv_sec = 0; 186 sleepytime.tv_usec = 400000; 187 if (ioctl(fd, TIOCSBRK, 0) == -1) 188 return (-1); 189 (void)select(0, 0, 0, 0, &sleepytime); 190 if (ioctl(fd, TIOCCBRK, 0) == -1) 191 return (-1); 192 return (0); 193 # else 194 return -1; 195 # endif 196 } 197 #endif /* HAVE_TCSENDBREAK */ 198 199 mysig_t 200 mysignal(int sig, mysig_t act) 201 { 202 #ifdef HAVE_SIGACTION 203 struct sigaction sa, osa; 204 205 if (sigaction(sig, NULL, &osa) == -1) 206 return (mysig_t) -1; 207 if (osa.sa_handler != act) { 208 memset(&sa, 0, sizeof(sa)); 209 sigemptyset(&sa.sa_mask); 210 sa.sa_flags = 0; 211 #ifdef SA_INTERRUPT 212 if (sig == SIGALRM) 213 sa.sa_flags |= SA_INTERRUPT; 214 #endif 215 sa.sa_handler = act; 216 if (sigaction(sig, &sa, NULL) == -1) 217 return (mysig_t) -1; 218 } 219 return (osa.sa_handler); 220 #else 221 #undef signal 222 return (signal(sig, act)); 223 #endif 224 } 225 226 #ifndef HAVE_STRDUP 227 char * 228 strdup(const char *str) 229 { 230 size_t len; 231 char *cp; 232 233 len = strlen(str) + 1; 234 cp = malloc(len); 235 if (cp != NULL) 236 return(memcpy(cp, str, len)); 237 return NULL; 238 } 239 #endif 240