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 mysig_t 215 mysignal(int sig, mysig_t act) 216 { 217 #ifdef HAVE_SIGACTION 218 struct sigaction sa, osa; 219 220 if (sigaction(sig, NULL, &osa) == -1) 221 return (mysig_t) -1; 222 if (osa.sa_handler != act) { 223 memset(&sa, 0, sizeof(sa)); 224 sigemptyset(&sa.sa_mask); 225 sa.sa_flags = 0; 226 #ifdef SA_INTERRUPT 227 if (sig == SIGALRM) 228 sa.sa_flags |= SA_INTERRUPT; 229 #endif 230 sa.sa_handler = act; 231 if (sigaction(sig, &sa, NULL) == -1) 232 return (mysig_t) -1; 233 } 234 return (osa.sa_handler); 235 #else 236 #undef signal 237 return (signal(sig, act)); 238 #endif 239 } 240 241 #ifndef HAVE_STRDUP 242 char * 243 strdup(const char *str) 244 { 245 size_t len; 246 char *cp; 247 248 len = strlen(str) + 1; 249 cp = malloc(len); 250 if (cp != NULL) 251 return(memcpy(cp, str, len)); 252 return NULL; 253 } 254 #endif 255 256 #ifndef HAVE_ISBLANK 257 int 258 isblank(int c) 259 { 260 return (c == ' ' || c == '\t'); 261 } 262 #endif 263 264 #ifndef HAVE_GETPGID 265 pid_t 266 getpgid(pid_t pid) 267 { 268 #if defined(HAVE_GETPGRP) && !defined(GETPGRP_VOID) 269 return getpgrp(pid); 270 #elif defined(HAVE_GETPGRP) 271 if (pid == 0) 272 return getpgrp(); 273 #endif 274 275 errno = ESRCH; 276 return -1; 277 } 278 #endif 279