fd.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
  4. */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <errno.h>
  9. #include <termios.h>
  10. #include "chan_user.h"
  11. #include <os.h>
  12. #include <um_malloc.h>
  13. struct fd_chan {
  14. int fd;
  15. int raw;
  16. struct termios tt;
  17. char str[sizeof("1234567890\0")];
  18. };
  19. static void *fd_init(char *str, int device, const struct chan_opts *opts)
  20. {
  21. struct fd_chan *data;
  22. char *end;
  23. int n;
  24. if (*str != ':') {
  25. printk(UM_KERN_ERR "fd_init : channel type 'fd' must specify a "
  26. "file descriptor\n");
  27. return NULL;
  28. }
  29. str++;
  30. n = strtoul(str, &end, 0);
  31. if ((*end != '\0') || (end == str)) {
  32. printk(UM_KERN_ERR "fd_init : couldn't parse file descriptor "
  33. "'%s'\n", str);
  34. return NULL;
  35. }
  36. data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
  37. if (data == NULL)
  38. return NULL;
  39. *data = ((struct fd_chan) { .fd = n,
  40. .raw = opts->raw });
  41. return data;
  42. }
  43. static int fd_open(int input, int output, int primary, void *d, char **dev_out)
  44. {
  45. struct fd_chan *data = d;
  46. int err;
  47. if (data->raw && isatty(data->fd)) {
  48. CATCH_EINTR(err = tcgetattr(data->fd, &data->tt));
  49. if (err)
  50. return err;
  51. err = raw(data->fd);
  52. if (err)
  53. return err;
  54. }
  55. sprintf(data->str, "%d", data->fd);
  56. *dev_out = data->str;
  57. return data->fd;
  58. }
  59. static void fd_close(int fd, void *d)
  60. {
  61. struct fd_chan *data = d;
  62. int err;
  63. if (!data->raw || !isatty(fd))
  64. return;
  65. CATCH_EINTR(err = tcsetattr(fd, TCSAFLUSH, &data->tt));
  66. if (err)
  67. printk(UM_KERN_ERR "Failed to restore terminal state - "
  68. "errno = %d\n", -err);
  69. data->raw = 0;
  70. }
  71. const struct chan_ops fd_ops = {
  72. .type = "fd",
  73. .init = fd_init,
  74. .open = fd_open,
  75. .close = fd_close,
  76. .read = generic_read,
  77. .write = generic_write,
  78. .console_write = generic_console_write,
  79. .window_size = generic_window_size,
  80. .free = generic_free,
  81. .winch = 1,
  82. };