All user-space apps ware moved to 8MB virtual address address (link.ld changes);...
[ZeXOS.git] / kernel / core / tty.c
blob648a7368f018ce597b0fffba8f44066f4fdfd8ee
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <build.h>
23 #include <system.h>
24 #include <string.h>
25 #include <vfs.h>
27 #ifdef ARCH_i386 /* i386 specific things */
28 extern int gets (void);
29 extern unsigned short *textmemptr;
30 #endif
31 extern int attrib;
32 extern int csr_x, csr_y;
33 extern unsigned char vgagui;
35 static char con_screen[TTY_CON_BUF]; /* console buffer for image of screen */
36 static unsigned short tty_count; /* number of created ttys */
37 tty_font_t tty_font; /* global font settings */
38 tty_char_t tty_char; /* global character array settings */
40 tty_t tty_list; /* list for all created ttys */
41 tty_t *tty0, *tty1; /* structures for default ttys (0, 1) */
43 static unsigned task_tty ();
45 /* setup of font */
46 bool tty_font_set (char *c, unsigned char x, unsigned char y)
48 if (!c || !x || !y)
49 return 0;
51 tty_font.c = c;
52 tty_font.x = x;
53 tty_font.y = y;
55 return 1;
58 /* setup of character array */
59 bool tty_char_set (unsigned short x, unsigned short y)
61 if ((x * y * 2) > TTY_CON_BUF)
62 return 0;
64 tty_char.x = x;
65 tty_char.y = y;
67 return 1;
70 /* clear selected screen */
71 bool tty_cls (tty_t *tty)
73 if (!tty)
74 return 0;
76 if (!tty->screen)
77 return 0;
79 memset (tty->screen, 0, tty_char.x * tty_char.y * 2);
81 tty->screen_x = 0;
82 tty->screen_y = 0;
83 tty->read_len = 0;
85 if (tty != currtty)
86 return 1;
88 #ifdef ARCH_i386
89 if (vgagui) {
90 if (vgagui == 2)
91 video_gfx_cls (0);
93 return 1;
96 csr_x = 0;
97 csr_y = 0;
99 video_scroll ();
100 video_move_csr ();
101 #endif
102 video_cls ();
104 return 1;
107 /* lock manipulation with selected tty */
108 bool tty_lock (tty_t *tty)
110 if (!tty)
111 return 0;
113 tty->active = false;
115 return 1;
118 /* unlock manipulation with selected tty */
119 bool tty_unlock (tty_t *tty)
121 if (!tty)
122 return 0;
124 tty->active = true;
126 return 1;
129 /* startup function for tty init */
130 bool tty_startup ()
132 tty_t *tty = tty0;
134 if (tty == NULL)
135 return 0;
137 currtty = tty;
139 strcpy (currtty->pwd, (char *) env_get ("PWD"));
141 currtty = tty;
143 env_set ("PWD", tty->pwd);
145 /* always default colors */
146 attrib = 0x07;
148 /* clear screen*/
149 video_cls ();
151 return 1;
154 /* change current tty to selected one */
155 bool tty_change (tty_t *tty)
157 #ifndef ARCH_i386
158 return 0;
159 #endif
160 if (tty == NULL)
161 return 0;
163 #ifdef ARCH_i386
164 /* redraw screen with selected tty */
165 memcpy (textmemptr, tty->screen, tty_char.x * tty_char.y * 2);
167 csr_x = tty->screen_x;
168 csr_y = tty->screen_y;
170 video_move_csr ();
171 #endif
172 strcpy (currtty->pwd, (char *) env_get ("PWD"));
174 if (currtty->user && currtty->user->name)
175 strcpy (currtty->user->name, (char *) env_get ("USER"));
177 currtty = tty;
179 env_set ("PWD", tty->pwd);
181 if (tty->user)
182 env_set ("USER", tty->user->name);
184 return 1;
187 /* move cursor position to selected place */
188 bool tty_gotoxy (tty_t *tty, unsigned char x, unsigned char y)
190 if (tty == NULL)
191 return 0;
193 if (x >= tty_char.x || y >= tty_char.y)
194 return 0;
196 video_gotoxy (x, y);
198 tty->screen_x = x;
199 tty->screen_y = y;
201 return 1;
204 /* find wanted tty by name */
205 tty_t *tty_find (char *name)
207 tty_t *tty;
209 for (tty = tty_list.next; tty != &tty_list; tty = tty->next) {
210 if (!strcmp (tty->name, name))
211 return tty;
214 return NULL;
217 /* find tty by task */
218 tty_t *tty_findbytask (task_t *task)
220 tty_t *tty;
222 for (tty = tty_list.next; tty != &tty_list; tty = tty->next) {
223 if (tty->task == task)
224 return tty;
227 return NULL;
230 /* display list of created tty consoles */
231 void tty_listview ()
233 unsigned short id = 1;
235 tty_t *tty;
237 for (tty = tty_list.next; tty != &tty_list; tty = tty->next) {
238 printf ("%d.\t%s\t%s\n", id, tty->name, currtty == tty ? "<- current" : "");
240 id ++;
244 /* main function for print strings into selected tty */
245 bool tty_write (tty_t *tty, char *str, unsigned len)
247 if (!tty)
248 return 0;
250 unsigned l = 0;
251 while (l != len) {
252 if (!tty_putnch (tty, str[l]))
253 break;
255 l ++;
258 return 1;
261 /* read strings from selected tty */
262 int tty_read (tty_t *tty, char *str, unsigned len)
264 if (!tty || !str)
265 return 0;
267 char *p = (char *) tty->screen;
269 unsigned l = 0;
270 unsigned n = 2000;
272 unsigned x = 0;
273 unsigned y = 0;
275 if (len+tty->read_len > n)
276 len = n-tty->read_len;
278 for (l = 0; l < len; l ++) {
279 if (p[((l+tty->read_len)*2)+1])
280 str[l] = p[((l+tty->read_len)*2)+1];
282 x ++;
284 if (x >= tty_char.x) {
285 x = 0;
286 y ++;
287 str[l] = '\n';
291 str[l] = '\0';
293 tty->read_len += l;
295 return l;
298 /* print character to current tty */
299 bool tty_putch (char c)
301 tty_putnch (currtty, c);
303 return 1;
306 /* print character to selected tty */
307 bool tty_putnch (tty_t *tty, char c)
309 /* we wont null character */
310 if (!c)
311 return 0;
313 switch (c) {
314 case '\n':
315 tty->screen_y ++;
316 tty->screen_x = 0;
317 break;
318 case '\b':
319 if (tty->screen_x)
320 tty->screen_x --;
322 /* save font attributes (colors) */
323 tty->screen[(tty->screen_x+(tty->screen_y*tty_char.x))*2] = ' ';
324 /* save character into buffer */
325 tty->screen[((tty->screen_x+(tty->screen_y*tty_char.x))*2)+1] = attrib;
326 break;
327 case '\t':
328 tty->screen_x = (tty->screen_x + 8) & ~(8 - 1);
329 break;
330 default:
331 /* save font attributes (colors) */
332 tty->screen[(tty->screen_x+(tty->screen_y*tty_char.x))*2] = c;
333 /* save character into buffer */
334 tty->screen[((tty->screen_x+(tty->screen_y*tty_char.x))*2)+1] = attrib;
335 tty->screen_x ++;
336 break;
339 if (tty->screen_x >= tty_char.x) {
340 tty->screen_x -= tty_char.x;
341 tty->screen_y ++;
344 if (tty->screen_y >= tty_char.y) {
345 unsigned i;
346 /* save old screen, but with one line offset */
347 for (i = 0; i < (tty_char.x * tty_char.y * 2) - (tty_char.x * 2); i ++)
348 con_screen[i] = tty->screen[i+(tty_char.x * 2)];
349 /* copy new image into tty screen */
350 for (i = 0; i < (tty_char.x * tty_char.y * 2); i ++)
351 tty->screen[i] = con_screen[i];
353 tty->read_len += tty_char.x;
355 tty->screen_y = tty_char.y - 1;
358 if (!vgagui)
359 if (tty == currtty)
360 video_putch (c);
362 return 1;
365 /* create Message Of The Day in /etc/motd */
366 bool tty_motd ()
368 vfs_list_add ("motd", VFS_FILEATTR_FILE | VFS_FILEATTR_READ | VFS_FILEATTR_SYSTEM, "/etc/");
370 char *motd = "\t\t\t\tWelcome !\n"
371 "This is ZeX/OS - operating system created by Tomas 'ZeXx86' Jedrzejek\n"
372 "Please visit web page www.zexos.org for more information ..\n"
373 "Latest source code is available on git repository: git://repo.or.cz/ZeXOS.git\n"
374 "You can display list of the built-in commands by \"help\".\n"
375 "Default login name is \"root\" secured by password \"root\".\n";
377 vfs_mmap ("/etc/motd", 9, motd, strlen (motd));
379 video_color (15, 0);
381 vfs_cat ("/etc/motd", 9);
383 video_color (7, 0);
385 return 1;
388 /* create new tty console */
389 tty_t *tty_create ()
391 /* Software limit - max. 1K of ttys */
392 if (tty_count > TTY_COUNT_MAX)
393 return 0;
395 char name[8];
396 sprintf (name, "tty%d", tty_count);
398 unsigned name_len = strlen (name);
400 /* alloc and init context */
401 tty_t *tty = (tty_t *) kmalloc (sizeof (tty_t));
403 if (!tty)
404 return 0;
406 memset (tty, 0, sizeof (tty_t));
408 tty->screen = (char *) kmalloc (tty_char.x * tty_char.y * 2);
410 if (!tty->screen) {
411 kfree (tty);
412 return 0;
415 tty->name = (char *) kmalloc (sizeof (char) * name_len + 1);
417 if (!tty->name) {
418 kfree (tty->screen);
419 kfree (tty);
420 return 0;
423 memcpy (tty->name, name, name_len);
424 tty->name[name_len] = '\0';
426 memset (tty->screen, 0, tty_char.x * tty_char.y * 2);
428 tty->screen_x = 0;
429 tty->screen_y = 0;
431 tty->logged = false;
433 tty->active = true;
435 tty->read_len = 0;
437 strcpy (tty->pwd, (char *) env_get ("PWD"));
439 tty->task = (task_t *) task_create (name, (unsigned) task_tty, 32);
441 /* add into list */
442 tty->next = &tty_list;
443 tty->prev = tty_list.prev;
444 tty->prev->next = tty;
445 tty->next->prev = tty;
447 tty_count ++;
449 return tty;
452 /* thread for running tty consoles - handle selected console */
453 void task_thread (tty_t *tty)
455 schedule ();
457 if (!tty)
458 return;
460 if (tty != currtty)
461 return;
463 if (tty->active) {
464 /* handle console on kernel level */
465 int id = gets ();
467 if (id == 1)
468 if (tty->user) {
469 console (id);
470 } else
471 getlogin (id);
473 /* VESA mode - graphical font */
474 if (vgagui == 2) {
475 unsigned i = 0;
476 unsigned j = 0;
477 unsigned k = 0;
478 unsigned m = tty_char.x * tty_char.y;
480 while (i < m) {
481 gputch (1+(j*tty_font.x), 11+(k*(tty_font.y+1)), vesa_16cto16b (tty->screen[i*2+1] & 0x0F), tty->screen[i*2]);
483 j ++;
485 if (j >= tty_char.x) {
486 j = 0;
487 k ++;
490 i ++;
493 video_gfx_fbswap ();
498 /* startup function for created tty console */
499 static unsigned task_tty ()
501 tty_t *tty = tty_findbytask (_curr_task);
503 if (!tty)
504 return 0;
506 while (1)
507 task_thread (tty);
510 /* change tty console to next (+) or previous (-) in list */
511 void tty_switch (char act)
513 switch (act) {
514 case '+':
516 tty_t *tty = currtty->next;
518 if (tty == &tty_list)
519 tty = tty_list.next;
521 if (tty)
522 tty_change (tty);
524 break;
526 case '-':
528 tty_t *tty = currtty->prev;
530 if (tty == &tty_list)
531 tty = tty_list.prev;
533 if (tty)
534 tty_change (tty);
536 break;
541 /* special function for initialization of graphical tty */
542 tty_t *gtty_init ()
544 tty_t *tty = tty_create ();
546 tty_change (tty);
548 return tty;
551 /* initialization of tty */
552 unsigned int init_tty ()
554 /* pre-set tty list */
555 tty_list.next = &tty_list;
556 tty_list.prev = &tty_list;
558 /* default values */
559 tty_count = 0;
561 tty_font_set ((char *) font5x8, 5, 8);
563 switch (vgagui) {
564 case 0: /* VGA-Textual console */
565 tty_char_set (80, 25);
566 break;
567 case 1: /* VGA console */
568 tty_char_set (53, 18);
569 break;
570 case 2: /* VESA concole */
571 tty_char_set (80, 65);
572 break;
575 video_color (7, 0);
577 /* create consoles */
578 tty0 = tty_create ();
580 if (!tty0)
581 return 0;
583 #ifdef ARCH_i386
584 tty1 = tty_create ();
586 if (!tty1)
587 return 0;
588 #endif
589 tty_startup ();
591 /* printf MOTD into TTY0 console */
592 tty_motd ();
594 /* then print login messages */
595 tty_write (tty0, "\nlogin: ", 8);
596 tty_write (tty1, "\nlogin: ", 8);
598 return 1;