[BACK]Return to server.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/server.c, Revision 1.64

1.64    ! nicm        1: /* $OpenBSD: server.c,v 1.63 2009/10/27 13:03:33 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
                      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/types.h>
                     20: #include <sys/ioctl.h>
                     21: #include <sys/socket.h>
                     22: #include <sys/stat.h>
                     23: #include <sys/un.h>
                     24: #include <sys/wait.h>
                     25:
                     26: #include <errno.h>
                     27: #include <fcntl.h>
1.5       nicm       28: #include <paths.h>
1.1       nicm       29: #include <signal.h>
                     30: #include <stdio.h>
                     31: #include <stdlib.h>
                     32: #include <string.h>
                     33: #include <syslog.h>
                     34: #include <termios.h>
                     35: #include <time.h>
                     36: #include <unistd.h>
                     37:
                     38: #include "tmux.h"
                     39:
                     40: /*
                     41:  * Main server functions.
                     42:  */
                     43:
                     44: /* Client list. */
                     45: struct clients  clients;
1.31      nicm       46: struct clients  dead_clients;
1.1       nicm       47:
1.45      nicm       48: /* Mapping of a pollfd to an fd independent of its position in the array. */
                     49: struct poll_item {
1.60      nicm       50:        int      fd;
                     51:        int      events;
                     52:
                     53:        void     (*fn)(int, int, void *);
                     54:        void    *data;
1.45      nicm       55:
                     56:        RB_ENTRY(poll_item) entry;
                     57: };
                     58: RB_HEAD(poll_items, poll_item) poll_items;
                     59:
                     60: int             server_poll_cmp(struct poll_item *, struct poll_item *);
1.60      nicm       61: struct poll_item*server_poll_lookup(int);
1.45      nicm       62: struct pollfd  *server_poll_flatten(int *);
1.60      nicm       63: void            server_poll_dispatch(struct pollfd *, int);
1.45      nicm       64: void            server_poll_reset(void);
                     65: RB_PROTOTYPE(poll_items, poll_item, entry, server_poll_cmp);
                     66: RB_GENERATE(poll_items, poll_item, entry, server_poll_cmp);
                     67:
1.1       nicm       68: int             server_create_socket(void);
1.60      nicm       69: void            server_callback(int, int, void *);
1.1       nicm       70: int             server_main(int);
                     71: void            server_shutdown(void);
1.42      nicm       72: int             server_should_shutdown(void);
1.1       nicm       73: void            server_child_signal(void);
1.31      nicm       74: void            server_clean_dead(void);
1.60      nicm       75: void            server_second_timers(void);
1.46      nicm       76: void            server_lock_server(void);
                     77: void            server_lock_sessions(void);
1.1       nicm       78: int             server_update_socket(void);
                     79:
1.45      nicm       80: int
                     81: server_poll_cmp(struct poll_item *pitem1, struct poll_item *pitem2)
                     82: {
1.60      nicm       83:        return (pitem1->fd - pitem2->fd);
1.45      nicm       84: }
                     85:
1.60      nicm       86: void
                     87: server_poll_add(int fd, int events, void (*fn)(int, int, void *), void *data)
1.45      nicm       88: {
1.60      nicm       89:        struct poll_item        *pitem;
                     90:
                     91:        pitem = xmalloc(sizeof *pitem);
                     92:        pitem->fd = fd;
                     93:        pitem->events = events;
                     94:
                     95:        pitem->fn = fn;
                     96:        pitem->data = data;
1.45      nicm       97:
1.60      nicm       98:        RB_INSERT(poll_items, &poll_items, pitem);
1.45      nicm       99: }
                    100:
1.60      nicm      101: struct poll_item *
                    102: server_poll_lookup(int fd)
