Annotation of src/usr.bin/tmux/server-fn.c, Revision 1.20
1.20 ! nicm 1: /* $OpenBSD: server-fn.c,v 1.19 2009/09/12 13:01:19 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.9 nicm 236: password_failures++;
1.18 nicm 237: password_backoff = 0;
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) {
1.18 nicm 263: password_backoff =
264: server_activity + ((failures - backoff) * tries / 2);
1.17 nicm 265: return (-2);
266: }
1.1 nicm 267: return (-1);
1.8 nicm 268: }
269:
270: void
271: server_kill_window(struct window *w)
272: {
273: struct session *s;
274: struct winlink *wl;
1.19 nicm 275: u_int i;
1.8 nicm 276:
277: for (i = 0; i < ARRAY_LENGTH(&sessions); i++) {
278: s = ARRAY_ITEM(&sessions, i);
279: if (s == NULL || !session_has(s, w))
280: continue;
281: if ((wl = winlink_find_by_window(&s->windows, w)) == NULL)
282: continue;
283:
1.19 nicm 284: if (session_detach(s, wl))
285: server_destroy_session(s);
286: else
287: server_redraw_session(s);
1.8 nicm 288: }
289: recalculate_sizes();
1.19 nicm 290: }
291:
292: void
293: server_destroy_session(struct session *s)
294: {
295: struct client *c;
296: u_int i;
297:
298: for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
299: c = ARRAY_ITEM(&clients, i);
300: if (c == NULL || c->session != s)
301: continue;
302: c->session = NULL;
303: server_write_client(c, MSG_EXIT, NULL, 0);
304: }
1.15 nicm 305: }
306:
307: void
308: server_set_identify(struct client *c)
309: {
310: struct timeval tv;
311: int delay;
312:
313: delay = options_get_number(&c->session->options, "display-panes-time");
314: tv.tv_sec = delay / 1000;
315: tv.tv_usec = (delay % 1000) * 1000L;
316:
317: if (gettimeofday(&c->identify_timer, NULL) != 0)
1.20 ! nicm 318: fatal("gettimeofday failed");
1.15 nicm 319: timeradd(&c->identify_timer, &tv, &c->identify_timer);
320:
321: c->flags |= CLIENT_IDENTIFY;
322: c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
323: server_redraw_client(c);
324: }
325:
326: void
327: server_clear_identify(struct client *c)
328: {
329: if (c->flags & CLIENT_IDENTIFY) {
330: c->flags &= ~CLIENT_IDENTIFY;
331: c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
332: server_redraw_client(c);
333: }
1.1 nicm 334: }