]>
Commit | Line | Data |
---|---|---|
c441a31a | 1 | /* $Id$ |
7189310c | 2 | * |
7ac48069 | 3 | * Display function for userreg client |
4 | * | |
5 | * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. | |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
989a2c2c | 8 | */ |
9 | ||
7189310c | 10 | #include <mit-copyright.h> |
7ac48069 | 11 | #include <moira.h> |
12 | ||
207dc170 | 13 | #include <sys/time.h> |
14 | ||
989a2c2c | 15 | #include <curses.h> |
7ac48069 | 16 | #include <stdio.h> |
17 | #include <time.h> | |
18 | #include <unistd.h> | |
19 | ||
989a2c2c | 20 | #include "userreg.h" |
21 | ||
7ac48069 | 22 | RCSID("$Header$"); |
23 | ||
24 | void make_border(int l); | |
25 | void query_user(char *prompt, char *buf, int maxsize, int timeout, | |
26 | int echop, int emptyok, int valuep); | |
27 | ||
989a2c2c | 28 | #define DESC_WIDTH 18 |
a2b4a2ee | 29 | #define HEADER "*** Athena User Account Registration ***" |
a2b4a2ee | 30 | #define HELP " Press backspace to delete a character. Press Ctrl-C to start over." |
989a2c2c | 31 | #define BORDER_CHAR '-' |
32 | #define MIN_COLS 80 | |
33 | #define MIN_LINES 24 | |
34 | ||
7ac48069 | 35 | WINDOW *displayw, *queryw; |
36 | WINDOW *dataw, *helpw; | |
37 | WINDOW *fnamew, *midw, *lnamew, *idw, *loginw; | |
7ff930df | 38 | extern char typed_mit_id[100]; |
989a2c2c | 39 | |
40 | /* Set up the windows and subwindows on the display */ | |
7ac48069 | 41 | void setup_display(void) |
5eaef520 | 42 | { |
5eaef520 | 43 | initscr(); /* Start up curses */ |
989a2c2c | 44 | |
5eaef520 | 45 | if (COLS < MIN_COLS || LINES < MIN_LINES) |
46 | { | |
47 | fprintf(stderr, "Screen must be at least %d x %d\n", | |
48 | MIN_LINES, MIN_COLS); | |
49 | exit(1); | |
50 | } | |
94464a85 | 51 | |
5eaef520 | 52 | noecho(); /* And the tty input */ |
53 | raw(); | |
54 | freopen("/dev/null", "w", stderr);/* Toss the standard error output */ | |
989a2c2c | 55 | |
5eaef520 | 56 | /* Make sure the place is clean */ |
57 | clear(); | |
989a2c2c | 58 | |
5eaef520 | 59 | /* Set up the top-level windows */ |
60 | /* First line is the header */ | |
61 | displayw = subwin(stdscr, 12, 0, 2, 0);/* Lines 2-13 */ | |
62 | scrollok(displayw, TRUE); | |
989a2c2c | 63 | |
5eaef520 | 64 | queryw = subwin(stdscr, 1, 0, 15, 0);/* Line 15 */ |
65 | scrollok(queryw, TRUE); | |
989a2c2c | 66 | |
5eaef520 | 67 | dataw = subwin(stdscr, 5, 0, 17, 0);/* Lines 17-21 */ |
989a2c2c | 68 | |
5eaef520 | 69 | /* Set up the data windows */ |
70 | fnamew = subwin(stdscr, 1, 0, 17, DESC_WIDTH); | |
71 | midw = subwin(stdscr, 1, 0, 18, DESC_WIDTH); | |
72 | lnamew = subwin(stdscr, 1, 0, 19, DESC_WIDTH); | |
73 | idw = subwin(stdscr, 1, 0, 20, DESC_WIDTH); | |
74 | loginw = subwin(stdscr, 1, 0, 21, DESC_WIDTH); | |
989a2c2c | 75 | } |
76 | ||
77 | /* Clear and restore the display */ | |
7ac48069 | 78 | void reset_display(void) |
5eaef520 | 79 | { |
80 | clear(); | |
81 | ||
82 | /* Put back the borders */ | |
83 | make_border(1); | |
84 | make_border(14); | |
85 | make_border(16); | |
86 | make_border(22); | |
87 | ||
88 | /* Put in the window dressing */ | |
89 | wmove(dataw, 0, 0); | |
90 | waddstr(dataw, "First Name:\n"); | |
91 | waddstr(dataw, "Middle Initial:\n"); | |
92 | waddstr(dataw, "Family Name:\n"); | |
93 | waddstr(dataw, "MIT ID #:\n\n"); | |
94 | waddstr(dataw, "Username:\n"); | |
95 | wclrtoeol(dataw); | |
96 | ||
97 | /* Set up the header */ | |
98 | mvaddstr(0, (COLS - strlen (HEADER)) / 2, HEADER); | |
99 | mvaddstr(23, 0, HELP); | |
100 | ||
101 | /* Put it all up */ | |
102 | refresh(); | |
989a2c2c | 103 | } |
104 | ||
105 | ||
106 | /* Make a one-line border on line l of stdscr */ | |
7ac48069 | 107 | void make_border(int l) |
989a2c2c | 108 | { |
5eaef520 | 109 | int i; |
989a2c2c | 110 | |
5eaef520 | 111 | move(l, 0); |
112 | for(i = 0; i < COLS - 1; i++) | |
113 | addch(BORDER_CHAR); | |
989a2c2c | 114 | } |
115 | ||
116 | /* This replaces several "useful" display functions in the old userreg */ | |
7ac48069 | 117 | void redisp(void) |
5eaef520 | 118 | { |
119 | mvwprintw(fnamew, 0, 0, "%-24s", user.u_first); | |
e6b3a349 | 120 | wrefresh(fnamew); |
5eaef520 | 121 | mvwprintw(midw, 0, 0, "%-24s", user.u_mid_init); |
e6b3a349 | 122 | wrefresh(midw); |
5eaef520 | 123 | mvwprintw(lnamew, 0, 0, "%-24s", user.u_last); |
e6b3a349 | 124 | wrefresh(lnamew); |
5eaef520 | 125 | mvwprintw(idw, 0, 0, "%-24s", typed_mit_id); |
e6b3a349 | 126 | wrefresh(idw); |
5eaef520 | 127 | mvwprintw(loginw, 0, 0, "%-24s", user.u_login); |
e6b3a349 | 128 | wrefresh(loginw); |
989a2c2c | 129 | } |
130 | ||
131 | ||
132 | /* Input and input_no_echo exist only to save on retyping */ | |
7ac48069 | 133 | void input(char *prompt, char *buf, int maxsize, int timeout, int emptyok) |
989a2c2c | 134 | { |
5eaef520 | 135 | query_user(prompt, buf, maxsize, timeout, TRUE, emptyok, TRUE); |
989a2c2c | 136 | } |
137 | ||
7ac48069 | 138 | void input_no_echo(char *prompt, char *buf, int maxsize, int timeout) |
989a2c2c | 139 | { |
5eaef520 | 140 | query_user(prompt, buf, maxsize, timeout, FALSE, FALSE, TRUE); |
989a2c2c | 141 | } |
142 | ||
143 | ||
4127ae1e | 144 | /* make the user press any key to continue */ |
7ac48069 | 145 | void wait_for_user(void) |
4127ae1e | 146 | { |
5eaef520 | 147 | char buf[BUFSIZ]; |
4127ae1e | 148 | |
5eaef520 | 149 | redisp(); |
150 | query_user("Press RETURN or ENTER to continue", buf, 1, | |
151 | 15 * 60, FALSE, TRUE, FALSE); | |
4127ae1e | 152 | } |
153 | ||
989a2c2c | 154 | |
155 | /* Gets input through the query buffer */ | |
156 | /* Exit(1)'s on read errors */ | |
157 | /* Signals SIGALRM after 'timeout' seconds */ | |
7ac48069 | 158 | void query_user(char *prompt, char *buf, int maxsize, int timeout, |
159 | int echop, int emptyok, int valuep) | |
989a2c2c | 160 | { |
5eaef520 | 161 | int c; |
162 | int i; | |
989a2c2c | 163 | struct itimerval it; |
164 | ||
165 | retry: | |
166 | /* Set up interval timer */ | |
167 | it.it_interval.tv_sec = 0; | |
168 | it.it_interval.tv_usec = 0; | |
169 | it.it_value.tv_sec = timeout; | |
170 | it.it_value.tv_usec = 0; | |
5eaef520 | 171 | setitimer(ITIMER_REAL, &it, NULL); |
989a2c2c | 172 | |
173 | /* Erase the query window and put up a prompt */ | |
5eaef520 | 174 | werase(queryw); |
175 | mvwaddstr(queryw, 0, 0, prompt); | |
176 | waddch(queryw, ' '); /* Put in a space, as Blox does */ | |
177 | wrefresh(queryw); | |
989a2c2c | 178 | |
179 | i = 0; | |
5eaef520 | 180 | while ((c = getchar()) != '\r' && c != '\n') |
181 | { | |
182 | switch (c) | |
183 | { | |
184 | case '\025': /* Ctl-U */ | |
185 | goto retry; | |
186 | case EOF: | |
187 | /* We're in raw mode, so EOF means disaster */ | |
188 | exit(1); | |
189 | break; | |
190 | delchar: | |
191 | case '\177': /* Delete */ | |
192 | case '\010': /* Backspace */ | |
193 | if (i) | |
194 | { | |
195 | i--; | |
196 | if (echop) | |
197 | { | |
198 | int x, y; | |
199 | getyx(queryw, y, x); | |
200 | wmove(queryw, y, x - 1); | |
201 | wclrtoeol(queryw); | |
202 | wrefresh(queryw); | |
203 | } | |
204 | } | |
205 | break; | |
206 | case '\003': /* Ctrl-C */ | |
207 | clear(); | |
208 | restore_display(); | |
209 | exit(0); | |
210 | break; | |
211 | default: | |
212 | if (c >= ' ') /* Ignore all other control chars */ | |
213 | { | |
214 | buf[i++] = c; | |
215 | if (echop) | |
216 | { | |
217 | waddch(queryw, c); | |
218 | wrefresh(queryw); | |
219 | } | |
220 | } | |
221 | break; | |
989a2c2c | 222 | } |
5eaef520 | 223 | if (valuep && i >= maxsize) |
224 | { | |
225 | wfeep(); | |
226 | wprintw(displayw, "You are not allowed to type more than %d " | |
227 | "characters for this answer.\n", maxsize - 1); | |
228 | wrefresh(displayw); | |
229 | goto delchar; | |
989a2c2c | 230 | } |
989a2c2c | 231 | } |
989a2c2c | 232 | |
5eaef520 | 233 | if (i == 0) |
234 | { | |
4127ae1e | 235 | if (emptyok && valuep && |
236 | (askyn("Do you really want this field left blank (y/n)? ") == NO)) | |
237 | goto retry; | |
5eaef520 | 238 | if (!emptyok) |
239 | { | |
4127ae1e | 240 | wprintw(displayw, "You must enter something here.\n"); |
241 | wrefresh(displayw); | |
242 | goto retry; | |
5eaef520 | 243 | } |
244 | } | |
245 | ||
989a2c2c | 246 | |
247 | /* Input is complete so disable interval timer. */ | |
248 | it.it_interval.tv_sec = 0; | |
249 | it.it_interval.tv_usec = 0; | |
250 | it.it_value.tv_sec = 0; | |
251 | it.it_value.tv_usec = 0; | |
5eaef520 | 252 | setitimer(ITIMER_REAL, &it, NULL); |
989a2c2c | 253 | |
254 | buf[i] = '\0'; /* Put a null on the end */ | |
255 | ||
5eaef520 | 256 | werase(queryw); /* Clean up the query window */ |
257 | wrefresh(queryw); | |
989a2c2c | 258 | |
259 | return; /* And get out of here. */ | |
260 | } | |
261 | ||
5eaef520 | 262 | int askyn(char *prompt) |
989a2c2c | 263 | { |
264 | int ypos, xpos; | |
265 | int answer; | |
266 | struct itimerval it; | |
8b2d95d4 | 267 | int c; |
989a2c2c | 268 | |
5eaef520 | 269 | start: |
270 | werase(queryw); | |
271 | mvwaddstr(queryw, 0, 0, prompt); | |
272 | wrefresh(queryw); | |
989a2c2c | 273 | |
7ff930df | 274 | getyx(queryw, ypos, xpos); |
989a2c2c | 275 | answer = 2; /* No answer. */ |
5eaef520 | 276 | |
989a2c2c | 277 | /* Reset interval timer for y/n question. */ |
278 | it.it_interval.tv_sec = 0; | |
279 | it.it_interval.tv_usec = 0; | |
280 | it.it_value.tv_sec = YN_TIMEOUT; | |
281 | it.it_value.tv_usec = 0; | |
5eaef520 | 282 | setitimer(ITIMER_REAL, &it, NULL); |
283 | ||
284 | while ((c = getchar ()) != '\r' && c != '\n') /* Wait for CR. */ | |
285 | { | |
286 | switch (c) | |
287 | { | |
288 | case 'n': /* No. */ | |
289 | case 'N': | |
290 | wmove(queryw, ypos, xpos); | |
291 | wclrtoeol(queryw); | |
292 | waddstr(queryw, "no"); | |
293 | wrefresh(queryw); | |
294 | answer = NO; | |
295 | continue; | |
296 | case 'y': /* Yes. */ | |
297 | case 'Y': | |
298 | wmove(queryw, ypos, xpos); | |
299 | wclrtoeol(queryw); | |
300 | waddstr(queryw, "yes"); | |
301 | wrefresh(queryw); | |
302 | answer = YES; | |
303 | continue; | |
304 | case '\177': /* Delete */ | |
305 | case '\010': /* Backspace */ | |
306 | case '\025': /* Ctl-U */ | |
307 | wmove(queryw, ypos, xpos); | |
308 | wclrtoeol(queryw); | |
309 | wrefresh(queryw); | |
310 | answer = 2; /* No answer. */ | |
311 | break; | |
312 | case EOF: | |
313 | /* We're in raw mode, so EOF means disaster */ | |
314 | exit(1); | |
315 | break; | |
316 | case '\003': /* Ctrl-C */ | |
317 | clear(); | |
318 | restore_display(); | |
319 | exit(0); | |
320 | break; | |
321 | default: /* Ignore everything else. */ | |
322 | break; | |
323 | } | |
989a2c2c | 324 | } |
325 | ||
326 | if (answer == 2) /* No answer. */ | |
5eaef520 | 327 | { |
328 | display_text_line(0); | |
989a2c2c | 329 | display_text_line("Please answer y or n."); |
330 | goto start; | |
331 | } | |
5eaef520 | 332 | |
333 | return answer; | |
989a2c2c | 334 | } |
335 | ||
336 | /* Display_text_line puts up a line of text in the display window */ | |
337 | /* Special case: if line is 0, clear the display area */ | |
7ac48069 | 338 | void display_text_line(char *line) |
989a2c2c | 339 | { |
5eaef520 | 340 | if (line) |
341 | { | |
342 | waddstr(displayw, line); | |
343 | waddch(displayw, '\n'); | |
344 | } | |
345 | else | |
346 | werase(displayw); | |
347 | wrefresh(displayw); | |
989a2c2c | 348 | } |
349 | ||
a2b4a2ee | 350 | /* Display_text displays a canned message from a file. The string |
351 | * will get imbedded in any %s's in the text. | |
352 | */ | |
7ac48069 | 353 | void display_text(char *filename, char *string) |
989a2c2c | 354 | { |
355 | FILE * fp; | |
5eaef520 | 356 | char buf[100], buf1[110]; |
989a2c2c | 357 | |
5eaef520 | 358 | werase(displayw); |
359 | if (!(fp = fopen (filename, "r"))) | |
360 | { | |
361 | wprintw (displayw, "Can't open file %s for reading.\n", filename); | |
362 | return; | |
363 | } | |
989a2c2c | 364 | |
5eaef520 | 365 | while (fgets (buf, 100, fp)) |
366 | { | |
a2b4a2ee | 367 | /* get rid of the newline */ |
5eaef520 | 368 | buf[strlen(buf) - 1] = '\0'; |
a2b4a2ee | 369 | sprintf(buf1, buf, string); |
370 | waddstr(displayw, buf1); | |
371 | waddch(displayw, '\n'); | |
5eaef520 | 372 | } |
989a2c2c | 373 | |
a2b4a2ee | 374 | wrefresh(displayw); |
5eaef520 | 375 | fclose(fp); |
989a2c2c | 376 | } |
377 | ||
378 | /* Clear_display wipes the display and turns off curses */ | |
7ac48069 | 379 | void restore_display(void) |
989a2c2c | 380 | { |
381 | clear(); | |
382 | refresh(); | |
383 | noraw(); | |
384 | echo(); | |
385 | endwin(); | |
386 | } | |
387 | ||
7ac48069 | 388 | void timer_on(void) |
989a2c2c | 389 | { |
390 | struct itimerval it; | |
391 | ||
392 | it.it_interval.tv_sec = 0; | |
393 | it.it_interval.tv_usec = 0; | |
394 | it.it_value.tv_sec = TIMER_TIMEOUT; | |
395 | it.it_value.tv_usec = 0; | |
5eaef520 | 396 | setitimer(ITIMER_REAL, &it, NULL); |
989a2c2c | 397 | } |
398 | ||
7ac48069 | 399 | void timer_off(void) |
989a2c2c | 400 | { |
401 | struct itimerval it; | |
402 | ||
403 | it.it_interval.tv_sec = 0; | |
404 | it.it_interval.tv_usec = 0; | |
405 | it.it_value.tv_sec = 0; | |
406 | it.it_value.tv_usec = 0; | |
5eaef520 | 407 | setitimer(ITIMER_REAL, &it, NULL); |
989a2c2c | 408 | } |
409 | ||
4127ae1e | 410 | |
7ac48069 | 411 | void wfeep(void) |
4127ae1e | 412 | { |
5eaef520 | 413 | char buf = '\007'; |
414 | write(1, &buf, 1); | |
4127ae1e | 415 | } |