1.45      nicm      103: {
1.60      nicm      104:        struct poll_item        pitem;
1.45      nicm      105:
1.60      nicm      106:        pitem.fd = fd;
                    107:        return (RB_FIND(poll_items, &poll_items, &pitem));
1.45      nicm      108: }
                    109:
                    110: struct pollfd *
                    111: server_poll_flatten(int *nfds)
                    112: {
                    113:        struct poll_item        *pitem;
                    114:        struct pollfd           *pfds;
                    115:
                    116:        pfds = NULL;
                    117:        *nfds = 0;
                    118:        RB_FOREACH(pitem, poll_items, &poll_items) {
                    119:                pfds = xrealloc(pfds, (*nfds) + 1, sizeof *pfds);
1.60      nicm      120:                pfds[*nfds].fd = pitem->fd;
                    121:                pfds[*nfds].events = pitem->events;
1.45      nicm      122:                (*nfds)++;
                    123:        }
                    124:        return (pfds);
                    125: }
                    126:
                    127: void
1.60      nicm      128: server_poll_dispatch(struct pollfd *pfds, int nfds)
1.45      nicm      129: {
                    130:        struct poll_item        *pitem;
1.60      nicm      131:        struct pollfd           *pfd;
1.45      nicm      132:
1.60      nicm      133:        while (nfds > 0) {
                    134:                pfd = &pfds[--nfds];
                    135:                if (pfd->revents != 0) {
                    136:                        pitem = server_poll_lookup(pfd->fd);
                    137:                        pitem->fn(pitem->fd, pfd->revents, pitem->data);
                    138:                }
1.45      nicm      139:        }
                    140:        xfree(pfds);
                    141: }
                    142:
                    143: void
                    144: server_poll_reset(void)
                    145: {
                    146:        struct poll_item        *pitem;
                    147:
                    148:        while (!RB_EMPTY(&poll_items)) {
                    149:                pitem = RB_ROOT(&poll_items);
                    150:                RB_REMOVE(poll_items, &poll_items, pitem);
                    151:                xfree(pitem);
                    152:        }
                    153: }
                    154:
1.60      nicm      155: /* Create server socket. */
                    156: int
                    157: server_create_socket(void)
1.1       nicm      158: {
1.60      nicm      159:        struct sockaddr_un      sa;
                    160:        size_t                  size;
                    161:        mode_t                  mask;
                    162:        int                     fd, mode;
                    163:
                    164:        memset(&sa, 0, sizeof sa);
                    165:        sa.sun_family = AF_UNIX;
                    166:        size = strlcpy(sa.sun_path, socket_path, sizeof sa.sun_path);
                    167:        if (size >= sizeof sa.sun_path) {
                    168:                errno = ENAMETOOLONG;
                    169:                fatal("socket failed");
                    170:        }
                    171:        unlink(sa.sun_path);
                    172:
                    173:        if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
                    174:                fatal("socket failed");
                    175:
                    176:        mask = umask(S_IXUSR|S_IRWXG|S_IRWXO);
                    177:        if (bind(fd, (struct sockaddr *) &sa, SUN_LEN(&sa)) == -1)
                    178:                fatal("bind failed");
                    179:        umask(mask);
                    180:
                    181:        if (listen(fd, 16) == -1)
                    182:                fatal("listen failed");
1.1       nicm      183:
                    184:        if ((mode = fcntl(fd, F_GETFL)) == -1)
                    185:                fatal("fcntl failed");
                    186:        if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1)
                    187:                fatal("fcntl failed");
                    188:        if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
                    189:                fatal("fcntl failed");
                    190:
