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.18 2023/12/12 15:47:41 claudio Exp $ */
337 /* $OpenBSD: imsg.c,v 1.23 2023/12/12 15:47:41 claudio Exp $ */
339 /*
340 * Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
341 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
343 * Permission to use, copy, modify, and distribute this software for any
344 * purpose with or without fee is hereby granted, provided that the above
345 * copyright notice and this permission notice appear in all copies.
347 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
348 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
349 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
350 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
351 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
352 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
353 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
354 */
356 #include <sys/types.h>
357 #include <sys/socket.h>
358 #include <sys/uio.h>
360 #include <limits.h>
361 #include <errno.h>
362 #include <endian.h>
363 #include <stdint.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 == 0 || 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 || buf->max == 0) {
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 return (b);
460 int
461 ibuf_add(struct ibuf *buf, const void *data, size_t len)
463 void *b;
465 if ((b = ibuf_reserve(buf, len)) == NULL)
466 return (-1);
468 memcpy(b, data, len);
469 return (0);
472 int
473 ibuf_add_ibuf(struct ibuf *buf, const struct ibuf *from)
475 return ibuf_add(buf, ibuf_data(from), ibuf_size(from));
478 /* remove after tree is converted */
479 int
480 ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
482 return ibuf_add_ibuf(buf, from);
485 int
486 ibuf_add_n8(struct ibuf *buf, uint64_t value)
488 uint8_t v;
490 if (value > UINT8_MAX) {
491 errno = EINVAL;
492 return (-1);
494 v = value;
495 return ibuf_add(buf, &v, sizeof(v));
498 int
499 ibuf_add_n16(struct ibuf *buf, uint64_t value)
501 uint16_t v;
503 if (value > UINT16_MAX) {
504 errno = EINVAL;
505 return (-1);
507 v = htobe16(value);
508 return ibuf_add(buf, &v, sizeof(v));
511 int
512 ibuf_add_n32(struct ibuf *buf, uint64_t value)
514 uint32_t v;
516 if (value > UINT32_MAX) {
517 errno = EINVAL;
518 return (-1);
520 v = htobe32(value);
521 return ibuf_add(buf, &v, sizeof(v));
524 int
525 ibuf_add_n64(struct ibuf *buf, uint64_t value)
527 value = htobe64(value);
528 return ibuf_add(buf, &value, sizeof(value));
531 int
532 ibuf_add_h16(struct ibuf *buf, uint64_t value)
534 uint16_t v;
536 if (value > UINT16_MAX) {
537 errno = EINVAL;
538 return (-1);
540 v = value;
541 return ibuf_add(buf, &v, sizeof(v));
544 int
545 ibuf_add_h32(struct ibuf *buf, uint64_t value)
547 uint32_t v;
549 if (value > UINT32_MAX) {
550 errno = EINVAL;
551 return (-1);
553 v = value;
554 return ibuf_add(buf, &v, sizeof(v));
557 int
558 ibuf_add_h64(struct ibuf *buf, uint64_t value)
560 return ibuf_add(buf, &value, sizeof(value));
563 int
564 ibuf_add_zero(struct ibuf *buf, size_t len)
566 void *b;
568 if ((b = ibuf_reserve(buf, len)) == NULL)
569 return (-1);
570 memset(b, 0, len);
571 return (0);
574 void *
575 ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
577 /* only allow seeking between rpos and wpos */
578 if (ibuf_size(buf) < pos || SIZE_MAX - pos < len ||
579 ibuf_size(buf) < pos + len) {
580 errno = ERANGE;
581 return (NULL);
584 return (buf->buf + buf->rpos + pos);
587 int
588 ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
590 void *b;
592 if ((b = ibuf_seek(buf, pos, len)) == NULL)
593 return (-1);
595 memcpy(b, data, len);
596 return (0);
599 int
600 ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
602 uint8_t v;
604 if (value > UINT8_MAX) {
605 errno = EINVAL;
606 return (-1);
608 v = value;
609 return (ibuf_set(buf, pos, &v, sizeof(v)));
612 int
613 ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
615 uint16_t v;
617 if (value > UINT16_MAX) {
618 errno = EINVAL;
619 return (-1);
621 v = htobe16(value);
622 return (ibuf_set(buf, pos, &v, sizeof(v)));
625 int
626 ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
628 uint32_t v;
630 if (value > UINT32_MAX) {
631 errno = EINVAL;
632 return (-1);
634 v = htobe32(value);
635 return (ibuf_set(buf, pos, &v, sizeof(v)));
638 int
639 ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
641 value = htobe64(value);
642 return (ibuf_set(buf, pos, &value, sizeof(value)));
645 int
646 ibuf_set_h16(struct ibuf *buf, size_t pos, uint64_t value)
648 uint16_t v;
650 if (value > UINT16_MAX) {
651 errno = EINVAL;
652 return (-1);
654 v = value;
655 return (ibuf_set(buf, pos, &v, sizeof(v)));
658 int
659 ibuf_set_h32(struct ibuf *buf, size_t pos, uint64_t value)
661 uint32_t v;
663 if (value > UINT32_MAX) {
664 errno = EINVAL;
665 return (-1);
667 v = value;
668 return (ibuf_set(buf, pos, &v, sizeof(v)));
671 int
672 ibuf_set_h64(struct ibuf *buf, size_t pos, uint64_t value)
674 return (ibuf_set(buf, pos, &value, sizeof(value)));
677 void *
678 ibuf_data(const struct ibuf *buf)
680 return (buf->buf + buf->rpos);
683 size_t
684 ibuf_size(const struct ibuf *buf)
686 return (buf->wpos - buf->rpos);
689 size_t
690 ibuf_left(const struct ibuf *buf)
692 if (buf->max == 0)
693 return (0);
694 return (buf->max - buf->wpos);
697 int
698 ibuf_truncate(struct ibuf *buf, size_t len)
700 if (ibuf_size(buf) >= len) {
701 buf->wpos = buf->rpos + len;
702 return (0);
704 if (buf->max == 0) {
705 /* only allow to truncate down */
706 errno = ERANGE;
707 return (-1);
709 return ibuf_add_zero(buf, len - ibuf_size(buf));
712 void
713 ibuf_rewind(struct ibuf *buf)
715 buf->rpos = 0;
718 void
719 ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
721 ibuf_enqueue(msgbuf, buf);
724 void
725 ibuf_from_buffer(struct ibuf *buf, void *data, size_t len)
727 memset(buf, 0, sizeof(*buf));
728 buf->buf = data;
729 buf->size = buf->wpos = len;
730 buf->fd = -1;
733 void
734 ibuf_from_ibuf(struct ibuf *buf, const struct ibuf *from)
736 ibuf_from_buffer(buf, ibuf_data(from), ibuf_size(from));
739 int
740 ibuf_get(struct ibuf *buf, void *data, size_t len)
742 if (ibuf_size(buf) < len) {
743 errno = EBADMSG;
744 return (-1);
747 memcpy(data, ibuf_data(buf), len);
748 buf->rpos += len;
749 return (0);
752 int
753 ibuf_get_ibuf(struct ibuf *buf, size_t len, struct ibuf *new)
755 if (ibuf_size(buf) < len) {
756 errno = EBADMSG;
757 return (-1);
760 ibuf_from_buffer(new, ibuf_data(buf), len);
761 buf->rpos += len;
762 return (0);
765 int
766 ibuf_get_n8(struct ibuf *buf, uint8_t *value)
768 return ibuf_get(buf, value, sizeof(*value));
771 int
772 ibuf_get_n16(struct ibuf *buf, uint16_t *value)
774 int rv;
776 rv = ibuf_get(buf, value, sizeof(*value));
777 *value = be16toh(*value);
778 return (rv);
781 int
782 ibuf_get_n32(struct ibuf *buf, uint32_t *value)
784 int rv;
786 rv = ibuf_get(buf, value, sizeof(*value));
787 *value = be32toh(*value);
788 return (rv);
791 int
792 ibuf_get_n64(struct ibuf *buf, uint64_t *value)
794 int rv;
796 rv = ibuf_get(buf, value, sizeof(*value));
797 *value = be64toh(*value);
798 return (rv);
801 int
802 ibuf_get_h16(struct ibuf *buf, uint16_t *value)
804 return ibuf_get(buf, value, sizeof(*value));
807 int
808 ibuf_get_h32(struct ibuf *buf, uint32_t *value)
810 return ibuf_get(buf, value, sizeof(*value));
813 int
814 ibuf_get_h64(struct ibuf *buf, uint64_t *value)
816 return ibuf_get(buf, value, sizeof(*value));
819 int
820 ibuf_skip(struct ibuf *buf, size_t len)
822 if (ibuf_size(buf) < len) {
823 errno = EBADMSG;
824 return (-1);
827 buf->rpos += len;
828 return (0);
831 void
832 ibuf_free(struct ibuf *buf)
834 if (buf == NULL)
835 return;
836 if (buf->max == 0) /* if buf lives on the stack */
837 abort(); /* abort before causing more harm */
838 if (buf->fd != -1)
839 close(buf->fd);
840 freezero(buf->buf, buf->size);
841 free(buf);
844 int
845 ibuf_fd_avail(struct ibuf *buf)
847 return (buf->fd != -1);
850 int
851 ibuf_fd_get(struct ibuf *buf)
853 int fd;
855 fd = buf->fd;
856 buf->fd = -1;
857 return (fd);
860 void
861 ibuf_fd_set(struct ibuf *buf, int fd)
863 if (buf->max == 0) /* if buf lives on the stack */
864 abort(); /* abort before causing more harm */
865 if (buf->fd != -1)
866 close(buf->fd);
867 buf->fd = fd;
870 int
871 ibuf_write(struct msgbuf *msgbuf)
873 struct iovec iov[IOV_MAX];
874 struct ibuf *buf;
875 unsigned int i = 0;
876 ssize_t n;
878 memset(&iov, 0, sizeof(iov));
879 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
880 if (i >= IOV_MAX)
881 break;
882 iov[i].iov_base = ibuf_data(buf);
883 iov[i].iov_len = ibuf_size(buf);
884 i++;
887 again:
888 if ((n = writev(msgbuf->fd, iov, i)) == -1) {
889 if (errno == EINTR)
890 goto again;
891 if (errno == ENOBUFS)
892 errno = EAGAIN;
893 return (-1);
896 if (n == 0) { /* connection closed */
897 errno = 0;
898 return (0);
901 msgbuf_drain(msgbuf, n);
903 return (1);
906 void
907 msgbuf_init(struct msgbuf *msgbuf)
909 msgbuf->queued = 0;
910 msgbuf->fd = -1;
911 TAILQ_INIT(&msgbuf->bufs);
914 static void
915 msgbuf_drain(struct msgbuf *msgbuf, size_t n)
917 struct ibuf *buf, *next;
919 for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
920 buf = next) {
921 next = TAILQ_NEXT(buf, entry);
922 if (n >= ibuf_size(buf)) {
923 n -= ibuf_size(buf);
924 ibuf_dequeue(msgbuf, buf);
925 } else {
926 buf->rpos += n;
927 n = 0;
932 void
933 msgbuf_clear(struct msgbuf *msgbuf)
935 struct ibuf *buf;
937 while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
938 ibuf_dequeue(msgbuf, buf);
941 int
942 msgbuf_write(struct msgbuf *msgbuf)
944 struct iovec iov[IOV_MAX];
945 struct ibuf *buf, *buf0 = NULL;
946 unsigned int i = 0;
947 ssize_t n;
948 struct msghdr msg;
949 struct cmsghdr *cmsg;
950 union {
951 struct cmsghdr hdr;
952 char buf[CMSG_SPACE(sizeof(int))];
953 } cmsgbuf;
955 memset(&iov, 0, sizeof(iov));
956 memset(&msg, 0, sizeof(msg));
957 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
958 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
959 if (i >= IOV_MAX)
960 break;
961 if (i > 0 && buf->fd != -1)
962 break;
963 iov[i].iov_base = ibuf_data(buf);
964 iov[i].iov_len = ibuf_size(buf);
965 i++;
966 if (buf->fd != -1)
967 buf0 = buf;
970 msg.msg_iov = iov;
971 msg.msg_iovlen = i;
973 if (buf0 != NULL) {
974 msg.msg_control = (caddr_t)&cmsgbuf.buf;
975 msg.msg_controllen = sizeof(cmsgbuf.buf);
976 cmsg = CMSG_FIRSTHDR(&msg);
977 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
978 cmsg->cmsg_level = SOL_SOCKET;
979 cmsg->cmsg_type = SCM_RIGHTS;
980 *(int *)CMSG_DATA(cmsg) = buf0->fd;
983 again:
984 if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
985 if (errno == EINTR)
986 goto again;
987 if (errno == ENOBUFS)
988 errno = EAGAIN;
989 return (-1);
992 if (n == 0) { /* connection closed */
993 errno = 0;
994 return (0);
997 /*
998 * assumption: fd got sent if sendmsg sent anything
999 * this works because fds are passed one at a time
1001 if (buf0 != NULL) {
1002 close(buf0->fd);
1003 buf0->fd = -1;
1006 msgbuf_drain(msgbuf, n);
1008 return (1);
1011 uint32_t
1012 msgbuf_queuelen(struct msgbuf *msgbuf)
1014 return (msgbuf->queued);
1017 static void
1018 ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
1020 if (buf->max == 0) /* if buf lives on the stack */
1021 abort(); /* abort before causing more harm */
1022 TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
1023 msgbuf->queued++;
1026 static void
1027 ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
1029 TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
1030 msgbuf->queued--;
1031 ibuf_free(buf);
1034 /* imsg.c */
1036 struct imsg_fd {
1037 TAILQ_ENTRY(imsg_fd) entry;
1038 int fd;
1041 int imsg_fd_overhead = 0;
1043 static int imsg_dequeue_fd(struct imsgbuf *);
1045 void
1046 imsg_init(struct imsgbuf *imsgbuf, int fd)
1048 msgbuf_init(&imsgbuf->w);
1049 memset(&imsgbuf->r, 0, sizeof(imsgbuf->r));
1050 imsgbuf->fd = fd;
1051 imsgbuf->w.fd = fd;
1052 imsgbuf->pid = getpid();
1053 TAILQ_INIT(&imsgbuf->fds);
1056 ssize_t
1057 imsg_read(struct imsgbuf *imsgbuf)
1059 struct msghdr msg;
1060 struct cmsghdr *cmsg;
1061 union {
1062 struct cmsghdr hdr;
1063 char buf[CMSG_SPACE(sizeof(int) * 1)];
1064 } cmsgbuf;
1065 struct iovec iov;
1066 ssize_t n = -1;
1067 int fd;
1068 struct imsg_fd *ifd;
1070 memset(&msg, 0, sizeof(msg));
1071 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
1073 iov.iov_base = imsgbuf->r.buf + imsgbuf->r.wpos;
1074 iov.iov_len = sizeof(imsgbuf->r.buf) - imsgbuf->r.wpos;
1075 msg.msg_iov = &iov;
1076 msg.msg_iovlen = 1;
1077 msg.msg_control = &cmsgbuf.buf;
1078 msg.msg_controllen = sizeof(cmsgbuf.buf);
1080 if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
1081 return (-1);
1083 again:
1084 if (getdtablecount() + imsg_fd_overhead +
1085 (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
1086 >= getdtablesize()) {
1087 errno = EAGAIN;
1088 free(ifd);
1089 return (-1);
1092 if ((n = recvmsg(imsgbuf->fd, &msg, 0)) == -1) {
1093 if (errno == EINTR)
1094 goto again;
1095 goto fail;
1098 imsgbuf->r.wpos += n;
1100 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
1101 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1102 if (cmsg->cmsg_level == SOL_SOCKET &&
1103 cmsg->cmsg_type == SCM_RIGHTS) {
1104 int i;
1105 int j;
1108 * We only accept one file descriptor. Due to C
1109 * padding rules, our control buffer might contain
1110 * more than one fd, and we must close them.
1112 j = ((char *)cmsg + cmsg->cmsg_len -
1113 (char *)CMSG_DATA(cmsg)) / sizeof(int);
1114 for (i = 0; i < j; i++) {
1115 fd = ((int *)CMSG_DATA(cmsg))[i];
1116 if (ifd != NULL) {
1117 ifd->fd = fd;
1118 TAILQ_INSERT_TAIL(&imsgbuf->fds, ifd,
1119 entry);
1120 ifd = NULL;
1121 } else
1122 close(fd);
1125 /* we do not handle other ctl data level */
1128 fail:
1129 free(ifd);
1130 return (n);
1133 ssize_t
1134 imsg_get(struct imsgbuf *imsgbuf, struct imsg *imsg)
1136 struct imsg m;
1137 size_t av, left, datalen;
1139 av = imsgbuf->r.wpos;
1141 if (IMSG_HEADER_SIZE > av)
1142 return (0);
1144 memcpy(&m.hdr, imsgbuf->r.buf, sizeof(m.hdr));
1145 if (m.hdr.len < IMSG_HEADER_SIZE ||
1146 m.hdr.len > MAX_IMSGSIZE) {
1147 errno = ERANGE;
1148 return (-1);
1150 if (m.hdr.len > av)
1151 return (0);
1153 m.fd = -1;
1154 m.buf = NULL;
1155 m.data = NULL;
1157 datalen = m.hdr.len - IMSG_HEADER_SIZE;
1158 imsgbuf->r.rptr = imsgbuf->r.buf + IMSG_HEADER_SIZE;
1159 if (datalen != 0) {
1160 if ((m.buf = ibuf_open(datalen)) == NULL)
1161 return (-1);
1162 if (ibuf_add(m.buf, imsgbuf->r.rptr, datalen) == -1) {
1163 /* this should never fail */
1164 ibuf_free(m.buf);
1165 return (-1);
1167 m.data = ibuf_data(m.buf);
1170 if (m.hdr.flags & IMSGF_HASFD)
1171 m.fd = imsg_dequeue_fd(imsgbuf);
1173 if (m.hdr.len < av) {
1174 left = av - m.hdr.len;
1175 memmove(&imsgbuf->r.buf, imsgbuf->r.buf + m.hdr.len, left);
1176 imsgbuf->r.wpos = left;
1177 } else
1178 imsgbuf->r.wpos = 0;
1180 *imsg = m;
1181 return (datalen + IMSG_HEADER_SIZE);
1184 int
1185 imsg_get_ibuf(struct imsg *imsg, struct ibuf *ibuf)
1187 if (imsg->buf == NULL) {
1188 errno = EBADMSG;
1189 return (-1);
1191 return ibuf_get_ibuf(imsg->buf, ibuf_size(imsg->buf), ibuf);
1194 int
1195 imsg_get_data(struct imsg *imsg, void *data, size_t len)
1197 if (len == 0) {
1198 errno = EINVAL;
1199 return (-1);
1201 if (imsg->buf == NULL || ibuf_size(imsg->buf) != len) {
1202 errno = EBADMSG;
1203 return (-1);
1205 return ibuf_get(imsg->buf, data, len);
1208 int
1209 imsg_get_fd(struct imsg *imsg)
1211 int fd = imsg->fd;
1213 imsg->fd = -1;
1214 return fd;
1217 uint32_t
1218 imsg_get_id(struct imsg *imsg)
1220 return (imsg->hdr.peerid);
1223 size_t
1224 imsg_get_len(struct imsg *imsg)
1226 if (imsg->buf == NULL)
1227 return 0;
1228 return ibuf_size(imsg->buf);
1231 pid_t
1232 imsg_get_pid(struct imsg *imsg)
1234 return (imsg->hdr.pid);
1237 uint32_t
1238 imsg_get_type(struct imsg *imsg)
1240 return (imsg->hdr.type);
1243 int
1244 imsg_compose(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
1245 int fd, const void *data, size_t datalen)
1247 struct ibuf *wbuf;
1249 if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
1250 return (-1);
1252 if (imsg_add(wbuf, data, datalen) == -1)
1253 return (-1);
1255 ibuf_fd_set(wbuf, fd);
1256 imsg_close(imsgbuf, wbuf);
1258 return (1);
1261 int
1262 imsg_composev(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
1263 int fd, const struct iovec *iov, int iovcnt)
1265 struct ibuf *wbuf;
1266 int i;
1267 size_t datalen = 0;
1269 for (i = 0; i < iovcnt; i++)
1270 datalen += iov[i].iov_len;
1272 if ((wbuf = imsg_create(imsgbuf, type, id, pid, datalen)) == NULL)
1273 return (-1);
1275 for (i = 0; i < iovcnt; i++)
1276 if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
1277 return (-1);
1279 ibuf_fd_set(wbuf, fd);
1280 imsg_close(imsgbuf, wbuf);
1282 return (1);
1286 * Enqueue imsg with payload from ibuf buf. fd passing is not possible
1287 * with this function.
1289 int
1290 imsg_compose_ibuf(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id,
1291 pid_t pid, struct ibuf *buf)
1293 struct ibuf *hdrbuf = NULL;
1294 struct imsg_hdr hdr;
1295 int save_errno;
1297 if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
1298 errno = ERANGE;
1299 goto fail;
1302 hdr.type = type;
1303 hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
1304 hdr.flags = 0;
1305 hdr.peerid = id;
1306 if ((hdr.pid = pid) == 0)
1307 hdr.pid = imsgbuf->pid;
1309 if ((hdrbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
1310 goto fail;
1311 if (imsg_add(hdrbuf, &hdr, sizeof(hdr)) == -1)
1312 goto fail;
1314 ibuf_close(&imsgbuf->w, hdrbuf);
1315 ibuf_close(&imsgbuf->w, buf);
1316 return (1);
1318 fail:
1319 save_errno = errno;
1320 ibuf_free(buf);
1321 ibuf_free(hdrbuf);
1322 errno = save_errno;
1323 return (-1);
1327 * Forward imsg to another channel. Any attached fd is closed.
1329 int
1330 imsg_forward(struct imsgbuf *imsgbuf, struct imsg *msg)
1332 struct ibuf *wbuf;
1333 size_t len = 0;
1335 if (msg->fd != -1) {
1336 close(msg->fd);
1337 msg->fd = -1;
1340 if (msg->buf != NULL) {
1341 ibuf_rewind(msg->buf);
1342 len = ibuf_size(msg->buf);
1345 if ((wbuf = imsg_create(imsgbuf, msg->hdr.type, msg->hdr.peerid,
1346 msg->hdr.pid, len)) == NULL)
1347 return (-1);
1349 if (msg->buf != NULL) {
1350 if (ibuf_add_buf(wbuf, msg->buf) == -1) {
1351 ibuf_free(wbuf);
1352 return (-1);
1356 imsg_close(imsgbuf, wbuf);
1357 return (1);
1360 struct ibuf *
1361 imsg_create(struct imsgbuf *imsgbuf, uint32_t type, uint32_t id, pid_t pid,
1362 size_t datalen)
1364 struct ibuf *wbuf;
1365 struct imsg_hdr hdr;
1367 datalen += IMSG_HEADER_SIZE;
1368 if (datalen > MAX_IMSGSIZE) {
1369 errno = ERANGE;
1370 return (NULL);
1373 hdr.type = type;
1374 hdr.flags = 0;
1375 hdr.peerid = id;
1376 if ((hdr.pid = pid) == 0)
1377 hdr.pid = imsgbuf->pid;
1378 if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
1379 return (NULL);
1381 if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
1382 return (NULL);
1384 return (wbuf);
1387 int
1388 imsg_add(struct ibuf *msg, const void *data, size_t datalen)
1390 if (datalen)
1391 if (ibuf_add(msg, data, datalen) == -1) {
1392 ibuf_free(msg);
1393 return (-1);
1395 return (datalen);
1398 void
1399 imsg_close(struct imsgbuf *imsgbuf, struct ibuf *msg)
1401 struct imsg_hdr *hdr;
1403 hdr = (struct imsg_hdr *)msg->buf;
1405 hdr->flags &= ~IMSGF_HASFD;
1406 if (ibuf_fd_avail(msg))
1407 hdr->flags |= IMSGF_HASFD;
1408 hdr->len = ibuf_size(msg);
1410 ibuf_close(&imsgbuf->w, msg);
1413 void
1414 imsg_free(struct imsg *imsg)
1416 ibuf_free(imsg->buf);
1419 static int
1420 imsg_dequeue_fd(struct imsgbuf *imsgbuf)
1422 int fd;
1423 struct imsg_fd *ifd;
1425 if ((ifd = TAILQ_FIRST(&imsgbuf->fds)) == NULL)
1426 return (-1);
1428 fd = ifd->fd;
1429 TAILQ_REMOVE(&imsgbuf->fds, ifd, entry);
1430 free(ifd);
1432 return (fd);
1435 int
1436 imsg_flush(struct imsgbuf *imsgbuf)
1438 while (imsgbuf->w.queued)
1439 if (msgbuf_write(&imsgbuf->w) <= 0)
1440 return (-1);
1441 return (0);
1444 void
1445 imsg_clear(struct imsgbuf *imsgbuf)
1447 int fd;
1449 msgbuf_clear(&imsgbuf->w);
1450 while ((fd = imsg_dequeue_fd(imsgbuf)) != -1)
1451 close(fd);
1453 #endif /* HAVE_LIB_IMSG */
1454 #if !HAVE_MEMMEM
1455 /*-
1456 * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
1458 * Redistribution and use in source and binary forms, with or without
1459 * modification, are permitted provided that the following conditions
1460 * are met:
1461 * 1. Redistributions of source code must retain the above copyright
1462 * notice, this list of conditions and the following disclaimer.
1463 * 2. Redistributions in binary form must reproduce the above copyright
1464 * notice, this list of conditions and the following disclaimer in
1465 * the documentation and/or other materials provided with the
1466 * distribution.
1467 * 3. The name of the author may not be used to endorse or promote
1468 * products derived from this software without specific prior written
1469 * permission.
1471 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
1472 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1473 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
1474 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
1475 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1476 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1477 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1478 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1479 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1480 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1481 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1484 * Find the first occurrence of the byte string s in byte string l.
1486 void *
1487 memmem(const void *l, size_t l_len, const void *s, size_t s_len)
1489 const char *cur, *last;
1490 const char *cl = l;
1491 const char *cs = s;
1493 /* a zero length needle should just return the haystack */
1494 if (l_len == 0)
1495 return (void *)cl;
1497 /* "s" must be smaller or equal to "l" */
1498 if (l_len < s_len)
1499 return NULL;
1501 /* special case where s_len == 1 */
1502 if (s_len == 1)
1503 return memchr(l, *cs, l_len);
1505 /* the last position where its possible to find "s" in "l" */
1506 last = cl + l_len - s_len;
1508 for (cur = cl; cur <= last; cur++)
1509 if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
1510 return (void *)cur;
1512 return NULL;
1514 #endif /* !HAVE_MEMMEM */
1515 #if !HAVE_MEMRCHR
1517 * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
1519 * Permission to use, copy, modify, and distribute this software for any
1520 * purpose with or without fee is hereby granted, provided that the above
1521 * copyright notice and this permission notice appear in all copies.
1523 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1524 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1525 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1526 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1527 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1528 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1529 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1533 #include <string.h>
1536 * Reverse memchr()
1537 * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
1539 void *
1540 memrchr(const void *s, int c, size_t n)
1542 const unsigned char *cp;
1544 if (n != 0) {
1545 cp = (unsigned char *)s + n;
1546 do {
1547 if (*(--cp) == (unsigned char)c)
1548 return((void *)cp);
1549 } while (--n != 0);
1551 return(NULL);
1553 #endif /* !HAVE_MEMRCHR */
1554 #if !HAVE_OPTRESET
1556 * Copyright (c) 1987, 1993, 1994
1557 * The Regents of the University of California. All rights reserved.
1559 * Redistribution and use in source and binary forms, with or without
1560 * modification, are permitted provided that the following conditions
1561 * are met:
1562 * 1. Redistributions of source code must retain the above copyright
1563 * notice, this list of conditions and the following disclaimer.
1564 * 2. Redistributions in binary form must reproduce the above copyright
1565 * notice, this list of conditions and the following disclaimer in the
1566 * documentation and/or other materials provided with the distribution.
1567 * 3. Neither the name of the University nor the names of its contributors
1568 * may be used to endorse or promote products derived from this software
1569 * without specific prior written permission.
1571 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1572 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1573 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1574 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1575 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1576 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1577 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1578 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1579 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1580 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1581 * SUCH DAMAGE.
1584 /* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
1586 #include <stdio.h>
1587 #include <stdlib.h>
1588 #include <string.h>
1590 int BSDopterr = 1, /* if error message should be printed */
1591 BSDoptind = 1, /* index into parent argv vector */
1592 BSDoptopt, /* character checked for validity */
1593 BSDoptreset; /* reset getopt */
1594 char *BSDoptarg; /* argument associated with option */
1596 #define BADCH (int)'?'
1597 #define BADARG (int)':'
1598 #define EMSG ""
1601 * getopt --
1602 * Parse argc/argv argument vector.
1604 int
1605 BSDgetopt(int nargc, char *const *nargv, const char *ostr)
1607 static const char *place = EMSG; /* option letter processing */
1608 char *oli; /* option letter list index */
1610 if (ostr == NULL)
1611 return (-1);
1613 if (BSDoptreset || !*place) { /* update scanning pointer */
1614 BSDoptreset = 0;
1615 if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
1616 place = EMSG;
1617 return (-1);
1619 if (place[1] && *++place == '-') { /* found "--" */
1620 if (place[1])
1621 return (BADCH);
1622 ++BSDoptind;
1623 place = EMSG;
1624 return (-1);
1626 } /* option letter okay? */
1627 if ((BSDoptopt = (int)*place++) == (int)':' ||
1628 !(oli = strchr(ostr, BSDoptopt))) {
1630 * if the user didn't specify '-' as an option,
1631 * assume it means -1.
1633 if (BSDoptopt == (int)'-')
1634 return (-1);
1635 if (!*place)
1636 ++BSDoptind;
1637 if (BSDopterr && *ostr != ':')
1638 (void)fprintf(stderr,
1639 "%s: unknown option -- %c\n", getprogname(),
1640 BSDoptopt);
1641 return (BADCH);
1643 if (*++oli != ':') { /* don't need argument */
1644 BSDoptarg = NULL;
1645 if (!*place)
1646 ++BSDoptind;
1648 else { /* need an argument */
1649 if (*place) /* no white space */
1650 BSDoptarg = (char *)place;
1651 else if (nargc <= ++BSDoptind) { /* no arg */
1652 place = EMSG;
1653 if (*ostr == ':')
1654 return (BADARG);
1655 if (BSDopterr)
1656 (void)fprintf(stderr,
1657 "%s: option requires an argument -- %c\n",
1658 getprogname(), BSDoptopt);
1659 return (BADCH);
1661 else /* white space */
1662 BSDoptarg = nargv[BSDoptind];
1663 place = EMSG;
1664 ++BSDoptind;
1666 return (BSDoptopt); /* dump back option letter */
1668 #endif
1669 #if !HAVE_REALLOCARRAY
1671 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
1673 * Permission to use, copy, modify, and distribute this software for any
1674 * purpose with or without fee is hereby granted, provided that the above
1675 * copyright notice and this permission notice appear in all copies.
1677 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1678 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1679 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1680 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1681 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1682 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1683 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1686 #include <sys/types.h>
1687 #include <errno.h>
1688 #include <stdint.h>
1689 #include <stdlib.h>
1692 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1693 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1695 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1697 void *
1698 reallocarray(void *optr, size_t nmemb, size_t size)
1700 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1701 nmemb > 0 && SIZE_MAX / nmemb < size) {
1702 errno = ENOMEM;
1703 return NULL;
1705 return realloc(optr, size * nmemb);
1707 #endif /* !HAVE_REALLOCARRAY */
1708 #if !HAVE_RECALLOCARRAY
1710 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
1712 * Permission to use, copy, modify, and distribute this software for any
1713 * purpose with or without fee is hereby granted, provided that the above
1714 * copyright notice and this permission notice appear in all copies.
1716 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1717 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1718 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1719 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1720 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1721 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1722 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1725 /* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */
1727 #include <errno.h>
1728 #include <stdlib.h>
1729 #include <stdint.h>
1730 #include <string.h>
1731 #include <unistd.h>
1734 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1735 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1737 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1739 void *
1740 recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
1742 size_t oldsize, newsize;
1743 void *newptr;
1745 if (ptr == NULL)
1746 return calloc(newnmemb, size);
1748 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1749 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
1750 errno = ENOMEM;
1751 return NULL;
1753 newsize = newnmemb * size;
1755 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1756 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
1757 errno = EINVAL;
1758 return NULL;
1760 oldsize = oldnmemb * size;
1763 * Don't bother too much if we're shrinking just a bit,
1764 * we do not shrink for series of small steps, oh well.
1766 if (newsize <= oldsize) {
1767 size_t d = oldsize - newsize;
1769 if (d < oldsize / 2 && d < (size_t)getpagesize()) {
1770 memset((char *)ptr + newsize, 0, d);
1771 return ptr;
1775 newptr = malloc(newsize);
1776 if (newptr == NULL)
1777 return NULL;
1779 if (newsize > oldsize) {
1780 memcpy(newptr, ptr, oldsize);
1781 memset((char *)newptr + oldsize, 0, newsize - oldsize);
1782 } else
1783 memcpy(newptr, ptr, newsize);
1785 explicit_bzero(ptr, oldsize);
1786 free(ptr);
1788 return newptr;
1790 #endif /* !HAVE_RECALLOCARRAY */
1791 #if !HAVE_SETPROCTITLE
1793 * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
1795 * Permission to use, copy, modify, and distribute this software for any
1796 * purpose with or without fee is hereby granted, provided that the above
1797 * copyright notice and this permission notice appear in all copies.
1799 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1800 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1801 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1802 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1803 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
1804 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1805 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1808 # if HAVE_PR_SET_NAME
1809 #include <sys/types.h>
1810 #include <stdarg.h>
1811 #include <stdio.h>
1812 #include <string.h>
1813 #include <sys/prctl.h>
1814 void
1815 setproctitle(const char *fmt, ...)
1817 char title[16], name[16], *cp;
1818 va_list ap;
1819 int used;
1821 va_start(ap, fmt);
1822 vsnprintf(title, sizeof(title), fmt, ap);
1823 va_end(ap);
1825 used = snprintf(name, sizeof(name), "%s: %s", getprogname(), title);
1826 if (used >= (int)sizeof(name)) {
1827 cp = strrchr(name, ' ');
1828 if (cp != NULL)
1829 *cp = '\0';
1831 prctl(PR_SET_NAME, name);
1833 # else
1834 void
1835 setproctitle(const char *fmt, ...)
1837 return;
1839 # endif
1840 #endif /* !HAVE_SETPROCTITLE */
1841 #if !HAVE_STRLCAT
1843 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1845 * Permission to use, copy, modify, and distribute this software for any
1846 * purpose with or without fee is hereby granted, provided that the above
1847 * copyright notice and this permission notice appear in all copies.
1849 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1850 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1851 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1852 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1853 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1854 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1855 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1858 #include <sys/types.h>
1859 #include <string.h>
1862 * Appends src to string dst of size siz (unlike strncat, siz is the
1863 * full size of dst, not space left). At most siz-1 characters
1864 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
1865 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
1866 * If retval >= siz, truncation occurred.
1868 size_t
1869 strlcat(char *dst, const char *src, size_t siz)
1871 char *d = dst;
1872 const char *s = src;
1873 size_t n = siz;
1874 size_t dlen;
1876 /* Find the end of dst and adjust bytes left but don't go past end */
1877 while (n-- != 0 && *d != '\0')
1878 d++;
1879 dlen = d - dst;
1880 n = siz - dlen;
1882 if (n == 0)
1883 return(dlen + strlen(s));
1884 while (*s != '\0') {
1885 if (n != 1) {
1886 *d++ = *s;
1887 n--;
1889 s++;
1891 *d = '\0';
1893 return(dlen + (s - src)); /* count does not include NUL */
1895 #endif /* !HAVE_STRLCAT */
1896 #if !HAVE_STRLCPY
1898 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1900 * Permission to use, copy, modify, and distribute this software for any
1901 * purpose with or without fee is hereby granted, provided that the above
1902 * copyright notice and this permission notice appear in all copies.
1904 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1905 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1906 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1907 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1908 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1909 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1910 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1913 #include <sys/types.h>
1914 #include <string.h>
1917 * Copy src to string dst of size siz. At most siz-1 characters
1918 * will be copied. Always NUL terminates (unless siz == 0).
1919 * Returns strlen(src); if retval >= siz, truncation occurred.
1921 size_t
1922 strlcpy(char *dst, const char *src, size_t siz)
1924 char *d = dst;
1925 const char *s = src;
1926 size_t n = siz;
1928 /* Copy as many bytes as will fit */
1929 if (n != 0) {
1930 while (--n != 0) {
1931 if ((*d++ = *s++) == '\0')
1932 break;
1936 /* Not enough room in dst, add NUL and traverse rest of src */
1937 if (n == 0) {
1938 if (siz != 0)
1939 *d = '\0'; /* NUL-terminate dst */
1940 while (*s++)
1944 return(s - src - 1); /* count does not include NUL */
1946 #endif /* !HAVE_STRLCPY */
1947 #if !HAVE_STRNDUP
1948 /* $OpenBSD$ */
1950 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1952 * Permission to use, copy, modify, and distribute this software for any
1953 * purpose with or without fee is hereby granted, provided that the above
1954 * copyright notice and this permission notice appear in all copies.
1956 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1957 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1958 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1959 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1960 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1961 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1962 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1965 #include <sys/types.h>
1967 #include <stddef.h>
1968 #include <stdlib.h>
1969 #include <string.h>
1971 char *
1972 strndup(const char *str, size_t maxlen)
1974 char *copy;
1975 size_t len;
1977 len = strnlen(str, maxlen);
1978 copy = malloc(len + 1);
1979 if (copy != NULL) {
1980 (void)memcpy(copy, str, len);
1981 copy[len] = '\0';
1984 return copy;
1986 #endif /* !HAVE_STRNDUP */
1987 #if !HAVE_STRNLEN
1988 /* $OpenBSD$ */
1991 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1993 * Permission to use, copy, modify, and distribute this software for any
1994 * purpose with or without fee is hereby granted, provided that the above
1995 * copyright notice and this permission notice appear in all copies.
1997 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1998 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1999 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
2000 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2001 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
2002 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2003 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2006 #include <sys/types.h>
2007 #include <string.h>
2009 size_t
2010 strnlen(const char *str, size_t maxlen)
2012 const char *cp;
2014 for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
2017 return (size_t)(cp - str);
2019 #endif /* !HAVE_STRNLEN */
2020 #if !HAVE_STRTONUM
2022 * Copyright (c) 2004 Ted Unangst and Todd Miller
2023 * All rights reserved.
2025 * Permission to use, copy, modify, and distribute this software for any
2026 * purpose with or without fee is hereby granted, provided that the above
2027 * copyright notice and this permission notice appear in all copies.
2029 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
2030 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
2031 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
2032 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2033 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
2034 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
2035 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2038 #include <errno.h>
2039 #include <limits.h>
2040 #include <stdlib.h>
2042 #define INVALID 1
2043 #define TOOSMALL 2
2044 #define TOOLARGE 3
2046 long long
2047 strtonum(const char *numstr, long long minval, long long maxval,
2048 const char **errstrp)
2050 long long ll = 0;
2051 int error = 0;
2052 char *ep;
2053 struct errval {
2054 const char *errstr;
2055 int err;
2056 } ev[4] = {
2057 { NULL, 0 },
2058 { "invalid", EINVAL },
2059 { "too small", ERANGE },
2060 { "too large", ERANGE },
2063 ev[0].err = errno;
2064 errno = 0;
2065 if (minval > maxval) {
2066 error = INVALID;
2067 } else {
2068 ll = strtoll(numstr, &ep, 10);
2069 if (numstr == ep || *ep != '\0')
2070 error = INVALID;
2071 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
2072 error = TOOSMALL;
2073 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
2074 error = TOOLARGE;
2076 if (errstrp != NULL)
2077 *errstrp = ev[error].errstr;
2078 errno = ev[error].err;
2079 if (error)
2080 ll = 0;
2082 return (ll);
2084 #endif /* !HAVE_STRTONUM */
2085 #if !HAVE_TIMESPECSUB
2086 #include <sys/time.h>
2087 void
2088 timespecsub(struct timespec *a, struct timespec *b, struct timespec *ret)
2090 ret->tv_sec = a->tv_sec - b->tv_sec;
2091 ret->tv_nsec = a->tv_nsec - b->tv_nsec;
2092 if (ret->tv_nsec < 0) {
2093 ret->tv_sec--;
2094 ret->tv_nsec += 1000000000L;
2097 #endif /* !HAVE_TIMESPECSUB */