move cat to software
This commit is contained in:
parent
7e6dc01b5d
commit
1814d85042
@ -1,106 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define STDIN_NAME "<stdin>"
|
|
||||||
#define STDOUT_NAME "<stdout>"
|
|
||||||
|
|
||||||
/* these are the predicted errors that could occur */
|
|
||||||
enum error_type{
|
|
||||||
FILE_ACCESS,
|
|
||||||
FILE_CLOSE,
|
|
||||||
FILE_WRITE
|
|
||||||
};
|
|
||||||
|
|
||||||
/* this is an error function that will print to standard error the error that
|
|
||||||
* occurred in the program and exit */
|
|
||||||
void
|
|
||||||
error(enum error_type type, char *argv0, char *file_name){
|
|
||||||
switch(type){
|
|
||||||
case FILE_ACCESS:
|
|
||||||
fprintf(stderr, "%s: %s: cannot open file\n", argv0, file_name);
|
|
||||||
break;
|
|
||||||
case FILE_CLOSE:
|
|
||||||
fprintf(stderr, "%s: %s: cannot close file\n", argv0, file_name);
|
|
||||||
break;
|
|
||||||
case FILE_WRITE:
|
|
||||||
fprintf(stderr, "%s: %s: cannot write to file\n", argv0, file_name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print input to output, returns 0 if successful and 1 if unsuccessful */
|
|
||||||
int
|
|
||||||
file_copy(FILE *input, FILE *output){
|
|
||||||
int c;
|
|
||||||
while((c = getc(input)) != EOF)
|
|
||||||
if(putc(c, output) == EOF)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[]){
|
|
||||||
/* the name of the file being printed (for diagnostics) */
|
|
||||||
char *file_name;
|
|
||||||
|
|
||||||
/* allocate this ahead of time */
|
|
||||||
char *stdin_file_name = STDIN_NAME;
|
|
||||||
|
|
||||||
/* the file pointer of the file being printed */
|
|
||||||
FILE *input;
|
|
||||||
|
|
||||||
/* this will always be stdout */
|
|
||||||
FILE *output = stdout;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* whether or not options are being parsed */
|
|
||||||
int parsing_opts = 1;
|
|
||||||
|
|
||||||
/* usage with 0 arguments - print standard input to standard output */
|
|
||||||
if(argc == 1 && file_copy(stdin, stdout))
|
|
||||||
error(FILE_WRITE, argv[0], STDOUT_NAME);
|
|
||||||
else if(argc == 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for(i = 1; i < argc; ++i){
|
|
||||||
/* parsing options */
|
|
||||||
|
|
||||||
/* after `--`, interpret `--`, `-`, and `-u` as literal
|
|
||||||
* filenames */
|
|
||||||
if(parsing_opts && !strcmp(argv[i], "--")){
|
|
||||||
parsing_opts = 0;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* ignore `-u` if still parsing options */
|
|
||||||
}else if(parsing_opts && !strcmp(argv[i], "-u"))
|
|
||||||
setbuf(output, (char *)NULL);
|
|
||||||
|
|
||||||
/* take `-` to mean standard input if still parsing options */
|
|
||||||
else if(parsing_opts && !strcmp(argv[i], "-")){
|
|
||||||
file_name = stdin_file_name;
|
|
||||||
input = stdin;
|
|
||||||
|
|
||||||
/* non-option; open the file and make sure file_name points to
|
|
||||||
* the right string */
|
|
||||||
}else{
|
|
||||||
file_name = argv[i];
|
|
||||||
input = fopen(file_name, "r");
|
|
||||||
if(input == NULL)
|
|
||||||
error(FILE_ACCESS, argv[0], file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print input to output */
|
|
||||||
if(file_copy(input, output))
|
|
||||||
error(FILE_WRITE, argv[0], STDOUT_NAME);
|
|
||||||
|
|
||||||
/* close input file if it's not stdin */
|
|
||||||
if(input != stdin && fclose(input))
|
|
||||||
error(FILE_CLOSE, argv[0], file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exit successfully */
|
|
||||||
return 0;
|
|
||||||
}
|
|
@ -1,290 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<HTML LANG="en">
|
|
||||||
<HEAD>
|
|
||||||
<LINK HREF="http://www.trinity.moe/knowledge/cat" REL="canonical" />
|
|
||||||
<LINK HREF="https://raw.githubusercontent.com/devenblake/homepage/main/favicon.ico" REL="shortcut icon" TYPE="image/x-icon" />
|
|
||||||
<LINK HREF="/css/blank.css" ID="highlight" REL="stylesheet" />
|
|
||||||
<LINK HREF="/css/blank.css" ID="styling" REL="stylesheet" />
|
|
||||||
<META CHARSET="UTF-8" />
|
|
||||||
<META CONTENT="noindex" NAME="googlebot" /> <!-- FUCK GOOGLE -->
|
|
||||||
<META CONTENT="interest-cohort=()" HTTP-EQUIV="Permissions-Policy" /> <!-- FUCK GOOGLE -->
|
|
||||||
<META NAME="viewport" CONTENT="width=device-width, initial-scale=1" />
|
|
||||||
<TITLE>cat(1)</TITLE>
|
|
||||||
</HEAD>
|
|
||||||
<BODY>
|
|
||||||
<P><A HREF="/">~ Return to the rest of the site</A></P>
|
|
||||||
|
|
||||||
<SCRIPT SRC="/js/cookies.js" TYPE="application/javascript"></SCRIPT>
|
|
||||||
<SCRIPT SRC="/js/sheets.js" TYPE="application/javascript"></SCRIPT>
|
|
||||||
<SCRIPT TYPE="application/javascript">window.onload = window.initializesheets;</SCRIPT>
|
|
||||||
<SCRIPT ASYNC TYPE="application/javascript">
|
|
||||||
/* see on page: acknowledgements */
|
|
||||||
window.is_highlightjs_here = false;
|
|
||||||
window.is_highlighted_languages = [];
|
|
||||||
window.to_be_highlighted = [];
|
|
||||||
window.is_highlight_stylesheet_here = false;
|
|
||||||
window.load_highlighting = function(language){
|
|
||||||
var element;
|
|
||||||
var script;
|
|
||||||
document.getElementById(language + "_toggle").remove();
|
|
||||||
if(!window.is_highlight_stylesheet_here){
|
|
||||||
document.getElementById("highlight").setAttribute("href", "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/styles/default.min.css");
|
|
||||||
window.is_highlight_stylesheet_here = true;
|
|
||||||
}
|
|
||||||
if(!window.is_highlightjs_here){
|
|
||||||
script = document.createElement('script');
|
|
||||||
script.async = false;
|
|
||||||
script.src = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/highlight.min.js";
|
|
||||||
document.body.appendChild(script);
|
|
||||||
window.is_highlightjs_here = true;
|
|
||||||
}
|
|
||||||
if(window.is_highlighted_languages.indexOf(language) == -1){
|
|
||||||
window.to_be_highlighted.push(language);
|
|
||||||
|
|
||||||
script = document.createElement('script');
|
|
||||||
script.async = false;
|
|
||||||
script.src = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.0.1/languages/" + language + ".min.js";
|
|
||||||
script.onload = function(){
|
|
||||||
var language = window.to_be_highlighted.shift()
|
|
||||||
var elements = document.getElementsByClassName("language-" + language);
|
|
||||||
for(var i = 0; i < elements.length; ++i)
|
|
||||||
try{
|
|
||||||
hljs.highlightElement(elements[i]);
|
|
||||||
}catch(err){
|
|
||||||
console.log(err.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.is_highlighted_languages.push(language);
|
|
||||||
}
|
|
||||||
document.body.appendChild(script);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</SCRIPT>
|
|
||||||
|
|
||||||
<H1>POSIX cat(1)</H1>
|
|
||||||
<H3>updated 2021-08-06</H3>
|
|
||||||
<HR ALIGN="left" SIZE="1" WIDTH="25%" />
|
|
||||||
<P><CODE>cat</CODE> on a POSIX or otherwise UNIX-like system is a program that exists to concatenate files; to “join” one file at its end to another at its start, and output that resulting file to standard output.</P>
|
|
||||||
<P>
|
|
||||||
<CODE>cat</CODE> was introduced in UNIX v1 to supercede the program pr which printed the contents of a single file to the screen (McIlroy); its first-edition manual page described cat as "about the easiest way to print a file" ("cat(1)").
|
|
||||||
<CODE>cat</CODE>’s modern, typical use is more or less the same; it’s often introduced to UNIX beginners as a method to print the contents of a file to the screen, which is why many implementations of <CODE>cat</CODE> include options that, while possibly useful, can be redundant - see the often-included <CODE>cat</CODE> <CODE>-e</CODE>, <CODE>-t</CODE>, and <CODE>-v</CODE> that replace the ends of lines, tabs, and invisible characters respectively with printing portrayals ("cat(1p)").
|
|
||||||
|
|
||||||
</P>
|
|
||||||
<P>
|
|
||||||
The POSIX standard as of 2003 requires only the option <CODE>-u</CODE> to be implemented, which prevents <CODE>cat</CODE> from buffering its output - on some systems, <CODE>cat</CODE> buffers its output in 512-byte blocks (McIlroy), similarly to <CODE>dd</CODE>’s default as defined by POSIX (“dd(1p)”), though most currently popular <CODE>cat</CODE> implementations do this by default and ignore the <CODE>-u</CODE> flag altogether (busybox, GNU coreutils).
|
|
||||||
POSIX doesn’t mandate buffering by default - specifically, <CODE>-u</CODE> <I>has</I> to guarantee that the output is unbuffered, but <CODE>cat</CODE> doesn't have to buffer it in the first place and can ignore <CODE>-u</CODE> in that case.
|
|
||||||
</P>
|
|
||||||
<P>This is a POSIX-compatible implementation of UNIX <CODE>cat</CODE> with no additional features nor buffered output in C:</P>
|
|
||||||
<INPUT ID="c_toggle" ONCLICK="window.load_highlighting('c');" TYPE="button" VALUE="Press this button to enable syntax highlighting within this code." />
|
|
||||||
<PRE><CODE CLASS="language-c" DATA-LANG="c">
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define STDIN_NAME "<stdin>"
|
|
||||||
#define STDOUT_NAME "<stdout>"
|
|
||||||
|
|
||||||
/* these are the predicted errors that could occur */
|
|
||||||
enum error_type{
|
|
||||||
FILE_ACCESS,
|
|
||||||
FILE_CLOSE,
|
|
||||||
FILE_WRITE
|
|
||||||
};
|
|
||||||
|
|
||||||
/* this is an error function that will print to standard error the error that
|
|
||||||
* occurred in the program and exit */
|
|
||||||
void
|
|
||||||
error(enum error_type type, char *argv0, char *file_name){
|
|
||||||
switch(type){
|
|
||||||
case FILE_ACCESS:
|
|
||||||
fprintf(stderr, "%s: %s: cannot open file\n", argv0, file_name);
|
|
||||||
break;
|
|
||||||
case FILE_CLOSE:
|
|
||||||
fprintf(stderr, "%s: %s: cannot close file\n", argv0, file_name);
|
|
||||||
break;
|
|
||||||
case FILE_WRITE:
|
|
||||||
fprintf(stderr, "%s: %s: cannot write to file\n", argv0, file_name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print input to output, returns 0 if successful and 1 if unsuccessful */
|
|
||||||
int
|
|
||||||
file_copy(FILE *input, FILE *output){
|
|
||||||
char c;
|
|
||||||
while((c = getc(input)) != EOF)
|
|
||||||
if(putc(c, output) == EOF)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[]){
|
|
||||||
/* the name of the file being printed (for diagnostics) */
|
|
||||||
char *file_name;
|
|
||||||
|
|
||||||
/* allocate this ahead of time */
|
|
||||||
char *stdin_file_name = STDIN_NAME;
|
|
||||||
|
|
||||||
/* the file pointer of the file being printed */
|
|
||||||
FILE *input;
|
|
||||||
|
|
||||||
/* this will always be stdout */
|
|
||||||
FILE *output = stdout;
|
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* whether or not options are being parsed */
|
|
||||||
int parsing_opts = 1;
|
|
||||||
|
|
||||||
/* usage with 0 arguments - print standard input to standard output */
|
|
||||||
if(argc == 1 && file_copy(stdin, stdout))
|
|
||||||
error(FILE_WRITE, argv[0], STDOUT_NAME);
|
|
||||||
else if(argc == 1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for(i = 1; i < argc; ++i){
|
|
||||||
/* parsing options */
|
|
||||||
|
|
||||||
/* after `--`, interpret `--`, `-`, and `-u` as literal
|
|
||||||
* filenames */
|
|
||||||
if(parsing_opts && !strcmp(argv[i], "--")){
|
|
||||||
parsing_opts = 0;
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* ignore `-u` if still parsing options */
|
|
||||||
}else if(parsing_opts && !strcmp(argv[i], "-u"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* take `-` to mean standard input if still parsing options */
|
|
||||||
else if(parsing_opts && !strcmp(argv[i], "-")){
|
|
||||||
file_name = stdin_file_name;
|
|
||||||
input = stdin;
|
|
||||||
|
|
||||||
/* non-option; open the file and make sure file_name points to
|
|
||||||
* the right string */
|
|
||||||
}else{
|
|
||||||
file_name = argv[i];
|
|
||||||
input = fopen(file_name, "r");
|
|
||||||
if(input == NULL)
|
|
||||||
error(FILE_ACCESS, argv[0], file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* print input to output */
|
|
||||||
if(file_copy(input, output))
|
|
||||||
error(FILE_WRITE, argv[0], STDOUT_NAME);
|
|
||||||
|
|
||||||
/* close input file if it's not stdin */
|
|
||||||
if(input != stdin && fclose(input))
|
|
||||||
error(FILE_CLOSE, argv[0], file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* exit successfully */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
</CODE></PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
This is also available at <A HREF="/knowledge/cat/cat.c">/knowledge/cat/cat.c on this website</A> as a plain .c file with which you can toy.
|
|
||||||
</P>
|
|
||||||
<P>It’s worth noting that this concept of cat as a utility that sequentially prints given files to standard output means <CODE>cat</CODE> can be replaced by a simple shell script that does the same using <CODE>dd</CODE> and <CODE>printf</CODE>; <CODE>cat</CODE> as defined by POSIX is actually totally redundant to other POSIX utilities. Here’s the shell script:</P>
|
|
||||||
<INPUT ID="shell_toggle" ONCLICK="window.load_highlighting('shell');" TYPE="button" VALUE="Press this button to enable syntax highlighting within this code." />
|
|
||||||
<PRE><CODE CLASS="language-shell" DATA-LANG="shell">
|
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# dd_ is used so that dd can easily be re-defined
|
|
||||||
dd_() { dd "$@"; }
|
|
||||||
|
|
||||||
# usage with 0 arguments - print standard input to standard output
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
dd_ 2>/dev/null
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
while [ -n "$1" ]; do
|
|
||||||
# parsing options
|
|
||||||
|
|
||||||
# after `--`, interpret `--`, `-`, and `-u` as literal filenames
|
|
||||||
[ "$1" = "--" ] && [ -z "$DONT_PARSE_ARGS" ] \
|
|
||||||
&& DONT_PARSE_ARGS=1 && shift 1 && continue \
|
|
||||||
|| true
|
|
||||||
|
|
||||||
# if `-u` specified and still parsing options, enable unbuffered output
|
|
||||||
# this is kind of a hack and a bit slow. technically it is buffered,
|
|
||||||
# just one byte at a time
|
|
||||||
[ "$1" = "-u" ] && [ -z "$DONT_PARSE_ARGS" ] \
|
|
||||||
&& dd_() { dd bs=1 "$@"; } && shift 1 && continue \
|
|
||||||
|| true
|
|
||||||
|
|
||||||
# take `-` to mean standard input if still parsing options
|
|
||||||
if [ "$1" = "-" ] && [ -z "$DONT_PARSE_ARGS" ]; then
|
|
||||||
dd_ </dev/stdin 2>/dev/null || exit $?
|
|
||||||
shift 1
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# print input to output
|
|
||||||
dd_ <"$1" 2>/dev/null || exit $?
|
|
||||||
|
|
||||||
shift 1
|
|
||||||
done
|
|
||||||
|
|
||||||
# exit successfully
|
|
||||||
exit 0
|
|
||||||
</CODE></PRE>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
It's worth noting that the <CODE>dd_</CODE> shell function in the above sample that allows for re-aliasing of <CODE>dd</CODE> to <CODE>dd bs=1</CODE> could be replaced with a shell variable <CODE>$DD</CODE> with the initial value <CODE>dd</CODE> and a changed value according to <CODE>-u</CODE> of <CODE>dd bs=1</CODE>.
|
|
||||||
However, <CODE>alias dd="dd bs=1"</CODE> would not work due to how shell aliases are parsed (ShellCheck).
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<P>
|
|
||||||
<CODE>cat</CODE> doesn't work well as a shell script though.
|
|
||||||
The script is relatively slow for short files and very slow for very large files (though <CODE>dd</CODE> itself should probably be used to copy large files from one medium to another anyway).
|
|
||||||
This is provided for educational purposes.
|
|
||||||
</P>
|
|
||||||
|
|
||||||
<H2>Cited media and further reading</H2><UL>
|
|
||||||
<LI>Articles<UL>
|
|
||||||
<LI><A HREF="https://www.cs.dartmouth.edu/~doug/reader.pdf">McIlroy, M. Douglas - “A Research Unix Reader”</A></LI>
|
|
||||||
<LI><A HREF="https://github.com/koalaman/shellcheck/wiki/SC2262">ShellCheck wiki page SC2262 ("This alias can't be defined and used in the same parsing unit. Use a function instead.")</A></LI>
|
|
||||||
</UL></LI>
|
|
||||||
<LI>Manual pages<UL>
|
|
||||||
<LI><A HREF="http://man.cat-v.org/unix-1st/1/cat">cat(1)</A> (UNIX v1)</LI>
|
|
||||||
<LI><A HREF="https://www.unix.com/man-page/posix/1posix/cat/">cat(1p)</A> (The Open Group, 2003)</LI>
|
|
||||||
<LI><A HREF="https://www.unix.com/man-page/posix/1posix/dd/">dd(1p)</A> (The Open Group, 2003)</LI>
|
|
||||||
<LI><A HREF="https://www.unix.com/man-page/POSIX/1posix/printf/">printf(1p)</A> (The Open Group, 2003)</LI>
|
|
||||||
</UL></LI>
|
|
||||||
<LI>Notable cat implementations<UL>
|
|
||||||
<LI>1979 - <A HREF="http://www.bell-labs.com/">Bell Labs</A>/<A HREF="https://en.wikipedia.org/wiki/Unix">UNIX v7</A> - <A HREF="https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/cat.c">/usr/src/cmd/cat.c</A></LI>
|
|
||||||
<LI>1992 - <A HREF="http://www.bell-labs.com/">Bell Labs</A>/<A HREF="https://9p.io/plan9/">Plan 9 from Bell Labs Fourth Edition</A> - <A HREF="https://github.com/plan9foundation/plan9/blob/main/sys/src/cmd/cat.c">/sys/src/cmd/cat.c</A></LI>
|
|
||||||
<LI><B>ongoing</B> started 1992 - <A HREF="https://www.gnu.org/">GNU</A>/<A HREF="https://www.gnu.org/software/coreutils/">coreutils</A> - <A HREF="https://git.savannah.gnu.org/cgit/coreutils.git/tree/src/cat.c">src/cat.c</A></LI>
|
|
||||||
<LI>1995 - <A HREF="https://www.berkeley.edu/">University of California, Berkeley</A>/<A HREF="https://en.wikipedia.org/wiki/Berkeley_Software_Distribution">4.4BSD-Lite2</A> - <A HREF="https://github.com/sergev/4.4BSD-Lite2/blob/master/usr/src/bin/cat/cat.c">/usr/src/bin/cat/cat.c</A></LI>
|
|
||||||
<LI><B>ongoing</B> forked from 4.4BSD-Lite2 - <A HREF="https://www.netbsd.org/">NetBSD</A>/<A HREF="https://github.com/NetBSD/src">src</A> - <A HREF="https://github.com/NetBSD/src/blob/trunk/bin/cat/cat.c">bin/cat/cat.c</A></LI>
|
|
||||||
<LI><B>ongoing</B> started 1995 - <A HREF="https://www.busybox.net/">busybox</A>/<A HREF="https://git.busybox.net/busybox/">busybox</A> - <A HREF="https://git.busybox.net/busybox/tree/coreutils/cat.c">coreutils/cat.c</A></LI>
|
|
||||||
</UL></LI>
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
<H2>Acknowledgements</H2><UL>
|
|
||||||
<LI>Content help<UL>
|
|
||||||
<LI>Miles</LI>
|
|
||||||
<LI>WeedSmokingJew</LI>
|
|
||||||
</UL></LI>
|
|
||||||
<LI>JavaScript help<UL>
|
|
||||||
<LI>adamz01h</H1>
|
|
||||||
<LI>wiresToGround</LI>
|
|
||||||
</UL></LI>
|
|
||||||
<LI>JavaScript libraries used<UL>
|
|
||||||
<LI><A HREF="https://highlightjs.org/">highlight.js</A></LI>
|
|
||||||
</UL></LI>
|
|
||||||
<LI>Sample code help<UL>
|
|
||||||
<LI>Ando_Bando</LI>
|
|
||||||
<LI>Miles</LI>
|
|
||||||
<LI>u/oh5nxo</LI>
|
|
||||||
<LI>WeedSmokingJew</LI>
|
|
||||||
</UL></LI>
|
|
||||||
</UL>
|
|
||||||
|
|
||||||
</BODY>
|
|
||||||
</HTML>
|
|
@ -9,7 +9,6 @@
|
|||||||
<A HREF="blah/" >blah/</A>,
|
<A HREF="blah/" >blah/</A>,
|
||||||
<A HREF="thegame" >thegame/</A>;
|
<A HREF="thegame" >thegame/</A>;
|
||||||
<B>knowledge</B>:
|
<B>knowledge</B>:
|
||||||
<A HREF="cat/" >cat(1)</A>,
|
|
||||||
<A HREF="c78/" >c78</A>,
|
<A HREF="c78/" >c78</A>,
|
||||||
<A HREF="software/">software</A>,
|
<A HREF="software/">software</A>,
|
||||||
<A HREF="x200t/" >X200T</A>;
|
<A HREF="x200t/" >X200T</A>;
|
||||||
|
@ -33,20 +33,103 @@ Non-standard, proprietary operating systems such as VMS, OS/2, Z/OS, and Microso
|
|||||||
Plan 9 from Bell Labs, due to its historical relationship with UNIX, will be mentioned when appropriate.
|
Plan 9 from Bell Labs, due to its historical relationship with UNIX, will be mentioned when appropriate.
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
<H2>UNIX</H2>
|
<H2 ID="unix">UNIX</H2>
|
||||||
<UL>
|
<UL>
|
||||||
<LI>_hyperlink(`https://en.wikipedia.org/wiki/Unix', `Unix') (Wikipedia)</LI>
|
<LI>_hyperlink(`https://en.wikipedia.org/wiki/Unix', `Unix') (Wikipedia)</LI>
|
||||||
<LI>_hyperlink(`https://github.com/dspinellis/unix-history-repo', `unix-history-repo') (GitHub)</LI>
|
<LI>_hyperlink(`https://github.com/dspinellis/unix-history-repo', `unix-history-repo') (GitHub)</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
<H2>POSIX</H2>
|
<H2 ID="posix">POSIX</H2>
|
||||||
|
<UL>
|
||||||
|
<LI>_hyperlink(`https://en.wikipedia.org/wiki/POSIX', `POSIX') (Wikipedia)</LI>
|
||||||
|
</UL>
|
||||||
|
|
||||||
|
<H3>cat(1)</H3>
|
||||||
|
<UL>
|
||||||
|
<LI><A HREF="https://en.wikipedia.org/wiki/Berkeley_Software_Distribution">4.4BSD-Lite2</A>/<A HREF="https://github.com/sergev/4.4BSD-Lite2/blob/master/usr/src/bin/cat/cat.c">usr/src/bin/cat/cat.c</A></LI>
|
||||||
|
<LI><A HREF="https://git.busybox.net/busybox/">busybox</A>/<A HREF="https://git.busybox.net/busybox/tree/coreutils/cat.c">coreutils/cat.c</A></LI>
|
||||||
|
<LI>_hyperlink(`http://man.cat-v.org/unix-1st/1/cat', `cat(1)') (UNIX v1)</LI>
|
||||||
|
<LI>_hyperlink(`https://www.unix.com/man-page/posix/1posix/cat/', `cat(1p)') (The Open Group, 2003)</LI>
|
||||||
|
<LI>_hyperlink(`http://harmful.cat-v.org/cat-v/', `UNIX Style, or cat -v Considered Harmful')</LI>
|
||||||
|
<LI>_hyperlink(`https://www.unix.com/man-page/posix/1posix/dd/', `dd(1p)') (The Open Group, 2003)</LI>
|
||||||
|
<LI>_hyperlink(`https://www.freebsd.org/', `FreeBSD')/_hyperlink(`https://github.com/freebsd/freebsd-src/blob/main/bin/cat/cat.c', `bin/cat/cat.c')</LI>
|
||||||
|
<LI><A HREF="https://www.gnu.org/software/coreutils/">GNU coreutils</A>/<A HREF="https://git.savannah.gnu.org/cgit/coreutils.git/tree/src/cat.c">src/cat.c</A></LI>
|
||||||
|
<LI>_hyperlink(`https://lyngvaer.no/log/cat-v-history', `The history of why cat -v is considered harmful')</LI>
|
||||||
|
<LI><A HREF="https://www.netbsd.org/">NetBSD</A>/<A HREF="https://github.com/NetBSD/src/blob/trunk/bin/cat/cat.c">bin/cat/cat.c</A></LI>
|
||||||
|
<LI><A HREF="https://9p.io/plan9/">Plan 9 from Bell Labs Fourth Edition</A>/<A HREF="https://github.com/plan9foundation/plan9/blob/main/sys/src/cmd/cat.c">sys/src/cmd/cat.c</A></LI>
|
||||||
|
<LI>_hyperlink(`https://www.unix.com/man-page/POSIX/1posix/printf/', `printf(1p)') (The Open Group, 2003)</LI>
|
||||||
|
<LI>_hyperlink(`https://harmful.cat-v.org/cat-v/unix_prog_design.pdf', `Program Design in the UNIX Environment')</LI>
|
||||||
|
<LI>_hyperlink(`https://www.cs.dartmouth.edu/~doug/reader.pdf', `A Research Unix Reader')</LI>
|
||||||
|
<LI><A HREF="https://en.wikipedia.org/wiki/Unix">UNIX v7</A>/<A HREF="https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/cat.c">usr/src/cmd/cat.c</A></LI>
|
||||||
|
<LI>Thanks to Miles and WeedSmokingJew for help with content.</LI>
|
||||||
|
<LI>Thanks to adamz01h and wiresToGround for help with the JavaScript that used to accompany this article (to facilitate syntax highlighting in code samples using _hyperlink(`https://highlightjs.org/', `highlight.js')).</LI>
|
||||||
|
<LI>Thanks to Ando_Bando, Miles, u/oh5nxo, and WeedSmokingJew for help with the accompanying code samples.</LI>
|
||||||
|
</UL>
|
||||||
|
<P>
|
||||||
|
_code(`cat(1)') is a program that exists to catenate files; to "join" one file at its end to another at its start.
|
||||||
|
</P>
|
||||||
|
<P>
|
||||||
|
_code(`cat(1)') was introduced in UNIX's first edition to succeed _code(`pr(1)'), which prints the contents of a single file to the screen.
|
||||||
|
Most use of _code(`cat(1)') is similar; it's often introduced to beginners as a means to print the contents of a file to the screen, which is why many implementations include options that modify output to make it easier to read on a display.
|
||||||
|
POSIX requires only _code(`-u') to be implemented, which guarantees output is unbuffered - on some systems output is buffered in 512-byte blocks, which is also the default of _code(`dd(1)'), though most current implementations (busybox, GNU coreutils) don't buffer output regardless.
|
||||||
|
Various implementations include _code(`-s') to strip duplicate blank lines (<CODE>cat "$@" | sed '/^\s*$/d'</CODE> would also work),
|
||||||
|
_code(`-n') to number lines (to which Pike and Kernighan offered <CODE>awk '{ print NR "\t" $0 }' "$@"</CODE> as a replacement)
|
||||||
|
and _code(`-b') to number non-blank lines (both cases for which _code(`nl(1)') was later made),
|
||||||
|
and _code(`-v') to mark invisible characters.
|
||||||
|
</P>
|
||||||
|
<P>
|
||||||
|
Additions to _code(`cat(1)') are controversial; Rob Pike and Brian Kernighan explain this in _italic(`Program Design in the UNIX Environment'), the paper that accompanied Rob Pike's presentation _italic(`UNIX Style, or cat -v Considered Harmful') at the 1983 USENIX Summer Conference.
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<P>
|
||||||
|
The following shell script is a POSIX-compliant implementation of _code(`cat(1)'):
|
||||||
|
</P>
|
||||||
|
|
||||||
|
<PRE>
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DD=dd
|
||||||
|
|
||||||
|
# usage with 0 arguments - print standard input to standard output
|
||||||
|
if test -z "$1"; then
|
||||||
|
dd 2>/dev/null
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
while test -n "$1"; do
|
||||||
|
# Parse options
|
||||||
|
|
||||||
|
if test -z "$DONT_PARSE_ARGS"
|
||||||
|
then case "$1" in
|
||||||
|
--)
|
||||||
|
DONT_PARSE_ARGS=1
|
||||||
|
shift; continue; ;;
|
||||||
|
-u)
|
||||||
|
DD="dd bs=1"
|
||||||
|
shift; continue; ;;
|
||||||
|
-)
|
||||||
|
$DD </dev/stdin 2>/dev/null
|
||||||
|
shift; continue; ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Print input to output.
|
||||||
|
$DD <"$1" 2>/dev/null
|
||||||
|
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
</PRE>
|
||||||
|
|
||||||
<H3 ID="echo">echo(1)</H3>
|
<H3 ID="echo">echo(1)</H3>
|
||||||
<UL>
|
<UL>
|
||||||
<LI>_hyperlink(`https://en.wikipedia.org/wiki/Echo_(command)', `echo') (Wikipedia)</LI>
|
<LI>_hyperlink(`https://en.wikipedia.org/wiki/Echo_(command)', `echo') (Wikipedia)</LI>
|
||||||
<LI>_hyperlink(`https://man7.org/linux/man-pages/man1/echo.1p.html', `echo(1p)') (man7)</LI>
|
<LI>_hyperlink(`https://man7.org/linux/man-pages/man1/echo.1p.html', `echo(1p)') (man7)</LI>
|
||||||
<LI><A HREF="https://www.netbsd.org/">NetBSD</A>/<A HREF="https://github.com/NetBSD/src/blob/trunk/bin/echo/echo.c">bin/echo/echo.sh</A></LI>
|
<LI><A HREF="https://www.netbsd.org/">NetBSD</A>/<A HREF="https://github.com/NetBSD/src/blob/trunk/bin/echo/echo.c">bin/echo/echo.sh</A></LI>
|
||||||
<LI><A HREF="https://www.in-ulm.de/~mascheck/various/echo+printf/">Variations in echo implementations</A></LI>
|
<LI>_hyperlink(`#unix', `UNIX v5')/<A HREF="https://www.tuhs.org/cgi-bin/utree.pl?file=V5/usr/source/s1/echo.c">usr/source/s1/echo.c</A></LI>
|
||||||
|
<LI>_hyperlink(`https://www.in-ulm.de/~mascheck/various/echo+printf/', `Variations in echo implementations')</LI>
|
||||||
</UL>
|
</UL>
|
||||||
<P>
|
<P>
|
||||||
Don't use _code(`echo(1)'), use _code(`printf(1)').
|
Don't use _code(`echo(1)'), use _code(`printf(1)').
|
||||||
@ -63,12 +146,13 @@ The following is an implementation of _code(`echo(1)') in the C programming lang
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 1; ; ) {
|
for(i = 1; ; ) {
|
||||||
printf("%s", argv[i]);
|
if(i >= argc)
|
||||||
++i;
|
|
||||||
if(i == argc) {
|
|
||||||
putchar('\n');
|
|
||||||
break;
|
break;
|
||||||
} else
|
printf("%s", argv[i]);
|
||||||
|
++i;
|
||||||
|
if(i == argc)
|
||||||
|
putchar('\n');
|
||||||
|
else
|
||||||
putchar(' ');
|
putchar(' ');
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -79,6 +163,9 @@ The following is an implementation of _code(`echo(1)') in shell.
|
|||||||
</P>
|
</P>
|
||||||
<PRE>
|
<PRE>
|
||||||
while :; do
|
while :; do
|
||||||
|
if test -z "$1"
|
||||||
|
then break
|
||||||
|
fi
|
||||||
printf "%s" "$1"
|
printf "%s" "$1"
|
||||||
`shift'
|
`shift'
|
||||||
if test -z "$1"; then
|
if test -z "$1"; then
|
||||||
@ -105,6 +192,14 @@ A traditional _code(`ed(1)') implementation is in plan9ports.
|
|||||||
I'm pretty sure some later UNIX-based OSes doubled the _code(`ed(1)') buffers, there's pretty much no downside to doing so in the modern era but it should be very easy to do yourself if it hasn't already been done (just double some of the array sizes in the beginning of _code(`ed.c')).
|
I'm pretty sure some later UNIX-based OSes doubled the _code(`ed(1)') buffers, there's pretty much no downside to doing so in the modern era but it should be very easy to do yourself if it hasn't already been done (just double some of the array sizes in the beginning of _code(`ed.c')).
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
|
<H3 ID="mkfifo">mkfifo(1)</H3>
|
||||||
|
<UL>
|
||||||
|
<LI>_hyperlink(`https://man.netbsd.org/mkfifo.1', `mkfifo(1)') (NetBSD)</LI>
|
||||||
|
<LI>_hyperlink(`https://man.netbsd.org/mkfifo.2', `mkfifo(2)') (NetBSD)</LI>
|
||||||
|
<LI>_hyperlink(`https://dev.to/0xbf/use-mkfifo-to-create-named-pipe-linux-tips-5bbk', `Use mkfifo to create named pipe')</LI>
|
||||||
|
<LI>_hyperlink(`https://unix.stackexchange.com/questions/433488/what-is-the-purpose-of-using-a-fifo-vs-a-temporary-file-or-a-pipe', `What is the purpose of using a FIFO vs a temporary file or a pipe?')</LI>
|
||||||
|
</UL>
|
||||||
|
|
||||||
<H3 ID="true">true(1)</H3>
|
<H3 ID="true">true(1)</H3>
|
||||||
<UL>
|
<UL>
|
||||||
<LI><A HREF="http://trillian.mit.edu/~jc/;-)/ATT_Copyright_true.html">CHAMBERS John - The /bin/true Command and Copyright</A></LI>
|
<LI><A HREF="http://trillian.mit.edu/~jc/;-)/ATT_Copyright_true.html">CHAMBERS John - The /bin/true Command and Copyright</A></LI>
|
||||||
@ -426,6 +521,10 @@ On systems without SystemD and with conflicting software, _code(`elogind(8)') ma
|
|||||||
Xenia was an entry for the Linux logo competition which Tux eventually won.
|
Xenia was an entry for the Linux logo competition which Tux eventually won.
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
|
<H2 ID="m4">m4</H2>
|
||||||
|
<UL>
|
||||||
|
<LI>_hyperlink(`https://mbreen.com/m4.html', `Notes on the M4 Macro Language')</LI>
|
||||||
|
</UL>
|
||||||
|
|
||||||
<H2>Make utility</H2>
|
<H2>Make utility</H2>
|
||||||
<P>
|
<P>
|
||||||
@ -552,6 +651,7 @@ _code(`gpart(8)') is a tool that scans a file (or block device presented as a fi
|
|||||||
<H3 ID="luks">LUKS</H3>
|
<H3 ID="luks">LUKS</H3>
|
||||||
<UL>
|
<UL>
|
||||||
<LI><A HREF="https://www.howtoforge.com/automatically-unlock-luks-encrypted-drives-with-a-keyfile/">Automatically Unlock LUKS Encrypted Drives With A Keyfile</A></LI>
|
<LI><A HREF="https://www.howtoforge.com/automatically-unlock-luks-encrypted-drives-with-a-keyfile/">Automatically Unlock LUKS Encrypted Drives With A Keyfile</A></LI>
|
||||||
|
<LI><A HREF="https://man.dragonflybsd.org/?command=cryptsetup§ion=8">cryptsetup(8)</A> (DragonFly Man Pages)</LI>
|
||||||
<LI><A HREF="https://wiki.gentoo.org/wiki/Dm-crypt">Dm-crypt</A> (Gentoo Wiki)</LI>
|
<LI><A HREF="https://wiki.gentoo.org/wiki/Dm-crypt">Dm-crypt</A> (Gentoo Wiki)</LI>
|
||||||
<LI><A HREF="https://www.cyberciti.biz/security/how-to-backup-and-restore-luks-header-on-linux/">How to backup and restore LUKS header on Linux</A></LI>
|
<LI><A HREF="https://www.cyberciti.biz/security/how-to-backup-and-restore-luks-header-on-linux/">How to backup and restore LUKS header on Linux</A></LI>
|
||||||
<LI><A HREF="https://devconnected.com/how-to-encrypt-partition-on-linux/">How To Encrypt Partition on Linux</A></LI>
|
<LI><A HREF="https://devconnected.com/how-to-encrypt-partition-on-linux/">How To Encrypt Partition on Linux</A></LI>
|
||||||
|
Loading…
Reference in New Issue
Block a user