1
0
forked from bonsai/harakit

intcmp(1): new tool; npc(1): new tool; scrut(1): new tool; str(1): new tool; strcmp(1): new tool; tests: added POSIX compatibility test and C compiler compatibility test; Makefile: converted to GNUmakefile; README: added README; docs: added docs

This commit is contained in:
2023-12-24 17:13:17 -07:00
parent b1f6caaf41
commit ef1416cd42
25 changed files with 997 additions and 487 deletions

104
src/cat.c
View File

@@ -1,104 +0,0 @@
/*
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This file is part of YAC coreutils.
*
* YAC coreutils is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* YAC coreutils is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <errno.h>
#include <sysexits.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>
#include "yac.h"
void cat(FILE *file, bool u) {
int byte = 0; /* variable for storing bytes as they are read */
int p = 0; /* index counter for bytes in buffered reading */
char buf[4096]; /* buffer for buffered reading */
if (u) {
while ((byte = fgetc(file)) != EOF) { putchar(byte); }
} else {
while ((byte = fgetc(file)) != EOF) {
if (p > sizeof(buf) - 1) {
fputs(buf, stdout);
p = 0;
} else {
buf[p] = byte;
p++;
}
}
fwrite(buf, 1, p, stdout);
fflush(stdout);
}
}
int main(int argc, char *argv[]) {
bool u = false;
int opt;
int i;
extern int optind;
while ((opt = getopt(argc, argv, "u")) != -1) {
switch (opt) {
/*
* From cat(1p):
*
* -u Write bytes from the input file to the standard output
* without delay as each is read.
*/
case 'u':
u = true;
break;
default:
fprintf(stderr, "Usage: %s (-u) file...\n", argv[0]);
return EX_USAGE;
}
}
/*
* From cat(1p):
*
* file A pathname of an input file. If no file operands are
* specified, the standard input shall be used. If a file is
* '-', the cat utility shall read from the standard input at
* that point in the sequence. The cat utility shall not close
* and reopen standard input when it is referenced in this way,
* but shall accept multiple occurrences of '-' as a file
* operand.
*/
if (optind == argc) {
cat(stdin, u);
return 0;
}
FILE *file;
for (i = optind; i < argc; i++) {
file = rpath(argv[0], argv[i]);
if (file != NULL) {
cat(file, u);
if (file != stdin) { fclose(file); }
} else { continue; }
}
return EX_OK;
}

View File

@@ -1,21 +1,9 @@
/*
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: CC0
*
* This file is part of YAC coreutils.
*
* YAC coreutils is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* YAC coreutils is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
* This work is marked with CC0 1.0. To view a copy of this license, visit
* <http://creativecommons.org/publicdomain/zero/1.0>.
*/
int main() { return 1; }

84
src/intcmp.c Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2023 DTB <trinity@trinity.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <errno.h> /* errno */
#include <stdio.h> /* fprintf(3), stderr */
#include <stdlib.h> /* strtol(3), size_t */
#ifndef EX_USAGE
# include <sysexits.h> /* EX_USAGE */
#endif
#include <unistd.h> /* getopt(3), optind */
/* 0b00? */ /* Equal | -e | 0b001 | 1 */
#define EQUAL 0x01 /* Greater | -g | 0b010 | 2 */
/* 0b0?0 */ /* Greater or Equal | -ge | 0b011 | 3 */
#define GREATER 0x02 /* Less | -l | 0b100 | 4 */
/* 0b?00 */ /* Less or Equal | -le | 0b101 | 5 */
#define LESS 0x04 /* Inequal (Greater or Less) | -gl | 0b110 | 6 */
static char *program_name = "intcmp";
int main(int argc, char *argv[]){
int c;
size_t i;
unsigned char mode;
int r; /* reference integer */
mode = 0;
if(argc < 3)
goto usage;
while((c = getopt(argc, argv, "egl")) != -1)
switch(c){
case 'e': mode |= EQUAL; break;
case 'g': mode |= GREATER; break;
case 'l': mode |= LESS; break;
default: goto usage;
}
if(optind + 2 /* ref cmp */ > argc){
usage: fprintf(stderr,
"Usage: %s (-eghl) [integer] [integer...]\n",
argv[0] == NULL ? program_name : argv[0]);
return EX_USAGE;
}
i = optind;
do{ r = c;
c = strtol(argv[i], &argv[i], 10);
if(*argv[i] != '\0' || errno != 0){
fprintf(stderr, "%s: argument #%d: Invalid integer\n",
argv[0], (int)i);
return EX_USAGE;
}
if(i == optind)
continue;
/* rule enforcement; if a mode isn't permitted and the numbers
* correspond to it, return 1 */
if( (!(mode & EQUAL) && r == c)
|| (!(mode & GREATER) && r > c)
|| (!(mode & LESS) && r < c))
return 1;
}while(++i < argc);
return 0;
}

