linux/drivers/char/tty_io.c

/*
 *  linux/drivers/char/tty_io.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

/*
 * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
 * or rs-channels. It also implements echoing, cooked mode etc.
 *
 * Kill-line thanks to John T Kohl, who also corrected VMIN = VTIME = 0.
 *
 * Modified by Theodore Ts'o, 9/14/92, to dynamically allocate the
 * tty_struct and tty_queue structures.  Previously there was an array
 * of 256 tty_struct's which was statically allocated, and the
 * tty_queue structures were allocated at boot time.  Both are now
 * dynamically allocated only when the tty is open.
 *
 * Also restructured routines so that there is more of a separation
 * between the high-level tty routines (tty_io.c and tty_ioctl.c) and
 * the low-level tty routines (serial.c, pty.c, console.c).  This
 * makes for cleaner and more compact code.  -TYT, 9/17/92 
 *
 * Modified by Fred N. van Kempen, 01/29/93, to add line disciplines
 * which can be dynamically activated and de-activated by the line
 * discipline handling modules (like SLIP).
 *
 * NOTE: pay no attention to the line discipline code (yet); its
 * interface is still subject to change in this version...
 * -- TYT, 1/31/92
 *
 * Added functionality to the OPOST tty handling.  No delays, but all
 * other bits should be there.
 *	-- Nick Holloway <alfie@dcs.warwick.ac.uk>, 27th May 1993.
 *
 * Rewrote canonical mode and added more termios flags.
 * 	-- julian@uhunix.uhcc.hawaii.edu (J. Cowley), 13Jan94
 *
 * Reorganized FASYNC support so mouse code can share it.
 *	-- ctm@ardi.com, 9Sep95
 *
 * New TIOCLINUX variants added.
 *	-- mj@k332.feld.cvut.cz, 19-Nov-95
 * 
 * Restrict vt switching via ioctl()
 *      -- grif@cs.ucr.edu, 5-Dec-95
 *
 * Rewrote init_dev and release_dev to eliminate races.
 *	-- Bill Hawes <whawes@star.net>, June 97
 */

#include <linux/config.h>
#include <linux/types.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/fcntl.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/kd.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/malloc.h>

#include <asm/segment.h>
#include <asm/system.h>
#include <asm/bitops.h>

#include <linux/scc.h>

#include "kbd_kern.h"
#include "vt_kern.h"
#include "selection.h"

#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif

/* Bieca konsola, urzdzenie o numerze gwnym TTY_MAJOR
   i numerze drugorzdnym 0 (reprezentowane przez plik /dev/tty0). */ 
#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
/* Terminal sterujcy dla procesu, urzdzenie o numerze gwnym
   TTYAUX_MAJOR i numerze drugorzdnym 0 (reprezentowane przez plik /dev/tty). */
#define TTY_DEV MKDEV(TTYAUX_MAJOR,0)

#undef TTY_DEBUG_HANGUP

#define TTY_PARANOIA_CHECK
#define CHECK_TTY_COUNT

extern void do_blank_screen(int nopowersave);
extern void set_vesa_blanking(const unsigned long arg);

/* Standardowa struktura termios dla sterownikw. */
struct termios tty_std_termios;		/* for the benefit of tty drivers  */
/* Lista sterownikw dla terminali. */
struct tty_driver *tty_drivers = NULL;	/* linked list of tty drivers */
/* Tablica dyscyplin linii. */
struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/

/*
 * fg_console is the current virtual console,
 * last_console is the last used one,
 * want_console is the console we want to switch to,
 * kmsg_redirect is the console for kernel messages,
 * redirect is the pseudo-tty that console output
 * is redirected to if asked by TIOCCONS.
 */
/* Bieca wirtualna konsola. */
int fg_console = 0;
/* Konsola ostatnio uywana. */
int last_console = 0;
/* Konsola, na ktr chcemy si przeczy. */
int want_console = -1;
/* Konsola dla komunikatw jdra. */
int kmsg_redirect = 0;
/* Pseudoterminal, na ktry jest przekierowywane wyjcie przez TIOCCONS. */
struct tty_struct * redirect = NULL;
/* Kolejka czekajcych na nacinicie klawisza. */
struct wait_queue * keypress_wait = NULL;
/* Znacznik informujcy, czy moemy przecza si pomidzy konsolami. */
char vt_dont_switch = 0;


static void initialize_tty_struct(struct tty_struct *tty);

static int tty_read(struct inode *, struct file *, char *, int);
static int tty_write(struct inode *, struct file *, const char *, int);
static int tty_select(struct inode *, struct file *, int, select_table *);
static int tty_open(struct inode *, struct file *);
static void tty_release(struct inode *, struct file *);
static int tty_ioctl(struct inode * inode, struct file * file,
		     unsigned int cmd, unsigned long arg);
static int tty_fasync(struct inode * inode, struct file * filp, int on);

extern void reset_palette(int currcons) ;
extern void set_palette(void) ;

#ifndef MIN
#define MIN(a,b)	((a) < (b) ? (a) : (b))
#endif


