^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * This module exports the functions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * 'int set_selection_user(struct tiocl_selection __user *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * struct tty_struct *)'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * 'int set_selection_kernel(struct tiocl_selection *, struct tty_struct *)'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * 'void clear_selection(void)'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * 'int paste_selection(struct tty_struct *)'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * 'int sel_loadlut(char __user *)'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Now that /dev/vcs exists, most of this can disappear again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/kbd_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/vt_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/consolemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/selection.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/tiocl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/tty_flip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define isspace(c) ((c) == ' ')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* FIXME: all this needs locking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static struct vc_selection {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct vc_data *cons; /* must not be deallocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) char *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned int buf_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) volatile int start; /* cleared by clear_selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) } vc_sel = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .lock = __MUTEX_INITIALIZER(vc_sel.lock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .start = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* clear_selection, highlight and highlight_pointer can be called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) from interrupt (via scrollback/front) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* set reverse video on characters s-e of console with selection. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static inline void highlight(const int s, const int e)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) invert_screen(vc_sel.cons, s, e-s+2, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* use complementary color to show the pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static inline void highlight_pointer(const int where)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) complement_pos(vc_sel.cons, where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static u32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) sel_pos(int n, bool unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return screen_glyph_unicode(vc_sel.cons, n / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return inverse_translate(vc_sel.cons, screen_glyph(vc_sel.cons, n), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * clear_selection - remove current selection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * Remove the current selection highlight, if any from the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * holding the selection. The caller must hold the console lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) void clear_selection(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) highlight_pointer(-1); /* hide the pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (vc_sel.start != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) highlight(vc_sel.start, vc_sel.end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) vc_sel.start = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) EXPORT_SYMBOL_GPL(clear_selection);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) bool vc_is_sel(struct vc_data *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return vc == vc_sel.cons;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * User settable table: what characters are to be considered alphabetic?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * 128 bits. Locked by the console lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static u32 inwordLut[]={
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 0x00000000, /* control chars */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 0x03FFE000, /* digits and "-./" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 0x87FFFFFE, /* uppercase and '_' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 0x07FFFFFE, /* lowercase */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static inline int inword(const u32 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return c > 0x7f || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * set loadlut - load the LUT table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * @p: user table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * Load the LUT table from user space. The caller must hold the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * lock. Make a temporary copy so a partial update doesn't make a mess.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int sel_loadlut(char __user *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) u32 tmplut[ARRAY_SIZE(inwordLut)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (copy_from_user(tmplut, (u32 __user *)(p+4), sizeof(inwordLut)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) memcpy(inwordLut, tmplut, sizeof(inwordLut));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* does screen address p correspond to character at LH/RH edge of screen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static inline int atedge(const int p, int size_row)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return (!(p % size_row) || !((p + 2) % size_row));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* stores the char in UTF8 and returns the number of bytes used (1-4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int store_utf8(u32 c, char *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (c < 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* 0******* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) p[0] = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) } else if (c < 0x800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* 110***** 10****** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) p[0] = 0xc0 | (c >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) p[1] = 0x80 | (c & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) } else if (c < 0x10000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* 1110**** 10****** 10****** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) p[0] = 0xe0 | (c >> 12);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) p[1] = 0x80 | ((c >> 6) & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) p[2] = 0x80 | (c & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) } else if (c < 0x110000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* 11110*** 10****** 10****** 10****** */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) p[0] = 0xf0 | (c >> 18);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) p[1] = 0x80 | ((c >> 12) & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) p[2] = 0x80 | ((c >> 6) & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) p[3] = 0x80 | (c & 0x3f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* outside Unicode, replace with U+FFFD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) p[0] = 0xef;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) p[1] = 0xbf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) p[2] = 0xbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * set_selection_user - set the current selection.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @sel: user selection info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @tty: the console tty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Invoked by the ioctl handle for the vt layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * The entire selection process is managed under the console_lock. It's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * a lot under the lock but its hardly a performance path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int set_selection_user(const struct tiocl_selection __user *sel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct tiocl_selection v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (copy_from_user(&v, sel, sizeof(*sel)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return set_selection_kernel(&v, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int vc_selection_store_chars(struct vc_data *vc, bool unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) char *bp, *obp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /* Allocate a new buffer before freeing the old one ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* chars can take up to 4 bytes with unicode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) GFP_KERNEL | __GFP_NOWARN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) printk(KERN_WARNING "selection: kmalloc() failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) clear_selection();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) kfree(vc_sel.buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) vc_sel.buffer = bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) obp = bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) for (i = vc_sel.start; i <= vc_sel.end; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) u32 c = sel_pos(i, unicode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (unicode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) bp += store_utf8(c, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) *bp++ = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (!isspace(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) obp = bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (!((i + 2) % vc->vc_size_row)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* strip trailing blanks from line and add newline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unless non-space at end of line. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (obp != bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bp = obp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) *bp++ = '\r';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) obp = bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) vc_sel.buf_len = bp - vc_sel.buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static int vc_do_selection(struct vc_data *vc, unsigned short mode, int ps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int pe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int new_sel_start, new_sel_end, spc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) bool unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) case TIOCL_SELCHAR: /* character-by-character selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) new_sel_start = ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) new_sel_end = pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) case TIOCL_SELWORD: /* word-by-word selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) spc = isspace(sel_pos(ps, unicode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (new_sel_start = ps; ; ps -= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if ((spc && !isspace(sel_pos(ps, unicode))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) (!spc && !inword(sel_pos(ps, unicode))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) new_sel_start = ps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!(ps % vc->vc_size_row))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) spc = isspace(sel_pos(pe, unicode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) for (new_sel_end = pe; ; pe += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if ((spc && !isspace(sel_pos(pe, unicode))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) (!spc && !inword(sel_pos(pe, unicode))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) new_sel_end = pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (!((pe + 2) % vc->vc_size_row))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case TIOCL_SELLINE: /* line-by-line selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) new_sel_start = rounddown(ps, vc->vc_size_row);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) new_sel_end = rounddown(pe, vc->vc_size_row) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) vc->vc_size_row - 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) case TIOCL_SELPOINTER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) highlight_pointer(pe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* remove the pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) highlight_pointer(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) /* select to end of line if on trailing space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (new_sel_end > new_sel_start &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) !atedge(new_sel_end, vc->vc_size_row) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) isspace(sel_pos(new_sel_end, unicode))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) for (pe = new_sel_end + 2; ; pe += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!isspace(sel_pos(pe, unicode)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) atedge(pe, vc->vc_size_row))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (isspace(sel_pos(pe, unicode)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) new_sel_end = pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (vc_sel.start == -1) /* no current selection */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) highlight(new_sel_start, new_sel_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) else if (new_sel_start == vc_sel.start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (new_sel_end == vc_sel.end) /* no action required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) else if (new_sel_end > vc_sel.end) /* extend to right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) highlight(vc_sel.end + 2, new_sel_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else /* contract from right */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) highlight(new_sel_end + 2, vc_sel.end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) else if (new_sel_end == vc_sel.end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (new_sel_start < vc_sel.start) /* extend to left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) highlight(new_sel_start, vc_sel.start - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) else /* contract from left */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) highlight(vc_sel.start, new_sel_start - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) else /* some other case; start selection from scratch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) clear_selection();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) highlight(new_sel_start, new_sel_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) vc_sel.start = new_sel_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) vc_sel.end = new_sel_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) return vc_selection_store_chars(vc, unicode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int vc_selection(struct vc_data *vc, struct tiocl_selection *v,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) int ps, pe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) poke_blanked_console();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (v->sel_mode == TIOCL_SELCLEAR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /* useful for screendump without selection highlights */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) clear_selection();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) v->xs = min_t(u16, v->xs - 1, vc->vc_cols - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) v->ys = min_t(u16, v->ys - 1, vc->vc_rows - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) v->xe = min_t(u16, v->xe - 1, vc->vc_cols - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) v->ye = min_t(u16, v->ye - 1, vc->vc_rows - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (mouse_reporting() && (v->sel_mode & TIOCL_SELMOUSEREPORT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) mouse_report(tty, v->sel_mode & TIOCL_SELBUTTONMASK, v->xs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) v->ys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ps = v->ys * vc->vc_size_row + (v->xs << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) pe = v->ye * vc->vc_size_row + (v->xe << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (ps > pe) /* make vc_sel.start <= vc_sel.end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) swap(ps, pe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (vc_sel.cons != vc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) clear_selection();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) vc_sel.cons = vc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return vc_do_selection(vc, v->sel_mode, ps, pe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) mutex_lock(&vc_sel.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) ret = vc_selection(vc_cons[fg_console].d, v, tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) mutex_unlock(&vc_sel.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) EXPORT_SYMBOL_GPL(set_selection_kernel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) /* Insert the contents of the selection buffer into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * queue of the tty associated with the current console.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * Invoked by ioctl().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * Locking: called without locks. Calls the ldisc wrongly with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * unsafe methods,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int paste_selection(struct tty_struct *tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct vc_data *vc = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int pasted = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) unsigned int count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct tty_ldisc *ld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) DECLARE_WAITQUEUE(wait, current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) poke_blanked_console();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) ld = tty_ldisc_ref_wait(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (!ld)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) return -EIO; /* ldisc was hung up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) tty_buffer_lock_exclusive(&vc->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) add_wait_queue(&vc->paste_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) mutex_lock(&vc_sel.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) while (vc_sel.buffer && vc_sel.buf_len > pasted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) set_current_state(TASK_INTERRUPTIBLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (signal_pending(current)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ret = -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (tty_throttled(tty)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) mutex_unlock(&vc_sel.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) schedule();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mutex_lock(&vc_sel.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) count = vc_sel.buf_len - pasted;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) count = tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) pasted += count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) mutex_unlock(&vc_sel.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) remove_wait_queue(&vc->paste_wait, &wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) __set_current_state(TASK_RUNNING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) tty_buffer_unlock_exclusive(&vc->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) tty_ldisc_deref(ld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) EXPORT_SYMBOL_GPL(paste_selection);