63
src/libfileis.c Normal file
View File

@@ -0,0 +1,63 @@
/*
* Copyright (c) 2023 DTB <trinity@trinity.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include "libfileis.h"
#include <unistd.h> /* access(3), F_OK, R_OK, W_OK, X_OK */
int f_executable(char *path){ return access(path, X_OK) == 0; } /* test -x */
int f_exists(char *path){ return access(path, F_OK) == 0; } /* test -e */
int f_readable(char *path){ return access(path, R_OK) == 0; } /* test -r */
int f_writeable(char *path){ return access(path, W_OK) == 0; } /* test -w */
#include <sys/stat.h> /* lstat(3), struct stat, S_ISBLK, S_ISCHR, S_ISDIR,
* S_ISFIFO, S_ISGID, S_ISREG, S_ISLNK, S_ISSOCK,
* S_ISUID, S_ISVTX */
static struct stat buf;
int f_blockspecial(char *path){ /* test -b */
return lstat(path, &buf) != -1 && S_ISBLK(buf.st_mode);
}
int f_charspecial(char *path){ /* test -c */
return lstat(path, &buf) != -1 && S_ISCHR(buf.st_mode);
}
int f_directory(char *path){ /* test -d */
return lstat(path, &buf) != -1 && S_ISDIR(buf.st_mode);
}
int f_fifospecial(char *path){ /* test -p */
return lstat(path, &buf) != -1 && S_ISFIFO(buf.st_mode);
}
int f_gid(char *path){ /* test -g */
return lstat(path, &buf) != -1 && (buf.st_mode & S_ISGID);
}
int f_regular(char *path){ /* test -f */
return lstat(path, &buf) != -1 && S_ISREG(buf.st_mode);
}
int f_socket(char *path){ /* test -S */
return lstat(path, &buf) != -1 && S_ISSOCK(buf.st_mode);
}
int f_sticky(char *path){ /* test -k */
return lstat(path, &buf) != -1 && (buf.st_mode & S_ISVTX);
}
int f_symlink(char *path){ /* test -h; test -L */
return lstat(path, &buf) != -1 && S_ISLNK(buf.st_mode);
}
int f_uid(char *path){ /* test -u */
return lstat(path, &buf) != -1 && (buf.st_mode & S_ISUID);
}

62
src/libfileis.h Normal file
View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2023 DTB <trinity@trinity.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
/* libfileis functions return true if the condition is true and false if the
* condition is false. Returned values are 0 or 1 only. */
/* True if file exists and is a block special file. */
int f_blockspecial(char *path);
/* True if file exists and is a character special file. */
int f_charspecial(char *path);
/* True if file exists and is a directory. */
int f_directory(char *path);
/* True if file exists and is executable. */
int f_executable(char *path);
/* True if file exists (regardless of type). */
int f_exists(char *path);
/* True if file exists and is a named pipe (FIFO). */
int f_fifospecial(char *path);
/* True if file exists and its set group ID flag is set. */
int f_gid(char *path);
/* True if file exists and is readable. */
int f_readable(char *path);
/* True if file exists and is a regular file. */
int f_regular(char *path);
/* True if file exists and is a socket. */
int f_socket(char *path);
/* True if file exists and its sticky bit is set. */
int f_sticky(char *path);
/* True if file exists and is a symbolic link. */
int f_symlink(char *path);
/* True if file exists and its set user ID flag is set. */
int f_uid(char *path);
/* True if file exists and is writeable. */
int f_writeable(char *path);

