Add manpages. Rewrite echo. Rewrite cat (a few times). Update Makefile.

Add ls(1) prototype.
This commit is contained in:
Mid Favila 2022-10-18 12:47:34 -04:00
parent 966113d372
commit 4f9f1fb15a
19 changed files with 655 additions and 210 deletions

5
TODO
View File

@ -14,20 +14,19 @@ Simple commands (only a handful of parameters at most, with simple premises)
-yes [done]
-basename/dirname
-echo [in-progress, SUS]
-wc [in-progress]
-wc [done]
-tee
-cat [done]
-pwd
-cksum
-cal
Filesystem modifiers
Filesystem interfaces
-rm
-mv
-cp
-mkdir
-rmdir
-mktemp
-chgrp
-chown
-chmod

View File

@ -1,4 +1,4 @@
.TH cat 1 2021-11-21 mp-utils Userland
.TH cat 1 2021-11-21 mp-utils "General Commands Manual"
.SH NAME
cat \- concatenate input
.PP
@ -12,7 +12,7 @@ including stdin. It then concatenates (attached end to end) each bit of input,
before printing it to stdout.
.SH OPTIONS
.PP
This implementation of cat accepts the following arguments:
This implementation of cat accepts the following flags:
-u: Unbuffered output. Print input as soon as possible.

View File

@ -1,4 +1,4 @@
.TH echo 1 2021-11-21 mp-utils Userland
.TH echo 1 2021-11-21 mp-utils "General Commands Manual"
.SH NAME
echo \- Print argv to stdout.
.PP
@ -10,10 +10,28 @@ SUS
backslash escapes.
.SH DESCRIPTION
.PP
Echo is a standard Unix tool that accepts input from the user and prints it to stdout while applying minimal or no formatting.
Echo accepts input from the user and prints it to stdout while escaping the following specified sequences.
\\a \- Print a BEL.
\\b \- Print a backspace.
\\c \- Suppress the trailing newline and ignore further input.
\\f \- Print a form-feed.
\\n \- Print a newline.
\\r \- Print a carriage return.
\\t \- Print a tabulation.
\\v \- Print a vertical tabulation.
\\0 \- Print the specified codepoint (specified in octal) in the system's encoding.
.SH OPTIONS
.PP
This implementation of echo accepts no arguments.
This implementation of echo accepts no parameters.
.SH ENVIRONMENT
This implementation of echo requires a C89 compiler.
.SH FILES
@ -28,24 +46,7 @@ SUS
3
.SH NOTES
.PP
Including the following backslash-escapes modifies echo's behavior.
\\a \- Print a BEL.
\\b \- Print a backspace.
\\f \- Print a form-feed.
\\f \- Print a newline.
\\r \- Print a carriage return.
\\t \- Print a tabulation.
\\v \- Print a vertical tabulation.
\\c \- Suppress the trailing newline and ignore further input.
For historical reasons implementations of echo vary wildly in their behavior across systems. For a portable way to print to stdout, see printf.
.SH BUGS
.PP
Currently, \\0xxx (octal) escapes have not been implemented.

34
doc/false.1 Normal file
View File

@ -0,0 +1,34 @@
.TH false 1 2021-11-21 mp-utils "General Commands Manual"
.SH NAME
false \- return EXIT_FAILURE
.PP
.SH SYNOPSIS
.PP
Immediately exits with EXIT_FAILURE.
.SH DESCRIPTION
.PP
false immediately returns EXIT_FAILURE.
.SH OPTIONS
.PP
This implementation of false accepts no flags.
.SH ENVIRONMENT
This implementation of false requires a C89 compiler.
.SH FILES
/usr/src/mp-utils/src/true.c
.SH CONFORMING TO
.PP
.SM
POSIX
2017,
.SM
SUS
3
.SH NOTES
.PP
None.
.SH BUGS
.PP
None known.
.SH SEE ALSO
true(1p), false(1p), true(1)

