1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
45:
46: 47: 48: 49:
50:
51: #include "fimp_console.h"
52: #include <sys/consio.h>
53: #include <string.h>
54:
55: 56: 57:
58: LOCAL ER console_service(fimp_t *req);
59: LOCAL ER console_registfn(fimpinf_t *fimpinf, void *info);
60: LOCAL ER console_unregistfn(fimpinf_t *fimpinf);
61: LOCAL ER console_attachfn(coninf_t *coninf, void *info);
62: LOCAL ER console_detachfn(coninf_t *coninf);
63:
64: EXPORT const fs_fimp_t fimp_consolefs_entry = {
65: console_service,
66: console_registfn,
67: console_unregistfn,
68: console_attachfn,
69: console_detachfn,
70: 0,
71: 0,
72: 0,
73: FIMP_FLAG_PRIVILEGE,
74: 0,
75: };
76:
77:
78: #define ROOT_FID (0)
79: #define STDIN_FID (1)
80: #define STDOUT_FID (2)
81: #define STDERR_FID (3)
82: #define STDIN_FN "stdin"
83: #define STDOUT_FN "stdout"
84: #define STDERR_FN "stderr"
85:
86:
87: #define CHK_AND(flags, value) (((flags) & (value)) == (value))
88: #define CHK_OR(flags, value) (((flags) & (value)) != 0)
89:
90:
91: IMPORT ER ConsoleIO(INT ac, UB *av[]);
92:
93: 94: 95:
96: LOCAL INT get_con_fid(const coninf_t *coninf, const B *name)
97: {
98: INT len;
99:
100: len = strlen(coninf->connm);
101: if (*name++ == '/' && strncmp(coninf->connm, name, len) == 0) {
102:
103: if (strlen(name) == len) return ROOT_FID;
104: if (name[len] == '/') {
105: name += len + 1;
106: if (strcmp(name, STDIN_FN) == 0) return STDIN_FID;
107: if (strcmp(name, STDOUT_FN) == 0) return STDOUT_FID;
108: if (strcmp(name, STDERR_FN) == 0) return STDERR_FID;
109: }
110: }
111: return -1;
112: }
113:
114: 115: 116:
117: LOCAL ER console_open(struct fimp_open *req)
118: {
119: ER er;
120: INT fid;
121:
122: er = E_OK;
123: switch (fid = get_con_fid(req->coninf, req->path)) {
124: case ROOT_FID:
125: if (CHK_OR(req->oflags, O_CREAT)) er = EX_ACCES;
126: else if (CHK_OR(req->oflags, O_WRONLY)) er = EX_ISDIR;
127: break;
128: case STDIN_FID:
129: if (CHK_OR(req->oflags, O_CREAT | O_WRONLY)) er = EX_ACCES;
130: else if (CHK_OR(req->oflags, O_DIRECTORY)) er = EX_NOTDIR;
131: break;
132: case STDOUT_FID:
133: case STDERR_FID:
134: if (CHK_OR(req->oflags, O_CREAT | O_RDONLY)) er = EX_ACCES;
135: else if (CHK_OR(req->oflags, O_DIRECTORY)) er = EX_NOTDIR;
136: break;
137: default:
138: if (CHK_OR(req->oflags, O_CREAT)) er = EX_ACCES;
139: else er = EX_NOENT;
140: }
141:
142: if (er == E_OK) {
143: if (CHK_AND(req->oflags, O_CREAT | O_EXCL)) {
144: er = EX_EXIST;
145: } else {
146: *req->fid = fid;
147: }
148: }
149: return er;
150: }
151:
152: 153: 154:
155: LOCAL ER console_close(struct fimp_close *req)
156: {
157: switch (req->fid) {
158: case ROOT_FID:
159: case STDIN_FID:
160: case STDOUT_FID:
161: case STDERR_FID:
162: break;
163: default:
164: return EX_BADF;
165: }
166: return E_OK;
167: }
168:
169: 170: 171:
172: LOCAL ER console_read64(struct fimp_read64 *req)
173: {
174: ER er;
175: INT len;
176:
177: er = EX_BADF;
178: if (req->fid == STDIN_FID) {
179:
180: len = console_in((UW)req->coninf->consd, req->buf, *req->len);
181: if (len >= 0) {
182: *req->len = len;
183: er = E_OK;
184: } else {
185: *req->len = 0;
186: er = EX_INTR;
187: }
188: *req->retoff = 0;
189: }
190: return er;
191: }
192:
193: 194: 195:
196: LOCAL ER console_write64(struct fimp_write64 *req)
197: {
198: ER er;
199: W len;
200:
201: er = EX_BADF;
202: if (req->fid == STDOUT_FID || req->fid == STDERR_FID) {
203:
204: len = console_out((UW)req->coninf->consd, req->buf, *req->len);
205: *req->len = len;
206: *req->retoff = 0;
207: er = E_OK;
208: }
209: return er;
210: }
211:
212: 213: 214:
215: LOCAL ER set_stat64_us(struct stat64_us *stat, W fid)
216: {
217: INT size;
218: mode_t mode;
219:
220: switch(fid) {
221: case ROOT_FID:
222: size = 3;
223: mode = S_IFDIR | S_IRUSR | S_IXUSR;
224: break;
225: case STDIN_FID:
226: size = 0;
227: mode = S_IFCHR | S_IRUSR;
228: break;
229: case STDOUT_FID:
230: case STDERR_FID:
231: size = 0;
232: mode = S_IFCHR | S_IWUSR;
233: break;
234: default:
235: return EX_BADF;
236: }
237: memset(stat, 0, sizeof(struct stat64_us));
238: stat->st_ino = fid;
239: stat->st_size = size * sizeof(struct dirent);
240: stat->st_mode = mode;
241: return E_OK;
242: }
243:
244: 245: 246:
247: LOCAL ER console_stat64_us(struct fimp_stat64_us *req)
248: {
249: return set_stat64_us(req->buf, get_con_fid(req->coninf, req->path));
250: }
251:
252: 253: 254:
255: LOCAL ER console_fstat64_us(struct fimp_fstat64_us *req)
256: {
257: return set_stat64_us(req->buf, req->fid);
258: }
259:
260: 261: 262:
263: LOCAL ER console_chdir(struct fimp_chdir *req)
264: {
265: return (get_con_fid(req->coninf, req->path) == ROOT_FID) ?
266: E_OK : EX_NOENT;
267: }
268:
269: 270: 271:
272: LOCAL ER console_fchdir(struct fimp_fchdir *req)
273: {
274: if (req->fid != ROOT_FID) return EX_BADF;
275:
276: req->buf[0] = '/';
277: strcpy(&req->buf[1], req->coninf->connm);
278: return E_OK;
279: }
280:
281: 282: 283:
284: LOCAL ER console_getdents(struct fimp_getdents *req)
285: {
286: ino_t ino;
287: const B *fname;
288: struct dirent *dir;
289: off64_t off;
290: INT rlen, len, nlen, reclen;
291: ER er;
292:
293: if (req->fid != ROOT_FID) return EX_BADF;
294:
295: off = *req->off;
296: if ((off % sizeof(struct dirent)) != 0) return EX_NOENT;
297:
298: er = E_OK;
299: rlen = *req->len;
300: for (dir = req->buf, len = 0; len + RECLEN_DIRENT(1) <= rlen; ) {
301: switch (off / sizeof(struct dirent)) {
302: case 0:
303: ino = STDIN_FID;
304: fname = STDIN_FN;
305: break;
306: case 1:
307: ino = STDOUT_FID;
308: fname = STDOUT_FN;
309: break;
310: case 2:
311: ino = STDERR_FID;
312: fname = STDERR_FN;
313: break;
314: default:
315: fname = NULL;
316: break;
317: }
318: if (fname == NULL) break;
319:
320:
321: if ((nlen = strlen(fname)) > NAME_MAX) nlen = NAME_MAX;
322: reclen = RECLEN_DIRENT(nlen);
323: if (len + reclen > rlen) {
324: if (len == 0) er = EX_INVAL;
325: break;
326: }
327:
328:
329: strncpy(dir->d_name, fname, nlen);
330: dir->d_name[nlen] = '\0';
331: dir->d_ino = ino;
332: dir->d_reclen = reclen;
333: len += reclen;
334:
335:
336: off += sizeof(struct dirent);
337: dir = (struct dirent *)((UB*)dir + reclen);
338:
339:
340: if (rlen == sizeof(struct dirent)) break;
341: }
342: *req->retoff = off;
343: *req->len = len;
344: return er;
345: }
346:
347: 348: 349:
350: LOCAL ER console_service(fimp_t *req)
351: {
352: ER er;
353:
354: switch (req->com.r_code) {
355: case FIMP_OPEN:
356: er = console_open(&req->r_open);
357: break;
358: case FIMP_CLOSE:
359: er = console_close(&req->r_close);
360: break;
361: case FIMP_READ64:
362: er = console_read64(&req->r_read64);
363: break;
364: case FIMP_WRITE64:
365: er = console_write64(&req->r_write64);
366: break;
367: case FIMP_STAT64_US:
368: er = console_stat64_us(&req->r_stat64_us);
369: break;
370: case FIMP_FSTAT64_US:
371: er = console_fstat64_us(&req->r_fstat64_us);
372: break;
373: case FIMP_GETDENTS:
374: er = console_getdents(&req->r_getdents);
375: break;
376: case FIMP_CHDIR:
377: er = console_chdir(&req->r_chdir);
378: break;
379: case FIMP_FCHDIR:
380: er = console_fchdir(&req->r_fchdir);
381: break;
382: case FIMP_FSYNC:
383: case FIMP_SYNC:
384: er = E_OK;
385: break;
386: case FIMP_RMDIR:
387: er = EX_BUSY;
388: break;
389: default:
390: er = EX_NOTSUP;
391: }
392: return er;
393: }
394:
395: 396: 397:
398: LOCAL ER console_registfn(fimpinf_t *fimpinf, void *info)
399: {
400:
401: return E_OK;
402: }
403:
404: 405: 406:
407: LOCAL ER console_unregistfn(fimpinf_t *fimpinf)
408: {
409:
410: return E_OK;
411: }
412:
413: 414: 415:
416: LOCAL ER console_attachfn(coninf_t *coninf, void *info)
417: {
418: ER er;
419: UW port;
420:
421:
422: er = console_conf(CS_GETPORT, &port);
423: if (er < E_OK) {
424: if (er == E_RSFN) {
425:
426: if (ConsoleIO(0, NULL) >= E_OK) {
427: er = console_conf(CS_GETPORT, &port);
428: }
429: }
430: if (er < E_OK) return EX_IO;
431: }
432: coninf->consd = (void *)port;
433: return E_OK;
434: }
435:
436: 437: 438:
439: LOCAL ER console_detachfn(coninf_t *coninf)
440: {
441:
442: return E_OK;
443: }
444: