Fixed all but the isr.c and isr.h files. Still some mintor issues to fixe here.

This commit is contained in:
Gregory Kenneth Bowne 2023-09-21 15:40:56 -07:00
parent 74d12e70ef
commit 6d5229a0f7
9 changed files with 366 additions and 182 deletions

162
ask.txt Normal file
View File

@ -0,0 +1,162 @@
I am making an x86 32 bit IA32 Operating System in Visual Studio Code 1.81 for Debian Linux. It's not a linux based OS. The system I am developing on has a Intel i7-3770k and is an x86_64 bit and runs Debian 10 Buster Linux with Linux Kernel version 4.19.0-25-amd64 (supports UNIX 98 PTY)and Bash 5.0.3 and the drive has an ext4 partition and a tempfs partition. I have the extension ms-vscode.cpptools installed on VSCode. I also have both gcc 8.3.0 and clang 7.0.1-8+deb10u2 installed. All of my compilers, debuggers, linkers are in /usr/bin. I have Coreutils 8.30, Binutils 2.31.1, Bison 3.3.2, Diffutils 3.7, Findutils 4.6.0.225, Gawk 4.2.1, Grep 3.3, Gzip 1.9, M4 1.4.18, Make 4.2.1, Patch 2.7.6, Perl 5.28.1, Python 3.7.3, Sed 4.7, Tar 1.30, Texinfo 6.5, Xz 5.2.4.
ClassicOS/
├── .github/
├── .vs/
├── .vscode/
├── CMakeLists.txt
├── README.md
├── build/
│ ├── boot.bin
│ └── boot.o
├── include/
├── src/
│ ├── boot/
│ │ ├── grub/
│ │ │ ├── grub.cf
│ │ │ └── menu.lst
│ │ ├── boot.asm
│ │ ├── linker.ld
│ ├── drivers/
│ │ ├── audio/
│ │ │ ├── audio.c
│ │ │ └── audio.h
│ │ ├── bus/
│ │ │ ├── eisa.c
│ │ │ ├── eisa.h
│ │ │ ├── isa.c
│ │ │ ├── isa.h
│ │ │ ├── mca.c
│ │ │ ├── mca.h
│ │ │ ├── pci.c
│ │ │ ├── pci.h
│ │ │ ├── vesa.c
│ │ │ └── vesa.h
│ │ ├── display/
│ │ │ ├── display.c
│ │ │ └── display.h
│ │ ├── io/
│ │ │ ├── io.c
│ │ │ └── movement.c
│ │ ├── keyboard/
│ │ │ ├── keyboard.c
│ │ │ └── keyboard.h
│ │ ├── mouse/
│ │ │ ├── mouse.c
│ │ │ └── mouse.h
│ │ ├── screen/
│ │ │ ├── screen.c
│ │ │ └── screen.h
│ │ ├── tty/
│ │ │ ├── tty.c
│ │ │ └── tty.h
│ ├── kernel/
│ │ ├── arch/
│ │ │ └── x86/
│ │ │ │ └── include/
│ │ │ │ │ ├── memory.c
│ │ │ │ │ ├── types.h
│ │ │ │ │ └── types.h
│ │ │ │ └── memory/
│ │ │ │ │ └── memory.c
│ │ │ ├── gdt.c
│ │ │ ├── gdt.h
│ │ │ ├── idt.c
│ │ │ ├── idt.h
│ │ │ ├── isr.c
│ │ │ └── isr.h
│ │ ├── kernel.c
│ │ ├── kernel.h
│ │ ├── kernel.o
│ │ ├── linker.ld
│ │ ├── print.c
│ │ └── print.o
│ └── shell/
│ ├── shell.c
│ └── shell.h
└── std/
This is my CMakeLists.txt
cmake_minimum_required(VERSION 3.13.4)
project(ClassicOS VERSION 0.0.1 LANGUAGES C)
# Source files
set(BOOT_SOURCE_FILES
src/boot/boot.asm
src/boot/linker.ld
)
set(GRUB_SOURCE_FILES
src/boot/grub/grub.cfg
src/boot/grub/menu.lst
)
set(DRIVERS_SOURCE_FILES
src/drivers/audio/audio.c
src/drivers/audio/audio.h
src/drivers/bus/eisa.c
src/drivers/bus/eisa.h
src/drivers/bus/isa.c
src/drivers/bus/isa.h
src/drivers/bus/mca.c
src/drivers/bus/mca.h
src/drivers/bus/pci.c
src/drivers/bus/pci.h
src/drivers/bus/vesa.c
src/drivers/bus/vesa.h
src/drivers/display/display.c
src/drivers/display/display.h
src/drivers/io/io.c
src/drivers/io/io.h
src/drivers/keyboard/keyboard.c
src/drivers/keyboard/keyboard.h
src/drivers/screen/screen.c
src/drivers/screen/screen.h
src/drivers/tty/tty.c
src/drivers/tty/tty.h
)
set(KERNEL_SOURCE_FILES
src/kernel/arch/x86/include/memory.h
src/kernel/arch/x86/include/types.h
src/kernel/arch/x86/include/types.h
src/kernel/arch/x86/memory/memory.c
src/kernel/arch/x86/gdt.c
src/kernel/arch/x86/gdt.c
src/kernel/arch/x86/idt.c
src/kernel/arch/x86/idt.h
src/kernel/arch/x86/isr.c
src/kernel/arch/x86/isr.h
src/kernel/kernel.c
src/kernel/kernel.h
src/kernel/linker.ld
src/kernel/print.c
)
add_executable(ClassicOS
${BOOT_SOURCE_FILES}
${GRUB_SOURCE_FILES}
${DRIVERS_SOURCE_FILES}
${KERNEL_SOURCE_FILES}
)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Enable testing
enable_testing()
target_link_libraries(ClassicOS PRIVATE)
set(CMAKE_C_COMPILER gcc)
set(CMAKE_LINKER ld)
set(CMAKE_EXE_LINKER_FLAGS "-g")
set(CMAKE_CXX_FLAGS "-g -Wall")
set(CMAKE_C_FLAGS "-g -Wall")
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_ASM_COMPILER nasm)
set(CMAKE_SYSTEM_PROCESSOR i386)
set(CMAKE_ASM_NASM_COMPILER nasm)
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build)
set_target_properties(ClassicOS PROPERTIES LINK_FLAGS "-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld")

