Makefile didn't work. Nice.

This commit is contained in:
Mid Favila 2022-10-01 19:05:39 -04:00
parent facda46907
commit 5c5bb242dc
11 changed files with 412 additions and 121 deletions

2
TODO
View File

@ -1,3 +1,5 @@
Write a function to return a dictionary containing key-value pairs
describing command line parameters
Write a Makefile. [done]
Add octal escape support to echo.
Rework yes(1) to buffer output. This achieves greater throughput per system call.

38
doc/cat.1 Normal file
View File

@ -0,0 +1,38 @@
.TH cat 1 2021-11-21 mp-utils Userland
.SH NAME
cat \- concatenate input
.PP
.SH SYNOPSIS
.PP
Concatenate input onto stdout.
.SH DESCRIPTION
.PP
cat is a standard Unix utility that accepts an arbitrary number of input files,
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:
-u: Unbuffered output. Print input as soon as possible.
.SH ENVIRONMENT
This implementation of cat requires a C89 compiler.
.SH FILES
/usr/src/mp-utils/src/cat.c
.SH CONFORMING TO
.PP
.SM
POSIX
2017,
.SM
SUS
3
.SH NOTES
.PP
None.
.SH BUGS
.PP
None known.
.SH SEE ALSO
cat(1p)

View File

@ -1,5 +1,4 @@
.TH echo 1 2021-11-21 mp-utils Userland
.SH NAME
echo \- Print argv to stdout.
.PP
@ -49,6 +48,6 @@ Including the following backslash-escapes modifies echo's behavior.
.SH BUGS
.PP
Currently, \\0 (octal) escapes have not been implemented.
Currently, \\0xxx (octal) escapes have not been implemented.
.SH SEE ALSO
echo(1p), printf(1)
echo(1p), printf(1p), printf(1)

34
doc/template Normal file
View File

@ -0,0 +1,34 @@
.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)

View File

@ -1,17 +1,30 @@
.TH wc 1 2021-11-21 mp-utils Userland
.SH NAME
wc \- print to stdout forever
wc \- count words, lines, bytes/characters
.PP
.SH SYNOPSIS
.PP
Print the provided string to stdout forever.
wc [-c|-m] [-lw] [files...]
.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.
wc is a standard Unix tool that tallies up the number of words (series of
non-blank bytes), lines (newlines), and bytes or characters in input.
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 no arguments.
This implementation of wc accepts the following arguments:
.SM
-c: Print the number of bytes.
-m: Print the number of characters.
-l: Print the number of lines.
-w: Print the number of words.
.SH ENVIRONMENT
This implementation of wc requires a C89 compiler.
.SH FILES
@ -29,6 +42,7 @@ SUS
None.
.SH BUGS
.PP
None known.
This implementation of wc does not currently treat characters any different than
bytes.
.SH SEE ALSO
wc(1p)
wc(1p)

View File

@ -1,5 +1,4 @@
.TH yes 1 2021-11-21 mp-utils Userland
.SH NAME
yes \- print to stdout forever
.PP
@ -8,7 +7,7 @@ yes \- print to stdout forever
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.
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.
@ -31,4 +30,4 @@ None.
.PP
None known.
.SH SEE ALSO
yes(1p)
yes(1p)

120
old/cat.c Normal file
View File

@ -0,0 +1,120 @@
/* cat.c -- program to concatenate input and stdin onto stdout. */
/* first version */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "support.h"
char *cat(FILE *fp, const int mode, long unsigned *bufsize)
{
char c;
static long unsigned int i, finalbuflen, tmpbuflen;
char *arr, *tmparr, *finalarr;
tmpbuflen = 4096;
if(!mode)
{
arr = malloc(tmpbuflen);
tmparr = finalarr = 0;
for(i = 0, finalbuflen = 0; (c = fgetc(fp)) != EOF; i++, finalbuflen++)
{
if(i >= tmpbuflen)
{
tmpbuflen *= 2;
tmparr = malloc(tmpbuflen);
memcpy(tmparr, arr, tmpbuflen/2);
free(arr);
arr = tmparr;
}
arr[i] = c;
}
finalarr = malloc(finalbuflen);
memcpy(finalarr, arr, finalbuflen);
free(arr);
arr = finalarr;
*bufsize = finalbuflen;
return arr;
}
else
{
for(;(c = fgetc(fp)) != EOF;)
{
putchar(c);
}
}
return NULL;
}
int main(int argc, char **argv)
{
long unsigned int i, upresence, fppresence, buflen, newbuflen;
char *buf, *newbuf, *tmpbuf;
FILE *fp;
i = upresence = fppresence = buflen = newbuflen = 0;
buf = newbuf = tmpbuf = 0;
fp = 0;
switch( (upresence = getopt(argc, argv, "u")))
{
case 'u': i++;
break;
default:
break;
}
for(i++;argv[i] != NULL; i++)
{
if(!strcmp(argv[i], "-"))
{
fppresence++;
newbuf = cat(fopen("/dev/stdin", "r"), upresence, &newbuflen);
}
else if((fp = fopen(argv[i], "r")) != NULL)
{
fppresence++;
newbuf = cat(fp, upresence, &newbuflen);
fclose(fp);
}
else
{
fprintf(stderr, "%s: failed to open %s. Aborting.\n", argv[0], argv[i]);
exit(1);
}
/* This is where the actual magic happens. */
if(!upresence)
{
/* Here, we copy buf and newbuf end-to-end into a new buffer of size buflen+newbuflen, then store that in buflen and */
/* return a pointer to the new buffer. */
tmpbuf = arrccat(buf, newbuf, &buflen, newbuflen);
free(buf);
buf = tmpbuf;
}
}
if(!fppresence)
{
buf = cat(fopen("/dev/stdin", "r"), upresence, &buflen);
}
if(!upresence)
{
for(i = 0; i < buflen; i++)
{
putchar(buf[i]);
}
}
exit(0);
}

