From: Robert Pengelly <robertapengelly@hotmail.com> Date: Thu, 20 Mar 2025 12:06:31 +0000 (+0000) Subject: Initial commit X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=690b65c63b1da666ea4c3c38a80abce8f1045449;p=rm.git Initial commit --- 690b65c63b1da666ea4c3c38a80abce8f1045449 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +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 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. + +For more information, please refer to <https://unlicense.org> diff --git a/Makefile.pdw b/Makefile.pdw new file mode 100644 index 0000000..359bf8f --- /dev/null +++ b/Makefile.pdw @@ -0,0 +1,23 @@ +#****************************************************************************** +# @file Makefile.pdw +#****************************************************************************** +AS=aswin +CC=gccwin +LD=ldwin + +COPTS=-S -O2 -fno-common -ansi -I. -I./include -I../pdos/pdpclib -I../pdos/src -D__WIN32__ -D__NOBIVA__ -D__PDOS__ +COBJ=lib.o report.o rm.o + +all: clean rm.exe + +rm.exe: $(COBJ) + $(LD) -s -o rm.exe ../pdos/pdpclib/w32start.o $(COBJ) ../pdos/pdpclib/msvcrt.a ../pdos/src/kernel32.a + +.c.o: + $(CC) $(COPTS) -o $*.s $< + $(AS) -o $@ $*.s + rm -f $*.s + +clean: + rm -f $(OBJ) + rm -f rm.exe diff --git a/Makefile.w32 b/Makefile.w32 new file mode 100644 index 0000000..8996a60 --- /dev/null +++ b/Makefile.w32 @@ -0,0 +1,21 @@ +#****************************************************************************** +# @file Makefile.w32 +#****************************************************************************** +SRCDIR ?= $(CURDIR) +VPATH := $(SRCDIR) + +CC := gcc +CFLAGS := -D_FILE_OFFSET_BITS=64 -Wall -Werror -Wextra -std=c90 + +CSRC := lib.c report.c rm.c + +all: rm.exe + +clean: + + if exist rm.exe ( del /q rm.exe ) + if exist rm ( del /q rm ) + +rm.exe: $(CSRC) + + $(CC) $(CFLAGS) -o $@ $^ diff --git a/README.md b/README.md new file mode 100644 index 0000000..61d9f29 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +## Licesne + + All source code is Public Domain. + +## Obtain the source code + + git clone https://git.candlhat.org/rm.git + +## Building + + Windows: + + Make sure you have mingw installed and the location within your PATH variable + then run mingw32-make.exe -f Makefile.w32. diff --git a/lib.c b/lib.c new file mode 100644 index 0000000..284ad74 --- /dev/null +++ b/lib.c @@ -0,0 +1,156 @@ +/****************************************************************************** + * @file lib.c + *****************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "rm.h" +#include "lib.h" +#include "report.h" + +static void print_usage (void) { + + if (program_name) { + fprintf (stderr, "Usage: %s [options] file...\n\n", program_name); + } + +} + +static void dynarray_add (void *ptab, long *nb_ptr, void *data) { + + long nb, nb_alloc; + void **pp; + + nb = *nb_ptr; + pp = *(void ***) ptab; + + if ((nb & (nb - 1)) == 0) { + + if (!nb) { + nb_alloc = 1; + } else { + nb_alloc = nb * 2; + } + + pp = xrealloc (pp, nb_alloc * sizeof (void *)); + *(void ***) ptab = pp; + + } + + pp[nb++] = data; + *nb_ptr = nb; + +} + +char *xstrdup (const char *__p) { + + char *p = xmalloc (strlen (__p) + 1); + + strcpy (p, __p); + return p; + +} + +void parse_args (int argc, char **argv, int optind) { + + const char *r; + + if (argc <= optind) { + + print_usage (); + exit (EXIT_SUCCESS); + + } + + r = argv[optind++]; + +check_options: + + if (r[0] == '-') { + ++r; + } + + while (*r != '\0') { + + char ch = *r++; + + if (ch == 'f') { + + state->fflag++; + continue; + + } + + if (ch == 'i') { + + state->iflag++; + continue; + + } + + if (ch == 'r') { + + state->rflag++; + continue; + + } + + report_at (program_name, 0, REPORT_ERROR, "invalid option -- '%c'", ch); + + print_usage (); + exit (EXIT_FAILURE); + + } + + if ((r = argv[optind])) { + + if (*r == '-') { + goto check_options; + } + + } + + if (optind >= argc) { + + print_usage (); + exit (EXIT_FAILURE); + + } + + while (optind < argc) { + dynarray_add (&state->files, &state->nb_files, xstrdup (argv[optind++])); + } + +} + +void *xmalloc (unsigned long __size) { + + void *ptr = malloc (__size); + + if (!ptr && __size) { + + report_at (program_name, 0, REPORT_ERROR, "memory full (malloc)"); + exit (EXIT_FAILURE); + + } + + memset (ptr, 0, __size); + return ptr; + +} + +void *xrealloc (void *__ptr, unsigned long __size) { + + void *ptr = realloc (__ptr, __size); + + if (!ptr && __size) { + + report_at (program_name, 0, REPORT_ERROR, "memory full (realloc)"); + exit (EXIT_FAILURE); + + } + + return ptr; + +} diff --git a/lib.h b/lib.h new file mode 100644 index 0000000..ec8cb8b --- /dev/null +++ b/lib.h @@ -0,0 +1,13 @@ +/****************************************************************************** + * @file lib.h + *****************************************************************************/ +#ifndef _LIB_H +#define _LIB_H + +char *xstrdup (const char *__p); +void parse_args (int argc, char **argv, int optind); + +void *xmalloc (unsigned long __size); +void *xrealloc (void *__ptr, unsigned long __size); + +#endif /* _LIB_H */ diff --git a/report.c b/report.c new file mode 100644 index 0000000..fb010ce --- /dev/null +++ b/report.c @@ -0,0 +1,149 @@ +/****************************************************************************** + * @file report.c + *****************************************************************************/ +#include <stdarg.h> +#include <stdio.h> +#include <string.h> + +#include "report.h" +unsigned int errors = 0; + +#ifndef __PDOS__ +#if defined (_WIN32) +# include <windows.h> +static int OriginalConsoleColor = -1; +#endif + +static void reset_console_color (void) { + +#if defined (_WIN32) + + HANDLE hStdError = GetStdHandle (STD_ERROR_HANDLE); + + if (OriginalConsoleColor == -1) { return; } + + SetConsoleTextAttribute (hStdError, OriginalConsoleColor); + OriginalConsoleColor = -1; + +#else + + fprintf (stderr, "\033[0m"); + +#endif + +} + +static void set_console_color (int color) { + +#if defined (_WIN32) + + HANDLE hStdError = GetStdHandle (STD_ERROR_HANDLE); + WORD wColor; + + if (OriginalConsoleColor == -1) { + + CONSOLE_SCREEN_BUFFER_INFO csbi; + + if (!GetConsoleScreenBufferInfo (hStdError, &csbi)) { + return; + } + + OriginalConsoleColor = csbi.wAttributes; + + } + + wColor = (OriginalConsoleColor & 0xF0) + (color & 0xF); + SetConsoleTextAttribute (hStdError, wColor); + +#else + + fprintf (stderr, "\033[%dm", color); + +#endif + +} +#endif + +static void output_message (const char *filename, unsigned int lineno, unsigned int idx, int type, const char *fmt, va_list ap) { + + if (filename) { + + if (lineno == 0) { + fprintf (stderr, "%s: ", filename); + } else { + fprintf (stderr, "%s:", filename); + } + + } + + if (lineno > 0) { + + if (idx == 0) { + fprintf (stderr, "%u: ", lineno); + } else { + fprintf (stderr, "%u:", lineno); + } + + } + + if (idx > 0) { + fprintf (stderr, "%u: ", idx); + } + + if (type == REPORT_ERROR || type == REPORT_FATAL_ERROR) { + +#ifndef __PDOS__ + set_console_color (COLOR_ERROR); +#endif + + if (type == REPORT_ERROR) { + fprintf (stderr, "error:"); + } else { + fprintf (stderr, "fatal error:"); + } + + } else if (type == REPORT_INTERNAL_ERROR) { + +#ifndef __PDOS__ + set_console_color (COLOR_INTERNAL_ERROR); +#endif + + fprintf (stderr, "internal error:"); + + } else if (type == REPORT_WARNING) { + +#ifndef __PDOS__ + set_console_color (COLOR_WARNING); +#endif + + fprintf (stderr, "warning:"); + + } + +#ifndef __PDOS__ + reset_console_color (); +#endif + + fprintf (stderr, " "); + vfprintf (stderr, fmt, ap); + fprintf (stderr, "\n"); + + if (type != REPORT_WARNING) { + ++errors; + } + +} + +unsigned int get_error_count (void) { + return errors; +} + +void report_at (const char *filename, unsigned int lineno, int type, const char *fmt, ...) { + + va_list ap; + + va_start (ap, fmt); + output_message (filename, lineno, 0, type, fmt, ap); + va_end (ap); + +} diff --git a/report.h b/report.h new file mode 100644 index 0000000..8e694dd --- /dev/null +++ b/report.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * @file report.h + *****************************************************************************/ +#ifndef _REPORT_H +#define _REPORT_H + +#if defined (_WIN32) +# define COLOR_ERROR 12 +# define COLOR_WARNING 13 +# define COLOR_INTERNAL_ERROR 19 +#else +# define COLOR_ERROR 91 +# define COLOR_INTERNAL_ERROR 94 +# define COLOR_WARNING 95 +#endif + +#define REPORT_WARNING 0 +#define REPORT_ERROR 1 +#define REPORT_FATAL_ERROR 3 +#define REPORT_INTERNAL_ERROR 4 + +unsigned int get_error_count (void); +void report_at (const char *filename, unsigned int lineno, int type, const char *fmt, ...); + +#endif /* _REPORT_H */ diff --git a/rm.c b/rm.c new file mode 100644 index 0000000..70b9b34 --- /dev/null +++ b/rm.c @@ -0,0 +1,166 @@ +/****************************************************************************** + * @file ar.c + *****************************************************************************/ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "rm.h" +#include "lib.h" +#include "report.h" + +struct rm_state *state = 0; +const char *program_name = 0; + +#if defined (_WIN32) +# include <windows.h> + +static BOOL IsDirectory (LPCTSTR szPath) { + + DWORD dwAttrib = GetFileAttributes (szPath); + return (dwAttrib != 0xFFFFFFFFL && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); + +} + +static void rm (const char *path) { + + const char *p = path; + char *p2; + + unsigned long len; + + if (isalpha ((int) p[0]) && p[1] == ':') { + p += 2; + } + + while (*p == '/') { + p++; + } + + p2 = xstrdup (path); + + if (IsDirectory (p2)) { + + char *subpath, *filename; + + HANDLE hFind; + WIN32_FIND_DATA FindFileData; + + if (!state->rflag && !state->fflag) { + + report_at (program_name, 0, REPORT_ERROR, "cannot remove directoies without -r"); + + free (p2); + return; + + } + + len = strlen (p2); + + if (p2[len - 1] == '/') { + + subpath = xmalloc (len + 5); + sprintf (subpath, "%s*.*", p2); + + } else { + + subpath = xmalloc (len + 6); + sprintf (subpath, "%s/*.*", p2); + + } + + if ((hFind = FindFirstFile (subpath, &FindFileData)) == INVALID_HANDLE_VALUE) { + + free (subpath); + return; + + } + + free (subpath); + + do { + + filename = FindFileData.cFileName; + + if (filename[0] == '.' && (filename[1] == '\0' || (filename[1] == '.' && filename[2] == '\0'))) { + continue; + } + + len = strlen (path); + + if (path[len - 1] == '/') { + + len += (strlen (filename) + 1); + + if (!(subpath = malloc (len))) { + + report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for '%s'", filename); + continue; + + } + + sprintf (subpath, "%s%s", path, filename); + + } else { + + len += (1 + strlen (filename) + 1); + + if (!(subpath = malloc (len))) { + + report_at (program_name, 0, REPORT_ERROR, "failed to allocate memory for '%s'", filename); + continue; + + } + + sprintf (subpath, "%s/%s", path, filename); + + } + + rm (subpath); + free (subpath); + + } while (FindNextFile (hFind, &FindFileData) != 0); + + FindClose (hFind); + + } else { + + int ret = remove (p2); + + if (!state->fflag && ret) { + report_at (program_name, 0, REPORT_ERROR, "unable to remove %s", p2); + } + + } + + free (p2); + +} +#endif + +int main (int argc, char **argv) { + + long i; + + if (argc && *argv) { + + char *p; + program_name = *argv; + + if ((p = strrchr (program_name, '/')) || (p = strrchr (program_name, '\\'))) { + program_name = (p + 1); + } + + } + + state = xmalloc (sizeof (*state)); + parse_args (argc, argv, 1); + + for (i = 0; i < state->nb_files; ++i) { + rm (state->files[i]); + } + + return (get_error_count () > 0 ? EXIT_FAILURE : EXIT_SUCCESS); + +} diff --git a/rm.h b/rm.h new file mode 100644 index 0000000..012d559 --- /dev/null +++ b/rm.h @@ -0,0 +1,21 @@ +/****************************************************************************** + * @file rm.h + *****************************************************************************/ +#ifndef _RM_H +#define _RM_H + +struct rm_state { + + const char **files; + long nb_files; + + int fflag; + int iflag; + int rflag; + +}; + +extern struct rm_state *state; +extern const char *program_name; + +#endif /* _RM_H */