⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/
stdlib.rs

1//! Standard Library Foundation
2//!
3//! Core library functions and utilities for user-space applications.
4
5#![allow(dead_code)]
6
7use alloc::{boxed::Box, format, string::String};
8use core::{ptr, slice};
9
10/// Memory allocation functions
11pub(crate) mod memory {
12    use super::*;
13
14    /// Allocate memory
15    ///
16    /// # Safety
17    /// Caller must eventually call `free` on the returned pointer (if non-null)
18    /// with the same allocator.  The returned memory is uninitialized.
19    pub(crate) unsafe fn malloc(size: usize) -> *mut u8 {
20        if size == 0 {
21            return ptr::null_mut();
22        }
23
24        // For now, use kernel allocator (in real implementation, use user-space
25        // allocator)
26        // Layout::from_size_align(1, 1) is infallible (size=1, align=1 is always valid)
27        let layout = core::alloc::Layout::from_size_align(size, 8)
28            .unwrap_or_else(|_| core::alloc::Layout::from_size_align(1, 1).expect("1-byte layout"));
29
30        alloc::alloc::alloc(layout)
31    }
32
33    /// Allocate zeroed memory
34    ///
35    /// # Safety
36    /// Caller must eventually call `free` on the returned pointer (if
37    /// non-null). `count * size` must not overflow (saturating_mul is used
38    /// as a safeguard).
39    pub(crate) unsafe fn calloc(count: usize, size: usize) -> *mut u8 {
40        let total_size = count.saturating_mul(size);
41        if total_size == 0 {
42            return ptr::null_mut();
43        }
44
45        // Layout::from_size_align(1, 1) is infallible (size=1, align=1 is always valid)
46        let layout = core::alloc::Layout::from_size_align(total_size, 8)
47            .unwrap_or_else(|_| core::alloc::Layout::from_size_align(1, 1).expect("1-byte layout"));
48
49        alloc::alloc::alloc_zeroed(layout)
50    }
51
52    /// Reallocate memory
53    ///
54    /// # Safety
55    /// `ptr` must be null or a pointer previously returned by
56    /// `malloc`/`calloc`. The old allocation is freed; do not use `ptr`
57    /// after this call. WARNING: current implementation assumes max 1KB old
58    /// allocation size.
59    pub(crate) unsafe fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 {
60        if ptr.is_null() {
61            return malloc(new_size);
62        }
63
64        if new_size == 0 {
65            free(ptr);
66            return ptr::null_mut();
67        }
68
69        // For now, allocate new and copy (in real implementation, try to expand in
70        // place)
71        let new_ptr = malloc(new_size);
72        if !new_ptr.is_null() {
73            // Copy old data (we don't know the old size, so this is a limitation)
74            // In a real implementation, we'd track allocation sizes
75            ptr::copy_nonoverlapping(ptr, new_ptr, new_size.min(1024)); // Assume max 1KB copy
76            free(ptr);
77        }
78
79        new_ptr
80    }
81
82    /// Free memory
83    ///
84    /// # Safety
85    /// `ptr` must be null or a pointer previously returned by `malloc`/`calloc`
86    /// that has not already been freed.  Double-free is undefined behavior.
87    pub(crate) unsafe fn free(ptr: *mut u8) {
88        if !ptr.is_null() {
89            // In real implementation, we'd track allocation size
90            // Layout(1, 1) is always valid: size > 0, align is power of 2
91            let layout = core::alloc::Layout::from_size_align(1, 1).expect("1-byte layout");
92            alloc::alloc::dealloc(ptr, layout);
93        }
94    }
95
96    /// Copy memory
97    ///
98    /// # Safety
99    /// `dest` and `src` must be valid for `n` bytes.  The regions must not
100    /// overlap; use `memmove` for overlapping copies.
101    pub(crate) unsafe fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
102        ptr::copy_nonoverlapping(src, dest, n);
103        dest
104    }
105
106    /// Move memory (handles overlapping regions)
107    ///
108    /// # Safety
109    /// `dest` and `src` must be valid for `n` bytes.  Regions may overlap.
110    pub(crate) unsafe fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
111        ptr::copy(src, dest, n);
112        dest
113    }
114
115    /// Set memory to value
116    ///
117    /// # Safety
118    /// `dest` must be valid for writing `n` bytes.
119    pub(crate) unsafe fn memset(dest: *mut u8, value: i32, n: usize) -> *mut u8 {
120        ptr::write_bytes(dest, value as u8, n);
121        dest
122    }
123
124    /// Compare memory
125    ///
126    /// # Safety
127    /// Both `s1` and `s2` must be valid for reading `n` bytes.
128    pub(crate) unsafe fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
129        let slice1 = slice::from_raw_parts(s1, n);
130        let slice2 = slice::from_raw_parts(s2, n);
131
132        for i in 0..n {
133            match slice1[i].cmp(&slice2[i]) {
134                core::cmp::Ordering::Less => return -1,
135                core::cmp::Ordering::Greater => return 1,
136                core::cmp::Ordering::Equal => continue,
137            }
138        }
139
140        0
141    }
142}
143
144/// String manipulation functions
145pub(crate) mod string {
146    use super::*;
147
148    /// Calculate string length
149    ///
150    /// # Safety
151    /// `s` must point to a valid, NUL-terminated C string.
152    pub(crate) unsafe fn strlen(s: *const u8) -> usize {
153        let mut len = 0;
154        while *s.add(len) != 0 {
155            len += 1;
156        }
157        len
158    }
159
160    /// Copy string
161    ///
162    /// # Safety
163    /// `src` must be NUL-terminated.  `dest` must have room for the
164    /// entire source string including its NUL terminator.
165    pub(crate) unsafe fn strcpy(dest: *mut u8, src: *const u8) -> *mut u8 {
166        let mut i = 0;
167        loop {
168            let c = *src.add(i);
169            *dest.add(i) = c;
170            if c == 0 {
171                break;
172            }
173            i += 1;
174        }
175        dest
176    }
177
178    /// Copy string with maximum length
179    ///
180    /// # Safety
181    /// `dest` must be valid for writing `n` bytes.  `src` must be valid
182    /// for reading up to `n` bytes or until a NUL terminator is found.
183    pub(crate) unsafe fn strncpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
184        let mut i = 0;
185        while i < n {
186            let c = *src.add(i);
187            *dest.add(i) = c;
188            if c == 0 {
189                break;
190            }
191            i += 1;
192        }
193
194        // Pad with zeros if necessary
195        while i < n {
196            *dest.add(i) = 0;
197            i += 1;
198        }
199
200        dest
201    }
202
203    /// Concatenate strings
204    ///
205    /// # Safety
206    /// Both `dest` and `src` must be NUL-terminated.  `dest` must have
207    /// room for its current content plus the entirety of `src` plus NUL.
208    pub(crate) unsafe fn strcat(dest: *mut u8, src: *const u8) -> *mut u8 {
209        let dest_len = strlen(dest);
210        strcpy(dest.add(dest_len), src);
211        dest
212    }
213
214    /// Compare strings
215    ///
216    /// # Safety
217    /// Both `s1` and `s2` must point to valid, NUL-terminated C strings.
218    pub(crate) unsafe fn strcmp(s1: *const u8, s2: *const u8) -> i32 {
219        let mut i = 0;
220        loop {
221            let c1 = *s1.add(i);
222            let c2 = *s2.add(i);
223
224            if c1 != c2 {
225                return if c1 < c2 { -1 } else { 1 };
226            }
227
228            if c1 == 0 {
229                return 0;
230            }
231
232            i += 1;
233        }
234    }
235
236    /// Compare strings with maximum length
237    ///
238    /// # Safety
239    /// Both `s1` and `s2` must be valid for reading up to `n` bytes
240    /// or until a NUL terminator is found.
241    pub(crate) unsafe fn strncmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
242        for i in 0..n {
243            let c1 = *s1.add(i);
244            let c2 = *s2.add(i);
245
246            if c1 != c2 {
247                return if c1 < c2 { -1 } else { 1 };
248            }
249
250            if c1 == 0 {
251                return 0;
252            }
253        }
254
255        0
256    }
257
258    /// Find character in string
259    ///
260    /// # Safety
261    /// `s` must point to a valid, NUL-terminated C string.
262    pub(crate) unsafe fn strchr(s: *const u8, c: i32) -> *const u8 {
263        let target = c as u8;
264        let mut i = 0;
265
266        loop {
267            let ch = *s.add(i);
268            if ch == target {
269                return s.add(i);
270            }
271            if ch == 0 {
272                break;
273            }
274            i += 1;
275        }
276
277        ptr::null()
278    }
279
280    /// Find substring in string
281    ///
282    /// # Safety
283    /// Both `haystack` and `needle` must point to valid, NUL-terminated C
284    /// strings.
285    pub(crate) unsafe fn strstr(haystack: *const u8, needle: *const u8) -> *const u8 {
286        let needle_len = strlen(needle);
287        if needle_len == 0 {
288            return haystack;
289        }
290
291        let haystack_len = strlen(haystack);
292        if needle_len > haystack_len {
293            return ptr::null();
294        }
295
296        for i in 0..=(haystack_len - needle_len) {
297            if strncmp(haystack.add(i), needle, needle_len) == 0 {
298                return haystack.add(i);
299            }
300        }
301
302        ptr::null()
303    }
304}
305
306/// File I/O functions
307pub(crate) mod io {
308    use alloc::sync::Arc;
309
310    use super::*;
311    use crate::fs::{get_vfs, OpenFlags};
312
313    /// File handle
314    ///
315    /// Fields are accessed through raw pointer dereference in the io module's
316    /// read/write/seek/close functions, so the compiler cannot see direct
317    /// usage.
318    #[allow(dead_code)] // Fields accessed via raw pointer dereference
319    pub struct File {
320        node: Arc<dyn crate::fs::VfsNode>,
321        position: usize,
322        flags: OpenFlags,
323    }
324
325    /// Standard file descriptors
326    pub const STDIN: i32 = 0;
327    pub const STDOUT: i32 = 1;
328    pub const STDERR: i32 = 2;
329
330    /// File open modes
331    pub const O_RDONLY: i32 = 0;
332    pub const O_WRONLY: i32 = 1;
333    pub const O_RDWR: i32 = 2;
334    pub const O_CREAT: i32 = 0x40;
335    pub const O_TRUNC: i32 = 0x200;
336    pub const O_APPEND: i32 = 0x400;
337
338    /// Seek modes
339    pub const SEEK_SET: i32 = 0;
340    pub const SEEK_CUR: i32 = 1;
341    pub const SEEK_END: i32 = 2;
342
343    /// Open a file
344    pub(crate) fn open(path: &str, flags: i32) -> Result<*mut File, crate::error::KernelError> {
345        let open_flags = if flags & O_RDWR != 0 {
346            OpenFlags::read_write()
347        } else if flags & O_WRONLY != 0 {
348            OpenFlags::write_only()
349        } else {
350            OpenFlags::read_only()
351        };
352
353        match get_vfs().read().open(path, open_flags) {
354            Ok(node) => {
355                let file = Box::new(File {
356                    node,
357                    position: 0,
358                    flags: open_flags,
359                });
360                Ok(Box::into_raw(file))
361            }
362            Err(e) => Err(e),
363        }
364    }
365
366    /// Close a file
367    ///
368    /// # Safety
369    /// `file` must be null or a pointer previously returned by `open`
370    /// that has not already been closed.  After this call, `file` is
371    /// dangling and must not be dereferenced.
372    pub(crate) unsafe fn close(file: *mut File) -> i32 {
373        if file.is_null() {
374            return -1;
375        }
376
377        drop(Box::from_raw(file));
378        0
379    }
380
381    /// Read from file
382    ///
383    /// # Safety
384    /// `file` must be a valid, open `File` pointer from `open`.
385    /// `buf` must be valid for writing `count` bytes.
386    pub(crate) unsafe fn read(file: *mut File, buf: *mut u8, count: usize) -> isize {
387        if file.is_null() || buf.is_null() {
388            return -1;
389        }
390
391        let file_ref = &mut *file;
392        let buffer = slice::from_raw_parts_mut(buf, count);
393
394        match file_ref.node.read(file_ref.position, buffer) {
395            Ok(bytes_read) => {
396                file_ref.position += bytes_read;
397                bytes_read as isize
398            }
399            Err(_) => -1,
400        }
401    }
402
403    /// Write to file
404    ///
405    /// # Safety
406    /// `file` must be a valid, open `File` pointer from `open`.
407    /// `buf` must be valid for reading `count` bytes.
408    pub(crate) unsafe fn write(file: *mut File, buf: *const u8, count: usize) -> isize {
409        if file.is_null() || buf.is_null() {
410            return -1;
411        }
412
413        let file_ref = &mut *file;
414        let buffer = slice::from_raw_parts(buf, count);
415
416        match file_ref.node.write(file_ref.position, buffer) {
417            Ok(bytes_written) => {
418                file_ref.position += bytes_written;
419                bytes_written as isize
420            }
421            Err(_) => -1,
422        }
423    }
424
425    /// Seek in file
426    ///
427    /// # Safety
428    /// `file` must be a valid, open `File` pointer from `open`.
429    pub(crate) unsafe fn seek(file: *mut File, offset: isize, whence: i32) -> isize {
430        if file.is_null() {
431            return -1;
432        }
433
434        let file_ref = &mut *file;
435
436        let new_position = match whence {
437            SEEK_SET => {
438                if offset < 0 {
439                    return -1;
440                }
441                offset as usize
442            }
443            SEEK_CUR => {
444                if offset < 0 && (-offset) as usize > file_ref.position {
445                    return -1;
446                }
447                if offset >= 0 {
448                    file_ref.position + offset as usize
449                } else {
450                    file_ref.position - (-offset) as usize
451                }
452            }
453            SEEK_END => {
454                // Get file size
455                match file_ref.node.metadata() {
456                    Ok(meta) => {
457                        if offset < 0 && (-offset) as usize > meta.size {
458                            return -1;
459                        }
460                        if offset >= 0 {
461                            meta.size + offset as usize
462                        } else {
463                            meta.size - (-offset) as usize
464                        }
465                    }
466                    Err(_) => return -1,
467                }
468            }
469            _ => return -1,
470        };
471
472        file_ref.position = new_position;
473        new_position as isize
474    }
475
476    /// Print to stdout
477    pub(crate) fn printf(fmt: &str, args: &[&dyn core::fmt::Display]) -> i32 {
478        // Simple printf implementation
479        let mut output = String::new();
480        let mut arg_index = 0;
481        let mut chars = fmt.chars();
482
483        while let Some(ch) = chars.next() {
484            if ch == '%' {
485                if let Some(next_ch) = chars.next() {
486                    match next_ch {
487                        's' | 'd' | 'x' | 'c' => {
488                            if arg_index < args.len() {
489                                output.push_str(&format!("{}", args[arg_index]));
490                                arg_index += 1;
491                            }
492                        }
493                        '%' => output.push('%'),
494                        _ => {
495                            output.push('%');
496                            output.push(next_ch);
497                        }
498                    }
499                } else {
500                    output.push('%');
501                }
502            } else {
503                output.push(ch);
504            }
505        }
506
507        crate::print!("{}", output);
508        output.len() as i32
509    }
510
511    /// Print to stdout with newline
512    pub(crate) fn puts(s: &str) -> i32 {
513        crate::println!("{}", s);
514        (s.len() + 1) as i32
515    }
516}
517
518/// Process management functions
519pub(crate) mod process {
520
521    /// Exit current process
522    pub(crate) fn exit(status: i32) -> ! {
523        crate::process::lifecycle::exit_process(status);
524        // Process should never return after exit.
525        // Use the arch-specific idle function to avoid duplicating
526        // inline asm that already exists in each arch module.
527        loop {
528            crate::arch::idle();
529        }
530    }
531
532    /// Get current process ID
533    pub(crate) fn getpid() -> u32 {
534        crate::process::get_current_process()
535            .map(|p| p.pid.0 as u32)
536            .unwrap_or(0) // Return 0 if no current process
537    }
538
539    /// Get parent process ID
540    pub(crate) fn getppid() -> u32 {
541        crate::process::get_current_process()
542            .and_then(|p| p.parent)
543            .map(|ppid| ppid.0 as u32)
544            .unwrap_or(1) // Return init (PID 1) if no parent or no current
545                          // process
546    }
547
548    /// Fork process
549    ///
550    /// Creates a copy of the current process. Returns:
551    /// - 0 to the child process
552    /// - Child's PID to the parent process
553    /// - -1 on error
554    pub(crate) fn fork() -> i32 {
555        match crate::process::fork_process() {
556            Ok(child_pid) => {
557                // fork_process() returns the child PID to the parent
558                // The child process will have return value 0 set in its context
559                child_pid.0 as i32
560            }
561            Err(_) => -1,
562        }
563    }
564
565    /// Execute program
566    pub(crate) fn exec(path: &str, args: &[&str]) -> i32 {
567        match crate::userspace::load_user_program(path, args, &[]) {
568            Ok(pid) => pid.0 as i32,
569            Err(_) => -1,
570        }
571    }
572
573    /// Wait for child process
574    ///
575    /// Waits for any child process to terminate and returns its PID.
576    /// If `status` is non-null, the exit status is stored there.
577    /// Returns -1 if there are no child processes or on error.
578    ///
579    /// # Safety
580    /// `status` must be either null or point to valid, writable, aligned
581    /// memory for a single `i32`.  If the pointer is invalid, writing the
582    /// exit status will corrupt memory or fault.
583    pub(crate) unsafe fn wait(status: *mut i32) -> i32 {
584        match crate::process::wait_for_child(None) {
585            Ok((pid, exit_status)) => {
586                // SAFETY: Caller guarantees `status` is null or a valid
587                // writable i32 pointer.  We check for null before writing.
588                if !status.is_null() {
589                    *status = exit_status;
590                }
591                pid.0 as i32
592            }
593            Err(_) => -1,
594        }
595    }
596}
597
598/// Math functions
599pub(crate) mod math {
600    /// Absolute value
601    pub(crate) fn abs(x: i32) -> i32 {
602        if x < 0 {
603            -x
604        } else {
605            x
606        }
607    }
608
609    /// Floating point absolute value
610    pub(crate) fn fabs(x: f64) -> f64 {
611        if x < 0.0 {
612            -x
613        } else {
614            x
615        }
616    }
617
618    /// Power function (integer)
619    pub(crate) fn pow_int(base: i32, exp: u32) -> i32 {
620        let mut result = 1;
621        let mut b = base;
622        let mut e = exp;
623
624        while e > 0 {
625            if e & 1 != 0 {
626                result *= b;
627            }
628            b *= b;
629            e >>= 1;
630        }
631
632        result
633    }
634
635    /// Square root (integer approximation)
636    pub(crate) fn sqrt_int(x: u32) -> u32 {
637        if x == 0 {
638            return 0;
639        }
640
641        let mut guess = x / 2;
642        let mut last_guess = x;
643
644        while guess != last_guess {
645            last_guess = guess;
646            guess = (guess + x / guess) / 2;
647        }
648
649        guess
650    }
651
652    /// Minimum
653    pub(crate) fn min(a: i32, b: i32) -> i32 {
654        if a < b {
655            a
656        } else {
657            b
658        }
659    }
660
661    /// Maximum
662    pub(crate) fn max(a: i32, b: i32) -> i32 {
663        if a > b {
664            a
665        } else {
666            b
667        }
668    }
669}
670
671/// Time functions
672pub(crate) mod time {
673    use core::sync::atomic::{AtomicU64, Ordering};
674
675    /// Boot timestamp base (could be set from RTC on boot)
676    static BOOT_TIME_SECONDS: AtomicU64 = AtomicU64::new(0);
677
678    /// Set boot time from RTC (call during system initialization)
679    pub(crate) fn set_boot_time(seconds_since_epoch: u64) {
680        BOOT_TIME_SECONDS.store(seconds_since_epoch, Ordering::Release);
681    }
682
683    /// Get current time in seconds since epoch
684    ///
685    /// Returns the current system time based on:
686    /// - Boot time (set from RTC during initialization)
687    /// - Timer ticks elapsed since boot
688    pub(crate) fn time() -> u64 {
689        let ticks = crate::arch::timer::get_ticks();
690        // Assuming ~1000 ticks per second (typical timer frequency)
691        // Convert ticks to seconds since boot
692        let seconds_since_boot = ticks / 1000;
693
694        BOOT_TIME_SECONDS.load(Ordering::Acquire) + seconds_since_boot
695    }
696
697    /// Sleep for seconds
698    pub(crate) fn sleep(seconds: u32) {
699        crate::thread_api::sleep_ms(seconds as u64 * 1000);
700    }
701
702    /// Sleep for microseconds
703    pub(crate) fn usleep(microseconds: u32) {
704        crate::thread_api::sleep_ms(microseconds as u64 / 1000);
705    }
706}
707
708/// Error handling
709pub(crate) mod error {
710    /// Error numbers (errno values)
711    pub const EPERM: i32 = 1; // Operation not permitted
712    pub const ENOENT: i32 = 2; // No such file or directory
713    pub const ESRCH: i32 = 3; // No such process
714    pub const EINTR: i32 = 4; // Interrupted system call
715    pub const EIO: i32 = 5; // I/O error
716    pub const ENXIO: i32 = 6; // No such device or address
717    pub const E2BIG: i32 = 7; // Argument list too long
718    pub const ENOEXEC: i32 = 8; // Exec format error
719    pub const EBADF: i32 = 9; // Bad file number
720    pub const ECHILD: i32 = 10; // No child processes
721    pub const EAGAIN: i32 = 11; // Try again
722    pub const ENOMEM: i32 = 12; // Out of memory
723    pub const EACCES: i32 = 13; // Permission denied
724    pub const EFAULT: i32 = 14; // Bad address
725    pub const EBUSY: i32 = 16; // Device or resource busy
726    pub const EEXIST: i32 = 17; // File exists
727    pub const ENODEV: i32 = 19; // No such device
728    pub const ENOTDIR: i32 = 20; // Not a directory
729    pub const EISDIR: i32 = 21; // Is a directory
730    pub const EINVAL: i32 = 22; // Invalid argument
731    pub const EMFILE: i32 = 24; // Too many open files
732    pub const ENOSPC: i32 = 28; // No space left on device
733    pub const EROFS: i32 = 30; // Read-only file system
734
735    use core::sync::atomic::{AtomicI32, Ordering};
736
737    static ERRNO: AtomicI32 = AtomicI32::new(0);
738
739    /// Get error number
740    pub(crate) fn get_errno() -> i32 {
741        ERRNO.load(Ordering::Relaxed)
742    }
743
744    /// Set error number
745    pub(crate) fn set_errno(errno: i32) {
746        ERRNO.store(errno, Ordering::Relaxed);
747    }
748
749    /// Get error string
750    pub(crate) fn strerror(errno: i32) -> &'static str {
751        match errno {
752            EPERM => "Operation not permitted",
753            ENOENT => "No such file or directory",
754            ESRCH => "No such process",
755            EINTR => "Interrupted system call",
756            EIO => "I/O error",
757            ENXIO => "No such device or address",
758            E2BIG => "Argument list too long",
759            ENOEXEC => "Exec format error",
760            EBADF => "Bad file number",
761            ECHILD => "No child processes",
762            EAGAIN => "Try again",
763            ENOMEM => "Out of memory",
764            EACCES => "Permission denied",
765            EFAULT => "Bad address",
766            EBUSY => "Device or resource busy",
767            EEXIST => "File exists",
768            ENODEV => "No such device",
769            ENOTDIR => "Not a directory",
770            EISDIR => "Is a directory",
771            EINVAL => "Invalid argument",
772            EMFILE => "Too many open files",
773            ENOSPC => "No space left on device",
774            EROFS => "Read-only file system",
775            _ => "Unknown error",
776        }
777    }
778}
779
780/// Random number generation
781pub(crate) mod random {
782    use core::sync::atomic::{AtomicU32, Ordering};
783
784    static SEED: AtomicU32 = AtomicU32::new(1);
785
786    /// Set random seed
787    pub(crate) fn srand(seed: u32) {
788        SEED.store(seed, Ordering::Relaxed);
789    }
790
791    /// Generate random number
792    pub(crate) fn rand() -> i32 {
793        let new_seed = SEED
794            .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |s| {
795                Some(s.wrapping_mul(1103515245).wrapping_add(12345))
796            })
797            .unwrap_or(1);
798        let result = new_seed.wrapping_mul(1103515245).wrapping_add(12345);
799        (result / 65536) as i32 % 32768
800    }
801
802    /// Generate random number in range
803    pub(crate) fn rand_range(min: i32, max: i32) -> i32 {
804        if min >= max {
805            return min;
806        }
807        min + (rand() % (max - min))
808    }
809}
810
811/// System information
812pub(crate) mod system {
813    use alloc::{collections::BTreeMap, string::String};
814
815    use spin::RwLock;
816
817    /// Global environment variable storage
818    static ENVIRONMENT: RwLock<Option<BTreeMap<String, String>>> = RwLock::new(None);
819
820    /// Initialize environment with default values
821    pub(crate) fn init_environment() {
822        let mut env = BTreeMap::new();
823        env.insert(
824            String::from("PATH"),
825            String::from("/bin:/usr/bin:/sbin:/usr/sbin"),
826        );
827        env.insert(String::from("HOME"), String::from("/root"));
828        env.insert(String::from("USER"), String::from("root"));
829        env.insert(String::from("SHELL"), String::from("/bin/vsh"));
830        env.insert(String::from("TERM"), String::from("vt100"));
831        env.insert(String::from("PWD"), String::from("/"));
832        env.insert(String::from("LANG"), String::from("C"));
833        *ENVIRONMENT.write() = Some(env);
834    }
835
836    /// System information structure
837    #[derive(Debug)]
838    pub struct SystemInfo {
839        pub os_name: &'static str,
840        pub version: &'static str,
841        pub architecture: &'static str,
842        pub total_memory: u64,
843        pub available_memory: u64,
844        pub cpu_count: u32,
845        pub uptime: u64,
846    }
847
848    /// Get system information
849    pub(crate) fn get_system_info() -> SystemInfo {
850        SystemInfo {
851            os_name: "VeridianOS",
852            version: "0.2.1",
853            architecture: if cfg!(target_arch = "x86_64") {
854                "x86_64"
855            } else if cfg!(target_arch = "aarch64") {
856                "aarch64"
857            } else if cfg!(target_arch = "riscv64") {
858                "riscv64"
859            } else {
860                "unknown"
861            },
862            total_memory: 1024 * 1024 * 1024,    // 1 GB
863            available_memory: 512 * 1024 * 1024, // 512 MB
864            cpu_count: 1,
865            uptime: 0,
866        }
867    }
868
869    /// Get environment variable
870    ///
871    /// Retrieves the value of the specified environment variable.
872    /// Returns None if the variable is not set.
873    pub(crate) fn getenv(name: &str) -> Option<String> {
874        let env_guard = ENVIRONMENT.read();
875        if let Some(ref env) = *env_guard {
876            env.get(name).cloned()
877        } else {
878            // Fallback defaults if environment not initialized
879            match name {
880                "PATH" => Some(String::from("/bin:/usr/bin")),
881                "HOME" => Some(String::from("/root")),
882                "USER" => Some(String::from("root")),
883                _ => None,
884            }
885        }
886    }
887
888    /// Set environment variable
889    ///
890    /// Sets the environment variable `name` to `value`.
891    /// Returns 0 on success, -1 on error.
892    pub(crate) fn setenv(name: &str, value: &str) -> i32 {
893        let mut env_guard = ENVIRONMENT.write();
894        if env_guard.is_none() {
895            // Initialize environment if not already done
896            *env_guard = Some(BTreeMap::new());
897        }
898
899        if let Some(ref mut env) = *env_guard {
900            env.insert(String::from(name), String::from(value));
901            0
902        } else {
903            -1
904        }
905    }
906
907    /// Unset environment variable
908    ///
909    /// Removes the environment variable `name`.
910    /// Returns 0 on success, -1 if variable doesn't exist.
911    pub(crate) fn unsetenv(name: &str) -> i32 {
912        let mut env_guard = ENVIRONMENT.write();
913        if let Some(ref mut env) = *env_guard {
914            if env.remove(name).is_some() {
915                0
916            } else {
917                -1
918            }
919        } else {
920            -1
921        }
922    }
923
924    /// Get all environment variables
925    ///
926    /// Returns a copy of all environment variables as a BTreeMap.
927    pub(crate) fn get_all_env() -> BTreeMap<String, String> {
928        let env_guard = ENVIRONMENT.read();
929        if let Some(ref env) = *env_guard {
930            env.clone()
931        } else {
932            BTreeMap::new()
933        }
934    }
935}
936
937/// Initialize standard library
938pub fn init() {
939    // Initialize environment variables with defaults
940    system::init_environment();
941    crate::println!("[STDLIB] Standard library foundation initialized");
942}