.
This commit is contained in:
parent
8c85fe8819
commit
10d663971c
59
.gitignore
vendored
Normal file
59
.gitignore
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Build directories
|
||||||
|
build/
|
||||||
|
cmake-build-*/
|
||||||
|
out/
|
||||||
|
bin/
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
dropshell
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
Makefile
|
||||||
|
*.cmake
|
||||||
|
|
||||||
|
# IDE specific files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs and databases
|
||||||
|
*.log
|
||||||
|
*.sqlite
|
||||||
|
|
||||||
|
# Local configuration
|
||||||
|
*.local
|
||||||
|
*.conf.local
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
deps/
|
||||||
|
vendor/
|
36
CMakeLists.txt
Normal file
36
CMakeLists.txt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(dropshell VERSION 1.0.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Find required packages
|
||||||
|
find_package(Boost REQUIRED COMPONENTS program_options filesystem system)
|
||||||
|
|
||||||
|
# Add executable
|
||||||
|
add_executable(dropshell
|
||||||
|
src/main.cpp
|
||||||
|
src/version.cpp
|
||||||
|
src/status.cpp
|
||||||
|
src/servers.cpp
|
||||||
|
src/help.cpp
|
||||||
|
src/config.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Link libraries
|
||||||
|
target_link_libraries(dropshell PRIVATE
|
||||||
|
Boost::program_options
|
||||||
|
Boost::filesystem
|
||||||
|
Boost::system
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install targets
|
||||||
|
install(TARGETS dropshell
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
)
|
||||||
|
|
||||||
|
# Install completion script
|
||||||
|
install(FILES src/dropshell-completion.bash
|
||||||
|
DESTINATION /etc/bash_completion.d
|
||||||
|
RENAME dropshell
|
||||||
|
)
|
84
README.md
84
README.md
@ -1,3 +1,83 @@
|
|||||||
# dropshell
|
# Dropshell
|
||||||
|
|
||||||
Simple remote server management system, based on bash scripts, and works with anything.
|
A system management tool for server operations, written in C++.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- System status monitoring
|
||||||
|
- Server configuration management
|
||||||
|
- Bash completion support
|
||||||
|
- Command-line interface with help and version information
|
||||||
|
|
||||||
|
## Building from Source
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- CMake (>= 3.10)
|
||||||
|
- Boost C++ Libraries (program_options, filesystem, system)
|
||||||
|
- C++17 compatible compiler
|
||||||
|
- Debian packaging tools (for creating packages)
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone the repository
|
||||||
|
git clone https://github.com/j842/dropshell.git
|
||||||
|
cd dropshell
|
||||||
|
|
||||||
|
# Create build directory
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
# Configure and build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installing
|
||||||
|
|
||||||
|
#### From Source
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install from source build
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
#### From Debian Package
|
||||||
|
|
||||||
|
To create a Debian package:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install build dependencies
|
||||||
|
sudo apt-get install devscripts debhelper cmake libboost-all-dev
|
||||||
|
|
||||||
|
# Build the package
|
||||||
|
dpkg-buildpackage -us -uc
|
||||||
|
|
||||||
|
# Install the package
|
||||||
|
sudo dpkg -i ../dropshell_1.0.0-1_*.deb
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Show help
|
||||||
|
dropshell help
|
||||||
|
|
||||||
|
# Show version
|
||||||
|
dropshell version
|
||||||
|
|
||||||
|
# Check system status
|
||||||
|
dropshell status
|
||||||
|
|
||||||
|
# List configured servers
|
||||||
|
dropshell servers
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The configuration file is located at `/etc/dropshell.conf`. You can modify this file to change default settings.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License - see LICENSE file for details
|
80
build.sh
Executable file
80
build.sh
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Exit on error
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print status messages
|
||||||
|
print_status() {
|
||||||
|
echo -e "${GREEN}[*] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}[!] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e "${YELLOW}[!] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if build directory exists, if not create it
|
||||||
|
if [ ! -d "build" ]; then
|
||||||
|
print_status "Creating build directory..."
|
||||||
|
mkdir build
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enter build directory
|
||||||
|
cd build
|
||||||
|
|
||||||
|
# Check if CMake is installed
|
||||||
|
if ! command -v cmake &> /dev/null; then
|
||||||
|
print_error "CMake is not installed. Please install CMake first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if make is installed
|
||||||
|
if ! command -v make &> /dev/null; then
|
||||||
|
print_error "Make is not installed. Please install Make first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Configure with CMake
|
||||||
|
print_status "Configuring with CMake..."
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
print_status "Building project..."
|
||||||
|
make -j$(nproc)
|
||||||
|
|
||||||
|
# Check if build was successful
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
print_status "Build successful!"
|
||||||
|
print_status "Binary location: $(pwd)/dropshell"
|
||||||
|
else
|
||||||
|
print_error "Build failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if user wants to install
|
||||||
|
read -p "Do you want to install the program? (y/n) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||||
|
print_status "Installing dropshell..."
|
||||||
|
sudo make install
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
print_status "Installation successful!"
|
||||||
|
else
|
||||||
|
print_error "Installation failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Return to original directory
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
print_status "Build process completed!"
|
8
debian/changelog
vendored
Normal file
8
debian/changelog
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
dropshell (1.0.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Initial release.
|
||||||
|
* Converted from bash script to C++ implementation
|
||||||
|
* Added proper system status monitoring
|
||||||
|
* Improved server management functionality
|
||||||
|
|
||||||
|
-- j842 <j842@example.com> Sun, 21 Apr 2025 12:00:00 +0000
|
15
debian/control
vendored
Normal file
15
debian/control
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Source: dropshell
|
||||||
|
Section: utils
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: j842 <j842@example.com>
|
||||||
|
Build-Depends: debhelper (>= 10), cmake, libboost-all-dev
|
||||||
|
Standards-Version: 4.5.0
|
||||||
|
Homepage: https://github.com/j842/dropshell
|
||||||
|
|
||||||
|
Package: dropshell
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}, libboost-program-options1.74.0, libboost-filesystem1.74.0, libboost-system1.74.0
|
||||||
|
Description: A system management tool for server operations
|
||||||
|
dropshell is a command-line tool for managing and monitoring servers.
|
||||||
|
It provides functionality for checking system status, managing server
|
||||||
|
configurations, and performing common administrative tasks.
|
26
debian/copyright
vendored
Normal file
26
debian/copyright
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: dropshell
|
||||||
|
Source: https://github.com/j842/dropshell
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2025 j842
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
.
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
14
debian/rules
vendored
Normal file
14
debian/rules
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
|
|
||||||
|
override_dh_auto_configure:
|
||||||
|
dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
override_dh_auto_install:
|
||||||
|
dh_auto_install
|
||||||
|
# Install bash completion
|
||||||
|
install -D -m 644 src/dropshell-completion.bash debian/dropshell/etc/bash_completion.d/dropshell
|
||||||
|
# Install configuration
|
||||||
|
install -D -m 644 src/dropshell.conf debian/dropshell/etc/dropshell.conf
|
137
install.sh
137
install.sh
@ -1,137 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
|
||||||
source "$SCRIPT_DIR/src/version.sh"
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
RED='\033[0;31m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Function to create directory with proper ownership
|
|
||||||
mkdir_with_ownership() {
|
|
||||||
local target_dir="$1"
|
|
||||||
local parent_dir="$(dirname "$target_dir")"
|
|
||||||
|
|
||||||
# Find the lowest existing parent directory
|
|
||||||
while [ ! -d "$parent_dir" ] && [ "$parent_dir" != "/" ]; do
|
|
||||||
parent_dir="$(dirname "$parent_dir")"
|
|
||||||
done
|
|
||||||
|
|
||||||
# If we found an existing directory, get its ownership
|
|
||||||
if [ -d "$parent_dir" ]; then
|
|
||||||
local owner=$(stat -c %U "$parent_dir")
|
|
||||||
local group=$(stat -c %G "$parent_dir")
|
|
||||||
install -d -o "$owner" -g "$group" "$target_dir"
|
|
||||||
else
|
|
||||||
echo -e "${RED}Error: Could not find any existing parent directory${NC}"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if USER_DEFINITIONS is provided
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo -e "${RED}Error: USER_DEFINITIONS path is required${NC}"
|
|
||||||
echo "Usage: $0 <USER_DEFINITIONS_PATH>"
|
|
||||||
echo "Example: $0 ~/.config/dropshell"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
USER_DEFINITIONS="$1"
|
|
||||||
|
|
||||||
# Script locations
|
|
||||||
SCRIPT_SOURCE="$SCRIPT_DIR/src/dropshell.sh"
|
|
||||||
SCRIPT_DEST="/usr/local/bin/dropshell"
|
|
||||||
COMPLETION_SOURCE="$SCRIPT_DIR/src/dropshell-completion.bash"
|
|
||||||
COMPLETION_DEST="/etc/bash_completion.d/dropshell"
|
|
||||||
EXAMPLE_DIR="$SCRIPT_DIR/.example"
|
|
||||||
DROPSHELL_OPT="/opt/dropshell"
|
|
||||||
|
|
||||||
# Check if running with sudo/root
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
|
||||||
echo -e "${RED}Please run as root or with sudo${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if source script exists
|
|
||||||
if [ ! -f "$SCRIPT_SOURCE" ]; then
|
|
||||||
echo -e "${RED}Error: $SCRIPT_SOURCE not found${NC}"
|
|
||||||
echo "Please ensure the script exists in the src directory"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if completion script exists
|
|
||||||
if [ ! -f "$COMPLETION_SOURCE" ]; then
|
|
||||||
echo -e "${RED}Error: $COMPLETION_SOURCE not found${NC}"
|
|
||||||
echo "Please ensure the completion script exists in the src directory"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create user definitions directory if it doesn't exist
|
|
||||||
if [ ! -d "$USER_DEFINITIONS" ]; then
|
|
||||||
echo "Creating user definitions directory..."
|
|
||||||
mkdir_with_ownership "$USER_DEFINITIONS" || exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if example directory exists and copy example files if needed
|
|
||||||
if [ ! -d "$EXAMPLE_DIR" ]; then
|
|
||||||
echo -e "${RED}Error: Example directory not found at $EXAMPLE_DIR${NC}"
|
|
||||||
echo "Please ensure the .example directory exists in the project root"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check and create servers directory
|
|
||||||
if [ ! -d "$USER_DEFINITIONS/servers" ]; then
|
|
||||||
echo "Copying example files..."
|
|
||||||
mkdir_with_ownership "$USER_DEFINITIONS/servers" || exit 1
|
|
||||||
cp -ra "$EXAMPLE_DIR"/servers/* "$USER_DEFINITIONS/servers"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check and create usertemplates directory
|
|
||||||
if [ ! -d "$USER_DEFINITIONS/usertemplates" ]; then
|
|
||||||
echo "Copying example files..."
|
|
||||||
mkdir_with_ownership "$USER_DEFINITIONS/usertemplates" || exit 1
|
|
||||||
cp -ra "$EXAMPLE_DIR"/usertemplates/* "$USER_DEFINITIONS/usertemplates"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# install user directory.
|
|
||||||
echo "Creating symbolic link for /opt/dropshell/user..."
|
|
||||||
mkdir -p "$DROPSHELL_OPT" || exit 1
|
|
||||||
if [ -e "$DROPSHELL_OPT/user" ]; then
|
|
||||||
rm -rf "$DROPSHELL_OPT/user"
|
|
||||||
fi
|
|
||||||
ln -s "$USER_DEFINITIONS" "$DROPSHELL_OPT/user"
|
|
||||||
|
|
||||||
# Create symbolic link
|
|
||||||
echo "Creating symbolic link for running from $SCRIPT_DEST..."
|
|
||||||
if [ -L "$SCRIPT_DEST" ]; then
|
|
||||||
rm "$SCRIPT_DEST"
|
|
||||||
fi
|
|
||||||
ln -s "$SCRIPT_SOURCE" "$SCRIPT_DEST"
|
|
||||||
|
|
||||||
# Make sure the scripts are executable
|
|
||||||
chmod +x "$SCRIPT_SOURCE"
|
|
||||||
chmod +x "$COMPLETION_SOURCE"
|
|
||||||
|
|
||||||
# Install bash completion
|
|
||||||
echo "Installing bash completion..."
|
|
||||||
if [ ! -d "/etc/bash_completion.d" ]; then
|
|
||||||
mkdir_with_ownership "/etc/bash_completion.d" || exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install completion script
|
|
||||||
cp "$COMPLETION_SOURCE" "$COMPLETION_DEST"
|
|
||||||
chmod 644 "$COMPLETION_DEST"
|
|
||||||
|
|
||||||
# Create environment file
|
|
||||||
cat > "/etc/dropshell.conf" << EOF
|
|
||||||
# Dropshell configuration
|
|
||||||
USER_DEFINITIONS="$USER_DEFINITIONS"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Source the completion script
|
|
||||||
echo "source $COMPLETION_DEST" >> ~/.bashrc
|
|
||||||
|
|
||||||
echo -e "${GREEN}Installation completed successfully!${NC}"
|
|
||||||
|
|
||||||
exit 0
|
|
92
install_prerequisites.sh
Executable file
92
install_prerequisites.sh
Executable file
@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print status messages
|
||||||
|
print_status() {
|
||||||
|
echo -e "${GREEN}[*] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_error() {
|
||||||
|
echo -e "${RED}[!] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_warning() {
|
||||||
|
echo -e "${YELLOW}[!] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
print_error "Please run this script as root (use sudo)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect distribution
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
OS=$NAME
|
||||||
|
VER=$VERSION_ID
|
||||||
|
else
|
||||||
|
print_error "Could not detect distribution"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_status "Detected OS: $OS $VER"
|
||||||
|
|
||||||
|
# Define packages based on distribution
|
||||||
|
case $OS in
|
||||||
|
"Ubuntu"|"Debian GNU/Linux")
|
||||||
|
# Common packages for both Ubuntu and Debian
|
||||||
|
PACKAGES="cmake make g++ libboost-all-dev devscripts debhelper"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_error "Unsupported distribution: $OS"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Function to check if a package is installed
|
||||||
|
is_package_installed() {
|
||||||
|
dpkg -l "$1" 2>/dev/null | grep -q "^ii"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install missing packages
|
||||||
|
print_status "Checking and installing required packages..."
|
||||||
|
for pkg in $PACKAGES; do
|
||||||
|
if ! is_package_installed "$pkg"; then
|
||||||
|
print_status "Installing $pkg..."
|
||||||
|
apt-get install -y "$pkg"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
print_error "Failed to install $pkg"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_status "$pkg is already installed"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Update package lists
|
||||||
|
print_status "Updating package lists..."
|
||||||
|
apt-get update
|
||||||
|
|
||||||
|
# Verify all required tools are installed
|
||||||
|
print_status "Verifying installation..."
|
||||||
|
for tool in cmake make g++; do
|
||||||
|
if ! command -v "$tool" &> /dev/null; then
|
||||||
|
print_error "$tool is not installed properly"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check Boost installation
|
||||||
|
if [ ! -d "/usr/include/boost" ]; then
|
||||||
|
print_error "Boost headers not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_status "All dependencies installed successfully!"
|
||||||
|
print_status "You can now run ./build.sh to build the project"
|
124
src/config.cpp
Normal file
124
src/config.cpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include "dropshell.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
namespace pt = boost::property_tree;
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
// Default user directory
|
||||||
|
static std::string user_directory;
|
||||||
|
static bool config_loaded = false;
|
||||||
|
|
||||||
|
bool is_config_loaded() {
|
||||||
|
return config_loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_config_path(std::string& path) {
|
||||||
|
// Try ~/.config/dropshell/dropshell.conf
|
||||||
|
const char* home = std::getenv("HOME");
|
||||||
|
if (home) {
|
||||||
|
fs::path user_path = fs::path(home) / ".config" / "dropshell" / "dropshell.conf";
|
||||||
|
if (!fs::exists(user_path)) {
|
||||||
|
// create path
|
||||||
|
fs::create_directories(user_path.parent_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
path = user_path.string();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::cerr << "Warning: Couldn't determine user directory" << std::endl;
|
||||||
|
path = "";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_user_directory(std::string& path) {
|
||||||
|
path = user_directory;
|
||||||
|
return !path.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_config() {
|
||||||
|
std::string config_path;
|
||||||
|
if (!get_config_path(config_path))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (config_path.empty()) {
|
||||||
|
// No config file found, but this is not an error
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
pt::ptree tree;
|
||||||
|
pt::read_ini(config_path, tree);
|
||||||
|
bool config_okay = true;
|
||||||
|
|
||||||
|
// Try to read user directory from config
|
||||||
|
try {
|
||||||
|
user_directory = tree.get<std::string>("user.directory");
|
||||||
|
} catch (const pt::ptree_error&) {
|
||||||
|
std::cerr << "Warning: User directory not set in config" << std::endl;
|
||||||
|
config_okay = false; // Not a critical error
|
||||||
|
}
|
||||||
|
|
||||||
|
// config loaded okay.
|
||||||
|
config_loaded = config_okay;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Warning: Error reading config file: " << e.what() << std::endl;
|
||||||
|
return true; // Not a critical error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_user_directory(const std::string& path) {
|
||||||
|
// Convert to absolute path
|
||||||
|
fs::path abs_path = fs::absolute(path);
|
||||||
|
|
||||||
|
// Create directory if it doesn't exist
|
||||||
|
if (!fs::exists(abs_path)) {
|
||||||
|
throw std::runtime_error("The user directory does not exist: " + abs_path.string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update config file
|
||||||
|
std::string config_path;
|
||||||
|
if (!get_config_path(config_path)) {
|
||||||
|
// No config file exists, create one in user's home directory
|
||||||
|
const char* home = std::getenv("HOME");
|
||||||
|
if (!home) {
|
||||||
|
throw std::runtime_error("HOME environment variable not set");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path config_dir = fs::path(home) / ".config" / "dropshell";
|
||||||
|
if (!fs::exists(config_dir)) {
|
||||||
|
fs::create_directories(config_dir);
|
||||||
|
}
|
||||||
|
config_path = (config_dir / "dropshell.conf").string();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
pt::ptree tree;
|
||||||
|
// Read existing config if it exists
|
||||||
|
if (fs::exists(config_path)) {
|
||||||
|
pt::read_ini(config_path, tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update user directory
|
||||||
|
tree.put("user.directory", abs_path.string());
|
||||||
|
|
||||||
|
// Write back to config file
|
||||||
|
pt::write_ini(config_path, tree);
|
||||||
|
|
||||||
|
// Update in-memory value
|
||||||
|
user_directory = abs_path.string();
|
||||||
|
|
||||||
|
std::cout << "User directory initialized to: " << abs_path.string() << std::endl;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
throw std::runtime_error("Failed to update config: " + std::string(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
@ -33,7 +33,6 @@ _dropshell_completions() {
|
|||||||
servers+=("$server_name")
|
servers+=("$server_name")
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
COMPREPLY=( $(compgen -W "${servers[@]}" -- ${cur}) )
|
COMPREPLY=( $(compgen -W "${servers[@]}" -- ${cur}) )
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
35
src/dropshell.hpp
Normal file
35
src/dropshell.hpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
// Version information
|
||||||
|
const std::string VERSION = "1.0.0";
|
||||||
|
const std::string RELEASE_DATE = "2025-04-21";
|
||||||
|
const std::string AUTHOR = "j842";
|
||||||
|
const std::string LICENSE = "MIT";
|
||||||
|
|
||||||
|
// Server information structure
|
||||||
|
struct ServerInfo {
|
||||||
|
std::string name;
|
||||||
|
std::string address;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Command handlers
|
||||||
|
void print_help(const boost::program_options::options_description& desc);
|
||||||
|
void print_version();
|
||||||
|
void check_status();
|
||||||
|
void list_servers();
|
||||||
|
void init_user_directory(const std::string& path);
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
std::vector<ServerInfo> get_configured_servers();
|
||||||
|
bool get_config_path(std::string& path);
|
||||||
|
bool load_config();
|
||||||
|
bool is_config_loaded();
|
||||||
|
bool get_user_directory(std::string& path);
|
||||||
|
|
||||||
|
} // namespace dropshell
|
125
src/dropshell.sh
125
src/dropshell.sh
@ -1,125 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Script name: dropshell.sh
|
|
||||||
# Description: A basic shell script for common operations
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Source version information
|
|
||||||
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
|
|
||||||
source "$SCRIPT_DIR/version.sh"
|
|
||||||
|
|
||||||
# Source configuration
|
|
||||||
if [ -f "/etc/dropshell.conf" ]; then
|
|
||||||
source "/etc/dropshell.conf"
|
|
||||||
else
|
|
||||||
echo -e "${RED}Error: Configuration file not found${NC}"
|
|
||||||
echo "Please run the installation script first"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if USER_DEFINITIONS is set
|
|
||||||
if [ -z "$USER_DEFINITIONS" ]; then
|
|
||||||
echo -e "${RED}Error: USER_DEFINITIONS not set${NC}"
|
|
||||||
echo "Please run the installation script first"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Function to print usage
|
|
||||||
print_usage() {
|
|
||||||
echo "Usage: $0 <command> [options]"
|
|
||||||
echo
|
|
||||||
echo "Commands:"
|
|
||||||
echo " help - Show this help message"
|
|
||||||
echo " version - Show version information"
|
|
||||||
echo " status - Check system status"
|
|
||||||
echo " servers - List configured servers"
|
|
||||||
echo
|
|
||||||
echo "Options:"
|
|
||||||
echo " -v, --verbose Enable verbose output"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to print version
|
|
||||||
print_version() {
|
|
||||||
get_version_info
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to check status
|
|
||||||
check_status() {
|
|
||||||
echo -e "${GREEN}System Status:${NC}"
|
|
||||||
echo "Date: $(date)"
|
|
||||||
echo "Uptime: $(uptime)"
|
|
||||||
echo "Memory Usage:"
|
|
||||||
free -h
|
|
||||||
echo
|
|
||||||
echo "Disk Usage:"
|
|
||||||
df -h /
|
|
||||||
}
|
|
||||||
|
|
||||||
# Function to list servers from _server.env files
|
|
||||||
list_servers() {
|
|
||||||
local servers_dir="/opt/dropshell/user/servers"
|
|
||||||
local max_name_len=0
|
|
||||||
local max_addr_len=0
|
|
||||||
local servers=()
|
|
||||||
|
|
||||||
# First pass: collect data and find max lengths
|
|
||||||
for server_dir in "$servers_dir"/*/; do
|
|
||||||
if [ -f "${server_dir}_server.env" ]; then
|
|
||||||
local server_name=$(basename "$server_dir")
|
|
||||||
local ssh_address=$(grep '^SSH_ADDRESS=' "${server_dir}_server.env" | cut -d'=' -f2-)
|
|
||||||
|
|
||||||
# Update max lengths
|
|
||||||
[ ${#server_name} -gt $max_name_len ] && max_name_len=${#server_name}
|
|
||||||
[ ${#ssh_address} -gt $max_addr_len ] && max_addr_len=${#ssh_address}
|
|
||||||
|
|
||||||
servers+=("$server_name|$ssh_address")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Add padding for headers
|
|
||||||
max_name_len=$((max_name_len > 4 ? max_name_len : 4))
|
|
||||||
max_addr_len=$((max_addr_len > 7 ? max_addr_len : 7))
|
|
||||||
|
|
||||||
# Print header
|
|
||||||
printf "%-${max_name_len}s | %-${max_addr_len}s\n" "Name" "Address"
|
|
||||||
printf "%-${max_name_len}s-+-%-${max_addr_len}s\n" "$(printf '%*s' $max_name_len '' | tr ' ' '-')" "$(printf '%*s' $max_addr_len '' | tr ' ' '-')"
|
|
||||||
|
|
||||||
# Print server rows
|
|
||||||
for server in "${servers[@]}"; do
|
|
||||||
IFS='|' read -r name addr <<< "$server"
|
|
||||||
printf "%-${max_name_len}s | %-${max_addr_len}s\n" "$name" "$addr"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Main script logic
|
|
||||||
case "$1" in
|
|
||||||
"help"|"-h"|"--help")
|
|
||||||
print_usage
|
|
||||||
;;
|
|
||||||
"version"|"-V"|"--version")
|
|
||||||
print_version
|
|
||||||
;;
|
|
||||||
"status")
|
|
||||||
check_status
|
|
||||||
;;
|
|
||||||
"servers")
|
|
||||||
list_servers
|
|
||||||
;;
|
|
||||||
"")
|
|
||||||
echo -e "${RED}Error: No command provided${NC}"
|
|
||||||
print_usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo -e "${RED}Error: Unknown command '$1'${NC}"
|
|
||||||
print_usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
exit 0
|
|
24
src/help.cpp
Normal file
24
src/help.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "dropshell.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
void print_help(const boost::program_options::options_description& desc) {
|
||||||
|
std::cout << "Usage: dropshell [OPTIONS] COMMAND [ARGS]" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "A tool for managing server configurations" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "Commands:" << std::endl;
|
||||||
|
std::cout << " help Show this help message" << std::endl;
|
||||||
|
std::cout << " version Show version information" << std::endl;
|
||||||
|
std::cout << " init DIR Initialize the user directory for server configurations" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << " status Check system status" << std::endl;
|
||||||
|
std::cout << " servers List configured servers" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "Examples:" << std::endl;
|
||||||
|
std::cout << " dropshell servers" << std::endl;
|
||||||
|
std::cout << " dropshell init /path/to/directory" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
84
src/main.cpp
Normal file
84
src/main.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include "dropshell.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
|
namespace po = boost::program_options;
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
try {
|
||||||
|
// Define command line options
|
||||||
|
po::options_description desc("Usage: dropshell <command> [options]");
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", "Show help message")
|
||||||
|
("version,V", "Show version information")
|
||||||
|
("command", po::value<std::string>(), "Command to execute")
|
||||||
|
("directory", po::value<std::string>(), "Directory path for init command")
|
||||||
|
("verbose,v", "Enable verbose output");
|
||||||
|
|
||||||
|
po::positional_options_description p;
|
||||||
|
p.add("command", 1);
|
||||||
|
p.add("directory", 1); // Add directory as a positional argument
|
||||||
|
|
||||||
|
po::variables_map vm;
|
||||||
|
po::store(po::command_line_parser(argc, argv)
|
||||||
|
.options(desc)
|
||||||
|
.positional(p)
|
||||||
|
.run(), vm);
|
||||||
|
po::notify(vm);
|
||||||
|
|
||||||
|
// Load configuration
|
||||||
|
if (!dropshell::load_config()) {
|
||||||
|
std::cerr << "Error: Failed to load configuration" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle commands
|
||||||
|
if (vm.count("help") || (vm.count("command") && vm["command"].as<std::string>() == "help")) {
|
||||||
|
dropshell::print_help(desc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("version") || (vm.count("command") && vm["command"].as<std::string>() == "version")) {
|
||||||
|
dropshell::print_version();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vm.count("command")) {
|
||||||
|
std::string cmd = vm["command"].as<std::string>();
|
||||||
|
if (cmd == "status") {
|
||||||
|
dropshell::check_status();
|
||||||
|
return 0;
|
||||||
|
} else if (cmd == "servers") {
|
||||||
|
dropshell::list_servers();
|
||||||
|
return 0;
|
||||||
|
} else if (cmd == "init") {
|
||||||
|
if (!vm.count("directory")) {
|
||||||
|
std::cerr << "Error: init command requires a directory argument" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
dropshell::init_user_directory(vm["directory"].as<std::string>());
|
||||||
|
return 0;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Error: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "Error: Unknown command '" << cmd << "'" << std::endl;
|
||||||
|
dropshell::print_help(desc);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No command provided
|
||||||
|
std::cerr << "Error: No command provided" << std::endl;
|
||||||
|
dropshell::print_help(desc);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Error: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
89
src/servers.cpp
Normal file
89
src/servers.cpp
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include "dropshell.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
|
namespace fs = boost::filesystem;
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
std::vector<ServerInfo> get_configured_servers() {
|
||||||
|
std::vector<ServerInfo> servers;
|
||||||
|
std::string user_dir;
|
||||||
|
|
||||||
|
if (!is_config_loaded()) {
|
||||||
|
std::cerr << "Error: Config not loaded" << std::endl;
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
if (!get_user_directory(user_dir)) {
|
||||||
|
std::cerr << "Error: User directory not set" << std::endl;
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
fs::path servers_dir = fs::path(user_dir) / "servers";
|
||||||
|
if (!fs::exists(servers_dir)) {
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& entry : fs::directory_iterator(servers_dir)) {
|
||||||
|
if (fs::is_directory(entry)) {
|
||||||
|
fs::path env_file = entry.path() / "_server.env";
|
||||||
|
if (fs::exists(env_file)) {
|
||||||
|
std::ifstream file(env_file.string());
|
||||||
|
std::string line;
|
||||||
|
std::string address;
|
||||||
|
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
if (boost::starts_with(line, "SSH_ADDRESS=")) {
|
||||||
|
address = line.substr(12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!address.empty()) {
|
||||||
|
servers.push_back({
|
||||||
|
entry.path().filename().string(),
|
||||||
|
address
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void list_servers() {
|
||||||
|
auto servers = get_configured_servers();
|
||||||
|
|
||||||
|
if (servers.empty()) {
|
||||||
|
std::cout << "No servers configured." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find maximum lengths for formatting
|
||||||
|
size_t max_name_len = 4; // "Name" is 4 chars
|
||||||
|
size_t max_addr_len = 7; // "Address" is 7 chars
|
||||||
|
|
||||||
|
for (const auto& server : servers) {
|
||||||
|
max_name_len = std::max(max_name_len, server.name.length());
|
||||||
|
max_addr_len = std::max(max_addr_len, server.address.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print header
|
||||||
|
std::cout << std::left << std::setw(max_name_len) << "Name" << " | "
|
||||||
|
<< std::setw(max_addr_len) << "Address" << std::endl;
|
||||||
|
|
||||||
|
// Print separator
|
||||||
|
std::cout << std::string(max_name_len, '-') << "-+-"
|
||||||
|
<< std::string(max_addr_len, '-') << std::endl;
|
||||||
|
|
||||||
|
// Print server rows
|
||||||
|
for (const auto& server : servers) {
|
||||||
|
std::cout << std::left << std::setw(max_name_len) << server.name << " | "
|
||||||
|
<< std::setw(max_addr_len) << server.address << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
58
src/status.cpp
Normal file
58
src/status.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "dropshell.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <chrono>
|
||||||
|
#include <ctime>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <sys/sysinfo.h>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
void check_status() {
|
||||||
|
// Get current time
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto time = std::chrono::system_clock::to_time_t(now);
|
||||||
|
std::cout << "System Status:" << std::endl;
|
||||||
|
std::cout << "Date: " << std::ctime(&time);
|
||||||
|
|
||||||
|
// Get uptime
|
||||||
|
struct sysinfo si;
|
||||||
|
if (sysinfo(&si) == 0) {
|
||||||
|
int days = si.uptime / 86400;
|
||||||
|
int hours = (si.uptime % 86400) / 3600;
|
||||||
|
int minutes = (si.uptime % 3600) / 60;
|
||||||
|
std::cout << "Uptime: " << days << " days, " << hours << " hours, " << minutes << " minutes" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get memory usage
|
||||||
|
std::ifstream meminfo("/proc/meminfo");
|
||||||
|
if (meminfo.is_open()) {
|
||||||
|
std::string line;
|
||||||
|
long total_mem = 0, free_mem = 0;
|
||||||
|
while (std::getline(meminfo, line)) {
|
||||||
|
if (line.find("MemTotal:") == 0) {
|
||||||
|
total_mem = std::stol(line.substr(9));
|
||||||
|
} else if (line.find("MemAvailable:") == 0) {
|
||||||
|
free_mem = std::stol(line.substr(13));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "Memory Usage:" << std::endl;
|
||||||
|
std::cout << "Total: " << total_mem / 1024 << " MB" << std::endl;
|
||||||
|
std::cout << "Available: " << free_mem / 1024 << " MB" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get disk usage
|
||||||
|
struct statvfs vfs;
|
||||||
|
if (statvfs("/", &vfs) == 0) {
|
||||||
|
uint64_t total = vfs.f_blocks * vfs.f_frsize;
|
||||||
|
uint64_t free = vfs.f_bfree * vfs.f_frsize;
|
||||||
|
uint64_t used = total - free;
|
||||||
|
|
||||||
|
std::cout << "Disk Usage:" << std::endl;
|
||||||
|
std::cout << "Total: " << total / (1024*1024*1024) << " GB" << std::endl;
|
||||||
|
std::cout << "Used: " << used / (1024*1024*1024) << " GB" << std::endl;
|
||||||
|
std::cout << "Free: " << free / (1024*1024*1024) << " GB" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
13
src/version.cpp
Normal file
13
src/version.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "dropshell.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace dropshell {
|
||||||
|
|
||||||
|
void print_version() {
|
||||||
|
std::cout << "dropshell version " << VERSION << std::endl;
|
||||||
|
std::cout << "Release date: " << RELEASE_DATE << std::endl;
|
||||||
|
std::cout << "Author: " << AUTHOR << std::endl;
|
||||||
|
std::cout << "License: " << LICENSE << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace dropshell
|
@ -1,15 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Version information
|
|
||||||
DROPSHELL_VERSION="1.0.0"
|
|
||||||
DROPSHELL_RELEASE_DATE="2025-04-21"
|
|
||||||
DROPSHELL_AUTHOR="j842"
|
|
||||||
DROPSHELL_LICENSE="MIT"
|
|
||||||
|
|
||||||
# Function to get full version information
|
|
||||||
get_version_info() {
|
|
||||||
echo "dropshell version $DROPSHELL_VERSION"
|
|
||||||
echo "Release date: $DROPSHELL_RELEASE_DATE"
|
|
||||||
echo "Author: $DROPSHELL_AUTHOR"
|
|
||||||
echo "License: $DROPSHELL_LICENSE"
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user