1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last program in the `sysinstall' line - the next
5  * generation being essentially a complete rewrite.
6  *
7  * $FreeBSD: stable/9/usr.sbin/sysinstall/msg.c 211417 2010-08-17 09:39:06Z brucec $
8  *
9  * Copyright (c) 1995
10  *	Jordan Hubbard.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer,
17  *    verbatim and that no modifications are made prior to this
18  *    point in the file.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36 
37 #include <sys/ioctl.h>
38 #include <sys/consio.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 
42 #include <netinet/in.h>
43 #include <netdb.h>
44 
45 #include <stdarg.h>
46 #include <syslog.h>
47 
48 #include "sysinstall.h"
49 
50 Boolean
isDebug(void)51 isDebug(void)
52 {
53     char *cp;
54 
55     return (cp = variable_get(VAR_DEBUG)) && strcmp(cp, "no");
56 }
57 
58 static Boolean
isNetworkUp(void)59 isNetworkUp(void)
60 {
61 	if (!(RunningAsInit) ||
62 	    (variable_check("NETWORK_CONFIGURED=NO")) != TRUE) {
63 	    return TRUE;
64 	}
65 
66 	return FALSE;
67 }
68 
69 void
msgSyslog(const char * errstr)70 msgSyslog(const char *errstr)
71 {
72 	struct sockaddr_in server;
73 	struct hostent *hp;
74 	char *host, *line;
75 	int sock;
76 
77 	if (!isNetworkUp())
78 	    return;
79 
80 	if (!(host = variable_get(VAR_SYSLOG_SERVER)))
81 	    return;
82 
83 	if (!(hp = gethostbyname2(host, AF_INET)))
84 	    return;
85 
86 	if (!(sock = socket(AF_INET, SOCK_DGRAM, 0)))
87 	    return;
88 
89 	bzero(&server, sizeof(struct sockaddr_in));
90 	server.sin_family = AF_INET;
91 	server.sin_port = htons(514);
92 	bcopy((char *)hp->h_addr, (char *)&server.sin_addr, hp->h_length);
93 
94 	asprintf(&line, "<%d>%s", LOG_NOTICE, errstr);
95 	sendto(sock, line, strlen(line), 0, (struct sockaddr *)&server,
96 	    sizeof(struct sockaddr_in));
97 
98 	close(sock);
99 	free(line);
100 }
101 
102 /* Whack up an informational message on the status line, in stand-out */
103 void
msgYap(char * fmt,...)104 msgYap(char *fmt, ...)
105 {
106     va_list args;
107     char *errstr;
108     int attrs;
109 
110     errstr = (char *)alloca(FILENAME_MAX);
111     va_start(args, fmt);
112     vsnprintf(errstr, FILENAME_MAX, fmt, args);
113     va_end(args);
114     attrs = getattrs(stdscr);
115     attrset(A_REVERSE);
116     mvaddstr(StatusLine, 0, errstr);
117     attrset(attrs);
118     refresh();
119 }
120 
121 /* Whack up an informational message on the status line */
122 void
msgInfo(char * fmt,...)123 msgInfo(char *fmt, ...)
124 {
125     va_list args;
126     char *errstr;
127     int i, attrs;
128     char line[81];
129 
130     attrs = getattrs(stdscr);
131     /* NULL is a special convention meaning "erase the old stuff" */
132     if (!fmt) {
133 	move(StatusLine, 0);
134 	clrtoeol();
135 	return;
136     }
137     errstr = (char *)alloca(FILENAME_MAX);
138     va_start(args, fmt);
139     vsnprintf(errstr, FILENAME_MAX, fmt, args);
140     va_end(args);
141     memset(line, ' ', 80);
142     for (i = 0; i < 80; i++) {
143 	if (errstr[i])
144 	    line[i] = errstr[i];
145 	else
146 	    break;
147     }
148     line[80] = '\0';
149     attrset(ATTR_TITLE);
150     mvaddstr(StatusLine, 0, line);
151     attrset(attrs);
152     move(StatusLine, 79);
153     refresh();
154 
155     msgSyslog(errstr);
156 }
157 
158 /* Whack up a warning on the status line */
159 void
msgWarn(char * fmt,...)160 msgWarn(char *fmt, ...)
161 {
162     va_list args;
163     char *errstr;
164     int attrs;
165 
166     errstr = (char *)alloca(FILENAME_MAX);
167     strcpy(errstr, "Warning: ");
168     va_start(args, fmt);
169     vsnprintf((char *)(errstr + strlen(errstr)), FILENAME_MAX, fmt, args);
170     va_end(args);
171     attrs = getattrs(stdscr);
172     beep();
173     attrset(ATTR_TITLE);
174     mvaddstr(StatusLine, 0, errstr);
175     attrset(attrs);
176     refresh();
177 
178     /* we don't want this hitting syslog twice */
179     if (isDebug()) {
180 	if (OnVTY)
181 		msgDebug("Warning message `%s'\n", errstr);
182 	else
183 		msgSyslog(errstr);
184     }
185 
186 }
187 
188 /* Whack up an error on the status line */
189 void
msgError(char * fmt,...)190 msgError(char *fmt, ...)
191 {
192     va_list args;
193     char *errstr;
194     int attrs;
195 
196     errstr = (char *)alloca(FILENAME_MAX);
197     strcpy(errstr, "Error: ");
198     va_start(args, fmt);
199     vsnprintf((char *)(errstr + strlen(errstr)), FILENAME_MAX, fmt, args);
200     va_end(args);
201     beep();
202     attrs = getattrs(stdscr);
203     attrset(ATTR_TITLE);
204     mvaddstr(StatusLine, 0, errstr);
205     attrset(attrs);
206     refresh();
207 
208     /* we don't want this hitting syslog twice */
209     if (isDebug()) {
210 	if (OnVTY)
211 		msgDebug("Error message `%s'\n", errstr);
212 	else
213 		msgSyslog(errstr);
214     }
215 }
216 
217 /* Whack up a fatal error on the status line */
218 void
msgFatal(char * fmt,...)219 msgFatal(char *fmt, ...)
220 {
221     va_list args;
222     char *errstr;
223     int attrs;
224 
225     errstr = (char *)alloca(FILENAME_MAX);
226     strcpy(errstr, "Fatal Error: ");
227     va_start(args, fmt);
228     vsnprintf((char *)(errstr + strlen(errstr)), FILENAME_MAX, fmt, args);
229     va_end(args);
230     beep();
231     attrs = getattrs(stdscr);
232     attrset(ATTR_TITLE);
233     mvaddstr(StatusLine, 0, errstr);
234     addstr(" - ");
235     addstr("PRESS ANY KEY TO ");
236     if (RunningAsInit)
237 	addstr("REBOOT");
238     else
239 	addstr("QUIT");
240     attrset(attrs);
241     refresh();
242     if (OnVTY)
243 	msgDebug("Fatal error `%s'!\n", errstr);
244     else
245     	msgSyslog(errstr);
246     getch();
247     systemShutdown(1);
248 }
249 
250 /* Put up a message in a popup confirmation box */
251 void
msgConfirm(char * fmt,...)252 msgConfirm(char *fmt, ...)
253 {
254     va_list args;
255     char *errstr;
256     WINDOW *w = savescr();
257 
258     errstr = (char *)alloca(FILENAME_MAX);
259     va_start(args, fmt);
260     vsnprintf(errstr, FILENAME_MAX, fmt, args);
261     va_end(args);
262     use_helpline(NULL);
263     use_helpfile(NULL);
264     if (OnVTY) {
265 	ioctl(0, VT_ACTIVATE, 1);
266 	msgInfo(NULL);
267     }
268     dialog_notify(errstr);
269     restorescr(w);
270 }
271 
272 /* Put up a message in a popup information box */
273 void
msgNotify(char * fmt,...)274 msgNotify(char *fmt, ...)
275 {
276     va_list args;
277     char *errstr;
278 
279     errstr = (char *)alloca(FILENAME_MAX);
280     va_start(args, fmt);
281     vsnprintf(errstr, FILENAME_MAX, fmt, args);
282     va_end(args);
283     use_helpline(NULL);
284     use_helpfile(NULL);
285     if (isDebug())
286 	msgDebug("Notify: %s\n", errstr);
287     dialog_msgbox(NULL, errstr, -1, -1, 0);
288 }
289 
290 /* Put up a message in a popup yes/no box and return 0 for YES, 1 for NO */
291 int
msgYesNo(char * fmt,...)292 msgYesNo(char *fmt, ...)
293 {
294     va_list args;
295     char *errstr;
296     int ret;
297     WINDOW *w = savescr();
298 
299     errstr = (char *)alloca(FILENAME_MAX);
300     va_start(args, fmt);
301     vsnprintf(errstr, FILENAME_MAX, fmt, args);
302     va_end(args);
303     use_helpline(NULL);
304     use_helpfile(NULL);
305     if (OnVTY) {
306 	ioctl(0, VT_ACTIVATE, 1);	/* Switch back */
307 	msgInfo(NULL);
308     }
309     if (variable_get(VAR_NONINTERACTIVE))
310 	return 0;	/* If non-interactive, return YES all the time */
311     ret = dialog_yesno("User Confirmation Requested", errstr, -1, -1);
312     restorescr(w);
313     return ret;
314 }
315 
316 /* Put up a message in a popup no/yes box and return 0 for YES, 1 for NO */
317 int
msgNoYes(char * fmt,...)318 msgNoYes(char *fmt, ...)
319 {
320     va_list args;
321     char *errstr;
322     int ret;
323     WINDOW *w = savescr();
324 
325     errstr = (char *)alloca(FILENAME_MAX);
326     va_start(args, fmt);
327     vsnprintf(errstr, FILENAME_MAX, fmt, args);
328     va_end(args);
329     use_helpline(NULL);
330     use_helpfile(NULL);
331     if (OnVTY) {
332 	ioctl(0, VT_ACTIVATE, 1);	/* Switch back */
333 	msgInfo(NULL);
334     }
335     if (variable_get(VAR_NONINTERACTIVE))
336 	return 1;	/* If non-interactive, return NO all the time */
337     ret = dialog_noyes("User Confirmation Requested", errstr, -1, -1);
338     restorescr(w);
339     return ret;
340 }
341 
342 /* Put up a message in an input box and return the value */
343 char *
msgGetInput(char * buf,char * fmt,...)344 msgGetInput(char *buf, char *fmt, ...)
345 {
346     va_list args;
347     char *errstr;
348     static char input_buffer[256];
349     int rval;
350     WINDOW *w = savescr();
351 
352     errstr = (char *)alloca(FILENAME_MAX);
353     va_start(args, fmt);
354     vsnprintf(errstr, FILENAME_MAX, fmt, args);
355     va_end(args);
356     use_helpline(NULL);
357     use_helpfile(NULL);
358     if (buf)
359 	SAFE_STRCPY(input_buffer, buf);
360     else
361 	input_buffer[0] = '\0';
362     if (OnVTY) {
363 	ioctl(0, VT_ACTIVATE, 1);	/* Switch back */
364 	msgInfo(NULL);
365     }
366     rval = dialog_inputbox("Value Required", errstr, -1, -1, input_buffer);
367     restorescr(w);
368     if (!rval)
369 	return input_buffer;
370     else
371 	return NULL;
372 }
373 
374 /* Write something to the debugging port */
375 void
msgDebug(char * fmt,...)376 msgDebug(char *fmt, ...)
377 {
378     va_list args;
379     char *dbg;
380 
381     if (DebugFD == -1)
382 	return;
383     dbg = (char *)alloca(FILENAME_MAX);
384     strcpy(dbg, "DEBUG: ");
385     va_start(args, fmt);
386     vsnprintf((char *)(dbg + strlen(dbg)), FILENAME_MAX, fmt, args);
387     va_end(args);
388 
389     msgSyslog(dbg);
390 
391     write(DebugFD, dbg, strlen(dbg));
392 }
393 
394 /* Tell the user there's some output to go look at */
395 void
msgWeHaveOutput(char * fmt,...)396 msgWeHaveOutput(char *fmt, ...)
397 {
398     va_list args;
399     char *errstr;
400     WINDOW *w = savescr();
401 
402     errstr = (char *)alloca(FILENAME_MAX);
403     va_start(args, fmt);
404     vsnprintf(errstr, FILENAME_MAX, fmt, args);
405     va_end(args);
406     use_helpline(NULL);
407     use_helpfile(NULL);
408     msgDebug("Notify: %s\n", errstr);
409     dialog_clear_norefresh();
410     sleep(2);
411     dialog_msgbox(NULL, errstr, -1, -1, 0);
412     restorescr(w);
413 }
414 
415 /* Simple versions of msgConfirm() and msgNotify() for calling from scripts */
416 int
msgSimpleConfirm(char * str)417 msgSimpleConfirm(char *str)
418 {
419     msgConfirm("%s", str);
420     return DITEM_SUCCESS;
421 }
422 
423 int
msgSimpleNotify(char * str)424 msgSimpleNotify(char *str)
425 {
426     msgNotify("%s", str);
427     return DITEM_SUCCESS;
428 }
429