[BACK]Return to catman.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/catman.c, Revision 1.13

1.13    ! schwarze    1: /*     $Id$ */
1.1       kristaps    2: /*
1.13    ! schwarze    3:  * Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
        !             4:  * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
1.1       kristaps    5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
1.13    ! schwarze   10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1.1       kristaps   11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1.13    ! schwarze   12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1.1       kristaps   13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18: #include "config.h"
                     19:
1.13    ! schwarze   20: #include <sys/types.h>
        !            21: #include <sys/socket.h>
1.1       kristaps   22: #include <sys/stat.h>
                     23:
1.13    ! schwarze   24: #if HAVE_ERR
        !            25: #include <err.h>
        !            26: #endif
1.1       kristaps   27: #include <fcntl.h>
1.13    ! schwarze   28: #if HAVE_FTS
        !            29: #include <fts.h>
        !            30: #else
        !            31: #include "compat_fts.h"
        !            32: #endif
1.1       kristaps   33: #include <stdio.h>
                     34: #include <stdlib.h>
                     35: #include <string.h>
                     36: #include <unistd.h>
                     37:
1.13    ! schwarze   38: int     process_manpage(int, int, const char *);
        !            39: int     process_tree(int, int);
        !            40: void    run_mandocd(int, const char *) __attribute__((noreturn));
        !            41: ssize_t         sock_fd_write(int, int, int, int);
        !            42: void    usage(void) __attribute__((noreturn));
        !            43:
        !            44:
        !            45: void
        !            46: run_mandocd(int sockfd, const char *outtype)
        !            47: {
        !            48:        char     sockfdstr[10];
        !            49:
        !            50:        if (snprintf(sockfdstr, sizeof(sockfdstr), "%d", sockfd) == -1)
        !            51:                err(1, "snprintf");
        !            52:        execlp("mandocd", "mandocd", "-T", outtype, sockfdstr, NULL);
        !            53:        err(1, "exec");
        !            54: }
        !            55:
        !            56: ssize_t
        !            57: sock_fd_write(int fd, int fd0, int fd1, int fd2)
        !            58: {
        !            59:        struct msghdr    msg;
        !            60:        struct iovec     iov;
        !            61:        union {
        !            62:                struct cmsghdr   cmsghdr;
        !            63:                char             control[CMSG_SPACE(3 * sizeof(int))];
        !            64:        } cmsgu;
        !            65:        struct cmsghdr  *cmsg;
        !            66:        int             *walk;
        !            67:        unsigned char    dummy[1] = {'\0'};
        !            68:
        !            69:        iov.iov_base = dummy;
        !            70:        iov.iov_len = sizeof(dummy);
        !            71:
        !            72:        msg.msg_name = NULL;
        !            73:        msg.msg_namelen = 0;
        !            74:        msg.msg_iov = &iov;
        !            75:        msg.msg_iovlen = 1;
        !            76:
        !            77:        msg.msg_control = cmsgu.control;
        !            78:        msg.msg_controllen = sizeof(cmsgu.control);
        !            79:
        !            80:        cmsg = CMSG_FIRSTHDR(&msg);
        !            81:        cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
        !            82:        cmsg->cmsg_level = SOL_SOCKET;
        !            83:        cmsg->cmsg_type = SCM_RIGHTS;
        !            84:
        !            85:        walk = (int *)CMSG_DATA(cmsg);
        !            86:        *(walk++) = fd0;
        !            87:        *(walk++) = fd1;
        !            88:        *(walk++) = fd2;
1.1       kristaps   89:
1.13    ! schwarze   90:        return sendmsg(fd, &msg, 0);
        !            91: }
1.1       kristaps   92:
                     93: int
1.13    ! schwarze   94: process_manpage(int srv_fd, int dstdir_fd, const char *path)
1.1       kristaps   95: {
1.13    ! schwarze   96:        int      in_fd, out_fd;
1.1       kristaps   97:
1.13    ! schwarze   98:        if ((in_fd = open(path, O_RDONLY)) == -1) {
        !            99:                warn("open(%s)", path);
        !           100:                return -1;
        !           101:        }
1.1       kristaps  102:
1.13    ! schwarze  103:        if ((out_fd = openat(dstdir_fd, path,
        !           104:            O_WRONLY | O_NOFOLLOW | O_CREAT | O_TRUNC,
        !           105:            S_IRUSR | S_IWUSR | S_IRGRP | S_IRWXO)) == -1) {
        !           106:                warn("openat(%s)", path);
        !           107:                close(in_fd);
        !           108:                return -1;
1.1       kristaps  109:        }
                    110:
1.13    ! schwarze  111:        if (sock_fd_write(srv_fd, in_fd, out_fd, STDERR_FILENO) < 0) {
        !           112:                warn("sendmsg");
        !           113:                return -1;
        !           114:        }
1.1       kristaps  115:
1.13    ! schwarze  116:        close(in_fd);
        !           117:        close(out_fd);
        !           118:        return 0;
1.1       kristaps  119: }
                    120:
1.13    ! schwarze  121: int
        !           122: process_tree(int srv_fd, int dstdir_fd)
1.1       kristaps  123: {
1.13    ! schwarze  124:        FTS             *ftsp;
        !           125:        FTSENT          *entry;
        !           126:        const char      *argv[2];
        !           127:        const char      *path;
1.1       kristaps  128:
1.13    ! schwarze  129:        argv[0] = ".";
        !           130:        argv[1] = (char *)NULL;
1.1       kristaps  131:
1.13    ! schwarze  132:        if ((ftsp = fts_open((char * const *)argv,
        !           133:            FTS_PHYSICAL | FTS_NOCHDIR, NULL)) == NULL) {
        !           134:                warn("fts_open");
        !           135:                return -1;
        !           136:        }
        !           137:
        !           138:        while ((entry = fts_read(ftsp)) != NULL) {
        !           139:                path = entry->fts_path + 2;
        !           140:                switch (entry->fts_info) {
        !           141:                case FTS_F:
        !           142:                        process_manpage(srv_fd, dstdir_fd, path);
        !           143:                        break;
        !           144:                case FTS_D:
        !           145:                case FTS_DP:
        !           146:                        break;
        !           147:                default:
        !           148:                        warnx("%s: not a regular file", path);
        !           149:                        break;
1.1       kristaps  150:                }
1.13    ! schwarze  151:        }
1.1       kristaps  152:
1.13    ! schwarze  153:        fts_close(ftsp);
        !           154:        return 0;
1.1       kristaps  155: }
                    156:
1.13    ! schwarze  157: int
        !           158: main(int argc, char **argv)
1.1       kristaps  159: {
1.13    ! schwarze  160:        const char      *outtype;
        !           161:        int              srv_fds[2];
        !           162:        int              dstdir_fd;
        !           163:        int              opt;
1.1       kristaps  164:        pid_t            pid;
                    165:
1.13    ! schwarze  166:        outtype = "ascii";
        !           167:        while ((opt = getopt(argc, argv, "T:")) != -1) {
        !           168:                switch (opt) {
        !           169:                case 'T':
        !           170:                        outtype = optarg;
1.1       kristaps  171:                        break;
1.13    ! schwarze  172:                default:
        !           173:                        usage();
1.1       kristaps  174:                }
1.13    ! schwarze  175:        }
1.1       kristaps  176:
1.13    ! schwarze  177:        if (argc > 0) {
        !           178:                argc -= optind;
        !           179:                argv += optind;
1.1       kristaps  180:        }
1.13    ! schwarze  181:        if (argc != 2)
        !           182:                usage();
1.1       kristaps  183:
1.13    ! schwarze  184:        if (socketpair(AF_LOCAL, SOCK_STREAM, AF_UNSPEC, srv_fds) == -1)
        !           185:                err(1, "socketpair");
1.1       kristaps  186:
1.13    ! schwarze  187:        pid = fork();
        !           188:        switch (pid) {
        !           189:        case -1:
        !           190:                err(1, "fork");
        !           191:        case 0:
        !           192:                close(srv_fds[0]);
        !           193:                run_mandocd(srv_fds[1], outtype);
        !           194:        default:
        !           195:                break;
1.1       kristaps  196:        }
1.13    ! schwarze  197:        close(srv_fds[1]);
1.1       kristaps  198:
1.13    ! schwarze  199:        if ((dstdir_fd = open(argv[1], O_RDONLY | O_DIRECTORY)) == -1)
        !           200:                err(1, "open(%s)", argv[1]);
1.1       kristaps  201:
1.13    ! schwarze  202:        if (chdir(argv[0]) == -1)
        !           203:                err(1, "chdir(%s)", argv[0]);
1.1       kristaps  204:
1.13    ! schwarze  205:        return process_tree(srv_fds[0], dstdir_fd) == -1 ? 1 : 0;
1.1       kristaps  206: }
                    207:
1.13    ! schwarze  208: void
        !           209: usage(void)
1.1       kristaps  210: {
1.13    ! schwarze  211:        fprintf(stderr, "usage: catman [-T output] srcdir dstdir\n");
        !           212:        exit(1);
1.1       kristaps  213: }

CVSweb