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 #if !defined(HAVE_STRSIGNAL) 108 char *strsignal(int sig) 109 { 110 static char buf[16]; 111 112 (void)snprintf(buf, sizeof(buf), "%d", sig); 113 return buf; 114 } 115 #endif 116 117 #ifndef HAVE_UTIMES 118 int utimes(char *filename, struct timeval *tvp) 119 { 120 struct utimbuf ub; 121 122 ub.actime = tvp[0].tv_sec; 123 ub.modtime = tvp[1].tv_sec; 124 125 return (utime(filename, &ub)); 126 } 127 #endif 128 129 #ifndef HAVE_TRUNCATE 130 int truncate(const char *path, off_t length) 131 { 132 int fd, ret, saverrno; 133 134 fd = open(path, O_WRONLY); 135 if (fd < 0) 136 return (-1); 137 138 ret = ftruncate(fd, length); 139 saverrno = errno; 140 close(fd); 141 if (ret == -1) 142 errno = saverrno; 143 144 return(ret); 145 } 146 #endif /* HAVE_TRUNCATE */ 147 148 #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) 149 int nanosleep(const struct timespec *req, struct timespec *rem) 150 { 151 int rc, saverrno; 152 extern int errno; 153 struct timeval tstart, tstop, tremain, time2wait; 154 155 TIMESPEC_TO_TIMEVAL(&time2wait, req) 156 (void) gettimeofday(&tstart, NULL); 157 rc = select(0, NULL, NULL, NULL, &time2wait); 158 if (rc == -1) { 159 saverrno = errno; 160 (void) gettimeofday (&tstop, NULL); 161 errno = saverrno; 162 tremain.tv_sec = time2wait.tv_sec - 163 (tstop.tv_sec - tstart.tv_sec); 164 tremain.tv_usec = time2wait.tv_usec - 165 (tstop.tv_usec - tstart.tv_usec); 166 tremain.tv_sec += tremain.tv_usec / 1000000L; 167 tremain.tv_usec %= 1000000L; 168 } else { 169 tremain.tv_sec = 0; 170 tremain.tv_usec = 0; 171 } 172 if (rem != NULL) 173 TIMEVAL_TO_TIMESPEC(&tremain, rem) 174 175 return(rc); 176 } 177 #endif 178 179 #if !defined(HAVE_USLEEP) 180 int usleep(unsigned int useconds) 181 { 182 struct timespec ts; 183 184 ts.tv_sec = useconds / 1000000; 185 ts.tv_nsec = (useconds % 1000000) * 1000; 186 return nanosleep(&ts, NULL); 187 } 188 #endif 189 190 #ifndef HAVE_TCGETPGRP 191 pid_t 192 tcgetpgrp(int fd) 193 { 194 int ctty_pgrp; 195 196 if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) 197 return(-1); 198 else 199 return(ctty_pgrp); 200 } 201 #endif /* HAVE_TCGETPGRP */ 202 203 #ifndef HAVE_TCSENDBREAK 204 int 205 tcsendbreak(int fd, int duration) 206 { 207 # if defined(TIOCSBRK) && defined(TIOCCBRK) 208 struct timeval sleepytime; 209 210 sleepytime.tv_sec = 0; 211 sleepytime.tv_usec = 400000; 212 if (ioctl(fd, TIOCSBRK, 0) == -1) 213 return (-1); 214 (void)select(0, 0, 0, 0, &sleepytime); 215 if (ioctl(fd, TIOCCBRK, 0) == -1) 216 return (-1); 217 return (0); 218 # else 219 return -1; 220 # endif 221 } 222 #endif /* HAVE_TCSENDBREAK */ 223 224 mysig_t 225 mysignal(int sig, mysig_t act) 226 { 227 #ifdef HAVE_SIGACTION 228 struct sigaction sa, osa; 229 230 if (sigaction(sig, NULL, &osa) == -1) 231 return (mysig_t) -1; 232 if (osa.sa_handler != act) { 233 memset(&sa, 0, sizeof(sa)); 234 sigemptyset(&sa.sa_mask); 235 sa.sa_flags = 0; 236 #ifdef SA_INTERRUPT 237 if (sig == SIGALRM) 238 sa.sa_flags |= SA_INTERRUPT; 239 #endif 240 sa.sa_handler = act; 241 if (sigaction(sig, &sa, NULL) == -1) 242 return (mysig_t) -1; 243 } 244 return (osa.sa_handler); 245 #else 246 #undef signal 247 return (signal(sig, act)); 248 #endif 249 } 250 251 #ifndef HAVE_STRDUP 252 char * 253 strdup(const char *str) 254 { 255 size_t len; 256 char *cp; 257 258 len = strlen(str) + 1; 259 cp = malloc(len); 260 if (cp != NULL) 261 return(memcpy(cp, str, len)); 262 return NULL; 263 } 264 #endif 265 266 #ifndef HAVE_ISBLANK 267 int 268 isblank(int c) 269 { 270 return (c == ' ' || c == '\t'); 271 } 272 #endif 273 274 #ifndef HAVE_GETPGID 275 pid_t 276 getpgid(pid_t pid) 277 { 278 #if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) 279 return getpgrp(pid); 280 #elif defined(HAVE_GETPGRP) 281 if (pid == 0) 282 return getpgrp(); 283 #endif 284 285 errno = ESRCH; 286 return -1; 287 } 288 #endif 289 290 #ifndef HAVE_PLEDGE 291 int 292 pledge(const char *promises, const char *paths[]) 293 { 294 return 0; 295 } 296 #endif 297 298 #ifndef HAVE_MBTOWC 299 /* a mbtowc that only supports ASCII */ 300 int 301 mbtowc(wchar_t *pwc, const char *s, size_t n) 302 { 303 if (s == NULL || *s == '\0') 304 return 0; /* ASCII is not state-dependent */ 305 if (*s < 0 || *s > 0x7f || n < 1) { 306 errno = EOPNOTSUPP; 307 return -1; 308 } 309 if (pwc != NULL) 310 *pwc = *s; 311 return 1; 312 } 313 #endif 314 315 #ifndef HAVE_LLABS 316 long long 317 llabs(long long j) 318 { 319 return (j < 0 ? -j : j); 320 } 321 #endif 322