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 #include "xmalloc.h" 20 21 RCSID("$Id: bsd-misc.c,v 1.25 2004/08/15 08:41:00 djm Exp $"); 22 23 #ifndef HAVE___PROGNAME 24 char *__progname; 25 #endif 26 27 /* 28 * NB. duplicate __progname in case it is an alias for argv[0] 29 * Otherwise it may get clobbered by setproctitle() 30 */ 31 char *ssh_get_progname(char *argv0) 32 { 33 #ifdef HAVE___PROGNAME 34 extern char *__progname; 35 36 return xstrdup(__progname); 37 #else 38 char *p; 39 40 if (argv0 == NULL) 41 return ("unknown"); /* XXX */ 42 p = strrchr(argv0, '/'); 43 if (p == NULL) 44 p = argv0; 45 else 46 p++; 47 48 return (xstrdup(p)); 49 #endif 50 } 51 52 #ifndef HAVE_SETLOGIN 53 int setlogin(const char *name) 54 { 55 return (0); 56 } 57 #endif /* !HAVE_SETLOGIN */ 58 59 #ifndef HAVE_INNETGR 60 int innetgr(const char *netgroup, const char *host, 61 const char *user, const char *domain) 62 { 63 return (0); 64 } 65 #endif /* HAVE_INNETGR */ 66 67 #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) 68 int seteuid(uid_t euid) 69 { 70 return (setreuid(-1, euid)); 71 } 72 #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ 73 74 #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) 75 int setegid(uid_t egid) 76 { 77 return(setresgid(-1, egid, -1)); 78 } 79 #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ 80 81 #if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) 82 const char *strerror(int e) 83 { 84 extern int sys_nerr; 85 extern char *sys_errlist[]; 86 87 if ((e >= 0) && (e < sys_nerr)) 88 return (sys_errlist[e]); 89 90 return ("unlisted error"); 91 } 92 #endif 93 94 #ifndef HAVE_UTIMES 95 int utimes(char *filename, struct timeval *tvp) 96 { 97 struct utimbuf ub; 98 99 ub.actime = tvp[0].tv_sec; 100 ub.modtime = tvp[1].tv_sec; 101 102 return (utime(filename, &ub)); 103 } 104 #endif 105 106 #ifndef HAVE_TRUNCATE 107 int truncate(const char *path, off_t length) 108 { 109 int fd, ret, saverrno; 110 111 fd = open(path, O_WRONLY); 112 if (fd < 0) 113 return (-1); 114 115 ret = ftruncate(fd, length); 116 saverrno = errno; 117 close(fd); 118 if (ret == -1) 119 errno = saverrno; 120 121 return(ret); 122 } 123 #endif /* HAVE_TRUNCATE */ 124 125 #if !defined(HAVE_SETGROUPS) && defined(SETGROUPS_NOOP) 126 /* 127 * Cygwin setgroups should be a noop. 128 */ 129 int 130 setgroups(size_t size, const gid_t *list) 131 { 132 return (0); 133 } 134 #endif 135 136 #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) 137 int nanosleep(const struct timespec *req, struct timespec *rem) 138 { 139 int rc, saverrno; 140 extern int errno; 141 struct timeval tstart, tstop, tremain, time2wait; 142 143 TIMESPEC_TO_TIMEVAL(&time2wait, req) 144 (void) gettimeofday(&tstart, NULL); 145 rc = select(0, NULL, NULL, NULL, &time2wait); 146 if (rc == -1) { 147 saverrno = errno; 148 (void) gettimeofday (&tstop, NULL); 149 errno = saverrno; 150 tremain.tv_sec = time2wait.tv_sec - 151 (tstop.tv_sec - tstart.tv_sec); 152 tremain.tv_usec = time2wait.tv_usec - 153 (tstop.tv_usec - tstart.tv_usec); 154 tremain.tv_sec += tremain.tv_usec / 1000000L; 155 tremain.tv_usec %= 1000000L; 156 } else { 157 tremain.tv_sec = 0; 158 tremain.tv_usec = 0; 159 } 160 TIMEVAL_TO_TIMESPEC(&tremain, rem) 161 162 return(rc); 163 } 164 #endif 165 166 #ifndef HAVE_TCGETPGRP 167 pid_t 168 tcgetpgrp(int fd) 169 { 170 int ctty_pgrp; 171 172 if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) 173 return(-1); 174 else 175 return(ctty_pgrp); 176 } 177 #endif /* HAVE_TCGETPGRP */ 178 179 #ifndef HAVE_TCSENDBREAK 180 int 181 tcsendbreak(int fd, int duration) 182 { 183 # if defined(TIOCSBRK) && defined(TIOCCBRK) 184 struct timeval sleepytime; 185 186 sleepytime.tv_sec = 0; 187 sleepytime.tv_usec = 400000; 188 if (ioctl(fd, TIOCSBRK, 0) == -1) 189 return (-1); 190 (void)select(0, 0, 0, 0, &sleepytime); 191 if (ioctl(fd, TIOCCBRK, 0) == -1) 192 return (-1); 193 return (0); 194 # else 195 return -1; 196 # endif 197 } 198 #endif /* HAVE_TCSENDBREAK */ 199 200 mysig_t 201 mysignal(int sig, mysig_t act) 202 { 203 #ifdef HAVE_SIGACTION 204 struct sigaction sa, osa; 205 206 if (sigaction(sig, NULL, &osa) == -1) 207 return (mysig_t) -1; 208 if (osa.sa_handler != act) { 209 memset(&sa, 0, sizeof(sa)); 210 sigemptyset(&sa.sa_mask); 211 sa.sa_flags = 0; 212 #ifdef SA_INTERRUPT 213 if (sig == SIGALRM) 214 sa.sa_flags |= SA_INTERRUPT; 215 #endif 216 sa.sa_handler = act; 217 if (sigaction(sig, &sa, NULL) == -1) 218 return (mysig_t) -1; 219 } 220 return (osa.sa_handler); 221 #else 222 #undef signal 223 return (signal(sig, act)); 224 #endif 225 } 226