1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12
13 /* File operation towards STDIN, STDOUT and STDERR */
14
15 #include "fd.h"
16 #include <assert.h>
17 #include <errno.h>
18 #include <sys/types.h>
19 #include <syscall_arch.h>
20 #include <sys/ioctl.h>
21 #include <sys/mman.h>
22 #include <chcore/memory.h>
23 #include <termios.h>
24
25 #include <chcore-internal/procmgr_defs.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <raw_syscall.h>
29 #include "stdio.h"
30
put(char buffer[],unsigned size)31 static void put(char buffer[], unsigned size)
32 {
33 chcore_syscall2(CHCORE_SYS_putstr, (vaddr_t)buffer, size);
34 }
35
36 #define MAX_LINE_SIZE 4095
37
chcore_stdio_fcntl(int fd,int cmd,int arg)38 int chcore_stdio_fcntl(int fd, int cmd, int arg)
39 {
40 int new_fd, ret = 0;
41
42 switch (cmd) {
43 case F_DUPFD_CLOEXEC:
44 case F_DUPFD: {
45 new_fd = dup_fd_content(fd, arg);
46 return new_fd;
47 }
48 default:
49 return -EINVAL;
50 }
51 return -1;
52 }
53
54 /* STDIN */
chcore_stdio_read(int fd,void * buf,size_t count)55 static ssize_t chcore_stdio_read(int fd, void *buf, size_t count)
56 {
57 return -EINVAL;
58 }
59
chcore_stdin_write(int fd,void * buf,size_t count)60 static ssize_t chcore_stdin_write(int fd, void *buf, size_t count)
61 {
62 return -EINVAL;
63 }
64
chcore_stdin_close(int fd)65 static int chcore_stdin_close(int fd)
66 {
67 free_fd(fd);
68 return 0;
69 }
70
chcore_stdio_ioctl(int fd,unsigned long request,void * arg)71 static int chcore_stdio_ioctl(int fd, unsigned long request, void *arg)
72 {
73 /* A fake window size */
74 if (request == TIOCGWINSZ) {
75 struct winsize *ws;
76
77 ws = (struct winsize *)arg;
78 ws->ws_row = 30;
79 ws->ws_col = 80;
80 ws->ws_xpixel = 0;
81 ws->ws_ypixel = 0;
82 return 0;
83 }
84 struct fd_desc *fdesc = fd_dic[fd];
85 assert(fdesc);
86 switch (request) {
87 case TCGETS: {
88 struct termios *t = (struct termios *)arg;
89 *t = fdesc->termios;
90 return 0;
91 }
92 case TCSETS:
93 case TCSETSW:
94 case TCSETSF: {
95 struct termios *t = (struct termios *)arg;
96 fdesc->termios = *t;
97 return 0;
98 }
99 }
100 warn("Unsupported ioctl fd=%d, cmd=0x%lx, arg=0x%lx\n", fd, request, arg);
101 return 0;
102 }
103
chcore_stdio_poll(int fd,struct pollarg * arg)104 static int chcore_stdio_poll(int fd, struct pollarg *arg)
105 {
106 return -EINVAL;
107 }
108
109 struct fd_ops stdin_ops = {
110 .read = chcore_stdio_read,
111 .write = chcore_stdin_write,
112 .close = chcore_stdin_close,
113 .poll = chcore_stdio_poll,
114 .ioctl = chcore_stdio_ioctl,
115 .fcntl = chcore_stdio_fcntl,
116 };
117
118 /* STDOUT */
119 #define STDOUT_BUFSIZE 1024
120
chcore_stdout_write(int fd,void * buf,size_t count)121 static ssize_t chcore_stdout_write(int fd, void *buf, size_t count)
122 {
123
124 char buffer[STDOUT_BUFSIZE];
125 size_t size = 0;
126
127 for (char *p = buf; p < (char *)buf + count; p++) {
128 if (size + 2 > STDOUT_BUFSIZE) {
129 put(buffer, size);
130 size = 0;
131 }
132
133 if (*p == '\n') {
134 buffer[size++] = '\r';
135 }
136 buffer[size++] = *p;
137 }
138
139 if (size > 0) {
140 put(buffer, size);
141 }
142
143 return count;
144 }
145
chcore_stdout_close(int fd)146 static int chcore_stdout_close(int fd)
147 {
148 free_fd(fd);
149 return 0;
150 }
151
152 struct fd_ops stdout_ops = {
153 .read = chcore_stdio_read,
154 .write = chcore_stdout_write,
155 .close = chcore_stdout_close,
156 .poll = chcore_stdio_poll,
157 .ioctl = chcore_stdio_ioctl,
158 .fcntl = chcore_stdio_fcntl,
159 };
160
161 /* STDERR */
chcore_stderr_read(int fd,void * buf,size_t count)162 static ssize_t chcore_stderr_read(int fd, void *buf, size_t count)
163 {
164 return -EINVAL;
165 }
166
chcore_stderr_write(int fd,void * buf,size_t count)167 static ssize_t chcore_stderr_write(int fd, void *buf, size_t count)
168 {
169 return chcore_stdout_write(fd, buf, count);
170 }
171
chcore_stderr_close(int fd)172 static int chcore_stderr_close(int fd)
173 {
174 free_fd(fd);
175 return 0;
176 }
177
178 struct fd_ops stderr_ops = {
179 .read = chcore_stderr_read,
180 .write = chcore_stderr_write,
181 .close = chcore_stderr_close,
182 .poll = NULL,
183 .ioctl = chcore_stdio_ioctl,
184 .fcntl = chcore_stdio_fcntl,
185 };