diff options
-rw-r--r-- | README.md | 19 | ||||
-rw-r--r-- | builddeps/limine.conf | 2 | ||||
-rw-r--r-- | builddeps/wallpaper.jpg | bin | 0 -> 203867 bytes | |||
-rw-r--r-- | configure.ac | 2 | ||||
-rwxr-xr-x | hyra-build.sh | 2 | ||||
-rw-r--r-- | sys/arch/amd64/isa/i8042.c | 6 | ||||
-rw-r--r-- | sys/fs/initramfs.c | 6 | ||||
-rw-r--r-- | sys/include/sys/limits.h | 1 | ||||
-rw-r--r-- | sys/include/sys/vnode.h | 24 | ||||
-rw-r--r-- | sys/kern/exec_elf64.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_descrip.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_sched.c | 19 | ||||
-rw-r--r-- | sys/kern/vfs_lookup.c | 4 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 6 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 2 | ||||
-rw-r--r-- | sys/vm/vm_vnode.c | 2 | ||||
-rw-r--r-- | tools/omar/omar.c | 41 | ||||
-rw-r--r-- | usr.bin/Makefile | 1 | ||||
-rw-r--r-- | usr.bin/date/date.c | 51 | ||||
-rw-r--r-- | usr.bin/getconf/getconf.c | 5 | ||||
-rw-r--r-- | usr.bin/login/login.c | 64 | ||||
-rw-r--r-- | usr.bin/sleep/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/sleep/sleep.c | 55 |
23 files changed, 271 insertions, 51 deletions
@@ -29,6 +29,25 @@ Default User: Upon booting, the `login` program will ask for user credentials. The default username is `root` and the default password is also `root`. +Programs: +---------------- +The Hyra userspace provides the user various programs that they can run, examples of +such programs include: + +- ``beep`` - Play a tone +- ``cat`` - Print files to stdout +- ``date`` - Get the current date or set system time +- ``echo`` - Print a line of text +- ``elfdump`` - Get information about an ELF binary +- ``fetch`` - System fetch! A must have :~) +- ``getconf`` - Get system configuration values +- ``mex`` - OSMORA hexdump utility +- ``sleep`` - Sleep for a number of seconds +- ``kmsg`` - Read the kernel message buffer +- ``readcore`` - Read coredump files + +And more! See ``usr.bin/*`` + Documentation: -------------- Documentation will be in the form of comments throughout the codebase and can also be found in the share/ directory within the project root. diff --git a/builddeps/limine.conf b/builddeps/limine.conf index d5ed978..1ad040c 100644 --- a/builddeps/limine.conf +++ b/builddeps/limine.conf @@ -1,5 +1,5 @@ timeout=10 -${WALLPAPER_PATH}=boot():/boot/tree.jpg +${WALLPAPER_PATH}=boot():/boot/wallpaper.jpg wallpaper: ${WALLPAPER_PATH} interface_branding_color: 1 term_background: 40000000 diff --git a/builddeps/wallpaper.jpg b/builddeps/wallpaper.jpg Binary files differnew file mode 100644 index 0000000..5d69f53 --- /dev/null +++ b/builddeps/wallpaper.jpg diff --git a/configure.ac b/configure.ac index 61f5b54..aec0464 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([Hyra], [2.2], [ian@osmora.org]) +AC_INIT([Hyra], [2.3], [ian@osmora.org]) TARGET="amd64" QEMU="qemu-system-x86_64" diff --git a/hyra-build.sh b/hyra-build.sh index 68f415f..1ebc3bb 100755 --- a/hyra-build.sh +++ b/hyra-build.sh @@ -67,7 +67,7 @@ gen_iso_root() { cp $RAMFS_NAME iso_root/boot/ cp builddeps/limine.conf stand/limine/limine-bios.sys \ stand/limine/limine-bios-cd.bin stand/limine/limine-uefi-cd.bin iso_root/ - cp builddeps/tree.jpg iso_root/boot/ + cp builddeps/wallpaper.jpg iso_root/boot/ } ################################## diff --git a/sys/arch/amd64/isa/i8042.c b/sys/arch/amd64/isa/i8042.c index 69d9f92..cde70ff 100644 --- a/sys/arch/amd64/isa/i8042.c +++ b/sys/arch/amd64/isa/i8042.c @@ -33,6 +33,7 @@ #include <sys/syslog.h> #include <sys/spinlock.h> #include <sys/param.h> +#include <sys/ascii.h> #include <sys/proc.h> #include <sys/reboot.h> #include <sys/queue.h> @@ -75,7 +76,7 @@ static int i8042_kb_getc(uint8_t sc, char *chr); static void i8042_drain(void); static char keytab[] = { - '\0', '\0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + '\0', '\x1B', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', '\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', @@ -276,6 +277,9 @@ i8042_kb_getc(uint8_t sc, char *chr) bool release = ISSET(sc, BIT(7)); switch (sc) { + case 0x76: + *chr = ASCII_ESC; + return 0; /* Caps lock [press] */ case 0x3A: /* diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c index c41deb4..beb2e84 100644 --- a/sys/fs/initramfs.c +++ b/sys/fs/initramfs.c @@ -61,12 +61,16 @@ struct initramfs_node { * @magic: Header magic ("OMAR") * @len: Length of the file * @namelen: Length of the filename + * @rev: OMAR revision + * @mode: File permissions */ struct __packed omar_hdr { char magic[4]; uint8_t type; uint8_t namelen; uint32_t len; + uint8_t rev; + uint32_t mode; }; static volatile struct limine_module_request mod_req = { @@ -140,7 +144,7 @@ initramfs_get_file(const char *path, struct initramfs_node *res) p += hdr->namelen; if (strcmp(namebuf, path) == 0) { - node.mode = 0700; + node.mode = hdr->mode; node.size = hdr->len; node.data = (void *)p; *res = node; diff --git a/sys/include/sys/limits.h b/sys/include/sys/limits.h index f56958e..5b97b68 100644 --- a/sys/include/sys/limits.h +++ b/sys/include/sys/limits.h @@ -31,6 +31,7 @@ #define _SYS_LIMITS_H_ #define PATH_MAX 1024 +#define NAME_MAX 256 #define SSIZE_MAX 32767 #define ARG_MAX 4096 #define CHAR_BIT 8 diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h index b135433..3402b02 100644 --- a/sys/include/sys/vnode.h +++ b/sys/include/sys/vnode.h @@ -92,6 +92,16 @@ struct vop_create_args { struct vnode **vpp; /* Result vnode */ }; +struct vop_getattr_args { + struct vnode *vp; /* Target vnode */ + struct vattr *res; /* Result vattr */ +}; + +struct vop_readdir_args { + struct vnode *vp; /* Target vnode */ + struct sio_txn *sio; /* SIO data to read into */ +}; + /* * A field in this structure is unavailable * if it has a value of VNOVAL. @@ -101,14 +111,10 @@ struct vattr { size_t size; }; -struct vop_getattr_args { - struct vnode *vp; - struct vattr *res; -}; - struct vops { int(*lookup)(struct vop_lookup_args *args); int(*getattr)(struct vop_getattr_args *args); + int(*readdir)(struct vop_readdir_args *args); int(*read)(struct vnode *vp, struct sio_txn *sio); int(*write)(struct vnode *vp, struct sio_txn *sio); int(*reclaim)(struct vnode *vp); @@ -117,19 +123,21 @@ struct vops { extern struct vnode *g_root_vnode; +/* Vnode cache operations */ int vfs_vcache_type(void); int vfs_vcache_migrate(int newtype); - int vfs_vcache_enter(struct vnode *vp); struct vnode *vfs_recycle_vnode(void); +/* Vnode operations */ int vfs_alloc_vnode(struct vnode **res, int type); int vfs_release_vnode(struct vnode *vp); -int vfs_vop_lookup(struct vnode *vp, struct vop_lookup_args *args); +/* Vnode operation wrappers */ +int vfs_vop_lookup(struct vop_lookup_args *args); +int vfs_vop_getattr(struct vop_getattr_args *args); int vfs_vop_read(struct vnode *vp, struct sio_txn *sio); int vfs_vop_write(struct vnode *vp, struct sio_txn *sio); -int vfs_vop_getattr(struct vnode *vp, struct vop_getattr_args *args); #endif /* _KERNEL */ #endif /* !_SYS_VNODE_H_ */ diff --git a/sys/kern/exec_elf64.c b/sys/kern/exec_elf64.c index 9706e77..8dc87dc 100644 --- a/sys/kern/exec_elf64.c +++ b/sys/kern/exec_elf64.c @@ -112,7 +112,7 @@ elf_get_file(const char *pathname, struct elf_file *res) getattr_args.res = &vattr; getattr_args.vp = vp; - status = vfs_vop_getattr(vp, &getattr_args); + status = vfs_vop_getattr(&getattr_args); if (status != 0) goto done; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 0fb026f..b5ff144 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -351,7 +351,7 @@ fd_seek(int fildes, off_t offset, int whence) getattr_args.vp = tmp->vp; getattr_args.res = &attr; - if ((vfs_vop_getattr(tmp->vp, &getattr_args)) < 0) { + if ((vfs_vop_getattr(&getattr_args)) < 0) { return -EPIPE; } diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 30036c0..774ba71 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -258,8 +258,27 @@ sched_enter(void) void sched_yield(void) { + struct proc *td; + struct cpu_info *ci = this_cpu(); + + if ((td = ci->curtd) == NULL) { + return; + } + + td->rested = true; + + /* FIXME: Hang yielding when waited on */ + if (ISSET(td->flags, PROC_WAITED)) { + return; + } + + ci->curtd = NULL; md_inton(); sched_oneshot(false); + + md_hlt(); + md_intoff(); + ci->curtd = td; } void diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index d88c447..7320102 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -181,7 +181,7 @@ namei_mp_search(struct mount *mp, const char *path, struct nameidata *ndp) lookup_args.dirvp = vp; lookup_args.vpp = &vp; - status = vfs_vop_lookup(vp, &lookup_args); + status = vfs_vop_lookup(&lookup_args); dynfree(name); if (status != 0) { @@ -234,7 +234,7 @@ namei(struct nameidata *ndp) lookup_args.name = path; lookup_args.dirvp = g_root_vnode; lookup_args.vpp = &vp; - status = vfs_vop_lookup(lookup_args.dirvp, &lookup_args); + status = vfs_vop_lookup(&lookup_args); /* Did we find it in the root */ if (status == 0) { diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index da0a4f9..69417d0 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -141,8 +141,9 @@ vfs_release_vnode(struct vnode *vp) } int -vfs_vop_lookup(struct vnode *vp, struct vop_lookup_args *args) +vfs_vop_lookup(struct vop_lookup_args *args) { + const struct vnode *vp = args->dirvp; const struct vops *vops = vp->vops; if (vops == NULL) @@ -180,8 +181,9 @@ vfs_vop_write(struct vnode *vp, struct sio_txn *sio) } int -vfs_vop_getattr(struct vnode *vp, struct vop_getattr_args *args) +vfs_vop_getattr(struct vop_getattr_args *args) { + const struct vnode *vp = args->vp; const struct vops *vops = vp->vops; if (vops == NULL) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 0d51331..d15ecf1 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -68,7 +68,7 @@ vfs_dostat(const char *path, struct stat *sbuf) vp = nd.vp; gattr.vp = vp; gattr.res = &attr; - error = vfs_vop_getattr(vp, &gattr); + error = vfs_vop_getattr(&gattr); if (error != 0) { return error; diff --git a/sys/vm/vm_vnode.c b/sys/vm/vm_vnode.c index 27defc9..777b382 100644 --- a/sys/vm/vm_vnode.c +++ b/sys/vm/vm_vnode.c @@ -73,7 +73,7 @@ vn_io(struct vnode *vp, struct vm_page **pgs, unsigned int npages, int rw) args.res = &vattr; c = MAX(vattr.size / DEFAULT_PAGESIZE, 1); - if ((err = vfs_vop_getattr(vp, &args)) != 0) { + if ((err = vfs_vop_getattr(&args)) != 0) { return err; } diff --git a/tools/omar/omar.c b/tools/omar/omar.c index 129303e..a4c7ad6 100644 --- a/tools/omar/omar.c +++ b/tools/omar/omar.c @@ -53,6 +53,9 @@ #define OMAR_ARCHIVE 0 #define OMAR_EXTRACT 1 +/* Revision */ +#define OMAR_REV 2 + #define ALIGN_UP(value, align) (((value) + (align)-1) & ~((align)-1)) #define BLOCK_SIZE 512 @@ -68,12 +71,16 @@ static const char *outpath = NULL; * @magic: Header magic ("OMAR") * @len: Length of the file * @namelen: Length of the filename + * @rev: OMAR revision + * @mode: File permissions */ struct omar_hdr { char magic[4]; uint8_t type; uint8_t namelen; uint32_t len; + uint8_t rev; + uint32_t mode; } __attribute__((packed)); static inline void @@ -112,7 +119,7 @@ strip_root(const char *path) * Recursive mkdir */ static void -mkpath(const char *path) +mkpath(struct omar_hdr *hdr, const char *path) { size_t len; char buf[256]; @@ -126,12 +133,12 @@ mkpath(const char *path) for (p = (char *)buf + 1; *p != '\0'; ++p) { if (*p == '/') { *p = '\0'; - mkdir(buf, 0700); + mkdir(buf, hdr->mode); *p = '/'; } } - mkdir(buf, 0700); + mkdir(buf, hdr->mode); } /* @@ -166,9 +173,11 @@ file_push(const char *pathname, const char *name) if (S_ISDIR(sb.st_mode)) { hdr.type = OMAR_DIR; } + hdr.mode = sb.st_mode; } hdr.len = (pathname == NULL) ? 0 : sb.st_size; + hdr.rev = OMAR_REV; hdr.namelen = strlen(name); /* @@ -282,16 +291,17 @@ archive_create(const char *base, const char *dirname) /* * Extract a single file * + * @hp: File header * @data: Data to extract * @len: Length of data * @path: Path to output file */ static int -extract_single(char *data, size_t len, const char *path) +extract_single(struct omar_hdr *hp, char *data, size_t len, const char *path) { int fd; - if ((fd = open(path, O_WRONLY | O_CREAT, 0700)) < 0) { + if ((fd = open(path, O_WRONLY | O_CREAT, hp->mode)) < 0) { return fd; } @@ -312,8 +322,10 @@ archive_extract(void) struct stat sb; struct omar_hdr *hdr; int fd, error; + size_t len; off_t off; char namebuf[256]; + char pathbuf[256]; if ((fd = open(inpath, O_RDONLY)) < 0) { perror("open"); @@ -351,20 +363,31 @@ archive_extract(void) fprintf(stderr, "bad magic\n"); break; } + if (hdr->rev != OMAR_REV) { + fprintf(stderr, "cannot extract rev %d archive\n", hdr->rev); + fprintf(stderr, "current OMAR revision: %d\n", OMAR_REV); + } name = (char *)hdr + sizeof(struct omar_hdr); memcpy(namebuf, name, hdr->namelen); namebuf[hdr->namelen] = '\0'; - printf("unpacking %s\n", namebuf); + + /* Get the full path */ + len = snprintf(pathbuf, sizeof(pathbuf), "%s/%s", outpath, namebuf); + if (len < 0) { + free(buf); + return len; + } + printf("unpacking %s\n", pathbuf); if (hdr->type == OMAR_DIR) { off = 512; - mkpath(namebuf); + mkpath(hdr, pathbuf); } else { - off = ALIGN_UP(sizeof(hdr) + hdr->namelen + hdr->len, BLOCK_SIZE); + off = ALIGN_UP(sizeof(*hdr) + hdr->namelen + hdr->len, BLOCK_SIZE); p = (char *)hdr + sizeof(struct omar_hdr); p += hdr->namelen; - extract_single(p, hdr->len, namebuf); + extract_single(hdr, p, hdr->len, pathbuf); } hdr = (struct omar_hdr *)((char *)hdr + off); diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 4c17ddf..e84831a 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -19,3 +19,4 @@ all: make -C echo/ $(ARGS) make -C readcore/ $(ARGS) make -C login/ $(ARGS) + make -C sleep/ $(ARGS) diff --git a/usr.bin/date/date.c b/usr.bin/date/date.c index a47e3eb..ab26c4c 100644 --- a/usr.bin/date/date.c +++ b/usr.bin/date/date.c @@ -32,6 +32,7 @@ #include <stdio.h> #include <fcntl.h> #include <unistd.h> +#include <string.h> #define MONTHS_PER_YEAR 12 #define DAYS_PER_WEEK 7 @@ -51,19 +52,63 @@ static const char *daytab[] = { "Fri" }; +static int +set_time(int clock_fd, struct date *dp, char *timestr) +{ + uint32_t hour, min, sec; + char *p; + + /* Hour */ + p = strtok(timestr, ":"); + if (p == NULL) + return -1; + hour = atoi(p); + + /* Minute */ + p = strtok(NULL, ":"); + if (p == NULL) + return -1; + min = atoi(p); + + /* Second */ + p = strtok(NULL, ":"); + if (p == NULL) + return -1; + sec = atoi(p); + + /* Set the time */ + dp->hour = hour; + dp->min = min; + dp->sec = sec; + write(clock_fd, dp, sizeof(*dp)); + return 0; +} + int -main(void) +main(int argc, char **argv) { const char *day, *month; char date_str[32]; struct date d; - int rtc_fd; + int rtc_fd, error = 0; - if ((rtc_fd = open("/dev/rtc", O_RDONLY)) < 0) { + if ((rtc_fd = open("/dev/rtc", O_RDWR)) < 0) { return rtc_fd; } + read(rtc_fd, &d, sizeof(d)); + + /* + * If a time was specified to be set in the + * 'hh:mm:ss' format, attempt to write it. + */ + if (argc > 1) { + error = set_time(rtc_fd, &d, argv[1]); + if (error < 0) + printf("bad time specified, not set\n"); + } + close(rtc_fd); /* This should not happen */ diff --git a/usr.bin/getconf/getconf.c b/usr.bin/getconf/getconf.c index c60bf5d..f028e76 100644 --- a/usr.bin/getconf/getconf.c +++ b/usr.bin/getconf/getconf.c @@ -37,12 +37,15 @@ struct sysvar { const char *var; uint8_t auxv : 1; - uint8_t val; + uint32_t val; }; static struct sysvar vartab[] = { { "PAGESIZE", 1, AT_PAGESIZE }, { "CHAR_BIT", 0, CHAR_BIT }, + { "NAME_MAX", 0, NAME_MAX }, + { "PATH_MAX", 0, PATH_MAX }, + { "SSIZE_MAX", 0, SSIZE_MAX }, { NULL, 0, 0 } }; diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c index 5938d19..e9b5e88 100644 --- a/usr.bin/login/login.c +++ b/usr.bin/login/login.c @@ -47,7 +47,6 @@ #define is_ascii(C) ((C) >= 0 && (C) <= 128) #define is_digit(C) ((C >= '0' && C <= '9')) -#define USERNAME "root" #define DEFAULT_SHELL "/usr/bin/osh" static char buf[64]; @@ -95,11 +94,15 @@ static int check_user(char *alias, char *hash, char *entry) { const char *p; + char shell_path[256]; char *shell_argv[] = { DEFAULT_SHELL, NULL }; char *envp[] = { NULL }; - size_t row = 0; - short retval = -1; + size_t len, row = 0; size_t line = 1; + short have_user = 0; + short have_pw = 0; + short have_uid = 0; + short have_shell = 0; uid_t uid = -1; if (alias == NULL || entry == NULL) { @@ -118,12 +121,12 @@ check_user(char *alias, char *hash, char *entry) switch (row) { case ROW_USERNAME: if (strcmp(p, alias) == 0) { - retval = 0; + have_user = 1; } break; /* UNREACHABLE */ case ROW_HASH: if (strcmp(p, hash) == 0) { - retval = 0; + have_pw = 1; } break; case ROW_USERID: @@ -133,9 +136,18 @@ check_user(char *alias, char *hash, char *entry) } uid = atoi(p); + have_uid = 1; break; case ROW_SHELL: - /* TODO */ + len = strlen(p) - 1; + if (len >= sizeof(shell_path) - 1) { + printf("bad shell path @ line %d\n", line); + return -1; + } + + memcpy(shell_path, p, len); + shell_path[len] = '\0'; + have_shell = 1; break; } @@ -144,16 +156,24 @@ check_user(char *alias, char *hash, char *entry) ++line; } - if (uid < 0) { - printf("failed to set uid\n"); + /* + * We need to have found the password hash, + * the username, AND the UID. If we have not, + * then this has failed. + */ + if (!have_pw || !have_user || !have_uid) { return -1; } - if (retval == 0) { - setuid(uid); - spawn(shell_argv[0], shell_argv, envp, SPAWN_WAIT); + /* Do we have the shell path? */ + if (!have_shell) { + return -1; } - return retval; + + setuid(uid); + shell_argv[0] = shell_path; + spawn(shell_argv[0], shell_argv, envp, SPAWN_WAIT); + return 0; } static char * @@ -205,35 +225,45 @@ getstr(void) static int getuser(FILE *fp) { - char *pwtmp; - char *alias; + char *pwtmp, *alias, *p; char entry[256]; char pwhash[SHA256_HEX_SIZE]; int retval; printf("username: "); - alias = getstr(); + p = getstr(); + alias = strdup(p); /* Grab the password now */ echo_chars = 0; printf("password: "); - pwtmp = getstr(); + p = getstr(); + pwtmp = strdup(p); sha256_hex(pwtmp, strlen(pwtmp), pwhash); /* Paranoia */ - pwtmp = NULL; + memset(pwtmp, 0, strlen(pwtmp)); buf_i = 0; memset(buf, 0, sizeof(buf)); + /* Clean up */ + free(pwtmp); + pwtmp = NULL; + /* See if anything matches */ while (fgets(entry, sizeof(entry), fp) != NULL) { retval = check_user(alias, pwhash, entry); if (retval == 0) { printf("login: successful\n"); + free(alias); return 0; } } + /* If we reach this point, bad creds */ + free(alias); + alias = NULL; + printf("bad username or password\n"); fseek(fp, 0, SEEK_SET); memset(buf, 0, sizeof(buf)); diff --git a/usr.bin/sleep/Makefile b/usr.bin/sleep/Makefile new file mode 100644 index 0000000..5bfd04f --- /dev/null +++ b/usr.bin/sleep/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/sleep: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/sleep/sleep.c b/usr.bin/sleep/sleep.c new file mode 100644 index 0000000..f7d07f8 --- /dev/null +++ b/usr.bin/sleep/sleep.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * 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. Neither the name of Hyra 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 <time.h> +#include <string.h> +#include <stdio.h> + +int +main(int argc, char **argv) +{ + struct timespec ts; + uint16_t nsec = 0; + + if (argc < 2) { + printf("sleep: usage: sleep <seconds>\n"); + return -1; + } + + nsec = atoi(argv[1]); + if (nsec == 0) { + printf("sleep: bad argument\n"); + return -1; + } + + ts.tv_nsec = 0; + ts.tv_sec = nsec; + sleep(&ts, &ts); + return 0; +} |