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_LIB_IMSG
325 /* $OpenBSD: imsg-buffer.c,v 1.16 2023/06/19 17:19:50 claudio Exp $ */
326 /* $OpenBSD: imsg.c,v 1.19 2023/06/19 17:19:50 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 *);
361 static void msgbuf_drain(struct msgbuf *, size_t);
363 struct ibuf *
364 ibuf_open(size_t len)
366 struct ibuf *buf;
368 if (len == 0) {
369 errno = EINVAL;
370 return (NULL);
372 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
373 return (NULL);
374 if ((buf->buf = calloc(len, 1)) == NULL) {
375 free(buf);
376 return (NULL);
378 buf->size = buf->max = len;
379 buf->fd = -1;
381 return (buf);
384 struct ibuf *
385 ibuf_dynamic(size_t len, size_t max)
387 struct ibuf *buf;
389 if (max < len) {
390 errno = EINVAL;
391 return (NULL);
394 if ((buf = calloc(1, sizeof(struct ibuf))) == NULL)
395 return (NULL);
396 if (len > 0) {
397 if ((buf->buf = calloc(len, 1)) == NULL) {
398 free(buf);
399 return (NULL);
402 buf->size = len;
403 buf->max = max;
404 buf->fd = -1;
406 return (buf);
409 static int
410 ibuf_realloc(struct ibuf *buf, size_t len)
412 unsigned char *b;
414 /* on static buffers max is eq size and so the following fails */
415 if (len > SIZE_MAX - buf->wpos || buf->wpos + len > buf->max) {
416 errno = ERANGE;
417 return (-1);
420 b = recallocarray(buf->buf, buf->size, buf->wpos + len, 1);
421 if (b == NULL)
422 return (-1);
423 buf->buf = b;
424 buf->size = buf->wpos + len;
426 return (0);
429 void *
430 ibuf_reserve(struct ibuf *buf, size_t len)
432 void *b;
434 if (len > SIZE_MAX - buf->wpos) {
435 errno = ERANGE;
436 return (NULL);
439 if (buf->wpos + len > buf->size)
440 if (ibuf_realloc(buf, len) == -1)
441 return (NULL);
443 b = buf->buf + buf->wpos;
444 buf->wpos += len;
445 memset(b, 0, len);
446 return (b);
449 int
450 ibuf_add(struct ibuf *buf, const void *data, size_t len)
452 void *b;
454 if ((b = ibuf_reserve(buf, len)) == NULL)
455 return (-1);
457 memcpy(b, data, len);
458 return (0);
461 int
462 ibuf_add_buf(struct ibuf *buf, const struct ibuf *from)
464 return ibuf_add(buf, from->buf, from->wpos);
467 int
468 ibuf_add_n8(struct ibuf *buf, uint64_t value)
470 uint8_t v;
472 if (value > UINT8_MAX) {
473 errno = EINVAL;
474 return (-1);
476 v = value;
477 return ibuf_add(buf, &v, sizeof(v));
480 int
481 ibuf_add_n16(struct ibuf *buf, uint64_t value)
483 uint16_t v;
485 if (value > UINT16_MAX) {
486 errno = EINVAL;
487 return (-1);
489 v = htobe16(value);
490 return ibuf_add(buf, &v, sizeof(v));
493 int
494 ibuf_add_n32(struct ibuf *buf, uint64_t value)
496 uint32_t v;
498 if (value > UINT32_MAX) {
499 errno = EINVAL;
500 return (-1);
502 v = htobe32(value);
503 return ibuf_add(buf, &v, sizeof(v));
506 int
507 ibuf_add_n64(struct ibuf *buf, uint64_t value)
509 value = htobe64(value);
510 return ibuf_add(buf, &value, sizeof(value));
513 int
514 ibuf_add_zero(struct ibuf *buf, size_t len)
516 void *b;
518 if ((b = ibuf_reserve(buf, len)) == NULL)
519 return (-1);
520 return (0);
523 void *
524 ibuf_seek(struct ibuf *buf, size_t pos, size_t len)
526 /* only allowed to seek in already written parts */
527 if (len > SIZE_MAX - pos || pos + len > buf->wpos) {
528 errno = ERANGE;
529 return (NULL);
532 return (buf->buf + pos);
535 int
536 ibuf_set(struct ibuf *buf, size_t pos, const void *data, size_t len)
538 void *b;
540 if ((b = ibuf_seek(buf, pos, len)) == NULL)
541 return (-1);
543 memcpy(b, data, len);
544 return (0);
547 int
548 ibuf_set_n8(struct ibuf *buf, size_t pos, uint64_t value)
550 uint8_t v;
552 if (value > UINT8_MAX) {
553 errno = EINVAL;
554 return (-1);
556 v = value;
557 return (ibuf_set(buf, pos, &v, sizeof(v)));
560 int
561 ibuf_set_n16(struct ibuf *buf, size_t pos, uint64_t value)
563 uint16_t v;
565 if (value > UINT16_MAX) {
566 errno = EINVAL;
567 return (-1);
569 v = htobe16(value);
570 return (ibuf_set(buf, pos, &v, sizeof(v)));
573 int
574 ibuf_set_n32(struct ibuf *buf, size_t pos, uint64_t value)
576 uint32_t v;
578 if (value > UINT32_MAX) {
579 errno = EINVAL;
580 return (-1);
582 v = htobe32(value);
583 return (ibuf_set(buf, pos, &v, sizeof(v)));
586 int
587 ibuf_set_n64(struct ibuf *buf, size_t pos, uint64_t value)
589 value = htobe64(value);
590 return (ibuf_set(buf, pos, &value, sizeof(value)));
593 void *
594 ibuf_data(struct ibuf *buf)
596 return (buf->buf);
599 size_t
600 ibuf_size(struct ibuf *buf)
602 return (buf->wpos);
605 size_t
606 ibuf_left(struct ibuf *buf)
608 return (buf->max - buf->wpos);
611 void
612 ibuf_close(struct msgbuf *msgbuf, struct ibuf *buf)
614 ibuf_enqueue(msgbuf, buf);
617 void
618 ibuf_free(struct ibuf *buf)
620 if (buf == NULL)
621 return;
622 #ifdef NOTYET
623 if (buf->fd != -1)
624 close(buf->fd);
625 #endif
626 freezero(buf->buf, buf->size);
627 free(buf);
630 int
631 ibuf_fd_avail(struct ibuf *buf)
633 return (buf->fd != -1);
636 int
637 ibuf_fd_get(struct ibuf *buf)
639 int fd;
641 fd = buf->fd;
642 #ifdef NOTYET
643 buf->fd = -1;
644 #endif
645 return (fd);
648 void
649 ibuf_fd_set(struct ibuf *buf, int fd)
651 if (buf->fd != -1)
652 close(buf->fd);
653 buf->fd = fd;
656 int
657 ibuf_write(struct msgbuf *msgbuf)
659 struct iovec iov[IOV_MAX];
660 struct ibuf *buf;
661 unsigned int i = 0;
662 ssize_t n;
664 memset(&iov, 0, sizeof(iov));
665 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
666 if (i >= IOV_MAX)
667 break;
668 iov[i].iov_base = buf->buf + buf->rpos;
669 iov[i].iov_len = buf->wpos - buf->rpos;
670 i++;
673 again:
674 if ((n = writev(msgbuf->fd, iov, i)) == -1) {
675 if (errno == EINTR)
676 goto again;
677 if (errno == ENOBUFS)
678 errno = EAGAIN;
679 return (-1);
682 if (n == 0) { /* connection closed */
683 errno = 0;
684 return (0);
687 msgbuf_drain(msgbuf, n);
689 return (1);
692 void
693 msgbuf_init(struct msgbuf *msgbuf)
695 msgbuf->queued = 0;
696 msgbuf->fd = -1;
697 TAILQ_INIT(&msgbuf->bufs);
700 static void
701 msgbuf_drain(struct msgbuf *msgbuf, size_t n)
703 struct ibuf *buf, *next;
705 for (buf = TAILQ_FIRST(&msgbuf->bufs); buf != NULL && n > 0;
706 buf = next) {
707 next = TAILQ_NEXT(buf, entry);
708 if (n >= buf->wpos - buf->rpos) {
709 n -= buf->wpos - buf->rpos;
710 ibuf_dequeue(msgbuf, buf);
711 } else {
712 buf->rpos += n;
713 n = 0;
718 void
719 msgbuf_clear(struct msgbuf *msgbuf)
721 struct ibuf *buf;
723 while ((buf = TAILQ_FIRST(&msgbuf->bufs)) != NULL)
724 ibuf_dequeue(msgbuf, buf);
727 int
728 msgbuf_write(struct msgbuf *msgbuf)
730 struct iovec iov[IOV_MAX];
731 struct ibuf *buf, *buf0 = NULL;
732 unsigned int i = 0;
733 ssize_t n;
734 struct msghdr msg;
735 struct cmsghdr *cmsg;
736 union {
737 struct cmsghdr hdr;
738 char buf[CMSG_SPACE(sizeof(int))];
739 } cmsgbuf;
741 memset(&iov, 0, sizeof(iov));
742 memset(&msg, 0, sizeof(msg));
743 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
744 TAILQ_FOREACH(buf, &msgbuf->bufs, entry) {
745 if (i >= IOV_MAX)
746 break;
747 if (i > 0 && buf->fd != -1)
748 break;
749 iov[i].iov_base = buf->buf + buf->rpos;
750 iov[i].iov_len = buf->wpos - buf->rpos;
751 i++;
752 if (buf->fd != -1)
753 buf0 = buf;
756 msg.msg_iov = iov;
757 msg.msg_iovlen = i;
759 if (buf0 != NULL) {
760 msg.msg_control = (caddr_t)&cmsgbuf.buf;
761 msg.msg_controllen = sizeof(cmsgbuf.buf);
762 cmsg = CMSG_FIRSTHDR(&msg);
763 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
764 cmsg->cmsg_level = SOL_SOCKET;
765 cmsg->cmsg_type = SCM_RIGHTS;
766 *(int *)CMSG_DATA(cmsg) = buf0->fd;
769 again:
770 if ((n = sendmsg(msgbuf->fd, &msg, 0)) == -1) {
771 if (errno == EINTR)
772 goto again;
773 if (errno == ENOBUFS)
774 errno = EAGAIN;
775 return (-1);
778 if (n == 0) { /* connection closed */
779 errno = 0;
780 return (0);
783 /*
784 * assumption: fd got sent if sendmsg sent anything
785 * this works because fds are passed one at a time
786 */
787 if (buf0 != NULL) {
788 close(buf0->fd);
789 buf0->fd = -1;
792 msgbuf_drain(msgbuf, n);
794 return (1);
797 static void
798 ibuf_enqueue(struct msgbuf *msgbuf, struct ibuf *buf)
800 TAILQ_INSERT_TAIL(&msgbuf->bufs, buf, entry);
801 msgbuf->queued++;
804 static void
805 ibuf_dequeue(struct msgbuf *msgbuf, struct ibuf *buf)
807 TAILQ_REMOVE(&msgbuf->bufs, buf, entry);
809 if (buf->fd != -1) {
810 close(buf->fd);
811 buf->fd = -1;
814 msgbuf->queued--;
815 ibuf_free(buf);
818 /* imsg.c */
820 int imsg_fd_overhead = 0;
822 static int imsg_get_fd(struct imsgbuf *);
824 void
825 imsg_init(struct imsgbuf *ibuf, int fd)
827 msgbuf_init(&ibuf->w);
828 memset(&ibuf->r, 0, sizeof(ibuf->r));
829 ibuf->fd = fd;
830 ibuf->w.fd = fd;
831 ibuf->pid = getpid();
832 TAILQ_INIT(&ibuf->fds);
835 ssize_t
836 imsg_read(struct imsgbuf *ibuf)
838 struct msghdr msg;
839 struct cmsghdr *cmsg;
840 union {
841 struct cmsghdr hdr;
842 char buf[CMSG_SPACE(sizeof(int) * 1)];
843 } cmsgbuf;
844 struct iovec iov;
845 ssize_t n = -1;
846 int fd;
847 struct imsg_fd *ifd;
849 memset(&msg, 0, sizeof(msg));
850 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
852 iov.iov_base = ibuf->r.buf + ibuf->r.wpos;
853 iov.iov_len = sizeof(ibuf->r.buf) - ibuf->r.wpos;
854 msg.msg_iov = &iov;
855 msg.msg_iovlen = 1;
856 msg.msg_control = &cmsgbuf.buf;
857 msg.msg_controllen = sizeof(cmsgbuf.buf);
859 if ((ifd = calloc(1, sizeof(struct imsg_fd))) == NULL)
860 return (-1);
862 again:
863 if (getdtablecount() + imsg_fd_overhead +
864 (int)((CMSG_SPACE(sizeof(int))-CMSG_SPACE(0))/sizeof(int))
865 >= getdtablesize()) {
866 errno = EAGAIN;
867 free(ifd);
868 return (-1);
871 if ((n = recvmsg(ibuf->fd, &msg, 0)) == -1) {
872 if (errno == EINTR)
873 goto again;
874 goto fail;
877 ibuf->r.wpos += n;
879 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
880 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
881 if (cmsg->cmsg_level == SOL_SOCKET &&
882 cmsg->cmsg_type == SCM_RIGHTS) {
883 int i;
884 int j;
886 /*
887 * We only accept one file descriptor. Due to C
888 * padding rules, our control buffer might contain
889 * more than one fd, and we must close them.
890 */
891 j = ((char *)cmsg + cmsg->cmsg_len -
892 (char *)CMSG_DATA(cmsg)) / sizeof(int);
893 for (i = 0; i < j; i++) {
894 fd = ((int *)CMSG_DATA(cmsg))[i];
895 if (ifd != NULL) {
896 ifd->fd = fd;
897 TAILQ_INSERT_TAIL(&ibuf->fds, ifd,
898 entry);
899 ifd = NULL;
900 } else
901 close(fd);
904 /* we do not handle other ctl data level */
907 fail:
908 free(ifd);
909 return (n);
912 ssize_t
913 imsg_get(struct imsgbuf *ibuf, struct imsg *imsg)
915 size_t av, left, datalen;
917 av = ibuf->r.wpos;
919 if (IMSG_HEADER_SIZE > av)
920 return (0);
922 memcpy(&imsg->hdr, ibuf->r.buf, sizeof(imsg->hdr));
923 if (imsg->hdr.len < IMSG_HEADER_SIZE ||
924 imsg->hdr.len > MAX_IMSGSIZE) {
925 errno = ERANGE;
926 return (-1);
928 if (imsg->hdr.len > av)
929 return (0);
930 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
931 ibuf->r.rptr = ibuf->r.buf + IMSG_HEADER_SIZE;
932 if (datalen == 0)
933 imsg->data = NULL;
934 else if ((imsg->data = malloc(datalen)) == NULL)
935 return (-1);
937 if (imsg->hdr.flags & IMSGF_HASFD)
938 imsg->fd = imsg_get_fd(ibuf);
939 else
940 imsg->fd = -1;
942 if (datalen != 0)
943 memcpy(imsg->data, ibuf->r.rptr, datalen);
945 if (imsg->hdr.len < av) {
946 left = av - imsg->hdr.len;
947 memmove(&ibuf->r.buf, ibuf->r.buf + imsg->hdr.len, left);
948 ibuf->r.wpos = left;
949 } else
950 ibuf->r.wpos = 0;
952 return (datalen + IMSG_HEADER_SIZE);
955 int
956 imsg_compose(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
957 int fd, const void *data, uint16_t datalen)
959 struct ibuf *wbuf;
961 if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
962 return (-1);
964 if (imsg_add(wbuf, data, datalen) == -1)
965 return (-1);
967 ibuf_fd_set(wbuf, fd);
968 imsg_close(ibuf, wbuf);
970 return (1);
973 int
974 imsg_composev(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
975 int fd, const struct iovec *iov, int iovcnt)
977 struct ibuf *wbuf;
978 int i, datalen = 0;
980 for (i = 0; i < iovcnt; i++)
981 datalen += iov[i].iov_len;
983 if ((wbuf = imsg_create(ibuf, type, peerid, pid, datalen)) == NULL)
984 return (-1);
986 for (i = 0; i < iovcnt; i++)
987 if (imsg_add(wbuf, iov[i].iov_base, iov[i].iov_len) == -1)
988 return (-1);
990 ibuf_fd_set(wbuf, fd);
991 imsg_close(ibuf, wbuf);
993 return (1);
996 int
997 imsg_compose_ibuf(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid,
998 pid_t pid, struct ibuf *buf)
1000 struct ibuf *wbuf = NULL;
1001 struct imsg_hdr hdr;
1002 int save_errno;
1004 if (ibuf_size(buf) + IMSG_HEADER_SIZE > MAX_IMSGSIZE) {
1005 errno = ERANGE;
1006 goto fail;
1009 hdr.type = type;
1010 hdr.len = ibuf_size(buf) + IMSG_HEADER_SIZE;
1011 hdr.flags = 0;
1012 hdr.peerid = peerid;
1013 if ((hdr.pid = pid) == 0)
1014 hdr.pid = ibuf->pid;
1016 if ((wbuf = ibuf_open(IMSG_HEADER_SIZE)) == NULL)
1017 goto fail;
1018 if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
1019 goto fail;
1021 ibuf_close(&ibuf->w, wbuf);
1022 ibuf_close(&ibuf->w, buf);
1023 return (1);
1025 fail:
1026 save_errno = errno;
1027 ibuf_free(buf);
1028 ibuf_free(wbuf);
1029 errno = save_errno;
1030 return (-1);
1033 struct ibuf *
1034 imsg_create(struct imsgbuf *ibuf, uint32_t type, uint32_t peerid, pid_t pid,
1035 uint16_t datalen)
1037 struct ibuf *wbuf;
1038 struct imsg_hdr hdr;
1040 datalen += IMSG_HEADER_SIZE;
1041 if (datalen > MAX_IMSGSIZE) {
1042 errno = ERANGE;
1043 return (NULL);
1046 hdr.type = type;
1047 hdr.flags = 0;
1048 hdr.peerid = peerid;
1049 if ((hdr.pid = pid) == 0)
1050 hdr.pid = ibuf->pid;
1051 if ((wbuf = ibuf_dynamic(datalen, MAX_IMSGSIZE)) == NULL) {
1052 return (NULL);
1054 if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1)
1055 return (NULL);
1057 return (wbuf);
1060 int
1061 imsg_add(struct ibuf *msg, const void *data, uint16_t datalen)
1063 if (datalen)
1064 if (ibuf_add(msg, data, datalen) == -1) {
1065 ibuf_free(msg);
1066 return (-1);
1068 return (datalen);
1071 void
1072 imsg_close(struct imsgbuf *ibuf, struct ibuf *msg)
1074 struct imsg_hdr *hdr;
1076 hdr = (struct imsg_hdr *)msg->buf;
1078 hdr->flags &= ~IMSGF_HASFD;
1079 if (ibuf_fd_avail(msg))
1080 hdr->flags |= IMSGF_HASFD;
1081 hdr->len = ibuf_size(msg);
1083 ibuf_close(&ibuf->w, msg);
1086 void
1087 imsg_free(struct imsg *imsg)
1089 freezero(imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE);
1092 static int
1093 imsg_get_fd(struct imsgbuf *ibuf)
1095 int fd;
1096 struct imsg_fd *ifd;
1098 if ((ifd = TAILQ_FIRST(&ibuf->fds)) == NULL)
1099 return (-1);
1101 fd = ifd->fd;
1102 TAILQ_REMOVE(&ibuf->fds, ifd, entry);
1103 free(ifd);
1105 return (fd);
1108 int
1109 imsg_flush(struct imsgbuf *ibuf)
1111 while (ibuf->w.queued)
1112 if (msgbuf_write(&ibuf->w) <= 0)
1113 return (-1);
1114 return (0);
1117 void
1118 imsg_clear(struct imsgbuf *ibuf)
1120 int fd;
1122 msgbuf_clear(&ibuf->w);
1123 while ((fd = imsg_get_fd(ibuf)) != -1)
1124 close(fd);
1126 #endif /* HAVE_LIB_IMSG */
1127 #if !HAVE_MEMMEM
1128 /*-
1129 * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
1131 * Redistribution and use in source and binary forms, with or without
1132 * modification, are permitted provided that the following conditions
1133 * are met:
1134 * 1. Redistributions of source code must retain the above copyright
1135 * notice, this list of conditions and the following disclaimer.
1136 * 2. Redistributions in binary form must reproduce the above copyright
1137 * notice, this list of conditions and the following disclaimer in
1138 * the documentation and/or other materials provided with the
1139 * distribution.
1140 * 3. The name of the author may not be used to endorse or promote
1141 * products derived from this software without specific prior written
1142 * permission.
1144 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
1145 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
1146 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
1147 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
1148 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
1149 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1150 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1151 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1152 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1153 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1154 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1157 * Find the first occurrence of the byte string s in byte string l.
1159 void *
1160 memmem(const void *l, size_t l_len, const void *s, size_t s_len)
1162 const char *cur, *last;
1163 const char *cl = l;
1164 const char *cs = s;
1166 /* a zero length needle should just return the haystack */
1167 if (l_len == 0)
1168 return (void *)cl;
1170 /* "s" must be smaller or equal to "l" */
1171 if (l_len < s_len)
1172 return NULL;
1174 /* special case where s_len == 1 */
1175 if (s_len == 1)
1176 return memchr(l, *cs, l_len);
1178 /* the last position where its possible to find "s" in "l" */
1179 last = cl + l_len - s_len;
1181 for (cur = cl; cur <= last; cur++)
1182 if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
1183 return (void *)cur;
1185 return NULL;
1187 #endif /* !HAVE_MEMMEM */
1188 #if !HAVE_MEMRCHR
1190 * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
1192 * Permission to use, copy, modify, and distribute this software for any
1193 * purpose with or without fee is hereby granted, provided that the above
1194 * copyright notice and this permission notice appear in all copies.
1196 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1197 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1198 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1199 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1200 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1201 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1202 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1206 #include <string.h>
1209 * Reverse memchr()
1210 * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
1212 void *
1213 memrchr(const void *s, int c, size_t n)
1215 const unsigned char *cp;
1217 if (n != 0) {
1218 cp = (unsigned char *)s + n;
1219 do {
1220 if (*(--cp) == (unsigned char)c)
1221 return((void *)cp);
1222 } while (--n != 0);
1224 return(NULL);
1226 #endif /* !HAVE_MEMRCHR */
1227 #if !HAVE_OPTRESET
1229 * Copyright (c) 1987, 1993, 1994
1230 * The Regents of the University of California. All rights reserved.
1232 * Redistribution and use in source and binary forms, with or without
1233 * modification, are permitted provided that the following conditions
1234 * are met:
1235 * 1. Redistributions of source code must retain the above copyright
1236 * notice, this list of conditions and the following disclaimer.
1237 * 2. Redistributions in binary form must reproduce the above copyright
1238 * notice, this list of conditions and the following disclaimer in the
1239 * documentation and/or other materials provided with the distribution.
1240 * 3. Neither the name of the University nor the names of its contributors
1241 * may be used to endorse or promote products derived from this software
1242 * without specific prior written permission.
1244 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1245 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1246 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1247 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
1248 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1249 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1250 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1251 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1252 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1253 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1254 * SUCH DAMAGE.
1257 /* OPENBSD ORIGINAL: lib/libc/stdlib/getopt.c */
1259 #include <stdio.h>
1260 #include <stdlib.h>
1261 #include <string.h>
1263 int BSDopterr = 1, /* if error message should be printed */
1264 BSDoptind = 1, /* index into parent argv vector */
1265 BSDoptopt, /* character checked for validity */
1266 BSDoptreset; /* reset getopt */
1267 char *BSDoptarg; /* argument associated with option */
1269 #define BADCH (int)'?'
1270 #define BADARG (int)':'
1271 #define EMSG ""
1274 * getopt --
1275 * Parse argc/argv argument vector.
1277 int
1278 BSDgetopt(int nargc, char *const *nargv, const char *ostr)
1280 static const char *place = EMSG; /* option letter processing */
1281 char *oli; /* option letter list index */
1283 if (ostr == NULL)
1284 return (-1);
1286 if (BSDoptreset || !*place) { /* update scanning pointer */
1287 BSDoptreset = 0;
1288 if (BSDoptind >= nargc || *(place = nargv[BSDoptind]) != '-') {
1289 place = EMSG;
1290 return (-1);
1292 if (place[1] && *++place == '-') { /* found "--" */
1293 if (place[1])
1294 return (BADCH);
1295 ++BSDoptind;
1296 place = EMSG;
1297 return (-1);
1299 } /* option letter okay? */
1300 if ((BSDoptopt = (int)*place++) == (int)':' ||
1301 !(oli = strchr(ostr, BSDoptopt))) {
1303 * if the user didn't specify '-' as an option,
1304 * assume it means -1.
1306 if (BSDoptopt == (int)'-')
1307 return (-1);
1308 if (!*place)
1309 ++BSDoptind;
1310 if (BSDopterr && *ostr != ':')
1311 (void)fprintf(stderr,
1312 "%s: unknown option -- %c\n", getprogname(),
1313 BSDoptopt);
1314 return (BADCH);
1316 if (*++oli != ':') { /* don't need argument */
1317 BSDoptarg = NULL;
1318 if (!*place)
1319 ++BSDoptind;
1321 else { /* need an argument */
1322 if (*place) /* no white space */
1323 BSDoptarg = (char *)place;
1324 else if (nargc <= ++BSDoptind) { /* no arg */
1325 place = EMSG;
1326 if (*ostr == ':')
1327 return (BADARG);
1328 if (BSDopterr)
1329 (void)fprintf(stderr,
1330 "%s: option requires an argument -- %c\n",
1331 getprogname(), BSDoptopt);
1332 return (BADCH);
1334 else /* white space */
1335 BSDoptarg = nargv[BSDoptind];
1336 place = EMSG;
1337 ++BSDoptind;
1339 return (BSDoptopt); /* dump back option letter */
1341 #endif
1342 #if !HAVE_REALLOCARRAY
1344 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
1346 * Permission to use, copy, modify, and distribute this software for any
1347 * purpose with or without fee is hereby granted, provided that the above
1348 * copyright notice and this permission notice appear in all copies.
1350 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1351 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1352 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1353 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1354 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1355 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1356 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1359 #include <sys/types.h>
1360 #include <errno.h>
1361 #include <stdint.h>
1362 #include <stdlib.h>
1365 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1366 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1368 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1370 void *
1371 reallocarray(void *optr, size_t nmemb, size_t size)
1373 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1374 nmemb > 0 && SIZE_MAX / nmemb < size) {
1375 errno = ENOMEM;
1376 return NULL;
1378 return realloc(optr, size * nmemb);
1380 #endif /* !HAVE_REALLOCARRAY */
1381 #if !HAVE_RECALLOCARRAY
1383 * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
1385 * Permission to use, copy, modify, and distribute this software for any
1386 * purpose with or without fee is hereby granted, provided that the above
1387 * copyright notice and this permission notice appear in all copies.
1389 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1390 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1391 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1392 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1393 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1394 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1395 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1398 /* OPENBSD ORIGINAL: lib/libc/stdlib/recallocarray.c */
1400 #include <errno.h>
1401 #include <stdlib.h>
1402 #include <stdint.h>
1403 #include <string.h>
1404 #include <unistd.h>
1407 * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
1408 * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
1410 #define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
1412 void *
1413 recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
1415 size_t oldsize, newsize;
1416 void *newptr;
1418 if (ptr == NULL)
1419 return calloc(newnmemb, size);
1421 if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1422 newnmemb > 0 && SIZE_MAX / newnmemb < size) {
1423 errno = ENOMEM;
1424 return NULL;
1426 newsize = newnmemb * size;
1428 if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1429 oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
1430 errno = EINVAL;
1431 return NULL;
1433 oldsize = oldnmemb * size;
1436 * Don't bother too much if we're shrinking just a bit,
1437 * we do not shrink for series of small steps, oh well.
1439 if (newsize <= oldsize) {
1440 size_t d = oldsize - newsize;
1442 if (d < oldsize / 2 && d < (size_t)getpagesize()) {
1443 memset((char *)ptr + newsize, 0, d);
1444 return ptr;
1448 newptr = malloc(newsize);
1449 if (newptr == NULL)
1450 return NULL;
1452 if (newsize > oldsize) {
1453 memcpy(newptr, ptr, oldsize);
1454 memset((char *)newptr + oldsize, 0, newsize - oldsize);
1455 } else
1456 memcpy(newptr, ptr, newsize);
1458 explicit_bzero(ptr, oldsize);
1459 free(ptr);
1461 return newptr;
1463 #endif /* !HAVE_RECALLOCARRAY */
1464 #if !HAVE_SETPROCTITLE
1466 * Copyright (c) 2016 Nicholas Marriott <nicholas.marriott@gmail.com>
1468 * Permission to use, copy, modify, and distribute this software for any
1469 * purpose with or without fee is hereby granted, provided that the above
1470 * copyright notice and this permission notice appear in all copies.
1472 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1473 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1474 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1475 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1476 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
1477 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
1478 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1481 # if HAVE_PR_SET_NAME
1482 #include <sys/types.h>
1483 #include <stdarg.h>
1484 #include <stdio.h>
1485 #include <string.h>
1486 #include <sys/prctl.h>
1487 void
1488 setproctitle(const char *fmt, ...)
1490 char title[16], name[16], *cp;
1491 va_list ap;
1492 int used;
1494 va_start(ap, fmt);
1495 vsnprintf(title, sizeof(title), fmt, ap);
1496 va_end(ap);
1498 used = snprintf(name, sizeof(name), "%s: %s", getprogname(), title);
1499 if (used >= (int)sizeof(name)) {
1500 cp = strrchr(name, ' ');
1501 if (cp != NULL)
1502 *cp = '\0';
1504 prctl(PR_SET_NAME, name);
1506 # else
1507 void
1508 setproctitle(const char *fmt, ...)
1510 return;
1512 # endif
1513 #endif /* !HAVE_SETPROCTITLE */
1514 #if !HAVE_STRLCAT
1516 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1518 * Permission to use, copy, modify, and distribute this software for any
1519 * purpose with or without fee is hereby granted, provided that the above
1520 * copyright notice and this permission notice appear in all copies.
1522 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1523 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1524 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1525 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1526 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1527 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1528 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1531 #include <sys/types.h>
1532 #include <string.h>
1535 * Appends src to string dst of size siz (unlike strncat, siz is the
1536 * full size of dst, not space left). At most siz-1 characters
1537 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
1538 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
1539 * If retval >= siz, truncation occurred.
1541 size_t
1542 strlcat(char *dst, const char *src, size_t siz)
1544 char *d = dst;
1545 const char *s = src;
1546 size_t n = siz;
1547 size_t dlen;
1549 /* Find the end of dst and adjust bytes left but don't go past end */
1550 while (n-- != 0 && *d != '\0')
1551 d++;
1552 dlen = d - dst;
1553 n = siz - dlen;
1555 if (n == 0)
1556 return(dlen + strlen(s));
1557 while (*s != '\0') {
1558 if (n != 1) {
1559 *d++ = *s;
1560 n--;
1562 s++;
1564 *d = '\0';
1566 return(dlen + (s - src)); /* count does not include NUL */
1568 #endif /* !HAVE_STRLCAT */
1569 #if !HAVE_STRLCPY
1571 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
1573 * Permission to use, copy, modify, and distribute this software for any
1574 * purpose with or without fee is hereby granted, provided that the above
1575 * copyright notice and this permission notice appear in all copies.
1577 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1578 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1579 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1580 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1581 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1582 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1583 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1586 #include <sys/types.h>
1587 #include <string.h>
1590 * Copy src to string dst of size siz. At most siz-1 characters
1591 * will be copied. Always NUL terminates (unless siz == 0).
1592 * Returns strlen(src); if retval >= siz, truncation occurred.
1594 size_t
1595 strlcpy(char *dst, const char *src, size_t siz)
1597 char *d = dst;
1598 const char *s = src;
1599 size_t n = siz;
1601 /* Copy as many bytes as will fit */
1602 if (n != 0) {
1603 while (--n != 0) {
1604 if ((*d++ = *s++) == '\0')
1605 break;
1609 /* Not enough room in dst, add NUL and traverse rest of src */
1610 if (n == 0) {
1611 if (siz != 0)
1612 *d = '\0'; /* NUL-terminate dst */
1613 while (*s++)
1617 return(s - src - 1); /* count does not include NUL */
1619 #endif /* !HAVE_STRLCPY */
1620 #if !HAVE_STRNDUP
1621 /* $OpenBSD$ */
1623 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1625 * Permission to use, copy, modify, and distribute this software for any
1626 * purpose with or without fee is hereby granted, provided that the above
1627 * copyright notice and this permission notice appear in all copies.
1629 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1630 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1631 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1632 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1633 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1634 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1635 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1638 #include <sys/types.h>
1640 #include <stddef.h>
1641 #include <stdlib.h>
1642 #include <string.h>
1644 char *
1645 strndup(const char *str, size_t maxlen)
1647 char *copy;
1648 size_t len;
1650 len = strnlen(str, maxlen);
1651 copy = malloc(len + 1);
1652 if (copy != NULL) {
1653 (void)memcpy(copy, str, len);
1654 copy[len] = '\0';
1657 return copy;
1659 #endif /* !HAVE_STRNDUP */
1660 #if !HAVE_STRNLEN
1661 /* $OpenBSD$ */
1664 * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
1666 * Permission to use, copy, modify, and distribute this software for any
1667 * purpose with or without fee is hereby granted, provided that the above
1668 * copyright notice and this permission notice appear in all copies.
1670 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1671 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1672 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1673 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1674 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1675 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1676 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1679 #include <sys/types.h>
1680 #include <string.h>
1682 size_t
1683 strnlen(const char *str, size_t maxlen)
1685 const char *cp;
1687 for (cp = str; maxlen != 0 && *cp != '\0'; cp++, maxlen--)
1690 return (size_t)(cp - str);
1692 #endif /* !HAVE_STRNLEN */
1693 #if !HAVE_STRTONUM
1695 * Copyright (c) 2004 Ted Unangst and Todd Miller
1696 * All rights reserved.
1698 * Permission to use, copy, modify, and distribute this software for any
1699 * purpose with or without fee is hereby granted, provided that the above
1700 * copyright notice and this permission notice appear in all copies.
1702 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1703 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1704 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1705 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1706 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1707 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1708 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1711 #include <errno.h>
1712 #include <limits.h>
1713 #include <stdlib.h>
1715 #define INVALID 1
1716 #define TOOSMALL 2
1717 #define TOOLARGE 3
1719 long long
1720 strtonum(const char *numstr, long long minval, long long maxval,
1721 const char **errstrp)
1723 long long ll = 0;
1724 int error = 0;
1725 char *ep;
1726 struct errval {
1727 const char *errstr;
1728 int err;
1729 } ev[4] = {
1730 { NULL, 0 },
1731 { "invalid", EINVAL },
1732 { "too small", ERANGE },
1733 { "too large", ERANGE },
1736 ev[0].err = errno;
1737 errno = 0;
1738 if (minval > maxval) {
1739 error = INVALID;
1740 } else {
1741 ll = strtoll(numstr, &ep, 10);
1742 if (numstr == ep || *ep != '\0')
1743 error = INVALID;
1744 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
1745 error = TOOSMALL;
1746 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
1747 error = TOOLARGE;
1749 if (errstrp != NULL)
1750 *errstrp = ev[error].errstr;
1751 errno = ev[error].err;
1752 if (error)
1753 ll = 0;
1755 return (ll);
1757 #endif /* !HAVE_STRTONUM */
1758 #if !HAVE_TIMESPECSUB
1759 #include <sys/time.h>
1760 void
1761 timespecsub(struct timespec *a, struct timespec *b, struct timespec *ret)
1763 ret->tv_sec = a->tv_sec - b->tv_sec;
1764 ret->tv_nsec = a->tv_nsec - b->tv_nsec;
1765 if (ret->tv_nsec < 0) {
1766 ret->tv_sec--;
1767 ret->tv_nsec += 1000000000L;
1770 #endif /* !HAVE_TIMESPECSUB */