View File

@ -1,87 +0,0 @@
[
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/audio/audio.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/audio/audio.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/audio/audio.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/bus/eisa.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/bus/eisa.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/bus/eisa.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/bus/isa.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/bus/isa.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/bus/isa.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/bus/mca.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/bus/mca.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/bus/mca.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/bus/pci.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/bus/pci.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/bus/pci.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/bus/vesa.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/bus/vesa.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/bus/vesa.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/display/display.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/display/display.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/display/display.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/io/io.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/io/io.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/io/io.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/keyboard/keyboard.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/keyboard/keyboard.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/keyboard/keyboard.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/screen/screen.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/screen/screen.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/screen/screen.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/drivers/tty/tty.c.o -c /home/gbowne1/Documents/ClassicOS/src/drivers/tty/tty.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/drivers/tty/tty.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/kernel/arch/x86/memory/memory.c.o -c /home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/memory/memory.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/memory/memory.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/kernel/arch/x86/gdt.c.o -c /home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/gdt.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/gdt.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/kernel/arch/x86/idt.c.o -c /home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/idt.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/idt.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/kernel/arch/x86/isr.c.o -c /home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/isr.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/kernel/arch/x86/isr.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/kernel/kernel.c.o -c /home/gbowne1/Documents/ClassicOS/src/kernel/kernel.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/kernel/kernel.c"
},
{
"directory": "/home/gbowne1/Documents/ClassicOS/build",
"command": "gcc -g -Wall -g -o CMakeFiles/ClassicOS.dir/src/kernel/print.c.o -c /home/gbowne1/Documents/ClassicOS/src/kernel/print.c",
"file": "/home/gbowne1/Documents/ClassicOS/src/kernel/print.c"
}
]

View File