64
src/npc.c Normal file
View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2023 DTB <trinity@trinity.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <stdio.h> /* fprintf(3), fputs(3), getc(3), putc(3), stdin, stdout,
* EOF */
#include <unistd.h> /* getopt(3) */
#if !defined EX_USAGE || !defined EX_OK
# include <sysexits.h>
#endif
int main(int argc, char *argv[]){
int c;
char showend;
char showtab;
showend = 0;
showtab = 0;
if(argc > 0)
while((c = getopt(argc, argv, "et")) != -1)
switch(c){
case 'e': showend = 1; break;
case 't': showtab = 1; break;
default: goto usage;
}
if(argc > optind){
usage: fprintf(stderr, "Usage: %s (-eht)\n", argv[0]);
return EX_USAGE;
}
while((c = getc(stdin)) != EOF){
if((c & 0x80) != 0)
fputs("M-", stdout);
switch(c ^ 0x80 /* 0b 1000 0000 */){
case 0x7f: fputs("^?", stdout);
break;
case '\n': if(showend)
putc('$', stdout);
default:
if(c >= ' ' || c == '\n' || (!showtab && c == '\t'))
putc(c, stdout);
else
fprintf(stdout, "^%c", c + '@');
}
}
return EX_OK;
}

98
src/scrut.c Normal file
View File

@@ -0,0 +1,98 @@
/*
* Copyright (c) 2023 DTB <trinity@trinity.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <stdio.h> /* fprintf(3), stderr, NULL */
#include <string.h> /* strchr(3) */
#ifndef EX_USAGE
# include <sysexits.h>
#endif
#include <unistd.h> /* access(3), getopt(3), F_OK, R_OK, W_OK, X_OK */
#include <sys/stat.h> /* lstat(3), stat struct, S_ISBLK, S_ISCHR, S_ISDIR,
* S_ISFIFO, S_ISGID, S_ISREG, S_ISLNK, S_ISSOCK,
* S_ISUID, S_ISVTX */
static char args[] = "bcdefghkprsuwxLS";
static char ops[(sizeof args) / (sizeof *args)];
static char *program_name = "scrut";
int main(int argc, char *argv[]){
struct stat buf;
int c;
size_t i;
if(argc < 2)
goto usage;
i = 0;
while((c = getopt(argc, argv, args)) != -1)
if(strchr(args, c) == NULL)
goto usage;
else
ops[i++] = c;
ops[i] = '\0';
if(optind == argc)
goto usage;
argv += optind;
do{ if(access(*argv, F_OK) != 0 || lstat(*argv, &buf) == -1)
return 1; /* doesn't exist or isn't stattable */
for(i = 0; ops[i] != '\0'; ++i)
if(ops[i] == 'e')
continue;
else if(ops[i] == 'h'){
usage: fprintf(stderr, "Usage: %s (-%s) [file...]\n",
argv[0] == NULL
? program_name
: argv[0],
args);
return EX_USAGE;
}else if(
(ops[i] == 'b'
&& !S_ISBLK(buf.st_mode))
|| (ops[i] == 'c'
&& !S_ISCHR(buf.st_mode))
|| (ops[i] == 'd'
&& !S_ISDIR(buf.st_mode))
|| (ops[i] == 'f'
&& !S_ISREG(buf.st_mode))
|| (ops[i] == 'g'
&& !(buf.st_mode & S_ISGID))
|| (ops[i] == 'k'
&& !(buf.st_mode & S_ISVTX))
|| (ops[i] == 'p'
&& !S_ISFIFO(buf.st_mode))
|| (ops[i] == 'r'
&& access(*argv, R_OK) != 0)
|| (ops[i] == 'u'
&& !(buf.st_mode & S_ISUID))
|| (ops[i] == 'w'
&& access(*argv, W_OK) != 0)
|| (ops[i] == 'x'
&& access(*argv, X_OK) != 0)
|| (ops[i] == 'L'
&& !S_ISLNK(buf.st_mode))
|| (ops[i] == 'S'
&& !S_ISSOCK(buf.st_mode)))
return 1;
}while(*++argv != NULL);
return 0;
}

