Blob


1 #include "config.h"
2 #if !HAVE_ERR
3 /*
4 * Copyright (c) 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
32 #include <errno.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
38 void
39 vwarnx(const char *fmt, va_list ap)
40 {
41 fprintf(stderr, "%s: ", getprogname());
42 if (fmt != NULL)
43 vfprintf(stderr, fmt, ap);
44 fprintf(stderr, "\n");
45 }
47 void
48 vwarnc(int code, const char *fmt, va_list ap)
49 {
50 fprintf(stderr, "%s: ", getprogname());
51 if (fmt != NULL) {
52 vfprintf(stderr, fmt, ap);
53 fprintf(stderr, ": ");
54 }
55 fprintf(stderr, "%s\n", strerror(code));
56 }
58 void
59 vwarn(const char *fmt, va_list ap)
60 {
61 int sverrno;
63 sverrno = errno;
64 fprintf(stderr, "%s: ", getprogname());
65 if (fmt != NULL) {
66 vfprintf(stderr, fmt, ap);
67 fprintf(stderr, ": ");
68 }
69 fprintf(stderr, "%s\n", strerror(sverrno));
70 }
72 void
73 verrc(int eval, int code, const char *fmt, va_list ap)
74 {
75 fprintf(stderr, "%s: ", getprogname());
76 if (fmt != NULL) {
77 vfprintf(stderr, fmt, ap);
78 fprintf(stderr, ": ");
79 }
80 fprintf(stderr, "%s\n", strerror(code));
81 exit(eval);
82 }
84 void
85 verrx(int eval, const char *fmt, va_list ap)
86 {
87 fprintf(stderr, "%s: ", getprogname());
88 if (fmt != NULL)
89 vfprintf(stderr, fmt, ap);
90 fprintf(stderr, "\n");
91 exit(eval);
92 }
94 void
95 verr(int eval, const char *fmt, va_list ap)
96 {
97 int sverrno;
99 sverrno = errno;
100 fprintf(stderr, "%s: ", getprogname());
101 if (fmt != NULL) {
102 vfprintf(stderr, fmt, ap);
103 fprintf(stderr, ": ");
105 fprintf(stderr, "%s\n", strerror(sverrno));
106 exit(eval);
109 void
110 err(int eval, const char *fmt, ...)
112 va_list ap;
114 va_start(ap, fmt);
115 verr(eval, fmt, ap);
116 va_end(ap);
119 void
120 errc(int eval, int code, const char *fmt, ...)
122 va_list ap;
124 va_start(ap, fmt);
125 verrc(eval, code, fmt, ap);
126 va_end(ap);
129 void
130 errx(int eval, const char *fmt, ...)
132 va_list ap;
134 va_start(ap, fmt);
135 verrx(eval, fmt, ap);
136 va_end(ap);
139 void
140 warn(const char *fmt, ...)
142 va_list ap;
144 va_start(ap, fmt);
145 vwarn(fmt, ap);
146 va_end(ap);
149 void
150 warnc(int code, const char *fmt, ...)
152 va_list ap;
154 va_start(ap, fmt);
155 vwarnc(code, fmt, ap);
156 va_end(ap);
159 void
160 warnx(const char *fmt, ...)
162 va_list ap;
164 va_start(ap, fmt);
165 vwarnx(fmt, ap);
166 va_end(ap);
168 #endif /* !HAVE_ERR */
169 #if !HAVE_FLOCK
170 #include <errno.h>
171 #include <fcntl.h>
172 #include <string.h>
174 /*
175 * flock(2) emulation on top of fcntl advisory locks. This is "good
176 * enough" for amused, not a _real_ emulation. flock and fcntl locks
177 * have subtly different behaviours!
178 */
179 int
180 flock(int fd, int op)
182 struct flock l;
183 int cmd;
185 memset(&l, 0, sizeof(l));
186 l.l_whence = SEEK_SET;
188 if (op & LOCK_SH)
189 l.l_type = F_RDLCK;
190 else if (op & LOCK_EX)
191 l.l_type = F_WRLCK;
192 else {
193 errno = EINVAL;
194 return -1;
197 cmd = F_SETLKW;
198 if (op & LOCK_NB)
199 cmd = F_SETLK;
201 return fcntl(fd, cmd, &l);
203 #endif /* HAVE_FLOCK */
204 #if !HAVE_FREEZERO
205 #include <stdlib.h>
206 #include <string.h>
208 void
209 freezero(void *ptr, size_t len)
211 if (ptr == NULL)
212 return;
213 memset(ptr, 0, len);
214 free(ptr);
216 #endif /* HAVE_FREEZERO */
217 #if !HAVE_EXPLICIT_BZERO
218 /* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */
219 /*
220 * Public domain.
221 * Written by Ted Unangst
222 */
224 #include <string.h>
226 /*
227 * explicit_bzero - don't let the compiler optimize away bzero
228 */
230 #if HAVE_MEMSET_S
232 void
233 explicit_bzero(void *p, size_t n)
235 if (n == 0)
236 return;
237 (void)memset_s(p, n, 0, n);
240 #else /* HAVE_MEMSET_S */
242 #include <strings.h>
244 /*
245 * Indirect memset through a volatile pointer to hopefully avoid
246 * dead-store optimisation eliminating the call.
247 */
248 static void (* volatile ssh_memset)(void *, int, size_t) =
249 (void (*volatile)(void *, int, size_t))memset;
251 void
252 explicit_bzero(void *p, size_t n)
254 if (n == 0)
255 return;
256 /*
257 * clang -fsanitize=memory needs to intercept memset-like functions
258 * to correctly detect memory initialisation. Make sure one is called
259 * directly since our indirection trick above sucessfully confuses it.
260 */
261 #if defined(__has_feature)
262 # if __has_feature(memory_sanitizer)
263 memset(p, 0, n);
264 # endif
265 #endif
267 ssh_memset(p, 0, n);
270 #endif /* HAVE_MEMSET_S */
271 #endif /* !HAVE_EXPLICIT_BZERO */
272 #if !HAVE_GETDTABLESIZE
273 /* public domain */
274 #include <unistd.h>
276 int
277 getdtablesize(void)
279 return sysconf(_SC_OPEN_MAX);
281 #endif /* !HAVE_GETDTABLESIZE */
282 #if !HAVE_GETPROGNAME
283 /*
284 * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
285 * Copyright (c) 2017 Kristaps Dzonsons <kristaps@bsd.lv>
286 * Copyright (c) 2020 Stephen Gregoratto <dev@sgregoratto.me>
288 * Permission to use, copy, modify, and distribute this software for any
289 * purpose with or without fee is hereby granted, provided that the above
290 * copyright notice and this permission notice appear in all copies.
292 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
293 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
294 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
295 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
296 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
297 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
298 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
299 */
301 #include <sys/types.h>
303 #include <errno.h>
305 #if HAVE_GETEXECNAME
306 #include <stdlib.h>
307 const char *
308 getprogname(void)
310 return getexecname();
312 #elif HAVE_PROGRAM_INVOCATION_SHORT_NAME
313 const char *
314 getprogname(void)
316 return (program_invocation_short_name);
318 #elif HAVE___PROGNAME
319 const char *
320 getprogname(void)
322 extern char *__progname;
324 return (__progname);
326 #else
327 #warning No getprogname available.
328 const char *
329 getprogname(void)
331 return ("amused");
333 #endif
334 #endif /* !HAVE_GETPROGNAME */
335 #if !HAVE_LIB_IMSG
336 /* $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $ */
337 /* $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 claudio Exp $ */
339 /*
340 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
342 * Permission to use, copy, modify, and distribute this software for any
343 * purpose with or without fee is hereby granted, provided that the above
344 * copyright notice and this permission notice appear in all copies.
346 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
347 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
348 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
349 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
350 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
351 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
352 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
353 */
355 #include "config.h"
357 #include <sys/types.h>
358 #include <sys/socket.h>
359 #include <sys/uio.h>
361 #include <limits.h>
362 #include <errno.h>
363 #include <endian.h>
364 #include <stdlib.h>
365 #include <string.h>
366 #include <unistd.h>
368 #include "imsg.h"
370 static int ibuf_realloc(struct ibuf *, size_t);
371 static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
372 static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
373 static void msgbuf_drain(struct msgbuf *, size_t);
375 struct ibuf *
376 ibuf_open(size_t len)
378 struct ibuf *buf;
380 if (len == 0) {
381 errno = EINVAL;
382 return (NULL);
384 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
385 return (NULL);
386 if ((buf->buf = calloc(len, 1)) == NULL) {
387 free(buf);
388 return (NULL);
390 buf->size = buf->max = len;
391 buf->fd = -1;
393 return (buf);
396 struct ibuf *
397 ibuf_dynamic(size_t len, size_t max)
399 struct ibuf *buf;
401 if (max < len) {
402 errno = EINVAL;
403 return (NULL);
406 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
407 return (NULL);
408 if (len > 0) {
409 if ((buf->buf = calloc(len, 1)) == NULL) {
410 free(buf);
411 return (NULL);
414 buf->size = len;
415 buf->max = max;
416 buf->fd = -1;
418 return (buf);
421 static int
422 ibuf_realloc(struct ibuf *buf, size_t len)
424 unsigned char *b;
426 /* on static buffers max is eq size and so the following fails */
427 if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
428 errno = ERANGE;
429 return (-1);
432 b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
433 if (b == NULL)
434 return (-1);
435 buf->buf = b;
436 buf->size = buf->wpos + len;
438 return (0);
441 void *
442 ibuf_reserve(struct ibuf *buf, size_t len)
444 void *b;
446 if (len > SIZE_MAX - buf->wpos) {
447 errno = ERANGE;
448 return (NULL);
451 if (buf->wpos + len > buf->size)
452 if (ibuf_realloc(buf, len) == -1)
453 return (NULL);
455 b = buf->buf + buf->wpos;
456 buf->wpos += len;
457 memset(b, 0, len);
458 return (b);
461 int
462 ibuf_add(struct ibuf *buf, const void *data, size_t len)
464 void *b;
466 if ((b = ibuf_reserve(buf, len)) == NULL)
467 return (-1);
469 memcpy(b, data, len);
470 return (0);
473 int
474 ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
476 return ibuf_add(buf, from->buf, from->wpos);
479 int
480 ibuf_add_n8(struct ibuf *buf, uint64_t value)
482 uint8_t v;
484 if (value > UINT8_MAX) {
485 errno = EINVAL;
486 return (-1);
488 v = value;
489 return ibuf_add(buf, &v, sizeof(v));
492 int
493 ibuf_add_n16(struct ibuf *buf, uint64_t value)
495 uint16_t v;
497 if (value > UINT16_MAX) {
498 errno = EINVAL;
499 return (-1);
501 v = htobe16(value);
502 return ibuf_add(buf, &v, sizeof(v));
505 int
506 ibuf_add_n32(struct ibuf *buf, uint64_t value)
508 uint32_t v;
510 if (value > UINT32_MAX) {
511 errno = EINVAL;
512 return (-1);
514 v = htobe32(value);
515 return ibuf_add(buf, &v, sizeof(v));
518 int
519 ibuf_add_n64(struct ibuf *buf, uint64_t value)
521 value = htobe64(value);
522 return ibuf_add(buf, &value, sizeof(value));
525 int
526 ibuf_add_zero(struct ibuf *buf, size_t len)
528 void *b;
530 if ((b = ibuf_reserve(buf, len)) == NULL)
531 return (-1);
532 return (0);
535 void *
536 ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
538 /* only allowed to seek in already written parts */
539 if (len > SIZE_MAX - pos || pos + len > buf->wpos) {
540 errno = ERANGE;
541 return (NULL);
544 return (buf->buf + pos);
547 int
548 ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
550 void *b;
552 if ((b = ibuf_seek(buf, pos, len)) == NULL)
553 return (-1);
555 memcpy(b, data, len);
556 return (0);
559 int
560 ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
562 uint8_t v;
564 if (value > UINT8_MAX) {
565 errno = EINVAL;
566 return (-1);
568 v = value;
569 return (ibuf_set(buf, pos, &v, sizeof(v)));
572 int
573 ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
575 uint16_t v;
577 if (value > UINT16_MAX) {
578 errno = EINVAL;
579 return (-1);
581 v = htobe16(value);
582 return (ibuf_set(buf, pos, &v, sizeof(v)));
585 int
586 ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
588 uint32_t v;
590 if (value > UINT32_MAX) {
591 errno = EINVAL;
592 return (-1);
594 v = htobe32(value);
595 return (ibuf_set(buf, pos, &v, sizeof(v)));
598 int
599 ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
601 value = htobe64(value);
602 return (ibuf_set(buf, pos, &value, sizeof(value)));
605 void *
606 ibuf_data(struct ibuf *buf)
608 return (buf->buf);
611 size_t
612 ibuf_size(struct ibuf *buf)
614 return (buf->wpos);
617 size_t
618 ibuf_left(struct ibuf *buf)
620 return (buf->max - buf->wpos);
623 void
624 ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
626 ibuf_enqueue(msgbuf, buf);
629 void
630 ibuf_free(struct ibuf *buf)
632 if (buf == NULL)
633 return;
634 #ifdef NOTYET
635 if (buf->fd != -1)
636 close(buf->fd);
637 #endif
638 freezero(buf->buf, buf->size);
639 free(buf);
642 int
643 ibuf_fd_avail(struct ibuf *buf)
645 return (buf->fd != -1);
648 int
649 ibuf_fd_get(struct ibuf *buf)
651 int fd;
653 fd = buf->fd;
654 #ifdef NOTYET
655 buf->fd = -1;
656 #endif
657 return (fd);
660 void
661 ibuf_fd_set(struct ibuf *buf, int fd)
663 if (buf->fd != -1)
664 close(buf->fd);
665 buf->fd = fd;
668 int
669 ibuf_write(struct msgbuf *msgbuf)
671 struct iovec iov[IOV_MAX];
672 struct ibuf *buf;
673 unsigned int i = 0;
674 ssize_t n;
676 memset(&iov, 0, sizeof(iov));
677 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
678 if (i >= IOV_MAX)
679 break;
680 iov[i].iov_base = buf->buf + buf->rpos;
681 iov[i].iov_len = buf->wpos - buf->rpos;
682 i++;
685 again:
686 if ((n = writev(msgbuf->fd, iov, i)) == -1) {
687 if (errno == EINTR)
688 goto again;
689 if (errno == ENOBUFS)
690 errno = EAGAIN;
691 return (-1);
694 if (n == 0) { /* connection closed */
695 errno = 0;
696 return (0);
699 msgbuf_drain(msgbuf, n);
701 return (1);
704 void
705 msgbuf_init(struct msgbuf *msgbuf)
707 msgbuf->queued = 0;
708 msgbuf->fd = -1;
709 TAILQ_INIT(&msgbuf->bufs);
712 static void
713 msgbuf_drain(struct msgbuf *msgbuf, size_t n)
715 struct ibuf *buf, *next;
717 for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
718 buf = next) {
719 next = TAILQ_NEXT(buf, entry);
720 if (n >= buf->wpos - buf->rpos) {
721 n -= buf->wpos - buf->rpos;
722 ibuf_dequeue(msgbuf, buf);
723 } else {
724 buf->rpos += n;
725 n = 0;
730 void
731 msgbuf_clear(struct msgbuf *msgbuf)
733 struct ibuf *buf;
735 while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
736 ibuf_dequeue(msgbuf, buf);
739 int
740 msgbuf_write(struct msgbuf *msgbuf)
742 struct iovec iov[IOV_MAX];
743 struct ibuf *buf, *buf0 = NULL;
744 unsigned int i = 0;
745 ssize_t n;
746 struct msghdr msg;
747 struct cmsghdr *cmsg;
748 union {
749 struct cmsghdr hdr;
750 char buf[CMSG_SPACE(sizeof(int))];
751 } cmsgbuf;
753 memset(&iov, 0, sizeof(iov));
754 memset(&msg, 0, sizeof(msg));
755 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
756 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
757 if (i >= IOV_MAX)
758 break;
759 if (i > 0 && buf->fd != -1)
760 break;
761 iov[i].iov_base = buf->buf + buf->rpos;
762 iov[i].iov_len = buf->wpos - buf->rpos;
763 i++;
764 if (buf->fd != -1)
765 buf0 = buf;
768 msg.msg_iov = iov;
769 msg.msg_iovlen = i;
771 if (buf0 != NULL) {
772 msg.msg_control = (caddr_t)&cmsgbuf.buf;
773 msg.msg_controllen = sizeof(cmsgbuf.buf);
774 cmsg = CMSG_FIRSTHDR(&msg);
775 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
776 cmsg->cmsg_level = SOL_SOCKET;
777 cmsg->cmsg_type = SCM_RIGHTS;
778 *(int *)CMSG_DATA(cmsg) = buf0->fd;
781 again:
782 if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
783 if (errno == EINTR)
784 goto again;
785 if (errno == ENOBUFS)
786 errno = EAGAIN;
787 return (-1);
790 if (n == 0) { /* connection closed */
791 errno = 0;
792 return (0);
795 /*
796 * assumption: fd got sent if sendmsg sent anything
797 * this works because fds are passed one at a time
798 */
799 if (buf0 != NULL) {
800 close(buf0->fd);
801 buf0->fd = -1;
804 msgbuf_drain(msgbuf, n);
806 return (1);
809 static void
810 ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
812 TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
813 msgbuf->queued++;
816 static void
817 ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
819 TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
821 if (buf->fd != -1) {
822 close(buf->fd);
823 buf->fd = -1;
826 msgbuf->queued--;
827 ibuf_free(buf);
830 /* imsg.c */
832 int imsg_fd_overhead = 0;
834 static int imsg_get_fd(struct imsgbuf *);
836 void
837 imsg_init(struct imsgbuf *ibuf, int fd)
839 msgbuf_init(&ibuf->w);
840 memset(&ibuf->r, 0, sizeof(ibuf->r));
841 ibuf->fd = fd;
842 ibuf->w.fd = fd;
843 ibuf->pid = getpid();
844 TAILQ_INIT(&ibuf->fds);
847 ssize_t
848 imsg_read(struct imsgbuf *ibuf)
850 struct msghdr msg;
851 struct cmsghdr *cmsg;
852 union {
853 struct cmsghdr hdr;
854 char buf[CMSG_SPACE(sizeof(int) * 1)];
855 } cmsgbuf;
856 struct iovec iov;
857 ssize_t n = -1;
858 int fd;
859 struct imsg_fd *ifd;
861 memset(&msg, 0, sizeof(msg));
862 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
864 iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
865 iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
866 msg.msg_iov = &iov;
867 msg.msg_iovlen = 1;
868 msg.msg_control = &cmsgbuf.buf;
869 msg.msg_controllen = sizeof(cmsgbuf.buf);
871 if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
872 return (-1);
874 again:
875 if (getdtablecount() + imsg_fd_overhead +
876 (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
877 >= getdtablesize()) {
878 errno = EAGAIN;
879 free(ifd);
880 return (-1);
883 if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
884 if (errno == EINTR)
885 goto again;
886 goto fail;
889 ibuf->r.wpos += n;
891 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
892 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
893 if (cmsg->cmsg_level == SOL_SOCKET &&
894 cmsg->cmsg_type == SCM_RIGHTS) {
895 int i;
896 int j;
898 /*
899 * We only accept one file descriptor. Due to C
900 * padding rules, our control buffer might contain
901 * more than one fd, and we must close them.
902 */
903 j = ((char *)cmsg + cmsg->cmsg_len -
904 (char *)CMSG_DATA(cmsg)) / sizeof(int);
905 for (i = 0; i < j; i++) {
906 fd = ((int *)CMSG_DATA(cmsg))[i];
907 if (ifd != NULL) {
908 ifd->fd = fd;
909 TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
910 entry);
911 ifd = NULL;
912 } else
913 close(fd);
916 /* we do not handle other ctl data level */
919 fail:
920 free(ifd);
921 return (n);
924 ssize_t
925 imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
927 size_t av, left, datalen;
929 av = ibuf->r.wpos;
931 if (IMSG_HEADER_SIZE > av)
932 return (0);
934 memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
935 if (imsg->hdr.len < IMSG_HEADER_SIZE ||
936 imsg->hdr.len > MAX_IMSGSIZE) {
937 errno = ERANGE;
938 return (-1);
940 if (imsg->hdr.len > av)
941 return (0);
942 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
943 ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
944 if (datalen == 0)
945 imsg->data = NULL;
946 else if ((imsg->data = malloc(datalen)) == NULL)
947 return (-1);
949 if (imsg->hdr.flags & IMSGF_HASFD)
950 imsg->fd = imsg_get_fd(ibuf);
951 else
952 imsg->fd = -1;
954 if (datalen != 0)
955 memcpy(imsg->data, ibuf->r.rptr, datalen);
957 if (imsg->hdr.len < av) {
958 left = av - imsg->hdr.len;
959 memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
960 ibuf->r.wpos = left;
961 } else
962 ibuf->r.wpos = 0;
964 return (datalen + IMSG_HEADER_SIZE);
967 int
968 imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
969 int fd, const void *data, uint16_t datalen)
971 struct ibuf *wbuf;
973 if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
974 return (-1);
976 if (imsg_add(wbuf, data, datalen) == -1)
977 return (-1);
979 ibuf_fd_set(wbuf, fd);
980 imsg_close(ibuf, wbuf);
982 return (1);
985 int
986 imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
987 int fd, const struct iovec *iov, int iovcnt)
989 struct ibuf *wbuf;
990 int i, datalen = 0;
992 for (i = 0; i < iovcnt; i++)
993 datalen += iov[i].iov_len;
995 if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
996 return (-1);
998 for (i = 0; i < iovcnt; i++)
999 if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
1000 return (-1);
1002 ibuf_fd_set(wbuf, fd);
1003 imsg_close(ibuf, wbuf);
1005 return (1);
1008 int
1009 imsg_compose_ibuf(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid,
1010 pid_t pid, struct ibuf *buf)
1012 struct ibuf *wbuf = NULL;
1013 struct imsg_hdr hdr;
1014 int save_errno;
1016 if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
1017 errno = ERANGE;
1018 goto fail;
1021 hdr.type = type;
1022 hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
1023 hdr.flags = 0;
1024 hdr.peerid = peerid;
1025 if ((hdr.pid = pid) == 0)
1026 hdr.pid = ibuf->pid;
1028 if ((wbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
1029 goto fail;
1030 if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
1031 goto fail;
1033 ibuf_close(&ibuf->w, wbuf);
1034 ibuf_close(&ibuf->w, buf);
1035 return (1);
1037 fail:
1038 save_errno = errno;
1039 ibuf_free(buf);
1040 ibuf_free(wbuf);
1041 errno = save_errno;
1042 return (-1);
1045 struct ibuf *
1046 imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
1047 uint16_t datalen)
1049 struct ibuf *wbuf;
1050 struct imsg_hdr hdr;
1052 datalen += IMSG_HEADER_SIZE;
1053 if (datalen > MAX_IMSGSIZE) {
1054 errno = ERANGE;
1055 return (NULL);
1058 hdr.type = type;
1059 hdr.flags = 0;
1060 hdr.peerid = peerid;
1061 if ((hdr.pid = pid) == 0)
1062 hdr.pid = ibuf->pid;
1063 if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
1064 return (NULL);
1066 if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
1067 return (NULL);
1069 return (wbuf);
1072 int
1073 imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
1075 if (datalen)
1076 if (ibuf_add(msg, data, datalen) == -1) {
1077 ibuf_free(msg);
1078 return (-1);
1080 return (datalen);
1083 void
1084 imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
1086 struct imsg_hdr *hdr;
1088 hdr = (struct imsg_hdr *)msg->buf;
1090 hdr->flags &= ~IMSGF_HASFD;
1091 if (ibuf_fd_avail(msg))
1092 hdr->flags |= IMSGF_HASFD;
1093 hdr->len = ibuf_size(msg);
1095 ibuf_close(&ibuf->w, msg);
1098 void
1099 imsg_free(struct imsg *imsg)
1101 freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
1104 static int
1105 imsg_get_fd(struct imsgbuf *ibuf)
1107 int fd;
1108 struct imsg_fd *ifd;
1110 if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
1111 return (-1);
1113 fd = ifd->fd;
1114 TAILQ_REMOVE(&ibuf->fds, ifd, entry);
1115 free(ifd);
1117 return (fd);
1120 int
1121 imsg_flush(struct imsgbuf *ibuf)
1123 while (ibuf->w.queued)
1124 if (msgbuf_write(&ibuf->w) <= 0)
1125 return (-1);
1126 return (0);
1129 void
1130 imsg_clear(struct imsgbuf *ibuf)
1132 int fd;
1134 msgbuf_clear(&ibuf->w);
1135 while ((fd = imsg_get_fd(ibuf)) != -1)
1136 close(fd);
1138 #endif /* HAVE_LIB_IMSG */
1139 #if !HAVE_MEMMEM
1140 /*-
1141 * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
1143 * Redistribution and use in source and binary forms, with or without
1144 * modification, are permitted provided that the following conditions
1145 * are met:
1146 * 1. Redistributions of source code must retain the above copyright
1147 * notice, this list of conditions and the following disclaimer.
1148 * 2. Redistributions in binary form must reproduce the above copyright
1149 * notice, this list of conditions and the following disclaimer in
1150 * the documentation and/or other materials provided with the
1151 * distribution.
1152 * 3. The name of the author may not be used to endorse or promote
1153 * products derived from this software without specific prior written
1154 * permission.
1156 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
1157 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1158 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
1159 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
1160 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1161 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1162 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1163 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1164 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1165 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1166 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1169 * Find the first occurrence of the byte string s in byte string l.
1171 void *
1172 memmem(const void *l, size_t l_len, const void *s, size_t s_len)
1174 const char *cur, *last;
1175 const char *cl = l;
1176 const char *cs = s;
1178 /* a zero length needle should just return the haystack */
1179 if (l_len == 0)
1180 return (void *)cl;
1182 /* "s" must be smaller or equal to "l" */
1183 if (l_len < s_len)
1184 return NULL;
1186 /* special case where s_len == 1 */
1187 if (s_len == 1)
1188 return memchr(l, *cs, l_len);
1190 /* the last position where its possible to find "s" in "l" */
1191 last = cl + l_len - s_len;
1193 for (cur = cl; cur <= last; cur++)
1194 if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
1195 return (void *)cur;
1197 return NULL;
1199 #endif /* !HAVE_MEMMEM */
1200 #if !HAVE_MEMRCHR
1202 * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
1204 * Permission to use, copy, modify, and distribute this software for any
1205 * purpose with or without fee is hereby granted, provided that the above
1206 * copyright notice and this permission notice appear in all copies.
1208 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1209 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1210 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1211 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1212 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1213 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1214 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1218 #include <string.h>
1221 * Reverse memchr()
1222 * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
1224 void *
1225 memrchr(const void *s, int c, size_t n)
1227 const unsigned char *cp;
1229 if (n != 0) {
1230 cp = (unsigned char *)s + n;
1231 do {
1232 if (*(--cp) == (unsigned char)c)
1233 return((void *)cp);
1234 } while (--n != 0);
1236 return(NULL);
1238 #endif /* !HAVE_MEMRCHR */
1239 #if !HAVE_OPTRESET
1241 * Copyright (c) 1987, 1993, 1994
1242 * The Regents of the University of California. All rights reserved.
1244 * Redistribution and use in source and binary forms, with or without
1245 * modification, are permitted provided that the following conditions
1246 * are met:
1247 * 1. Redistributions of source code must retain the above copyright
1248 * notice, this list of conditions and the following disclaimer.
1249 * 2. Redistributions in binary form must reproduce the above copyright
1250 * notice, this list of conditions and the following disclaimer in the
1251 * documentation and/or other materials provided with the distribution.
1252 * 3. Neither the name of the University nor the names of its contributors
1253 * may be used to endorse or promote products derived from this software
1254 * without specific prior written permission.
1256 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1257 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1258 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1259 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1260 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1261 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1262 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1263 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1264 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1265 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1266 * SUCH DAMAGE.
1269 /* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
1271 #include <stdio.h>
1272 #include <stdlib.h>
1273 #include <string.h>
1275 int BSDopterr = 1, /* if error message should be printed */
1276 BSDoptind = 1, /* index into parent argv vector */
1277 BSDoptopt, /* character checked for validity */
1278 BSDoptreset; /* reset getopt */
1279 char *BSDoptarg; /* argument associated with option */
1281 #define BADCH (int)'?'
1282 #define BADARG (int)':'
1283 #define EMSG ""
1286 * getopt --
1287 * Parse argc/argv argument vector.
1289 int
1290 BSDgetopt(int nargc, char *const *nargv, const char *ostr)
1292 static const char *place = EMSG; /* option letter processing */
1293 char *oli; /* option letter list index */
1295 if (ostr == NULL)
1296 return (-1);
1298 if (BSDoptreset || !*place) { /* update scanning pointer */
1299 BSDoptreset = 0;
1300 if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
1301 place = EMSG;
1302 return (-1);
1304 if (place[1] && *++place == '-') { /* found "--" */
1305 if (place[1])
1306 return (BADCH);
1307 ++BSDoptind;
1308 place = EMSG;
1309 return (-1);
1311 } /* option letter okay? */
1312 if ((BSDoptopt = (int)*place++) == (int)':' ||
1313 !(oli = strchr(ostr, BSDoptopt))) {
1315 * if the user didn't specify '-' as an option,
1316 * assume it means -1.
1318 if (BSDoptopt == (int)'-')
1319 return (-1);
1320 if (!*place)
1321 ++BSDoptind;
1322 if (BSDopterr && *ostr != ':')
1323 (void)fprintf(stderr,
1324 "%s: unknown option -- %c\n", getprogname(),
1325 BSDoptopt);
1326 return (BADCH);
1328 if (*++oli != ':') { /* don't need argument */
1329 BSDoptarg = NULL;
1330 if (!*place)
1331 ++BSDoptind;
1333 else { /* need an argument */
1334 if (*place) /* no white space */
1335 BSDoptarg = (char *)place;
1336 else if (nargc <= ++BSDoptind) { /* no arg */
1337 place = EMSG;
1338 if (*ostr == ':')
1339 return (BADARG);
1340 if (BSDopterr)
1341 (void)fprintf(stderr,
1342 "%s: option requires an argument -- %c\n",
1343 getprogname(), BSDoptopt);
1344 return (BADCH);
1346 else /* white space */
1347 BSDoptarg = nargv[BSDoptind];
1348 place = EMSG;
1349 ++BSDoptind;
1351 return (BSDoptopt); /* dump back option letter */
1353 #endif
1354 #if !HAVE_REALLOCARRAY
1356 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
1358 * Permission to use, copy, modify, and distribute this software for any
1359 * purpose with or without fee is hereby granted, provided that the above
1360 * copyright notice and this permission notice appear in all copies.
1362 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1363 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1364 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1365 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1366 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1367 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1368 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1371 #include <sys/types.h>
1372 #include <errno.h>
1373 #include <stdint.h>
1374 #include <stdlib.h>
1377 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1378 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1380 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1382 void *
1383 reallocarray(void *optr, size_t nmemb, size_t size)
1385 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1386 nmemb > 0 && SIZE_MAX / nmemb < size) {
1387 errno = ENOMEM;
1388 return NULL;
1390 return realloc(optr, size * nmemb);
1392 #endif /* !HAVE_REALLOCARRAY */
1393 #if !HAVE_RECALLOCARRAY
1395 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
1397 * Permission to use, copy, modify, and distribute this software for any
1398 * purpose with or without fee is hereby granted, provided that the above
1399 * copyright notice and this permission notice appear in all copies.
1401 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1402 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1403 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1404 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1405 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1406 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1407 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1410 /* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */
1412 #include <errno.h>
1413 #include <stdlib.h>
1414 #include <stdint.h>
1415 #include <string.h>
1416 #include <unistd.h>
1419 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1420 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1422 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1424 void *
1425 recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
1427 size_t oldsize, newsize;
1428 void *newptr;
1430 if (ptr == NULL)
1431 return calloc(newnmemb, size);
1433 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1434 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
1435 errno = ENOMEM;
1436 return NULL;
1438 newsize = newnmemb * size;
1440 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1441 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
1442 errno = EINVAL;
1443 return NULL;
1445 oldsize = oldnmemb * size;
1448 * Don't bother too much if we're shrinking just a bit,
1449 * we do not shrink for series of small steps, oh well.
1451 if (newsize <= oldsize) {
1452 size_t d = oldsize - newsize;
1454 if (d < oldsize / 2 && d < (size_t)getpagesize()) {
1455 memset((char *)ptr + newsize, 0, d);
1456 return ptr;
1460 newptr = malloc(newsize);
1461 if (newptr == NULL)
1462 return NULL;
1464 if (newsize > oldsize) {
1465 memcpy(newptr, ptr, oldsize);
1466 memset((char *)newptr + oldsize, 0, newsize - oldsize);
1467 } else
1468 memcpy(newptr, ptr, newsize);
1470 explicit_bzero(ptr, oldsize);
1471 free(ptr);
1473 return newptr;
1475 #endif /* !HAVE_RECALLOCARRAY */
1476 #if !HAVE_SETPROCTITLE
1478 * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
1480 * Permission to use, copy, modify, and distribute this software for any
1481 * purpose with or without fee is hereby granted, provided that the above
1482 * copyright notice and this permission notice appear in all copies.
1484 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1485 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1486 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1487 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1488 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
1489 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1490 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1493 # if HAVE_PR_SET_NAME
1494 #include <sys/types.h>
1495 #include <stdarg.h>
1496 #include <stdio.h>
1497 #include <string.h>
1498 #include <sys/prctl.h>
1499 void
1500 setproctitle(const char *fmt, ...)
1502 char title[16], name[16], *cp;
1503 va_list ap;
1504 int used;
1506 va_start(ap, fmt);
1507 vsnprintf(title, sizeof(title), fmt, ap);
1508 va_end(ap);
1510 used = snprintf(name, sizeof(name), "%s: %s", getprogname(), title);
1511 if (used >= (int)sizeof(name)) {
1512 cp = strrchr(name, ' ');
1513 if (cp != NULL)
1514 *cp = '\0';
1516 prctl(PR_SET_NAME, name);
1518 # else
1519 void
1520 setproctitle(const char *fmt, ...)
1522 return;
1524 # endif
1525 #endif /* !HAVE_SETPROCTITLE */
1526 #if !HAVE_STRLCAT
1528 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1530 * Permission to use, copy, modify, and distribute this software for any
1531 * purpose with or without fee is hereby granted, provided that the above
1532 * copyright notice and this permission notice appear in all copies.
1534 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1535 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1536 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1537 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1538 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1539 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1540 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1543 #include <sys/types.h>
1544 #include <string.h>
1547 * Appends src to string dst of size siz (unlike strncat, siz is the
1548 * full size of dst, not space left). At most siz-1 characters
1549 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
1550 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
1551 * If retval >= siz, truncation occurred.
1553 size_t
1554 strlcat(char *dst, const char *src, size_t siz)
1556 char *d = dst;
1557 const char *s = src;
1558 size_t n = siz;
1559 size_t dlen;
1561 /* Find the end of dst and adjust bytes left but don't go past end */
1562 while (n-- != 0 && *d != '\0')
1563 d++;
1564 dlen = d - dst;
1565 n = siz - dlen;
1567 if (n == 0)
1568 return(dlen + strlen(s));
1569 while (*s != '\0') {
1570 if (n != 1) {
1571 *d++ = *s;
1572 n--;
1574 s++;
1576 *d = '\0';
1578 return(dlen + (s - src)); /* count does not include NUL */
1580 #endif /* !HAVE_STRLCAT */
1581 #if !HAVE_STRLCPY
1583 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1585 * Permission to use, copy, modify, and distribute this software for any
1586 * purpose with or without fee is hereby granted, provided that the above
1587 * copyright notice and this permission notice appear in all copies.
1589 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1590 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1591 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1592 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1593 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1594 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1595 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1598 #include <sys/types.h>
1599 #include <string.h>
1602 * Copy src to string dst of size siz. At most siz-1 characters
1603 * will be copied. Always NUL terminates (unless siz == 0).
1604 * Returns strlen(src); if retval >= siz, truncation occurred.
1606 size_t
1607 strlcpy(char *dst, const char *src, size_t siz)
1609 char *d = dst;
1610 const char *s = src;
1611 size_t n = siz;
1613 /* Copy as many bytes as will fit */
1614 if (n != 0) {
1615 while (--n != 0) {
1616 if ((*d++ = *s++) == '\0')
1617 break;
1621 /* Not enough room in dst, add NUL and traverse rest of src */
1622 if (n == 0) {
1623 if (siz != 0)
1624 *d = '\0'; /* NUL-terminate dst */
1625 while (*s++)
1629 return(s - src - 1); /* count does not include NUL */
1631 #endif /* !HAVE_STRLCPY */
1632 #if !HAVE_STRNDUP
1633 /* $OpenBSD$ */
1635 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1637 * Permission to use, copy, modify, and distribute this software for any
1638 * purpose with or without fee is hereby granted, provided that the above
1639 * copyright notice and this permission notice appear in all copies.
1641 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1642 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1643 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1644 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1645 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1646 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1647 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1650 #include <sys/types.h>
1652 #include <stddef.h>
1653 #include <stdlib.h>
1654 #include <string.h>
1656 char *
1657 strndup(const char *str, size_t maxlen)
1659 char *copy;
1660 size_t len;
1662 len = strnlen(str, maxlen);
1663 copy = malloc(len + 1);
1664 if (copy != NULL) {
1665 (void)memcpy(copy, str, len);
1666 copy[len] = '\0';
1669 return copy;
1671 #endif /* !HAVE_STRNDUP */
1672 #if !HAVE_STRNLEN
1673 /* $OpenBSD$ */
1676 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1678 * Permission to use, copy, modify, and distribute this software for any
1679 * purpose with or without fee is hereby granted, provided that the above
1680 * copyright notice and this permission notice appear in all copies.
1682 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1683 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1684 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1685 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1686 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1687 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1688 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1691 #include <sys/types.h>
1692 #include <string.h>
1694 size_t
1695 strnlen(const char *str, size_t maxlen)
1697 const char *cp;
1699 for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
1702 return (size_t)(cp - str);
1704 #endif /* !HAVE_STRNLEN */
1705 #if !HAVE_STRTONUM
1707 * Copyright (c) 2004 Ted Unangst and Todd Miller
1708 * All rights reserved.
1710 * Permission to use, copy, modify, and distribute this software for any
1711 * purpose with or without fee is hereby granted, provided that the above
1712 * copyright notice and this permission notice appear in all copies.
1714 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1715 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1716 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1717 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1718 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1719 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1720 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1723 #include <errno.h>
1724 #include <limits.h>
1725 #include <stdlib.h>
1727 #define INVALID 1
1728 #define TOOSMALL 2
1729 #define TOOLARGE 3
1731 long long
1732 strtonum(const char *numstr, long long minval, long long maxval,
1733 const char **errstrp)
1735 long long ll = 0;
1736 int error = 0;
1737 char *ep;
1738 struct errval {
1739 const char *errstr;
1740 int err;
1741 } ev[4] = {
1742 { NULL, 0 },
1743 { "invalid", EINVAL },
1744 { "too small", ERANGE },
1745 { "too large", ERANGE },
1748 ev[0].err = errno;
1749 errno = 0;
1750 if (minval > maxval) {
1751 error = INVALID;
1752 } else {
1753 ll = strtoll(numstr, &ep, 10);
1754 if (numstr == ep || *ep != '\0')
1755 error = INVALID;
1756 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
1757 error = TOOSMALL;
1758 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
1759 error = TOOLARGE;
1761 if (errstrp != NULL)
1762 *errstrp = ev[error].errstr;
1763 errno = ev[error].err;
1764 if (error)
1765 ll = 0;
1767 return (ll);
1769 #endif /* !HAVE_STRTONUM */
1770 #if !HAVE_TIMESPECSUB
1771 #include <sys/time.h>
1772 void
1773 timespecsub(struct timespec *a, struct timespec *b, struct timespec *ret)
1775 ret->tv_sec = a->tv_sec - b->tv_sec;
1776 ret->tv_nsec = a->tv_nsec - b->tv_nsec;
1777 if (ret->tv_nsec < 0) {
1778 ret->tv_sec--;
1779 ret->tv_nsec += 1000000000L;
1782 #endif /* !HAVE_TIMESPECSUB */