/* * This file is part of Jehanne. * * Copyright (C) 2015 Giacomo Tesio * * Jehanne is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 3 of the License. * * Jehanne is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Jehanne. If not, see . */ #include #include #include <9P2000.h> #include "console.h" #define WAIT_FOR(v) while(rendezvous(&v, (void*)0x12345) == (void*)~0) #define PROVIDE(v) while(rendezvous(&v, (void*)0x11111) == (void*)~0) /* debugging */ int debugging; extern void (*__assert)(char*); static int debugnotes(void *v, char *s) { debug("%d: noted: %s\n", getpid(), s); return 0; } static void traceassert(char*a) { fprint(2, "assert failed: %s, %#p %#p %#p %#p %#p %#p %#p %#p %#p %#p\n", a, __builtin_return_address(2), __builtin_return_address(3), __builtin_return_address(4), __builtin_return_address(5), __builtin_return_address(6), __builtin_return_address(7), __builtin_return_address(8), __builtin_return_address(9), __builtin_return_address(10), __builtin_return_address(11) ); exits(a); } void enabledebug(const char *file) { int fd; if (!debugging) { if((fd = open(file, OCEXEC|OTRUNC|OWRITE)) < 0){ debug("open: %r\n"); if((fd = ocreate(file, OCEXEC|OWRITE, 0666)) < 0) sysfatal("create %r"); } dup(fd, 2); close(fd); __assert = traceassert; if(!atnotify(debugnotes, 1)){ fprint(2, "atnotify: %r\n"); exits("atnotify"); } fmtinstall('F', fcallfmt); } ++debugging; } void debug(const char *fmt, ...) { va_list arg; if (debugging) { va_start(arg, fmt); vfprint(2, fmt, arg); va_end(arg); } } /* process management */ /* start the relevant services * * assumes that * - fd 0 can be read by inputFilter * - fd 1 can be written by outputFilter * - fd 2 can receive debug info (if debugging) * * returns the fd to mount */ int servecons(StreamFilter inputFilter, StreamFilter outputFilter, int *devmnt) { int pid, input, output, fs, mnt; pid = getpid(); rfork(RFNAMEG); debug("%s %d: started, linecontrol = %d, blind = %d\n", argv0, pid, linecontrol, blind); fs = fsinit(&mnt, devmnt); if(!debugging) close(2); /* start the file system */ switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFCENVG|RFNOTEG|RFCNAMEG|RFFDG)){ case -1: sysfatal("rfork (file server)"); break; case 0: close(0); close(1); close(mnt); PROVIDE(fs); rfork(RFREND); fsserve(fs); break; default: break; } WAIT_FOR(fs); close(fs); /* start output device writer */ debug("%s %d: starting output device writer\n", argv0, pid); switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNOTEG|RFFDG|RFNAMEG)){ case -1: sysfatal("rfork (output writer): %r"); break; case 0: if(mount(mnt, -1, "/dev", MBEFORE, "", *devmnt) == -1) sysfatal("mount (output writer): %r"); if((output = open("/dev/gconsout", OREAD)) == -1) sysfatal("open /dev/gconsout: %r"); close(0); PROVIDE(output); rfork(RFCENVG|RFCNAMEG|RFREND); outputFilter(output, 1); break; default: break; } /* start input device reader */ debug("%s %d: starting input device reader\n", argv0, pid); switch(rfork(RFPROC|RFMEM|RFNOWAIT|RFNOTEG|RFFDG|RFNAMEG)){ case -1: sysfatal("rfork (input reader): %r"); break; case 0: if(mount(mnt, -1, "/dev", MBEFORE, "", *devmnt) == -1) sysfatal("mount (input reader): %r"); if((input = open("/dev/gconsin", OWRITE)) == -1) sysfatal("open /dev/gconsin: %r"); close(1); PROVIDE(input); rfork(RFCENVG|RFCNAMEG|RFREND); inputFilter(0, input); break; default: break; } WAIT_FOR(input); WAIT_FOR(output); close(0); close(1); return mnt; } void post(char *srv, int fd) { int f; char buf[128]; fprint(2, "post %s...\n", srv); sprint(buf, "#s/%s", srv); f = ocreate(buf, OWRITE, 0666); if(f < 0) sysfatal("ocreate(%s)", srv); sprint(buf, "%d", fd); if(write(f, buf, strlen(buf)) != strlen(buf)) sysfatal("write"); close(f); }