View File

@ -20,7 +20,7 @@ false: true
ln -s true false
install: all
mkdir -p ${DESTDIR}/${PREFIX}
mkdir -p ${DESTDIR}/${PREFIX}/bin
install -Dm0755 ${BIN} ${DESTDIR}/${PREFIX}/bin/
clean:

160
src/cat.c
View File

@ -1,112 +1,108 @@
/* 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"
char *cat(FILE *fp, const int mode, long unsigned *bufsize)
/* parameters */
enum
{
char c;
static long unsigned int i, finalbuflen, tmpbuflen;
char *arr, *tmparr, *finalarr;
tmpbuflen = 4096;
U
};
if(!mode)
{
arr = malloc(tmpbuflen);
tmparr = finalarr = 0;
for(i = 0, finalbuflen = 0; (c = fgetc(fp)) != EOF; i++, finalbuflen++)
{
if(i >= tmpbuflen)
{
tmpbuflen *= 2;
tmparr = malloc(tmpbuflen);
memcpy(tmparr, arr, tmpbuflen/2);
free(arr);
arr = tmparr;
}
arr[i] = c;
}
finalarr = malloc(finalbuflen);
memcpy(finalarr, arr, finalbuflen);
free(arr);
arr = finalarr;
*bufsize = finalbuflen;
return arr;
}
else
/* 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)))
{
for(;(c = fgetc(fp)) != EOF;)
{
putchar(c);
}
throw(MALLOC_FAIL, "concat: couldn't create buffer");
}
return NULL;
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)
{
long unsigned int i, upresence, fppresence, buflen, newbuflen;
char *buf, *newbuf, *tmpbuf;
FILE *fp;
i = upresence = fppresence = buflen = newbuflen = 0;
buf = newbuf = tmpbuf = 0;
fp = 0;
int i, c, bufsize, newbufsize;
if((upresence = (getopt(argc, argv, ":u") == 'u')))
char *buf, *newbuf;
char pars[1] = {0};
FILE *fd;
i = c = bufsize = newbufsize = 0;
buf = newbuf = 0;
fd = 0;
/* process our parameters */
for(; (c = getopt(argc, argv, "u")) != -1; c = 0)
{
i++;
switch(c)
{
case 'u': pars[U] = 1;
break;
case ':':
case '?':
default: throw(NEEDARG_FAIL, mastrcat(argv[0], " [-u] [file ...]"));
break;
}
}
for(i++;argv[i] != NULL; i++)
{
if(!strcmp(argv[i], "-"))
{
fppresence++;
newbuf = cat(fopen("/dev/stdin", "r"), upresence, &newbuflen);
}
else if((fp = fopen(argv[i], "r")) != NULL)
{
fppresence++;
newbuf = cat(fp, upresence, &newbuflen);
fclose(fp);
}
else
{
fprintf(stderr, "%s: failed to open %s. Aborting.\n", argv[0], argv[i]);
exit(1);
}
i = optind;
/* This is where the actual magic happens. */
if(!upresence)
/* i < argc is obvious; steps through all provided args. */
/* !argc-optind && !newbuf is a little less so - it allows this loop to run once if the user provides no paths */
for(i = optind; (i < argc) || (((argc - optind) == 0) && !newbuf); i++, newbufsize = 0)
{
if( !(fd = file_open(argv[i], "r")))
{
/* Here, we copy buf and newbuf end-to-end into a new buffer of size buflen+newbuflen, then store that in buflen and */
/* return a pointer to the new buffer. */
tmpbuf = arrccat(buf, newbuf, &buflen, newbuflen);
free(buf);
buf = tmpbuf;
throw(FOPEN_FAIL, mastrcat(argv[0], mastrcat(": could not open file ", argv[i])));
}
newbuf = file_read(fd, &newbufsize);
if(pars[U])
{
fwrite(newbuf, sizeof(char), newbufsize, stdout);
free(newbuf);
continue;
}
buf = concat(buf, newbuf, bufsize, newbufsize);
bufsize += newbufsize;
free(newbuf);
}
if(!fppresence)
if(!pars[U])
{
buf = cat(fopen("/dev/stdin", "r"), upresence, &buflen);
}
if(!upresence)
{
for(i = 0; i < buflen; i++)
{
putchar(buf[i]);
}
fwrite(buf, sizeof(char), bufsize, stdout);
}
exit(0);

View File

@ -6,7 +6,9 @@
#include <sys/stat.h>
enum {
/* Error constants */
enum
{
UNKNOWN_FAIL = 1,
MALLOC_FAIL,
NEEDARG_FAIL,
@ -16,30 +18,33 @@ enum {
MISC_FAIL
};
/* 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). */
char *arrccat(char *arr1, char *arr2, size_t *arr1len, size_t arr2len)
/* Standard data identifiers for nodes */
enum
{
char *newarr;
unsigned int i, i2;
newarr = malloc(*arr1len+arr2len);
i = i2 = 0;
CHAR = 1,
INT,
LONG,
DOUBLE,
CHARP,
INTP,
LONGP,
DOUBLEP,
NODEP
};
for(i = 0; i < *arr1len; i++)
{
newarr[i] = arr1[i];
}
/* node - node type suitable for being a member in a linked list. */
/* name - the name of the data in this node */
/* data - pointer to arbitrary data */
/* type - implementation-defined identifier for what kind of data this node holds */
typedef struct LNODE
{
struct LNODE *previous;
char *name;
void *data;
int type;
struct LNODE *next;
} node;
for(i2 = 0; i2 < arr2len; i2++, i++)
{
newarr[i] = arr2[i2];
}
*arr1len = *arr1len+arr2len;
return newarr;
}
/* Condition should be one of the above enum'd strings. Info is optional; it can just be NULL when irrelevant. */
void throw(long unsigned int condition, void *info)
@ -65,6 +70,46 @@ 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). */
char *arrccat(char *arr1, char *arr2, size_t *arr1len, size_t arr2len)
{
char *newarr;
unsigned int i, i2;
newarr = malloc(*arr1len+arr2len);
i = i2 = 0;
for(i = 0; i < *arr1len; i++)
{
newarr[i] = arr1[i];
}
for(i2 = 0; i2 < arr2len; i2++, i++)
{
newarr[i] = arr2[i2];
}
*arr1len = *arr1len+arr2len;
return newarr;
}
/* mastrcat -- improved string concat function. returns a pointer to the first element in a buffer containing the strings str1 */
/* and str2 joined end-to-end. */
char *mastrcat(char *str1, char *str2)
@ -86,7 +131,7 @@ char *mastrcat(char *str1, char *str2)
}
return nbuf;
}
}
/* open stdin if path is null */
FILE *file_open(char *path, char *mode)
@ -98,7 +143,7 @@ FILE *file_open(char *path, char *mode)
if(!mode)
{
throw(MISC_FAIL, "file_open: mode is null. Terminating.");
return(NULL);
}
if(path == NULL || !strcmp(path, "-"))
@ -112,10 +157,53 @@ FILE *file_open(char *path, char *mode)
if(!fd)
{
throw(FOPEN_FAIL, mastrcat("file_open: couldn't open ", mastrcat(path, mastrcat(" using mode ", mode))));
return(NULL);
}
return(fd);
}
/* return a buffer containing the contents of fd, or NULL if failure. Store the size of the new buffer in newsize; -1 on fail. */
char *file_read(FILE *fd, int *newsize)
{
int bufsize, c, i;
char *buf, *tmpbuf;
/* bufsize is arbitrary */
bufsize = 4096;
c = i = 0;
buf = tmpbuf = 0;
if( !(buf = malloc(bufsize)))
{
*newsize = -1;
return(NULL);
}
for(i = 0; (c = fgetc(fd)) != EOF; i++)
{
if(i >= bufsize)
{
if( !(tmpbuf = malloc(bufsize *= 2)))
{
*newsize = -1;
return(NULL);
}
memcpy(tmpbuf, buf, i-1);
free(buf);
buf = tmpbuf;
}
buf[i] = c;
}
*newsize = i;
return(buf);
}

View File

@ -1,4 +1,5 @@
/* wc.c -- program to count and display the number of lines, words and one of bytes or characters in the named files */
/* first version */
#include <stdlib.h>