Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4 : */
5 :
6 : #include <linux/irqreturn.h>
7 : #include <linux/kd.h>
8 : #include <linux/sched/signal.h>
9 : #include <linux/slab.h>
10 :
11 : #include "chan.h"
12 : #include <irq_kern.h>
13 : #include <irq_user.h>
14 : #include <kern_util.h>
15 : #include <os.h>
16 :
17 : #define LINE_BUFSIZE 4096
18 :
19 0 : static irqreturn_t line_interrupt(int irq, void *data)
20 : {
21 0 : struct chan *chan = data;
22 0 : struct line *line = chan->line;
23 :
24 0 : if (line)
25 0 : chan_interrupt(line, irq);
26 :
27 0 : return IRQ_HANDLED;
28 : }
29 :
30 : /*
31 : * Returns the free space inside the ring buffer of this line.
32 : *
33 : * Should be called while holding line->lock (this does not modify data).
34 : */
35 : static unsigned int write_room(struct line *line)
36 : {
37 : int n;
38 :
39 0 : if (line->buffer == NULL)
40 : return LINE_BUFSIZE - 1;
41 :
42 : /* This is for the case where the buffer is wrapped! */
43 0 : n = line->head - line->tail;
44 :
45 0 : if (n <= 0)
46 0 : n += LINE_BUFSIZE; /* The other case */
47 0 : return n - 1;
48 : }
49 :
50 0 : unsigned int line_write_room(struct tty_struct *tty)
51 : {
52 0 : struct line *line = tty->driver_data;
53 : unsigned long flags;
54 : unsigned int room;
55 :
56 0 : spin_lock_irqsave(&line->lock, flags);
57 0 : room = write_room(line);
58 0 : spin_unlock_irqrestore(&line->lock, flags);
59 :
60 0 : return room;
61 : }
62 :
63 0 : unsigned int line_chars_in_buffer(struct tty_struct *tty)
64 : {
65 0 : struct line *line = tty->driver_data;
66 : unsigned long flags;
67 : unsigned int ret;
68 :
69 0 : spin_lock_irqsave(&line->lock, flags);
70 : /* write_room subtracts 1 for the needed NULL, so we readd it.*/
71 0 : ret = LINE_BUFSIZE - (write_room(line) + 1);
72 0 : spin_unlock_irqrestore(&line->lock, flags);
73 :
74 0 : return ret;
75 : }
76 :
77 : /*
78 : * This copies the content of buf into the circular buffer associated with
79 : * this line.
80 : * The return value is the number of characters actually copied, i.e. the ones
81 : * for which there was space: this function is not supposed to ever flush out
82 : * the circular buffer.
83 : *
84 : * Must be called while holding line->lock!
85 : */
86 0 : static int buffer_data(struct line *line, const char *buf, int len)
87 : {
88 : int end, room;
89 :
90 0 : if (line->buffer == NULL) {
91 0 : line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
92 0 : if (line->buffer == NULL) {
93 0 : printk(KERN_ERR "buffer_data - atomic allocation "
94 : "failed\n");
95 0 : return 0;
96 : }
97 0 : line->head = line->buffer;
98 0 : line->tail = line->buffer;
99 : }
100 :
101 0 : room = write_room(line);
102 0 : len = (len > room) ? room : len;
103 :
104 0 : end = line->buffer + LINE_BUFSIZE - line->tail;
105 :
106 0 : if (len < end) {
107 0 : memcpy(line->tail, buf, len);
108 0 : line->tail += len;
109 : }
110 : else {
111 : /* The circular buffer is wrapping */
112 0 : memcpy(line->tail, buf, end);
113 0 : buf += end;
114 0 : memcpy(line->buffer, buf, len - end);
115 0 : line->tail = line->buffer + len - end;
116 : }
117 :
118 : return len;
119 : }
120 :
121 : /*
122 : * Flushes the ring buffer to the output channels. That is, write_chan is
123 : * called, passing it line->head as buffer, and an appropriate count.
124 : *
125 : * On exit, returns 1 when the buffer is empty,
126 : * 0 when the buffer is not empty on exit,
127 : * and -errno when an error occurred.
128 : *
129 : * Must be called while holding line->lock!*/
130 0 : static int flush_buffer(struct line *line)
131 : {
132 : int n, count;
133 :
134 0 : if ((line->buffer == NULL) || (line->head == line->tail))
135 : return 1;
136 :
137 0 : if (line->tail < line->head) {
138 : /* line->buffer + LINE_BUFSIZE is the end of the buffer! */
139 0 : count = line->buffer + LINE_BUFSIZE - line->head;
140 :
141 0 : n = write_chan(line->chan_out, line->head, count,
142 : line->write_irq);
143 0 : if (n < 0)
144 : return n;
145 0 : if (n == count) {
146 : /*
147 : * We have flushed from ->head to buffer end, now we
148 : * must flush only from the beginning to ->tail.
149 : */
150 0 : line->head = line->buffer;
151 : } else {
152 0 : line->head += n;
153 0 : return 0;
154 : }
155 : }
156 :
157 0 : count = line->tail - line->head;
158 0 : n = write_chan(line->chan_out, line->head, count,
159 : line->write_irq);
160 :
161 0 : if (n < 0)
162 : return n;
163 :
164 0 : line->head += n;
165 0 : return line->head == line->tail;
166 : }
167 :
168 0 : void line_flush_buffer(struct tty_struct *tty)
169 : {
170 0 : struct line *line = tty->driver_data;
171 : unsigned long flags;
172 :
173 0 : spin_lock_irqsave(&line->lock, flags);
174 0 : flush_buffer(line);
175 0 : spin_unlock_irqrestore(&line->lock, flags);
176 0 : }
177 :
178 : /*
179 : * We map both ->flush_chars and ->put_char (which go in pair) onto
180 : * ->flush_buffer and ->write. Hope it's not that bad.
181 : */
182 0 : void line_flush_chars(struct tty_struct *tty)
183 : {
184 0 : line_flush_buffer(tty);
185 0 : }
186 :
187 0 : int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
188 : {
189 0 : struct line *line = tty->driver_data;
190 : unsigned long flags;
191 0 : int n, ret = 0;
192 :
193 0 : spin_lock_irqsave(&line->lock, flags);
194 0 : if (line->head != line->tail)
195 0 : ret = buffer_data(line, buf, len);
196 : else {
197 0 : n = write_chan(line->chan_out, buf, len,
198 : line->write_irq);
199 0 : if (n < 0) {
200 : ret = n;
201 : goto out_up;
202 : }
203 :
204 0 : len -= n;
205 0 : ret += n;
206 0 : if (len > 0)
207 0 : ret += buffer_data(line, buf + n, len);
208 : }
209 : out_up:
210 0 : spin_unlock_irqrestore(&line->lock, flags);
211 0 : return ret;
212 : }
213 :
214 0 : void line_throttle(struct tty_struct *tty)
215 : {
216 0 : struct line *line = tty->driver_data;
217 :
218 0 : deactivate_chan(line->chan_in, line->read_irq);
219 0 : line->throttled = 1;
220 0 : }
221 :
222 0 : void line_unthrottle(struct tty_struct *tty)
223 : {
224 0 : struct line *line = tty->driver_data;
225 :
226 0 : line->throttled = 0;
227 0 : chan_interrupt(line, line->read_irq);
228 0 : }
229 :
230 0 : static irqreturn_t line_write_interrupt(int irq, void *data)
231 : {
232 0 : struct chan *chan = data;
233 0 : struct line *line = chan->line;
234 : int err;
235 :
236 : /*
237 : * Interrupts are disabled here because genirq keep irqs disabled when
238 : * calling the action handler.
239 : */
240 :
241 0 : spin_lock(&line->lock);
242 0 : err = flush_buffer(line);
243 0 : if (err == 0) {
244 0 : spin_unlock(&line->lock);
245 0 : return IRQ_NONE;
246 0 : } else if ((err < 0) && (err != -EAGAIN)) {
247 0 : line->head = line->buffer;
248 0 : line->tail = line->buffer;
249 : }
250 0 : spin_unlock(&line->lock);
251 :
252 0 : tty_port_tty_wakeup(&line->port);
253 :
254 0 : return IRQ_HANDLED;
255 : }
256 :
257 0 : int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
258 : {
259 0 : const struct line_driver *driver = line->driver;
260 : int err;
261 :
262 0 : if (input) {
263 0 : err = um_request_irq(UM_IRQ_ALLOC, fd, IRQ_READ,
264 : line_interrupt, 0,
265 : driver->read_irq_name, data);
266 0 : if (err < 0)
267 : return err;
268 :
269 0 : line->read_irq = err;
270 : }
271 :
272 0 : if (output) {
273 0 : err = um_request_irq(UM_IRQ_ALLOC, fd, IRQ_WRITE,
274 : line_write_interrupt, 0,
275 : driver->write_irq_name, data);
276 0 : if (err < 0)
277 : return err;
278 :
279 0 : line->write_irq = err;
280 : }
281 :
282 : return 0;
283 : }
284 :
285 0 : static int line_activate(struct tty_port *port, struct tty_struct *tty)
286 : {
287 : int ret;
288 0 : struct line *line = tty->driver_data;
289 :
290 0 : ret = enable_chan(line);
291 0 : if (ret)
292 : return ret;
293 :
294 0 : if (!line->sigio) {
295 0 : chan_enable_winch(line->chan_out, port);
296 0 : line->sigio = 1;
297 : }
298 :
299 0 : chan_window_size(line, &tty->winsize.ws_row,
300 : &tty->winsize.ws_col);
301 :
302 0 : return 0;
303 : }
304 :
305 : static void unregister_winch(struct tty_struct *tty);
306 :
307 0 : static void line_destruct(struct tty_port *port)
308 : {
309 0 : struct tty_struct *tty = tty_port_tty_get(port);
310 0 : struct line *line = tty->driver_data;
311 :
312 0 : if (line->sigio) {
313 0 : unregister_winch(tty);
314 0 : line->sigio = 0;
315 : }
316 0 : }
317 :
318 : static const struct tty_port_operations line_port_ops = {
319 : .activate = line_activate,
320 : .destruct = line_destruct,
321 : };
322 :
323 0 : int line_open(struct tty_struct *tty, struct file *filp)
324 : {
325 0 : struct line *line = tty->driver_data;
326 :
327 0 : return tty_port_open(&line->port, tty, filp);
328 : }
329 :
330 0 : int line_install(struct tty_driver *driver, struct tty_struct *tty,
331 : struct line *line)
332 : {
333 : int ret;
334 :
335 0 : ret = tty_standard_install(driver, tty);
336 0 : if (ret)
337 : return ret;
338 :
339 0 : tty->driver_data = line;
340 :
341 0 : return 0;
342 : }
343 :
344 0 : void line_close(struct tty_struct *tty, struct file * filp)
345 : {
346 0 : struct line *line = tty->driver_data;
347 :
348 0 : tty_port_close(&line->port, tty, filp);
349 0 : }
350 :
351 0 : void line_hangup(struct tty_struct *tty)
352 : {
353 0 : struct line *line = tty->driver_data;
354 :
355 0 : tty_port_hangup(&line->port);
356 0 : }
357 :
358 1 : void close_lines(struct line *lines, int nlines)
359 : {
360 : int i;
361 :
362 17 : for(i = 0; i < nlines; i++)
363 16 : close_chan(&lines[i]);
364 1 : }
365 :
366 16 : int setup_one_line(struct line *lines, int n, char *init,
367 : const struct chan_opts *opts, char **error_out)
368 : {
369 16 : struct line *line = &lines[n];
370 16 : struct tty_driver *driver = line->driver->driver;
371 16 : int err = -EINVAL;
372 :
373 16 : if (line->port.count) {
374 0 : *error_out = "Device is already open";
375 0 : goto out;
376 : }
377 :
378 16 : if (!strcmp(init, "none")) {
379 0 : if (line->valid) {
380 0 : line->valid = 0;
381 0 : kfree(line->init_str);
382 0 : tty_unregister_device(driver, n);
383 0 : parse_chan_pair(NULL, line, n, opts, error_out);
384 0 : err = 0;
385 : }
386 : } else {
387 16 : char *new = kstrdup(init, GFP_KERNEL);
388 16 : if (!new) {
389 0 : *error_out = "Failed to allocate memory";
390 0 : return -ENOMEM;
391 : }
392 16 : if (line->valid) {
393 0 : tty_unregister_device(driver, n);
394 0 : kfree(line->init_str);
395 : }
396 16 : line->init_str = new;
397 16 : line->valid = 1;
398 16 : err = parse_chan_pair(new, line, n, opts, error_out);
399 16 : if (!err) {
400 1 : struct device *d = tty_port_register_device(&line->port,
401 : driver, n, NULL);
402 1 : if (IS_ERR(d)) {
403 0 : *error_out = "Failed to register device";
404 0 : err = PTR_ERR(d);
405 0 : parse_chan_pair(NULL, line, n, opts, error_out);
406 : }
407 : }
408 16 : if (err) {
409 15 : line->init_str = NULL;
410 15 : line->valid = 0;
411 15 : kfree(new);
412 : }
413 : }
414 : out:
415 : return err;
416 : }
417 :
418 : /*
419 : * Common setup code for both startup command line and mconsole initialization.
420 : * @lines contains the array (of size @num) to modify;
421 : * @init is the setup string;
422 : * @error_out is an error string in the case of failure;
423 : */
424 :
425 0 : int line_setup(char **conf, unsigned int num, char **def,
426 : char *init, char *name)
427 : {
428 : char *error;
429 :
430 0 : if (*init == '=') {
431 : /*
432 : * We said con=/ssl= instead of con#=, so we are configuring all
433 : * consoles at once.
434 : */
435 0 : *def = init + 1;
436 : } else {
437 : char *end;
438 0 : unsigned n = simple_strtoul(init, &end, 0);
439 :
440 0 : if (*end != '=') {
441 : error = "Couldn't parse device number";
442 0 : goto out;
443 : }
444 0 : if (n >= num) {
445 : error = "Device number out of range";
446 : goto out;
447 : }
448 0 : conf[n] = end + 1;
449 : }
450 : return 0;
451 :
452 : out:
453 0 : printk(KERN_ERR "Failed to set up %s with "
454 : "configuration string \"%s\" : %s\n", name, init, error);
455 0 : return -EINVAL;
456 : }
457 :
458 0 : int line_config(struct line *lines, unsigned int num, char *str,
459 : const struct chan_opts *opts, char **error_out)
460 : {
461 : char *end;
462 : int n;
463 :
464 0 : if (*str == '=') {
465 0 : *error_out = "Can't configure all devices from mconsole";
466 0 : return -EINVAL;
467 : }
468 :
469 0 : n = simple_strtoul(str, &end, 0);
470 0 : if (*end++ != '=') {
471 0 : *error_out = "Couldn't parse device number";
472 0 : return -EINVAL;
473 : }
474 0 : if (n >= num) {
475 0 : *error_out = "Device number out of range";
476 0 : return -EINVAL;
477 : }
478 :
479 0 : return setup_one_line(lines, n, end, opts, error_out);
480 : }
481 :
482 0 : int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
483 : int size, char **error_out)
484 : {
485 : struct line *line;
486 : char *end;
487 0 : int dev, n = 0;
488 :
489 0 : dev = simple_strtoul(name, &end, 0);
490 0 : if ((*end != '\0') || (end == name)) {
491 0 : *error_out = "line_get_config failed to parse device number";
492 0 : return 0;
493 : }
494 :
495 0 : if ((dev < 0) || (dev >= num)) {
496 0 : *error_out = "device number out of range";
497 0 : return 0;
498 : }
499 :
500 0 : line = &lines[dev];
501 :
502 0 : if (!line->valid)
503 0 : CONFIG_CHUNK(str, size, n, "none", 1);
504 : else {
505 0 : struct tty_struct *tty = tty_port_tty_get(&line->port);
506 0 : if (tty == NULL) {
507 0 : CONFIG_CHUNK(str, size, n, line->init_str, 1);
508 : } else {
509 0 : n = chan_config_string(line, str, size, error_out);
510 0 : tty_kref_put(tty);
511 : }
512 : }
513 :
514 : return n;
515 : }
516 :
517 0 : int line_id(char **str, int *start_out, int *end_out)
518 : {
519 : char *end;
520 : int n;
521 :
522 0 : n = simple_strtoul(*str, &end, 0);
523 0 : if ((*end != '\0') || (end == *str))
524 : return -1;
525 :
526 0 : *str = end;
527 0 : *start_out = n;
528 0 : *end_out = n;
529 0 : return n;
530 : }
531 :
532 0 : int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
533 : {
534 0 : if (n >= num) {
535 0 : *error_out = "Device number out of range";
536 0 : return -EINVAL;
537 : }
538 0 : return setup_one_line(lines, n, "none", NULL, error_out);
539 : }
540 :
541 1 : int register_lines(struct line_driver *line_driver,
542 : const struct tty_operations *ops,
543 : struct line *lines, int nlines)
544 : {
545 : struct tty_driver *driver;
546 : int err;
547 : int i;
548 :
549 1 : driver = tty_alloc_driver(nlines, TTY_DRIVER_REAL_RAW |
550 : TTY_DRIVER_DYNAMIC_DEV);
551 1 : if (IS_ERR(driver))
552 0 : return PTR_ERR(driver);
553 :
554 1 : driver->driver_name = line_driver->name;
555 1 : driver->name = line_driver->device_name;
556 1 : driver->major = line_driver->major;
557 1 : driver->minor_start = line_driver->minor_start;
558 1 : driver->type = line_driver->type;
559 1 : driver->subtype = line_driver->subtype;
560 1 : driver->init_termios = tty_std_termios;
561 :
562 17 : for (i = 0; i < nlines; i++) {
563 16 : tty_port_init(&lines[i].port);
564 16 : lines[i].port.ops = &line_port_ops;
565 16 : spin_lock_init(&lines[i].lock);
566 16 : lines[i].driver = line_driver;
567 32 : INIT_LIST_HEAD(&lines[i].chan_list);
568 : }
569 2 : tty_set_operations(driver, ops);
570 :
571 1 : err = tty_register_driver(driver);
572 1 : if (err) {
573 0 : printk(KERN_ERR "register_lines : can't register %s driver\n",
574 : line_driver->name);
575 0 : tty_driver_kref_put(driver);
576 0 : for (i = 0; i < nlines; i++)
577 0 : tty_port_destroy(&lines[i].port);
578 : return err;
579 : }
580 :
581 1 : line_driver->driver = driver;
582 1 : mconsole_register_dev(&line_driver->mc);
583 1 : return 0;
584 : }
585 :
586 : static DEFINE_SPINLOCK(winch_handler_lock);
587 : static LIST_HEAD(winch_handlers);
588 :
589 : struct winch {
590 : struct list_head list;
591 : int fd;
592 : int tty_fd;
593 : int pid;
594 : struct tty_port *port;
595 : unsigned long stack;
596 : struct work_struct work;
597 : };
598 :
599 0 : static void __free_winch(struct work_struct *work)
600 : {
601 0 : struct winch *winch = container_of(work, struct winch, work);
602 0 : um_free_irq(WINCH_IRQ, winch);
603 :
604 0 : if (winch->pid != -1)
605 0 : os_kill_process(winch->pid, 1);
606 0 : if (winch->stack != 0)
607 0 : free_stack(winch->stack, 0);
608 0 : kfree(winch);
609 0 : }
610 :
611 0 : static void free_winch(struct winch *winch)
612 : {
613 0 : int fd = winch->fd;
614 0 : winch->fd = -1;
615 0 : if (fd != -1)
616 0 : os_close_file(fd);
617 0 : __free_winch(&winch->work);
618 0 : }
619 :
620 0 : static irqreturn_t winch_interrupt(int irq, void *data)
621 : {
622 0 : struct winch *winch = data;
623 : struct tty_struct *tty;
624 : struct line *line;
625 0 : int fd = winch->fd;
626 : int err;
627 : char c;
628 : struct pid *pgrp;
629 :
630 0 : if (fd != -1) {
631 0 : err = generic_read(fd, &c, NULL);
632 0 : if (err < 0) {
633 0 : if (err != -EAGAIN) {
634 0 : winch->fd = -1;
635 0 : list_del(&winch->list);
636 0 : os_close_file(fd);
637 0 : printk(KERN_ERR "winch_interrupt : "
638 : "read failed, errno = %d\n", -err);
639 0 : printk(KERN_ERR "fd %d is losing SIGWINCH "
640 : "support\n", winch->tty_fd);
641 0 : INIT_WORK(&winch->work, __free_winch);
642 0 : schedule_work(&winch->work);
643 0 : return IRQ_HANDLED;
644 : }
645 : goto out;
646 : }
647 : }
648 0 : tty = tty_port_tty_get(winch->port);
649 0 : if (tty != NULL) {
650 0 : line = tty->driver_data;
651 0 : if (line != NULL) {
652 0 : chan_window_size(line, &tty->winsize.ws_row,
653 : &tty->winsize.ws_col);
654 0 : pgrp = tty_get_pgrp(tty);
655 0 : if (pgrp)
656 0 : kill_pgrp(pgrp, SIGWINCH, 1);
657 0 : put_pid(pgrp);
658 : }
659 0 : tty_kref_put(tty);
660 : }
661 : out:
662 : return IRQ_HANDLED;
663 : }
664 :
665 0 : void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,
666 : unsigned long stack)
667 : {
668 : struct winch *winch;
669 :
670 0 : winch = kmalloc(sizeof(*winch), GFP_KERNEL);
671 0 : if (winch == NULL) {
672 0 : printk(KERN_ERR "register_winch_irq - kmalloc failed\n");
673 0 : goto cleanup;
674 : }
675 :
676 0 : *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list),
677 : .fd = fd,
678 : .tty_fd = tty_fd,
679 : .pid = pid,
680 : .port = port,
681 : .stack = stack });
682 :
683 0 : if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
684 : IRQF_SHARED, "winch", winch) < 0) {
685 0 : printk(KERN_ERR "register_winch_irq - failed to register "
686 : "IRQ\n");
687 : goto out_free;
688 : }
689 :
690 0 : spin_lock(&winch_handler_lock);
691 0 : list_add(&winch->list, &winch_handlers);
692 : spin_unlock(&winch_handler_lock);
693 :
694 : return;
695 :
696 : out_free:
697 0 : kfree(winch);
698 : cleanup:
699 0 : os_kill_process(pid, 1);
700 0 : os_close_file(fd);
701 0 : if (stack != 0)
702 0 : free_stack(stack, 0);
703 : }
704 :
705 0 : static void unregister_winch(struct tty_struct *tty)
706 : {
707 : struct list_head *ele, *next;
708 : struct winch *winch;
709 : struct tty_struct *wtty;
710 :
711 0 : spin_lock(&winch_handler_lock);
712 :
713 0 : list_for_each_safe(ele, next, &winch_handlers) {
714 0 : winch = list_entry(ele, struct winch, list);
715 0 : wtty = tty_port_tty_get(winch->port);
716 0 : if (wtty == tty) {
717 0 : list_del(&winch->list);
718 0 : spin_unlock(&winch_handler_lock);
719 0 : free_winch(winch);
720 0 : break;
721 : }
722 0 : tty_kref_put(wtty);
723 : }
724 0 : spin_unlock(&winch_handler_lock);
725 0 : }
726 :
727 1 : static void winch_cleanup(void)
728 : {
729 : struct winch *winch;
730 :
731 : spin_lock(&winch_handler_lock);
732 1 : while ((winch = list_first_entry_or_null(&winch_handlers,
733 : struct winch, list))) {
734 0 : list_del(&winch->list);
735 0 : spin_unlock(&winch_handler_lock);
736 :
737 0 : free_winch(winch);
738 :
739 : spin_lock(&winch_handler_lock);
740 : }
741 :
742 1 : spin_unlock(&winch_handler_lock);
743 1 : }
744 : __uml_exitcall(winch_cleanup);
745 :
746 1 : char *add_xterm_umid(char *base)
747 : {
748 : char *umid, *title;
749 : int len;
750 :
751 1 : umid = get_umid();
752 1 : if (*umid == '\0')
753 : return base;
754 :
755 1 : len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
756 2 : title = kmalloc(len, GFP_KERNEL);
757 1 : if (title == NULL) {
758 0 : printk(KERN_ERR "Failed to allocate buffer for xterm title\n");
759 0 : return base;
760 : }
761 :
762 1 : snprintf(title, len, "%s (%s)", base, umid);
763 1 : return title;
764 : }
|