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