75
src/str.c Normal file
View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2023 DTB <trinity@trinity.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <ctype.h>
#include <stddef.h> /* NULL */
#include <stdio.h> /* fprintf(3) */
#include <string.h> /* strcmp(3) */
#if !defined EX_USAGE
# include <sysexits.h>
#endif
static char *program_name = "str";
static struct {
char *name;
int (*f)(int);
}ctypes[] = {
{ "isalnum", isalnum },
{ "isalpha", isalpha },
{ "isblank", isblank },
{ "iscntrl", iscntrl },
{ "isdigit", isdigit },
{ "isxdigit", isxdigit },
{ "isgraph", isgraph },
{ "islower", islower },
{ "isprint", isprint },
{ "ispunct", ispunct },
{ "isspace", isspace },
{ "isupper", isupper }
};
int main(int argc, char *argv[]){
int ctype;
int i;
int r;
if(argc >= 3){
for(ctype = 0; ctype < (sizeof ctypes) / (sizeof *ctypes);
++ctype)
if(strcmp(argv[1], ctypes[ctype].name) == 0)
goto pass;
}
fprintf(stderr, "Usage: %s [type] [string...]\n",
argv[0] == NULL ? program_name : argv[0]);
return EX_USAGE;
pass: for(argv += 2, r = 1; *argv != NULL; ++argv)
for(i = 0; argv[0][i] != '\0'; ++i)
/* First checks if argv[0][i] is valid ASCII; ctypes(3)
* don't handle non-ASCII.
* This is bad. */
if(argv[0][i] < 0x80 && !ctypes[ctype].f(argv[0][i]))
return 1;
else
r = 0;
return r;
}

25
src/strcmp.c Normal file
View File

@@ -0,0 +1,25 @@
#include <stdio.h> /* fprintf(3), stderr */
#ifndef EX_USAGE
# include <sysexits.h> /* EX_USAGE */
#endif
static char *program_name = "strcmp";
int main(int argc, char *argv[]){
int i;
if(argc < 3){
fprintf(stderr, "Usage: %s [string] [string...]\n",
argv[0] == NULL ? program_name : argv[0]);
return EX_USAGE;
}
for(; *argv[1] != '\0'; ++argv[1])
for(i = 2; i < argc; ++i)
if(*argv[i-1] > *argv[i])
return 1;
else if(*argv[i-1] < *argv[i]++)
return -1; /* actually 255 */
return 0;
}

View File

@@ -1,209 +0,0 @@
/*
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
* Copyright (c) 2023 Marceline Cramer <mars@tebibyte.media>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This file is part of YAC coreutils.
*
* YAC coreutils is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* YAC coreutils is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <errno.h>
#include <sysexits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "yac.h"
typedef struct string_t {
char *mem;
int len;
int capacity;
} string_t;
string_t *string_new() {
string_t *string = calloc(1, sizeof(string_t));
string->capacity = 1024;
string->len = 0;
string->mem = calloc(string->capacity, sizeof(char));
return string;
}
void string_putc(string_t *string, char c) {
string->mem[string->len] = c;
string->len++;
if (string->len >= string->capacity) {
string->capacity *= 2;
string->mem = realloc(string->mem, string->capacity * sizeof(char));
}
}
void tailc(FILE *f, long num) {}
void tailn(FILE *f, long num) {
string_t *lines[num];
int cursor = 0;
int looped = 0;
lines[cursor] = string_new();
int c = fgetc(f);
for (;;) {
if (c == EOF) {
string_putc(lines[cursor], '\0');
break;
}
string_putc(lines[cursor], c);
if (c == '\n') {
string_putc(lines[cursor], '\0');
if ((c = fgetc(f)) == EOF) {
break;
}
if (++cursor >= num) {
looped = 1;
cursor = 0;
}
lines[cursor] = string_new();
} else {
c = fgetc(f);
}
}
int read = looped ? cursor + 1 : 0;
do {
if (read >= num) {
read = 0;
}
fputs(lines[read]->mem, stdout);
} while (read++ != cursor);
}
void tailf(FILE *file) {
int byte;
while(true) {
if ((byte = fgetc(file)) != EOF) { putchar(byte); }
}
}
int main(int argc, char *argv[]) {
bool c = false;
bool f = false;
bool n = false;
int i;
int opt;
long num;
void (*fn)(FILE *, long) = tailn;
extern int optind;
while ((opt = getopt(argc, argv, "c:fn:")) != -1) {
switch (opt) {
/*
* From tail(1p):
*
* -c number The application shall ensure that the number option-argument
* is a decimal integer, optionally including a sign. The sign
* shall affect the location in the file, measured in bytes, to
* begin the copying:
*
* ┌─────┬────────────────────────────────────────┐
* │Sign │ Copying Starts │
* ├─────┼────────────────────────────────────────┤
* │ + │ Relative to the beginning of the file. │
* │ - │ Relative to the end of the file. │
* │none │ Relative to the end of the file. │
* └─────┴────────────────────────────────────────┘
* The application shall ensure that if the sign of the number
* option-argument is '+', the number option-argument is a non-
* zero decimal integer.
*
* The origin for counting shall be 1; that is, -c +1 represents
* the first byte of the file, -c -1 the last.
*
* -f If the input file is a regular file or if the file operand
* specifies a FIFO, do not terminate after the last line of the
* input file has been copied, but read and copy further bytes
* from the input file when they become available. If no file
* operand is specified and standard input is a pipe or FIFO,
* the -f option shall be ignored. If the input file is not a
* FIFO, pipe, or regular file, it is unspecified whether or not
* the -f option shall be ignored.
*
* -n number This option shall be equivalent to -c number, except the
* starting location in the file shall be measured in lines
* instead of bytes. The origin for counting shall be 1; that
* is, -n +1 represents the first line of the file, -n -1 the
* last.
*
* If neither -c nor -n is specified, -n 10 shall be assumed.
*/
case 'c':
c = true;
fn = tailc;
num = strtol(optarg, NULL, 10);
break;
case 'f':
f = true;
case 'n':
n = true;
num = strtol(optarg, NULL, 10);
break;
default:
fprintf(
stderr,
"Usage: %s (-f) [-c characters] [-n lines] file...\n",
argv[0]
);
return EX_USAGE;
}
}
if (!n && !c) {
num = 10;
} else if (n && c) {
fprintf(
stderr,
"Usage: %s (-f) [-c characters] [-n lines] file...\n",
argv[0]
);
return EX_USAGE;
}
FILE *file;
if (optind == argc) {
fn(stdin, num);
if (f) { tailf(stdin); }
} else {
for (i = optind; i < argc; i++) {
if ((file = rpath(argv[0], argv[i])) != NULL) {
fn(file, num);
}
if (f) { tailf(file); }
fclose(file);
}
}
return EX_OK;
}