1.60      nicm      191:        return (fd);
                    192: }
                    193:
                    194: /* Callback for server socket. */
                    195: void
                    196: server_callback(int fd, int events, unused void *data)
                    197: {
                    198:        struct sockaddr_storage sa;
                    199:        socklen_t               slen = sizeof sa;
                    200:        int                     newfd;
                    201:
                    202:        if (events & (POLLERR|POLLNVAL|POLLHUP))
                    203:                fatalx("lost server socket");
                    204:        if (!(events & POLLIN))
                    205:                return;
1.1       nicm      206:
1.60      nicm      207:        newfd = accept(fd, (struct sockaddr *) &sa, &slen);
                    208:        if (newfd == -1) {
                    209:                if (errno == EAGAIN || errno == EINTR || errno == ECONNABORTED)
1.13      nicm      210:                        return;
1.60      nicm      211:                fatal("accept failed");
                    212:        }
                    213:        if (sigterm) {
                    214:                close(newfd);
                    215:                return;
1.1       nicm      216:        }
1.60      nicm      217:        server_client_create(newfd);
1.1       nicm      218: }
                    219:
                    220: /* Fork new server. */
                    221: int
                    222: server_start(char *path)
                    223: {
1.16      nicm      224:        struct client   *c;
                    225:        int              pair[2], srv_fd;
                    226:        char            *cause;
                    227:        char             rpathbuf[MAXPATHLEN];
1.1       nicm      228:
                    229:        /* The first client is special and gets a socketpair; create it. */
                    230:        if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
                    231:                fatal("socketpair failed");
                    232:
                    233:        switch (fork()) {
                    234:        case -1:
                    235:                fatal("fork failed");
                    236:        case 0:
                    237:                break;
                    238:        default:
                    239:                close(pair[1]);
                    240:                return (pair[0]);
                    241:        }
                    242:        close(pair[0]);
                    243:
                    244:        /*
                    245:         * Must daemonise before loading configuration as the PID changes so
                    246:         * $TMUX would be wrong for sessions created in the config file.
                    247:         */
1.16      nicm      248:        if (daemon(1, 0) != 0)
1.1       nicm      249:                fatal("daemon failed");
                    250:
1.16      nicm      251:        logfile("server");
                    252:        log_debug("server started, pid %ld", (long) getpid());
                    253:
1.1       nicm      254:        ARRAY_INIT(&windows);
                    255:        ARRAY_INIT(&clients);
1.31      nicm      256:        ARRAY_INIT(&dead_clients);
1.1       nicm      257:        ARRAY_INIT(&sessions);
1.31      nicm      258:        ARRAY_INIT(&dead_sessions);
1.47      nicm      259:        TAILQ_INIT(&session_groups);
1.15      nicm      260:        mode_key_init_trees();
1.1       nicm      261:        key_bindings_init();
                    262:        utf8_build();
                    263:
                    264:        start_time = time(NULL);
                    265:        socket_path = path;
                    266:
1.16      nicm      267:        if (realpath(socket_path, rpathbuf) == NULL)
                    268:                strlcpy(rpathbuf, socket_path, sizeof rpathbuf);
                    269:        log_debug("socket path %s", socket_path);
                    270:        setproctitle("server (%s)", rpathbuf);
                    271:
                    272:        srv_fd = server_create_socket();
1.60      nicm      273:        server_client_create(pair[1]);
1.16      nicm      274:
1.64    ! nicm      275:        if (access(SYSTEM_CFG, R_OK) == 0) {
        !           276:                if (load_cfg(SYSTEM_CFG, NULL, &cause) != 0)
1.16      nicm      277:                        goto error;
1.64    ! nicm      278:        } else if (errno != ENOENT) {
        !           279:                xasprintf(&cause, "%s: %s", strerror(errno), SYSTEM_CFG);
1.16      nicm      280:                goto error;
1.64    ! nicm      281:        }
1.24      nicm      282:        if (cfg_file != NULL && load_cfg(cfg_file, NULL, &cause) != 0)
1.16      nicm      283:                goto error;
1.5       nicm      284:
1.16      nicm      285:        exit(server_main(srv_fd));
1.1       nicm      286:
1.16      nicm      287: error:
                    288:        /* Write the error and shutdown the server. */
                    289:        c = ARRAY_FIRST(&clients);
1.1       nicm      290:
1.16      nicm      291:        server_write_error(c, cause);
                    292:        xfree(cause);
1.1       nicm      293:
1.27      nicm      294:        sigterm = 1;
1.16      nicm      295:        server_shutdown();
1.1       nicm      296:
                    297:        exit(server_main(srv_fd));
                    298: }
                    299:
                    300: /* Main server loop. */
                    301: int
                    302: server_main(int srv_fd)
                    303: {
1.60      nicm      304:        struct pollfd   *pfds;
1.1       nicm      305:        int              nfds, xtimeout;
1.42      nicm      306:        u_int            i;
1.1       nicm      307:        time_t           now, last;
                    308:
                    309:        siginit();
1.20      nicm      310:        log_debug("server socket is %d", srv_fd);
1.1       nicm      311:
                    312:        last = time(NULL);
                    313:
                    314:        pfds = NULL;
                    315:        for (;;) {
                    316:                /* If sigterm, kill all windows and clients. */
                    317:                if (sigterm)
                    318:                        server_shutdown();
                    319:
1.42      nicm      320:                /* Stop if no sessions or clients left. */
                    321:                if (server_should_shutdown())
                    322:                        break;
                    323:
1.1       nicm      324:                /* Handle child exit. */
                    325:                if (sigchld) {
1.61      nicm      326:                        sigchld = 0;
1.1       nicm      327:                        server_child_signal();
1.61      nicm      328:                        continue;
1.1       nicm      329:                }
                    330:
                    331:                /* Recreate socket on SIGUSR1. */
                    332:                if (sigusr1) {
1.61      nicm      333:                        sigusr1 = 0;
1.1       nicm      334:                        close(srv_fd);
                    335:                        srv_fd = server_create_socket();
1.61      nicm      336:                        continue;
1.1       nicm      337:                }
                    338:
1.45      nicm      339:                /* Initialise pollfd array and add server socket. */
                    340:                server_poll_reset();
1.60      nicm      341:                server_poll_add(srv_fd, POLLIN, server_callback, NULL);
1.1       nicm      342:
                    343:                /* Fill window and client sockets. */
1.63      nicm      344:                server_job_prepare();
                    345:                server_window_prepare();
                    346:                server_client_prepare();
                    347:
1.1       nicm      348:                /* Update socket permissions. */
                    349:                xtimeout = INFTIM;
1.27      nicm      350:                if (server_update_socket() != 0)
1.1       nicm      351:                        xtimeout = POLL_TIMEOUT;
                    352:
                    353:                /* Do the poll. */
1.45      nicm      354:                pfds = server_poll_flatten(&nfds);
1.4       nicm      355:                if (poll(pfds, nfds, xtimeout) == -1) {
1.1       nicm      356:                        if (errno == EAGAIN || errno == EINTR)
                    357:                                continue;
                    358:                        fatal("poll failed");
                    359:                }
1.60      nicm      360:                server_poll_dispatch(pfds, nfds);
1.1       nicm      361:
                    362:                /* Call second-based timers. */
                    363:                now = time(NULL);
                    364:                if (now != last) {
                    365:                        last = now;
                    366:                        server_second_timers();
                    367:                }
                    368:
1.60      nicm      369:                /* Run once-per-loop events. */
                    370:                server_job_loop();
                    371:                server_window_loop();
                    372:                server_client_loop();
1.1       nicm      373:
1.8       nicm      374:                /* Collect any unset key bindings. */
                    375:                key_bindings_clean();
1.31      nicm      376:
                    377:                /* Collect dead clients and sessions. */
                    378:                server_clean_dead();
1.1       nicm      379:        }
1.45      nicm      380:        server_poll_reset();
1.1       nicm      381:
                    382:        for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
                    383:                if (ARRAY_ITEM(&sessions, i) != NULL)
                    384:                        session_destroy(ARRAY_ITEM(&sessions, i));
                    385:        }
                    386:        ARRAY_FREE(&sessions);
                    387:
                    388:        for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
                    389:                if (ARRAY_ITEM(&clients, i) != NULL)
