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) = memset;
250 void
251 explicit_bzero(void *p, size_t n)
253 if (n == 0)
254 return;
255 /*
256 * clang -fsanitize=memory needs to intercept memset-like functions
257 * to correctly detect memory initialisation. Make sure one is called
258 * directly since our indirection trick above sucessfully confuses it.
259 */
260 #if defined(__has_feature)
261 # if __has_feature(memory_sanitizer)
262 memset(p, 0, n);
263 # endif
264 #endif
266 ssh_memset(p, 0, n);
269 #endif /* HAVE_MEMSET_S */
270 #endif /* !HAVE_EXPLICIT_BZERO */
271 #if !HAVE_GETPROGNAME
272 /*
273 * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
274 * Copyright (c) 2017 Kristaps Dzonsons <kristaps@bsd.lv>
275 * Copyright (c) 2020 Stephen Gregoratto <dev@sgregoratto.me>
277 * Permission to use, copy, modify, and distribute this software for any
278 * purpose with or without fee is hereby granted, provided that the above
279 * copyright notice and this permission notice appear in all copies.
281 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
282 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
283 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
284 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
285 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
286 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
287 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
288 */
290 #include <sys/types.h>
292 #include <errno.h>
294 #if HAVE_GETEXECNAME
295 #include <stdlib.h>
296 const char *
297 getprogname(void)
299 return getexecname();
301 #elif HAVE_PROGRAM_INVOCATION_SHORT_NAME
302 const char *
303 getprogname(void)
305 return (program_invocation_short_name);
307 #elif HAVE___PROGNAME
308 const char *
309 getprogname(void)
311 extern char *__progname;
313 return (__progname);
315 #else
316 #warning No getprogname available.
317 const char *
318 getprogname(void)
320 return ("amused");
322 #endif
323 #endif /* !HAVE_GETPROGNAME */
324 #if !HAVE_IMSG
325 /* $OpenBSD: imsg-buffer.c,v 1.13 2021/03/31 17:42:24 eric Exp $ */
326 /* $OpenBSD: imsg.c,v 1.17 2022/01/28 10:41:44 claudio Exp $ */
328 /*
329 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
331 * Permission to use, copy, modify, and distribute this software for any
332 * purpose with or without fee is hereby granted, provided that the above
333 * copyright notice and this permission notice appear in all copies.
335 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
336 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
337 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
338 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
339 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
340 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
341 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
342 */
344 #include "config.h"
346 #include <sys/types.h>
347 #include <sys/socket.h>
348 #include <sys/uio.h>
350 #include <limits.h>
351 #include <errno.h>
352 #include <stdlib.h>
353 #include <string.h>
354 #include <unistd.h>
356 #include "imsg.h"
358 static int ibuf_realloc(struct ibuf *, size_t);
359 static void ibuf_enqueue(struct msgbuf *, struct ibuf *);
360 static void ibuf_dequeue(struct msgbuf *, struct ibuf *);
362 struct ibuf *
363 ibuf_open(size_t len)
365 struct ibuf *buf;
367 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
368 return (NULL);
369 if ((buf->buf = malloc(len)) == NULL) {
370 free(buf);
371 return (NULL);
373 buf->size = buf->max = len;
374 buf->fd = -1;
376 return (buf);
379 struct ibuf *
380 ibuf_dynamic(size_t len, size_t max)
382 struct ibuf *buf;
384 if (max < len)
385 return (NULL);
387 if ((buf = ibuf_open(len)) == NULL)
388 return (NULL);
390 if (max > 0)
391 buf->max = max;
393 return (buf);
396 static int
397 ibuf_realloc(struct ibuf *buf, size_t len)
399 unsigned char *b;
401 /* on static buffers max is eq size and so the following fails */
402 if (buf->wpos + len > buf->max) {
403 errno = ERANGE;
404 return (-1);
407 b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
408 if (b == NULL)
409 return (-1);
410 buf->buf = b;
411 buf->size = buf->wpos + len;
413 return (0);
416 int
417 ibuf_add(struct ibuf *buf, const void *data, size_t len)
419 if (buf->wpos + len > buf->size)
420 if (ibuf_realloc(buf, len) == -1)
421 return (-1);
423 memcpy(buf->buf + buf->wpos, data, len);
424 buf->wpos += len;
425 return (0);
428 void *
429 ibuf_reserve(struct ibuf *buf, size_t len)
431 void *b;
433 if (buf->wpos + len > buf->size)
434 if (ibuf_realloc(buf, len) == -1)
435 return (NULL);
437 b = buf->buf + buf->wpos;
438 buf->wpos += len;
439 return (b);
442 void *
443 ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
445 /* only allowed to seek in already written parts */
446 if (pos + len > buf->wpos)
447 return (NULL);
449 return (buf->buf + pos);
452 size_t
453 ibuf_size(struct ibuf *buf)
455 return (buf->wpos);
458 size_t
459 ibuf_left(struct ibuf *buf)
461 return (buf->max - buf->wpos);
464 void
465 ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
467 ibuf_enqueue(msgbuf, buf);
470 int
471 ibuf_write(struct msgbuf *msgbuf)
473 struct iovec iov[IOV_MAX];
474 struct ibuf *buf;
475 unsigned int i = 0;
476 ssize_t n;
478 memset(&iov, 0, sizeof(iov));
479 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
480 if (i >= IOV_MAX)
481 break;
482 iov[i].iov_base = buf->buf + buf->rpos;
483 iov[i].iov_len = buf->wpos - buf->rpos;
484 i++;
487 again:
488 if ((n = writev(msgbuf->fd, iov, i)) == -1) {
489 if (errno == EINTR)
490 goto again;
491 if (errno == ENOBUFS)
492 errno = EAGAIN;
493 return (-1);
496 if (n == 0) { /* connection closed */
497 errno = 0;
498 return (0);
501 msgbuf_drain(msgbuf, n);
503 return (1);
506 void
507 ibuf_free(struct ibuf *buf)
509 if (buf == NULL)
510 return;
511 freezero(buf->buf, buf->size);
512 free(buf);
515 void
516 msgbuf_init(struct msgbuf *msgbuf)
518 msgbuf->queued = 0;
519 msgbuf->fd = -1;
520 TAILQ_INIT(&msgbuf->bufs);
523 void
524 msgbuf_drain(struct msgbuf *msgbuf, size_t n)
526 struct ibuf *buf, *next;
528 for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
529 buf = next) {
530 next = TAILQ_NEXT(buf, entry);
531 if (buf->rpos + n >= buf->wpos) {
532 n -= buf->wpos - buf->rpos;
533 ibuf_dequeue(msgbuf, buf);
534 } else {
535 buf->rpos += n;
536 n = 0;
541 void
542 msgbuf_clear(struct msgbuf *msgbuf)
544 struct ibuf *buf;
546 while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
547 ibuf_dequeue(msgbuf, buf);
550 int
551 msgbuf_write(struct msgbuf *msgbuf)
553 struct iovec iov[IOV_MAX];
554 struct ibuf *buf, *buf0 = NULL;
555 unsigned int i = 0;
556 ssize_t n;
557 struct msghdr msg;
558 struct cmsghdr *cmsg;
559 union {
560 struct cmsghdr hdr;
561 char buf[CMSG_SPACE(sizeof(int))];
562 } cmsgbuf;
564 memset(&iov, 0, sizeof(iov));
565 memset(&msg, 0, sizeof(msg));
566 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
567 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
568 if (i >= IOV_MAX)
569 break;
570 if (i > 0 && buf->fd != -1)
571 break;
572 iov[i].iov_base = buf->buf + buf->rpos;
573 iov[i].iov_len = buf->wpos - buf->rpos;
574 i++;
575 if (buf->fd != -1)
576 buf0 = buf;
579 msg.msg_iov = iov;
580 msg.msg_iovlen = i;
582 if (buf0 != NULL) {
583 msg.msg_control = (caddr_t)&cmsgbuf.buf;
584 msg.msg_controllen = sizeof(cmsgbuf.buf);
585 cmsg = CMSG_FIRSTHDR(&msg);
586 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
587 cmsg->cmsg_level = SOL_SOCKET;
588 cmsg->cmsg_type = SCM_RIGHTS;
589 *(int *)CMSG_DATA(cmsg) = buf0->fd;
592 again:
593 if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
594 if (errno == EINTR)
595 goto again;
596 if (errno == ENOBUFS)
597 errno = EAGAIN;
598 return (-1);
601 if (n == 0) { /* connection closed */
602 errno = 0;
603 return (0);
606 /*
607 * assumption: fd got sent if sendmsg sent anything
608 * this works because fds are passed one at a time
609 */
610 if (buf0 != NULL) {
611 close(buf0->fd);
612 buf0->fd = -1;
615 msgbuf_drain(msgbuf, n);
617 return (1);
620 static void
621 ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
623 TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
624 msgbuf->queued++;
627 static void
628 ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
630 TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
632 if (buf->fd != -1)
633 close(buf->fd);
635 msgbuf->queued--;
636 ibuf_free(buf);
639 /* imsg.c */
641 int imsg_fd_overhead = 0;
643 static int imsg_get_fd(struct imsgbuf *);
645 void
646 imsg_init(struct imsgbuf *ibuf, int fd)
648 msgbuf_init(&ibuf->w);
649 memset(&ibuf->r, 0, sizeof(ibuf->r));
650 ibuf->fd = fd;
651 ibuf->w.fd = fd;
652 ibuf->pid = getpid();
653 TAILQ_INIT(&ibuf->fds);
656 ssize_t
657 imsg_read(struct imsgbuf *ibuf)
659 struct msghdr msg;
660 struct cmsghdr *cmsg;
661 union {
662 struct cmsghdr hdr;
663 char buf[CMSG_SPACE(sizeof(int) * 1)];
664 } cmsgbuf;
665 struct iovec iov;
666 ssize_t n = -1;
667 int fd;
668 struct imsg_fd *ifd;
670 memset(&msg, 0, sizeof(msg));
671 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
673 iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
674 iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
675 msg.msg_iov = &iov;
676 msg.msg_iovlen = 1;
677 msg.msg_control = &cmsgbuf.buf;
678 msg.msg_controllen = sizeof(cmsgbuf.buf);
680 if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
681 return (-1);
683 again:
684 if (getdtablecount() + imsg_fd_overhead +
685 (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
686 >= getdtablesize()) {
687 errno = EAGAIN;
688 free(ifd);
689 return (-1);
692 if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
693 if (errno == EINTR)
694 goto again;
695 goto fail;
698 ibuf->r.wpos += n;
700 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
701 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
702 if (cmsg->cmsg_level == SOL_SOCKET &&
703 cmsg->cmsg_type == SCM_RIGHTS) {
704 int i;
705 int j;
707 /*
708 * We only accept one file descriptor. Due to C
709 * padding rules, our control buffer might contain
710 * more than one fd, and we must close them.
711 */
712 j = ((char *)cmsg + cmsg->cmsg_len -
713 (char *)CMSG_DATA(cmsg)) / sizeof(int);
714 for (i = 0; i < j; i++) {
715 fd = ((int *)CMSG_DATA(cmsg))[i];
716 if (ifd != NULL) {
717 ifd->fd = fd;
718 TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
719 entry);
720 ifd = NULL;
721 } else
722 close(fd);
725 /* we do not handle other ctl data level */
728 fail:
729 free(ifd);
730 return (n);
733 ssize_t
734 imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
736 size_t av, left, datalen;
738 av = ibuf->r.wpos;
740 if (IMSG_HEADER_SIZE > av)
741 return (0);
743 memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
744 if (imsg->hdr.len < IMSG_HEADER_SIZE ||
745 imsg->hdr.len > MAX_IMSGSIZE) {
746 errno = ERANGE;
747 return (-1);
749 if (imsg->hdr.len > av)
750 return (0);
751 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
752 ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
753 if (datalen == 0)
754 imsg->data = NULL;
755 else if ((imsg->data = malloc(datalen)) == NULL)
756 return (-1);
758 if (imsg->hdr.flags & IMSGF_HASFD)
759 imsg->fd = imsg_get_fd(ibuf);
760 else
761 imsg->fd = -1;
763 if (datalen != 0)
764 memcpy(imsg->data, ibuf->r.rptr, datalen);
766 if (imsg->hdr.len < av) {
767 left = av - imsg->hdr.len;
768 memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
769 ibuf->r.wpos = left;
770 } else
771 ibuf->r.wpos = 0;
773 return (datalen + IMSG_HEADER_SIZE);
776 int
777 imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
778 int fd, const void *data, uint16_t datalen)
780 struct ibuf *wbuf;
782 if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
783 return (-1);
785 if (imsg_add(wbuf, data, datalen) == -1)
786 return (-1);
788 wbuf->fd = fd;
790 imsg_close(ibuf, wbuf);
792 return (1);
795 int
796 imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
797 int fd, const struct iovec *iov, int iovcnt)
799 struct ibuf *wbuf;
800 int i, datalen = 0;
802 for (i = 0; i < iovcnt; i++)
803 datalen += iov[i].iov_len;
805 if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
806 return (-1);
808 for (i = 0; i < iovcnt; i++)
809 if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
810 return (-1);
812 wbuf->fd = fd;
814 imsg_close(ibuf, wbuf);
816 return (1);
819 /* ARGSUSED */
820 struct ibuf *
821 imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
822 uint16_t datalen)
824 struct ibuf *wbuf;
825 struct imsg_hdr hdr;
827 datalen += IMSG_HEADER_SIZE;
828 if (datalen > MAX_IMSGSIZE) {
829 errno = ERANGE;
830 return (NULL);
833 hdr.type = type;
834 hdr.flags = 0;
835 hdr.peerid = peerid;
836 if ((hdr.pid = pid) == 0)
837 hdr.pid = ibuf->pid;
838 if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
839 return (NULL);
841 if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
842 return (NULL);
844 return (wbuf);
847 int
848 imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
850 if (datalen)
851 if (ibuf_add(msg, data, datalen) == -1) {
852 ibuf_free(msg);
853 return (-1);
855 return (datalen);
858 void
859 imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
861 struct imsg_hdr *hdr;
863 hdr = (struct imsg_hdr *)msg->buf;
865 hdr->flags &= ~IMSGF_HASFD;
866 if (msg->fd != -1)
867 hdr->flags |= IMSGF_HASFD;
869 hdr->len = (uint16_t)msg->wpos;
871 ibuf_close(&ibuf->w, msg);
874 void
875 imsg_free(struct imsg *imsg)
877 freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
880 static int
881 imsg_get_fd(struct imsgbuf *ibuf)
883 int fd;
884 struct imsg_fd *ifd;
886 if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
887 return (-1);
889 fd = ifd->fd;
890 TAILQ_REMOVE(&ibuf->fds, ifd, entry);
891 free(ifd);
893 return (fd);
896 int
897 imsg_flush(struct imsgbuf *ibuf)
899 while (ibuf->w.queued)
900 if (msgbuf_write(&ibuf->w) <= 0)
901 return (-1);
902 return (0);
905 void
906 imsg_clear(struct imsgbuf *ibuf)
908 int fd;
910 msgbuf_clear(&ibuf->w);
911 while ((fd = imsg_get_fd(ibuf)) != -1)
912 close(fd);
914 #endif /* HAVE_IMSG */
915 #if !HAVE_MEMMEM
916 /*-
917 * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
919 * Redistribution and use in source and binary forms, with or without
920 * modification, are permitted provided that the following conditions
921 * are met:
922 * 1. Redistributions of source code must retain the above copyright
923 * notice, this list of conditions and the following disclaimer.
924 * 2. Redistributions in binary form must reproduce the above copyright
925 * notice, this list of conditions and the following disclaimer in
926 * the documentation and/or other materials provided with the
927 * distribution.
928 * 3. The name of the author may not be used to endorse or promote
929 * products derived from this software without specific prior written
930 * permission.
932 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
933 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
934 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
935 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
936 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
937 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
938 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
939 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
940 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
941 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
942 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
943 */
944 /*
945 * Find the first occurrence of the byte string s in byte string l.
946 */
947 void *
948 memmem(const void *l, size_t l_len, const void *s, size_t s_len)
950 const char *cur, *last;
951 const char *cl = l;
952 const char *cs = s;
954 /* a zero length needle should just return the haystack */
955 if (l_len == 0)
956 return (void *)cl;
958 /* "s" must be smaller or equal to "l" */
959 if (l_len < s_len)
960 return NULL;
962 /* special case where s_len == 1 */
963 if (s_len == 1)
964 return memchr(l, *cs, l_len);
966 /* the last position where its possible to find "s" in "l" */
967 last = cl + l_len - s_len;
969 for (cur = cl; cur <= last; cur++)
970 if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
971 return (void *)cur;
973 return NULL;
975 #endif /* !HAVE_MEMMEM */
976 #if !HAVE_MEMRCHR
977 /*
978 * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
980 * Permission to use, copy, modify, and distribute this software for any
981 * purpose with or without fee is hereby granted, provided that the above
982 * copyright notice and this permission notice appear in all copies.
984 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
985 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
986 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
987 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
988 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
989 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
990 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
992 */
994 #include <string.h>
996 /*
997 * Reverse memchr()
998 * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
999 */
1000 void *
1001 memrchr(const void *s, int c, size_t n)
1003 const unsigned char *cp;
1005 if (n != 0) {
1006 cp = (unsigned char *)s + n;
1007 do {
1008 if (*(--cp) == (unsigned char)c)
1009 return((void *)cp);
1010 } while (--n != 0);
1012 return(NULL);
1014 #endif /* !HAVE_MEMRCHR */
1015 #if !HAVE_OPTRESET
1017 * Copyright (c) 1987, 1993, 1994
1018 * The Regents of the University of California. All rights reserved.
1020 * Redistribution and use in source and binary forms, with or without
1021 * modification, are permitted provided that the following conditions
1022 * are met:
1023 * 1. Redistributions of source code must retain the above copyright
1024 * notice, this list of conditions and the following disclaimer.
1025 * 2. Redistributions in binary form must reproduce the above copyright
1026 * notice, this list of conditions and the following disclaimer in the
1027 * documentation and/or other materials provided with the distribution.
1028 * 3. Neither the name of the University nor the names of its contributors
1029 * may be used to endorse or promote products derived from this software
1030 * without specific prior written permission.
1032 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1033 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1034 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1035 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1036 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1037 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1038 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1039 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1040 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1041 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1042 * SUCH DAMAGE.
1045 /* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
1047 #include <stdio.h>
1048 #include <stdlib.h>
1049 #include <string.h>
1051 int BSDopterr = 1, /* if error message should be printed */
1052 BSDoptind = 1, /* index into parent argv vector */
1053 BSDoptopt, /* character checked for validity */
1054 BSDoptreset; /* reset getopt */
1055 char *BSDoptarg; /* argument associated with option */
1057 #define BADCH (int)'?'
1058 #define BADARG (int)':'
1059 #define EMSG ""
1062 * getopt --
1063 * Parse argc/argv argument vector.
1065 int
1066 BSDgetopt(int nargc, char *const *nargv, const char *ostr)
1068 static const char *place = EMSG; /* option letter processing */
1069 char *oli; /* option letter list index */
1071 if (ostr == NULL)
1072 return (-1);
1074 if (BSDoptreset || !*place) { /* update scanning pointer */
1075 BSDoptreset = 0;
1076 if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
1077 place = EMSG;
1078 return (-1);
1080 if (place[1] && *++place == '-') { /* found "--" */
1081 if (place[1])
1082 return (BADCH);
1083 ++BSDoptind;
1084 place = EMSG;
1085 return (-1);
1087 } /* option letter okay? */
1088 if ((BSDoptopt = (int)*place++) == (int)':' ||
1089 !(oli = strchr(ostr, BSDoptopt))) {
1091 * if the user didn't specify '-' as an option,
1092 * assume it means -1.
1094 if (BSDoptopt == (int)'-')
1095 return (-1);
1096 if (!*place)
1097 ++BSDoptind;
1098 if (BSDopterr && *ostr != ':')
1099 (void)fprintf(stderr,
1100 "%s: unknown option -- %c\n", getprogname(),
1101 BSDoptopt);
1102 return (BADCH);
1104 if (*++oli != ':') { /* don't need argument */
1105 BSDoptarg = NULL;
1106 if (!*place)
1107 ++BSDoptind;
1109 else { /* need an argument */
1110 if (*place) /* no white space */
1111 BSDoptarg = (char *)place;
1112 else if (nargc <= ++BSDoptind) { /* no arg */
1113 place = EMSG;
1114 if (*ostr == ':')
1115 return (BADARG);
1116 if (BSDopterr)
1117 (void)fprintf(stderr,
1118 "%s: option requires an argument -- %c\n",
1119 getprogname(), BSDoptopt);
1120 return (BADCH);
1122 else /* white space */
1123 BSDoptarg = nargv[BSDoptind];
1124 place = EMSG;
1125 ++BSDoptind;
1127 return (BSDoptopt); /* dump back option letter */
1129 #endif
1130 #if !HAVE_REALLOCARRAY
1132 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
1134 * Permission to use, copy, modify, and distribute this software for any
1135 * purpose with or without fee is hereby granted, provided that the above
1136 * copyright notice and this permission notice appear in all copies.
1138 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1139 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1140 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1141 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1142 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1143 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1144 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1147 #include <sys/types.h>
1148 #include <errno.h>
1149 #include <stdint.h>
1150 #include <stdlib.h>
1153 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1154 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1156 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1158 void *
1159 reallocarray(void *optr, size_t nmemb, size_t size)
1161 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1162 nmemb > 0 && SIZE_MAX / nmemb < size) {
1163 errno = ENOMEM;
1164 return NULL;
1166 return realloc(optr, size * nmemb);
1168 #endif /* !HAVE_REALLOCARRAY */
1169 #if !HAVE_RECALLOCARRAY
1171 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
1173 * Permission to use, copy, modify, and distribute this software for any
1174 * purpose with or without fee is hereby granted, provided that the above
1175 * copyright notice and this permission notice appear in all copies.
1177 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1178 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1179 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1180 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1181 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1182 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1183 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1186 /* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */
1188 #include <errno.h>
1189 #include <stdlib.h>
1190 #include <stdint.h>
1191 #include <string.h>
1192 #include <unistd.h>
1195 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1196 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1198 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1200 void *
1201 recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
1203 size_t oldsize, newsize;
1204 void *newptr;
1206 if (ptr == NULL)
1207 return calloc(newnmemb, size);
1209 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1210 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
1211 errno = ENOMEM;
1212 return NULL;
1214 newsize = newnmemb * size;
1216 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1217 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
1218 errno = EINVAL;
1219 return NULL;
1221 oldsize = oldnmemb * size;
1224 * Don't bother too much if we're shrinking just a bit,
1225 * we do not shrink for series of small steps, oh well.
1227 if (newsize <= oldsize) {
1228 size_t d = oldsize - newsize;
1230 if (d < oldsize / 2 && d < (size_t)getpagesize()) {
1231 memset((char *)ptr + newsize, 0, d);
1232 return ptr;
1236 newptr = malloc(newsize);
1237 if (newptr == NULL)
1238 return NULL;
1240 if (newsize > oldsize) {
1241 memcpy(newptr, ptr, oldsize);
1242 memset((char *)newptr + oldsize, 0, newsize - oldsize);
1243 } else
1244 memcpy(newptr, ptr, newsize);
1246 explicit_bzero(ptr, oldsize);
1247 free(ptr);
1249 return newptr;
1251 #endif /* !HAVE_RECALLOCARRAY */
1252 #if !HAVE_SETPROCTITLE
1254 * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
1256 * Permission to use, copy, modify, and distribute this software for any
1257 * purpose with or without fee is hereby granted, provided that the above
1258 * copyright notice and this permission notice appear in all copies.
1260 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1261 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1262 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1263 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1264 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
1265 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1266 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1269 # if HAVE_PR_SET_NAME
1270 #include <sys/types.h>
1271 #include <stdarg.h>
1272 #include <stdio.h>
1273 #include <string.h>
1274 #include <sys/prctl.h>
1275 void
1276 setproctitle(const char *fmt, ...)
1278 char title[16], name[16], *cp;
1279 va_list ap;
1280 int used;
1282 va_start(ap, fmt);
1283 vsnprintf(title, sizeof(title), fmt, ap);
1284 va_end(ap);
1286 used = snprintf(name, sizeof(name), "%s: %s", getprogname(), title);
1287 if (used >= (int)sizeof(name)) {
1288 cp = strrchr(name, ' ');
1289 if (cp != NULL)
1290 *cp = '\0';
1292 prctl(PR_SET_NAME, name);
1294 # else
1295 void
1296 setproctitle(const char *fmt, ...)
1298 return;
1300 # endif
1301 #endif /* !HAVE_SETPROCTITLE */
1302 #if !HAVE_STRLCAT
1304 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1306 * Permission to use, copy, modify, and distribute this software for any
1307 * purpose with or without fee is hereby granted, provided that the above
1308 * copyright notice and this permission notice appear in all copies.
1310 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1311 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1312 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1313 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1314 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1315 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1316 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1319 #include <sys/types.h>
1320 #include <string.h>
1323 * Appends src to string dst of size siz (unlike strncat, siz is the
1324 * full size of dst, not space left). At most siz-1 characters
1325 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
1326 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
1327 * If retval >= siz, truncation occurred.
1329 size_t
1330 strlcat(char *dst, const char *src, size_t siz)
1332 char *d = dst;
1333 const char *s = src;
1334 size_t n = siz;
1335 size_t dlen;
1337 /* Find the end of dst and adjust bytes left but don't go past end */
1338 while (n-- != 0 && *d != '\0')
1339 d++;
1340 dlen = d - dst;
1341 n = siz - dlen;
1343 if (n == 0)
1344 return(dlen + strlen(s));
1345 while (*s != '\0') {
1346 if (n != 1) {
1347 *d++ = *s;
1348 n--;
1350 s++;
1352 *d = '\0';
1354 return(dlen + (s - src)); /* count does not include NUL */
1356 #endif /* !HAVE_STRLCAT */
1357 #if !HAVE_STRLCPY
1359 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1361 * Permission to use, copy, modify, and distribute this software for any
1362 * purpose with or without fee is hereby granted, provided that the above
1363 * copyright notice and this permission notice appear in all copies.
1365 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1366 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1367 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1368 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1369 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1370 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1371 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1374 #include <sys/types.h>
1375 #include <string.h>
1378 * Copy src to string dst of size siz. At most siz-1 characters
1379 * will be copied. Always NUL terminates (unless siz == 0).
1380 * Returns strlen(src); if retval >= siz, truncation occurred.
1382 size_t
1383 strlcpy(char *dst, const char *src, size_t siz)
1385 char *d = dst;
1386 const char *s = src;
1387 size_t n = siz;
1389 /* Copy as many bytes as will fit */
1390 if (n != 0) {
1391 while (--n != 0) {
1392 if ((*d++ = *s++) == '\0')
1393 break;
1397 /* Not enough room in dst, add NUL and traverse rest of src */
1398 if (n == 0) {
1399 if (siz != 0)
1400 *d = '\0'; /* NUL-terminate dst */
1401 while (*s++)
1405 return(s - src - 1); /* count does not include NUL */
1407 #endif /* !HAVE_STRLCPY */
1408 #if !HAVE_STRNDUP
1409 /* $OpenBSD$ */
1411 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1413 * Permission to use, copy, modify, and distribute this software for any
1414 * purpose with or without fee is hereby granted, provided that the above
1415 * copyright notice and this permission notice appear in all copies.
1417 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1418 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1419 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1420 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1421 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1422 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1423 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1426 #include <sys/types.h>
1428 #include <stddef.h>
1429 #include <stdlib.h>
1430 #include <string.h>
1432 char *
1433 strndup(const char *str, size_t maxlen)
1435 char *copy;
1436 size_t len;
1438 len = strnlen(str, maxlen);
1439 copy = malloc(len + 1);
1440 if (copy != NULL) {
1441 (void)memcpy(copy, str, len);
1442 copy[len] = '\0';
1445 return copy;
1447 #endif /* !HAVE_STRNDUP */
1448 #if !HAVE_STRNLEN
1449 /* $OpenBSD$ */
1452 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1454 * Permission to use, copy, modify, and distribute this software for any
1455 * purpose with or without fee is hereby granted, provided that the above
1456 * copyright notice and this permission notice appear in all copies.
1458 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1459 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1460 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1461 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1462 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1463 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1464 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1467 #include <sys/types.h>
1468 #include <string.h>
1470 size_t
1471 strnlen(const char *str, size_t maxlen)
1473 const char *cp;
1475 for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
1478 return (size_t)(cp - str);
1480 #endif /* !HAVE_STRNLEN */
1481 #if !HAVE_STRTONUM
1483 * Copyright (c) 2004 Ted Unangst and Todd Miller
1484 * All rights reserved.
1486 * Permission to use, copy, modify, and distribute this software for any
1487 * purpose with or without fee is hereby granted, provided that the above
1488 * copyright notice and this permission notice appear in all copies.
1490 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1491 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1492 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1493 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1494 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1495 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1496 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1499 #include <errno.h>
1500 #include <limits.h>
1501 #include <stdlib.h>
1503 #define INVALID 1
1504 #define TOOSMALL 2
1505 #define TOOLARGE 3
1507 long long
1508 strtonum(const char *numstr, long long minval, long long maxval,
1509 const char **errstrp)
1511 long long ll = 0;
1512 int error = 0;
1513 char *ep;
1514 struct errval {
1515 const char *errstr;
1516 int err;
1517 } ev[4] = {
1518 { NULL, 0 },
1519 { "invalid", EINVAL },
1520 { "too small", ERANGE },
1521 { "too large", ERANGE },
1524 ev[0].err = errno;
1525 errno = 0;
1526 if (minval > maxval) {
1527 error = INVALID;
1528 } else {
1529 ll = strtoll(numstr, &ep, 10);
1530 if (numstr == ep || *ep != '\0')
1531 error = INVALID;
1532 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
1533 error = TOOSMALL;
1534 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
1535 error = TOOLARGE;
1537 if (errstrp != NULL)
1538 *errstrp = ev[error].errstr;
1539 errno = ev[error].err;
1540 if (error)
1541 ll = 0;
1543 return (ll);
1545 #endif /* !HAVE_STRTONUM */