View File

@@ -1,21 +1,9 @@
/*
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: AGPL-3.0-or-later
* SPDX-License-Identifier: CC0
*
* This file is part of YAC coreutils.
*
* YAC coreutils is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* YAC coreutils is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
* This work is marked with CC0 1.0. To view a copy of this license, visit
* <http://creativecommons.org/publicdomain/zero/1.0>.
*/
int main() {}

View File

@@ -1,77 +0,0 @@
/*
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This file is part of YAC coreutils.
*
* YAC coreutils is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* YAC coreutils is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysexits.h>
#include <sys/stat.h>
/* Resolve a file from a path */
FILE *rpath(char *argv0, char *path) {
struct stat stats;
FILE *file;
if (path[0] == '-') {
switch (path[1]) {
case '\0':
file = stdin;
break;
default:
file = NULL;
break;
}
} else if (stat(path, &stats) == 0 && S_ISDIR(stats.st_mode)) {
fprintf(stderr, "%s: %s: Is a directory.\n", argv0, path);
exit(EX_NOINPUT);
} else if ((file = fopen(path, "r")) == NULL) {
switch (errno) {
case EACCES:
fprintf(stderr, "%s: %s: Permission denied.\n", argv0, path);
exit(EX_NOINPUT);
case EISDIR:
fprintf(stderr, "%s: %s: Is a directory.\n", argv0, path);
exit(EX_NOINPUT);
case ELOOP:
fprintf(
stderr,
"%s: %s: Is a symbolic link loop.\n",
argv0,
path
);
exit(EX_UNAVAILABLE);
case EMFILE:
fprintf(stderr, "%s: Internal error.\n", argv0);
exit(EX_SOFTWARE);
case ENOENT: case ENOTDIR: case ENXIO:
fprintf(
stderr,
"%s: %s: No such path or directory.\n",
argv0,
path
);
exit(EX_NOINPUT);
default:
fprintf(stderr, "%s: Unknown error.\n", argv0);
exit(EX_UNAVAILABLE);
}
}
return file;
}

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This file is part of YAC coreutils.
*
* YAC coreutils is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* YAC coreutils is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
#ifndef YAC_H
#define YAC_H
FILE *rpath(char *argv0, char *path);
#endif