1.60      nicm      390:                        server_client_lost(ARRAY_ITEM(&clients, i));
1.1       nicm      391:        }
                    392:        ARRAY_FREE(&clients);
                    393:
1.15      nicm      394:        mode_key_free_trees();
1.1       nicm      395:        key_bindings_free();
                    396:
                    397:        close(srv_fd);
                    398:
                    399:        unlink(socket_path);
                    400:        xfree(socket_path);
                    401:
1.6       nicm      402:        options_free(&global_s_options);
                    403:        options_free(&global_w_options);
1.1       nicm      404:
                    405:        return (0);
                    406: }
                    407:
                    408: /* Kill all clients. */
                    409: void
                    410: server_shutdown(void)
                    411: {
                    412:        struct session  *s;
                    413:        struct client   *c;
                    414:        u_int            i, j;
                    415:
1.42      nicm      416:        for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
                    417:                c = ARRAY_ITEM(&clients, i);
                    418:                if (c != NULL) {
                    419:                        if (c->flags & (CLIENT_BAD|CLIENT_SUSPENDED))
1.60      nicm      420:                                server_client_lost(c);
1.42      nicm      421:                        else
                    422:                                server_write_client(c, MSG_SHUTDOWN, NULL, 0);
                    423:                }
                    424:        }
                    425:
