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