34
doc/sleep.1 Normal file
View File

@ -0,0 +1,34 @@
.TH sleep 1 2021-11-21 mp-utils "General Commands Manual"
.SH NAME
sleep \- wait N seconds
.PP
.SH SYNOPSIS
.PP
Stall for N seconds before exiting.
.SH DESCRIPTION
.PP
Sleep accepts one argument, a non-negative integer, stalls for that number of seconds, and then exits with EXIT_SUCCESS.
.SH OPTIONS
.PP
This implementation of sleep accepts no parameters.
.SH ENVIRONMENT
This implementation of sleep requires a C89 compiler.
.SH FILES
/usr/src/mp-utils/src/sleep.c
.SH CONFORMING TO
.PP
.SM
POSIX
2017,
.SM
SUS
3
.SH NOTES
.PP
None.
.SH BUGS
.PP
None known.
.SH SEE ALSO
sleep(1p)

View File

@ -1,34 +0,0 @@
.TH wc 1 2021-11-21 mp-utils Userland
.SH NAME
wc \- print to stdout forever
.PP
.SH SYNOPSIS
.PP
Print the provided string to stdout forever.
.SH DESCRIPTION
.PP
Yes is a standard Unix tool that accepts input from the user and prints it to stdout repeatedly, or y when no input is provided.
.SH OPTIONS
.PP
This implementation of wc accepts no arguments.
.SH ENVIRONMENT
This implementation of wc requires a C89 compiler.
.SH FILES
/usr/src/mp-utils/src/wc.c
.SH CONFORMING TO
.PP
.SM
POSIX
2017,
.SM
SUS
3
.SH NOTES
.PP
None.
.SH BUGS
.PP
None known.
.SH SEE ALSO
wc(1p)

34
doc/true.1 Normal file
View File

@ -0,0 +1,34 @@
.TH true 1 2021-11-21 mp-utils "General Commands Manual"
.SH NAME
true \- return EXIT_SUCCESS
.PP
.SH SYNOPSIS
.PP
Immediately exits with EXIT_SUCCESS.
.SH DESCRIPTION
.PP
true immediately returns EXIT_SUCCESS.
.SH OPTIONS
.PP
This implementation of true accepts no parameters.
.SH ENVIRONMENT
This implementation of true requires a C89 compiler.
.SH FILES
/usr/src/mp-utils/src/true.c
.SH CONFORMING TO
.PP
.SM
POSIX
2017,
.SM
SUS
3
.SH NOTES
.PP
None.
.SH BUGS
.PP
None known.
.SH SEE ALSO
true(1p), false(1p), false(1)

View File

@ -1,4 +1,4 @@
.TH wc 1 2021-11-21 mp-utils Userland
.TH wc 1 2021-11-21 mp-utils "General Commands Manual"
.SH NAME
wc \- count words, lines, bytes/characters
.PP
@ -14,7 +14,7 @@ Characters in the context of wc includes multi-byte character support; that
bytes are called characters is an unfortunate notational happenstance.
.SH OPTIONS
.PP
This implementation of wc accepts the following arguments:
This implementation of wc accepts the following flags:
.SM
-c: Print the number of bytes.

View File

@ -1,4 +1,4 @@
.TH yes 1 2021-11-21 mp-utils Userland
.TH yes 1 2021-11-21 mp-utils "General Commands Manual"
.SH NAME
yes \- print to stdout forever
.PP
@ -10,7 +10,7 @@ Print the provided string to stdout forever.
yes is a standard Unix tool that accepts input from the user and prints it to stdout repeatedly, or y when no input is provided.
.SH OPTIONS
.PP
This implementation of yes accepts no arguments.
This implementation of yes accepts no flags.
.SH ENVIRONMENT
This implementation of yes requires a C89 compiler.
.SH FILES

72
old/cat2.c Normal file
View File

