1 /* 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6 #include "linux/sched.h" 7 #include "linux/slab.h" 8 #include "linux/list.h" 9 #include "linux/kd.h" 10 #include "linux/interrupt.h" 11 #include "linux/devfs_fs_kernel.h" 12 #include "asm/uaccess.h" 13 #include "chan_kern.h" 14 #include "irq_user.h" 15 #include "line.h" 16 #include "kern.h" 17 #include "user_util.h" 18 #include "kern_util.h" 19 #include "os.h" 20 #include "irq_kern.h" 21 22 #define LINE_BUFSIZE 4096 23 24 static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) 25 { 26 struct chan *chan = data; 27 struct line *line = chan->line; 28 struct tty_struct *tty = line->tty; 29 30 if (line) 31 chan_interrupt(&line->chan_list, &line->task, tty, irq); 32 return IRQ_HANDLED; 33 } 34 35 static void line_timer_cb(void *arg) 36 { 37 struct line *line = arg; 38 39 if(!line->throttled) 40 chan_interrupt(&line->chan_list, &line->task, line->tty, 41 line->driver->read_irq); 42 } 43 44 /* Returns the free space inside the ring buffer of this line. 45 * 46 * Should be called while holding line->lock (this does not modify datas). 47 */ 48 static int write_room(struct line *line) 49 { 50 int n; 51 52 if (line->buffer == NULL) 53 return LINE_BUFSIZE - 1; 54 55 /* This is for the case where the buffer is wrapped! */ 56 n = line->head - line->tail; 57 58 if (n <= 0) 59 n = LINE_BUFSIZE + n; /* The other case */ 60 return n - 1; 61 } 62 63 int line_write_room(struct tty_struct *tty) 64 { 65 struct line *line = tty->driver_data; 66 unsigned long flags; 67 int room; 68 69 if (tty->stopped) 70 return 0; 71 72 spin_lock_irqsave(&line->lock, flags); 73 room = write_room(line); 74 spin_unlock_irqrestore(&line->lock, flags); 75 76 /*XXX: Warning to remove */ 77 if (0 == room) 78 printk(KERN_DEBUG "%s: %s: no room left in buffer\n", 79 __FUNCTION__,tty->name); 80 return room; 81 } 82 83 int line_chars_in_buffer(struct tty_struct *tty) 84 { 85 struct line *line = tty->driver_data; 86 unsigned long flags; 87 int ret; 88 89 spin_lock_irqsave(&line->lock, flags); 90 91 /*write_room subtracts 1 for the needed NULL, so we readd it.*/ 92 ret = LINE_BUFSIZE - (write_room(line) + 1); 93 spin_unlock_irqrestore(&line->lock, flags); 94 95 return ret; 96 } 97 98 /* 99 * This copies the content of buf into the circular buffer associated with 100 * this line. 101 * The return value is the number of characters actually copied, i.e. the ones 102 * for which there was space: this function is not supposed to ever flush out 103 * the circular buffer. 104 * 105 * Must be called while holding line->lock! 106 */ 107 static int buffer_data(struct line *line, const char *buf, int len) 108 { 109 int end, room; 110 111 if(line->buffer == NULL){ 112 line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); 113 if (line->buffer == NULL) { 114 printk("buffer_data - atomic allocation failed\n"); 115 return(0); 116 } 117 line->head = line->buffer; 118 line->tail = line->buffer; 119 } 120 121 room = write_room(line); 122 len = (len > room) ? room : len; 123 124 end = line->buffer + LINE_BUFSIZE - line->tail; 125 126 if (len < end){ 127 memcpy(line->tail, buf, len); 128 line->tail += len; 129 } 130 else { 131 /* The circular buffer is wrapping */ 132 memcpy(line->tail, buf, end); 133 buf += end; 134 memcpy(line->buffer, buf, len - end); 135 line->tail = line->buffer + len - end; 136 } 137 138 return len; 139 } 140 141 /* 142 * Flushes the ring buffer to the output channels. That is, write_chan is 143 * called, passing it line->head as buffer, and an appropriate count. 144 * 145 * On exit, returns 1 when the buffer is empty, 146 * 0 when the buffer is not empty on exit, 147 * and -errno when an error occurred. 148 * 149 * Must be called while holding line->lock!*/ 150 static int flush_buffer(struct line *line) 151 { 152 int n, count; 153 154 if ((line->buffer == NULL) || (line->head == line->tail)) 155 return 1; 156 157 if (line->tail < line->head) { 158 /* line->buffer + LINE_BUFSIZE is the end of the buffer! */ 159 count = line->buffer + LINE_BUFSIZE - line->head; 160 161 n = write_chan(&line->chan_list, line->head, count, 162 line->driver->write_irq); 163 if (n < 0) 164 return n; 165 if (n == count) { 166 /* We have flushed from ->head to buffer end, now we 167 * must flush only from the beginning to ->tail.*/ 168 line->head = line->buffer; 169 } else { 170 line->head += n; 171 return 0; 172 } 173 } 174 175 count = line->tail - line->head; 176 n = write_chan(&line->chan_list, line->head, count, 177 line->driver->write_irq); 178 179 if(n < 0) 180 return n; 181 182 line->head += n; 183 return line->head == line->tail; 184 } 185 186 void line_flush_buffer(struct tty_struct *tty) 187 { 188 struct line *line = tty->driver_data; 189 unsigned long flags; 190 int err; 191 192 /*XXX: copied from line_write, verify if it is correct!*/ 193 if(tty->stopped) 194 return; 195 //return 0; 196 197 spin_lock_irqsave(&line->lock, flags); 198 err = flush_buffer(line); 199 /*if (err == 1) 200 err = 0;*/ 201 spin_unlock_irqrestore(&line->lock, flags); 202 //return err; 203 } 204 205 /* We map both ->flush_chars and ->put_char (which go in pair) onto ->flush_buffer 206 * and ->write. Hope it's not that bad.*/ 207 void line_flush_chars(struct tty_struct *tty) 208 { 209 line_flush_buffer(tty); 210 } 211 212 void line_put_char(struct tty_struct *tty, unsigned char ch) 213 { 214 line_write(tty, &ch, sizeof(ch)); 215 } 216 217 int line_write(struct tty_struct *tty, const unsigned char *buf, int len) 218 { 219 struct line *line = tty->driver_data; 220 unsigned long flags; 221 int n, err, ret = 0; 222 223 if(tty->stopped) 224 return 0; 225 226 spin_lock_irqsave(&line->lock, flags); 227 if (line->head != line->tail) { 228 ret = buffer_data(line, buf, len); 229 err = flush_buffer(line); 230 if (err <= 0 && (err != -EAGAIN || !ret)) 231 ret = err; 232 } else { 233 n = write_chan(&line->chan_list, buf, len, 234 line->driver->write_irq); 235 if (n < 0) { 236 ret = n; 237 goto out_up; 238 } 239 240 len -= n; 241 ret += n; 242 if (len > 0) 243 ret += buffer_data(line, buf + n, len); 244 } 245 out_up: 246 spin_unlock_irqrestore(&line->lock, flags); 247 return ret; 248 } 249 250 void line_set_termios(struct tty_struct *tty, struct termios * old) 251 { 252 /* nothing */ 253 } 254 255 static struct { 256 int cmd; 257 char *level; 258 char *name; 259 } tty_ioctls[] = { 260 /* don't print these, they flood the log ... */ 261 { TCGETS, NULL, "TCGETS" }, 262 { TCSETS, NULL, "TCSETS" }, 263 { TCSETSW, NULL, "TCSETSW" }, 264 { TCFLSH, NULL, "TCFLSH" }, 265 { TCSBRK, NULL, "TCSBRK" }, 266 267 /* general tty stuff */ 268 { TCSETSF, KERN_DEBUG, "TCSETSF" }, 269 { TCGETA, KERN_DEBUG, "TCGETA" }, 270 { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, 271 { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, 272 { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, 273 274 /* linux-specific ones */ 275 { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, 276 { KDGKBMODE, KERN_INFO, "KDGKBMODE" }, 277 { KDGKBTYPE, KERN_INFO, "KDGKBTYPE" }, 278 { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" }, 279 }; 280 281 int line_ioctl(struct tty_struct *tty, struct file * file, 282 unsigned int cmd, unsigned long arg) 283 { 284 int ret; 285 int i; 286 287 ret = 0; 288 switch(cmd) { 289 #ifdef TIOCGETP 290 case TIOCGETP: 291 case TIOCSETP: 292 case TIOCSETN: 293 #endif 294 #ifdef TIOCGETC 295 case TIOCGETC: 296 case TIOCSETC: 297 #endif 298 #ifdef TIOCGLTC 299 case TIOCGLTC: 300 case TIOCSLTC: 301 #endif 302 case TCGETS: 303 case TCSETSF: 304 case TCSETSW: 305 case TCSETS: 306 case TCGETA: 307 case TCSETAF: 308 case TCSETAW: 309 case TCSETA: 310 case TCXONC: 311 case TCFLSH: 312 case TIOCOUTQ: 313 case TIOCINQ: 314 case TIOCGLCKTRMIOS: 315 case TIOCSLCKTRMIOS: 316 case TIOCPKT: 317 case TIOCGSOFTCAR: 318 case TIOCSSOFTCAR: 319 return -ENOIOCTLCMD; 320 #if 0 321 case TCwhatever: 322 /* do something */ 323 break; 324 #endif 325 default: 326 for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) 327 if (cmd == tty_ioctls[i].cmd) 328 break; 329 if (i < ARRAY_SIZE(tty_ioctls)) { 330 if (NULL != tty_ioctls[i].level) 331 printk("%s%s: %s: ioctl %s called\n", 332 tty_ioctls[i].level, __FUNCTION__, 333 tty->name, tty_ioctls[i].name); 334 } else { 335 printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", 336 __FUNCTION__, tty->name, cmd); 337 } 338 ret = -ENOIOCTLCMD; 339 break; 340 } 341 return ret; 342 } 343 344 void line_throttle(struct tty_struct *tty) 345 { 346 struct line *line = tty->driver_data; 347 348 deactivate_chan(&line->chan_list, line->driver->read_irq); 349 line->throttled = 1; 350 } 351 352 void line_unthrottle(struct tty_struct *tty) 353 { 354 struct line *line = tty->driver_data; 355 356 line->throttled = 0; 357 chan_interrupt(&line->chan_list, &line->task, tty, 358 line->driver->read_irq); 359 360 /* Maybe there is enough stuff pending that calling the interrupt 361 * throttles us again. In this case, line->throttled will be 1 362 * again and we shouldn't turn the interrupt back on. 363 */ 364 if(!line->throttled) 365 reactivate_chan(&line->chan_list, line->driver->read_irq); 366 } 367 368 static irqreturn_t line_write_interrupt(int irq, void *data, 369 struct pt_regs *unused) 370 { 371 struct chan *chan = data; 372 struct line *line = chan->line; 373 struct tty_struct *tty = line->tty; 374 int err; 375 376 /* Interrupts are enabled here because we registered the interrupt with 377 * SA_INTERRUPT (see line_setup_irq).*/ 378 379 spin_lock_irq(&line->lock); 380 err = flush_buffer(line); 381 if (err == 0) { 382 return IRQ_NONE; 383 } else if(err < 0) { 384 line->head = line->buffer; 385 line->tail = line->buffer; 386 } 387 spin_unlock_irq(&line->lock); 388 389 if(tty == NULL) 390 return IRQ_NONE; 391 392 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && 393 (tty->ldisc.write_wakeup != NULL)) 394 (tty->ldisc.write_wakeup)(tty); 395 396 /* BLOCKING mode 397 * In blocking mode, everything sleeps on tty->write_wait. 398 * Sleeping in the console driver would break non-blocking 399 * writes. 400 */ 401 402 if (waitqueue_active(&tty->write_wait)) 403 wake_up_interruptible(&tty->write_wait); 404 return IRQ_HANDLED; 405 } 406 407 int line_setup_irq(int fd, int input, int output, struct line *line, void *data) 408 { 409 struct line_driver *driver = line->driver; 410 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 411 412 if (input) 413 err = um_request_irq(driver->read_irq, fd, IRQ_READ, 414 line_interrupt, flags, 415 driver->read_irq_name, data); 416 if (err) 417 return err; 418 if (output) 419 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 420 line_write_interrupt, flags, 421 driver->write_irq_name, data); 422 line->have_irq = 1; 423 return err; 424 } 425 426 int line_open(struct line *lines, struct tty_struct *tty) 427 { 428 struct line *line; 429 int err = -ENODEV; 430 431 line = &lines[tty->index]; 432 tty->driver_data = line; 433 434 /* The IRQ which takes this lock is not yet enabled and won't be run 435 * before the end, so we don't need to use spin_lock_irq.*/ 436 spin_lock(&line->lock); 437 438 tty->driver_data = line; 439 line->tty = tty; 440 if(!line->valid) 441 goto out; 442 443 if(tty->count == 1){ 444 /* Here the device is opened, if necessary, and interrupt 445 * is registered. 446 */ 447 enable_chan(line); 448 INIT_WORK(&line->task, line_timer_cb, line); 449 450 if(!line->sigio){ 451 chan_enable_winch(&line->chan_list, tty); 452 line->sigio = 1; 453 } 454 455 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 456 &tty->winsize.ws_col); 457 } 458 459 err = 0; 460 out: 461 spin_unlock(&line->lock); 462 return err; 463 } 464 465 static void unregister_winch(struct tty_struct *tty); 466 467 void line_close(struct tty_struct *tty, struct file * filp) 468 { 469 struct line *line = tty->driver_data; 470 471 /* XXX: I assume this should be called in process context, not with 472 * interrupts disabled! 473 */ 474 spin_lock_irq(&line->lock); 475 476 /* We ignore the error anyway! */ 477 flush_buffer(line); 478 479 if(tty->count == 1){ 480 line->tty = NULL; 481 tty->driver_data = NULL; 482 483 if(line->sigio){ 484 unregister_winch(tty); 485 line->sigio = 0; 486 } 487 } 488 489 spin_unlock_irq(&line->lock); 490 } 491 492 void close_lines(struct line *lines, int nlines) 493 { 494 int i; 495 496 for(i = 0; i < nlines; i++) 497 close_chan(&lines[i].chan_list, 0); 498 } 499 500 /* Common setup code for both startup command line and mconsole initialization. 501 * @lines contains the the array (of size @num) to modify; 502 * @init is the setup string; 503 */ 504 505 int line_setup(struct line *lines, unsigned int num, char *init) 506 { 507 int i, n; 508 char *end; 509 510 if(*init == '=') { 511 /* We said con=/ssl= instead of con#=, so we are configuring all 512 * consoles at once.*/ 513 n = -1; 514 } 515 else { 516 n = simple_strtoul(init, &end, 0); 517 if(*end != '='){ 518 printk(KERN_ERR "line_setup failed to parse \"%s\"\n", 519 init); 520 return 0; 521 } 522 init = end; 523 } 524 init++; 525 526 if (n >= (signed int) num) { 527 printk("line_setup - %d out of range ((0 ... %d) allowed)\n", 528 n, num - 1); 529 return 0; 530 } 531 else if (n >= 0){ 532 if (lines[n].tty != NULL) { 533 printk("line_setup - device %d is open\n", n); 534 return 0; 535 } 536 if (lines[n].init_pri <= INIT_ONE){ 537 lines[n].init_pri = INIT_ONE; 538 if (!strcmp(init, "none")) 539 lines[n].valid = 0; 540 else { 541 lines[n].init_str = init; 542 lines[n].valid = 1; 543 } 544 } 545 } 546 else { 547 for(i = 0; i < num; i++){ 548 if(lines[i].init_pri <= INIT_ALL){ 549 lines[i].init_pri = INIT_ALL; 550 if(!strcmp(init, "none")) lines[i].valid = 0; 551 else { 552 lines[i].init_str = init; 553 lines[i].valid = 1; 554 } 555 } 556 } 557 } 558 return n == -1 ? num : n; 559 } 560 561 int line_config(struct line *lines, unsigned int num, char *str, 562 struct chan_opts *opts) 563 { 564 struct line *line; 565 char *new; 566 int n; 567 568 if(*str == '='){ 569 printk("line_config - can't configure all devices from " 570 "mconsole\n"); 571 return 1; 572 } 573 574 new = kstrdup(str, GFP_KERNEL); 575 if(new == NULL){ 576 printk("line_config - kstrdup failed\n"); 577 return 1; 578 } 579 n = line_setup(lines, num, new); 580 if(n < 0) 581 return 1; 582 583 line = &lines[n]; 584 return parse_chan_pair(line->init_str, line, n, opts); 585 } 586 587 int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 588 int size, char **error_out) 589 { 590 struct line *line; 591 char *end; 592 int dev, n = 0; 593 594 dev = simple_strtoul(name, &end, 0); 595 if((*end != '\0') || (end == name)){ 596 *error_out = "line_get_config failed to parse device number"; 597 return 0; 598 } 599 600 if((dev < 0) || (dev >= num)){ 601 *error_out = "device number out of range"; 602 return 0; 603 } 604 605 line = &lines[dev]; 606 607 spin_lock(&line->lock); 608 if(!line->valid) 609 CONFIG_CHUNK(str, size, n, "none", 1); 610 else if(line->tty == NULL) 611 CONFIG_CHUNK(str, size, n, line->init_str, 1); 612 else n = chan_config_string(&line->chan_list, str, size, error_out); 613 spin_unlock(&line->lock); 614 615 return n; 616 } 617 618 int line_id(char **str, int *start_out, int *end_out) 619 { 620 char *end; 621 int n; 622 623 n = simple_strtoul(*str, &end, 0); 624 if((*end != '\0') || (end == *str)) 625 return -1; 626 627 *str = end; 628 *start_out = n; 629 *end_out = n; 630 return n; 631 } 632 633 int line_remove(struct line *lines, unsigned int num, int n) 634 { 635 int err; 636 char config[sizeof("conxxxx=none\0")]; 637 638 sprintf(config, "%d=none", n); 639 err = line_setup(lines, num, config); 640 if(err >= 0) 641 err = 0; 642 return err; 643 } 644 645 struct tty_driver *line_register_devfs(struct lines *set, 646 struct line_driver *line_driver, 647 struct tty_operations *ops, struct line *lines, 648 int nlines) 649 { 650 int i; 651 struct tty_driver *driver = alloc_tty_driver(nlines); 652 653 if (!driver) 654 return NULL; 655 656 driver->driver_name = line_driver->name; 657 driver->name = line_driver->device_name; 658 driver->devfs_name = line_driver->devfs_name; 659 driver->major = line_driver->major; 660 driver->minor_start = line_driver->minor_start; 661 driver->type = line_driver->type; 662 driver->subtype = line_driver->subtype; 663 driver->flags = TTY_DRIVER_REAL_RAW; 664 driver->init_termios = tty_std_termios; 665 tty_set_operations(driver, ops); 666 667 if (tty_register_driver(driver)) { 668 printk("%s: can't register %s driver\n", 669 __FUNCTION__,line_driver->name); 670 put_tty_driver(driver); 671 return NULL; 672 } 673 674 for(i = 0; i < nlines; i++){ 675 if(!lines[i].valid) 676 tty_unregister_device(driver, i); 677 } 678 679 mconsole_register_dev(&line_driver->mc); 680 return driver; 681 } 682 683 static DEFINE_SPINLOCK(winch_handler_lock); 684 static LIST_HEAD(winch_handlers); 685 686 void lines_init(struct line *lines, int nlines, struct chan_opts *opts) 687 { 688 struct line *line; 689 int i; 690 691 for(i = 0; i < nlines; i++){ 692 line = &lines[i]; 693 INIT_LIST_HEAD(&line->chan_list); 694 695 if(line->init_str == NULL) 696 continue; 697 698 line->init_str = kstrdup(line->init_str, GFP_KERNEL); 699 if(line->init_str == NULL) 700 printk("lines_init - kstrdup returned NULL\n"); 701 702 if(parse_chan_pair(line->init_str, line, i, opts)){ 703 printk("parse_chan_pair failed for device %d\n", i); 704 line->valid = 0; 705 } 706 } 707 } 708 709 struct winch { 710 struct list_head list; 711 int fd; 712 int tty_fd; 713 int pid; 714 struct tty_struct *tty; 715 }; 716 717 static irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) 718 { 719 struct winch *winch = data; 720 struct tty_struct *tty; 721 struct line *line; 722 int err; 723 char c; 724 725 if(winch->fd != -1){ 726 err = generic_read(winch->fd, &c, NULL); 727 if(err < 0){ 728 if(err != -EAGAIN){ 729 printk("winch_interrupt : read failed, " 730 "errno = %d\n", -err); 731 printk("fd %d is losing SIGWINCH support\n", 732 winch->tty_fd); 733 return IRQ_HANDLED; 734 } 735 goto out; 736 } 737 } 738 tty = winch->tty; 739 if (tty != NULL) { 740 line = tty->driver_data; 741 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 742 &tty->winsize.ws_col); 743 kill_pg(tty->pgrp, SIGWINCH, 1); 744 } 745 out: 746 if(winch->fd != -1) 747 reactivate_fd(winch->fd, WINCH_IRQ); 748 return IRQ_HANDLED; 749 } 750 751 void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty) 752 { 753 struct winch *winch; 754 755 winch = kmalloc(sizeof(*winch), GFP_KERNEL); 756 if (winch == NULL) { 757 printk("register_winch_irq - kmalloc failed\n"); 758 return; 759 } 760 761 *winch = ((struct winch) { .list = LIST_HEAD_INIT(winch->list), 762 .fd = fd, 763 .tty_fd = tty_fd, 764 .pid = pid, 765 .tty = tty }); 766 767 spin_lock(&winch_handler_lock); 768 list_add(&winch->list, &winch_handlers); 769 spin_unlock(&winch_handler_lock); 770 771 if(um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, 772 SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 773 "winch", winch) < 0) 774 printk("register_winch_irq - failed to register IRQ\n"); 775 } 776 777 static void free_winch(struct winch *winch) 778 { 779 list_del(&winch->list); 780 781 if(winch->pid != -1) 782 os_kill_process(winch->pid, 1); 783 if(winch->fd != -1) 784 os_close_file(winch->fd); 785 786 free_irq(WINCH_IRQ, winch); 787 kfree(winch); 788 } 789 790 static void unregister_winch(struct tty_struct *tty) 791 { 792 struct list_head *ele; 793 struct winch *winch; 794 795 spin_lock(&winch_handler_lock); 796 797 list_for_each(ele, &winch_handlers){ 798 winch = list_entry(ele, struct winch, list); 799 if(winch->tty == tty){ 800 free_winch(winch); 801 break; 802 } 803 } 804 spin_unlock(&winch_handler_lock); 805 } 806 807 static void winch_cleanup(void) 808 { 809 struct list_head *ele, *next; 810 struct winch *winch; 811 812 spin_lock(&winch_handler_lock); 813 814 list_for_each_safe(ele, next, &winch_handlers){ 815 winch = list_entry(ele, struct winch, list); 816 free_winch(winch); 817 } 818 819 spin_unlock(&winch_handler_lock); 820 } 821 __uml_exitcall(winch_cleanup); 822 823 char *add_xterm_umid(char *base) 824 { 825 char *umid, *title; 826 int len; 827 828 umid = get_umid(); 829 if(*umid == '\0') 830 return base; 831 832 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 833 title = kmalloc(len, GFP_KERNEL); 834 if(title == NULL){ 835 printk("Failed to allocate buffer for xterm title\n"); 836 return base; 837 } 838 839 snprintf(title, len, "%s (%s)", base, umid); 840 return title; 841 } 842