Skip to content

Commit

Permalink
Enough compatibility work to make figlet build and run!
Browse files Browse the repository at this point in the history
I ran out of steam writing library routines and imported two
BSD-licensed libc routines: sscanf() and getopt().

I will most likely rewrite them sooner or later. For now
I just wanted to see figlet running.
  • Loading branch information
awesomekling committed Oct 31, 2018
1 parent 69c7a59 commit 819ce91
Show file tree
Hide file tree
Showing 22 changed files with 714 additions and 36 deletions.
3 changes: 1 addition & 2 deletions Kernel/MemoryManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ void MemoryManager::initializePaging()

identityMap(LinearAddress(4096), 4 * MB);

// Put pages between 4MB and 8MB in the page freelist.
for (size_t i = (4 * MB) + PAGE_SIZE; i < (8 * MB); i += PAGE_SIZE) {
m_freePages.append(PhysicalAddress(i));
}
Expand Down Expand Up @@ -170,7 +169,7 @@ RetainPtr<Zone> MemoryManager::createZone(size_t size)
InterruptDisabler disabler;
auto pages = allocatePhysicalPages(ceilDiv(size, PAGE_SIZE));
if (pages.isEmpty()) {
kprintf("[MM] createZone: no physical pages for size %u", size);
kprintf("[MM] createZone: no physical pages for size %u\n", size);
return nullptr;
}
return adopt(*new Zone(move(pages)));
Expand Down
8 changes: 4 additions & 4 deletions Kernel/Syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
case Syscall::PosixRead:
//kprintf("syscall: read(%d, %p, %u)\n", arg1, arg2, arg3);
return current->sys$read((int)arg1, (void*)arg2, (size_t)arg3);
case Syscall::PosixSeek:
// FIXME: This has the wrong signature, should be like lseek()
kprintf("syscall: seek(%d, %d)\n", arg1, arg2);
return current->sys$seek((int)arg1, (int)arg2);
case Syscall::PosixLseek:
return current->sys$lseek((int)arg1, (off_t)arg2, (int)arg3);
case Syscall::PosixKill:
return current->sys$kill((pid_t)arg1, (int)arg2);
case Syscall::PosixGetuid:
Expand All @@ -104,6 +102,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
return 0;
case Syscall::GetArguments:
return current->sys$get_arguments((int*)arg1, (char***)arg2);
case Syscall::GetEnvironment:
return current->sys$get_environment((char***)arg1);
case Syscall::PosixChdir:
return current->sys$chdir((const char*)arg1);
case Syscall::PosixUname:
Expand Down
3 changes: 2 additions & 1 deletion Kernel/Syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ enum Function {
PosixOpen = 0x1985,
PosixClose = 0x1986,
PosixRead = 0x1987,
PosixSeek = 0x1988,
PosixLseek = 0x1988,
PosixKill = 0x1989,
PosixGetuid = 0x1990,
PosixExit = 0x1991,
Expand All @@ -39,6 +39,7 @@ enum Function {
PosixWrite = 0x2007,
PosixTtynameR = 0x2008,
PosixStat = 0x2009,
GetEnvironment = 0x2010,
};

void initialize();
Expand Down
41 changes: 37 additions & 4 deletions Kernel/Task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ int Task::sys$set_mmap_name(void* addr, size_t size, const char* name)

void* Task::sys$mmap(void* addr, size_t size)
{
InterruptDisabler disabler;
// FIXME: Implement mapping at a client-preferred address.
ASSERT(addr == nullptr);
auto* region = allocateRegion(size, "mmap");
Expand All @@ -193,6 +194,7 @@ void* Task::sys$mmap(void* addr, size_t size)

int Task::sys$munmap(void* addr, size_t size)
{
InterruptDisabler disabler;
auto* region = regionFromRange(LinearAddress((dword)addr), size);
if (!region)
return -1;
Expand All @@ -213,6 +215,12 @@ int Task::sys$gethostname(char* buffer, size_t size)

int Task::sys$spawn(const char* path, const char** args)
{
if (args) {
for (size_t i = 0; args[i]; ++i) {
VALIDATE_USER_BUFFER(args[i], strlen(args[i]));
}
}

int error = 0;
auto* child = Task::createUserTask(path, m_uid, m_gid, m_pid, error, args, m_tty);
if (child)
Expand Down Expand Up @@ -261,10 +269,17 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
taskArguments.append(parts.last());
}

Vector<String> taskEnvironment;
taskEnvironment.append("PATH=/bin");
taskEnvironment.append("SHELL=/bin/sh");
taskEnvironment.append("TERM=console");
taskEnvironment.append("HOME=/");

InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3, move(cwd), handle->vnode(), tty);

t->m_arguments = move(taskArguments);
t->m_initialEnvironment = move(taskEnvironment);

ExecSpace space;
Region* region = nullptr;
Expand Down Expand Up @@ -322,11 +337,29 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
#ifdef TASK_DEBUG
kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
#endif

error = 0;
return t;
}

int Task::sys$get_environment(char*** environ)
{
auto* region = allocateRegion(4096, "environ");
if (!region)
return -ENOMEM;
MM.mapRegion(*this, *region);
char* envpage = (char*)region->linearAddress.get();
*environ = (char**)envpage;
char* bufptr = envpage + (sizeof(char*) * (m_initialEnvironment.size() + 1));
for (size_t i = 0; i < m_initialEnvironment.size(); ++i) {
(*environ)[i] = bufptr;
memcpy(bufptr, m_initialEnvironment[i].characters(), m_initialEnvironment[i].length());
bufptr += m_initialEnvironment[i].length();
*(bufptr++) = '\0';
}
(*environ)[m_initialEnvironment.size()] = nullptr;
return 0;
}

int Task::sys$get_arguments(int* argc, char*** argv)
{
auto* region = allocateRegion(4096, "argv");
Expand Down Expand Up @@ -763,12 +796,12 @@ ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size)
return handle->get_dir_entries((byte*)buffer, size);
}