@ -5,15 +5,26 @@
#include <stdint.h>
// Keyboard input buffer
#define KEYBOARD_BUFFER_SIZE 32
#define KEYBOARD_BUFFER_SIZE 32
#define KEYBOARD_DATA_PORT 0x60
#define KEYBOARD_INTERRUPT_VECTOR 0x09
#define KEYBOARD_COMMAND_PORT 0x64
#define KEYBOARD_DATA_PORT 0x60
#define KEYBOARD_ENABLE_COMMAND 0xAE
#define KEYBOARD_ENABLE_SCANCODE 0xF4
#define KEYBOARD_ACKNOWLEDGE_SCANCODE 0xFA
static uint8_t keyboard_buffer[KEYBOARD_BUFFER_SIZE];
static size_t keyboard_buffer_head = 0;
static size_t keyboard_buffer_tail = 0;
void set_interrupt_vector(uint8_t vector, void (*handler)());
void enable_interrupt(uint8_t vector);
// Keyboard interrupt handler
void keyboard_interrupt_handler()
{
uint8_t scancode = inb(0x60);
uint8_t scancode = inb(KEYBOARD_DATA_PORT);
// Add scancode to buffer
keyboard_buffer[keyboard_buffer_head] = scancode;
@ -24,15 +35,15 @@ void keyboard_interrupt_handler()
void keyboard_init()
{
// Install keyboard interrupt handler
set_interrupt_vector(0x09, keyboard_interrupt_handler);
enable_interrupt(0x09);
set_interrupt_vector(KEYBOARD_INTERRUPT_VECTOR, keyboard_interrupt_handler);
enable_interrupt(KEYBOARD_INTERRUPT_VECTOR);
// Enable keyboard
outb(0x64, 0xAE);
while (inb(0x64) & 0x02)
outb(KEYBOARD_COMMAND_PORT, KEYBOARD_ENABLE_COMMAND);
while (inb(KEYBOARD_COMMAND_PORT) & 0x02)
;
outb(0x60, 0xF4);
while (inb(0x60) != 0xFA)
outb(KEYBOARD_DATA_PORT, KEYBOARD_ENABLE_SCANCODE);
while (inb(KEYBOARD_DATA_PORT) != KEYBOARD_ACKNOWLEDGE_SCANCODE)
;
}

View File

@ -1,11 +1,13 @@
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h>
void keyboard_init();
bool keyboard_buffer_empty();
void keyboard_init();
bool keyboard_buffer_empty();
uint8_t keyboard_read_scancode();
void set_interrupt_vector(uint8_t vector, void (*handler)());
void enable_interrupt(uint8_t vector);
#endif

View File

@ -1,29 +1,34 @@
// gdt.h
#ifndef GDT_H
#define GDT_H
#include <stdint.h>
// GDT table
extern struct gdt_entry *gdt;
// GDT entry structure
struct gdt_entry
{
uint16_t limit_low; // Lower 16 bits of segment limit
uint16_t base_low; // Lower 16 bits of segment base address
uint8_t base_middle; // Middle 8 bits of segment base address
uint8_t access; // Access flags
uint8_t granularity; // Granularity and segment limit flags
uint8_t base_high; // Upper 8 bits of segment base address
uint16_t limit_low; // The lower 16 bits of the limit
uint16_t base_low; // The lower 16 bits of the base
uint8_t base_middle; // The next 8 bits of the base
uint8_t access; // Access flags, determine what ring this segment can be used in
uint8_t granularity;
uint8_t base_high; // The last 8 bits of the base
} __attribute__((packed));
// GDT pointer structure
struct gdt_ptr
{
uint16_t limit; // Size of GDT in bytes - 1
uint32_t base; // Address of GDT
uint16_t limit; // The upper 16 bits of all selector limits
uint32_t base; // The address of the first gdt_entry_t struct
} __attribute__((packed));
// Initialize the GDT
void gdt_init();
// Set a GDT entry
void gdt_set_gate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran);
#endif

View File

