Annotation of embedaddon/tmux/osdep-freebsd.c, revision 1.1.1.1

1.1       misho       1: /* $OpenBSD$ */
                      2: 
                      3: /*
                      4:  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
                      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:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18: 
                     19: #include <sys/param.h>
                     20: #include <sys/proc.h>
                     21: #include <sys/stat.h>
                     22: #include <sys/sysctl.h>
                     23: #include <sys/user.h>
                     24: 
                     25: #include <err.h>
                     26: #include <errno.h>
                     27: #include <event.h>
                     28: #include <stdint.h>
                     29: #include <stdlib.h>
                     30: #include <string.h>
                     31: #include <unistd.h>
                     32: #include <libutil.h>
                     33: 
                     34: struct kinfo_proc      *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
                     35: char                   *osdep_get_name(int, char *);
                     36: char                   *osdep_get_cwd(int);
                     37: struct event_base      *osdep_event_init(void);
                     38: 
                     39: #ifndef nitems
                     40: #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
                     41: #endif
                     42: 
                     43: #define is_runnable(p) \
                     44:        ((p)->ki_stat == SRUN || (p)->ki_stat == SIDL)
                     45: #define is_stopped(p) \
                     46:        ((p)->ki_stat == SSTOP || (p)->ki_stat == SZOMB)
                     47: 
                     48: struct kinfo_proc *
                     49: cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
                     50: {
                     51:        if (is_runnable(p1) && !is_runnable(p2))
                     52:                return (p1);
                     53:        if (!is_runnable(p1) && is_runnable(p2))
                     54:                return (p2);
                     55: 
                     56:        if (is_stopped(p1) && !is_stopped(p2))
                     57:                return (p1);
                     58:        if (!is_stopped(p1) && is_stopped(p2))
                     59:                return (p2);
                     60: 
                     61:        if (p1->ki_estcpu > p2->ki_estcpu)
                     62:                return (p1);
                     63:        if (p1->ki_estcpu < p2->ki_estcpu)
                     64:                return (p2);
                     65: 
                     66:        if (p1->ki_slptime < p2->ki_slptime)
                     67:                return (p1);
                     68:        if (p1->ki_slptime > p2->ki_slptime)
                     69:                return (p2);
                     70: 
                     71:        if (strcmp(p1->ki_comm, p2->ki_comm) < 0)
                     72:                return (p1);
                     73:        if (strcmp(p1->ki_comm, p2->ki_comm) > 0)
                     74:                return (p2);
                     75: 
                     76:        if (p1->ki_pid > p2->ki_pid)
                     77:                return (p1);
                     78:        return (p2);
                     79: }
                     80: 
                     81: char *
                     82: osdep_get_name(int fd, char *tty)
                     83: {
                     84:        int              mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PGRP, 0 };
                     85:        struct stat      sb;
                     86:        size_t           len;
                     87:        struct kinfo_proc *buf, *newbuf, *bestp;
                     88:        u_int            i;
                     89:        char            *name;
                     90: 
                     91:        buf = NULL;
                     92: 
                     93:        if (stat(tty, &sb) == -1)
                     94:                return (NULL);
                     95:        if ((mib[3] = tcgetpgrp(fd)) == -1)
                     96:                return (NULL);
                     97: 
                     98: retry:
                     99:        if (sysctl(mib, nitems(mib), NULL, &len, NULL, 0) == -1)
                    100:                return (NULL);
                    101:        len = (len * 5) / 4;
                    102: 
                    103:        if ((newbuf = realloc(buf, len)) == NULL)
                    104:                goto error;
                    105:        buf = newbuf;
                    106: 
                    107:        if (sysctl(mib, nitems(mib), buf, &len, NULL, 0) == -1) {
                    108:                if (errno == ENOMEM)
                    109:                        goto retry;
                    110:                goto error;
                    111:        }
                    112: 
                    113:        bestp = NULL;
                    114:        for (i = 0; i < len / sizeof (struct kinfo_proc); i++) {
                    115:                if (buf[i].ki_tdev != sb.st_rdev)
                    116:                        continue;
                    117:                if (bestp == NULL)
                    118:                        bestp = &buf[i];
                    119:                else
                    120:                        bestp = cmp_procs(&buf[i], bestp);
                    121:        }
                    122: 
                    123:        name = NULL;
                    124:        if (bestp != NULL)
                    125:                name = strdup(bestp->ki_comm);
                    126: 
                    127:        free(buf);
                    128:        return (name);
                    129: 
                    130: error:
                    131:        free(buf);
                    132:        return (NULL);
                    133: }
                    134: 
                    135: static char *
                    136: osdep_get_cwd_fallback(int fd)
                    137: {
                    138:        static char              wd[PATH_MAX];
                    139:        struct kinfo_file       *info = NULL;
                    140:        pid_t                    pgrp;
                    141:        int                      nrecords, i;
                    142: 
                    143:        if ((pgrp = tcgetpgrp(fd)) == -1)
                    144:                return (NULL);
                    145: 
                    146:        if ((info = kinfo_getfile(pgrp, &nrecords)) == NULL)
                    147:                return (NULL);
                    148: 
                    149:        for (i = 0; i < nrecords; i++) {
                    150:                if (info[i].kf_fd == KF_FD_TYPE_CWD) {
                    151:                        strlcpy(wd, info[i].kf_path, sizeof wd);
                    152:                        free(info);
                    153:                        return (wd);
                    154:                }
                    155:        }
                    156: 
                    157:        free(info);
                    158:        return (NULL);
                    159: }
                    160: 
                    161: #ifdef KERN_PROC_CWD
                    162: char *
                    163: osdep_get_cwd(int fd)
                    164: {
                    165:        static struct kinfo_file        info;
                    166:        static int                      fallback;
                    167:        int     name[] = { CTL_KERN, KERN_PROC, KERN_PROC_CWD, 0 };
                    168:        size_t  len = sizeof info;
                    169: 
                    170:        if (fallback)
                    171:                return (osdep_get_cwd_fallback(fd));
                    172: 
                    173:        if ((name[3] = tcgetpgrp(fd)) == -1)
                    174:                return (NULL);
                    175: 
                    176:        if (sysctl(name, 4, &info, &len, NULL, 0) == -1) {
                    177:                if (errno == ENOENT) {
                    178:                        fallback = 1;
                    179:                        return (osdep_get_cwd_fallback(fd));
                    180:                }
                    181:                return (NULL);
                    182:        }
                    183:        return (info.kf_path);
                    184: }
                    185: #else /* !KERN_PROC_CWD */
                    186: char *
                    187: osdep_get_cwd(int fd)
                    188: {
                    189:        return (osdep_get_cwd_fallback(fd));
                    190: }
                    191: #endif /* KERN_PROC_CWD */
                    192: 
                    193: struct event_base *
                    194: osdep_event_init(void)
                    195: {
                    196:        /*
                    197:         * On some versions of FreeBSD, kqueue doesn't work properly on tty
                    198:         * file descriptors. This is fixed in recent FreeBSD versions.
                    199:         */
                    200:        setenv("EVENT_NOKQUEUE", "1", 1);
                    201:        return (event_init());
                    202: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>