@ -0,0 +1,72 @@
/* cat.c -- program to concatenate named files and/or stdin onto stdout */
/* version 2 */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "support.h"
/* parameters */
enum
{
U
};
int main(int argc, char **argv)
{
int i, c, bufsize, newbufsize;
char *buf, *newbuf;
char pars[1] = {0};
FILE *fd;
i = c = bufsize = newbufsize = 0;
buf = newbuf = 0;
fd = 0;
/* i < argc is obvious; steps through all provided args. */
/* !argc-optind && !c is a little less so - it allows this loop to run once if the user provides no paths */
do
{
if( !(fd = file_open(argv[i], "r")))
{
throw(FOPEN_FAIL, mastrcat(argv[0], mastrcat(": could not open file ", argv[i])));
}
if(pars[U])
{
for(; (c = fgetc(fd)) != EOF; c = 0)
{
fputc(c, stdout);
}
}
else
{
newbuf = file_read(fd, &newbufsize);
buf = concat(buf, newbuf, bufsize, newbufsize);
bufsize += newbufsize;
free(newbuf);
}
i++, newbufsize = 0;
}
while((i < argc) || (((argc - optind) == 0) && !c));
if(!pars[U])
{
fwrite(buf, sizeof(char), bufsize, stdout);
}
exit(EXIT_SUCCESS);
}

71
old/echo.c Normal file
View File

@ -0,0 +1,71 @@
/* echo -- version one */
/* program to print its argument vector to stdout */
/* mostly SUS compliant */
#include "support.h"
int main(int argc, char **argv)
{
int i, i2;
char escape = 0;
if(argc > 1)
for(i = 1; i < argc; i++)
{
for(i2 = 0; argv[i][i2] != '\0'; i2++)
{
if(escape)
switch(argv[i][i2])
{
case 'a':
escape = 0;
putchar('\a');
break;
case 'b':
escape = 0;
putchar('\b');
break;
case 'c': // Immediately stop execution.
goto end;
case 'f':
escape = 0;
putchar('\f');
break;
case 'n':
escape = 0;
putchar('\n');
break;
case 'r':
escape = 0;
putchar('\r');
break;
case 't':
escape = 0;
putchar('\t');
break;
case 'v':
escape = 0;
putchar('\v');
break;
case '\\':
escape = 0;
putchar('\\');
break;
case '0': // This is for octal values.
break;
}
else if(argv[i][i2] == '\\')
escape++;
else
putchar(argv[i][i2]);
}
if(i < (argc-1))
putchar(' ');
}
putchar('\n');
end:
exit(EXIT_SUCCESS);
}
o

180
proto/ls.c Normal file
View File

