- sudo apt-get update -qq
- sudo apt-get install -qq nasm
env:
- - ARCH=host HOST_ARCH=x86
+ - ARCH=host HOST_ARCH=x86 USE_ACPICA=0
- ARCH=host HOST_ARCH=x86_64 CC="$CC -m64"
script: "make all"
\r
KERNEL_SRC = ../../KernelLand/Kernel/\r
\r
-KERNEL_OBJ := logging.o adt.o lib.o libc.o debug.o messages.o drvutil_disk.o drvutil_video.o\r
+KERNEL_OBJ := logging.o adt.o lib.o debug.o messages.o drvutil_disk.o drvutil_video.o\r
+#KERNEL_OBJ += libc.o\r
KERNEL_OBJ += vfs/main.o vfs/open.o vfs/acls.o vfs/io.o vfs/dir.o\r
KERNEL_OBJ += vfs/nodecache.o vfs/mount.o vfs/memfile.o vfs/select.o\r
KERNEL_OBJ += vfs/fs/root.o vfs/fs/devfs.o\r
\r
KCPPFLAGS = -I include/ -I $(KERNEL_SRC)include/\r
CFLAGS += -Wall -g -std=gnu99\r
-LDFLAGS += -lSDL -lSDLmain -g -Wl,--defsym,__buildnum=$(BUILD_NUM)\r
+CPPFLAGS += $(shell sdl-config --cflags) -I /usr/include/\r
+LDFLAGS += $(shell sdl-config --libs) -g -Wl,--defsym,__buildnum=$(BUILD_NUM)\r
\r
ifeq ($(PLATFORM),win)\r
BIN := ../AcessKernel.exe\r
$(K_OBJ): $(KERNEL_SRC)obj-native-$(PLATFORM)/%.o: $(KERNEL_SRC)%.c\r
@mkdir -p $(dir $@)\r
@echo [CC] -o $@\r
- $(CC) -ffreestanding -c $< -o $@ $(CFLAGS) $(KCPPFLAGS) $(CPPFLAGS)\r
+ @$(CC) -ffreestanding -c $< -o $@ $(CFLAGS) $(KCPPFLAGS) $(CPPFLAGS)\r
\r
\r
\r
$(BUILDINFO_SRC): $(filter-out $(BUILDINFO_OBJ), $(OBJ)) Makefile\r
@echo "" > $@\r
- $(eval _GITHASH=$(shell (git log -n 1 | head -n 1 | awk '{print $$2}') || echo UNK))\r
- $(eval _GITCHANGED=$(shell (git status --porcelain | grep -c '^ M ') || echo UNK))\r
+ $(eval _GITHASH=$(shell (git log -n 1 | head -n 1 | awk '{print $$2}') 2>/dev/null || echo UNK))\r
+ $(eval _GITCHANGED=$(shell (git status --porcelain | grep -c '^ M ') 2>/dev/null || echo UNK))\r
+ $(eval _HOSTNAME=$(shell hostname --fqdn 2>/dev/null || hostname || echo UNK))\r
@echo "const char gsKernelVersion[] = \"$(ACESS_VERSION)\";" >> $@\r
@echo "const char gsGitHash[] = \"$(_GITHASH)\";" >> $@\r
- @echo "const char gsBuildInfo[] = \"Acess2 v$(KERNEL_VERSION) $(ARCH)-$(PLATFORM)\\\\r\\\\n\"" >> $@\r
- @echo " \"Build $(shell hostname --fqdn):$(BUILD_NUM) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@\r
+ @echo "const char gsBuildInfo[] = \"AcessNative $(ACESS_VERSION) $(ARCH)-$(PLATFORM)\\\\r\\\\n\"" >> $@\r
+ @echo " \"Build $(_HOSTNAME):$(BUILD_NUM) Git $(_GITHASH) - $(_GITCHANGED) modified\";" >> $@\r
@echo "const int giBuildNumber = $(BUILD_NUM);" >> $@\r
$(BUILDINFO_OBJ): $(BUILDINFO_SRC)\r
@echo [CC] -o $@\r
#include <stdlib.h>
#include <stdarg.h>
#include <sys/time.h>
+#include <string.h>
#if 0
void LogF(const char *Fmt, ...)
void Debug_PutCharDebug(char ch)
{
printf("%c", ch);
+ if( ch == '\n' )
+ fflush(stdout);
}
void Debug_PutStringDebug(const char *String)
{
printf("%s", String);
+ if( strchr(String, '\n') )
+ fflush(stdout);
}
void *Heap_Allocate(const char *File, int Line, int ByteCount)
free(Ptr);
}
+char *Heap_StringDup(const char *File, int Line, const char *Str)
+{
+ return strdup(Str);
+}
+
void Heap_Dump(void)
{
}
// nop
}
+int strpos(const char *str, char ch)
+{
+ const char *retptr = strchr(str, ch);
+ int rv = retptr ? retptr - str : -1;
+ return rv;
+}
+
+int CheckString(const char *string)
+{
+ if( (intptr_t)string < 0x1000 )
+ return 0;
+ return 1;
+}
+
+int CheckMem(const void *buf, size_t len)
+{
+ if( (intptr_t)buf < 0x1000 )
+ return 0;
+ return 1;
+}
+
+void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
+{
+ static const char cUCDIGITS[] = "0123456789ABCDEF";
+ char tmpBuf[64+1];
+ int pos=0, i;
+ Uint64 rem;
+
+ // Sanity check
+ if(!buf) return;
+
+ // Sanity Check
+ if(base > 16 || base < 2) {
+ buf[0] = 0;
+ return;
+ }
+
+ // Convert
+ while(num > base-1) {
+ rem = num % base;
+ num = num / base; // Shift `num` and get remainder
+ tmpBuf[pos] = cUCDIGITS[ rem ];
+ pos++;
+ }
+ tmpBuf[pos++] = cUCDIGITS[ num ]; // Last digit of `num`
+
+ // Put in reverse
+ i = 0;
+ minLength -= pos;
+ while(minLength-- > 0)
+ buf[i++] = pad;
+ while(pos-- > 0)
+ buf[i++] = tmpBuf[pos]; // Reverse the order of characters
+ buf[i] = 0;
+}
+
typedef int BOOL;
#include <stddef.h>
-#undef NULL
#undef offsetof
struct sShortSpinlock
extern void Heap_Deallocate(void *Ptr);
extern int Heap_IsHeapAddr(void *Ptr);
extern void Heap_Validate(void);
+extern char *Heap_StringDup(const char *File, int Line, const char *Str);
#define malloc(size) Heap_Allocate(_MODULE_NAME_"/"__FILE__, __LINE__, (size))
#define calloc(num,size) Heap_AllocateZero(_MODULE_NAME_"/"__FILE__, __LINE__, (num)*(size))
#define free(ptr) Heap_Deallocate((ptr))
#define IsHeap(ptr) Heap_IsHeapAddr((ptr))
-#define strdup(Str) _strdup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str))
+#define strdup(Str) Heap_StringDup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str))
#endif
tProcess *Process;
- Uint32 Events, WaitMask;
+ Uint32 EventState, WaitMask;
void *EventSem; // Should be SDL_sem, but I don't want SDL in this header
// Message queue
* nativefs.c\r
* - Host filesystem access\r
*/\r
-#define DEBUG 0\r
+#define DEBUG 1\r
#define off_t _acess_off_t\r
+#define sprintf _acess_sprintf\r
#include <acess.h> // Acess\r
#include <vfs.h> // Acess\r
#undef off_t\r
+#undef sprintf\r
#include <dirent.h> // Posix\r
#include <sys/stat.h> // Posix\r
#include <stdio.h> // Posix\r
LEAVE('i', 0);\r
return 0;\r
}\r
- LEAVE('-');\r
- return fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );\r
+ size_t ret = fread( Buffer, 1, Length, (FILE *)(tVAddr)Node->Inode );\r
+ LEAVE('x', ret);\r
+ return ret;\r
}\r
\r
size_t NativeFS_Write(tVFS_Node *Node, _acess_off_t Offset, size_t Length, const void *Buffer)\r
*
* Syscall Distribution
*/
-#define DEBUG 0
+#define DEBUG 1
#include <acess.h>
#include <threads.h>
#include <events.h>
a3 = *(_t3*)Args;Args+=sizeof(_t3);\
a4 = *(_t4*)Args;Args+=sizeof(_t4);\
a5 = *(_t5*)Args;Args+=sizeof(_t5);\
- LOG("SYSCALL5 '%s' %p %p %p %p %p %p", Fmt, (intptr_t)a0,(intptr_t)a1,(intptr_t)a2,(intptr_t)a3,(intptr_t)a4,(intptr_t)a5);\
+ LOG("SYSCALL6 '%s' %p %p %p %p %p %p", Fmt, (intptr_t)a0,(intptr_t)a1,(intptr_t)a2,(intptr_t)a3,(intptr_t)a4,(intptr_t)a5);\
_call\
}
#define SYSCALL5(_name, _fmtstr, _t0, _t1, _t2, _t3, _t4, _call) int _name(Uint*Errno,const char*Fmt,void*Args,int*Sizes){\
}
// === CODE ===
-int Syscall_Null(Uint*Errno, const char *Format, void *Args, int *Sizes)
+int Syscall_Null(Uint *Errno, const char *Format, void *Args, int *Sizes)
{
return 0;
}
);
SYSCALL2(Syscall_Open, "si", const char *, int,
- return VFS_Open(a0, a1|VFS_OPENFLAG_USER);
+ int rv = VFS_Open(a0, a1|VFS_OPENFLAG_USER);
+ if(rv == -1) *Errno = errno;
+ return rv;
);
SYSCALL1(Syscall_Close, "i", int,
VFS_Close(a0);
Log_Warning("Syscalls", "Read - %i < %i", Sizes[2], a1);
return -1;
}
- return VFS_Read(a0, a1, a2);
+ size_t rv = VFS_Read(a0, a1, a2);
+ if(rv == -1) *Errno = errno;
+ return rv;
);
SYSCALL3(Syscall_Write, "iid", int, int, const void *,
- if( Sizes[2] < a1 )
+ if( Sizes[2] < a1 ) {
+ *Errno = EINVAL;
return -1;
- return VFS_Write(a0, a1, a2);
+ }
+ size_t rv = VFS_Write(a0, a1, a2);
+ if(rv == -1) *Errno = errno;
+ return rv;
);
SYSCALL3(Syscall_Seek, "iIi", int, int64_t, int,
return VFS_Seek(a0, a1, a2);
);
SYSCALL3(Syscall_FInfo, "idi", int, void *, int,
if( Sizes[1] < sizeof(tFInfo)+a2*sizeof(tVFS_ACL)) {
- LOG("offsetof(size) = %i", offsetof(tFInfo, size));
+ //LOG("offsetof(size) = %i", offsetof(tFInfo, size));
LOG("Bad size %i < %i", Sizes[1], sizeof(tFInfo)+a2*sizeof(tVFS_ACL));
*Errno = -EINVAL;
return -1;
int argListLen = 0;
int i, retVal;
tRequestHeader *ret;
- int retValueCount = 1;
- int retDataLen = sizeof(Uint64);
+ int retValueCount;
+ int retDataLen;
void *returnData[Request->NParams];
int argSizes[Request->NParams];
Uint ret_errno = 0;
+ // Clear errno (Acess verson) at the start of the request
+ errno = 0;
+
// Sanity check
if( Request->CallID >= ciNumSyscalls ) {
Log_Notice("Syscalls", "Unknown syscall number %i", Request->CallID);
Log_Notice("Syscalls", "Unimplemented syscall %i", Request->CallID);
return NULL;
}
-
+
+ // Init return count/size
+ retValueCount = 2;
+ retDataLen = sizeof(Uint64) + sizeof(Uint32);
+
// Get size of argument list
for( i = 0; i < Request->NParams; i ++ )
{
case ARG_TYPE_DATA:
formatString[i] = 'd';
argListLen += sizeof(void*);
+ // Prepare the return values
+ if( Request->Params[i].Flags & ARG_FLAG_RETURN )
+ {
+ retDataLen += Request->Params[i].Length;
+ retValueCount ++;
+ }
break;
case ARG_TYPE_STRING:
formatString[i] = 's';
argListLen += sizeof(char*);
break;
default:
+ Log_Error("Syscalls", "Unknown param type %i", Request->Params[i].Type);
return NULL; // ERROR!
}
}
// Data gets special handling, because only it can be returned to the user
// (ARG_TYPE_DATA is a pointer)
case ARG_TYPE_DATA:
- // Prepare the return values
- if( Request->Params[i].Flags & ARG_FLAG_RETURN )
- {
- retDataLen += Request->Params[i].Length;
- retValueCount ++;
- }
-
// Check for non-resident data
if( Request->Params[i].Length == 0 )
{
}
}
+ // --- Perform request
retVal = caSyscalls[Request->CallID](&ret_errno, formatString, argListData, argSizes);
}
+ // ---------- Return
+
+ if( ret_errno == 0 && errno != 0 ) {
+ ret_errno = errno;
+ LOG("errno = %i", errno);
+ }
+
// Allocate the return
size_t msglen = sizeof(tRequestHeader) + retValueCount * sizeof(tRequestValue) + retDataLen;
ret = malloc(msglen);
*(Uint64*)inData = retVal;
inData += sizeof(Uint64);
+ // Static Uint32 errno value
+ ret->Params[1].Type = ARG_TYPE_INT32;
+ ret->Params[1].Flags = 0;
+ ret->Params[1].Length = sizeof(Uint32);
+ *(Uint32*)inData = ret_errno;
+ inData += sizeof(Uint32);
+
+ LOG("Ret: %llx, errno=%i", retVal, ret_errno);
+
//Log_Debug("Syscalls", "Return 0x%llx", retVal);
- retValueCount = 1;
+ retValueCount = 2;
for( i = 0; i < Request->NParams; i ++ )
{
if( Request->Params[i].Type != ARG_TYPE_DATA ) continue;
retValueCount ++;
}
- *ReturnLength = sizeof(tRequestHeader)
- + retValueCount * sizeof(tRequestValue)
- + retDataLen;
+ *ReturnLength = ret->MessageLength;
return ret;
}
//Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);
gpCurrentThread->WaitMask = Mask;
- if( !(gpCurrentThread->Events & Mask) )
+ if( !(gpCurrentThread->EventState & Mask) )
{
if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
}
//Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
}
- rv = gpCurrentThread->Events & Mask;
- gpCurrentThread->Events &= ~Mask;
+ rv = gpCurrentThread->EventState & Mask;
+ gpCurrentThread->EventState &= ~Mask;
gpCurrentThread->WaitMask = -1;
//Log_Debug("Threads", "- rv = %x", rv);
void Threads_PostEvent(tThread *Thread, Uint32 Events)
{
- Thread->Events |= Events;
+ Thread->EventState |= Events;
// Log_Debug("Threads", "Trigger event %x (->Events = %p) on %p", Events, Thread->Events, Thread);
if( Events == 0 || Thread->WaitMask & Events ) {
void Threads_ClearEvent(Uint32 EventMask)
{
- gpCurrentThread->Events &= ~EventMask;
+ gpCurrentThread->EventState &= ~EventMask;
}
// === PROTOTYPES ===
int Video_Install(char **Arguments);
-Uint64 Video_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
-Uint64 Video_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer);
+size_t Video_Read(tVFS_Node *Node, Uint64 Offset, size_t Length, void *Buffer);
+size_t Video_Write(tVFS_Node *Node, Uint64 Offset, size_t Length, const void *Buffer);
int Video_IOCtl(tVFS_Node *Node, int ID, void *Data);
// --- 2D Acceleration Functions --
void Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
/**
* \brief Read from framebuffer (unimplemented)
*/
-Uint64 Video_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
+size_t Video_Read(tVFS_Node *Node, Uint64 Offset, size_t Length, void *Buffer)
{
return 0;
}
/**
* \brief Write to the framebuffer
*/
-Uint64 Video_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)
+size_t Video_Write(tVFS_Node *Node, Uint64 Offset, size_t Length, const void *Buffer)
{
int i;
ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
ifeq ($(PLATFORM),win)
BIN := ../ld-acess.exe
- LDFLAGS += -lws2_32
+ LINKADDR := 0x70000000
+ LDFLAGS += -lws2_32 -Wl,--image-base,$(LINKADDR)
endif
ifeq ($(PLATFORM),lin)
BIN := ../ld-acess
strcat(tmp, "/");
strcat(tmp, Name);
- fd = acess_open(tmp, 4); // OPENFLAG_EXEC
+ fd = acess__SysOpen(tmp, 4); // OPENFLAG_EXEC
if(fd != -1) {
- acess_close(fd);
+ acess__SysClose(fd);
return strdup(tmp);
}
}
printf("Binary_LocateLibrary: tmp = '%s'\n", tmp);
#endif
- fd = acess_open(tmp, 4); // OPENFLAG_EXEC
+ fd = acess__SysOpen(tmp, 4); // OPENFLAG_EXEC
if(fd != -1) {
- acess_close(fd);
+ acess__SysClose(fd);
return strdup(tmp);
}
}
}
}
- fd = acess_open(Filename, 2|1); // Execute and Read
+ fd = acess__SysOpen(Filename, 2|1); // Execute and Read
if( fd == -1 ) {
// TODO: Handle libary directories
perror("Opening binary");
return NULL;
}
- acess_read(fd, &dword, 4);
- acess_seek(fd, 0, ACESS_SEEK_SET);
+ acess__SysRead(fd, &dword, 4);
+ acess__SysSeek(fd, 0, ACESS_SEEK_SET);
if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) {
fmt = &gElf_FormatDef;
}
else {
fprintf(stderr, "Unknown executable format (0x%08x)\n", dword);
- acess_close(fd);
+ acess__SysClose(fd);
return NULL;
}
printf("fmt->Load(0x%x)...\n", fd);
#endif
ret = fmt->Load(fd);
- acess_close(fd);
+ acess__SysClose(fd);
#if DEBUG
printf("fmt->Load(0x%x): %p\n", fd, ret);
#endif
Binary_SetReadyToUse(Base);
}
-static inline int SysSetMemFlags(uintptr_t Addr, unsigned int flags, unsigned int mask)
+static inline int _SysSetMemFlags(uintptr_t Addr, unsigned int flags, unsigned int mask)
{
return 0;
}
+
extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount);
extern uintptr_t FindFreeRange(size_t ByteCount, int MaxBits);
Elf64_Ehdr hdr;\r
\r
// Read ELF Header\r
- acess_read(FD, &hdr, sizeof(hdr));\r
+ acess__SysRead(FD, &hdr, sizeof(hdr));\r
\r
// Check the file type\r
if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {\r
return NULL;\r
}\r
LOG("hdr.phoff = 0x%08x\n", hdr->phoff);\r
- acess_seek(FD, hdr->phoff, ACESS_SEEK_SET);\r
- acess_read(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
+ acess__SysSeek(FD, hdr->phoff, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
\r
// Count Pages\r
iPageCount = 0;\r
char *tmp;\r
//if(ret->Interpreter) continue;\r
tmp = malloc(phtab[i].FileSize);\r
- acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
- acess_read(FD, tmp, phtab[i].FileSize);\r
+ acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, tmp, phtab[i].FileSize);\r
//ret->Interpreter = Binary_RegInterp(tmp);\r
LOG("Interpreter '%s'\n", tmp);\r
free(tmp);\r
return NULL;\r
}\r
\r
- acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
- acess_read(FD, PTRMK(void, addr), phtab[i].FileSize);\r
+ acess__SysSeek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, PTRMK(void, addr), phtab[i].FileSize);\r
memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
}\r
\r
return NULL;\r
}\r
LOG("hdr.phoff = 0x%08llx\n", (long long)hdr->e_phoff);\r
- acess_seek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
- acess_read(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\r
+ acess__SysSeek(FD, hdr->e_phoff, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, phtab, sizeof(Elf64_Phdr) * hdr->e_phnum);\r
\r
// Count Pages\r
iPageCount = 0;\r
//if(ret->Interpreter) continue;\r
tmp = malloc(phtab[i].p_filesz+1);\r
tmp[ phtab[i].p_filesz ] = 0;\r
- acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
- acess_read(FD, tmp, phtab[i].p_filesz);\r
+ acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, tmp, phtab[i].p_filesz);\r
//ret->Interpreter = Binary_RegInterp(tmp);\r
LOG("Interpreter '%s'\n", tmp);\r
free(tmp);\r
return NULL;\r
}\r
\r
- acess_seek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
- acess_read(FD, PTRMK(void, addr), phtab[i].p_filesz);\r
+ acess__SysSeek(FD, phtab[i].p_offset, ACESS_SEEK_SET);\r
+ acess__SysRead(FD, PTRMK(void, addr), phtab[i].p_filesz);\r
memset( PTRMK(char, addr) + phtab[i].p_filesz, 0, phtab[i].p_memsz - phtab[i].p_filesz );\r
}\r
\r
#include <stdarg.h>
#include <stddef.h>
-#define DEBUG(v...) do{}while(0)//Debug(v)
+#define DEBUG(v...) Debug(v)
+//#define DEBUG(v...) do{}while(0)//Debug(v)
#define PAGE_SIZE 4096
typedef struct sFILE FILE;
// === CODE ===
// --- VFS Calls
-int acess_chdir(const char *Path)
+int acess__SysChdir(const char *Path)
{
return _Syscall(SYS_CHDIR, ">s", Path);
}
-int acess_open(const char *Path, int Flags)
+int acess__SysOpen(const char *Path, int Flags)
{
if( strncmp(Path, "$$$$", 4) == 0 )
{
return _Syscall(SYS_OPEN, ">s >i", Path, Flags);
}
-void acess_close(int FD) {
+void acess__SysClose(int FD)
+{
if(FD & NATIVE_FILE_MASK) {
return native_close(FD & (NATIVE_FILE_MASK-1));
}
_Syscall(SYS_CLOSE, ">i", FD);
}
-int acess_reopen(int FD, const char *Path, int Flags) {
+int acess__SysReopen(int FD, const char *Path, int Flags) {
DEBUG("reopen(0x%x, \"%s\", 0x%x)", FD, Path, Flags);
return _Syscall(SYS_REOPEN, ">i >s >i", FD, Path, Flags);
}
-size_t acess_read(int FD, void *Dest, size_t Bytes) {
+size_t acess__SysRead(int FD, void *Dest, size_t Bytes) {
if(FD & NATIVE_FILE_MASK)
return native_read(FD & (NATIVE_FILE_MASK-1), Dest, Bytes);
// if( FD > 2 )
return _Syscall(SYS_READ, ">i >i <d", FD, Bytes, Bytes, Dest);
}
-size_t acess_write(int FD, const void *Src, size_t Bytes) {
+size_t acess__SysWrite(int FD, const void *Src, size_t Bytes) {
if(FD & NATIVE_FILE_MASK)
return native_write(FD & (NATIVE_FILE_MASK-1), Src, Bytes);
// if( FD > 2 )
return _Syscall(SYS_WRITE, ">i >i >d", FD, Bytes, Bytes, Src);
}
-int acess_seek(int FD, int64_t Ofs, int Dir) {
+int acess__SysSeek(int FD, int64_t Ofs, int Dir)
+{
if(FD & NATIVE_FILE_MASK) {
return native_seek(FD & (NATIVE_FILE_MASK-1), Ofs, Dir);
}
return _Syscall(SYS_SEEK, ">i >I >i", FD, Ofs, Dir);
}
-uint64_t acess_tell(int FD) {
+uint64_t acess__SysTell(int FD)
+{
if(FD & NATIVE_FILE_MASK)
return native_tell( FD & (NATIVE_FILE_MASK-1) );
DEBUG("tell(0x%x)", FD);
return _Syscall(SYS_TELL, ">i", FD);
}
-int acess_ioctl(int fd, int id, void *data) {
+int acess__SysIOCtl(int fd, int id, void *data) {
int len;
DEBUG("ioctl(%i, %i, %p)", fd, id, data);
// NOTE: The length here is hacky and could break
len = PAGE_SIZE - ((uintptr_t)data % PAGE_SIZE);
return _Syscall(SYS_IOCTL, ">i >i ?d", fd, id, len, data);
}
-int acess_finfo(int fd, t_sysFInfo *info, int maxacls) {
+int acess__SysFInfo(int fd, t_sysFInfo *info, int maxacls) {
// DEBUG("offsetof(size, t_sysFInfo) = %i", offsetof(t_sysFInfo, size));
DEBUG("finfo(%i, %p, %i)", fd, info, maxacls);
return _Syscall(SYS_FINFO, ">i <d >i",
);
}
-int acess_SysReadDir(int fd, char *dest) {
+int acess__SysReadDir(int fd, char *dest) {
DEBUG("SysReadDir(%i, %p)", fd, dest);
return _Syscall(SYS_READDIR, ">i <d", fd, 256, dest);
}
-int acess__SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *error, time_t *timeout, uint32_t events)
+int acess__SysSelect(int nfds, fd_set *read, fd_set *write, fd_set *error, int64_t *timeout, uint32_t events)
{
DEBUG("_SysSelect(%i, %p, %p, %p, %p, 0x%x)", nfds, read, write, error, timeout, events);
return _Syscall(SYS_SELECT, ">i ?d ?d ?d >d >i", nfds,
);
}
-int acess_select(int nfds, fd_set *read, fd_set *write, fd_set *error, time_t *timeout)
-{
- return acess__SysSelect(nfds, read, write, error, timeout, 0);
-}
-
-
int acess__SysOpenChild(int fd, char *name, int flags) {
DEBUG("_SysOpenChild(0x%x, '%s', 0x%x)", fd, name, flags);
return _Syscall(SYS_OPENCHILD, ">i >s >i", fd, name, flags);
}
// --- Memory Management ---
-uint64_t acess__SysAllocate(uint vaddr)
+uint64_t acess__SysAllocate(uintptr_t vaddr)
{
if( AllocateMemory(vaddr, 0x1000) == -1 ) // Allocate a page
return 0;
}
// --- Process Management ---
-int acess_clone(int flags, void *stack)
+int acess__SysClone(int flags, void *stack)
{
#ifdef __WIN32__
Warning("Win32 does not support anything like fork(2), cannot emulate");
#endif
}
-int acess_execve(char *path, char **argv, const char **envp)
+int acess__SysExecVE(char *path, char **argv, const char **envp)
{
int i, argc;
return kernel_tid;
}
-void acess_sleep(void)
-{
- DEBUG("%s()", __func__);
- _Syscall(SYS_SLEEP, "");
-}
+//void acess_sleep(void)
+//{
+// DEBUG("%s()", __func__);
+// _Syscall(SYS_SLEEP, "");
+//}
-int acess_waittid(int TID, int *ExitStatus)
+int acess__SysWaitTID(int TID, int *ExitStatus)
{
DEBUG("%s(%i, %p)", __func__, TID, ExitStatus);
return _Syscall(SYS_WAITTID, ">i <d", TID, sizeof(int), &ExitStatus);
int acess_getuid(void) { return _Syscall(SYS_GETUID, ""); }
int acess_getgid(void) { return _Syscall(SYS_GETGID, ""); }
-int acess_SysSendMessage(int DestTID, int Length, void *Data)
+int acess__SysSendMessage(int DestTID, int Length, void *Data)
{
DEBUG("%s(%i, 0x%x, %p)", __func__, DestTID, Length, Data);
return _Syscall(SYS_SENDMSG, ">i >d", DestTID, Length, Data);
}
-int acess_SysGetMessage(int *SourceTID, int BufLen, void *Data)
+int acess__SysGetMessage(int *SourceTID, int BufLen, void *Data)
{
DEBUG("%s(%p, %p)", __func__, SourceTID, Data);
return _Syscall(SYS_GETMSG, "<d <d",
exit(Status);
}
+uint32_t acess__SysSetMemFlags(uintptr_t vaddr, uint32_t flags, uint32_t mask)
+{
+ // TODO: Impliment acess__SysSetMemFlags?
+ return 0;
+}
+
// === Symbol List ===
#define DEFSYM(name) {#name, &acess_##name}
const tSym caBuiltinSymbols[] = {
DEFSYM(_exit),
- DEFSYM(chdir),
- DEFSYM(open),
- DEFSYM(close),
- DEFSYM(reopen),
- DEFSYM(read),
- DEFSYM(write),
- DEFSYM(seek),
- DEFSYM(tell),
- DEFSYM(ioctl),
- DEFSYM(finfo),
- DEFSYM(SysReadDir),
- DEFSYM(select),
+ DEFSYM(_SysChdir),
+ DEFSYM(_SysOpen),
DEFSYM(_SysOpenChild),
+ DEFSYM(_SysReopen),
+ DEFSYM(_SysClose),
+ DEFSYM(_SysRead),
+ DEFSYM(_SysWrite),
+ DEFSYM(_SysSeek),
+ DEFSYM(_SysTell),
+ DEFSYM(_SysIOCtl),
+ DEFSYM(_SysFInfo),
+ DEFSYM(_SysReadDir),
DEFSYM(_SysGetACL),
DEFSYM(_SysMount),
DEFSYM(_SysSelect),
- DEFSYM(clone),
- DEFSYM(execve),
+ DEFSYM(_SysClone),
+ DEFSYM(_SysExecVE),
DEFSYM(_SysSpawn),
- DEFSYM(sleep),
+// DEFSYM(sleep),
- DEFSYM(waittid),
+ DEFSYM(_SysWaitTID),
DEFSYM(gettid),
DEFSYM(setuid),
DEFSYM(setgid),
DEFSYM(getuid),
DEFSYM(getgid),
- DEFSYM(SysSendMessage),
- DEFSYM(SysGetMessage),
+ DEFSYM(_SysSendMessage),
+ DEFSYM(_SysGetMessage),
DEFSYM(_SysAllocate),
+ DEFSYM(_SysSetMemFlags),
DEFSYM(_SysDebug),
DEFSYM(_SysSetFaultHandler),
DEFSYM(_SysWaitEvent),
// Syscall request (used by acess_*)
extern uint64_t _Syscall(int SyscallID, const char *ArgTypes, ...);
+extern int acess__errno;
+
extern int native_open(const char *Path, int Flags);
extern void native_close(int FD);
extern size_t native_read(int FD, void *Dest, size_t Bytes);
extern int native_spawn(const char *filename, const char *const argv[], const char *const envp[]);
// Syscalls used by the linker
-extern int acess_open(const char *Path, int Flags);
-extern void acess_close(int FD);
-extern size_t acess_read(int FD, void *Dest, size_t Bytes);
-extern int acess_seek(int FD, int64_t Offset, int Dir);
+extern int acess__SysOpen(const char *Path, int Flags);
+extern void acess__SysClose(int FD);
+extern size_t acess__SysRead(int FD, void *Dest, size_t Bytes);
+extern int acess__SysSeek(int FD, int64_t Offset, int Dir);
// Symbol type
typedef struct {
}
if(strcmp(argv[i], "--open") == 0) {
- if( acess_open(argv[++i], 6) == -1 ) { // Read/Write
+ if( acess__SysOpen(argv[++i], 6) == -1 ) { // Read/Write
fprintf(stderr, "Unable to open '%s'\n", argv[i]);
exit(1);
}
base = Binary_Load(appPath, (uintptr_t*)&appMain);
printf("[DEBUG %i] base = %p\n", giSyscall_ClientID, base);
- if( !base ) return 127;
+ if( !base ) {
+ *((char*)NULL) = 0;
+ return 127;
+ }
printf("==============================\n");
printf("[DEBUG %i] %i ", giSyscall_ClientID, appArgc);
size_t size = (VirtAddr & 0xFFF) + ByteCount;
void *tmp;
#if __WIN32__
- tmp = VirtualAlloc((void*)base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ do
+ {
+ MEMORY_BASIC_INFORMATION info;
+ VirtualQuery( (void*)base, &info, sizeof(info) );
+ if( info.State != MEM_FREE ) {
+ printf("ERROR: Unable to allocate memory %p+0x%x, already allocated\n",
+ (void*)base, size);
+ base += 0x1000;
+ if( size < 0x1000 )
+ return 0;
+ size -= 0x1000;
+ }
+ else
+ break;
+ } while( size >= 0x1000 );
+ tmp = VirtualAlloc((void*)base, size, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if( tmp == NULL ) {
- printf("ERROR: Unable to allocate memory (0x%x)\n", (int)GetLastError());
+ printf("ERROR: Unable to allocate memory %p+%x (0x%x)\n",
+ (void*)base, size,
+ (int)GetLastError());
return -1;
}
#else
/*
*/
-#define DEBUG 0
+#define DEBUG 1
#if DEBUG
memset((void *)&gSyscall_ServerAddr, '\0', sizeof(struct sockaddr_in));
gSyscall_ServerAddr.sin_family = AF_INET;
gSyscall_ServerAddr.sin_port = htons(SERVER_PORT);
+ gSyscall_ServerAddr.sin_addr.s_addr = htonl(0x7F000001);
}
int _InitSyscalls(void)
exit(0);
}
- #if 0
- // Set client address
- memset((void *)&client, '\0', sizeof(struct sockaddr_in));
- client.sin_family = AF_INET;
- client.sin_port = htons(0);
- client.sin_addr.s_addr = htonl(0x7F000001);
- #endif
-
#if USE_TCP
if( connect(gSocket, (struct sockaddr *)&gSyscall_ServerAddr, sizeof(struct sockaddr_in)) < 0 )
{
fprintf(stderr, "[ERROR -] Cannot connect to server (localhost:%i)\n", SERVER_PORT);
perror("_InitSyscalls");
#if __WIN32__
+ fprintf(stderr, "[ERROR -] - WSAGetLastError said %i", WSAGetLastError());
closesocket(gSocket);
WSACleanup();
#else
#endif
#if 0
+ // Set client address
+ memset((void *)&client, '\0', sizeof(struct sockaddr_in));
+ client.sin_family = AF_INET;
+ client.sin_port = htons(0);
+ client.sin_addr.s_addr = htonl(0x7F000001);
// Bind
if( bind(gSocket, (struct sockaddr *)&client, sizeof(struct sockaddr_in)) == -1 )
{
}
if( ret == 0 ) {
fprintf(stderr, "[ERROR %i] Connection closed.\n", giSyscall_ClientID);
+ #if __WIN32__
+ closesocket(gSocket);
+ #else
close(gSocket);
+ #endif
exit(0);
}
#include <string.h>
#include <stddef.h>
#include <unistd.h>
-#include <spawn.h> // posix_spawn
+#ifndef __WIN32__
+# include <spawn.h> // posix_spawn
+#endif
#include "request.h"
#if SYSCALL_TRACE
#define DEBUG(...) do{}while(0)
#endif
+#define assert(cnd) do{ \
+ if( !(cnd) ) { \
+ fprintf(stderr, "%s:%i - assert failed - " #cnd, __FILE__, __LINE__);\
+ exit(-1); \
+ } \
+}while(0)
+
#define MAX_FPS 16
// === Types ===
{
va_list args;
int paramCount, dataLength;
- int retCount = 1, retLength = sizeof(uint64_t);
+ int retCount = 2, retLength = sizeof(uint64_t) + sizeof(uint32_t);
void **retPtrs; // Pointers to return buffers
const char *str;
tRequestHeader *req;
}
va_end(args);
- // Send syscall request
+ // --- Send syscall request
if( SendRequest(req, dataLength, retLength) < 0 ) {
fprintf(stderr, "syscalls.c: SendRequest failed (SyscallID = %i)\n", SyscallID);
exit(127);
}
- // Parse return value
- dataPtr = &req->Params[req->NParams];
- retValue = 0;
- if( req->NParams >= 1 )
- {
- switch(req->Params[0].Type)
- {
- case ARG_TYPE_INT64:
- retValue = *(uint64_t*)dataPtr;
- dataPtr += req->Params[0].Length;
- break;
- case ARG_TYPE_INT32:
- retValue = *(uint32_t*)dataPtr;
- dataPtr += req->Params[0].Length;
- break;
- }
- }
+ Debug("req->NParams = %i", req->NParams);
+ assert(req->NParams >= 2);
+ // return
+ assert(req->Params[0].Type == ARG_TYPE_INT64);
+ assert(req->Params[0].Length == sizeof(uint64_t));
+ retValue = *(uint64_t*)dataPtr;
+ dataPtr += sizeof(uint64_t);
+ // errno
+ assert(req->Params[1].Type == ARG_TYPE_INT32);
+ assert(req->Params[1].Length == sizeof(uint32_t));
+ acess__errno = *(uint32_t*)dataPtr;
+ dataPtr += sizeof(uint32_t);
// Write changes to buffers
- if( req->NParams - 1 != retCount ) {
+ if( req->NParams - 2 != retCount ) {
fprintf(stderr, "syscalls.c: Return count inbalance (%i - 1 != exp %i) [Call %i]\n",
req->NParams, retCount, SyscallID);
exit(127);
}
retCount = 0;
- for( i = 1; i < req->NParams; i ++ )
+ for( i = 2; i < req->NParams; i ++ )
{
#if 0
int j;
printf(" %02x", ((uint8_t*)dataPtr)[j]);
printf("\n");
#endif
+ assert( req->Params[i].Type == ARG_TYPE_DATA );
memcpy( retPtrs[retCount++], dataPtr, req->Params[i].Length );
dataPtr += req->Params[i].Length;
}
{
int rv;
+ #if __WIN32__
+ rv = _spawnve(_P_NOWAIT, filename, argv, envp);
+ #else
rv = posix_spawn(NULL, filename, NULL, NULL, (void*)argv, (void*)envp);
+ #endif
return rv;
}
tRequestValue Params[];
} tRequestHeader;
-enum eSyscalls {
- SYS_NULL,
-
- SYS_EXIT,
-
- SYS_OPEN,
- SYS_CLOSE,
- SYS_READ,
- SYS_WRITE,
- SYS_SEEK,
- SYS_TELL,
- SYS_IOCTL,
- SYS_FINFO,
- SYS_READDIR,
- SYS_OPENCHILD,
- SYS_GETACL,
- SYS_MOUNT,
- SYS_REOPEN,
- SYS_CHDIR,
-
- SYS_WAITTID,
- SYS_SETUID,
- SYS_SETGID,
-
- SYS_GETTID,
- SYS_GETPID,
- SYS_GETUID,
- SYS_GETGID,
- // IPC
- SYS_SLEEP,
- SYS_AN_FORK,
- SYS_AN_SPAWN,
- SYS_SENDMSG,
- SYS_GETMSG,
- SYS_SELECT,
- SYS_WAITEVENT,
-
+enum eSyscalls {
+ #define _(n) n
+ #include "syscalls_list.h"
+ #undef _
N_SYSCALLS
};
#ifndef DONT_INCLUDE_SYSCALL_NAMES
static const char * casSYSCALL_NAMES[] = {
- "SYS_NULL",
-
- "SYS_EXIT",
-
- "SYS_OPEN",
- "SYS_CLOSE",
- "SYS_READ",
- "SYS_WRITE",
- "SYS_SEEK",
- "SYS_TELL",
- "SYS_IOCTL",
- "SYS_FINFO",
- "SYS_READDIR",
- "SYS_OPENCHILD",
- "SYS_GETACL",
- "SYS_MOUNT",
- "SYS_REOPEN",
- "SYS_CHDIR",
-
- "SYS_WAITTID",
- "SYS_SETUID",
- "SYS_SETGID",
-
- "SYS_GETTID",
- "SYS_GETPID",
- "SYS_GETUID",
- "SYS_GETGID",
-
- // IPC
- "SYS_SLEEP",
- "SYS_AN_FORK",
- "SYS_SENDMSG",
- "SYS_GETMSG",
- "SYS_SELECT",
- "SYS_WAITEVENT"
+ #define _(n) #n
+ #include "syscalls_list.h"
+ #undef _
+ "-"
};
#endif
--- /dev/null
+_(SYS_NULL),
+
+_(SYS_EXIT),
+
+_(SYS_OPEN),
+_(SYS_CLOSE),
+_(SYS_READ),
+_(SYS_WRITE),
+_(SYS_SEEK),
+_(SYS_TELL),
+_(SYS_IOCTL),
+_(SYS_FINFO),
+_(SYS_READDIR),
+_(SYS_OPENCHILD),
+_(SYS_GETACL),
+_(SYS_MOUNT),
+_(SYS_REOPEN),
+_(SYS_CHDIR),
+
+_(SYS_WAITTID),
+_(SYS_SETUID),
+_(SYS_SETGID),
+
+_(SYS_GETTID),
+_(SYS_GETPID),
+_(SYS_GETUID),
+_(SYS_GETGID),
+
+// IPC
+_(SYS_SLEEP),
+_(SYS_AN_FORK),
+_(SYS_AN_SPAWN),
+_(SYS_SENDMSG),
+_(SYS_GETMSG),
+_(SYS_SELECT),
+_(SYS_WAITEVENT),
+
* acpica.c
* - ACPICA Interface
*/
-#define ACPI_DEBUG_OUTPUT 1
+#define ACPI_DEBUG_OUTPUT 0
#define DEBUG 0
#define _AcpiModuleName "Shim"
#define _COMPONENT "Acess"
// Create BIOS Call process
pid = Proc_Clone(CLONE_VM);
- Log_Debug("VM8086", "pid = %i", pid);
+ //Log_Debug("VM8086", "pid = %i", pid);
if(pid == -1)
{
Log_Error("VM8086", "Unable to clone kernel into VM8086 worker");
Uint16 * volatile rmstack; // Real Mode Stack
int i;
- Log_Debug("VM8086", "Initialising worker");
+ //Log_Debug("VM8086", "Initialising worker");
// Set Image Name
Threads_SetName("VM8086");
+++ /dev/null
-../x86/pci.c
\ No newline at end of file
--- /dev/null
+#include "../x86/pci.c"
va_list args;
#if LOCK_DEBUG_OUTPUT
- SHORTLOCK(&glDebug_Lock);
+ if(!CPU_HAS_LOCK(&glDebug_Lock)) SHORTLOCK(&glDebug_Lock);
#endif
Debug_Puts(0, "Debug: ");
va_list args;
#if LOCK_DEBUG_OUTPUT
- SHORTLOCK(&glDebug_Lock);
+ if( !CPU_HAS_LOCK(&glDebug_Lock) )
+ SHORTLOCK(&glDebug_Lock);
#endif
// And never SHORTREL
-/* AcessOS
- * FIFO Pipe Driver
+/*
+ * Acess2 Kernel
+ * - By John Hodge (thePowersGang)
+ *
+ * drv/fifo.c
+ * - FIFO Pipe Driver
*/
#define DEBUG 0
#include <acess.h>
if(Filename[0] == '\0') return NULL;
// Anon Pipe
- if(Filename[0] == 'a' && Filename[1] == 'n'
- && Filename[2] == 'o' && Filename[3] == 'n'
- && Filename[4] == '\0') {
+ if( strcmp(Filename, "anon") == 0 )
+ {
tmp = FIFO_Int_NewPipe(DEFAULT_RING_SIZE, "anon");
return &tmp->Node;
}
// Mark some flags
if( pipe->ReadPos == pipe->WritePos ) {
+ LOG("%i == %i, marking none to read", pipe->ReadPos, pipe->WritePos);
VFS_MarkAvaliable(Node, 0);
}
VFS_MarkFull(Node, 0); // Buffer can't still be full
while(remaining)
{
// Wait for buffer to empty
- if(pipe->Flags & PF_BLOCKING) {
- if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize )
+ if(pipe->Flags & PF_BLOCKING)
+ {
+ if( pipe->ReadPos == (pipe->WritePos+1)%pipe->BufSize ) {
+ LOG("Blocking write on FIFO");
VFS_SelectNode(Node, VFS_SELECT_WRITE, NULL, "FIFO_Write");
+ }
len = remaining;
if( pipe->ReadPos > pipe->WritePos )
if(len > pipe->BufSize - pipe->WritePos)
{
int ofs = pipe->BufSize - pipe->WritePos;
+ LOG("pipe->Buffer = %p, pipe->WritePos = %i, ofs=%i, len=%i",
+ pipe->Buffer, pipe->WritePos, ofs, len);
memcpy(&pipe->Buffer[pipe->WritePos], Buffer, ofs);
- memcpy(&pipe->Buffer, (Uint8*)Buffer + ofs, len-ofs);
+ memcpy(&pipe->Buffer[0], (Uint8*)Buffer + ofs, len-ofs);
}
else
{
+ LOG("pipe->Buffer = %p, pipe->WritePos = %i", pipe->Buffer, pipe->WritePos);
memcpy(&pipe->Buffer[pipe->WritePos], Buffer, len);
}
// Mark some flags
if( pipe->ReadPos == pipe->WritePos ) {
+ LOG("Buffer is full");
VFS_MarkFull(Node, 1); // Buffer full
}
VFS_MarkAvaliable(Node, 1);
tPipe *ret;
int namelen = strlen(Name) + 1;
int allocsize = sizeof(tPipe) + sizeof(tVFS_ACL) + Size + namelen;
-
+
+ ENTER("iSize sName", Size, Name);
+
ret = calloc(1, allocsize);
- if(!ret) return NULL;
+ if(!ret) LEAVE_RET('n', NULL);
- // Clear Return
+ // Set default flags
ret->Flags = PF_BLOCKING;
// Allocate Buffer
= ret->Node.MTime
= ret->Node.ATime = now();
ret->Node.Type = &gFIFO_PipeNodeType;
+
+ LEAVE('p', ret);
return ret;
}
if( !child )
{
child = calloc( 1, sizeof(tSysFS_Ent)+tmp+1 );
+ if( !child ) {
+ Log_Error("SysFS", "calloc(%i) failure", sizeof(tSysFS_Ent)+tmp+1);
+ return -1;
+ }
child->Next = NULL;
memcpy(child->Name, &Path[start], tmp);
child->Name[tmp] = '\0';
ent->Node.Size ++;
else
gSysFS_DriverInfo.RootNode.Size ++;
- Log_Log("SysFS", "Added directory '%s'", child->Name);
+ Log_Log("SysFS", "Added directory '%.*s'", tmp, &Path[start]);
+ Log_Log("SysFS", "Added directory '%.*s'", tmp, child->Name);
}
ent = child;
if( strcmp(opt, "Video") == 0 ) {
if( !gsVT_OutputDevice )
- gsVT_OutputDevice = strdup(val);
+ gsVT_OutputDevice = val;
}
else if( strcmp(opt, "Input") == 0 ) {
if( !gsVT_InputDevice )
- gsVT_InputDevice = strdup(val);
+ gsVT_InputDevice = val;
}
else if( strcmp(opt, "Width") == 0 ) {
giVT_RealWidth = atoi( val );
else if( strcmp(opt, "Scrollback") == 0 ) {
giVT_Scrollback = atoi( val );
}
+ else {
+ Log_Notice("VTerm", "Unknown option '%s'", opt);
+ }
}
}
// - Sanity Checking
size = term->Width*term->Height*4;
if( Offset > size ) {
- Log_Notice("VTerm", "VT_Write: Offset (0x%llx) > FBSize (0x%x)",
- Offset, size);
+ Log_Notice("VTerm", "VT_Write: %i Offset (0x%llx) > FBSize (0x%x)",
+ (int)Node->Inode, Offset, size);
return 0;
}
if( Offset + Length > size ) {
extern void VT_KBCallBack(Uint32 Codepoint);
// --- VT100 Emulation ---
extern void VT_int_ParseEscape_StandardLarge(tVTerm *Term, char CmdChar, int argc, int *args);
-extern int VT_int_ParseEscape(tVTerm *Term, const char *Buffer);
+extern int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes);
// --- Terminal Buffer ---
extern void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count);
extern void VT_int_PutChar(tVTerm *Term, Uint32 Ch);
*/
void VT_int_PutString(tVTerm *Term, const Uint8 *Buffer, Uint Count)
{
- Uint32 val;
int i;
// Iterate
for( i = 0; i < Count; i++ )
{
// Handle escape sequences
- if( Buffer[i] == 0x1B )
+ if( Buffer[i] == 0x1B && Count - i > 1 )
{
- i ++;
- i += VT_int_ParseEscape(Term, (const char*)&Buffer[i]) - 1;
- continue;
+ int ret = VT_int_ParseEscape(Term, (const char*)&Buffer[i+1], Count-(i+1));
+ if( ret > 0 )
+ {
+ i += ret;
+ continue;
+ }
}
// Fast check for non UTF-8
if( Buffer[i] < 128 ) // Plain ASCII
VT_int_PutChar(Term, Buffer[i]);
else { // UTF-8
+ Uint32 val;
i += ReadUTF8(&Buffer[i], &val) - 1;
VT_int_PutChar(Term, val);
}
* \fn int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
* \brief Parses a VT100 Escape code
*/
-int VT_int_ParseEscape(tVTerm *Term, const char *Buffer)
+int VT_int_ParseEscape(tVTerm *Term, const char *Buffer, size_t Bytes)
{
char c;
- int argc = 0, j = 1;
+ int argc = 0, j = 0;
int args[6] = {0,0,0,0};
int bQuestionMark = 0;
-
- switch(Buffer[0])
+
+ if( Bytes == j ) return j;
+ c = Buffer[j++];
+
+ switch(c)
{
//Large Code
case '[':
// Get Arguments
+ if(Bytes == j) return j;
c = Buffer[j++];
if(c == '?') {
bQuestionMark = 1;
+ if(Bytes == j) return j;
c = Buffer[j++];
}
if( '0' <= c && c <= '9' )
{
do {
- if(c == ';') c = Buffer[j++];
+ if(c == ';') {
+ if(Bytes == j) return j;
+ c = Buffer[j++];
+ }
while('0' <= c && c <= '9') {
args[argc] *= 10;
args[argc] += c-'0';
+ if(Bytes == j) return j;
c = Buffer[j++];
}
argc ++;
}
// Get Command
- if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
+ if( !('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z') )
{
- if( bQuestionMark )
+ // Error
+ return j;
+ }
+
+ if( bQuestionMark )
+ {
+ switch(c)
{
- switch(c)
+ // DEC Private Mode Set
+ case 'h':
+ if(argc != 1) break;
+ switch(args[0])
{
- // DEC Private Mode Set
- case 'h':
- if(argc != 1) break;
- switch(args[0])
- {
- case 25:
- Term->Flags &= ~VT_FLAG_HIDECSR;
- break;
- case 1047:
- VT_int_ToggleAltBuffer(Term, 1);
- break;
- }
+ case 25:
+ Term->Flags &= ~VT_FLAG_HIDECSR;
+ break;
+ case 1047:
+ VT_int_ToggleAltBuffer(Term, 1);
break;
- case 'l':
- if(argc != 1) break;
- switch(args[0])
- {
- case 25:
- Term->Flags |= VT_FLAG_HIDECSR;
- break;
- case 1047:
- VT_int_ToggleAltBuffer(Term, 0);
- break;
- }
+ }
+ break;
+ case 'l':
+ if(argc != 1) break;
+ switch(args[0])
+ {
+ case 25:
+ Term->Flags |= VT_FLAG_HIDECSR;
break;
- default:
- Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
+ case 1047:
+ VT_int_ToggleAltBuffer(Term, 0);
break;
}
+ break;
+ default:
+ Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
+ break;
}
- else
- {
- VT_int_ParseEscape_StandardLarge(Term, c, argc, args);
- }
+ }
+ else
+ {
+ VT_int_ParseEscape_StandardLarge(Term, c, argc, args);
}
break;
-
+ case '\0':
+ // Ignore \0
+ break;
default:
- Log_Notice("VTerm", "TODO: Handle short escape codes");
+ //Log_Notice("VTerm", "TODO: Handle short escape codes");
+ {
+ static volatile int tmp = 0;
+ if(tmp == 0) {
+ tmp = 1;
+ Debug("VTerm: Unknown short 0x%x", c);
+ tmp = 0;
+ }
+ }
break;
}
//! General purpose event for short waits
//! e.g. waiting for an IRQ in a Read() call
#define THREAD_EVENT_SHORTWAIT 0x00000010
+//! Fired when a child process quits
+#define THREAD_EVENT_DEADCHILD 0x00000020
#define THREAD_EVENT_USER1 0x10000000
#define THREAD_EVENT_USER2 0x20000000
struct sProcess *Process; //!< Thread Group / Process
struct sThread *Parent; //!< Parent Thread
char *ThreadName; //!< Name of thread
-
+
+ struct sThread *LastDeadChild; //!< Last child to die (will have the \a DeadChildren lock)
+ tMutex DeadChildLock; //!< Lock to prevent clobbering of \a LastDeadChild, acquired by child, released by parent
+
// --- arch/proc.c's responsibility
//! Kernel Stack Base
tVAddr KernelStack;
tVFS_ACL acls[]; //!< ACL buffer (size is passed in the \a MaxACLs argument to VFS_FInfo)
} PACKED tFInfo;
+// --- fd_set --
+#include "../../../Usermode/Libraries/ld-acess.so_src/include_exp/acess/fd_set.h"
+
+#if 0
/**
* \brief fd_set for select()
*/
* \param fdsetp Set to modify
*/
#define FD_ISSET(fd, fdsetp) ((fdsetp)->flags[(fd)/16]&(1<<((fd)%16)))
+#endif
// === FUNCTIONS ===
/**
if( Level >= NUM_LOG_LEVELS ) return;
va_copy(args_tmp, Args);
- len = vsnprintf(NULL, 256, Format, args_tmp);
+ len = vsnprintf(NULL, 0, Format, args_tmp);
#if USE_RING_BUFFER || !CACHE_MESSAGES
{
void *tmp;
tThread *cur = Proc_GetCurThread();
- ENTER("pSource pBuffer", Source, Buffer);
+ ENTER("pSource xBufSize pBuffer", Source, BufSize, Buffer);
// Check if queue has any items
if(!cur->Messages) {
+ LOG("empty queue");
LEAVE('i', 0);
return 0;
}
#define CHECK_STR_ARRAY(arr) do {\
int i;\
char **tmp = (char**)arr; \
- CHECK_NUM_NONULL( tmp, sizeof(char**) ); \
- for(i=0;tmp[i];i++) { \
+ CHECK_NUM_NULLOK( tmp, sizeof(char**) ); \
+ for(i=0;tmp&&tmp[i];i++) { \
CHECK_STR_NONULL( tmp[i] ); \
CHECK_NUM_NONULL( &tmp[i+1], sizeof(char*) ); \
}\
CHECK_STR_NONULL((const char*)Regs->Arg1);
CHECK_STR_ARRAY((const char**)Regs->Arg2);
CHECK_STR_ARRAY((const char**)Regs->Arg3);
- CHECK_NUM_NULLOK((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
+ if( Regs->Arg4 > 0 )
+ CHECK_NUM_NONULL((void*)Regs->Arg5, Regs->Arg4*sizeof(int));
ret = Proc_SysSpawn(
(const char*)Regs->Arg1, (const char**)Regs->Arg2, (const char**)Regs->Arg3,
Regs->Arg4, (int*)Regs->Arg5
if(Proc_Clone(CLONE_VM|CLONE_NOUSER) == 0)
{
const char *args[] = {gsInitBinary, 0};
+ VFS_Open("/Devices/VTerm/0", VFS_OPENFLAG_READ|VFS_OPENFLAG_USER); // 0: stdin
+ VFS_Open("/Devices/VTerm/0", VFS_OPENFLAG_WRITE|VFS_OPENFLAG_USER); // 1: stdout
Proc_Execve(gsInitBinary, args, &args[1], 0);
Log_KernelPanic("System", "Unable to spawn init '%s'", gsInitBinary);
}
#include <hal_proc.h>
#include <semaphore.h>
#include <vfs_threads.h> // VFS Handle maintainence
+#include <events.h>
// Configuration
#define DEBUG_TRACE_TICKETS 0 // Trace ticket counts
tTID Threads_WaitTID(int TID, int *Status)
{
// Any Child
- if(TID == -1) {
- Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
- return -1;
+ if(TID == -1)
+ {
+ Uint32 ev = Threads_WaitEvents(THREAD_EVENT_DEADCHILD);
+ tTID ret = -1;
+ if( ev & THREAD_EVENT_DEADCHILD )
+ {
+ // A child died, get the TID
+ tThread *us = Proc_GetCurThread();
+ ASSERT(us->LastDeadChild);
+ ret = us->LastDeadChild->TID;
+ // - Mark as dead (as opposed to undead)
+ ASSERT(us->LastDeadChild->Status == THREAD_STAT_ZOMBIE);
+ us->LastDeadChild->Status = THREAD_STAT_DEAD;
+ // - Set return status
+ if(Status)
+ *Status = us->LastDeadChild->RetStatus;
+ us->LastDeadChild = NULL;
+ Mutex_Release(&us->DeadChildLock);
+ }
+ else
+ {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
+ }
+ return ret;
}
// Any peer/child thread
}
// Specific Thread
- if(TID > 0) {
- tThread *t = Threads_GetThread(TID);
+ if(TID > 0)
+ {
tTID ret;
-
- // Wait for the thread to die!
- // TODO: Handle child also being suspended if wanted
- while(t->Status != THREAD_STAT_ZOMBIE) {
- Threads_Sleep();
- Log_Debug("Threads", "%i waiting for %i, t->Status = %i",
- Threads_GetTID(), t->TID, t->Status);
- }
-
- // Set return status
- ret = t->TID;
- switch(t->Status)
+ // NOTE: Race condition - Other child dies, desired child dies, first death is 'lost'
+ while( (ret = Threads_WaitTID(-1, Status)) != TID )
{
- case THREAD_STAT_ZOMBIE:
- // Kill the thread
- t->Status = THREAD_STAT_DEAD;
- // TODO: Child return value?
- if(Status) *Status = t->RetStatus;
- // add to delete queue
- Threads_Delete( t );
- break;
- default:
- if(Status) *Status = -1;
- break;
+ if( ret == -1 )
+ break;
}
return ret;
}
Thread->Status = THREAD_STAT_ZOMBIE;
SHORTREL( &glThreadListLock );
- // TODO: Send something like SIGCHLD
- Threads_Wake( Thread->Parent );
+ // TODO: It's possible that we could be timer-preempted here, should disable that... somehow
+ Mutex_Acquire( &Thread->Parent->DeadChildLock ); // released by parent
+ Thread->Parent->LastDeadChild = Thread;
+ Threads_PostEvent( Thread->Parent, THREAD_EVENT_DEADCHILD );
Log("Thread %i went *hurk* (%i)", Thread->TID, Status);
tVFS_Handle *h;
if( FDs == NULL )
h = &gaUserHandles[i];
- else {
+ else if( FDs[i] == -1 )
+ {
+ Log_Warning("VFS", "VFS_SaveHandles - Slot %i error FD (-1), ignorning", i);
+ memset(&ret[i], 0, sizeof(tVFS_Handle));
+ continue ;
+ }
+ else
+ {
h = VFS_GetHandle(FDs[i] & (VFS_KERNEL_FLAG - 1));
if(!h) {
Log_Warning("VFS", "VFS_SaveHandles - Invalid FD %i",
tThread *thisthread = Proc_GetCurThread();
int ret;
- ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout bIsKernel",
- MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, IsKernel);
+ ENTER("iMaxHandle pReadHandles pWriteHandles pErrHandles pTimeout xExtraEvents bIsKernel",
+ MaxHandle, ReadHandles, WriteHandles, ErrHandles, Timeout, ExtraEvents, IsKernel);
// Notes: The idea is to make sure we only enter wait (Threads_WaitEvents)
// if we are going to be woken up (either by an event at a later time,
// or the semaphore is incremeneted (or both, but never none)
// Register with nodes
+ if( ReadHandles )
+ LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
ret = VFS_int_Select_Register(thisthread, MaxHandle, ReadHandles, 0, IsKernel);
ret += VFS_int_Select_Register(thisthread, MaxHandle, WriteHandles, 1, IsKernel);
ret += VFS_int_Select_Register(thisthread, MaxHandle, ErrHandles, 2, IsKernel);
// If there were events waiting, de-register and return
if( ret > 0 )
{
+ LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
ret = VFS_int_Select_Deregister(thisthread, MaxHandle, ReadHandles, 0, IsKernel);
ret += VFS_int_Select_Deregister(thisthread, MaxHandle, WriteHandles, 1, IsKernel);
ret += VFS_int_Select_Deregister(thisthread, MaxHandle, ErrHandles, 2, IsKernel);
+ LOG(" - ReadHandles[0] = %x", ReadHandles->flags[0]);
LEAVE('i', ret);
return ret;
}
}
// Check for the flag
- if( !!*flag == !!wantedFlagValue )
+ if( !!*flag == !!wantedFlagValue ) {
+ LOG(" %i == want %i", !!*flag, !!wantedFlagValue);
numFlagged ++;
+ }
}
LEAVE('i', numFlagged);
continue;
}
- // Get the type of the listen
-
// Get the type of the listen
if( VFS_int_Select_GetType(Type, handle->Node, &list, &flag, &wantedFlagValue, NULL) ) {
LEAVE('i', 0);
// Check for the flag
if( !!*flag == !!wantedFlagValue ) {
numFlagged ++;
+ LOG(" %i == want %i", !!*flag, !!wantedFlagValue);
+ FD_SET(i, Handles);
}
else {
FD_CLR(i, Handles);
const tBGA_Mode *gpBGA_CurrentMode;\r
const tBGA_Mode gBGA_Modes[] = {\r
{640,480,32, 640*480*4},\r
+ {800,480,32, 800*480*4}, // Nice mode for VM testing\r
{800,600,32, 800*600*4},\r
{1024,768,32, 1024*768*4}\r
};\r
--- /dev/null
+/**
+ * Acess2 Raspberry Pi (BCM2835)
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Driver core
+ *
+ * http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/screen01.html
+ */
+#define DEBUG 0
+#define VERSION ((0<<8)|1)
+#include <acess.h>
+#include <errno.h>
+#include <modules.h>
+#include <vfs.h>
+#include <fs_devfs.h>
+#include <drv_pci.h>
+#include <api_drv_video.h>
+
+// === PROTOCOLS ===
+ int RPiVid_Install(const char **Arguments);
+// - GPU Communication
+ int RPiVid_int_MBoxCheck(Uint8 Box);
+Uint32 RPiVid_int_MBoxRecv(Uint8 Box);
+void RPiVid_int_MBoxSend(Uint8 Box, Uint32 Message);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, RPiVid, RPiVid_Install, NULL, NULL);
+
+// === CODE ===
+int RPiVid_Install(const char **Arguments)
+{
+ return 0;
+}
+
+
+// --- GPU Comms ---
+int RPiVid_int_MBoxCheck(Uint8 Box)
+{
+ return 0;
+}
+
+Uint32 RPiVid_int_MBoxRecv(Uint8 Box)
+{
+ Uint32 val;
+ do {
+ while( gRPiVid_Mbox->Status & (1 << 30) )
+ ;
+ val = gRPiVid_Mbox->Read;
+ } while( (val & 0xF) != Box );
+
+ return 0;
+}
+
+void RPiVid_int_MBoxSend(Uint8 Box, Uint32 Message)
+{
+ while( gRPiVid_Mbox.Status & (1 << 31) )
+ ;
+ gRPiVid_Mbox.Write = (Message << 4) | (Box & 0xF);
+}
+
files.$(ARCH).c: GenerateInitRD.php files.lst
+# Override default install method, because the floppy is small :)
+install:
+ true
+
-include files.$(ARCH).c.dep
File "ping" "__BIN__/Bin/ping"
File "telnet" "__BIN__/Bin/telnet"
File "irc" "__BIN__/Bin/irc"
+ File "bomb" "__BIN__/Bin/bomb"
File "dhcpc" "__BIN__/SBin/dhcpc"
}
Dir "Libs" {
File "libaxwin3.so" "__BIN__/Libs/libaxwin3.so"
File "libposix.so" "__BIN__/Libs/libposix.so"
File "libpsocket.so" "__BIN__/Libs/libpsocket.so"
+ File "libunicode.so" "__BIN__/Libs/libunicode.so"
}
Dir "Conf" {
- File "BootConf.cfg" "__FS__/Conf/BootConf.cfg"
+ File "inittab" "__FS__/Conf/inittab"
}
Dir "Apps" {
Dir "AxWin" {
File "AxWinWM" "__BIN__/Apps/AxWin/3.0/AxWinWM"
File "AxWinUI" "__BIN__/Apps/AxWin/3.0/AxWinUI"
File "ate" "__BIN__/Apps/AxWin/3.0/ate"
+ File "terminal" "__BIN__/Apps/AxWin/3.0/terminal"
File "AcessLogoSmall.sif" "__SRC__/Usermode/Applications/axwin3_src/AcessLogoSmall.sif"
}
}
UDP_SendPacketTo(chan, ep->AddrType, &ep->Addr, ep->Port, data, (size_t)Length - ofs);
- return 0;
+ return Length;
}
/**
{
int id = -1;
int i = 0;
-// Uint16 base;
tCard *card;
giRhine2_CardCount = PCI_CountDevices(VENDOR_ID, DEVICE_ID);
- Log_Debug("Rhine2", "giRhine2_CardCount = %i", giRhine2_CardCount);
if( giRhine2_CardCount == 0 ) return MODULE_ERR_NOTNEEDED;
gaRhine2_Cards = calloc( giRhine2_CardCount, sizeof(tCard) );
{
if(Pos < 0 || Pos > MAX_DISKS )
return -ENOENT;
- if(gaFDD_Disks[Pos].bValid)
+ if(!gaFDD_Disks[Pos].bValid)
return 1;
Dest[0] = '0' + Pos;
USRLIBS := crt0.o acess.ld ld-acess.so libc.so libposix.so
USRLIBS += libreadline.so libnet.so liburi.so libpsocket.so
-USRLIBS += libimage_sif.so
+USRLIBS += libimage_sif.so libunicode.so
USRAPPS := init login CLIShell cat ls mount
USRAPPS += bomb lspci
USRAPPS += ip dhcpclient ping telnet irc wget telnetd
-USRAPPS += axwin3 gui_ate
+USRAPPS += axwin3 gui_ate gui_shell
ALL_DYNMODS = $(addprefix all-,$(DYNMODS))
ALL_MODULES := $(addprefix all-,$(MODULES))
--- /dev/null
+GL control channel:
+ App -> GUI -> VTerm -> Driver
+- App creates 3D window
+- GUI passes X,Y WxH to VTerm (and can issue resize notices upwards)
+- VTerm passes to driver (and can disable display of local regions when VT switch)
+
+Allocates command ring buffer for libgl
+
-l*|-L*)
_libs=$_libs" $1"
;;
+ -v|--version|-V)
+ _verarg=$_verarg" $1"
+ ;;
+ --inv=ld)
+ _actas=ld
+ ;;
+ -print-prog-name=ld)
+ echo $0 --inv=ld
+ exit 0
+ ;;
*)
_miscargs=$_miscargs" $1"
;;
done
run() {
-# echo --- $*
+ #echo --- $*
$*
return $?
}
#echo "_compile = $_compile, _preproc = $_preproc"
+if [[ "x$_actas" == "xld" ]]; then
+ run $_LD $LDFLAGS $_ldflags $_outfile $_miscargs $LIBGCC_PATH $_libs
+ exit $?
+fi
+
if [[ $_preproc -eq 1 ]]; then
run $_CC -E $CFLAGS $_cflags $_miscargs $_outfile
elif [[ $_makedep -eq 1 ]]; then
elif echo " $_miscargs" | grep '\.c' >/dev/null; then
tmpout=`mktemp acess_gccproxy.XXXXXXXXXX.o --tmpdir`
run $_CC $CFLAGS $_cflags $_miscargs -c -o $tmpout
- run $_LD $LDFLAGS $_ldflags $_libs $tmpout $_outfile -lgcc $_libs
+ run $_LD $LDFLAGS $_ldflags $_libs $tmpout $_outfile $LIBGCC_PATH $_libs
+ _rv=$?
rm $tmpout
+ exit $_rv
else
run $_LD$_ldflags $_miscargs $_outfile $LDFLAGS $_libs
fi
void mainmenu_app_textedit(void *unused)
{
- const char *args[] = {"ate",NULL};
// _SysDebug("TODO: Launch text editor");
+ const char *args[] = {"ate",NULL};
_SysSpawn("/Acess/Apps/AxWin/3.0/ate", args, (const char **)gEnvion, 0, NULL, NULL);
}
void mainmenu_app_terminal(void *unused)
{
- _SysDebug("TODO: Launch terminal emulator");
+ _SysDebug("Launch terminal emulator");
+ const char *args[] = {"terminal",NULL};
+ _SysSpawn("/Acess/Apps/AxWin/3.0/terminal", args, (const char **)gEnvion, 0, NULL, NULL);
}
void mainmenu_run_dialog(void *unused)
DIR := Apps/AxWin/3.0
BIN := AxWinWM
-OBJ := main.o input.o video.o ipc.o image.o utf-8.o
+OBJ := main.o input.o video.o ipc.o image.o
OBJ += wm.o wm_input.o wm_render.o wm_render_text.o wm_hotkeys.o
OBJ += decorator.o
OBJ += renderers/framebuffer.o
OBJ += renderers/widget/spacer.o
OBJ += renderers/widget/subwin.o
-LDFLAGS += -limage_sif -luri -lnet
+LDFLAGS += -limage_sif -luri -lnet -lunicode
-include ../../Makefile.tpl
+++ /dev/null
-/*
- * Acess2 GUI (AxWin) Version 3
- * - By John Hodge (thePowersGang)
- *
- * utf8.h
- * - UTF-8 Parsing header
- */
-#ifndef _UTF8_H_
-#define _UTF8_H_
-
-#include <stdint.h>
-
-extern int ReadUTF8(const char *Input, uint32_t *Val);
-extern int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val);
-extern int WriteUTF8(char *buf, uint32_t Val);
-
-#endif
-
ASSERT(Msg->ID == IPCMSG_FOCUSWINDOW);
// Don't allow the focus to be changed unless the client has the focus
- if(!gpWM_FocusedWindow) return 1;
- if(gpWM_FocusedWindow->Client != Client) return 1;
+// if(!gpWM_FocusedWindow) return 1;
+// if(gpWM_FocusedWindow->Client != Client) return 1;
win = IPC_int_GetWindow(Client, Msg->Window);
if(!win) return 1;
Renderer_RichText_Init();
WM_Initialise();
- // TODO: Config
+ // TODO: Move these to config
uint32_t keys[4];
keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_r;
WM_Hotkey_Register(2, keys, "Interface>Run");
+ keys[0] = KEYSYM_LEFTGUI; keys[1] = KEYSYM_t;
+ WM_Hotkey_Register(2, keys, "Interface>Terminal");
// Spawn interface root
{
sprintf(server_info, "AXWIN3_SERVER=%i", server_tid);
// TODO: Does the client need FDs?
int rv = _SysSpawn(csInterfaceApp, argv, envp, 0, NULL, NULL);
- if( rv ) {
+ if( rv < 0 ) {
_SysDebug("_SysSpawn chucked a sad, rv=%i, errno=%i", rv, _errno);
}
}
{
short W, H;
void *Data;
- char _data[];
} tFBBuffer;
typedef struct
{
buf = malloc(sizeof(tFBBuffer) + msg->W * msg->H * 4);
buf->W = msg->W;
buf->H = msg->H;
- buf->Data = buf->_data;
+ buf->Data = buf + 1;
info->Buffers[msg->Buffer] = buf;
Window->W, (info->DispLines-i)*info->LineHeight,
info->DefaultBG
);
+
+ // HACK!
+ info->DispCols = Window->W / 8;
+
+ // TODO: Text cursor
+ _SysDebug("Cursor at %i,%i", info->CursorCol, info->CursorRow);
+ _SysDebug(" Range [%i+%i],[%i+%i]", info->FirstVisRow, info->DispLines, info->FirstVisCol, info->DispCols);
+ if( info->CursorRow >= info->FirstVisRow && info->CursorRow < info->FirstVisRow + info->DispLines )
+ {
+ if( info->CursorCol >= info->FirstVisCol && info->CursorCol < info->FirstVisCol + info->DispCols )
+ {
+ // TODO: Kill hardcoded 8 with cached text distance
+ WM_Render_FillRect(Window,
+ (info->CursorCol - info->FirstVisCol) * 8,
+ (info->CursorRow - info->FirstVisRow) * info->LineHeight,
+ 1,
+ info->LineHeight,
+ info->DefaultFG
+ );
+ }
+ }
}
int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data)
case _ATTR_DEFFG:
info->DefaultFG = msg->Value;
break;
+ case _ATTR_CURSORPOS:
+ info->CursorRow = msg->Value >> 12;
+ info->CursorCol = msg->Value & 0xFFF;
+ break;
case _ATTR_SCROLL:
// TODO: Set scroll flag
break;
}
line->ByteLength = Len - sizeof(*msg);
memcpy(line->Data, msg->LineData, Len - sizeof(*msg));
-
+
+ WM_Invalidate( Window );
+
return 0;
}
if(Len < sizeof(*msg)) return -1;
info->DispLines = msg->H / info->LineHeight;
return 1; }
+ case WNDMSG_KEYDOWN:
+ case WNDMSG_KEYUP:
+ case WNDMSG_KEYFIRE:
+ return 1;
}
return 0;
}
#include <common.h>
#include "./common.h"
#include "./colours.h"
-#include <utf8.h>
+#include <unicode.h>
#include <string.h>
// TODO: Include a proper keysym header
+++ /dev/null
-/*
- * Acess2 GUI (AxWin) Version 3
- * - By John Hodge (thePowersGang)
- *
- * utf-8.c
- * - UTF-8 Parsing code
- */
-#include <stdint.h>
-#include <utf8.h>
-
-/**
- * \brief Read a UTF-8 character from a string
- * \param Input Source UTF-8 encoded string
- * \param Val Destination for read codepoint
- * \return Number of bytes read/used
- */
-int ReadUTF8(const char *Input, uint32_t *Val)
-{
- const uint8_t *str = (const uint8_t *)Input;
- *Val = 0xFFFD; // Assume invalid character
-
- // ASCII
- if( !(*str & 0x80) ) {
- *Val = *str;
- return 1;
- }
-
- // Middle of a sequence
- if( (*str & 0xC0) == 0x80 ) {
- return 1;
- }
-
- // Two Byte
- if( (*str & 0xE0) == 0xC0 ) {
- *Val = (*str & 0x1F) << 6; // Upper 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 2;
- }
-
- // Three Byte
- if( (*str & 0xF0) == 0xE0 ) {
- *Val = (*str & 0x0F) << 12; // Upper 4 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 3;
- }
-
- // Four Byte
- if( (*str & 0xF8) == 0xF0 ) {
- *Val = (*str & 0x07) << 18; // Upper 3 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
- str ++;
- if( (*str & 0xC0) != 0x80) return -1; // Validity check
- *Val |= (*str & 0x3F); // Lower 6 Bits
- return 4;
- }
-
- // UTF-8 Doesn't support more than four bytes
- return 4;
-}
-
-/**
- * \brief Get the UTF-8 character before the
- * \
- */
-int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val)
-{
- int len = 0;
-
- // Scan backwards for the beginning of the character
- while( Offset > 0 && (Base[Offset--] & 0xC0) == 0x80 )
- len ++;
- // Invalid string (no beginning)
- if(Offset == 0 && (Base[Offset] & 0xC0) == 0x80 )
- return len;
-
- len ++; // First character
- if( ReadUTF8(Base+Offset, Val) != len ) {
- *Val = 0xFFFD;
- }
- return len;
-}
-
-/**
- * \brief Write a UTF-8 character sequence to a string
- * \param buf Destination buffer (must have at least 4 bytes available)
- * \param Val Unicode codepoint to write
- * \return Number of bytes written
- * \note Does not NULL terminate the string in \a buf
- */
-int WriteUTF8(char *buf, uint32_t Val)
-{
- uint8_t *str = (void*)buf;
-
- // ASCII
- if( Val < 128 ) {
- if(str) {
- *str = Val;
- }
- return 1;
- }
-
- // Two Byte
- if( Val < 0x8000 ) {
- if(str) {
- *str = 0xC0 | (Val >> 6);
- str ++;
- *str = 0x80 | (Val & 0x3F);
- }
- return 2;
- }
-
- // Three Byte
- if( Val < 0x10000 ) {
- if(str) {
- *str = 0xE0 | (Val >> 12);
- str ++;
- *str = 0x80 | ((Val >> 6) & 0x3F);
- str ++;
- *str = 0x80 | (Val & 0x3F);
- }
- return 3;
- }
-
- // Four Byte
- if( Val < 0x110000 ) {
- if(str) {
- *str = 0xF0 | (Val >> 18);
- str ++;
- *str = 0x80 | ((Val >> 12) & 0x3F);
- str ++;
- *str = 0x80 | ((Val >> 6) & 0x3F);
- str ++;
- *str = 0x80 | (Val & 0x3F);
- }
- return 4;
- }
-
- // UTF-8 Doesn't support more than four bytes
- return 0;
-}
-
_SysDebug("Video_Update - Updating lines %i to %i (0x%x+0x%x px)",
giVideo_FirstDirtyLine, giVideo_LastDirtyLine, ofs, size);
- _SysSeek(giTerminalFD, ofs*4, 1);
+ _SysSeek(giTerminalFD, ofs*4, SEEK_SET);
_SysDebug("Video_Update - Sending FD %i %p 0x%x", giTerminalFD, gpScreenBuffer+ofs, size*4);
_SysWrite(giTerminalFD, gpScreenBuffer+ofs, size*4);
_SysDebug("Video_Update - Done");
{
struct sWndMsg_Bool _msg;
+ _SysDebug("WM_FocusWindow(%p)", Destination);
+
if( gpWM_FocusedWindow == Destination )
return ;
if( Destination && !(Destination->Flags & WINFLAG_SHOW) )
#include <common.h>
#include <wm_internals.h>
#include <stdlib.h>
-#include <utf8.h>
+#include <unicode.h>
#include <limits.h> // INT_MAX
// === TYPES ===
#include "include/internal.h"
#include <richtext_messages.h>
#include <string.h>
+#include <wm_messages.h>
//#include <alloca.h>
// === TYPES ===
// === CODE ===
int AxWin3_RichText_MessageHandler(tHWND Window, int MessageID, int Size, void *Data)
{
+ tRichText_Window *info = AxWin3_int_GetDataPtr(Window);
+ struct sWndMsg_KeyAction *keyaction = Data;
+ _SysDebug("MessageID = %i", MessageID);
+ switch(MessageID)
+ {
+ case WNDMSG_KEYFIRE:
+ if(Size < sizeof(*keyaction)) return -1;
+ info->KeyCallback(Window, 2, keyaction->KeySym, keyaction->UCS32);
+ return 1;
+ }
return 0;
}
_SysIOCtl(Iface->IfaceFD, 6, Addr);
_SysIOCtl(Iface->IfaceFD, 7, &mask_bits);
- if( Router );
+ if( Router )
{
uint8_t *addr = Router;
_SysDebug("Router %i.%i.%i.%i", addr[0], addr[1], addr[2], addr[3]);
-include ../Makefile.cfg
-LDFLAGS += -laxwin3
+LDFLAGS += -laxwin3 -lunicode
-OBJ = main.o
+OBJ = main.o vt100.o display.o
BIN = terminal
DIR := Apps/AxWin/3.0
--- /dev/null
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * display.c
+ * - Abstract display manipulation methods
+ */
+#include "include/display.h"
+#include <acess/sys.h> // _SysDebug
+#include <stdlib.h> // exit
+#include <string.h>
+#include <unicode.h>
+#include <stdio.h>
+#include <axwin3/axwin.h>
+#include <axwin3/richtext.h>
+
+#define UNIMPLIMENTED() do{_SysDebug("UNIMPLIMENTED %s", __func__); exit(-1);}while(0)
+
+// === EXTERN ==
+extern tHWND gMainWindow;
+
+// === GLOBALS ===
+ int giDisplayCols;
+ int giDisplayLines;
+ int giDisplayTotalLines;
+ int giDisplayBufSize;
+ int giCurrentLine;
+ int giCurrentLinePos; // byte offset, not column
+ int giCurrentCol;
+ int giFirstDispLine; // First displayed line
+ int giFirstLine; // Ring buffer start
+char **gasDisplayLines;
+ int *gaiDisplayLineSizes;
+char *gabDisplayLinesDirty;
+
+// === CODE ===
+void Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
+{
+ giDisplayCols = Cols;
+ giDisplayLines = Lines;
+ giDisplayTotalLines = Lines + ExtraScrollbackLines;
+ gasDisplayLines = calloc( sizeof(char*), (Lines + ExtraScrollbackLines) );
+ gaiDisplayLineSizes = calloc( sizeof(int), (Lines + ExtraScrollbackLines) );
+ gabDisplayLinesDirty = calloc( sizeof(char), (Lines + ExtraScrollbackLines) );
+
+ AxWin3_RichText_SetLineCount(gMainWindow, Lines+ExtraScrollbackLines);
+ AxWin3_RichText_SetCursorType(gMainWindow, 1); // TODO: enum
+}
+
+void Display_int_PushString(int Length, const char *Text)
+{
+ _SysDebug("Line %i += %i '%*C'", giCurrentLine, Length, Length, Text);
+ if( !gasDisplayLines[giCurrentLine] || giCurrentLinePos + Length >= gaiDisplayLineSizes[giCurrentLine] )
+ {
+ int reqsize = giCurrentLinePos + Length;
+ gaiDisplayLineSizes[giCurrentLine] = (reqsize + 32-1) & ~(32-1);
+ void *tmp = realloc(gasDisplayLines[giCurrentLine], gaiDisplayLineSizes[giCurrentLine]);
+ if( !tmp ) perror("Display_AddText - realloc");
+ gasDisplayLines[giCurrentLine] = tmp;
+ }
+
+ memcpy(gasDisplayLines[giCurrentLine]+giCurrentLinePos, Text, Length);
+ gabDisplayLinesDirty[giCurrentLine] = 1;
+ gasDisplayLines[giCurrentLine][giCurrentLinePos+Length] = 0;
+ giCurrentLinePos += Length;
+
+}
+
+void Display_AddText(int Length, const char *UTF8Text)
+{
+ _SysDebug("%i '%.*s'", Length, Length, UTF8Text);
+ // Copy as many characters (not bytes, have to trim off the last char) as we can to the current line
+ // - then roll over to the next line
+ while( Length > 0 )
+ {
+ int space = giDisplayCols - giCurrentCol;
+ int bytes = 0;
+ while( space && bytes < Length )
+ {
+ uint32_t cp;
+ bytes += ReadUTF8(UTF8Text+bytes, &cp);
+ if( Unicode_IsPrinting(cp) ) {
+ space --;
+ giCurrentCol ++;
+ }
+ }
+
+ Display_int_PushString(bytes, UTF8Text);
+
+ UTF8Text += bytes;
+ _SysDebug("Length(%i) -= bytes(%i)", Length, bytes);
+ Length -= bytes;
+ if( Length != 0 )
+ {
+ // Next line
+ giCurrentLinePos = 0;
+ giCurrentCol = 0;
+ giCurrentLine ++;
+ }
+ }
+}
+
+void Display_Newline(int bCarriageReturn)
+{
+ Display_Flush();
+
+ // Going down!
+ giCurrentLine ++;
+ if( giCurrentLine == giDisplayLines )
+ giCurrentLine = 0;
+ if( giCurrentLine == giFirstLine )
+ {
+ giFirstLine ++;
+ if(giFirstLine == giDisplayLines)
+ giFirstLine = 0;
+ }
+
+ if( bCarriageReturn ) {
+ giCurrentLinePos = 0;
+ giCurrentCol = 0;
+ }
+ else {
+ giCurrentLinePos = 0;
+ int i = giCurrentCol;
+ if( !gasDisplayLines[giCurrentLine] )
+ {
+ giCurrentCol = 0;
+ while(i--)
+ Display_AddText(1, " ");
+ }
+ else
+ {
+ while( i -- )
+ {
+ uint32_t cp;
+ giCurrentLinePos += ReadUTF8(gasDisplayLines[giCurrentLine]+giCurrentLinePos, &cp);
+ if( !Unicode_IsPrinting(cp) )
+ i ++;
+ }
+ }
+ }
+}
+
+void Display_SetCursor(int Row, int Col)
+{
+ UNIMPLIMENTED();
+}
+
+void Display_MoveCursor(int RelRow, int RelCol)
+{
+ if( RelRow < 0 )
+ {
+ for( ; RelRow < 0; RelRow ++ )
+ {
+ uint32_t cp;
+ int delta = ReadUTF8Rev(gasDisplayLines[giCurrentLine], giCurrentLinePos, &cp);
+ if( !Unicode_IsPrinting(cp) )
+ RelRow --;
+ else
+ giCurrentCol --;
+ giCurrentLinePos -= delta;
+ }
+ }
+ else
+ {
+ UNIMPLIMENTED();
+ }
+}
+
+void Display_ClearLine(int Dir) // 0: All, 1: Forward, -1: Reverse
+{
+ if( Dir == 0 )
+ {
+ // Completely clear line
+ if( gasDisplayLines[giCurrentLine] )
+ free(gasDisplayLines[giCurrentLine]);
+ gasDisplayLines[giCurrentLine] = NULL;
+ gabDisplayLinesDirty[giCurrentLine] = 1;
+ }
+ else if( Dir == 1 )
+ {
+ // Forward clear (truncate)
+ }
+ else if( Dir == -1 )
+ {
+ // Reverse clear (replace with spaces)
+ }
+ else
+ {
+ // BUGCHECK
+ }
+}
+
+void Display_ClearLines(int Dir) // 0: All, 1: Forward, -1: Reverse
+{
+ if( Dir == 0 )
+ {
+ // Push giDisplayLines worth of empty lines
+ // Move cursor back up by giDisplayLines
+ }
+ else if( Dir == 1 )
+ {
+ // Push (giDisplayLines - (giCurrentLine-giFirstDispLine)) and reverse
+ }
+ else if( Dir == -1 )
+ {
+ // Reverse clear (replace with spaces)
+ }
+ else
+ {
+ // BUGCHECK
+ }
+}
+
+void Display_SetForeground(uint32_t RGB)
+{
+ char buf[7+1];
+ sprintf(buf, "\1%06x", RGB&0xFFFFFF);
+ Display_int_PushString(7, buf);
+}
+
+void Display_SetBackground(uint32_t RGB)
+{
+ char buf[7+1];
+ sprintf(buf, "\2%06x", RGB&0xFFFFFF);
+ Display_int_PushString(7, buf);
+}
+
+void Display_Flush(void)
+{
+ int i;
+ for( i = 0; i < giDisplayCols; i ++ )
+ {
+ int line = (giFirstLine + i) % giDisplayTotalLines;
+ if( !gabDisplayLinesDirty[line] )
+ continue;
+ _SysDebug("Line %i+%i '%s'", giFirstLine, i, gasDisplayLines[line]);
+ AxWin3_RichText_SendLine(gMainWindow, giFirstLine + i, gasDisplayLines[line] );
+ gabDisplayLinesDirty[line] = 0;
+ }
+
+ // force redraw?
+ AxWin3_RichText_SetCursorPos(gMainWindow, giCurrentLine, giCurrentCol);
+}
+
+void Display_ShowAltBuffer(int AltBufEnabled)
+{
+ UNIMPLIMENTED();
+}
+
* - By John Hodge (thePowersGang)
*
* display.h
- * - RichText Termianl Translation
+ * - RichText terminal translation
*/
#ifndef _DISPLAY_H_
#define _DISPLAY_H_
+#include <stdint.h>
+
+extern void Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
+
extern void Display_AddText(int Length, const char *UTF8Text);
extern void Display_Newline(int bCarriageReturn);
extern void Display_SetCursor(int Row, int Col);
extern void Display_ClearLines(int Dir); // 0: All, 1: Forward, -1: Reverse
extern void Display_SetForeground(uint32_t RGB);
extern void Display_SetBackground(uint32_t RGB);
+/**
+ * \brief Ensure that recent updates are flushed to the server
+ * \note Called at the end of an "input" buffer
+ */
+extern void Display_Flush(void);
+
+/**
+ * \brief Switch the display to the alternate buffer (no scrollback)
+ */
+extern void Display_ShowAltBuffer(int AltBufEnabled);
#endif
#include <axwin3/axwin.h>
#include <axwin3/menu.h>
#include <axwin3/richtext.h>
+#include <axwin3/keysyms.h>
#include <stdio.h>
+#include <acess/sys.h>
#include "include/display.h"
#include "include/vt100.h"
+#include <string.h>
+#include <unicode.h>
// === PROTOTYPES ===
int main(int argc, char *argv[], const char **envp);
int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
+void Term_HandleOutput(int Len, const char *Buf);
// === GLOBALS ===
tHWND gMainWindow;
// <testing>
AxWin3_RichText_SetLineCount(gMainWindow, 3);
AxWin3_RichText_SendLine(gMainWindow, 0, "First line!");
- AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \x01""ff0000A red");
+ AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \1ff0000A red");
// </testing>
- AxWin3_ResizeWindow(gMainWindow, 600, 400);
- AxWin3_MoveWindow(gMainWindow, 50, 50);
+ Display_Init(80, 25, 100);
+ AxWin3_ResizeWindow(gMainWindow, 80*8, 25*16);
+ AxWin3_MoveWindow(gMainWindow, 20, 50);
AxWin3_ShowWindow(gMainWindow, 1);
AxWin3_FocusWindow(gMainWindow);
// Spawn shell
- giChildStdout = open("/Devices/FIFO/anon", O_RDWR);
- giChildStdin = open("/Devices/FIFO/anon", O_RDWR);
+ giChildStdin = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+ giChildStdout = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
+ if( giChildStdout == -1 || giChildStdin == -1 ) {
+ perror("Oh, fsck");
+ _SysDebug("out,in = %i,%i", giChildStdout, giChildStdin);
+ return -1;
+ }
{
int fds[] = {giChildStdin, giChildStdout, giChildStdout};
const char *argv[] = {"CLIShell", NULL};
- _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+ int pid = _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+ if( pid < 0 )
+ _SysDebug("ERROR: Shell spawn failed");
}
// Main loop
if( FD_ISSET(giChildStdout, &fds) )
{
+ _SysDebug("Activity on child stdout");
// Read and update screen
char buf[32];
- int len = read(giChildStdout, buf, sizeof(buf));
+ int len = _SysRead(giChildStdout, buf, sizeof(buf));
if( len <= 0 ) break;
Term_HandleOutput(len, buf);
#define _bitset(var,bit,set) do{if(set)var|=1<<(bit);else var&=1<<(bit);}while(0)
switch(KeySym)
{
- case KEY_LCTRL:
- _bitset(ctrl_state, 0, bPress);
+ case KEYSYM_LEFTCTRL:
+ _bitset(ctrl_state, 0, bPress!=0);
return 0;
- case KEY_RCTRL:
- _bitset(ctrl_state, 0, bPress);
+ case KEYSYM_RIGHTCTRL:
+ _bitset(ctrl_state, 1, bPress!=0);
return 0;
}
#undef _bitset
// Handle shortcuts
// - Ctrl-A -- Ctrl-Z
- if( ctrl_state && KeySym >= KEY_a && KeySym <= KEY_z )
+ if( ctrl_state && KeySym >= KEYSYM_a && KeySym <= KEYSYM_z )
{
- Translated = KeySym - KEY_a + 1;
+ Translated = KeySym - KEYSYM_a + 1;
}
- if( Translated )
+ // == 2 :: FIRE
+ if( bPress == 2 )
{
- // Encode and send
+ if( Translated )
+ {
+ char buf[6];
+ int len;
+
+ // Encode and send
+ len = WriteUTF8(buf, Translated);
+
+ _SysDebug("Keystroke translated to '%.*s'", len, buf);
+ _SysWrite(giChildStdin, buf, len);
+
+ return 0;
+ }
- return 0;
- }
-
- // No translation, look for escape sequences to send
- switch(KeySym)
- {
- case KEY_LEFTARROW:
- // str = "\x1b[D";
- break;
+ // No translation, look for escape sequences to send
+ const char *str = NULL;
+ switch(KeySym)
+ {
+ case KEYSYM_LEFTARROW:
+ str = "\x1b[D";
+ break;
+ }
+ if( str )
+ {
+ _SysWrite(giChildStdin, str, strlen(str));
+ }
}
return 0;
}
Display_AddText(-esc_len, Buf + ofs);
esc_len = -esc_len;
}
- Len -= esc_len;
ofs += esc_len;
+ _SysDebug("Len = %i, ofs = %i", Len, ofs);
}
+
+ Display_Flush();
}
* Acess GUI Terminal
* - By John Hodge (thePowersGang)
*
- * main.c
- * - Core
+ * vt100.c
+ * - VT100/xterm Emulation
*/
#include <string.h>
+#include <limits.h>
#include "include/vt100.h"
#include "include/display.h"
+#include <ctype.h> // isalpha
+#include <acess/sys.h> // _SysDebug
+
+const uint32_t caVT100Colours[] = {
+ // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
+ // Same again, but bright
+ 0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAAA,
+ 0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF
+};
+
+ int Term_HandleVT100_Long(int Len, const char *Buf);
+
+static inline int min(int a, int b)
+{
+ return a < b ? a : b;
+}
int Term_HandleVT100(int Len, const char *Buf)
{
- const int max_length = 16;
- static char inc_buf[max_length]
+ #define MAX_VT100_ESCAPE_LEN 16
+ static char inc_buf[MAX_VT100_ESCAPE_LEN];
static int inc_len = 0;
if( inc_len > 0 || *Buf == '\x1b' )
{
- memcpy(inc_buf + inc_len, Buf, min(max_length - inc_len, Len));
// Handle VT100 (like) escape sequence
-
- inc_len = 0;
- return 1;
+ int new_bytes = min(MAX_VT100_ESCAPE_LEN - inc_len, Len);
+ int ret = 0, old_inc_len = inc_len;
+ memcpy(inc_buf + inc_len, Buf, new_bytes);
+
+ inc_len += new_bytes;
+
+ if( inc_len <= 1 )
+ return 1; // Skip 1 character (the '\x1b')
+
+ switch(inc_buf[1])
+ {
+ case '[': // Multibyte, funtime starts
+ ret = Term_HandleVT100_Long(inc_len-2, inc_buf+2);
+ if( ret > 0 ) {
+ ret += 2;
+ }
+ break;
+ default:
+ ret = 2;
+ break;
+ }
+
+ if( ret != 0 ) {
+ inc_len = 0;
+ ret -= old_inc_len; // counter cached bytes
+ }
+ return ret;
}
switch( *Buf )
{
case '\b':
// TODO: Backspace
+ Display_MoveCursor(-1, 0);
+ Display_AddText(1, " ");
+ Display_MoveCursor(-1, 0);
return 1;
case '\t':
- // TODO: tab
+ // TODO: tab (get current cursor pos, space until multiple of 8)
return 1;
case '\n':
Display_Newline(1);
return 1;
case '\r':
// TODO: Carriage return
- return ;
+ Display_MoveCursor(INT_MIN, 0);
+ return 1;
}
int ret = 0;
}
return -ret;
}
+
+int Term_HandleVT100_Long(int Len, const char *Buffer)
+{
+ char c;
+ int argc = 0, j = 0;
+ int args[6] = {0,0,0,0,0,0};
+ int bQuestionMark = 0;
+
+ // Get Arguments
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ if(c == '?') {
+ bQuestionMark = 1;
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ }
+ if( '0' <= c && c <= '9' )
+ {
+ do {
+ if(c == ';') {
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ }
+ while('0' <= c && c <= '9') {
+ args[argc] *= 10;
+ args[argc] += c-'0';
+ if(j == Len) return 0;
+ c = Buffer[j++];
+ }
+ argc ++;
+ } while(c == ';');
+ }
+
+ // Get Command
+ if( !isalpha(c) ) {
+ // Bother.
+ _SysDebug("Unexpected char 0x%x in VT100 escape code", c);
+ return 1;
+ }
+
+ if( bQuestionMark )
+ {
+ // Special commands
+ switch( c )
+ {
+ default:
+ _SysDebug("Unknown VT100 extended escape char 0x%x", c);
+ break;
+ }
+ }
+ else
+ {
+ // Standard commands
+ switch( c )
+ {
+ case 'J':
+ if( argc == 0 )
+ Display_ClearLine(0);
+ else if( args[0] == 2 )
+ Display_ClearLines(0); // Entire screen!
+ else
+ _SysDebug("TODO: VT100 %i J", args[0]);
+ break;
+ case 'm':
+ if( argc == 0 )
+ {
+ // Reset
+ }
+ else
+ {
+ int i;
+ for( i = 0; i < argc; i ++ )
+ {
+ if( args[i] < 8 )
+ {
+ // Flags?
+ }
+ else if( 30 <= args[i] && args[i] <= 37 )
+ {
+ // TODO: Bold/bright
+ Display_SetForeground( caVT100Colours[ args[i]-30 ] );
+ }
+ else if( 40 <= args[i] && args[i] <= 47 )
+ {
+ // TODO: Bold/bright
+ Display_SetBackground( caVT100Colours[ args[i]-30 ] );
+ }
+ }
+ }
+ break;
+ default:
+ _SysDebug("Unknown VT100 escape char 0x%x", c);
+ break;
+ }
+ }
+ return j;
+}
--- /dev/null
+/*
+ * Acess2 Userland init(8)
+ * - Userland root process
+ *
+ * common.h
+ * - Common type definitions
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+typedef struct sInitProgram tInitProgram;
+
+struct sKTerm
+{
+ int ID;
+};
+
+struct sSTerm
+{
+ uint32_t FormatBits;
+ unsigned int BaudRate;
+ char Path[];
+};
+
+struct sDaemon
+{
+ char *StdoutPath; // heap
+ char *StderrPath; // heap
+};
+
+union uProgTypes
+{
+ struct sKTerm KTerm;
+ struct sSTerm STerm;
+ struct sDaemon Daemon;
+};
+
+enum eProgType
+{
+ PT_KTERM,
+ PT_STERM,
+ PT_DAEMON
+};
+
+struct sInitProgram
+{
+ tInitProgram *Next;
+ enum eProgType Type;
+ int CurrentPID;
+ char **Command;
+ union uProgTypes TypeInfo;
+};
+
+#endif
+
#include <acess/sys.h>
#include <stdlib.h>
#include <stdio.h>
-//#include "common.h"
+#include <string.h>
+#include "common.h"
+#include <ctype.h>
// === CONSTANTS ===
-#define NUM_TERMS 4
-#define DEFAULT_TERMINAL "/Devices/VTerm/0"
#define DEFAULT_SHELL "/Acess/SBin/login"
+#define INITTAB_FILE "/Acess/Conf/inittab"
#define ARRAY_SIZE(x) ((sizeof(x))/(sizeof((x)[0])))
// === PROTOTYPES ===
+ int ProcessInittab(const char *Path);
+char *ReadQuotedString(FILE *FP);
+char **ReadCommand(FILE *FP);
+void FreeCommand(char **Command);
+
+tInitProgram *AllocateProgram(char **Command, enum eProgType Type, size_t ExtraSpace);
+void RespawnProgam(tInitProgram *Program);
+
+ int AddKTerminal(int TerminalSpec, char **Command);
+ int AddSerialTerminal(const char *DevPathSegment, const char *ModeStr, char **Command);
+ int AddDaemon(char *StdoutPath, char *StderrPath, char **Command);
+
+ int SpawnCommand(int c_stdin, int c_stdout, int c_stderr, char **ArgV);
+ int SpawnKTerm(tInitProgram *Program);
+ int SpawnSTerm(tInitProgram *Program);
+ int SpawnDaemon(tInitProgram *Program);
+
+// === GLOBALS ===
+const char *gsInittabPath = INITTAB_FILE;
+tInitProgram *gpInitPrograms;
// === CODE ===
/**
*/
int main(int argc, char *argv[])
{
- int tid;
- int i;
- char termpath[sizeof(DEFAULT_TERMINAL)] = DEFAULT_TERMINAL;
- char *child_argv[2] = {DEFAULT_SHELL, 0};
+ // Parse commandline args
+ // TODO: cmdline
+
+ // TODO: Behave differently if not invoked as first process?
+
+ // Begin init process
+ if( ProcessInittab(gsInittabPath) != 0 )
+ {
+ // No inittab file found, default to:
+ _SysDebug("inittab '%s' is invalid, falling back to one VT", gsInittabPath);
+
+ #if 0
+ for( ;; )
+ {
+ int pid = SpawnCommand(0, 1, 1, (char *[]){DEFAULT_SHELL, NULL});
+ // TODO: Detect errors
+ _SysWaitTID(pid, NULL);
+ }
+ #else
+ return 41;
+ #endif
+ }
+
+ // TODO: Implement message watching
+ for(;;)
+ {
+ int pid, status;
+ pid = _SysWaitTID(-1, &status);
+ _SysDebug("PID %i died, looking for respawn entry", pid);
+ }
- // - Parse init script
+ return 42;
+}
+
+char *ReadQuotedString(FILE *FP)
+{
+ char ch;
+
+ while( isblank(ch = fgetc(FP)) )
+ ;
+
+ if( ch == '\n' ) {
+ return NULL;
+ }
+
+ char *retstr = NULL;
+ int mode = 0;
+ int pos = 0, space = 0;
+ for( ; !feof(FP); ch = fgetc(FP) )
+ {
+ int skip;
+ skip = 1;
+ if( mode & 4 ) {
+ // Add escaped/special character
+ skip = 0;
+ mode &= 3;
+ }
+ else if( mode == 0 )
+ {
+ if( isspace(ch) ) {
+ fseek(FP, -1, SEEK_CUR);
+ break;
+ }
+ else if( ch == '\\' )
+ mode |= 4;
+ else if( ch == '"' )
+ mode = 1;
+ else if( ch == '\'')
+ mode = 2;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
+ // Double-quoted string
+ else if( mode == 1 )
+ {
+ if( ch == '"' )
+ mode = 0;
+ else if( ch == '\\' )
+ mode |= 4;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
+ // Single-quoted string
+ else if( mode == 2 )
+ {
+ if( ch == '\'' )
+ mode = 0;
+ else if( ch == '\\' )
+ mode |= 4;
+ else {
+ // Add character
+ skip = 0;
+ }
+ }
- // - Start virtual terminals
- for( i = 0; i < NUM_TERMS; i++ )
- {
- tid = _SysClone(CLONE_VM, 0);
- if(tid == 0)
+ if( !skip )
{
- termpath[sizeof(DEFAULT_TERMINAL)-2] = '0' + i;
+ if( pos == space ) {
+ space += 32;
+ void *tmp = realloc(retstr, space+1);
+ if( !tmp ) {
+ _SysDebug("ReadQuotedString - realloc(%i) failure", space+1);
+ free(retstr);
+ return NULL;
+ }
+ retstr = tmp;
+ }
+ retstr[pos++] = ch;
+ }
+ }
+ retstr[pos] = '\0';
+ return retstr;
+}
+
+char **ReadCommand(FILE *FP)
+{
+ const int space = 8;
+ int pos = 0;
+ char **ret = malloc(space*sizeof(char*));
+ char *arg;
+ do {
+ arg = ReadQuotedString(FP);
+ if(arg == NULL)
+ break;
+ if( pos == space - 1 ) {
+ _SysDebug("Too many arguments %i", pos);
+ ret[pos] = NULL;
+ FreeCommand(ret);
+ return NULL;
+ }
+ ret[pos++] = arg;
+ } while(arg != NULL);
+ ret[pos] = NULL;
+ return ret;
+}
+
+void FreeCommand(char **Command)
+{
+ int pos = 0;
+ while( Command[pos] )
+ {
+ free(Command[pos]);
+ pos ++;
+ }
+ free(Command);
+}
+
+int ProcessInittab(const char *Path)
+{
+ FILE *fp = fopen(Path, "r");
+
+ if( !fp )
+ return 1;
+
+ while(!feof(fp))
+ {
+ char cmdbuf[64+1];
+
+ int rv;
+ if( (rv = fscanf(fp, "%64s%*[ \t]", &cmdbuf)) != 1 ) {
+ _SysDebug("fscanf rv %i != exp 1", rv);
+ break;
+ }
+
+ // Clear comments
+ if( cmdbuf[0] == '#' ) {
+ while( !feof(fp) && fgetc(fp) != '\n' )
+ ;
+ continue ;
+ }
+ if( cmdbuf[0] == '\0' ) {
+ char ch = fgetc(fp);
+ if( ch != '\n' && ch != -1 ) {
+ fclose(fp);
+ _SysDebug("Unexpected char 0x%x, expecting EOL", ch);
+ return 2; // Unexpected character?
+ }
+ continue ;
+ }
+
+ // Check commands
+ if( strcmp(cmdbuf, "ktty") == 0 ) {
+ // ktty <ID> <command...>
+ // - Spins off a console on the specified kernel TTY
+ int id = 0;
+ if( fscanf(fp, "%d ", &id) != 1 ) {
+ _SysDebug("init[ktty] - TTY ID read failed");
+ goto lineError;
+ }
+ char **command = ReadCommand(fp);
+ if( !command ) {
+ _SysDebug("init[ktty] - Command read failure");
+ goto lineError;
+ }
+ AddKTerminal(id, command);
+ free(command);
+ }
+ else if(strcmp(cmdbuf, "stty") == 0 ) {
+ // stty <devpath> [78][NOE][012][bB]<baud> <command...>
+ char path_seg[32+1];
+ char modespec[4+6+1];
+ if( fscanf(fp, "%32s %6s ", &path_seg, &modespec) != 2 ) {
+ goto lineError;
+ }
+ char **command = ReadCommand(fp);
+ if( !command )
+ goto lineError;
+ AddSerialTerminal(path_seg, modespec, command);
+ }
+ else if(strcmp(cmdbuf, "daemon") == 0 ) {
+ // daemon <stdout> <stderr> <command...>
+ // - Runs a daemon (respawning) that logs to the specified files
+ // - Will append a header whenever the daemon starts
+ char *stdout_path = ReadQuotedString(fp);
+ char *stderr_path = ReadQuotedString(fp);
+ char **command = ReadCommand(fp);
- _SysOpen(termpath, OPENFLAG_READ); // Stdin
- _SysOpen(termpath, OPENFLAG_WRITE); // Stdout
- _SysOpen(termpath, OPENFLAG_WRITE); // Stderr
- _SysExecVE(DEFAULT_SHELL, child_argv, NULL);
- for(;;) ;
+ AddDaemon(stdout_path, stderr_path, command);
+ }
+ else if(strcmp(cmdbuf, "exec") == 0 ) {
+ // exec <command...>
+ // - Runs a command and waits for it to complete before continuing
+ // - NOTE: No other commands will respawn while this is running
+ char **command = ReadCommand(fp);
+ if(!command)
+ goto lineError;
+
+ int handles[] = {0, 1, 2};
+ int pid = _SysSpawn(command[0], (const char **)command, NULL, 3, handles, NULL);
+ int retstatus;
+ _SysWaitTID(pid, &retstatus);
+ _SysDebug("Command '%s' returned %i", command[0], retstatus);
+
+ FreeCommand(command);
+ }
+ else {
+ // Unknown command.
+ _SysDebug("Unknown command '%s'", cmdbuf);
+ goto lineError;
}
+ fscanf(fp, " ");
+ continue;
+ lineError:
+ _SysDebug("label lineError: goto'd");
+ while( !feof(fp) && fgetc(fp) != '\n' )
+ ;
+ continue ;
}
+
+ fclose(fp);
+ return 0;
+}
+
+tInitProgram *AllocateProgram(char **Command, enum eProgType Type, size_t ExtraSpace)
+{
+ tInitProgram *ret;
- // TODO: Implement message watching
- for(;;)
- _SysWaitEvent(THREAD_EVENT_IPCMSG);
+ ret = malloc( sizeof(tInitProgram) - sizeof(union uProgTypes) + ExtraSpace );
+ ret->Next = NULL;
+ ret->CurrentPID = 0;
+ ret->Type = Type;
+ ret->Command = Command;
- return 42;
+ // Append
+ ret->Next = gpInitPrograms;
+ gpInitPrograms = ret;
+
+ return ret;
+}
+
+void RespawnProgam(tInitProgram *Program)
+{
+ int rv = 0;
+ switch(Program->Type)
+ {
+ case PT_KTERM: rv = SpawnKTerm(Program); break;
+ case PT_STERM: rv = SpawnSTerm(Program); break;
+ case PT_DAEMON: rv = SpawnDaemon(Program); break;
+ default:
+ _SysDebug("BUGCHECK - Program Type %i unknown", Program->Type);
+ break;
+ }
+ if( !rv ) {
+ _SysDebug("Respawn failure!");
+ // TODO: Remove from list?
+ }
+}
+
+int AddKTerminal(int TerminalID, char **Command)
+{
+ // TODO: Smarter validation
+ if( TerminalID < 0 || TerminalID > 7 )
+ return -1;
+
+ tInitProgram *ent = AllocateProgram(Command, PT_KTERM, sizeof(struct sKTerm));
+ ent->TypeInfo.KTerm.ID = TerminalID;
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int AddSerialTerminal(const char *DevPathSegment, const char *ModeStr, char **Command)
+{
+ char dbit, parity, sbit;
+ int baud;
+
+ // Parse mode string
+ if( sscanf(ModeStr, "%1[78]%1[NOE]%1[012]%*1[bB]%d", &dbit, &parity, &sbit, &baud) != 5 ) {
+ // Oops?
+ return -1;
+ }
+
+ // Validate baud rate / build mode word
+ // TODO: Does baud rate need validation?
+ uint32_t modeword = 0;
+ modeword |= (dbit == '7' ? 1 : 0) << 0;
+ modeword |= (parity == 'O' ? 1 : (parity == 'E' ? 2 : 0)) << 1;
+ modeword |= (sbit - '0') << 3;
+
+ // Create info
+ const char DEVPREFIX[] = "/Devices/";
+ int pathlen = sizeof(DEVPREFIX) + strlen(DevPathSegment);
+ tInitProgram *ent = AllocateProgram(Command, PT_STERM, sizeof(struct sSTerm)+pathlen);
+ ent->TypeInfo.STerm.FormatBits = modeword;
+ ent->TypeInfo.STerm.BaudRate = baud;
+ strcpy(ent->TypeInfo.STerm.Path, DEVPREFIX);
+ strcat(ent->TypeInfo.STerm.Path, DevPathSegment);
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int AddDaemon(char *StdoutPath, char *StderrPath, char **Command)
+{
+ tInitProgram *ent = AllocateProgram(Command, PT_DAEMON, sizeof(struct sDaemon));
+ ent->TypeInfo.Daemon.StdoutPath = StdoutPath;
+ ent->TypeInfo.Daemon.StderrPath = StderrPath;
+
+ RespawnProgam(ent);
+ return 0;
+}
+
+int SpawnCommand(int c_stdin, int c_stdout, int c_stderr, char **ArgV)
+{
+ int handles[] = {c_stdin, c_stdout, c_stderr};
+
+ int rv = _SysSpawn(ArgV[0], (const char **)ArgV, NULL, 3, handles, NULL);
+
+ _SysClose(c_stdin);
+ if( c_stdout != c_stdin )
+ _SysClose(c_stdout);
+ if( c_stderr != c_stdin && c_stderr != c_stdout )
+ _SysClose(c_stderr);
+
+ return rv;
+}
+
+int SpawnKTerm(tInitProgram *Program)
+{
+ const char fmt[] = "/Devices/VTerm/%i";
+ char path[sizeof(fmt)];
+
+ snprintf(path, sizeof(path), fmt, Program->TypeInfo.KTerm.ID);
+
+ int in = _SysOpen(path, OPENFLAG_READ);
+ int out = _SysOpen(path, OPENFLAG_WRITE);
+
+ return SpawnCommand(in, out, out, Program->Command);
+}
+
+int SpawnSTerm(tInitProgram *Program)
+{
+ int in = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_READ);
+ int out = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_WRITE);
+
+ #if 0
+ if( _SysIOCtl(in, 0, NULL) != DRV_TYPE_SERIAL )
+ {
+ // Oops?
+ return -2;
+ }
+ _SysIOCtl(in, SERIAL_IOCTL_GETSETBAUD, &Program->TypeInfo.STerm.BaudRate);
+ _SysIOCtl(in, SERIAL_IOCTL_GETSETFORMAT, &Program->TypeInfo.STerm.FormatBits);
+ #endif
+
+ return SpawnCommand(in, out, out, Program->Command);
+}
+
+int SpawnDaemon(tInitProgram *Program)
+{
+ int in = _SysOpen("/Devices/null", OPENFLAG_READ);
+ int out = _SysOpen(Program->TypeInfo.Daemon.StdoutPath, OPENFLAG_WRITE);
+ int err = _SysOpen(Program->TypeInfo.Daemon.StderrPath, OPENFLAG_WRITE);
+
+ if( in == -1 || out == -1 || err == -1 ) {
+ _SysClose(in);
+ _SysClose(out);
+ _SysClose(err);
+ return -2;
+ }
+
+ return SpawnCommand(in, out, err, Program->Command);
}
tServer *gpServers;\r
tWindow gWindow_Status = {\r
NULL, NULL, NULL, // No next, empty list, no server\r
- 0, "" // No activity, empty name (rendered as status)\r
+ 0, {""} // No activity, empty name (rendered as status)\r
};\r
tWindow *gpWindows = &gWindow_Status;\r
tWindow *gpCurrentWindow = &gWindow_Status;\r
return 0;
}
+static void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
+{
+ FD_SET(fd, set);
+ if(*maxfd < fd) *maxfd = fd;
+}
+
void EventLoop(void)
{
fd_set fds;
int maxfd;
- void FD_SET_MAX(fd_set *set, int fd, int *maxfd)
- {
- FD_SET(fd, set);
- if(*maxfd < fd) *maxfd = fd;
- }
-
for( ;; )
{
FD_ZERO(&fds);
--- /dev/null
+exec /Acess/Bin/dhcpc
+
+ktty 0 /Acess/SBin/login
+ktty 1 /Acess/SBin/login
+stty serial/0 /Acess/SBin/login
+
+
+#vim: ft=text
DIRS = Bin SBin Libs Modules Apps
DIRS += Conf Conf/Auth
-FILES = Conf/BootConf.cfg
+FILES = Conf/inittab
# Conf/Auth/Users Conf/Auth/Passwords Conf/Auth/Groups
#DIRS := $(addprefix $(DISTROOT)/,$(DIRS))
// Override the clone syscall
#define _exit _exit_raw
#define _clone _clone_raw
+#define _SysSeek _SysSeek_borken
#include "syscalls.s.h"
#undef _exit
#undef _clone
+#undef _SysSeek
+
+// NOTE: _SysSeek needs special handling for alignment
+.globl _SysSeek
+_SysSeek:
+ push {lr}
+ mov r1,r2
+ mov r2,r3
+ ldr r3, [sp,#4]
+ svc #SYS_SEEK
+ ldr r3, =_errno
+ str r2, [r3]
+ pop {pc}
.globl _clone
_clone:
pop {r4}
mov pc, lr
+
.globl _exit
_exit:
svc #0
} fd_set;
-extern void FD_ZERO(fd_set *fdsetp);
-extern void FD_CLR(int fd, fd_set *fdsetp);
-extern void FD_SET(int fd, fd_set *fdsetp);
-extern int FD_ISSET(int fd, fd_set *fdsetp);
+static inline void FD_ZERO(fd_set *fdsetp)
+{
+ int i = FD_SETSIZE/16;
+ while( i-- )
+ fdsetp->flags[i] = 0;
+}
+static inline void FD_CLR(int fd, fd_set *fdsetp)
+{
+ if(fd < 0 || fd > FD_SETSIZE) return;
+ fd_set_ent_t mask = 1 << (fd % 16);
+ fdsetp->flags[fd/16] &= ~mask;
+}
+static inline void FD_SET(int fd, fd_set *fdsetp)
+{
+ if(fd < 0 || fd > FD_SETSIZE) return;
+ fd_set_ent_t mask = 1 << (fd % 16);
+ fdsetp->flags[fd/16] |= mask;
+}
+static inline int FD_ISSET(int fd, fd_set *fdsetp)
+{
+ if(fd < 0 || fd > FD_SETSIZE) return 0;
+ fd_set_ent_t mask = 1 << (fd % 16);
+ return !!( fdsetp->flags[fd/16] & mask );
+}
#endif
#define GETMSG_IGNORE ((void*)-1)
#define FILEFLAG_DIRECTORY 0x10
#define FILEFLAG_SYMLINK 0x20
+#define CLONE_VM 0x10
+
// === TYPES ===
+++ /dev/null
-../../../../../KernelLand/Kernel/include/keysyms.h
\ No newline at end of file
--- /dev/null
+#include "../../../../../KernelLand/Kernel/include/keysyms.h"
\r
INCFILES := stdio.h stdlib.h\r
\r
-OBJ = stub.o heap.o stdlib.o env.o stdio.o string.o select.o rand.o\r
+OBJ = stub.o heap.o stdlib.o env.o stdio.o string.o rand.o\r
OBJ += perror.o scanf.o signals.o strtoi.o strtof.o\r
OBJ += arch/$(ARCHDIR).ao\r
# signals.o\r
// int offset = -1;
enum e_vcscanf_sizes size = _VCSCANF_UNDEF;
enum e_vcscanf_types valtype;
+ int fail = 0;
+ int nnewch;
const char *set_start;
int set_len;
{
while( (ich = __getc(h)) && isspace(ich) )
nch ++;
+ if(ich) __rewind(h);
continue ;
}
{
// Decimal integer
case 'd':
- nch += _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 10, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// variable-base integer
case 'i':
- nch += _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 0, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// Octal integer
case 'o':
- nch += _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 8, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// Hexadecimal integer
case 'x': case 'X':
- nch += _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+ nnewch = _vcscanf_int(__getc, __rewind, h, 16, maxlen, &ival);
+ if(nnewch==0) fail=1;
+ nch += nnewch;
valtype = _VCSCANF_INT;
break;
// strtod format float
maxlen = -1;
ich = 0;
- while( maxlen -- && (ich = __getc(h)) && !isblank(ich) )
+ while( maxlen -- && (ich = __getc(h)) && !isspace(ich) )
{
if(ptr._char) *ptr._char++ = ich;
nch ++;
}
if( maxlen >= 0 && ich )
__rewind(h);
+ if(ptr._char) *ptr._char++ = 0;
valtype = _VCSCANF_NOTYPE;
break;
// match a set of characters
fch = *format++;
} while( fch && fch != ']' );
+ if( maxlen == 0 )
+ maxlen = -1;
ich = 0;
while( maxlen -- && (ich = __getc(h)) && memchr(set_start, set_len, ich) )
{
}
if( maxlen >= 0 && ich )
__rewind(h);
+ if(ptr._char) *ptr._char++ = 0;
valtype = _VCSCANF_NOTYPE;
break;
case 'p': // read back printf("%p")
valtype = _VCSCANF_NOTYPE;
break;
}
-
+
+ if(fail)
+ break;
+
switch(valtype)
{
case _VCSCANF_NOTYPE:
int _vfscanf_getc(void *h)
{
- return fgetc(h); // TODO: Handle -1 -> 0
+ int ch = fgetc(h);
+ return ch == -1 ? 0 : ch;
}
void _vfscanf_rewind(void *h)
{
+++ /dev/null
-/*
- * Acess2 C Library
- * - By John Hodge (thePowersGang)
- *
- * select.c
- */
-
-//#include <sys/select.h>
-#include <sys/types.h>
-
-void FD_ZERO(fd_set *fdsetp)
-{
- int i = FD_SETSIZE/16;
- while( i-- )
- fdsetp->flags[i]=0;
-}
-
-void FD_CLR(int fd, fd_set *fdsetp)
-{
- if(fd < 0 || fd > FD_SETSIZE) return;
- fdsetp->flags[fd/16] &= (fd_set_ent_t) ((~1 << (fd%16))) & 0xFFFF;
-}
-
-void FD_SET(int fd, fd_set *fdsetp)
-{
- if(fd < 0 || fd > FD_SETSIZE) return;
- fdsetp->flags[fd/16] |= (fd_set_ent_t) (1 << (fd%16));
-}
-
-int FD_ISSET(int fd, fd_set *fdsetp)
-{
- if(fd < 0 || fd > FD_SETSIZE) return 0;
- return !!( fdsetp->flags[fd/16] & (1<<(fd%16)) );
-}
-
}\r
else {\r
ret = _SysRead(fp->FD, ptr, size*num);\r
+ if( ret == (size_t)-1)\r
+ return -1;\r
+ if( ret == 0 && size*num > 0 ) {\r
+ fp->Flags |= FILE_FLAG_EOF;\r
+ return 0;\r
+ }\r
ret /= size;\r
}\r
\r
EXPORT int fgetc(FILE *fp)\r
{\r
char ret = 0;\r
- if( fread(&ret, 1, 1, fp) == (size_t)-1 )\r
+ if( fread(&ret, 1, 1, fp) != 1 )\r
return -1;\r
return ret;\r
}\r
return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
}\r
\r
-//sprintfv\r
+\r
/**\r
* \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
* \brief Prints a formatted string to a buffer\r
uint64_t arg;\r
int bLongLong, bPadLeft;\r
\r
- void _addchar(char ch)\r
- {\r
- if(buf && pos < __maxlen) buf[pos] = ch;\r
- pos ++;\r
- }\r
+ #define _addchar(ch) do { \\r
+ if(buf && pos < __maxlen) buf[pos] = (ch); \\r
+ else (void)(ch); \\r
+ pos ++; \\r
+ } while(0)\r
\r
tmp[32] = '\0';\r
\r
}\r
_addchar('\0');\r
pos --;\r
+ #undef _addchar\r
\r
//_SysDebug("vsnprintf: buf = '%s'", buf);\r
\r
va_end(args);\r
\r
// Send to stdout\r
- _SysWrite(_stdout, buf, size+1);\r
+ _SysWrite(_stdout, buf, size);\r
\r
// Free buffer\r
free(buf);\r
typedef struct stat t_fstat;
-#define CLONE_VM 0x10
-
typedef unsigned int id_t;
typedef unsigned long pid_t;
typedef unsigned long tid_t;
--- /dev/null
+# Acess 2 "libunicode"
+#
+
+include ../Makefile.cfg
+
+CPPFLAGS +=
+CFLAGS += -Wall
+LDFLAGS += -lc -soname libunicode.so
+
+OBJ = main.o utf-8.o
+BIN = libunicode.so
+
+include ../Makefile.tpl
+
--- /dev/null
+/*
+ * Acess2 "libunicode" UTF Parser
+ * - By John Hodge (thePowersGang)
+ *
+ * unicode.h
+ * - Main header
+ */
+#ifndef _LIBUNICODE__UNICODE_H_
+#define _LIBUNICODE__UNICODE_H_
+
+#include <stdint.h>
+
+/**
+ * \breif Read a single codepoint from a UTF-8 stream
+ * \return Number of bytes read
+ */
+extern int ReadUTF8(const char *Input, uint32_t *Val);
+/**
+ * \brief Read backwards in the stream
+ */
+extern int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val);
+/**
+ * \breif Write a single codepoint to a UTF-8 stream
+ */
+extern int WriteUTF8(char *buf, uint32_t Val);
+
+
+static inline int Unicode_IsPrinting(uint32_t Codepoint) { return 1; }
+
+#endif
+
--- /dev/null
+/*
+ * Acess2 "libunicode"
+ * - By John Hoge
+ *
+ * main.c
+ * - Stub main
+ */
+
+int SoMain(void)
+{
+ return 0;
+}
--- /dev/null
+/*
+ * Acess2 "libunicode" UTF Parser
+ * - By John Hodge (thePowersGang)
+ *
+ * utf-8.c
+ * - UTF-8 Parsing code
+ */
+#include <stdint.h>
+#include <unicode.h>
+
+/**
+ * \brief Read a UTF-8 character from a string
+ * \param Input Source UTF-8 encoded string
+ * \param Val Destination for read codepoint
+ * \return Number of bytes read/used
+ */
+int ReadUTF8(const char *Input, uint32_t *Val)
+{
+ const uint8_t *str = (const uint8_t *)Input;
+ *Val = 0xFFFD; // Assume invalid character
+
+ // ASCII
+ if( !(*str & 0x80) ) {
+ *Val = *str;
+ return 1;
+ }
+
+ // Middle of a sequence
+ if( (*str & 0xC0) == 0x80 ) {
+ return 1;
+ }
+
+ // Two Byte
+ if( (*str & 0xE0) == 0xC0 ) {
+ *Val = (*str & 0x1F) << 6; // Upper 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F); // Lower 6 Bits
+ return 2;
+ }
+
+ // Three Byte
+ if( (*str & 0xF0) == 0xE0 ) {
+ *Val = (*str & 0x0F) << 12; // Upper 4 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F); // Lower 6 Bits
+ return 3;
+ }
+
+ // Four Byte
+ if( (*str & 0xF8) == 0xF0 ) {
+ *Val = (*str & 0x07) << 18; // Upper 3 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
+ str ++;
+ if( (*str & 0xC0) != 0x80) return -1; // Validity check
+ *Val |= (*str & 0x3F); // Lower 6 Bits
+ return 4;
+ }
+
+ // UTF-8 Doesn't support more than four bytes
+ return 4;
+}
+
+/**
+ * \brief Get the UTF-8 character before the
+ * \
+ */
+int ReadUTF8Rev(const char *Base, int Offset, uint32_t *Val)
+{
+ int len = 0;
+
+ // Scan backwards for the beginning of the character
+ while( Offset > 0 && (Base[Offset--] & 0xC0) == 0x80 )
+ len ++;
+ // Invalid string (no beginning)
+ if(Offset == 0 && (Base[Offset] & 0xC0) == 0x80 )
+ return len;
+
+ len ++; // First character
+ if( ReadUTF8(Base+Offset, Val) != len ) {
+ *Val = 0xFFFD;
+ }
+ return len;
+}
+
+/**
+ * \brief Write a UTF-8 character sequence to a string
+ * \param buf Destination buffer (must have at least 4 bytes available)
+ * \param Val Unicode codepoint to write
+ * \return Number of bytes written
+ * \note Does not NULL terminate the string in \a buf
+ */
+int WriteUTF8(char *buf, uint32_t Val)
+{
+ uint8_t *str = (void*)buf;
+
+ // ASCII
+ if( Val < 128 ) {
+ if(str) {
+ *str = Val;
+ }
+ return 1;
+ }
+
+ // Two Byte
+ if( Val < 0x8000 ) {
+ if(str) {
+ *str = 0xC0 | (Val >> 6);
+ str ++;
+ *str = 0x80 | (Val & 0x3F);
+ }
+ return 2;
+ }
+
+ // Three Byte
+ if( Val < 0x10000 ) {
+ if(str) {
+ *str = 0xE0 | (Val >> 12);
+ str ++;
+ *str = 0x80 | ((Val >> 6) & 0x3F);
+ str ++;
+ *str = 0x80 | (Val & 0x3F);
+ }
+ return 3;
+ }
+
+ // Four Byte
+ if( Val < 0x110000 ) {
+ if(str) {
+ *str = 0xF0 | (Val >> 18);
+ str ++;
+ *str = 0x80 | ((Val >> 12) & 0x3F);
+ str ++;
+ *str = 0x80 | ((Val >> 6) & 0x3F);
+ str ++;
+ *str = 0x80 | (Val & 0x3F);
+ }
+ return 4;
+ }
+
+ // UTF-8 Doesn't support more than four bytes
+ return 0;
+}
+