1/*- 2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <stand.h> 31#include <string.h> 32 33#include "bootstrap.h" 34/* 35 * Core console support 36 */ 37 38static int cons_set(struct env_var *ev, int flags, const void *value); 39static int cons_find(const char *name); 40static int cons_check(const char *string); 41static void cons_change(const char *string); 42 43/* 44 * Detect possible console(s) to use. If preferred console(s) have been 45 * specified, mark them as active. Else, mark the first probed console 46 * as active. Also create the console variable. 47 */ 48void 49cons_probe(void) 50{ 51 int cons; 52 int active; 53 char *prefconsole; 54 55 /* Do all console probes */ 56 for (cons = 0; consoles[cons] != NULL; cons++) { 57 consoles[cons]->c_flags = 0; 58 consoles[cons]->c_probe(consoles[cons]); 59 } 60 /* Now find the first working one */ 61 active = -1; 62 for (cons = 0; consoles[cons] != NULL && active == -1; cons++) { 63 consoles[cons]->c_flags = 0; 64 consoles[cons]->c_probe(consoles[cons]); 65 if (consoles[cons]->c_flags == (C_PRESENTIN | C_PRESENTOUT)) 66 active = cons; 67 } 68 /* Force a console even if all probes failed */ 69 if (active == -1) 70 active = 0; 71 72 /* Check to see if a console preference has already been registered */ 73 prefconsole = getenv("console"); 74 if (prefconsole != NULL) 75 prefconsole = strdup(prefconsole); 76 if (prefconsole != NULL) { 77 unsetenv("console"); /* we want to replace this */ 78 cons_change(prefconsole); 79 } else { 80 consoles[active]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; 81 consoles[active]->c_init(0); 82 prefconsole = strdup(consoles[active]->c_name); 83 } 84 85 printf("Consoles: "); 86 for (cons = 0; consoles[cons] != NULL; cons++) 87 if (consoles[cons]->c_flags & (C_ACTIVEIN | C_ACTIVEOUT)) 88 printf("%s ", consoles[cons]->c_desc); 89 printf("\n"); 90 91 if (prefconsole != NULL) { 92 env_setenv("console", EV_VOLATILE, prefconsole, cons_set, 93 env_nounset); 94 free(prefconsole); 95 } 96} 97 98int 99getchar(void) 100{ 101 int cons; 102 int rv; 103 104 /* Loop forever polling all active consoles */ 105 for(;;) 106 for (cons = 0; consoles[cons] != NULL; cons++) 107 if ((consoles[cons]->c_flags & (C_PRESENTIN | C_ACTIVEIN)) == 108 (C_PRESENTIN | C_ACTIVEIN) && 109 ((rv = consoles[cons]->c_in()) != -1)) 110 return(rv); 111} 112 113int 114ischar(void) 115{ 116 int cons; 117 118 for (cons = 0; consoles[cons] != NULL; cons++) 119 if ((consoles[cons]->c_flags & (C_PRESENTIN | C_ACTIVEIN)) == 120 (C_PRESENTIN | C_ACTIVEIN) && 121 (consoles[cons]->c_ready() != 0)) 122 return(1); 123 return(0); 124} 125 126void 127putchar(int c) 128{ 129 int cons; 130 131 /* Expand newlines */ 132 if (c == '\n') 133 putchar('\r'); 134 135 for (cons = 0; consoles[cons] != NULL; cons++) 136 if ((consoles[cons]->c_flags & (C_PRESENTOUT | C_ACTIVEOUT)) == 137 (C_PRESENTOUT | C_ACTIVEOUT)) 138 consoles[cons]->c_out(c); 139} 140 141/* 142 * Find the console with the specified name. 143 */ 144static int 145cons_find(const char *name) 146{ 147 int cons; 148 149 for (cons = 0; consoles[cons] != NULL; cons++) 150 if (!strcmp(consoles[cons]->c_name, name)) 151 return (cons); 152 return (-1); 153} 154 155/* 156 * Select one or more consoles. 157 */ 158static int 159cons_set(struct env_var *ev, int flags, const void *value) 160{ 161 int cons; 162 163 if ((value == NULL) || (cons_check(value) == -1)) { 164 if (value != NULL) 165 printf("no such console!\n"); 166 printf("Available consoles:\n"); 167 for (cons = 0; consoles[cons] != NULL; cons++) 168 printf(" %s\n", consoles[cons]->c_name); 169 return(CMD_ERROR); 170 } 171 172 cons_change(value); 173 174 env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL); 175 return(CMD_OK); 176} 177 178/* 179 * Check that all of the consoles listed in *string are valid consoles 180 */ 181static int 182cons_check(const char *string) 183{ 184 int cons; 185 char *curpos, *dup, *next; 186 187 dup = next = strdup(string); 188 cons = -1; 189 while (next != NULL) { 190 curpos = strsep(&next, " ,"); 191 if (*curpos != '\0') { 192 cons = cons_find(curpos); 193 if (cons == -1) 194 break; 195 } 196 } 197 198 free(dup); 199 return (cons); 200} 201 202/* 203 * Activate all of the consoles listed in *string and disable all the others. 204 */ 205static void 206cons_change(const char *string) 207{ 208 int cons; 209 char *curpos, *dup, *next; 210 211 /* Disable all consoles */ 212 for (cons = 0; consoles[cons] != NULL; cons++) { 213 consoles[cons]->c_flags &= ~(C_ACTIVEIN | C_ACTIVEOUT); 214 } 215 216 /* Enable selected consoles */ 217 dup = next = strdup(string); 218 while (next != NULL) { 219 curpos = strsep(&next, " ,"); 220 if (*curpos == '\0') 221 continue; 222 cons = cons_find(curpos); 223 if (cons >= 0) { 224 consoles[cons]->c_flags |= C_ACTIVEIN | C_ACTIVEOUT; 225 consoles[cons]->c_init(0); 226 if ((consoles[cons]->c_flags & (C_PRESENTIN | C_PRESENTOUT)) != 227 (C_PRESENTIN | C_PRESENTOUT)) 228 printf("console %s failed to initialize\n", 229 consoles[cons]->c_name); 230 } 231 } 232 233 free(dup); 234} 235