1.1       nicm      426:        for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
                    427:                s = ARRAY_ITEM(&sessions, i);
                    428:                for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
                    429:                        c = ARRAY_ITEM(&clients, j);
                    430:                        if (c != NULL && c->session == s) {
                    431:                                s = NULL;
                    432:                                break;
                    433:                        }
                    434:                }
                    435:                if (s != NULL)
                    436:                        session_destroy(s);
                    437:        }
1.42      nicm      438: }
                    439:
                    440: /* Check if the server should be shutting down (no more clients or windows). */
                    441: int
                    442: server_should_shutdown(void)
                    443: {
                    444:        u_int   i;
1.1       nicm      445:
1.42      nicm      446:        for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
                    447:                if (ARRAY_ITEM(&sessions, i) != NULL)
                    448:                        return (0);
                    449:        }
1.1       nicm      450:        for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
1.42      nicm      451:                if (ARRAY_ITEM(&clients, i) != NULL)
                    452:                        return (0);
1.1       nicm      453:        }
1.42      nicm      454:        return (1);
1.1       nicm      455: }
                    456:
                    457: /* Handle SIGCHLD. */
                    458: void
                    459: server_child_signal(void)
                    460: {
                    461:        struct window           *w;
                    462:        struct window_pane      *wp;
1.53      nicm      463:        struct job              *job;
1.1       nicm      464:        int                      status;
                    465:        pid_t                    pid;
                    466:        u_int                    i;
                    467:
                    468:        for (;;) {
                    469:                switch (pid = waitpid(WAIT_ANY, &status, WNOHANG|WUNTRACED)) {
                    470:                case -1:
                    471:                        if (errno == ECHILD)
                    472:                                return;
1.39      nicm      473:                        fatal("waitpid failed");
1.1       nicm      474:                case 0:
                    475:                        return;
                    476:                }
1.53      nicm      477:                if (!WIFSTOPPED(status)) {
                    478:                        SLIST_FOREACH(job, &all_jobs, lentry) {
                    479:                                if (pid == job->pid) {
                    480:                                        job->pid = -1;
                    481:                                        job->status = status;
                    482:                                }
                    483:                        }
1.1       nicm      484:                        continue;
1.53      nicm      485:                }
1.1       nicm      486:                if (WSTOPSIG(status) == SIGTTIN || WSTOPSIG(status) == SIGTTOU)
                    487:                        continue;
                    488:
                    489:                for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
                    490:                        w = ARRAY_ITEM(&windows, i);
                    491:                        if (w == NULL)
                    492:                                continue;
                    493:                        TAILQ_FOREACH(wp, &w->panes, entry) {
                    494:                                if (wp->pid == pid) {
                    495:                                        if (killpg(pid, SIGCONT) != 0)
                    496:                                                kill(pid, SIGCONT);
                    497:                                }
                    498:                        }
                    499:                }
1.53      nicm      500:        }
                    501: }
                    502:
1.31      nicm      503: /* Free dead, unreferenced clients and sessions. */
                    504: void
                    505: server_clean_dead(void)
                    506: {
                    507:        struct session  *s;
                    508:        struct client   *c;
                    509:        u_int            i;
                    510:
                    511:        for (i = 0; i < ARRAY_LENGTH(&dead_sessions); i++) {
                    512:                s = ARRAY_ITEM(&dead_sessions, i);
                    513:                if (s == NULL || s->references != 0)
                    514:                        continue;
                    515:                ARRAY_SET(&dead_sessions, i, NULL);
                    516:                xfree(s);
                    517:        }
                    518:
                    519:        for (i = 0; i < ARRAY_LENGTH(&dead_clients); i++) {
                    520:                c = ARRAY_ITEM(&dead_clients, i);
                    521:                if (c == NULL || c->references != 0)
                    522:                        continue;
                    523:                ARRAY_SET(&dead_clients, i, NULL);
                    524:                xfree(c);
                    525:        }
1.1       nicm      526: }
                    527:
1.60      nicm      528: /* Call any once-per-second timers. */
1.1       nicm      529: void
1.60      nicm      530: server_second_timers(void)
1.1       nicm      531: {
1.60      nicm      532:        struct window           *w;
                    533:        struct window_pane      *wp;
1.35      nicm      534:        u_int                    i;
1.1       nicm      535:
1.60      nicm      536:        if (options_get_number(&global_s_options, "lock-server"))
                    537:                server_lock_server();
                    538:        else
                    539:                server_lock_sessions();
1.1       nicm      540:
1.60      nicm      541:        for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
                    542:                w = ARRAY_ITEM(&windows, i);
                    543:                if (w == NULL)
1.1       nicm      544:                        continue;
                    545:
1.60      nicm      546:                TAILQ_FOREACH(wp, &w->panes, entry) {
                    547:                        if (wp->mode != NULL && wp->mode->timer != NULL)
                    548:                                wp->mode->timer(wp);
1.1       nicm      549:                }
                    550:        }
                    551: }
                    552:
1.46      nicm      553: /* Lock the server if ALL sessions have hit the time limit. */
                    554: void
                    555: server_lock_server(void)
                    556: {
                    557:        struct session  *s;
                    558:        u_int            i;
                    559:        int              timeout;
                    560:        time_t           t;
                    561:
                    562:        t = time(NULL);
                    563:        for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
                    564:                if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
                    565:                        continue;
                    566:
1.59      nicm      567:                if (s->flags & SESSION_UNATTACHED) {
                    568:                        s->activity = time(NULL);
                    569:                        continue;
                    570:                }
                    571:
1.46      nicm      572:                timeout = options_get_number(&s->options, "lock-after-time");
                    573:                if (timeout <= 0 || t <= s->activity + timeout)
                    574:                        return; /* not timed out */
                    575:        }
                    576:
                    577:        server_lock();
                    578:        recalculate_sizes();
                    579: }
                    580:
                    581: /* Lock any sessions which have timed out. */
                    582: void
                    583: server_lock_sessions(void)
                    584: {
                    585:         struct session  *s;
1.62      deraadt   586:        u_int            i;
1.46      nicm      587:        int              timeout;
1.62      deraadt   588:        time_t           t;
1.46      nicm      589:
1.62      deraadt   590:        t = time(NULL);
                    591:        for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
1.46      nicm      592:                if ((s = ARRAY_ITEM(&sessions, i)) == NULL)
                    593:                        continue;
1.59      nicm      594:
                    595:                if (s->flags & SESSION_UNATTACHED) {
                    596:                        s->activity = time(NULL);
                    597:                        continue;
                    598:                }
1.46      nicm      599:
                    600:                timeout = options_get_number(&s->options, "lock-after-time");
                    601:                if (timeout > 0 && t > s->activity + timeout) {
                    602:                        server_lock_session(s);
                    603:                        recalculate_sizes();
1.1       nicm      604:                }
                    605:        }
                    606: }
                    607:
                    608: /* Update socket execute permissions based on whether sessions are attached. */
                    609: int
                    610: server_update_socket(void)
                    611: {
                    612:        struct session  *s;
                    613:        u_int            i;
                    614:        static int       last = -1;
                    615:        int              n;
                    616:
                    617:        n = 0;
                    618:        for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
                    619:                s = ARRAY_ITEM(&sessions, i);
                    620:                if (s != NULL && !(s->flags & SESSION_UNATTACHED)) {
                    621:                        n++;
                    622:                        break;
                    623:                }
                    624:        }
                    625:
                    626:        if (n != last) {
                    627:                last = n;
                    628:                if (n != 0)
                    629:                        chmod(socket_path, S_IRWXU);
                    630:                else
                    631:                        chmod(socket_path, S_IRUSR|S_IWUSR);
                    632:        }
                    633:
                    634:        return (n);
                    635: }