@ -0,0 +1,180 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include "../src/support.h"
/* pars -- end with L is lowercase par, end with U is uppercase, non-alpha spelled out */
enum
{
AL,
AU,
CL,
CU,
DL,
FL,
FU,
GL,
IL,
KL,
LL,
ML,
NL,
OL,
PL,
QL,
RL,
RU,
SL,
SU,
TL,
UL,
XL,
ONE,
};
int main(int argc, char **argv)
{
char pars[23] = {0};
int i;
DIR *dp;
struct dirent *dirp;
i = 0;
dp = 0;
dirp = 0;
/* process our parameters */
for(; (i = getopt(argc, argv, "ikqrsglnoAaCmx1FpHLRdSftcu")) != -1; i = 0)
{
switch(i)
{
case 'a': pars[AL] = 1;
pars[AU] = 0;
break;
case 'A': pars[AU] = 1;
pars[AL] = 0;
break;
case 'c': pars[CL] = 1;
break;
case 'C':
if(pars[ML] || pars[XL] || pars[ONE] )
{
throw(NEEDARG_FAIL, " ls [-ikqrsglno] [-A|-a] [-C|-m|-x|-l]\n\t[-F|-p] [-H|-L] [-R|-d] [-S|-f|-t] [-c|-u] [path ...]");
}
pars[CU] = 1;
break;
case 'd': pars[DL] = 1;
pars[RU] = 0;
break;
case 'f': pars[FL] = 1;
pars[SU] = 0;
pars[TL] = 0;
break;
case 'F': pars[FU] = 1;
pars[PL] = 0;
break;
case 'g': pars[GL] = 1;
break;
case 'i': pars[IL] = 1;
break;
case 'k': pars[KL] = 1;
break;
case 'l': pars[LL] = 1;
break;
case 'm':
if(pars[CU] || pars[XL] || pars[ONE] )
{
throw(NEEDARG_FAIL, " ls [-ikqrsglno] [-A|-a] [-C|-m|-x|-l]\n\t[-F|-p] [-H|-L] [-R|-d] [-S|-f|-t] [-c|-u] [path ...]");
}
pars[ML] = 1;
pars[CU] = 0;
pars[XL] = 0;
pars[ONE] = 0;
break;
case 'n': pars[NL] = 1;
break;
case 'o': pars[OL] = 1;
break;
case 'p': pars[PL] = 1;
pars[FU] = 0;
break;
case 'q': pars[QL] = 1;
break;
case 'r': pars[RL] = 1;
break;
case 'R': pars[RU] = 1;
pars[DL] = 0;
break;
case 's': pars[SL] = 1;
break;
case 'S': pars[SU] = 1;
pars[FL] = 0;
pars[TL] = 0;
break;
case 't': pars[TL] = 1;
pars[SU] = 0;
pars[FL] = 0;
break;
case 'u': pars[UL] = 1;
pars[CL] = 0;
break;
case 'x':
if(pars[ML] || pars[CU] || pars[ONE] )
{
throw(NEEDARG_FAIL, " ls [-ikqrsglno] [-A|-a] [-C|-m|-x|-l]\n\t[-F|-p] [-H|-L] [-R|-d] [-S|-f|-t] [-c|-u] [path ...]");
}
pars[XL] = 1;
break;
case '1':
if(pars[ML] || pars[XL] || pars[CU] )
{
throw(NEEDARG_FAIL, " ls [-ikqrsglno] [-A|-a] [-C|-m|-x|-l]\n\t[-F|-p] [-H|-L] [-R|-d] [-S|-f|-t] [-c|-u] [path ...]");
}
pars[ONE] = 1;
break;
case ':':
case '?':
default: throw(NEEDARG_FAIL, mastrcat(argv[0], " ls [-ikqrsglno] [-A|-a] [-C|-m|-x|-l]\n\t[-F|-p] [-H|-L] [-R|-d] [-S|-f|-t] [-c|-u] [path ...]"));
break;
}
}
i = optind;
do
{
if(!argv[i])
{
argv[i] = ".";
}
if( !(dp = opendir(argv[i])))
{
throw(MISC_FAIL, mastrcat(argv[0], mastrcat(": could not access named file or directory: ", argv[i])));
}
for(;(dirp = readdir(dp));)
{
if(dirp->d_name[0] == '.' && !pars[AL])
{
continue;
}
printf("%s\n", dirp->d_name);
}
i++;
}
while(i < argc);
exit(EXIT_SUCCESS);
}

View File

@ -14,6 +14,13 @@ BIN = cat\
echo\
wc\
MAN = \
cat.1 \
false.1 \
true.1 \
yes.1 \
echo.1 \
wc.1 \
all: ${BIN}
false: true
@ -21,7 +28,9 @@ false: true
install: all
mkdir -p ${DESTDIR}/${PREFIX}/bin
mkdir -p ${DESTDIR}/${PREFIX}/share/man/man.1
install -Dm0755 ${BIN} ${DESTDIR}/${PREFIX}/bin/
install -Dm0644 ${MAN} ${DESTDIR}/${PREFIX}/share/man/man.1/
clean:
rm ${BIN} *.o

109
src/cat.c
View File

