bsd-misc.c 8.1 KB

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