unixpipe.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2014 Kevin Lange
  5. */
  6. #include <kernel/system.h>
  7. #include <kernel/fs.h>
  8. #include <kernel/pipe.h>
  9. #include <kernel/logging.h>
  10. #include <kernel/printf.h>
  11. #include <kernel/ringbuffer.h>
  12. #include <sys/ioctl.h>
  13. #define UNIX_PIPE_BUFFER 512
  14. struct unix_pipe {
  15. fs_node_t * read_end;
  16. fs_node_t * write_end;
  17. volatile int read_closed;
  18. volatile int write_closed;
  19. ring_buffer_t * buffer;
  20. };
  21. static void close_complete(struct unix_pipe * self) {
  22. ring_buffer_destroy(self->buffer);
  23. }
  24. static uint32_t read_unixpipe(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  25. struct unix_pipe * self = node->device;
  26. size_t read = 0;
  27. while (read < size) {
  28. if (self->write_closed && !ring_buffer_unread(self->buffer)) {
  29. return read;
  30. }
  31. size_t r = ring_buffer_read(self->buffer, 1, buffer+read);
  32. if (r && *((char *)(buffer + read)) == '\n') {
  33. return read+r;
  34. }
  35. read += r;
  36. }
  37. return read;
  38. }
  39. static uint32_t write_unixpipe(fs_node_t * node, uint32_t offset, uint32_t size, uint8_t *buffer) {
  40. struct unix_pipe * self = node->device;
  41. size_t written = 0;
  42. while (written < size) {
  43. if (self->read_closed) {
  44. /* SIGPIPE to current process */
  45. signal_t * sig = malloc(sizeof(signal_t));
  46. sig->handler = current_process->signals.functions[SIGPIPE];
  47. sig->signum = SIGPIPE;
  48. handle_signal((process_t *)current_process, sig);
  49. return written;
  50. }
  51. size_t w = ring_buffer_write(self->buffer, 1, buffer+written);
  52. written += w;
  53. }
  54. return written;
  55. }
  56. static void close_read_pipe(fs_node_t * node) {
  57. struct unix_pipe * self = node->device;
  58. debug_print(NOTICE, "Closing read end of pipe.");
  59. self->read_closed = 1;
  60. if (self->write_closed) {
  61. debug_print(NOTICE, "Both ends now closed, should clean up.");
  62. } else {
  63. ring_buffer_interrupt(self->buffer);
  64. }
  65. }
  66. static void close_write_pipe(fs_node_t * node) {
  67. struct unix_pipe * self = node->device;
  68. debug_print(NOTICE, "Closing write end of pipe.");
  69. self->write_closed = 1;
  70. if (self->read_closed) {
  71. debug_print(NOTICE, "Both ends now closed, should clean up.");
  72. } else {
  73. ring_buffer_interrupt(self->buffer);
  74. }
  75. }
  76. static int check_pipe(fs_node_t * node) {
  77. struct unix_pipe * self = node->device;
  78. if (ring_buffer_unread(self->buffer) > 0) {
  79. return 0;
  80. }
  81. return 1;
  82. }
  83. static int wait_pipe(fs_node_t * node, void * process) {
  84. struct unix_pipe * self = node->device;
  85. ring_buffer_select_wait(self->buffer, process);
  86. return 0;
  87. }
  88. int make_unix_pipe(fs_node_t ** pipes) {
  89. size_t size = UNIX_PIPE_BUFFER;
  90. pipes[0] = malloc(sizeof(fs_node_t));
  91. pipes[1] = malloc(sizeof(fs_node_t));
  92. memset(pipes[0], 0, sizeof(fs_node_t));
  93. memset(pipes[1], 0, sizeof(fs_node_t));
  94. sprintf(pipes[0]->name, "[pipe:read]");
  95. sprintf(pipes[1]->name, "[pipe:write]");
  96. pipes[0]->mask = 0666;
  97. pipes[1]->mask = 0666;
  98. pipes[0]->flags = FS_PIPE;
  99. pipes[1]->flags = FS_PIPE;
  100. pipes[0]->read = read_unixpipe;
  101. pipes[1]->write = write_unixpipe;
  102. pipes[0]->close = close_read_pipe;
  103. pipes[1]->close = close_write_pipe;
  104. /* Read end can wait */
  105. pipes[0]->selectcheck = check_pipe;
  106. pipes[0]->selectwait = wait_pipe;
  107. struct unix_pipe * internals = malloc(sizeof(struct unix_pipe));
  108. internals->read_end = pipes[0];
  109. internals->write_end = pipes[1];
  110. internals->read_closed = 0;
  111. internals->write_closed = 0;
  112. internals->buffer = ring_buffer_create(size);
  113. pipes[0]->device = internals;
  114. pipes[1]->device = internals;
  115. return 0;
  116. }