@ -1,115 +1,78 @@
/* cat.c -- program to concatenate named files and/or stdin onto stdout */
/* version 2 */
/* cat -- third revision of a program to concatenate files and/or stdin onto */
/* stdout */
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include "support.h"
/* parameters */
/* Params */
enum
{
U
};
/* concat - return a buffer of size new_size containing s1 and s2 concatenated. */
char *concat(char *a1, char *a2, int a1_size, int a2_size)
{
char *newbuf;
newbuf = 0;
if( !(newbuf = malloc(a1_size+a2_size)))
{
throw(MALLOC_FAIL, "concat: couldn't create buffer");
}
if(a1_size)
{
mid_mempcpy(newbuf, a1, a1_size, 0);
}
if(a2_size)
{
mid_mempcpy(newbuf, a2, a2_size, a1_size);
}
return(newbuf);
}
int main(int argc, char **argv)
{
int i, c, bufsize, newbufsize;
char *buf, *newbuf;
char pars[1] = {0};
int i, i2;
char param_state[1] = {0};
FILE *fd;
i = c = bufsize = newbufsize = 0;
buf = newbuf = 0;
i = i2 = 0;
fd = 0;
/* process our parameters */
for(; (c = getopt(argc, argv, "u")) != -1; c = 0)
for(; (i = getopt(argc, argv, "u")) != -1;)
{
switch(c)
switch(i)
{
case 'u': pars[U] = 1;
break;
case ':':
case '?':
default: throw(NEEDARG_FAIL, mastrcat(argv[0], " [-u] [file ...]"));
case 'u':
param_state[U] = 1;
break;
default:
throw(NEEDARG_FAIL, mastrcat(argv[0], " [-u] [file ...]"));
}
}
i = optind;
/* i < argc is obvious; steps through all provided args. */
/* !argc-optind && !c is a little less so - it allows this loop to run once if the user provides no paths */
do
if(param_state[U])
{
if( !(fd = file_open(argv[i], "r")))
{
throw(FOPEN_FAIL, mastrcat(argv[0], mastrcat(": could not open file ", argv[i])));
}
setvbuf(stdout, NULL, _IONBF, 0);
}
if(pars[U])
do
{
if(argv[i] == NULL || !strcmp("-", argv[i]))
{
for(; (c = fgetc(fd)) != EOF; c = 0)
{
fputc(c, stdout);
}
fd = fopen("/dev/stdin", "r");
}
else
{
newbuf = file_read(fd, &newbufsize);
buf = concat(buf, newbuf, bufsize, newbufsize);
bufsize += newbufsize;
free(newbuf);
if( !(fd = fopen(argv[i], "r")))
{
throw(FOPEN_FAIL, mastrcat(argv[0], mastrcat(": could not open file ", argv[i])));
}
}
i++, newbufsize = 0;
}
while((i < argc) || (((argc - optind) == 0) && !c));
if(!pars[U])
{
fwrite(buf, sizeof(char), bufsize, stdout);
}
for(i2 = 0; (i2 = fgetc(fd)) != EOF; i2 = 0)
{
fputc(i2, stdout);
}
exit(0);
i++;
}
while(i < argc);
exit(EXIT_SUCCESS);
}

View File