/* * These two routines return the name of tty. tty_name() should NOT * be used in interrupt drivers, since it's not re-entrant. Use * _tty_name() instead. */ /* Nastpne dwie funckje zwracaj nazw terminala. tty_name nie powinna by uywana w sterownikach przerwaniowych, poniewa nie jest wielowejciowa (uywa bufora statycznego). Naley wtedy uywa _tty_name. */ char *_tty_name(struct tty_struct *tty, char *buf) { if (tty) sprintf(buf, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start + tty->driver.name_base); else strcpy(buf, "NULL tty"); return buf; }
char *tty_name(struct tty_struct *tty) { static char buf[64]; return(_tty_name(tty, buf)); }
/* tty_paranoia_check -sprawdza poprawno numeru magic oraz czy struktura opisujca terminal nie jest NULLem. Powrt: 0 :OK, 1 :wpp. */ inline int tty_paranoia_check(struct tty_struct *tty, kdev_t device, const char *routine) { #ifdef TTY_PARANOIA_CHECK static const char *badmagic = "Warning: bad magic number for tty struct (%s) in %s\n"; static const char *badtty = "Warning: null TTY for (%s) in %s\n"; if (!tty) { printk(badtty, kdevname(device), routine); return 1; } if (tty->magic != TTY_MAGIC) { printk(badmagic, kdevname(device), routine); return 1; } #endif return 0; }
/* check_tty_count -sprawdza, czy licznik count, oznaczajcy liczb otworzonych plikw specjalnych dla danego urzdzenia, zawiera prawidow warto. Powrt: 0 :OK, poprawna warto :wpp. */ static int check_tty_count(struct tty_struct *tty, const char *routine) { #ifdef CHECK_TTY_COUNT struct file *f; int i, count = 0; /* Przegldamy list plikw zliczajc te, ktre s uywane (licznik f_count dowiza z tablic deskryptorw uytkownikw wikszy od 0) oraz wskazuj na nasz terminal. */ for (f = first_file, i=0; i<nr_files; i++, f = f->f_next) { if (!f->f_count) continue; if (f->private_data == tty) { count++; } } /* Jeeli struktura tty opisuje cz podrzdn pseudoterminala zwikszamy jeszcze raz licznik. Licznik w czci podrzdnej pseudoterminala jest wikszy o jeden od rzeczywistej liczby, aby cz podrzdna nie zostaa zamknita przed czci nadrzdn. */ if (tty->driver.type == TTY_DRIVER_TYPE_PTY && tty->driver.subtype == PTY_TYPE_SLAVE && tty->link && tty->link->count) count++; /* Jeeli obliczona przez nas warto nie zgadza si z licznikiem count w strukturze opisujcej terminal zwracamy prawidow warto. */ if (tty->count != count) { printk("Warning: dev (%s) tty->count(%d) != #fd's(%d) in %s\n", kdevname(tty->device), tty->count, count, routine); return count; } #endif return 0; }
/* tty_register_ldisc -rejestracja dyscypliny linii. Jeeli wskanik na struktur dyscypliny linii jest NULLem rejestracja oznacza wyzerowanie dyscypliny linii o podanym numerze. Powrt: 0 :OK, kod bdu :wpp. */ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) { /* Sprawdzamy, czy numer dycypliny linii zawarty w zakresie. */ if (disc < N_TTY || disc >= NR_LDISCS) return -EINVAL; /* Ustawiamy odpowiedni dyscyplin linii w tablicy dyscyplin linii ldiscs, aktualizujemy jej numer i znacznik informujcy o zdefiniowaniu dyscypliny linii. Jeeli nowa dyscyplina nie jest podana zerujemy element o numerze disc w tablicy ldiscs. */ if (new_ldisc) { ldiscs[disc] = *new_ldisc; ldiscs[disc].flags |= LDISC_FLAG_DEFINED; ldiscs[disc].num = disc; } else memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc)); return 0; }
/* Set the discipline of a tty line. */ /* tty_set_ldisc -zmieniamy dyscyplin linii. Powrt: 0 :OK, kod bdu :wpp. */ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) { int retval = 0; struct tty_ldisc o_ldisc; /* Sprawdzamy poprawno numeru dyscypliny linii. */ if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS)) return -EINVAL; #ifdef CONFIG_KERNELD /* Eduardo Blanco <ejbs@cs.cs.com.uy> */ if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) { char modname [20]; sprintf(modname, "tty-ldisc-%d", ldisc); request_module (modname); } #endif /* Sprawdzamy, czy dyscyplina linii o podanym numerze zostaa zdefiniowana. */ if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) return -EINVAL; /* Jeeli ju jestemy w danej dyscyplinie linii to powrt z sukcesem. */ if (tty->ldisc.num == ldisc) return 0; /* We are already in the desired discipline */ /* Zapamitujemy biec dyscyplin linii. W przypadku niepowodzenia z now sprbujemy przywrci star dyscyplin linii. */ o_ldisc = tty->ldisc; /* Jeli jest co w buforze sterownika to prbujemy wysa na terminal. */ tty_wait_until_sent(tty, 0); /* Zamykamy biec duscyplin linii. */ /* Shutdown the current discipline. */ if (tty->ldisc.close) (tty->ldisc.close)(tty); /* Ustawiamy now dyscyplin linii. */ /* Now set up the new line discipline. */ tty->ldisc = ldiscs[ldisc]; tty->termios->c_line = ldisc; /* Jeeli istnieje to wywoujemy funkcj otworzenia specyficzn dla dyscypliny linii. */ if (tty->ldisc.open) retval = (tty->ldisc.open)(tty); /* Jeeli nie powiodo si otworzenie danej dyscypliny linii ... */ if (retval < 0) { /* ... prbujemy przywrci poprzedni. */ tty->ldisc = o_ldisc; tty->termios->c_line = tty->ldisc.num; /* Jeeli nie udao nam si otworzy poprzedniej dyscypliny linii ... */ if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) { /* ... przeczamy si do standardowej dyscypliny linii N_TTY. */ tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if (tty->ldisc.open) { int r = tty->ldisc.open(tty); /* Jeeli nie potrafilimy otworzy podstawowej dyscpypliny linii to panikujemy! */ if (r < 0) panic("Couldn't open N_TTY ldisc for " "%s --- error %d.", tty_name(tty), r); } } } /* Jeeli zmienilimy dyscpylin linii (niekoniecznie na dan) wywoujemy funkcj zmiany dyscypliny linii ze sterownika (oczywicie o ile istnieje). */ if (tty->ldisc.num != o_ldisc.num && tty->driver.set_ldisc) tty->driver.set_ldisc(tty); return retval; }
/* * This routine returns a tty driver structure, given a device number */ /* get_tty_driver -zwraca struktur opisujc sterownik dla danego urzdzenia. Powrt: tty_driver :jeeli istnieje, NULL :wpp. */ struct tty_driver *get_tty_driver(kdev_t device) { int major, minor; struct tty_driver *p; /* Pobieramy numer gwny i drugorzdny urzdzenia. */ minor = MINOR(device); major = MAJOR(device); /* Przegldamy list sterownikw, aby znale waciwy. Sterownik p obsuguje num urzdze o kolejnych numerach drugorzdnych poczynajc od p->minor_start i o numerze gwnym p->major. Uwaga: minor_start tylko dla konsoli jest rny od 0 (wynosi 1). */ for (p = tty_drivers; p; p = p->next) { if (p->major != major) continue; if (minor < p->minor_start) continue; if (minor >= p->minor_start + p->num) continue; /* Zwracamy waciwy sterownik. (1) Sterownik jest dla urzdze o podanym numerze gwnym. (2) Numer drugorzdny urzdzenia mieci si w zakresie obsugiwanym przez sterownik. */ return p; } /* Nie znalelimy sterownika dla podanego urzdzenia. */ return NULL; }
/* * If we try to write to, or set the state of, a terminal and we're * not in the foreground, send a SIGTTOU. If the signal is blocked or * ignored, go ahead and perform the operation. (POSIX 7.2) */ /* tty_check_change -dla procesu dziaajcego w tle sprawdzamy czy moe wykona operacj pisania lub zmiany stanu terminala. Powrt: 0 :OK, kod bdu :wpp. */ int tty_check_change(struct tty_struct * tty) { /* Jeeli nie jest to nasz terminal sterujcy :OK */ if (current->tty != tty) return 0; /* Ujemny numer grupy terminala :OK. */ if (tty->pgrp <= 0) { printk("tty_check_change: tty->pgrp <= 0!\n"); return 0; } /* Jeeli naleymy do grupy terminala :OK. */ if (current->pgrp == tty->pgrp) return 0; /* Jeeli jest ignorowany sygna SIGTTOU :OK. */ if (is_ignored(SIGTTOU)) return 0; /* Jeeli grupa, do ktrej naley nasz proces jest 'osierocona' :bd. */ if (is_orphaned_pgrp(current->pgrp)) return -EIO; /* Wysyamy sygna SIGTTOU do grupy, do ktrej naley proces. */ (void) kill_pg(current->pgrp,SIGTTOU,1); return -ERESTARTSYS; }
static int hung_up_tty_read(struct inode * inode, struct file * file, char * buf, int count) { return 0; }
static int hung_up_tty_write(struct inode * inode, struct file * file, const char * buf, int count) { return -EIO; }
static int hung_up_tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait) { return 1; }
static int hung_up_tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { return cmd == TIOCSPGRP ? -ENOTTY : -EIO; }
static int tty_lseek(struct inode * inode, struct file * file, off_t offset, int orig) { return -ESPIPE; }
/* Opisuje operacje dla terminala. */ static struct file_operations tty_fops = { tty_lseek, tty_read, tty_write, NULL, /* tty_readdir */ tty_select, tty_ioctl, NULL, /* tty_mmap */ tty_open, tty_release, NULL, /* tty_fsync */ tty_fasync };
/* hung_up_tty_fops -operacje, ktre s ustawiane po zerwaniu cznoci z terminalem. */ static struct file_operations hung_up_tty_fops = { tty_lseek, hung_up_tty_read, hung_up_tty_write, NULL, /* hung_up_tty_readdir */ hung_up_tty_select, hung_up_tty_ioctl, NULL, /* hung_up_tty_mmap */ NULL, /* hung_up_tty_open */ tty_release, /* hung_up_tty_release */ NULL, /* hung_up_tty_fsync */ NULL /* hung_up_tty_fasync */ };
/* do_tty_hangup -zerwanie cznoci z terminalem. */ void do_tty_hangup(struct tty_struct * tty, struct file_operations *fops) { int i; struct file * filp; struct task_struct *p; if (!tty) return; /* Sprawdzamy licznik w strukturze terminala. */ check_tty_count(tty, "do_tty_hangup"); /* Przegldamy list plikw wyszukukjc te, ktre s uywane, wskazuj nasz terminal i wywoujemy dla nich funkcj fasync oraz ustawiamy f_op (file_operations) na fops przekazane jako argument do funkcji (s to hung_up_tty_fops). */ for (filp = first_file, i=0; i<nr_files; i++, filp = filp->f_next) { if (!filp->f_count) continue; if (filp->private_data != tty) continue; if (!filp->f_inode) continue; if (filp->f_inode->i_rdev == CONSOLE_DEV) continue; if (filp->f_op != &tty_fops) continue; tty_fasync(filp->f_inode, filp, 0); filp->f_op = fops; } /* Wywoujemy (jeeli istnieje) funkcj oprnienia buforw z dyscypliny linii. */ if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); /* Wywoujemy (jeeli istnieje) funkcj oprnienia buforw ze sterownika. */ if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); /* Budzimy procesy czekajce w kolejce do pisania na danym terminalu. */ wake_up_interruptible(&tty->write_wait); /* Budzimy procesy czekajce w kolejce do czytania z danego terminala. */ wake_up_interruptible(&tty->read_wait); /* * Shutdown the current line discipline, and reset it to * N_TTY. */ /* Zamykamy biec dyscyplin linii. */ if (tty->ldisc.num != ldiscs[N_TTY].num) { if (tty->ldisc.close) (tty->ldisc.close)(tty); /* Przeczamy si do standardowej dyscypliny linii N_TTY. */ tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if (tty->ldisc.open) { i = (tty->ldisc.open)(tty); if (i < 0) printk("do_tty_hangup: N_TTY open: error %d\n", -i); } } /* Przegldamy wszystkie procesy. */ for_each_task(p) { /* Jeeli proces jest liderem sesji terminala wysyamy do niego sygna SIGHUP (zerwania cznoci) i SIGCONT (wznowienie wstrzymanego procesu) oraz zapamitujemy identyfikator grupy terminalowej. */ if ((tty->session > 0) && (p->session == tty->session) && p->leader) { send_sig(SIGHUP,p,1); send_sig(SIGCONT,p,1); if (tty->pgrp > 0) p->tty_old_pgrp = tty->pgrp; } /* Dla wszystkich procesw, dla ktrych terminal, z ktrym zrywamy czno by terminalem sterujcym, ustawiamy terminal steryjcy na NULL. */ if (p->tty == tty) p->tty = NULL; } /* Resetujemy flagi, pole sesji, pole identyfikatora grupy terminala oraz pole stanu dla pseudoterminala. */ tty->flags = 0; tty->session = 0; tty->pgrp = -1; tty->ctrl_status = 0; /* Jeeli w sterowniku jest ustawiona flaga resetowania struktury termios inicjujemy struktur termios w terminalu. */ if (tty->driver.flags & TTY_DRIVER_RESET_TERMIOS) *tty->termios = tty->driver.init_termios; /* Wywoujemy funkcj zerwania acznoci z terminalem ze sterownika. */ if (tty->driver.hangup) (tty->driver.hangup)(tty); }
void tty_hangup(struct tty_struct * tty) { #ifdef TTY_DEBUG_HANGUP printk("%s hangup...\n", tty_name(tty)); #endif do_tty_hangup(tty, &hung_up_tty_fops); }
void tty_vhangup(struct tty_struct * tty) { #ifdef TTY_DEBUG_HANGUP printk("%s vhangup...\n", tty_name(tty)); #endif do_tty_hangup(tty, &hung_up_tty_fops); }
/* tty_hung_up_p -sprawdzenie, czy operacje s ustawione na hung_up_tty_fops. */ int tty_hung_up_p(struct file * filp) { return (filp->f_op == &hung_up_tty_fops); }
/* * This function is typically called only by the session leader, when * it wants to disassociate itself from its controlling tty. * * It performs the following functions: * (1) Sends a SIGHUP and SIGCONT to the foreground process group * (2) Clears the tty from being controlling the session * (3) Clears the controlling tty for all processes in the * session group. * * The argument on_exit is set to 1 if called when a process is * exiting; it is 0 if called by the ioctl TIOCNOTTY. */ /* disassociate_ctty -funkcja woana zazwyczaj przez lidera sesji, kiedy chce on odczy si od swojego terminal sterujcego. Wykonuje nastpujce operacje: (1) Wysya SIGHUP i SIGCONT do grupy procesw pierwszoplanowych (2) Wymazuje znacznik kontrolowania sesji w terminalu (3) Wymazuje terminal sterujcy dla wszystkich procesw w grupie sesji. Argument on_exit jest 1, jeeli funkcja jest woana przez proces koczcy si,a jest rwny 0, jeli jest woana przez ioctl z argumentem TIOCNOTTY. */ void disassociate_ctty(int on_exit) { struct tty_struct *tty = current->tty; struct task_struct *p; int tty_pgrp = -1; if (tty) { /* Jeeli proces ma terminal sterujcy to zapamitujemy numer grupy terminalowej oraz ... */ tty_pgrp = tty->pgrp; /* ... jeli nie mamy do czynienia z pseudoterminalem i lider sesji koczy si (on_exit==1) to wywoujemy funkcj zerwania cznoci z terminalem. */ if (on_exit && tty->driver.type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); } else { /* W przypadku gdy proces nie mia terminala sterujcego. */ if (current->tty_old_pgrp) { /* Jeli pole tty_old_pgrp zawiera co oznacza to, i wczeniej nastpio zerwanie cznoci z terminalem i proces ten by liderem sesji. Wysyamy sygnay SIGHUP (zerwania cznoci) i SIGCONT (wznowienia wstrzymanego procesu) do grupy tty_old_pgrp (starej grupy terminalowej). */ kill_pg(current->tty_old_pgrp, SIGHUP, on_exit); kill_pg(current->tty_old_pgrp, SIGCONT, on_exit); } return; } /* Wysyamy sygnay SIGHUP i SIGCONT do grupy terminalowej procesu. */ if (tty_pgrp > 0) { kill_pg(tty_pgrp, SIGHUP, on_exit); if (!on_exit) kill_pg(tty_pgrp, SIGCONT, on_exit); } /* Resetujemy pole tty_old_pgrp procesu. */ current->tty_old_pgrp = 0; /* Resetujemy pole sesji i grupy terminalowej w terminalu. */ tty->session = 0; tty->pgrp = -1; /* Wymazujemy terminal sterujcy dla wszystkich procesw nalecych do sesji. */ for_each_task(p) if (p->session == current->session) p->tty = NULL; }
/* * Sometimes we want to wait until a particular VT has been activated. We * do it in a very simple manner. Everybody waits on a single queue and * get woken up at once. Those that are satisfied go on with their business, * while those not ready go back to sleep. Seems overkill to add a wait * to each vt just for this - usually this does nothing! */ /* Czasem chcemy poczeka na aktywacj konkretnego terminala. Robimy to w bardzo prosty sposb. Wszyscy czekaj na jednej kolejce i budz si na raz. Ci, ktrzy s usatysfakcjonowani zaczynaj przetwarzanie, natomiast reszta idzie z powrotem spa. */ static struct wait_queue *vt_activate_queue = NULL;
/* * Sleeps until a vt is activated, or the task is interrupted. Returns * 0 if activation, -1 if interrupted. */ /* vt_waitactive -sen, dopki terminal nie zostanie uaktywniony lub nie nadejdzie przerwanie. Powrt: 0 :aktywacja, -1 :przerwanie. */ int vt_waitactive(void) { /* Zanij (przerwania dozwolone) na kolejce czekajcych na terminale. */ interruptible_sleep_on(&vt_activate_queue); /* Zwraca -1, jeeli by sygna i nie jest on blokowany, przypadek przeciwny oznacza aktywacj. */ return (current->signal & ~current->blocked) ? -1 : 0; }
#define vt_wake_waitactive() wake_up(&vt_activate_queue)
/* reset_vc -resetujemy ustawienia dla danej konsoli. */ void reset_vc(unsigned int new_console) { vt_cons[new_console]->vc_mode = KD_TEXT; kbd_table[new_console].kbdmode = VC_XLATE; vt_cons[new_console]->vt_mode.mode = VT_AUTO; vt_cons[new_console]->vt_mode.waitv = 0; vt_cons[new_console]->vt_mode.relsig = 0; vt_cons[new_console]->vt_mode.acqsig = 0; vt_cons[new_console]->vt_mode.frsig = 0; vt_cons[new_console]->vt_pid = -1; vt_cons[new_console]->vt_newvt = -1; reset_palette (new_console) ; }
/* * Performs the back end of a vt switch */ /* complete_change_console -dokoczenie przeczenia pomidzy konsolami. */ void complete_change_console(unsigned int new_console) { unsigned char old_vc_mode; /* Jeeli konsola, na ktr chcemy si przeczy jest nasz biec konsol lub jest zabronione przeczanie pomidzy konsolami to powrt. */ if ((new_console == fg_console) || (vt_dont_switch)) return; /* Sprawdzamy czy konsola zostaa zaalokowana. */ if (!vc_cons_allocated(new_console)) return; /* Zapamitujemy biec konsol jako ostatnio uywan. */ last_console = fg_console; /* * If we're switching, we could be going from KD_GRAPHICS to * KD_TEXT mode or vice versa, which means we need to blank or * unblank the screen later. */ /* Jeeli przeczamy si pomidzy konsolami moemy przechodzi midzy trybem graficznym a tekstowym, co oznacza, e musimy pniej wygasi i odwiey ekran. Zapamitujemy biey tryb. */ old_vc_mode = vt_cons[fg_console]->vc_mode; /* Aktualizujemy informacje o ekranie. */ update_screen(new_console); /* * If this new console is under process control, send it a signal * telling it that it has acquired. Also check if it has died and * clean up (similar to logic employed in change_console()) */ /* Jeeli nowa konsola ma proces sterujcy (jest w trybie VT_PROCESS), wysyamy do niego sygna, e zostaa zdobyta. Musimy rwnie sprawdzi, czy nie umar i posprzta. */ if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ /* Wysyamy sygna jako uprzywilejowany (trzeci argument dla kill_proc jest 1), na pewno zostanie wysany. kill_proc zwrci nam bd, jeli nie znajdzie tego procesu. */ if (kill_proc(vt_cons[new_console]->vt_pid, vt_cons[new_console]->vt_mode.acqsig, 1) != 0) { /* * The controlling process has died, so we revert back to * normal operation. In this case, we'll also change back * to KD_TEXT mode. I'm not sure if this is strictly correct * but it saves the agony when the X server dies and the screen * remains blanked due to KD_GRAPHICS! It would be nice to do * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ /* Proces sterujcy zmar, wic powrcamy do normy - resetujemy now konsol. Przeczamy si rwnie do trybu tekstowego. Nie jest pewne czy to jest zupenie poprawne, ale ratuje przed zawieszeniem jeeli X serwer zmar i ekran pozostaje wygaszony w trybie graficznym. */ reset_vc(new_console); } } /* * We do this here because the controlling process above may have * gone, and so there is now a new vc_mode */ /* Robimy to tutaj, poniewa proces sterujcy mg si skoczy i mamy nowy tryb. */ if (old_vc_mode != vt_cons[new_console]->vc_mode) { if (vt_cons[new_console]->vc_mode == KD_TEXT) do_unblank_screen(); else do_blank_screen(1); } /* Set the colour palette for this VT */ /* Ustawiamy palet dla tego wirtualnego terminala, jeeli jest w trybie tekstowym. */ if (vt_cons[new_console]->vc_mode == KD_TEXT) set_palette() ; /* * Wake anyone waiting for their VT to activate */ /* Budzimy czekajcych na aktywacj terminali. */ vt_wake_waitactive(); return; }
/* * Performs the front-end of a vt switch */ /* change_console -zmiana konsoli. */ void change_console(unsigned int new_console) { /* Jeeli konsola, na ktr chcemy si przeczy jest nasz biec konsol lub jest zabronione przeczanie pomidzy konsolami to powrt. */ if ((new_console == fg_console) || (vt_dont_switch)) return; if (!vc_cons_allocated(new_console)) return; /* * If this vt is in process mode, then we need to handshake with * that process before switching. Essentially, we store where that * vt wants to switch to and wait for it to tell us when it's done * (via VT_RELDISP ioctl). * * We also check to see if the controlling process still exists. * If it doesn't, we reset this vt to auto mode and continue. * This is a cheap way to track process control. The worst thing * that can happen is: we send a signal to a process, it dies, and * the switch gets "lost" waiting for a response; hopefully, the * user will try again, we'll detect the process is gone (unless * the user waits just the right amount of time :-) and revert the * vt to auto control. */ /* Jeeli biecy terminal ma proces sterujcy, musimy si porozumie z nim przed przeczeniem. Przechowujemy terminal, na ktry chcemy si przeczy i czekamy na informacje o przeczneiu (przez VT_RELDISP). Sprawdzamy rwnie czy proces sterujcy wci istnieje. Jeeli nie istnieje to przeczamy wirtualny terminal do trybu automatycznego i kontynuujemy. Jest to prosty sposb na ledzenie procesu sterujcego. Najgorszy scenariusz, ktry moe si zdarzy to: wysyamy sygna do procesu, on umiera, dostajemy 'zgubione' czekajc na odpowied; na szczcie uytkownik sprbuje znowu, wykryjemy, e nie ma procesu sterujcego i przeczymy terminal w tryb automatyczny. */ if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS) { /* * Send the signal as privileged - kill_proc() will * tell us if the process has gone or something else * is awry */ /* Wysyamy sygna jako uprzywilejowany (na pewno zostanie wysany). kill_proc przekae nam czy proces skoczy si. */ if (kill_proc(vt_cons[fg_console]->vt_pid, vt_cons[fg_console]->vt_mode.relsig, 1) == 0) { /* * It worked. Mark the vt to switch to and * return. The process needs to send us a * VT_RELDISP ioctl to complete the switch. */ /* Proces dziaa. Zaznaczamy wirtualny terminal, na ktry chcemy si przeczy. Proces sterujcy musi nam przesa ioctl VT_RELDISP, abymy skoczyli przeczanie. */ vt_cons[fg_console]->vt_newvt = new_console; return; } /* * The controlling process has died, so we revert back to * normal operation. In this case, we'll also change back * to KD_TEXT mode. I'm not sure if this is strictly correct * but it saves the agony when the X server dies and the screen * remains blanked due to KD_GRAPHICS! It would be nice to do * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ /* Proces sterujcy zmar, wic wracamy do normy. Przeczamy si rwnie do trybu tekstowego. Nie jest pewne czy to jest zupenie poprawne, lecz ratuje przed zawieszeniem, jeeli X serwer umrze i ekran pozostaje wygaszony w trybie graficznym. */ reset_vc(fg_console); /* * Fall through to normal (VT_AUTO) handling of the switch... */ } /* * Ignore all switches in KD_GRAPHICS+VT_AUTO mode */ /* Bieca konsola nie miaa procesu sterujcego i jest w trybie graficznym: nie pezczamy si. */ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; /* Koczymy przeacznie konsoli, jeeli bieca konsola miaa proces sterujcy, ktry zmar lub nie miaa procesu sterujcego i jest w trybie tekstowym. */ complete_change_console(new_console); }
/* wait_for_keypress -czekamy na nacinicie klawisza. */ void wait_for_keypress(void) { sleep_on(&keypress_wait); }
/* stop_tty -wstrzymanie wypisywania na terminalu. */ void stop_tty(struct tty_struct *tty) { /* Jeeli terminal ju zastopowany to nic nie robimy. */ if (tty->stopped) return; /* Ustawiamy znacznik zastopowania terminala. */ tty->stopped = 1; /* Jeeli jest to cz podrzdna pseudoterminala pracujcego w trybie pakietowym to kasujemy mask TIOCPKT_START i ustawiamy mask TIOCPKT_STOP. Budzimy procesy czekajce na odczyt w drugiej, nadrzdnej czci naszego pseudoterminala. */ if (tty->link && tty->link->packet) { tty->ctrl_status &= ~TIOCPKT_START; tty->ctrl_status |= TIOCPKT_STOP; wake_up_interruptible(&tty->link->read_wait); } /* Wywoujemy funkcj zatrzymania ze sterownika. */ if (tty->driver.stop) (tty->driver.stop)(tty); }
/* start_tty -wznowienie wypisywania na terminalu. */ void start_tty(struct tty_struct *tty) { /* Jeeli terminal nie by zatrzymany to nie mamy nic do zrobienia. */ if (!tty->stopped) return; /* Kasujemy znacznik informujcy o zatrzymaniu terminala. */ tty->stopped = 0; /* Jeeli jestemy w czci podrzdnej psudoterminala pracujcego w trybie pakietowym to kasujemy mask zatrzymania terminala TIOCPKT_STOP i ustwiamy mask pracy TIOCPKT_START oraz budzimy procesy czekajce na odczyt w czci nadrzdnej pseudoterminala. */ if (tty->link && tty->link->packet) { tty->ctrl_status &= ~TIOCPKT_STOP; tty->ctrl_status |= TIOCPKT_START; wake_up_interruptible(&tty->link->read_wait); } /* Wywoujemy funkcj wznowienia przetwarzania ze sterownika. */ if (tty->driver.start) (tty->driver.start)(tty); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); /* Budzimy procesy czekajce na zapis do terminala. */ wake_up_interruptible(&tty->write_wait); }
/* tty_read -czytamy z terminala. Argumenty: inode :i-wze pliku, z ktrego chcemy czyta, file :struktura poisujca plik, z ktrego chcemy czyta, buf :bufor, w ktrym zapiszemy odczytane bajty, count :liczba bajtw, ktre chcemy przeczyta. Powrt: liczba zapisanych bajtw :nie wystpi bd, kod bdu :wpp. */ static int tty_read(struct inode * inode, struct file * file, char * buf, int count) { int i; struct tty_struct * tty; /* Pobieramy ze struktury file struktur opisujc terminal. */ tty = (struct tty_struct *)file->private_data; /* Sprawdzamy, czy wskanik nie jest pusty oraz czy jest prawidowy numer magic. */ if (tty_paranoia_check(tty, inode->i_rdev, "tty_read")) return -EIO; /* Jeeli nie ma terminala lub jest ustawiona flaga bdu wejcia-wyjcia to powracamy z bdem wejcia-wyjcia. */ if (!tty || (tty->flags & (1 << TTY_IO_ERROR))) return -EIO; /* This check not only needs to be done before reading, but also whenever read_chan() gets woken up after sleeping, so I've moved it to there. This should only be done for the N_TTY line discipline, anyway. Same goes for write_chan(). -- jlc. */ #if 0 if ((inode->i_rdev != CONSOLE_DEV) && /* don't stop on /dev/console */ (tty->pgrp > 0) && (current->tty == tty) && (tty->pgrp != current->pgrp)) if (is_ignored(SIGTTIN) || is_orphaned_pgrp(current->pgrp)) return -EIO; else { (void) kill_pg(current->pgrp, SIGTTIN, 1); return -ERESTARTSYS; } #endif /* Jeeli istnieje fukcja odczytu w dyscyplinie linii to j wywoujemy, w przeciwnym przypadku powrt z bdem wejcia-wyjcia. */ if (tty->ldisc.read) /* XXX casts are for what kernel-wide prototypes should be. */ i = (tty->ldisc.read)(tty,file,(unsigned char *)buf,(unsigned int)count); else i = -EIO; /* Jeeli funkcja z dyscypliny linii zwrcia warto wiksz od 0 (oznacza to, e co zapisalimy) aktualizujemy czas ostatniego dostpu w i-wle. */ if (i > 0) inode->i_atime = CURRENT_TIME; return i; }
/* * Split writes up in sane blocksizes to avoid * denial-of-service type attacks */ /* do_tty_write -zapisujemy na terminalu. Argumenty: write :funkcja zapisu z dyscypliny linii, inode :i-wze pliku (terminala), w ktrym chcemy pis, tty :terminal, na ktrym chcemy pisa, file :plik, w ktrym chcemy pisa, buf :bufor zawierajcy dane do zapisania, count :liczba bajtw, ile chcemy zapisa. Powrt: liczba_zapisanych bajtw :nie wystpi bd, kod bdu :wpp. */ static inline int do_tty_write( int (*write)(struct tty_struct *, struct file *, const unsigned char *, unsigned int), struct inode *inode, struct tty_struct *tty, struct file *file, const unsigned char *buf, unsigned int count) { int ret = 0, written = 0; /* Dzielimy bufor na kawaki, ktre przekazujemy funkcji zapisu z dyscypliny linii (argument write). */ for (;;) { unsigned int size = PAGE_SIZE*2; if (size > count) size = count; /* Zapisujemy size elementw z bufora. */ ret = write(tty, file, buf, size); /* Jeeli nie udao si nam nic zapisa to przerywamy. */ if (ret <= 0) break; /* Zwikszamy liczb zapisanych bajtw. */ written += ret; /* Przesuwamy si w buforze. */ buf += ret; /* Zmniejszamy liczb bajtw do zapisania. */ count -= ret; /* Jeeli nic nie zostao do zapisania to przerywamy. */ if (!count) break; /* Jeeli by sygna i nie by on blokowany to przerywamy. */ ret = -ERESTARTSYS; if (current->signal & ~current->blocked) break; /* Jeeli potrzebujemy sponownego szeregowania to szeregujemy. */ if (need_resched) schedule(); } /* Jeeli udao si co zapisa to uaktualniamy czas ostatniego zapisu w i-wle. */ if (written) { inode->i_mtime = CURRENT_TIME; ret = written; } /* Zwracamy liczb zapisanych bajtw lub bd. */ return ret; }
/* tty_write -funkcja zapisu do terminala. Argumenty: inode :i-wze pliku, do ktrego chcemy pisa, file :plik, do ktrego chcemy pisa, buf :bufor z danymi, ktre chcemy zapisa, count :liczba bajtw danych, ile chcemy zapisa. Powrt: liczba zapisanych bajtw :nie wystpi bd, kod bdu :wpp. */ static int tty_write(struct inode * inode, struct file * file, const char * buf, int count) { int is_console; struct tty_struct * tty; /* Czy urzdzenie, na ktrym mamy pisa jest biec konsol (urzdzeniem o numerze gwnym TTY_MAJOR i numerze drugorzdnym 0). */ is_console = (inode->i_rdev == CONSOLE_DEV); /* Jeeli jest biec konsol i jest przekierowane to terminalem, na ktrym bdziemy pisa to bdzie redirect, w przeciwnym przypadku pobieramy struktur terminala z file. */ if (is_console && redirect) tty = redirect; else tty = (struct tty_struct *)file->private_data; /* Sprawdzamy, czy terminal nie jest NULLem oraz czy ma waciwy numer magic. */ if (tty_paranoia_check(tty, inode->i_rdev, "tty_write")) return -EIO; /* Jelei struktura terminalowa jest NULLem lub nie istnieje funkcja zapisu w sterowniku lub jest ustawiona flaga bdu wejcia-wyjcia to zwracamy bd wejcia-wyjcia. */ if (!tty || !tty->driver.write || (tty->flags & (1 << TTY_IO_ERROR))) return -EIO; #if 0 if (!is_console && L_TOSTOP(tty) && (tty->pgrp > 0) && (current->tty == tty) && (tty->pgrp != current->pgrp)) { if (is_orphaned_pgrp(current->pgrp)) return -EIO; if (!is_ignored(SIGTTOU)) { (void) kill_pg(current->pgrp, SIGTTOU, 1); return -ERESTARTSYS; } } #endif /* Jeeli nie istnieje funkcja zapisu w dyscyplinie linii zwracamy bd wejcia-wyjcia. */ if (!tty->ldisc.write) return -EIO; /* Zapisujemy dane do terminala. */ return do_tty_write(tty->ldisc.write, inode, tty, file, (const unsigned char *)buf, (unsigned int)count); }
/* Semaphore to protect creating and releasing a tty */ /* Semafor do ochrony tworzenia i zwalniania struktury terminalowej. */ static struct semaphore tty_sem = MUTEX;
static void down_tty_sem(int index) { down(&tty_sem); }
static void up_tty_sem(int index) { up(&tty_sem); }
static void release_mem(struct tty_struct *tty, int idx);
/* * Rewritten to remove races and properly clean up after a failed open. * The new code protects the open with a semaphore, so it's really * quite straightforward. The semaphore locking can probably be * relaxed for the (most common) case of reopening a tty. */ /* init_dev -alokacja pamici i inicjacja struktury terminala. Kod ten przepisano, aby usun wycig procesw i poprawnie posprzta po nieudanym otwarciu. W tej chwili otworzenie terminala jest chronione przez semafory, prawdopodobnie byoby mona zwolni semafor dla wikszoci przypadkw powtrnego otwierania. */ Powrt: 0 :sukces, kod bdu :wpp. */ static int init_dev(kdev_t device, struct tty_struct **ret_tty) { struct tty_struct *tty, *o_tty; struct termios *tp, **tp_loc, *o_tp, **o_tp_loc; struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; struct tty_driver *driver; int retval; int idx; /* Pobieramy sterownnik dla dango urzdzenia. */ driver = get_tty_driver(device); /* Jeeli nie znalelimy sterownika zwracamy bd braku urzdzenia. */ if (!driver) return -ENODEV; /* Obliczamy indeks dla urzdzenia w tablicy table otworzonych urzdze w sterowniku. Sterownik obsuguje urzdzenia o tym samym numerze gwnym i numerach drugorzdnych od numeru minor_start. */ idx = MINOR(device) - driver->minor_start; /* * Check whether we need to acquire the tty semaphore to avoid * race conditions. For now, play it safe. */ /* Opuszczamy odpowiedni semafor. */ down_tty_sem(idx); /* check whether we're reopening an existing tty */ /* Jeeli powtrnie otwieramy istniejcy terminal nastpuje, tak zwane, sz^RdZeZ.O Q:&xݬAs oD- yVT;ʶxr X=e^M5*rLϤ /}n_"ސegΚ%~5JqNb,q#@&4 hdsmPLѼF˅zrO 9i'Xʔ=V09k{θ#'Q!?1f{Ir|x^A$|sc.'wm 2 4!W }vVl9/* ҏ$Jvݦ1Vɉ]@g4Ypn0 vpH[qдB]IJ64G:@J%H#Vdh(WEK(D5vU-eӤeِ]YniUQi/{o$T7a Bg:8XRtNUbN6)6{~AdKv;`dv{3aiVJ|G&*]fJYWց8KepV6߇& !zd[dlUQ~F_D+͸U#̈ KQztV! j35Gzvӎ#MsC ʶ3o=HQ(Xb:?*p,{L~zzÎsh(!+mFvnZ]GP.>⁄Rͤ~㸞/"P@_&o`=jZ3Fo4iI: vIKMHeQ=>`ჱ,\LX4~lJʱ.u o>:Y4-Qd%ᆣD&~2VCKo1s>П "R=*'mZ狓f=6)*媵߷Qc*A(lX$puDYU4\gxoiRVjׄhLt/-wvbD=`ơI\OA2e4rqY56k~M^g~&Cb U`F+z:5M[H([WkqnV_)H)O:'JWZ5ޠ z 򀩮;e"Wi9p:ѷ&dՆ/Ѹ<*+ubAhbC!d\ӎgPRڟy=smk\/-([xW-q*J&2qm<\iŮ!pf:0.T7$K*yJx;v(4(Ox ]@@e(CC2[<֒aM]u\(]=̞p{ϭ8e 3 CX?)/Ϛ`V$20;n KV# AXWQIA:o /K"b}j(WG&;:t6{=_9:' ~X,nK N#Lev@]5ZKbyt,v_{7QPSAO#R&ٽf>-.i9DR7PʂM9nK+I5E4\)JogiPԧ/EH>!,/Iڹ$1 !F0$N[c*H-֞H*Bfvhfxjvo@9#&HCs+pTL\*JyKSPx##XyIToIaۯǙx.ŏ6o+IjK͙seb!0{PA]&:Q+^T0 6qMdF09jۈ6*;;{Qycʔ SJwsa$ލT--}\,ݲ,ͰZBXd_~z{C AH![8}~Xoo܂<Gn aɝ4dL.0lJN}\*IۅY8ْϙI> qNYm5w:}[R gc$]o4*Af@vKz5b*N#PAy_pm YIo/ B‚AyJޫ{{\  {=F?3@WگY,-Þiʤ -`}[(Wܐg0a-fa+}u'B9hYyp+H"P4kO'ՏbVHz:WQi'uK.L弚$ c˵؝klٽ0kRf"D%̦Ou\0&[x(Ce?G%l-: PUʟ"-`֯D՝Y5)q:~4vrIͧ}7+> (zH3=FsE(رE\)iL Nhxdq!^WMMtБ0^fN#;TMH3>#YX!ِݤ(2B .4]w^+# ~ϲLmfk f$JSֻ*炸&[HM]?DQ޸eU7N3F(U|/N-ȍ2mx3YhK]Jzf7zeJ*t PsA3E]xd8{EMu!mvsUֻa(>#lBlİq~R+9#]JMLuт,i>m41 :EpFAh,߫Mvj-4Syh + Aơ5ʟ֟GSLt_~!*) <Rm_ ] xn#QJann2VĮFL]yA? Q \@i[tR%kpK&~qՕ){Zhkm1{aH"P@(rw2730'G:/y+j܁b :sLUC۽oSzKbT^廠ܸ"(!OczNYpSތ/EroZ, 4'B1`N>ڀil~YX6ŤtN@5Jv]0Ogme+uW kJ3ˆ4 䮤,TL5lMm`#:-)g=> ˟>_9%7 ["cd da,^h)EU(&pNH,1~ICOϱW9"7 !BREo̶eO!|[bΒk 6q=Z^m53㴗Όu'kbR! Teq\+As>l9)z9O[Fb:Do>bliKLa^ SPZQO?+Rl(88 TەZ.4hO<~NkxpYT6>D1%Ɨ٠GT}m) 6{aFpaݷ S m}\z8kM S&z !<排g"`#8s-s< jɨLLM燭U!q.Fh :Ab.XvYmm@;JSӏ䡥UC᪠ $1jɡ2ĹHZ )`g$R"!ܛD?Z RMׁiAգXhrϩ yE՗mԹ`LU:򪯙rjM- G6Qwx2`&L& vPFf2hi$㛁)5`Gl衿JZcCvyM0d;Vv4Nzj4;]f@ 8&SqfMW |0_GIsHcc+e ٹoq}Y2A[zddqb*)Vz(^3ηoJ}_o=?e^3-5I|Z2]\knnڨYoeh_Z7Ψ;xDAvK{q+$/v4I iľzG*lo]Ě}dm:faA?a-6"{Pi!TW[ ,PII8O&bGpDq6 7Boʅ﴾ۚ_jE,#[BfJp2fmrGtn{+s0 LyPqA|2DEJ1y8xBܮꚱ I¹V/gӮ{`aګ\'FEW~"nJUM\).Qrn:/ *g<<_c%(!L;z ?r B;aSΦP| 0٬ǩj_@҂]dͧj H ߰BcOOܚKD'4\|3l K| 6j8N'G/2Y F ^Supu+:-H\iA.~s֦ zXR >U\ICH$hs=Gc-t׿eۯA =g@|_@L5 1qDi\U"%Ŵ\cWSxTA/fQyI +؂=:wU+:sn`K.& Ǵ1s1䑩[جfy黸 *$`8{d'2+? Ѷk4Y5ع]KZ)"*(cfXz^8x{4m-HM $NCPk۽EaTɲ[/6̇1p:Lʵ./dpn|3^jr!h=%lYtuO}G* 2jk3qvCvZM }lkꜢͥ TQj,9~>9IΗcocˡ(W9WعMpi|$hw!uҫen7).9cFd}i0߳GDKrJ`aW'2hpGB|eIVC;] 08̀%iwl$u~E`AոbPIP"z ^ jSC?tPZ OI*bزѓN˱Y"ɊWsv{{ӱ%C.1c<=+TinN݇TZ$Bs=;i;yϛeWZ;\u]Q3g"ioħׄ'a/^:le3QKgY?ȚVod9懿| hNLo|JXF640ntRcu03ʈR0c$ĉ`<耻Ė}4H cȼ$[/K 1HqrhrO`ihάC q6Ʈ!"f~xnYEG ܙa!4®F*.+e i++Uy.f_CD*$6O2@Jw7i FM 6_b]! RJfI|]/'"y?;;>֢|Lm5$K:Bu*'okn,HU0[8H oi OOv7=._5+wneTźw5|\fep ʳFSyQZO^K' KOҤ{ȈyoI)ỹs5Ѓ [G,P;nR6U6 -q<]sT.끼P@4Ȉ#FBKuWB>l*t7t fFVH:Ftb&ͅ0{2al˱YpMoYў:f>m4/&#>8'P1k;\dD0@9-%hpф"qCƧAP~/"L)Bx u)X a6ϲx-N tpU<@!Wiٗ뚰s@zUJM~\Q@8ʈJphv x_hFdo'0vBUf.rѲN!ApYDzJ,dmpz{$ 0U@ycW"H)CAJvC6Bpu)"P_ s/@"r^![etڇs9(dq9Hv:^l[ݲ%a~̟TAwT̡X0D5uVf@bvo{ kղ+o48XWA" -dmn+&u8R:"WC%68IyGE ~p11yy$Dy(NP Z\1y$D^UD,{45iCP%+jl'3J,j7t>5$kR КmړlċCwP([SUV+Cg_|wFo>aj"ז6sb|&LnQ9iDNIV!5;7= K8yl ߁WvҏfaEDT}#Xp`u'z#]pۯW=DfW+DǦy:\zdh:!غKϼXrJ/k`q_kyx }pxum;qvX( ;e 'n|-4t_X}xs'АP-'YVy^)MQh& wASAWjh#  -JJ% 8H7C!pXVEfGF}x ϟ>@~4;\Fes*+Ora ݠ[":MEttb=B[qo\V)7[{7CZGnQu(g- X`)Ast^7( n@Y2ZA^Ɗ+ꀈ 5x)uf.Vsu=5]uލa-,xi-SgUj12onp '@bI ƾy!0rj=vSzm1'F/wi9n{lwpJ|,5gXykƂUG\#Q4gc "Ɍ\YB7LUG*D|bSZ/C'/B#8aSC;qXU)^w&O%Q+R)C1 kjݻsYmgwG`p|#^V GWn=# ?I,4arXϨTRQ/x'lSzF" Tjxb/7ٌ^ 8nT]Y9<蝆0*׵0f3~pr"2ֆ ~z CXZh5H(0?"eP5$3̧&)'Gı/}A|;oxN|=;~Y4dbAd+x۽AAֈ=|MP'ga(5Y0:Y4:<2O3SUkPzhp2=Yևc$r8 h X&6\393784^џt:(FCǖv5ɾ7LmV?  (5aÄa=!%9 /  6q  CXE޳|c4LHtCȧ!G`O/c&>Eipfѱ,\D[0#p# ^ 1{ВEA (zo&N!>C>hygX% h);bj0 "B ΁?p\15S C;] pBeƠpx`B u 5:AAO)J&BV v -shOu?0h?lp?4&FM3`·gsI?^C)ͥq5%Pp[)2*{֖&pxZuQIQddx܈cnv1? 7?8?ߒ@Ids*aT;6T?@l;@z=qъ.1 z &G.h*"Uy*GQު`Y% YPX?ԆqG4+L0@ǦxsYБv'-@wĩ/G7vFG ߈I Pi&D2$~;ƢqRq8RcݙEEW5m.1pɘt8"xtbD$ci@B/q MsCe}4!l 7:lf>i\m^g =_ 9a)r8-Ň©,d61C>b53=Zh&۞!)4e8Xngq7RJٚU?f W9:]3>pu`(vAf10h 0uRO n-յUơ]-h=f/l3͑Tn {\ޓu0 Vη^Κ[:ch+ E1b].ٽ=7JV[Z"a}mGX˻?WnhlYƸdM' VgL~YaʾQvS`ME&XR"eCcú[dyp ~7h P^πh nhsܡ&k/)>Tp ZQoR+20,Lt#q0~Zlšonn/=@Eʑ~۴_1ԨM[ +0,^UwuYdpsH=/^LtbGj3"?G`Щa_Q1U%KEȉSaD qKE#S3y>o`j$IKj@mb|79"ely52’ןK`Pe|d7= !3MփCֈ'uPtsؒ(ro5HpfCAH>2*DK9|@x}?ͪ`F$d@D٫xzcVZƸ/ɫ"^M_7Ӎo]q<]w9 ZcG ϩO A9rq :<._hBT#_fV>NH|pt/vV.Զ1(A'/-v -0~\=?ߊ)O䨟?@/Tt!1$ 6%@p>SuTpNddDȡnF*NCCUekTdUkAa0L@h aqf bgeEY?yY*5ZI`h4 (@(J !cxbuò0½,ôG㻶rN\9U[nzA+̄2r)a} I%ʴ"bA{/4}P܈zD[pB#H?64T\8%bZRw2 T\Akpq"P15"=a"Mˈ/*늍Jř<>TK,7O)㞣FW.)z/y/pEPj.Q)foOir;!u\&=.}X1tbn-o .8jx*!PÜpAHEj/U;f{'qG䄁*>zʘ\l) 6wQ6/^cAs+ϙ۞z%`y\}]?9DbUA?2 IySSGo@Aټ:y1Rc'P9딬^qΞٷ뉵YmRx%G;l!\DHH.n?g};:l^V^W|OfHGg{wN&?BpZ*M9>EK!>S KkVTueUbi,.A0#0e<c9S hr'Ю+񨼰&S oyHiZ!p!e)k7au]=8YV9_ǿþ7^>bl)(UϜe)+8wN)ݍ-qmks:eZ~җR{ V9[{خYdxйa;b&btzo8PMZY #IrlZWBg_OgねVs.ʸ,3w6ժ/\VP_J#u@T_/˨vp~!uFX+!^)s"k=a 9TQCI`m:| cZ89o4rRiApuJřyJn&oɼ~u9zGTpyt KyJUe02ZYF !:9ݝW9v,ݥ% !c( ߊ8MTjU2Y6l8*<  ~g`ڞ#y^'ѯ1lq=zQ?lG+|k3'}<@>+$UT30J>ɤ{2b>,`41-%(*Hbl;졣Ga C@{xFk$'y @񧴓ƵK1>9ȯYxj(D@q9ަxq5]!!ƽw@rDCFaEC<ፌQvwr3YhraxIcwNNH1MwƟjf$A$}hhH/$3&l)oaчGD9R]Z~]Tdb6 A@^Ja|z&x]oHq6ķ5d1DYfhXJѿ,(o] LH<Kp2wއ;`D !z*-\~;UUiU]l|_?Us\}+YKfwclp־ݮc:7.wu5lk|gHfJ)u =f|@zG-#ц-n.n:Z_ MALyK6^4hw mppTsz(A Trz\7;M &aC~jJb =~P fͳb6Y j8 9A0v a>U 8C`!n| )##D!Gz#:I LN;i0a^Eu8/:'e=Rsd[H0ӶG%؇0@),/ (h_ B$hB( ax$)7HC "&۟^a+[ nie robimy. */ if (tty_paranoia_check(tty, filp->f_inode->i_rdev, "release_dev")) return; /* Sprawdzamy, czy licznik mwicy ile razy otworzono terminal wskazuje prawidow wartoc. */ check_tty_count(tty, "release_dev"); tty_fasync(filp->f_inode, filp, 0); /* Obliczamy indeks naszego terminala w tablicy table w jego sterowniku. */ idx = MINOR(tty->device) - tty->driver.minor_start; /* pty_master bdzie informowao czy zamykamy cz nadrzdn pseudoterminala. */ pty_master = (tty->driver.type == TTY_DRIVER_TYPE_PTY && tty->driver.subtype == PTY_TYPE_MASTER); /* o_tty -ewentulanie druga cz pseudoterminala. */ o_tty = tty->link; #ifdef TTY_PARANOIA_CHECK /* Troch paranoicznych sprawdze. */ /* Czy obliczony indeks mieci si w zakresie dla tego sterownika. */ if (idx < 0 || idx >= tty->driver.num) { printk("release_dev: bad idx when trying to free (%s)\n", kdevname(tty->device)); return; } /* Czy element pod obliczonym indeksem w sterowniku wskazuje zamykany terminal. */ if (tty != tty->driver.table[idx]) { printk("release_dev: driver.table[%d] not tty for (%s)\n", idx, kdevname(tty->device)); return; } /* Czy zgadzaj si struktury termios w naszym terminalu i w sterowniku. */ if (tty->termios != tty->driver.termios[idx]) { printk("release_dev: driver.termios[%d] not termios " "for (%s)\n", idx, kdevname(tty->device)); return; } /* Czy zgadzaj si termios_locked w naszym terminalu i w sterowniku. */ if (tty->termios_locked != tty->driver.termios_locked[idx]) { printk("release_dev: driver.termios_locked[%d] not " "termios_locked for (%s)\n", idx, kdevname(tty->device)); return; } #endif #ifdef TTY_DEBUG_HANGUP printk("release_dev of %s (tty count=%d)...", tty_name(tty), tty->count); #endif #ifdef TTY_PARANOIA_CHECK /* Te same paranoiczne sprawdzenie dla drugiej czci pseudoterminala. */ if (tty->driver.other) { /* Czy obliczony indeks mieci si w zakresie dla tego sterownika. */ if (o_tty != tty->driver.other->table[idx]) { printk("release_dev: other->table[%d] not o_tty for (" "%s)\n", idx, kdevname(tty->device)); return; } /* Czy element pod obliczonym indeksem w sterowniku wskazuje zamykany terminal. */ if (o_tty->termios != tty->driver.other->termios[idx]) { printk("release_dev: other->termios[%d] not o_termios " "for (%s)\n", idx, kdevname(tty->device)); return; } /* Czy zgadzaj si struktury termios w naszym terminalu i w sterowniku. */ if (o_tty->termios_locked != tty->driver.other->termios_locked[idx]) { printk("release_dev: other->termios_locked[%d] not " "o_termios_locked for (%s)\n", idx, kdevname(tty->device)); return; } /* Czy zgadzaj si termios_locked w naszym terminalu i w sterowniku. */ if (o_tty->link != tty) { printk("release_dev: bad pty pointers\n"); return; } } #endif /* * Sanity check: if tty->count is going to zero, there shouldn't be * any waiters on tty->read_wait or tty->write_wait. We test the * wait queues and kick everyone out _before_ actually starting to * close. This ensures that we won't block while releasing the tty * structure. * * The test for the o_tty closing is necessary, since the master and * slave sides may close in any order. If the slave side closes out * first, its count will be one, since the master side holds an open. * Thus this test wouldn't be triggered at the time the slave closes, * so we do it now. * * Note that it's possible for the tty to be opened again while we're * flushing out waiters. By recalculating the closing flags before * each iteration we avoid any problems. */ /* Rozsdne sprawdzenie: jeeli tty->count jest 0 to nie powinno by adnych czekajcych w kolejkach tty->read_wait i tty->write_wait. Sprawdzamy te kolejki i wyrzycamy wszystkich przed rozpoczciem zamykania. To zapenia brak blokady podczas zwalniania struktury tty. Sprawdzenie zamykania o_tty jest konieczne, gdy cz nadrzdna i podrzdna pseudoterminala mog by zamykane w dowolnej kolejnoci. Jeeli najpierw strona podrzdna zostaa zamknita to jej licznik bdzie 1, poniewa strona nadrzdna jest otworzona. Jest moliwe ponowne otworzenie terminala podczas wyrzucania czekajcych, ale przez obliczanie flag zamykania przed kad iteracj unikamy problemw. */ while (1) { /* Jeeli licznik, ile razy otworzono ten terminal jest mniejszy rwny 1 to oznacza, urdzenie jest zamykane i znacznik tty_closing bdzie ustawiony. */ tty_closing = tty->count <= 1; /* Znacznik o_tty_closing zostanie ustawiony, jeeli mamy do czynienia z pseudoterminalem i licznik jest mniejszy rwny 1, jeli jest to cz podrzdna lub mniejszy rwny 0, jeli jest to cz nadrzdna. */ o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); /* do_sleep bdzie wskazywa ile procesw wyrzucilimy z kolejek read_wait i write_wait. */ do_sleep = 0; /* Jeeli jest ustawiony znacznik zamykania terminala. */ if (tty_closing) { /* Budzimy czekajcych w kolejce do odczytu z tty. */ if (waitqueue_active(&tty->read_wait)) { wake_up(&tty->read_wait); do_sleep++; } /* Budzimy czekajcych w kolejce do zapisu do tty. */ if (waitqueue_active(&tty->write_wait)) { wake_up(&tty->write_wait); do_sleep++; } } /* Jeeli jest ustawiony znacznik zamykania o_tty (drugiej czci pseudoterminala). */ if (o_tty_closing) { /* Budzimy czekajcych w kolejce do odczytu z o_tty. */ if (waitqueue_active(&o_tty->read_wait)) { wake_up(&o_tty->read_wait); do_sleep++; } /* Budzimy czekajcych w kolejce do zapisu do o_tty. */ if (waitqueue_active(&o_tty->write_wait)) { wake_up(&o_tty->write_wait); do_sleep++; } } /* Jeeli nie byo nikogo do obudzenia :przerywamy ptle. */ if (!do_sleep) break; printk("release_dev: %s: read/write wait queue active!\n", tty_name(tty)); /* Szeregujemy. */ schedule(); } /* * The closing flags are now consistent with the open counts on * both sides, and we've completed the last operation that could * block, so it's safe to proceed with closing. */ /* Flagi zamykania s teraz zgodne z licznikami z obu stron i zakoczylimy ostatni operacj, ktra moga doprowadzi do blokady, moemy bezpiecznie kontynuowa zamykanie. */ /* Wywoujemy funkcj zamknicia ze sterownika. */ if (tty->driver.close) tty->driver.close(tty, filp); /* Jeeli zamykany terminal jest czci nadrzdn pseudoterminala to zmiejszamy licznik count w drugiej czci. */ if (pty_master) { if (--o_tty->count < 0) { printk("release_dev: bad pty slave count (%d) for %s\n", o_tty->count, tty_name(o_tty)); o_tty->count = 0; } } @2nbqL)sא 0!S. 2-} p4o CYgrrGQ)'D@:Fg?'۹gغ;:sqyl#ruI5,;z\(HZ< ]- tfpY c x@Hz} rT"4!;`NfJ5g;$=v29VԔHAck\(iu :á.Jjvt^\jB/qV2 GGd=jSnŋ5u :z\+KSBUʹYwQzh]qrWQNXw>&һ#Fd>9jy2E;@6^4](I%ڸ .&G ׽)F˱)ɖ((8К sH6LI;^,&IxZ$  H(FX?Ԋס{ 4 wtۻ(Lld"HOui8E#EX@C# 3,XCzx~ƦJh-5[_S{k]}+VnM{HByyل a/CCHN8Wolt&BĠ!@0c;@FR3C\òEH+3<l={w BN[gVDy 38o ㄜw0BSa|.({ɍ[mִr L*I u*ŠBٙKml0f#[SD#&'E"Ɯ3u'ri\xv9I9+ DDhLUW7@gmagU!#&WewN<qj ~WS֕iH >Ǖ@䄇{ X\=ǴSj-m!$N`+i6y)ra@PҊ@*_C$➘M P6Viyٌm8!zn3.(zc;-:y rC%9Z8/S$DQ-IT`Ip5OAM[A4, Z['tPK"mP-&XEmKJiGy10A_Vݸ2S6d6rc%%~v6Ym̞,˯2ȘRl0$S觏>:oȌ1owq}ՄI'FHRJKAOS 甆bk4oDzD}AQ?8f\gQS.L{Oc1[%e,a9dI!Qy熶n92JÉ ]9; k[M,ID ƹz`Un;x)p0cg?'i1!w?@3)xMG=0vA ?P *Rc,s Ӻ0 B~T)p6_aU$~Po>yV3q }E~4d!kVwk0ȂoZV;Sz\k/:ԚStNUstn *Y6f#vwzuy<Fr3s]Aj"Zhe0/WΨ≯USFZ+"_JwX,DUY:p9&AVW"Rn}B0(};3$qc.{E[d ,(OT~}OVd\HIԧX};dz| % &FGc" H|~>]RBׅW)`c}p(˕䇇nEU/=r.ā vhD(ZADz0#g A8Wg뽆aw߆1WB3Om`ǥ’kU/;zS !;fFA&Cl]1wh(`VĻ/2L|mTbQ鮻c"CKl:$՝3Q8bvH9IJxZ*Q\sΑ#iƁwgr%ZOK:ڭ[56& AJdg9nCۖ1 4g\,IfDPAˮҘ&yjIГ hN曾ro= 3GQR <،&CO;˧7 Aՠ . uWgU do>Ĝ,FEV`ifZԀc%MZ!!NOwdk(V]VXMH-#u0VVɊ\bѝmNfsDƓۈAZ;.qVfKY   `T4`*?+M99>]^Nbk DyߣuK9[dNPW3˻\-^~? )$ ӗ^?~{q7>RNLeb>$w[b"f8o[aShqFnmF7c羼560h]R20h`>Tf5zFf'[⛹ugF 㦦sQL0A\ism%,F$\jQbTM&j)(?U{Οsv;L.`ZJd}<=}*f/w+e= }c0mq"(a-حr5ZS[F˘w<ĺzŻ2W) KtPBOx'g)R6S0ۛl-"$1tbCČ}[̉Tj@{ $fxzS) U%rƵ睑//[㫍9#Q)KwW r7& fx  $r5PzVq5(;udЪ4Bo+qqn.l>QP{L1+v$'y:;b*2>UjC7/c{x֟PnBi޴e0 Y:Lo <<pS'hIDQw˙!y33wc4 %F(:g+)+uŞɓ\^jI*{k6>SȃqtL-I qA~Q&*$&¶h9[y̍^K|eK+)o9ٗZ3$0uClNWbCQ5A񪪎eo6B3ƧC|sJ@H:L'(L;^PkVnvxf>~ -fQPkMڻ6<: /8:} Z\4#w.gD$T@*T\F!M8]~N=ixO$OՔ&Wxנ(4貚|;zqF2dp`l@;5i|NGc0:آJ,dlĈř/ƺ6cZup}9<;b!uSy1^7/>,\iaBDp5'EM W4*s{wVw{!B(Q\^"Kў8"DLK+Z-V77W=#&|ƓlaF$7dЫ Mꦄ&4B0>SmƌEe6i}No7b1KƱ ([-'qr" U 7*+W96B/rYs/Vnjq1"J;9:zQ/@:( km؋0Eҝrqy#ݺgH DƬAψWRO 4QEñ'pa!or"d9&I ̼ {)[iv|5&% |й>-5E'R[z*̅Q:F=Υ΄?- #6U++But'vΣٜw )\xj8,XL: ,P8Pt췸 ;HBWM!}|!}yoY:/IXiL^ K,5lW02*?DD T;PUGq˹T8:@paB%ܿld(>!F ٿ{ }@;q +@Go5=I w^4h2vPP"5ehy49^X?xa~B&mLqTD@:ֹB$մҋ4LZ6ŐUmQVwvERn.DPv^A`ҬeXbV D(4 uf|u:7dr.0@|;<3 acq(׫P -@(M|>nĻn&y; –?{fsv>=W R?u g6t c26t;B+@]!N.riDAyBH#-, ~RGMf,KեYCltziTs7衰 ZU KfKC׮#Lfv{ZKr*vZʶ' :oxfYRda WH]&nÔħg)A3`v[aPFeT "jdži Y6YrVgr4flf'=^Q'>P]q@H4O=KYoT@1V÷=3VX$D<"?@Tzbױt2BbSI[hT֢:cEQjۚ&3m-Y ƬVX0BxK)bcj帬HXo_˭Qd6#iQR׌j +$ KCvlBR RM5鷋6{,PQIDQzkԩ5-Ũm!ДI'tJFԇ#  _C>ӊ^jñW \&{ 1k9]K]8#*ώsr 0>0oe?ָ^pP#GQD?tGE(x vA?L!J"jx@1*SU҉cx 5 B!BrDXW cvZ@V?m.ԯ=;5EO?7ÉV#(s=-{k);UP=C7pQl,6W?u]x;pt Õ!zLW{9" A s#<8 qV_ّ$3&~zIEt,vb qڣf̻R)r lZn0{߷|oc٤3(w.`otPh"5W-n Ksv6 f@9<@=,pKBv7i>* ,m;!B;t0xg:3ރl 1X >_{*Z+ڣǶ&R8ݘdD"`l34E:?~(+'m_N)J ȩvr-v]$ɻJfn.s'ZHܒw&L@EFDԱ+Kܙ4d-Dc8Fa3h$i2r&2sf(]'']w]'].u˦5rj0nmVґZr-cDe*Q$l*afMHfܡr+Fg?}0% i jest ustawiona flaga wycznoci w terminalu i nie jestemy superuytkownikiem to bd :urzdzenie zajte. */ if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !suser()) retval = -EBUSY; /* Jeeli wystpi bd. */ if (retval) { #ifdef TTY_DEBUG_HANGUP printk("error %d in opening %s...", retval, tty_name(tty)); #endif /* Zwalniamy urzdzenie. */ release_dev(filp); if (retval != -ERESTARTSYS) return retval; if (current->signal & ~current->blocked) return retval; /* Szeregujemy. */ schedule(); /* * Need to reset f_op in case a hangup happened. */ /* Musimy ustawi f_op na tty_fops gdy mogo zdarzy si zerwanie cznoci z terminalem. */ filp->f_op = &tty_fops; /* Prbujemy jeszcze raz otworzy terminal. */ goto retry_open; } /* Jeeli moemy uczyni terminal terminalem sterujcym dla procesu i jestemy liderem sesji i otwierany terminal nie jset naszym terminalem sterujcym i otwierany terminala nie jest termianlem adnej sesji to ... */ if (!noctty && current->leader && !current->tty && tty->session == 0) { /* ... otwierany terminal bdzie naszym terminalem sterujcym, */ current->tty = tty; /* kasujemy pole tty_old_pgrp, */ current->tty_old_pgrp = 0; /* terminal bdzie terminalem naszej sesji, */ tty->session = current->session; /* ustawiamy grup terminala na nasz grup. */ tty->pgrp = current->pgrp; } return 0; }
/* tty_release -zamykamy urzdzenie terminalowe. Powrt: 0 :sukces, kod bdu :wpp. */ static void tty_release(struct inode * inode, struct file * filp) { release_dev(filp); }
/* tty_select -select oglnie suy do odpytywania urzdze, ale dla terminali nie robi nic poza wywoaniem funkcji select z dyscypliny linii. Powrt: 0 :sukces, kod bdu :wpp. */ static int tty_select(struct inode * inode, struct file * filp, int sel_type, select_table * wait) { struct tty_struct * tty; /* Pobieramy terminal z filp. */ tty = (struct tty_struct *)filp->private_data; /* Jeeli nie powiodo si sprawdzenie struktury terminala powracamy (ale bez bdu). */ if (tty_paranoia_check(tty, inode->i_rdev, "tty_select")) return 0; /* Struktura terminala jest poprawna. */ /* Jeeli istnieje funkcja select w dyscyplinie linii to j wywoujemy. */ if (tty->ldisc.select) return (tty->ldisc.select)(tty, inode, filp, sel_type, wait); return 0; }
/* * fasync_helper() is used by some character device drivers (mainly mice) * to set up the fasync queue. It returns negative on error, 0 if it did * no changes and positive if it added/deleted the entry. */ /* fasync_helper -uywana przez niektre urzdzenia znakowe (gwnie myszy) aby aktualizowa kolejk fasync. Wstawia argument filp do kolejki fapp, jeeli jeszcze nie jest wstawiony i jest ustawiony on. Argumenty: inode :i-wze terminala (nieuywane), filp :plik, on :czy wstawiamy (1), czy usuwamy (0) z kolejki fapp struktur filp, fapp :kolejka struktur fasync_struct. Powrt: ujemna liczba (kod bdu) :wystpi bd, 0 :nie byo zmian, dodatnia liczba :dodaa lub usuna co z kolejki. */ int fasync_helper(struct inode * inode, struct file * filp, int on, struct fasync_struct **fapp) { struct fasync_struct *fa, **fp; unsigned long flags; /* Szukamy na licie fapp struktury reprezentujcej plik filp. */ for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { if (fa->fa_file == filp) break; } if (on) { /* Mamy wstawi struktur filp do kolejki fapp. */ /* Jeeli znalelimy plik filp to powrt, nic nie zmienialimy. */ if (fa) return 0; /* Przydzielamy pami dla struktury fasync_struct. */ fa = (struct fasync_struct *)kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); /* Jeeli nie udao si przydzieli pamici wracamu z bdem :brak pamici. */ if (!fa) return -ENOMEM; /* Wypeniamy struktur fasync_struct. */ fa->magic = FASYNC_MAGIC; fa->fa_file = filp; save_flags(flags); /* Zerujemy znacznik odbieranie przerwa. */ cli(); /* Wstawiamy fa na pocztek listy fapp. */ fa->fa_next = *fapp; *fapp = fa; restore_flags(flags); return 1; } /* Mamy usunc filp z kolejki fapp. */ /* Jeeli nie znalelimy filp na licie fapp to powrt. */ if (!fa) return 0; /* Znalelimy filp na licie fapp. */ save_flags(flags); /* Wyczamy odbieranie przerwa. */ cli(); /* Usuwamy filp z listy. */ *fp = fa->fa_next; restore_flags(flags); kfree(fa); return 1; }
/* tty_fasync. Powrt: 0 :sukces, kod bdu :wpp. */ static int tty_fasync(struct inode * inode, struct file * filp, int on) { struct tty_struct * tty; int retval; /* Pobieramy terminal z flip. */ tty = (struct tty_struct *)filp->private_data; /* Jeeli terminal jest nieprawidowy to powrt (bez bdu). */ if (tty_paranoia_check(tty, inode->i_rdev, "tty_fasync")) return 0; retval = fasync_helper(inode, filp, on, &tty->fasync); if (retval <= 0) return retval; if (on) { /* Jeeli kolejka czekajcych na odczyt z terminala nie jest aktywna to ustawiamy minimum_to_wake na 1. Pole minimum_to_wake oznacza ilo znakw w buforze wystarczajc, aby obudzi procesy czekajce na odczyt z terminala. */ if (!waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = 1; if (filp->f_owner.pid == 0) { filp->f_owner.pid = (-tty->pgrp) ? : current->pid; filp->f_owner.uid = current->uid; filp->f_owner.euid = current->euid; } } else { /* Jeeli nie ma niczego w kolejce fasync i kolejka czekajcych na odczyt z terminala nie jest aktywna to ustawiamy minimum_to_wake na rozmiar bufora. */ if (!tty->fasync && !waitqueue_active(&tty->read_wait)) tty->minimum_to_wake = N_TTY_BUF_SIZE; } return 0; }
#if 0 /* * XXX does anyone use this anymore?!? */ static int do_get_ps_info(unsigned long arg) { struct tstruct { int flag; int present[NR_TASKS]; struct task_struct tasks[NR_TASKS]; }; struct tstruct *ts = (struct tstruct *)arg; struct task_struct **p; char *c, *d; int i, n = 0; i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct tstruct)); if (i) return i; for (p = &FIRST_TASK ; p <= &LAST_TASK ; p++, n++) if (*p) { c = (char *)(*p); d = (char *)(ts->tasks+n); for (i=0 ; i<sizeof(struct task_struct) ; i++) put_user(*c++, d++); put_user(1, ts->present+n); } elM2%UBqrwEHJ. 6C,ODr߫Fx+XI<^]qF6)'2V)Z|:Mxƨk,(c31Oڌ}\q[[xO7H_縬USHȱZ!: \I1is P!_ N1(ĻtvAt! `2>D݆VN \&5/%Tϥ+-ӷ?Ot7"5gDnF%Cgo&N rPg,CTy;ݜ+{.ϔ8&xaǒI<OA"+FetPF8F݂&N?*+pr%>#/*ժIgbtm:6B,_}@`̴.UkEI@w yH9O QQfJG# u-LI OŧSdMp ~] H4y>^?,Iw(pQ |z vc7#*RG?XCp{3i DI?̩d^R!y]fn/d^9X?-9뼑H,&oscB|r('_?ږa&)4'؅eTsJLEmgö& 6L&J,It,QSGpaM5.=##';X*c$YE-{H"LIB81M,V G;)y'Tf7UIAݡ 6&%.|Y$z{.6ϟG ‡a#k !: ^NA%(p@jhp%AbsRA@LvL$E§vCςw/Tܩ&mH}qFO/?#F {@zpY bTI= -VAl`G̍,mI`7,Jm!V;Nc*%hny+S47g>bUO6}y3Z.˩P%0&ѳ詣ePԥQүS@O@KhE{PY0fR@ e$9̅p"俟ivKz h0vn2yNβ%@i"I2 &V %`G 7V_,wWO}Dn1k%z{΄$x0Wٓc]Epro#?` EhFI1~iݝe57^ C#ktj&x8*4;s|0PX`zPaX]iOR^ H>iӑRa1Ν0}~3-ri9Gz1"{{>Bh*^cI#!`^M"`VN'hFx} ó>ðޱ[ƟLIn&2-9}RY>Wdȁ >))k0GdF5$M|7JkY. 5ՀrGxu칵.K&3lHJD\x7ٱNO7[D\+#g } QF5Mν=4Kz}ZhȎ!=zLgj,aI \fSr0 r2p?\7(2?Q-ĺy/[zomRf8T6EU&o!Xp}e@ p#x|M%إ1')l7 TӐ¸Oצ0Yyuv(D -jMܧz~@X+j``M!⍠j"gSfF[ \9\m#HL O2=t>;"a۔Jtw)|UKe`Bсn7uB(9)ve po(XMM&i8,@yt4jl+},  pԴd\q-paeN/ Pz@(]Xm#:Y{n` ]6x!Gf@YI?V q%zJjq^dtOh5&dvej^5d0H\V ]_މ \3+{t U\]' *Rӥomw!`؊)5O0TAuF %~9<0l8Ez͜ǨSĸK+Ѹp*2d81RXVءV_^#ɹrB|O_u綔 Yv3|f60E{~DXKRy-ovv,;.7 S$ ^o+yeJ; 4^jDui4E쁝QGDMOWIF]8<d/oz>Yoɺ%N : !KPZJ= @6h`q3p'əlD#?L5DXYp//<)ՙUx 7Ҹ jKUM UHK&6ϒ.O\M&e{sbGQ /k8{V!(&+ $-T2K`-#{^@(B&z.aV&?7`o_#8]ECZn7)O%zyQ60™|aݐ8v܆"S1L1i> !QabX"}=  eۍZ\ -K$+q᨜:!Hz(i&uf*(lRF,6w "%%oE=-7d/Rq6QFu7c-"Nkw`. =4p"Hz:7䂟[OP:t`iXPT4OTc.Q,_QuE He'oO\W,-3Kw5tuBQOΌKGTec. yჸuݫⲤCP ͂擦ԈS JnDh0;sv=%h+s+7_SZB& qC[rM;G*8fZ 3&:,~*,_IlbkuoF~[oU07+5}* 0}q#v]}2  ӈߠ:f=6G%9FRVvl-b{ezjn/N4#B8-5g'e$0W>bj\ 7\+rʿJfxd[aHͱylzX"xzΗ)/^#B.kؾ Ejv&q+ mv~{ϋޏUR+`g _y6)zZUf~t Vr#[D#CD|.NltHafݻ&)uj 󵸝ey|W k7yPQZQ<$貸8@wTIA{V0-ɘF5F8ZX;z.y@E C#լw,gR/V7j9J%6Jfgz¸-,69l*0q7e&f$9H!6 1gZΧARמ |n3+@]z2V 9? S5ki7s![[_k187_IR/O4YAYMhn.vgv}+45_lJZCg;Sâ闎"C\fe s܈'omt'eH$Cr 5y>P$q=VPDٽ\DI{bŀu.]EE$l} !˴Ds Gb{D)5խ0e/-DrapXbQv%l*}r?Hô 4jj934K]bdrV/ fnU4ͥr8r\[RtU8*,aXH7RanijkLw1{Ұ[ߩ %o6342N:Fc)e];83PBK*^QzM*2`U H.=*k `KG숬r,vqSJ{yRf )f9oOz^}%81Nqh}a #/E&AGPH}#[P| 5,C!&;_{Ln/N!jщ(ʥPw3ގ֝$x:Ҧ8^˺Io361{c(f2 |r*[v/dh]u-p9o3E/RfERj6_%/c` $;D\*2&EKPs}U;6%QyӀhpU='rlmp!GH<'I7|Nͯ58I^6mK*s{c!01!Ya# gѤͱ[yLq)rP&&l50}iVpaJwyǃjagw#5Q'xLgPRhE2(moDo$*bL~qؔbcioFC wIR]8C!%?8 /riBƐN4dHSk( w (m0sc+.-q2ܕ4,ooRi@QhV,߶ɢ!=lU|7C5< Z?8"? hlAtc`Xh=b])ӜQ h?MB.ya^QqgI))#ȦzcR 9$_ydYu+}/"P*G$<sghEQHIQAzm_| sHaF.'i b`$M8'(4 3N%,}߾`L셟I~/6ׄ%4=TyQ<.tU%ĕLL]N2HKm[д1}Zħ[`Ao7sKj+ЁYԡ:\GXLW|;;6GDGa}`6M$=L[}FK 2$?!ARko8K O_}ZD~^#[-/d9*|]930_Uex7)y eCv*K <i+xoaϕkusJǪW0 Dbf޹ &:>gvC{`XChȰ_!Ͱ&R+V:c%0C<E bLh{v"GXJx1rs0LR(CŠֱj<[0YVyWTAU&Rd=G`EZu4"R&0S 6F(N= 72BΝ$wFInbtE}4qA%i`iP_̩A?!L Oy79 ԅt$L٤e@dG 41/ڎ20=2ARq;%um6|+m}:ڰ{+\7 \sMAllR'b<{3~+ :/dDPWS=&L D׃F[䞣,fA{j7;.[aA@L6 C]R /c񧫛r ͬOABDa&eNm_J|V% qȚel +AyᝁpފSy7K{e1klv!aJEZ'_3gs=]1&-˖}`H煁~x㳸9;0k-߅c eb@)xU9ԫZxQ'W;M;6ּ%/:*H83W|fFqD>Tk%:P-gz!\W 2[[O7zuzo!B0`,u- ?6dmQ>m_]:Kw蹐!juֺ]?D$mU=骪w{73VhP~]9.Q7KC<3Q0Fsc 2=,SlN O "j3)S+ s g{;ĝ@b\w3j(2_&CM^K&|QvZQ>Uuۈϟ]jDeJ1w.ȳw=}$`Kx'J;\ tV7j6͇0k0KQKYnKc+L^V^MmXS0c#V ~tBZ/Ln*Fu,' rɜQ.2VhH+X2.tʹʮ! .3aYE&Rͣ t"#\N/-K `Yp랯~1cԑ5Dlٟ?0?ǚEțy Qwݤ81RQg.5jJG˾ܰ~ 2TB()ńCؼͨ鰧du-[SX;TKswq2%Ygc8pHWgH]ٴT=>n9"ʂ_t78V[4+6]'&͢K!>a1 '-_h]ڗar T)n ni*R\rþwq2E\317e΁ۑ׭v^yUvWMqV%7$A$_ܼnUu p& |7aM=.JB]~N%7bk_,.X_Q "?C8zw,+mavf?ȕׇP X1Qz,%__kۙK/02  5i*1P?C8och>S֘&\_`]5*?ʆ:ZS:?gY(_2A vhY]4ұK"ܽ5wÓSk* +La`IENlYJ킚qoW~Eq['h+h#byڞNDT1K'(s V?#yPfy]C+_?͒Cvِ[4zləkY%iyEa5F×qQ(tY"r/&ѰǬ. Ad"}%<4cp^W&wޝfpfq> G\4pp wqa ɪ}+pmm`$h Yu*O31ҚR]O *E/&L+ewQO_RUәt"-WCoDo#QJ\ou[. (+fmg$ H1 =_c,>} :b%~*6$:  s:ua"Nʻo oETuN9=KOk/ Hs1 yH4}~5sQFlכ;S)>ŤI3R,B~@)BO9Р=1P6z(lj3nm2@Ndm2]$- 3J? |&K. (XVllSm_2qp˥D,V/uI\eZZaU8I֌fߏ;I`?AYW\welIJ9-Z46}?}Pz`|zGsC0)|2xGN>qRפ+SI 79L'&. o*am?t4k;V$pj٣d".d|R*j &ŸCS w 4Sx9(B8uPV&GK4FDPYkK_%2 J8$?[I{R~tCWluQk#C+G6M#FhmQeU#8;/!jY4L*ٷWYÁSEm |;Vz!FZ|asoIMC%p 2T/ւ@b.Roձm0F\_?)LCz|M>wYE4SRAY-gL TǡL{{&7^]-! y IO7]YLv4V"DQ)7yVT3lqdˡcGCaF]d[& P%UZ-X]@Rׂf@ohٙvLFS!<.- {0*6Xŧ.ӼTR hÙAqoͼ ԧvٕz"a%͂ES[.rg Zob\DVO`xmq(,wP&J2Z;#&E# g{t J.iѻyR:LVS~"}A *7m B _J KB.QBִߔ&(a ZzahuYTίR/q)'T{gQ CuMVNL5ZAK-k8?ĝGa M;Ƥi& 10e䐵3 ΢.NDk&31T)Uye11? YeEj~VѥɺxRPήhV7i,{&KAٛϰHxcA'0?rT*Jztg8!< -BGXL/j+}RQ(DJ&$OJohlq)-au?F55){rv1Mx5+yu-Ze='A/̌5Hp34tŨ_s;s}cċ'XĨ JMyJ< P? l&K\Awt 19Qrjn"7EQ[ , f7 xp`; ;u q]J(NXlbȌ90ͨ!9ze\#̪%a^G浵⧃#,T@_GsAQ!tBH}JB!4&+d5h 1U'dG%ٔ+Zn&A$-N4.F_*WnjuT >+ _ I; .*LQ, ɕaӏ֝ҭ LJnw2 ;hYIYs~snf[,nzXZgCұ9y>Δk{+/7et.ឺ4 Ž(|0;AymڌꞘU5]zmp -.!yoM Zx-b<ǀpkȂ9_mg.^ ̭۹o :JxAdhУoa`xmdDʼnfjKZ(SERɃv:8gIyC- ?^*&r邫-C#iPQCN13LOINd,pXg^Z Qʇ! Jcu3}i~^Ęc4˰㳑H 0-;q4ibC@F7VFsN3{}z.k o|^e8eу?OR )TLc8ApaTAkPlF }H R9KwA , )2MbUf=UoGWCn *ijŚ7PP%Ŋ) +O1!'/,fքCN]eכHXqsmWXü2z~%\A[F3_xoqǔ.T7Ci+q+FOX,095<Jɢ4-srai3>қV;mIaXN'1YMΪ`L~6T_<#bDi{+@uU+=9UmaH*|QЉ%Qp qKJg~bQiz@^՚.d^qH+XGѺ)U>8v+LŔHݒ^׷F "k_Ѡlo9- bKSЖ&N826P8aX`ya$3C[ô[$Aէ]C%ʶCNsXLl?+Fg'H&UD]]w1z;% {qoF_Wg[~ J Ҋ7rnXu6Hv6y$c'V~AtJjHG#`V+L^>b|=!r?NO%W xmDŽ?в)hןm4iݐ4 a6ޣuע"3Ml{QZ0[Uc)AW c1#<)PyVn1jEAlY͘9U|lUĀuU'r9~:<\Vy^;=>Qklܑ.ʳPێWJ8'>2gM4BOK]yg#]Ŏ٨{ @Cft<m몆!?M}"ul՘Z%/|,Ty+Q״}ȾOq[}WE<8[9*gWwMX #x&7*s\,IZhZG_`ouؓ LIpwжuLIMNЉĽkF}> Elb6녿&Q̖ NȶY\Pq_ezGӃ L"l}+P5vR_7"S1Tphs)_m+|R>"WW/QKgi^a!#;Cmpx8PmoMQ>z0R"iN@e+H &Ca2_6:U44< ,,o1V3xkS!Ib30 @x yynh;_&G#c]- 1N*#?Ϋh *ITIJJQ}3{GIZsaU4 L'2k@>43mDvF5ѐ1N'Y49v;gg@uqC49rK݊br0SS=EB 8v '"NA8}_&ORD`!AAc3I.Y@S-@_4f٪2bߛzM >&Jhv<7Qse" Mw(` V7+$)$Z`6'3_ Aݘ CY˧pԫu{^v*Y*#?%eƒACQ=e(h(0`WVz~|_ozC->(Qd|.z2EA~ёD<+o}Ǵ~Udۅa2חQބA2ͨ*k2Sjl4ktz.[~x3 1lzP쿘(6,'e'Q̆ytk$H}>;Én)(N'R!mҪSA aydxn(P4 VRo0< Ir  1'>!QD)Kd)`h "ib3r~U.z NS*Yr' Id=as~!#}CߩUy@${<% !~rk-N3H1,6!'hӎ1)&OW"Qt[.@Vƃ#0f4_$ l3%`h`$ҩWOU1T`0dI閿MG4U/L;g$:n`͸y1xYs֞e0MP iUdSIIE@M⎝ LQm-sJ 9(PLjf4RG')wWI!!sWp`ǧ/LdE6a܂cAV{%d8Y{'.qTd6?L&} n$I.Hӻ1Z#mh#0SnEȞD; mE,jQ(Q2. (b1-("v h%^EQ%~x-=h%I@ZI-Pw# ^FGDdꬹF!=4V t'3 ,gA;A!_ZTppEl UZiԉVrHGAcF5PcMt2%SYd-qPYwpeؾ;a#Y {џqٿ~#$ϯfq?y~[_%L?p=;ǴrnOoz$á,@?D= 􄽇OP^6yA1 &Hi1LuG'0|ả{CěYEUUyλn|S̡(ŢO-*Se_3̈&)5(^n4Fnej BVHlɲae1EZp(hAԌёIw^Wռ&佧(FYцt]$M5Rr ee (:828W!+AY\7N#]* 10!ԥPU8;lm8uhqMZZDILhۤvJ~Zy:T@a)̲G=ѰhiiZiWE%%*De!Cj$~&7I͈8EqǠ5txR )*I0I,fd0A&t` 8%9 E A×Wj(y)Wo~VJ˕a%NDT6ѧC "[ i__6`# { T;vS$)Rqz;(ANA1([?l6 Nk`kf"$͔u0R%TJ;V *}pJ3j /C7Hj$5EQ@`mB6D%ɮd hћT$foтls`7Y[M&11"/i^f֍&NDy(q4X(mڶ3+ElU A~2A5- %+^ ĵ+1I`,lQ`Jaa3tB(la` WԶcIƂĐZF̎3lq'h & YV Z ehckay|RS,RH$F!O%(N06C,'iG~!$IJ'(EIeI 3_y_HlțDd&D7a["Xb" 0 'AznNɁ#QMt0CD60u! !Я t9b~!\%4ƣ*jiBPRDH#t[#k@ Xn)Q- z)"V0ċz1H&U  YTebJr4`E FQ@9FB4}~W@{AWkr(H ٓP:BZͱ ]KI6ζ\miW[h\S@@&5 d>tI?I?9ǥC9^gx4_j#",>ND(FfQ@/z1T:!" {$ _J~_2}P~$#!}'0TZxщp_aѶ?Zղ`aGH=?G>\/Fq|(+"" f(u~':*fm`BDq_yY)D[ ~0GLS~{XyeTD#oGd$A87sS""n>O~}8yvoaT*HEM}uHOcH(*P,gkE tMTUW3M`p1 mʗGAp(L0"䀸+|D|)Έ"^tX(1dz+O^FC<5Ѫϓ>luOYjqf2^,q(HC2eD?NI ~2gі7aG2t Ý_o;s b(Tދ@r y }j5Zm ?_#R&k= l!ﰍ^$2֌(OL(&,w5+Q"$zEGx'؞9{X.('O{yc0仯(9 H񵨴"\5vd(tℊHq PE szC0.Z P.N=#ߟ6|W`qah`%d%&H@(3y>  v\ , `?{{SɗfI)\F}}.}TCYр f@\Zҏy8Ōα :G.qwm.< 2j0͚8E6vpfXld5NwVytpm)b)>6cU6d^aH'ߖ|PpQ+@]-1hgi0l=9UWMZ`+1lϒ 95.uŘv }IݹHi  :Zm⻁PƒLg|nlgcm29Љ=cqAL dGؖ#O\YCxJAlOw^9gc*u^/\B41D]/@jmmT&l  A)p\(TS)%" Cī8UsR:54kW]2;T˶@Q1Z{k 'Ϧ\e3I i"8}f L. FDՈ""/z1tz~'w nf?U?kȠpAYkGx+gA a֋;'hSBQ=IcqB>øÝ]ޙL12(O*~d 4"AY3sx ЫokV:YȎ}S>W8 K -ӌBzapP`Tz6MIx%UP%.ԡxp\.=[li$riI@T CYg-Fztǝ>w͸aϖ R1 v. „VO~ͅ7SdOn; %h>C{v,7T;={}>-Q=U{g8^H>10j'zq<8.3 N9t@~akAA(YlUT))bHL@k F=.nm m;lG'198u{-#nkc mgN=_sS!|}2AO?av{C!H(kl=Kk<[=+eڶO1d[w$9K#=ޮ5QnOni4n]j\Zg=]T.[살,5ÛQZ˓(C@f#B BSeX\~T6t{ (HVp?Z|)'^:(ɏkTg ZOBp<[7ߵԣ91%}R|6CxD+%@p"@E=/Ca;86cуK)}ݣ"D(2*pP8N5q/z.|{Ux6e8wүkD|6vTtlL|3MrԚRI\pwp.xVJƌ? a#SB!Ҡdb7ۗϿotr2<]}x/G!X$;O* ]9!X ͸<긏^VuzфyF?xC0k`{Mf:r|PО!p;J*0aa4dh5P^\x1Nठ9 Z wC)7F$06ʹ5:pD\5dX#mF b9a(X)R* UX$L=lbIFU-vkM lc+rqHQ f[rLb1(id&(0f *Z 5C?;s~ 4Hc;m@N$ê*(ҕh~!͙e>2KD#/n1dOT׃Dgvnk)چ 1br]|N-?bC*6 k0ěPlc&>#m"A291^92q4 O(G. /t+@ ē&P^&`}|po:Qivu*ud&] U ys&xg,#F$>#yh{Of ABގ=x}d>!} Cܩsole_driver s dziwnymi urzdzeniami, poniewa nie zawsze wskazuj to samo (s to odpowiednio: terminal sterujcy:/dev/tty i bieca konsola:/dev/tty0 lub /dev/console). Ale pomimo tego normalnie rejestrujemy te sterowniki, a wic take urzdzenia. */ /* Rejestracja sterownika dev_tty_driver dla terminala sterujcego. */ memset(&dev_tty_driver, 0, sizeof(struct tty_driver)); dev_tty_driver.magic = TTY_DRIVER_MAGIC; dev_tty_driver.name = "tty"; dev_tty_driver.name_base = 0; dev_tty_driver.major = TTY_MAJOR; dev_tty_driver.minor_start = 0; dev_tty_driver.num = 1; if (tty_register_driver(&dev_tty_driver)) panic("Couldn't register /dev/tty driver\n"); /* Rejestracja sterownika dev_console_driver dla biecej konsoli. */ dev_console_driver = dev_tty_driver; dev_console_driver.name = "console"; dev_console_driver.major = TTYAUX_MAJOR; if (tty_register_driver(&dev_console_driver)) panic("Couldn't register /dev/console driver\n"); /* A teraz pozostae inicjalizacje ... */ kbd_init(); #ifdef CONFIG_SERIAL rs_init(); #endif #ifdef CONFIG_SCC scc_init(); #endif #ifdef CONFIG_CYCLADES cy_init(); #endif #ifdef CONFIG_STALLION stl_init(); #endif #ifdef CONFIG_ISTALLION stli_init(); #endif #ifdef CONFIG_DIGI pcxe_init(); #endif #ifdef CONFIG_RISCOM8 riscom8_init(); #endif #ifdef CONFIG_BAYCOM baycom_init(); #endif #ifdef CONFIG_SPECIALIX specialix_init(); #endif pty_init(); vcs_init(); return 0; }
Komentowaa: Patrycja Wgrzynowicz