@ -37,7 +37,7 @@ extern void serial_port_handler();
// Initialize an IDT entry
void idt_set_gate(uint8_t num, void *base, uint16_t sel, uint8_t flags)
{
uint32_t base_addr = (uint32_t)base;
uintptr_t base_addr = (uintptr_t)base;
idt[num].base_lo = base_addr & BYTE_MASK;
idt[num].base_hi = (base_addr >> BASE_MIDDLE_SHIFT) & 0xFFFF;
idt[num].sel = sel;

View File

@ -3,16 +3,10 @@
#include <stdint.h>
// Structure for storing register values during an ISR
struct isr_regs
// Define the isr_regs structure
struct idt_regs
{
uint32_t ds; // Data segment selector
uint32_t edi, esi, ebp, esp, ebx, edx, ecx,
eax; // Pushed by pusha instruction
uint32_t int_no,
err_code; // Interrupt number and error code (if applicable)
uint32_t eip, cs, eflags, useresp,
ss; // Pushed by the processor automatically
// Add the necessary members for your ISR context
};
// IDT entry structure
@ -34,12 +28,12 @@ struct idt_ptr
// Exception handlers
void divide_error();
void page_fault(struct isr_regs *regs);
void general_protection_fault(struct isr_regs *regs);
void page_fault(struct idt_regs *);
void general_protection_fault(struct idt_regs *);
void double_fault();
// Interrupt handlers
void system_call(struct isr_regs *regs);
void system_call(struct idt_regs *);
void timer();
void keyboard();
void device();

View File

@ -2,14 +2,21 @@
#include "idt.h"
#include <stdio.h>
enum {
TIMER_INTERRUPT = 0x20,
KEYBOARD_INTERRUPT = 0x21,
NETWORK_INTERRUPT = 0x22,
DISK_INTERRUPT = 0x23,
enum
{
TIMER_INTERRUPT = 0x20,
KEYBOARD_INTERRUPT = 0x21,
NETWORK_INTERRUPT = 0x22,
DISK_INTERRUPT = 0x23,
SERIAL_PORT_INTERRUPT = 0x24
};
struct isr_regs
{
// Define the structure of the isr_regs here
// ...
};
// ISR table
void (*isr_table[256])(struct isr_regs *regs);
@ -19,26 +26,29 @@ void isr_register(uint8_t num, void (*handler)(struct isr_regs *regs))
isr_table[num] = handler;
}
// ISR handler
// ISR handler
void isr_handler(struct isr_regs *regs)
{
switch (regs->int_no) {
case 0:
divide_error();
break;
case 13:
general_protection_fault(regs);
break;
case 14:
page_fault(regs);
break;
default:
void (*handler)(struct isr_regs *regs);
handler = isr_table[regs->int_no];
if (handler) {
handler(regs);
}
break;
switch (regs->int_no)
{
case 0:
divide_error();
break;
case 13:
general_protection_fault(regs);
break;
case 14:
page_fault(regs);
break;
default:
void (*handler)(struct isr_regs *regs);
handler = isr_table[regs->int_no];
if (handler)
{
handler(regs);
}
break;
}
}
@ -81,29 +91,30 @@ void system_call(struct isr_regs *regs)
uint32_t syscall_number = regs->eax;
// Handle different system call numbers
switch (syscall_number) {
case 1:
// Handle open() system call
// ...
break;
case 2:
// Handle read() system call
// ...
break;
case 3:
// Handle write() system call
// ...
break;
case 4:
// Handle close() system call
// ...
break;
switch (syscall_number)
{
case 1:
// Handle open() system call
// ...
break;
case 2:
// Handle read() system call
// ...
break;
case 3:
// Handle write() system call
// ...
break;
case 4:
// Handle close() system call
// ...
break;
// Add more cases for other system calls
default:
// Unknown system call number
printf("Unknown system call number: %d\n", syscall_number);
break;
default:
// Unknown system call number
printf("Unknown system call number: %d\n", syscall_number);
break;
}
}
@ -123,27 +134,28 @@ void device()
uint32_t interrupt_type = read_interrupt_type();
// Call the appropriate interrupt handler
switch (interrupt_type) {
case TIMER_INTERRUPT:
timer();
break;
case KEYBOARD_INTERRUPT:
keyboard();
break;
case NETWORK_INTERRUPT:
network();
break;
case DISK_INTERRUPT:
disk();
break;
case SERIAL_PORT_INTERRUPT:
serial_port();
break;
switch (interrupt_type)
{
case TIMER_INTERRUPT:
timer();
break;
case KEYBOARD_INTERRUPT:
keyboard();
break;
case NETWORK_INTERRUPT:
network();
break;
case DISK_INTERRUPT:
disk();
break;
case SERIAL_PORT_INTERRUPT:
serial_port();
break;
// Add more cases for other types of device interrupts
default:
// Unknown interrupt type
printf("Unknown device interrupt type: %d\n", interrupt_type);
break;
default:
// Unknown interrupt type
printf("Unknown device interrupt type: %d\n", interrupt_type);
break;
}
}

85
version-check.sh Normal file
View File

@ -0,0 +1,85 @@
#!/bin/bash
# A script to list version numbers of critical development tools
# If you have tools installed in other directories, adjust PATH here AND
# in ~lfs/.bashrc (section 4.4) as well.
LC_ALL=C
PATH=/usr/bin:/bin
bail() { echo "FATAL: $1"; exit 1; }
grep --version > /dev/null 2> /dev/null || bail "grep does not work"
sed '' /dev/null || bail "sed does not work"
sort /dev/null || bail "sort does not work"
ver_check()
{
if ! type -p $2 &>/dev/null
then
echo "ERROR: Cannot find $2 ($1)"; return 1;
fi
v=$($2 --version 2>&1 | grep -E -o '[0-9]+\.[0-9\.]+[a-z]*' | head -n1)
if printf '%s\n' $3 $v | sort --version-sort --check &>/dev/null
then
printf "OK: %-9s %-6s >= $3\n" "$1" "$v"; return 0;
else
printf "ERROR: %-9s is TOO OLD ($3 or later required)\n" "$1";
return 1;
fi
}
ver_kernel()
{
kver=$(uname -r | grep -E -o '^[0-9\.]+')
if printf '%s\n' $1 $kver | sort --version-sort --check &>/dev/null
then
printf "OK: Linux Kernel $kver >= $1\n"; return 0;
else
printf "ERROR: Linux Kernel ($kver) is TOO OLD ($1 or later required)\n" "$kver";
return 1;
fi
}
# Coreutils first because-sort needs Coreutils >= 7.0
ver_check Coreutils sort 7.0 || bail "--version-sort unsupported"
ver_check Bash bash 3.2
ver_check Binutils ld 2.13.1
ver_check Bison bison 2.7
ver_check Diffutils diff 2.8.1
ver_check Findutils find 4.2.31
ver_check Gawk gawk 4.0.1
ver_check GCC gcc 5.1
ver_check "GCC (C++)" g++ 5.1
ver_check Grep grep 2.5.1a
ver_check Gzip gzip 1.3.12
ver_check M4 m4 1.4.10
ver_check Make make 4.0
ver_check Patch patch 2.5.4
ver_check Perl perl 5.8.8
ver_check Python python3 3.4
ver_check Sed sed 4.1.5
ver_check Tar tar 1.22
ver_check Texinfo texi2any 5.0
ver_check Xz xz 5.0.0
ver_kernel 4.14
if mount | grep -q 'devpts on /dev/pts' && [ -e /dev/ptmx ]
then echo "OK: Linux Kernel supports UNIX 98 PTY";
else echo "ERROR: Linux Kernel does NOT support UNIX 98 PTY"; fi
alias_check() {
if $1 --version 2>&1 | grep -qi $2
then printf "OK: %-4s is $2\n" "$1";
else printf "ERROR: %-4s is NOT $2\n" "$1"; fi
}
echo "Aliases:"
alias_check awk GNU
alias_check yacc Bison
alias_check sh Bash
echo "Compiler check:"
if printf "int main(){}" | g++ -x c++ -
then echo "OK: g++ works";
else echo "ERROR: g++ does NOT work"; fi
rm -f a.out
EOF