@ -1,65 +1,102 @@
/* echo -- version two */
/* program to print argument vector to stdout while escaping BEL, tab, backspace and others */
/* mostly SUS compliant */
#include <stdlib.h>
#include <stdio.h>
#include "support.h"
void escape(char c)
{
switch(c)
{
case 'a':
fputc('\a', stdout);
break;
case 'b':
fputc('\b', stdout);
break;
case 'c':
exit(EXIT_SUCCESS);
break;
case 'f':
fputc('\f', stdout);
break;
case 'n':
fputc('\n', stdout);
break;
case 'r':
fputc('\r', stdout);
break;
case 't':
fputc('\t', stdout);
break;
case 'v':
fputc('\v', stdout);
break;
case '\\':
fputc('\\', stdout);
break;
case '0':
break;
default:
fputc('\\', stdout);
fputc(c, stdout);
break;
}
}
int main(int argc, char **argv)
{
char esc_state;
int i, i2;
char escape = 0;
if(argc > 1)
for(i = 1; i < argc; i++)
esc_state = 0;
i = 1;
i2 = 0;
for(; i < argc; i++)
{
for(i2 = 0; argv[i][i2] != '\0'; i2++)
{
for(i2 = 0; argv[i][i2] != '\0'; i2++)
if(!esc_state && '\\' == argv[i][i2])
{
if(escape)
switch(argv[i][i2])
{
case 'a':
escape = 0;
putchar('\a');
break;
case 'b':
escape = 0;
putchar('\b');
break;
case 'c': // Immediately stop execution.
goto end;
case 'f':
escape = 0;
putchar('\f');
break;
case 'n':
escape = 0;
putchar('\n');
break;
case 'r':
escape = 0;
putchar('\r');
break;
case 't':
escape = 0;
putchar('\t');
break;
case 'v':
escape = 0;
putchar('\v');
break;
case '\\':
escape = 0;
putchar('\\');
break;
case '0': // This is for octal values.
break;
}
else if(argv[i][i2] == '\\')
escape++;
else
putchar(argv[i][i2]);
esc_state = 1;
}
if(i < (argc-1))
putchar(' ');
}
putchar('\n');
else if(esc_state)
{
esc_state = 0;
end:
return 0;
escape(argv[i][i2]);
}
else
{
fputc(argv[i][i2], stdout);
}
}
if(esc_state)
{
esc_state = 0;
fputc('\\', stdout);
}
if((i + 1) != argc)
{
fputc(' ', stdout);
}
}
fputc('\n', stdout);
exit(EXIT_SUCCESS);
}

View File

@ -39,5 +39,5 @@ int main(int argc, char **argv)
sleep(i);
exit(0);
exit(EXIT_SUCCESS);
}

View File

@ -70,21 +70,6 @@ void throw(long unsigned int condition, void *info)
}
}
/* mid_mempcpy -- copy n bytes from s2 to s1 starting at position p */
int mid_mempcpy(char *s1, char *s2, int n, int p)
{
int i;
i = 0;
for(i = 0; i <= n; i++, p++)
{
s1[p] = s2[i];
}
return(0);
}
/* arrccat -- function to copy arr2len bytes from arr2 to the arr1len'th position of arr1. returns *newarr, and stores the length */
/* of newarr[] in arr1len (that's why it needs to be a pointer to arr1len and not just a long unsigned integer). */
@ -207,3 +192,63 @@ char *file_read(FILE *fd, int *newsize)
*newsize = i;
return(buf);
}
node *node_create()
{
node *newnode;
newnode = 0;
;
return(newnode);
}
int node_free(node *todel)
{
node *nodep;
nodep = todel->previous;
nodep->next = todel->next;
free(todel->name);
free(todel->data);
free(todel);
return(0);
}
/* concat - return a buffer of size new_size containing s1 and s2 concatenated. */
char *concat(char *a1, char *a2, int a1_size, int a2_size)
{
char *newbuf;
newbuf = 0;
if( !(newbuf = malloc(a1_size+a2_size)))
{
throw(MALLOC_FAIL, "concat: couldn't create buffer");
}
if(a1_size)
{
memcpy(newbuf, a1, a1_size);
}
if(a2_size)
{
memcpy((newbuf + a1_size), a2, a2_size);
}
return(newbuf);
}

View File

@ -3,7 +3,7 @@
int main(int argc, char **argv)
{
if(!strcmp(argv[0], "true"))
return 0;
exit(EXIT_SUCCESS);
else
return 1;
exit(EXIT_FAILURE);
}

View File

@ -190,5 +190,5 @@ int main(int argc, char **argv)
while((i+=1) < argc);
exit(0);
exit(EXIT_SUCCESS);
}