Annotation of src/usr.bin/tmux/server-fn.c, Revision 1.17
1.17 ! nicm 1: /* $OpenBSD: server-fn.c,v 1.16 2009/09/01 09:11:05 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:
1.17 ! nicm 21: #include <login_cap.h>
! 22: #include <pwd.h>
1.1 nicm 23: #include <string.h>
1.5 nicm 24: #include <time.h>
1.1 nicm 25: #include <unistd.h>
26:
27: #include "tmux.h"
28:
29: int server_lock_callback(void *, const char *);
30:
1.13 nicm 31: void
32: server_fill_environ(struct session *s, struct environ *env)
1.1 nicm 33: {
1.13 nicm 34: char tmuxvar[MAXPATHLEN], *term;
35: u_int idx;
1.1 nicm 36:
37: if (session_index(s, &idx) != 0)
38: fatalx("session not found");
39: xsnprintf(tmuxvar, sizeof tmuxvar,
1.13 nicm 40: "%s,%ld,%u", socket_path, (long) getpid(), idx);
41: environ_set(env, "TMUX", tmuxvar);
1.1 nicm 42:
1.13 nicm 43: term = options_get_string(&s->options, "default-terminal");
44: environ_set(env, "TERM", term);
1.1 nicm 45: }
46:
47: void
1.10 nicm 48: server_write_error(struct client *c, const char *msg)
49: {
50: struct msg_print_data printdata;
51:
52: strlcpy(printdata.msg, msg, sizeof printdata.msg);
53: server_write_client(c, MSG_ERROR, &printdata, sizeof printdata);
54: }
55:
56: void
1.1 nicm 57: server_write_client(
1.11 nicm 58: struct client *c, enum msgtype type, const void *buf, size_t len)
1.1 nicm 59: {
1.14 nicm 60: struct imsgbuf *ibuf = &c->ibuf;
1.1 nicm 61:
1.12 nicm 62: if (c->flags & CLIENT_BAD)
63: return;
1.14 nicm 64: log_debug("writing %d to client %d", type, c->ibuf.fd);
65: imsg_compose(ibuf, type, PROTOCOL_VERSION, -1, -1, (void *) buf, len);
1.1 nicm 66: }
67:
68: void
69: server_write_session(
1.11 nicm 70: struct session *s, enum msgtype type, const void *buf, size_t len)
1.1 nicm 71: {
72: struct client *c;
73: u_int i;
74:
75: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
76: c = ARRAY_ITEM(&clients, i);
77: if (c == NULL || c->session == NULL)
78: continue;
79: if (c->session == s)
80: server_write_client(c, type, buf, len);
81: }
82: }
83:
84: void
85: server_redraw_client(struct client *c)
86: {
87: c->flags |= CLIENT_REDRAW;
88: }
89:
90: void
91: server_status_client(struct client *c)
92: {
93: c->flags |= CLIENT_STATUS;
94: }
95:
96: void
97: server_redraw_session(struct session *s)
98: {
99: struct client *c;
100: u_int i;
101:
102: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
103: c = ARRAY_ITEM(&clients, i);
104: if (c == NULL || c->session == NULL)
105: continue;
106: if (c->session == s)
107: server_redraw_client(c);
108: }
109: }
110:
111: void
112: server_status_session(struct session *s)
113: {
114: struct client *c;
115: u_int i;
116:
117: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
118: c = ARRAY_ITEM(&clients, i);
119: if (c == NULL || c->session == NULL)
120: continue;
121: if (c->session == s)
122: server_status_client(c);
123: }
124: }
125:
126: void
127: server_redraw_window(struct window *w)
128: {
129: struct client *c;
130: u_int i;
131:
132: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
133: c = ARRAY_ITEM(&clients, i);
134: if (c == NULL || c->session == NULL)
135: continue;
136: if (c->session->curw->window == w)
137: server_redraw_client(c);
138: }
139: w->flags |= WINDOW_REDRAW;
140: }
141:
142: void
143: server_status_window(struct window *w)
144: {
145: struct session *s;
146: u_int i;
147:
148: /*
149: * This is slightly different. We want to redraw the status line of any
150: * clients containing this window rather than any where it is the
151: * current window.
152: */
153:
154: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
155: s = ARRAY_ITEM(&sessions, i);
156: if (s != NULL && session_has(s, w))
157: server_status_session(s);
158: }
159: }
160:
161: void
162: server_lock(void)
163: {
1.17 ! nicm 164: struct client *c;
! 165: static struct passwd *pw, pwstore;
! 166: static char pwbuf[_PW_BUF_LEN];
! 167: u_int i;
1.1 nicm 168:
169: if (server_locked)
170: return;
171:
1.17 ! nicm 172: if (getpwuid_r(getuid(), &pwstore, pwbuf, sizeof pwbuf, &pw) != 0) {
! 173: server_locked_pw = NULL;
! 174: return;
! 175: }
! 176: server_locked_pw = pw;
! 177:
1.1 nicm 178: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
179: c = ARRAY_ITEM(&clients, i);
180: if (c == NULL || c->session == NULL)
181: continue;
182:
183: status_prompt_clear(c);
1.6 nicm 184: status_prompt_set(c,
1.16 nicm 185: "Password:", server_lock_callback, NULL, c, PROMPT_HIDDEN);
1.1 nicm 186: server_redraw_client(c);
187: }
1.17 ! nicm 188:
1.1 nicm 189: server_locked = 1;
190: }
191:
192: int
193: server_lock_callback(unused void *data, const char *s)
194: {
195: return (server_unlock(s));
196: }
197:
198: int
199: server_unlock(const char *s)
200: {
201: struct client *c;
1.17 ! nicm 202: login_cap_t *lc;
1.1 nicm 203: u_int i;
204: char *out;
1.17 ! nicm 205: u_int failures, tries, backoff;
1.1 nicm 206:
1.17 ! nicm 207: if (!server_locked || server_locked_pw == NULL)
1.1 nicm 208: return (0);
209: server_activity = time(NULL);
1.17 ! nicm 210: if (server_activity < password_backoff)
! 211: return (-2);
1.1 nicm 212:
213: if (server_password != NULL) {
214: if (s == NULL)
215: return (-1);
216: out = crypt(s, server_password);
217: if (strcmp(out, server_password) != 0)
218: goto wrong;
219: }
220:
221: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
222: c = ARRAY_ITEM(&clients, i);
223: if (c == NULL)
224: continue;
225:
226: status_prompt_clear(c);
227: server_redraw_client(c);
228: }
229:
230: server_locked = 0;
1.9 nicm 231: password_failures = 0;
1.17 ! nicm 232: password_backoff = 0;
1.1 nicm 233: return (0);
234:
235: wrong:
1.17 ! nicm 236: password_backoff = server_activity;
1.9 nicm 237: password_failures++;
1.17 ! nicm 238:
1.1 nicm 239: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
240: c = ARRAY_ITEM(&clients, i);
1.10 nicm 241: if (c == NULL || c->prompt_buffer == NULL)
1.1 nicm 242: continue;
243:
244: *c->prompt_buffer = '\0';
245: c->prompt_index = 0;
1.9 nicm 246: server_redraw_client(c);
1.1 nicm 247: }
248:
1.17 ! nicm 249: /*
! 250: * Start slowing down after "login-backoff" attempts and reset every
! 251: * "login-tries" attempts.
! 252: */
! 253: lc = login_getclass(server_locked_pw->pw_class);
! 254: if (lc != NULL) {
! 255: tries = login_getcapnum(lc, (char *) "login-tries", 10, 10);
! 256: backoff = login_getcapnum(lc, (char *) "login-backoff", 3, 3);
! 257: } else {
! 258: tries = 10;
! 259: backoff = 3;
! 260: }
! 261: failures = password_failures % tries;
! 262: if (failures > backoff) {
! 263: password_backoff += ((failures - backoff) * tries / 2);
! 264: return (-2);
! 265: }
1.1 nicm 266: return (-1);
1.8 nicm 267: }
268:
269: void
270: server_kill_window(struct window *w)
271: {
272: struct session *s;
273: struct winlink *wl;
274: struct client *c;
275: u_int i, j;
276: int destroyed;
277:
278:
279: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
280: s = ARRAY_ITEM(&sessions, i);
281: if (s == NULL || !session_has(s, w))
282: continue;
283: if ((wl = winlink_find_by_window(&s->windows, w)) == NULL)
284: continue;
285:
286: destroyed = session_detach(s, wl);
287: for (j = 0; j < ARRAY_LENGTH(&clients); j++) {
288: c = ARRAY_ITEM(&clients, j);
289: if (c == NULL || c->session != s)
290: continue;
291:
292: if (destroyed) {
293: c->session = NULL;
294: server_write_client(c, MSG_EXIT, NULL, 0);
295: } else
296: server_redraw_client(c);
297: }
298: }
299: recalculate_sizes();
1.15 nicm 300: }
301:
302: void
303: server_set_identify(struct client *c)
304: {
305: struct timeval tv;
306: int delay;
307:
308: delay = options_get_number(&c->session->options, "display-panes-time");
309: tv.tv_sec = delay / 1000;
310: tv.tv_usec = (delay % 1000) * 1000L;
311:
312: if (gettimeofday(&c->identify_timer, NULL) != 0)
313: fatal("gettimeofday");
314: timeradd(&c->identify_timer, &tv, &c->identify_timer);
315:
316: c->flags |= CLIENT_IDENTIFY;
317: c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
318: server_redraw_client(c);
319: }
320:
321: void
322: server_clear_identify(struct client *c)
323: {
324: if (c->flags & CLIENT_IDENTIFY) {
325: c->flags &= ~CLIENT_IDENTIFY;
326: c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
327: server_redraw_client(c);
328: }
1.1 nicm 329: }