1 /* 2 * Copyright (c) 1999-2004 Damien Miller <djm@mindrot.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "includes.h" 18 #include "xmalloc.h" 19 20 RCSID("$Id: bsd-misc.c,v 1.21 2004/02/17 05:49:55 djm Exp $"); 21 22 /* 23 * NB. duplicate __progname in case it is an alias for argv[0] 24 * Otherwise it may get clobbered by setproctitle() 25 */ 26 char *ssh_get_progname(char *argv0) 27 { 28 #ifdef HAVE___PROGNAME 29 extern char *__progname; 30 31 return xstrdup(__progname); 32 #else 33 char *p; 34 35 if (argv0 == NULL) 36 return ("unknown"); /* XXX */ 37 p = strrchr(argv0, '/'); 38 if (p == NULL) 39 p = argv0; 40 else 41 p++; 42 43 return (xstrdup(p)); 44 #endif 45 } 46 47 #ifndef HAVE_SETLOGIN 48 int setlogin(const char *name) 49 { 50 return (0); 51 } 52 #endif /* !HAVE_SETLOGIN */ 53 54 #ifndef HAVE_INNETGR 55 int innetgr(const char *netgroup, const char *host, 56 const char *user, const char *domain) 57 { 58 return (0); 59 } 60 #endif /* HAVE_INNETGR */ 61 62 #if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) 63 int seteuid(uid_t euid) 64 { 65 return (setreuid(-1, euid)); 66 } 67 #endif /* !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) */ 68 69 #if !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) 70 int setegid(uid_t egid) 71 { 72 return(setresgid(-1, egid, -1)); 73 } 74 #endif /* !defined(HAVE_SETEGID) && defined(HAVE_SETRESGID) */ 75 76 #if !defined(HAVE_STRERROR) && defined(HAVE_SYS_ERRLIST) && defined(HAVE_SYS_NERR) 77 const char *strerror(int e) 78 { 79 extern int sys_nerr; 80 extern char *sys_errlist[]; 81 82 if ((e >= 0) && (e < sys_nerr)) 83 return (sys_errlist[e]); 84 85 return ("unlisted error"); 86 } 87 #endif 88 89 #ifndef HAVE_UTIMES 90 int utimes(char *filename, struct timeval *tvp) 91 { 92 struct utimbuf ub; 93 94 ub.actime = tvp[0].tv_sec; 95 ub.modtime = tvp[1].tv_sec; 96 97 return (utime(filename, &ub)); 98 } 99 #endif 100 101 #ifndef HAVE_TRUNCATE 102 int truncate(const char *path, off_t length) 103 { 104 int fd, ret, saverrno; 105 106 fd = open(path, O_WRONLY); 107 if (fd < 0) 108 return (-1); 109 110 ret = ftruncate(fd, length); 111 saverrno = errno; 112 close(fd); 113 if (ret == -1) 114 errno = saverrno; 115 116 return(ret); 117 } 118 #endif /* HAVE_TRUNCATE */ 119 120 #if !defined(HAVE_SETGROUPS) && defined(SETGROUPS_NOOP) 121 /* 122 * Cygwin setgroups should be a noop. 123 */ 124 int 125 setgroups(size_t size, const gid_t *list) 126 { 127 return (0); 128 } 129 #endif 130 131 #if !defined(HAVE_NANOSLEEP) && !defined(HAVE_NSLEEP) 132 int nanosleep(const struct timespec *req, struct timespec *rem) 133 { 134 int rc, saverrno; 135 extern int errno; 136 struct timeval tstart, tstop, tremain, time2wait; 137 138 TIMESPEC_TO_TIMEVAL(&time2wait, req) 139 (void) gettimeofday(&tstart, NULL); 140 rc = select(0, NULL, NULL, NULL, &time2wait); 141 if (rc == -1) { 142 saverrno = errno; 143 (void) gettimeofday (&tstop, NULL); 144 errno = saverrno; 145 tremain.tv_sec = time2wait.tv_sec - 146 (tstop.tv_sec - tstart.tv_sec); 147 tremain.tv_usec = time2wait.tv_usec - 148 (tstop.tv_usec - tstart.tv_usec); 149 tremain.tv_sec += tremain.tv_usec / 1000000L; 150 tremain.tv_usec %= 1000000L; 151 } else { 152 tremain.tv_sec = 0; 153 tremain.tv_usec = 0; 154 } 155 TIMEVAL_TO_TIMESPEC(&tremain, rem) 156 157 return(rc); 158 } 159 #endif 160 161 #ifndef HAVE_TCGETPGRP 162 pid_t 163 tcgetpgrp(int fd) 164 { 165 int ctty_pgrp; 166 167 if (ioctl(fd, TIOCGPGRP, &ctty_pgrp) == -1) 168 return(-1); 169 else 170 return(ctty_pgrp); 171 } 172 #endif /* HAVE_TCGETPGRP */ 173 174 #ifndef HAVE_TCSENDBREAK 175 int 176 tcsendbreak(int fd, int duration) 177 { 178 # if defined(TIOCSBRK) && defined(TIOCCBRK) 179 struct timeval sleepytime; 180 181 sleepytime.tv_sec = 0; 182 sleepytime.tv_usec = 400000; 183 if (ioctl(fd, TIOCSBRK, 0) == -1) 184 return (-1); 185 (void)select(0, 0, 0, 0, &sleepytime); 186 if (ioctl(fd, TIOCCBRK, 0) == -1) 187 return (-1); 188 return (0); 189 # else 190 return -1; 191 # endif 192 } 193 #endif /* HAVE_TCSENDBREAK */ 194 195 mysig_t 196 mysignal(int sig, mysig_t act) 197 { 198 #ifdef HAVE_SIGACTION 199 struct sigaction sa, osa; 200 201 if (sigaction(sig, NULL, &osa) == -1) 202 return (mysig_t) -1; 203 if (osa.sa_handler != act) { 204 memset(&sa, 0, sizeof(sa)); 205 sigemptyset(&sa.sa_mask); 206 sa.sa_flags = 0; 207 #ifdef SA_INTERRUPT 208 if (sig == SIGALRM) 209 sa.sa_flags |= SA_INTERRUPT; 210 #endif 211 sa.sa_handler = act; 212 if (sigaction(sig, &sa, NULL) == -1) 213 return (mysig_t) -1; 214 } 215 return (osa.sa_handler); 216 #else 217 #undef signal 218 return (signal(sig, act)); 219 #endif 220 } 221