2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* Unified handling of special chars.
|
|
|
|
*
|
2012-07-20 17:15:04 +08:00
|
|
|
* Copyright IBM Corp. 2001
|
2005-04-17 06:20:36 +08:00
|
|
|
* Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/stddef.h>
|
|
|
|
#include <asm/errno.h>
|
|
|
|
#include <linux/sysrq.h>
|
|
|
|
#include <linux/ctype.h>
|
|
|
|
|
|
|
|
#include "ctrlchar.h"
|
|
|
|
|
|
|
|
#ifdef CONFIG_MAGIC_SYSRQ
|
2015-08-18 23:42:39 +08:00
|
|
|
static struct sysrq_work ctrlchar_sysrq;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static void
|
2006-12-08 22:53:52 +08:00
|
|
|
ctrlchar_handle_sysrq(struct work_struct *work)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2015-08-18 23:42:39 +08:00
|
|
|
struct sysrq_work *sysrq = container_of(work, struct sysrq_work, work);
|
|
|
|
|
|
|
|
handle_sysrq(sysrq->key);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2015-08-18 23:42:39 +08:00
|
|
|
void schedule_sysrq_work(struct sysrq_work *sw)
|
|
|
|
{
|
|
|
|
INIT_WORK(&sw->work, ctrlchar_handle_sysrq);
|
|
|
|
schedule_work(&sw->work);
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check for special chars at start of input.
|
|
|
|
*
|
|
|
|
* @param buf Console input buffer.
|
|
|
|
* @param len Length of valid data in buffer.
|
|
|
|
* @param tty The tty struct for this console.
|
|
|
|
* @return CTRLCHAR_NONE, if nothing matched,
|
|
|
|
* CTRLCHAR_SYSRQ, if sysrq was encountered
|
|
|
|
* otherwise char to be inserted logically or'ed
|
|
|
|
* with CTRLCHAR_CTRL
|
|
|
|
*/
|
|
|
|
unsigned int
|
|
|
|
ctrlchar_handle(const unsigned char *buf, int len, struct tty_struct *tty)
|
|
|
|
{
|
|
|
|
if ((len < 2) || (len > 3))
|
|
|
|
return CTRLCHAR_NONE;
|
|
|
|
|
|
|
|
/* hat is 0xb1 in codepage 037 (US etc.) and thus */
|
|
|
|
/* converted to 0x5e in ascii ('^') */
|
|
|
|
if ((buf[0] != '^') && (buf[0] != '\252'))
|
|
|
|
return CTRLCHAR_NONE;
|
|
|
|
|
|
|
|
#ifdef CONFIG_MAGIC_SYSRQ
|
|
|
|
/* racy */
|
|
|
|
if (len == 3 && buf[1] == '-') {
|
2015-08-18 23:42:39 +08:00
|
|
|
ctrlchar_sysrq.key = buf[2];
|
|
|
|
schedule_sysrq_work(&ctrlchar_sysrq);
|
2005-04-17 06:20:36 +08:00
|
|
|
return CTRLCHAR_SYSRQ;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (len != 2)
|
|
|
|
return CTRLCHAR_NONE;
|
|
|
|
|
|
|
|
switch (tolower(buf[1])) {
|
|
|
|
case 'c':
|
|
|
|
return INTR_CHAR(tty) | CTRLCHAR_CTRL;
|
|
|
|
case 'd':
|
|
|
|
return EOF_CHAR(tty) | CTRLCHAR_CTRL;
|
|
|
|
case 'z':
|
|
|
|
return SUSP_CHAR(tty) | CTRLCHAR_CTRL;
|
|
|
|
}
|
|
|
|
return CTRLCHAR_NONE;
|
|
|
|
}
|