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 #include <sys/types.h> 21 #ifdef HAVE_SYS_SELECT_H 22 # include <sys/select.h> 23 #endif 24 #ifdef HAVE_SYS_TIME_H 25 # include <sys/time.h> 26 #endif 27 28 #include <string.h> 29 #include <signal.h> 30 #include <stdlib.h> 31 #include <time.h> 32 #include <unistd.h> 33 34 #ifndef HAVE___PROGNAME 35 char *__progname; 36 #endif 37 38 /* 39 * NB. duplicate __progname in case it is an alias for argv[0] 40 * Otherwise it may get clobbered by setproctitle() 41 */ 42 char *ssh_get_progname(char *argv0) 43 { 44 char *p, *q; 45 #ifdef HAVE___PROGNAME 46 extern char *__progname; 47 48 p = __progname; 49 #else 50 if (argv0 == NULL) 51 return ("unknown"); /* XXX */ 52 p = strrchr(argv0, '/'); 53 if (p == NULL) 54 p = argv0; 55 else 56 p++; 57 #endif 58 if ((q = strdup(p)) == NULL) { 59 perror("strdup"); 60 exit(1); 61 } 62 return q; 63 } 64 65 #ifndef HAVE_SETLOGIN 66 int setlogin(const char *name) 67 { 68 return (0); 69 } 70 #endif /* !HAVE_SETLOGIN */ 71 72 #ifndef HAVE_INNETGR 73 int innetgr(const char *netgroup, const char *host, 74 const char *user, const char *domain) 75 { 76 return (0); 77 } 78 #endif /* HAVE_INNETGR */ 79 80 #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) 81 int seteuid(uid_t euid) 82 { 83 return (setreuid(-1, euid)); 84 } 85 #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ 86 87 #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) 88 int setegid(uid_t egid) 89 { 90 return(setresgid(-1, egid, -1)); 91 } 92 #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ 93 94 #if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) 95 const char *strerror(int e) 96 { 97 extern int sys_nerr; 98 extern char *sys_errlist[]; 99 100 if ((e >= 0) && (e < sys_nerr)) 101 return (sys_errlist[e]); 102 103 return ("unlisted error"); 104 } 105 #endif 106 107 #ifndef HAVE_UTIMES 108 int utimes(char *filename, struct timeval *tvp) 109 { 110 struct utimbuf ub; 111 112 ub.actime = tvp[0].tv_sec; 113 ub.modtime = tvp[1].tv_sec; 114 115 return (utime(filename, &ub)); 116 } 117 #endif 118 119 #ifndef HAVE_TRUNCATE 120 int truncate(const char *path, off_t length) 121 { 122 int fd, ret, saverrno; 123 124 fd = open(path, O_WRONLY); 125 if (fd < 0) 126 return (-1); 127 128 ret = ftruncate(fd, length); 129 saverrno = errno; 130 close(fd); 131 if (ret == -1) 132 errno = saverrno; 133 134 return(ret); 135 } 136 #endif /* HAVE_TRUNCATE */ 137 138 #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) 139 int nanosleep(const struct timespec *req, struct timespec *rem) 140 { 141 int rc, saverrno; 142 extern int errno; 143 struct timeval tstart, tstop, tremain, time2wait; 144 145 TIMESPEC_TO_TIMEVAL(&time2wait, req) 146 (void) gettimeofday(&tstart, NULL); 147 rc = select(0, NULL, NULL, NULL, &time2wait); 148 if (rc == -1) { 149 saverrno = errno; 150 (void) gettimeofday (&tstop, NULL); 151 errno = saverrno; 152 tremain.tv_sec = time2wait.tv_sec - 153 (tstop.tv_sec - tstart.tv_sec); 154 tremain.tv_usec = time2wait.tv_usec - 155 (tstop.tv_usec - tstart.tv_usec); 156 tremain.tv_sec += tremain.tv_usec / 1000000L; 157 tremain.tv_usec %= 1000000L; 158 } else { 159 tremain.tv_sec = 0; 160 tremain.tv_usec = 0; 161 } 162 if (rem != NULL) 163 TIMEVAL_TO_TIMESPEC(&tremain, rem) 164 165 return(rc); 166 } 167 #endif 168 169 #if !defined(HAVE_USLEEP) 170 int usleep(unsigned int useconds) 171 { 172 struct timespec ts; 173 174 ts.tv_sec = useconds / 1000000; 175 ts.tv_nsec = (useconds % 1000000) * 1000; 176 return nanosleep(&ts, NULL); 177 } 178 #endif 179 180 #ifndef HAVE_TCGETPGRP 181 pid_t 182 tcgetpgrp(int fd) 183 { 184 int ctty_pgrp; 185 186 if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) 187 return(-1); 188 else 189 return(ctty_pgrp); 190 } 191 #endif /* HAVE_TCGETPGRP */ 192 193 #ifndef HAVE_TCSENDBREAK 194 int 195 tcsendbreak(int fd, int duration) 196 { 197 # if defined(TIOCSBRK) && defined(TIOCCBRK) 198 struct timeval sleepytime; 199 200 sleepytime.tv_sec = 0; 201 sleepytime.tv_usec = 400000; 202 if (ioctl(fd, TIOCSBRK, 0) == -1) 203 return (-1); 204 (void)select(0, 0, 0, 0, &sleepytime); 205 if (ioctl(fd, TIOCCBRK, 0) == -1) 206 return (-1); 207 return (0); 208 # else 209 return -1; 210 # endif 211 } 212 #endif /* HAVE_TCSENDBREAK */ 213 214 #ifndef HAVE_STRDUP 215 char * 216 strdup(const char *str) 217 { 218 size_t len; 219 char *cp; 220 221 len = strlen(str) + 1; 222 cp = malloc(len); 223 if (cp != NULL) 224 return(memcpy(cp, str, len)); 225 return NULL; 226 } 227 #endif 228 229 #ifndef HAVE_ISBLANK 230 int 231 isblank(int c) 232 { 233 return (c == ' ' || c == '\t'); 234 } 235 #endif 236 237 #ifndef HAVE_GETPGID 238 pid_t 239 getpgid(pid_t pid) 240 { 241 #if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) && GETPGRP_VOID == 0 242 return getpgrp(pid); 243 #elif defined(HAVE_GETPGRP) 244 if (pid == 0) 245 return getpgrp(); 246 #endif 247 248 errno = ESRCH; 249 return -1; 250 } 251 #endif 252 253 #ifndef HAVE_PLEDGE 254 int 255 pledge(const char *promises, const char *paths[]) 256 { 257 return 0; 258 } 259 #endif 260 261 #ifndef HAVE_MBTOWC 262 /* a mbtowc that only supports ASCII */ 263 int 264 mbtowc(wchar_t *pwc, const char *s, size_t n) 265 { 266 if (s == NULL || *s == '\0') 267 return 0; /* ASCII is not state-dependent */ 268 if (*s < 0 || *s > 0x7f || n < 1) { 269 errno = EOPNOTSUPP; 270 return -1; 271 } 272 if (pwc != NULL) 273 *pwc = *s; 274 return 1; 275 } 276 #endif 277 278 #ifndef HAVE_LLABS 279 long long 280 llabs(long long j) 281 { 282 return (j < 0 ? -j : j); 283 } 284 #endif 285 286 #ifndef HAVE_BZERO 287 void 288 bzero(void *b, size_t n) 289 { 290 (void)memset(b, 0, n); 291 } 292 #endif 293 294 #ifndef HAVE_RAISE 295 int 296 raise(int sig) 297 { 298 kill(getpid(), sig); 299 } 300 #endif 301 302 #ifndef HAVE_GETSID 303 pid_t 304 getsid(pid_t pid) 305 { 306 errno = ENOSYS; 307 return -1; 308 } 309 #endif 310 311 #ifdef FFLUSH_NULL_BUG 312 #undef fflush 313 int _ssh_compat_fflush(FILE *f) 314 { 315 int r1, r2, r3; 316 317 if (f == NULL) { 318 r2 = fflush(stdout); 319 r3 = fflush(stderr); 320 if (r1 == -1 || r2 == -1 || r3 == -1) 321 return -1; 322 return 0; 323 } 324 return fflush(f); 325 } 326 #endif 327