int Task::sys$seek(int fd, int offset)
int Task::sys$lseek(int fd, off_t offset, int whence)
{
auto* handle = fileHandleIfExists(fd);
if (!handle)
return -1;
return handle->seek(offset, SEEK_SET);
return -EBADF;
return handle->seek(offset, whence);
}

int Task::sys$ttyname_r(int fd, char* buffer, size_t size)
Expand Down
4 changes: 3 additions & 1 deletion Kernel/Task.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class Task : public InlineLinkedListNode<Task> {
ssize_t sys$write(int fd, const void*, size_t);
int sys$lstat(const char*, Unix::stat*);
int sys$stat(const char*, Unix::stat*);
int sys$seek(int fd, int offset);
int sys$lseek(int fd, off_t, int whence);
int sys$kill(pid_t pid, int sig);
int sys$geterror() { return m_error; }
void sys$exit(int status);
Expand All @@ -110,6 +110,7 @@ class Task : public InlineLinkedListNode<Task> {
int sys$gettimeofday(timeval*);
int sys$gethostname(char* name, size_t length);
int sys$get_arguments(int* argc, char*** argv);
int sys$get_environment(char*** environ);
int sys$uname(utsname*);
int sys$readlink(const char*, char*, size_t);
int sys$ttyname_r(int fd, char*, size_t);
Expand Down Expand Up @@ -220,6 +221,7 @@ class Task : public InlineLinkedListNode<Task> {
void murder();

Vector<String> m_arguments;
Vector<String> m_initialEnvironment;
};

extern void task_init();
Expand Down
7 changes: 7 additions & 0 deletions Kernel/sync-local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cp ../../figlet-2.2.5/figlet mnt/bin/
mkdir -p mnt/usr/local/share/figlet
FIGLET_FONTDIR=/
cp ../../figlet-2.2.5/fonts/standard.flf mnt/$FIGLET_FONTDIR
cp ../../figlet-2.2.5/fonts/big.flf mnt/$FIGLET_FONTDIR
cp ../../figlet-2.2.5/fonts/slant.flf mnt/$FIGLET_FONTDIR
cp ../../figlet-2.2.5/fonts/lean.flf mnt/$FIGLET_FONTDIR
1 change: 1 addition & 0 deletions Kernel/sync-sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ cp ../Userland/clear mnt/bin/clear
cp ../Userland/tst mnt/bin/tst
cp ../Userland/mm mnt/bin/mm
cp ../Userland/kill mnt/bin/kill
sh sync-local.sh
cp kernel.map mnt/
umount mnt
sync
2 changes: 2 additions & 0 deletions LibC/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ LIBC_OBJS = \
utsname.o \
assert.o \
signal.o \
getopt.o \
scanf.o \
entry.o

OBJS = $(AK_OBJS) $(LIBC_OBJS)
Expand Down
2 changes: 1 addition & 1 deletion LibC/assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ __BEGIN_DECLS

void __assertion_failed(const char* msg, const char* file, unsigned line, const char* func);

#define assert(expr) (static_cast<bool>(expr) ? (void)0 : __assertion_failed(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__))
#define assert(expr) ((expr) ? (void)0 : __assertion_failed(#expr, __FILE__, __LINE__, __PRETTY_FUNCTION__))
#define CRASH() do { asm volatile("ud2"); } while(0)
#define ASSERT assert
#define RELEASE_ASSERT assert
Expand Down
17 changes: 14 additions & 3 deletions LibC/entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ int errno;
FILE* stdin;
FILE* stdout;
FILE* stderr;
char** environ;

extern "C" void __malloc_init();

extern "C" int _start()
{
__malloc_init();

errno = 0;

__default_streams[0].fd = 0;
Expand All @@ -26,12 +31,18 @@ extern "C" int _start()

StringImpl::initializeGlobals();

int status = 254;
int argc;
char** argv;
int rc = Syscall::invoke(Syscall::GetArguments, (dword)&argc, (dword)&argv);
int status = 254;
if (rc == 0)
status = main(argc, argv);
if (rc < 0)
goto epilogue;
rc = Syscall::invoke(Syscall::GetEnvironment, (dword)&environ);
if (rc < 0)
goto epilogue;
status = main(argc, argv);

epilogue:
Syscall::invoke(Syscall::PosixExit, status);

// Birger's birthday <3
Expand Down
109 changes: 109 additions & 0 deletions LibC/getopt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright (c) 1987, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

#include <getopt.h>

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt; /* character checked for validity */
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */

#define BADCH (int)'?'
#define BADARG (int)':'
#define EMSG ""

int getopt(int nargc, char* const nargv[], const char* ostr)
{
static const char* place = EMSG; /* option letter processing */
char *oli; /* option letter list index */

ASSERT(nargv != NULL);
ASSERT(ostr != NULL);

if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (-1);
}
if (place[1] && *++place == '-' /* found "--" */
&& place[1] == '\0') {
++optind;
place = EMSG;
return -1;
}
} /* option letter okay? */
if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr, optopt))) {
/*
* if the user didn't specify '-' as an option,
* assume it means -1.
*/
if (optopt == (int)'-')
return -1;
if (!*place)
++optind;
if (opterr && *ostr != ':')
fprintf(stderr, "unknown option -- %c\n", optopt);
return BADCH;
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place)
++optind;
}
else { /* need an argument */
if (*place) /* no white space */
optarg = (char*)place;
else if (nargc <= ++optind) { /* no arg */
place = EMSG;
if (*ostr == ':')
return BADARG;
if (opterr)
fprintf(stderr, "option requires an argument -- %c\n", optopt);
return BADCH;
}
else /* white space */
optarg = nargv[optind];
place = EMSG;
++optind;
}
return optopt; /* dump back option letter */
}
13 changes: 13 additions & 0 deletions LibC/getopt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <sys/cdefs.h>

__BEGIN_DECLS

int getopt(int argc, char* const argv[], const char* optstring);
extern char* optarg;
extern int optind;
extern int opterr;
extern int optopt;

__END_DECLS
Loading

0 comments on commit 819ce91

Please sign in to comment.