~~Exercise.#~~
#include
#include
int main(int argc, char *argv[]){
char buffer[256];
while(1){
int length = read(STDIN_FILENO, buffer, 256);
if(length == -1){
perror(NULL);
return 1;
}
if(length == 0)
break;
write(STDOUT_FILENO, buffer, length);
}
return 0;
}
~~Exercise.#~~
#include
#include
int readFile(){
char buffer[256];
while(1){
int length = read(STDIN_FILENO, buffer, 256);
if(length == -1){
perror(NULL);
return 1;
}
if(length == 0)
return 0;
write(STDOUT_FILENO, buffer, length);
}
}
int main(int argc, char *argv[]){
if(readFile())
return -1;
lseek(STDIN_FILENO, 0, SEEK_SET);
if(readFile())
return -1;
return 0;
}
~~Exercise.#~~
#include
#include
int main(int argc, char *argv[]){
char buffer[256];
while(1){
int length = read(4, buffer, 256);
if(length == -1){
perror(NULL);
return 1;
}
if(length == 0)
break;
write(STDOUT_FILENO, buffer, length);
}
return 0;
}
~~Exercise.#~~
#include
#include
#include
int main(int argc, char *argv[]){
int fd = open("/tmp/z", O_RDONLY);
if(fd == -1){
perror(NULL);
return 1;
}
char buffer[256];
while(1){
int length = read(fd, buffer, 256);
if(length == -1){
perror(NULL);
return 1;
}
if(length == 0)
break;
write(STDOUT_FILENO, buffer, length);
}
close(fd);
return 0;
}
~~Exercise.#~~
#include
#include
#include
int main(int argc, char *argv[]){
int fd = open(argv[1], O_RDONLY);
if(fd == -1){
perror(NULL);
return 1;
}
char buffer[256];
while(1){
int length = read(fd, buffer, 256);
if(length == -1){
perror(NULL);
return 1;
}
if(length == 0)
break;
write(STDOUT_FILENO, buffer, length);
}
close(fd);
return 0;
}
~~Exercise.#~~
#include
#include
#include
#include
#include
int main(int argc, char *argv[]){
int fd = open(argv[1], O_RDONLY);
if(fd == -1){
perror(NULL);
return 1;
}
int num = 1;
int printNumber = 1;
while(1){
char c;
int count = read(fd, &c, 1);
if(count == -1){
perror(NULL);
return 1;
}
if(count == 0)
break;
if(printNumber){
char numBuf[16];
sprintf(numBuf, "%5d ", num++);
write(STDOUT_FILENO, numBuf, strlen(numBuf));
printNumber=0;
}
write(STDOUT_FILENO, &c, 1);
if(c == '\n')
printNumber=1;
}
close(fd);
return 0;
}
++++ The program above is intentionally made simple rather than efficient; the program below is more efficient, but has a few more lines. |
#include
#include
#include
#include
void checkPrintNl(int *shallPrint, unsigned *number){
if(!*shallPrint)
return;
char buf[12];
sprintf(buf, "%5u ", (*number)++);
write(STDOUT_FILENO, buf, strlen(buf));
*shallPrint=0;
}
int main(int argc, char *argv[]){
int fd = open(argv[1], O_RDONLY);
if(fd == -1){
perror(NULL);
return 1;
}
int printLineNum = 1;
unsigned lineNum = 1;
while(1){
char buf[256];
int length = read(fd, buf, 256);
if(length == -1){
perror(NULL);
return 1;
}
if(length == 0)
break;
char *it = buf, *nlPos;
while( (nlPos = memchr(it, '\n', length)) ){
checkPrintNl(&printLineNum, &lineNum);
int partLen = nlPos+1-it;
write(STDOUT_FILENO, it, partLen);
length -= partLen;
it = nlPos+1;
printLineNum = 1;
}
if(length){
checkPrintNl(&printLineNum, &lineNum);
write(STDOUT_FILENO, it, length);
}
}
return 0;
}
++++
~~Exercise.#~~
#include
#include
#include
#include
#define CHECK(result, textOnFail) \
if(result == -1){ \
perror(textOnFail); \
return 1; \
}
int main(int argc, char *argv[]){
if(argc < 3){
write(STDERR_FILENO, "Not enough arguments\n", 21);
return 1;
}
int file1 = open(argv[1], O_RDONLY);
CHECK(file1, argv[1]);
int file2 = open(argv[2], O_RDONLY);
CHECK(file2, argv[2]);
while(1){
char buf1[256], buf2[256];
int len1 = read(file1, buf1, 256);
CHECK(len1, argv[1]);
int len2 = read(file2, buf2, 256);
CHECK(len2, argv[2]);
if(len1 != len2)
break;
if(len1 == 0){
write(STDOUT_FILENO, "Files have the same contents\n", 29);
return 0;
}
if(memcmp(buf1, buf2, len1))
break;
}
write(STDOUT_FILENO, "Files differ\n", 13);
return 0;
}
~~Exercise.#~~
#include
#include
#include
#include
int main(int argc, char *argv[]){
++argv; --argc; // get rid of program name; simplifies array indexes
int *file = malloc(sizeof(int) * argc);
int running = 0;
for(int i = 0; i < argc; ++i){
file[i] = open(argv[i], O_RDONLY);
if(file[i] == -1)
perror(argv[i]);
else
running = 1;
}
while(running){
running = 0;
for(int i = 0; i < argc; ++i){
while(file[i] != -1){
char c;
int l = read(file[i], &c, 1);
if(l <= 0){
if(l == -1)
perror(argv[i]);
close(file[i]);
file[i] = -1;
break;
}
if(c == '\n'){
running = 1;
break;
}
write(STDOUT_FILENO, &c, 1);
}
write(STDOUT_FILENO, (i == argc-1) ? "\n" : "\t", 1);
}
}
free(file);
return 0;
}
++++ The program above is intentionally made simple rather than efficient; the program below is more efficient, but has more lines. |
NB: speedup of this program vs the one above is way beyond 100x
#include
#include
#include
#include
#include
#include
/** A few words of explanation: each 'read' and 'write' call involves
* the operating system. Calling the OS is expensive. Thus, I/O is
* usually buffered. This program buffers both input and output, but
* to buffer output and still use OS API, one has to buffer I/O oneself.
*/
#define BUFSIZE 4096
// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ OUTPUT BUFFERING ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
struct { //< custom standard output buffer
char b[2*BUFSIZE];
size_t c;
} outBuf;
void flushOutput(){ //< writes out the standard output buffer
if(outBuf.c != write(STDOUT_FILENO, outBuf.b, outBuf.c)){
perror("writing to output failed");
exit(1);
}
outBuf.c = 0;
}
/** adds data to output buffer and outputs if buffer is sufficiently filled
* @warning: this relies on an assumption that count never exceeds BUFSIZE */
void bufferOutput(char *data, size_t count){
assert(count <= BUFSIZE);
memcpy(outBuf.b + outBuf.c, data, count);
if((outBuf.c += count) >= BUFSIZE)
flushOutput();
}
// ~ ~ ~ ~ ~ READING LINES FROM INPUT & BUFFERING INPUT ~ ~ ~ ~ ~
struct myFile { //< stores state & buffer of a file
char *name; //< used for diagnostics when read returns -1
int fd; //< once the file ends (or read fails), -1 is put here
char buf[BUFSIZE];
int pos; //< position where data in buf starts
int count; //< number of bytes in but from pos to end of data
};
/// reads from file to buffer,
/// @returns 0 if any data was read, else returns 1
int readChunk(struct myFile *f){
f->pos = 0;
f->count = read(f->fd, f->buf, BUFSIZE);
if(f->count<=0){
if(f->count == -1)
perror(f->name);
close(f->fd);
f->fd = -1;
return 1;
}
return 0;
}
/** reads and outputs a line from file,
* @returns 0 if there is any outstanding data in file, else returns 1 */
int readAndOutputLine(struct myFile *f){
while(1){
if(f->fd == -1)
return 1;
if(f->count == 0)
if(readChunk(f))
return 1;
char *nlPos, *startPos = f->buf+f->pos;
if( (nlPos = memchr(startPos, '\n', f->count)) ){
int partLen = nlPos-startPos;
bufferOutput(startPos, partLen);
f->pos += partLen+1;
f->count -= partLen+1;
if(f->count)
return 0;
return readChunk(f);
}
bufferOutput(startPos, f->count);
f->count = 0;
}
}
// ~ ~ ~ ~ ~ OPENING FILES, LOOPING THROUGH LINES ~ ~ ~ ~ ~
int main(int argc, char *argv[]){
++argv; --argc; // get rid of program name; simplifies array indexes
struct myFile *myFiles = malloc(sizeof(myFiles) * argc);
int allFilesEof = 1;
for(int i = 0 ; i < argc; ++i){
myFiles[i].fd = open(argv[i], O_RDONLY);
if(myFiles[i].fd == -1)
perror(argv[i]);
else {
myFiles[i].name = argv[i];
allFilesEof &= readChunk(myFiles+i);
}
}
while(!allFilesEof){
allFilesEof = readAndOutputLine(myFiles);
for(int i = 1 ; i < argc; ++i){
bufferOutput("\t", 1);
allFilesEof &= readAndOutputLine(myFiles+i);
}
bufferOutput("\n", 1);
}
free(myFiles);
flushOutput();
return 0;
}
++++
~~Exercise.#~~
#include
#include
#include
#include
void handleSignal(int num) {
write(2, "Shutting down...\n", 17);
exit(1);
}
int main() {
signal(SIGINT, handleSignal);
while (1)
getchar();
}
~~Exercise.#~~
#include
#include
#include
#include
#include
#include
void writeDateTo(int fd) {
struct timespec now;
char buf[21];
clock_gettime(CLOCK_REALTIME, &now);
buf[20] = '\n';
for (int i = 0; i < 10; ++i, now.tv_nsec /= 10)
buf[19 - i] = '0' + now.tv_nsec % 10;
buf[10] = '.';
for (int i = 0; i < 10; ++i, now.tv_sec /= 10)
buf[9 - i] = '0' + now.tv_sec % 10;
write(fd, buf, 21);
}
void handleSignal(int num) {
int fd = open("signal_log", O_WRONLY | O_APPEND | O_CREAT, 0666);
writeDateTo(fd);
close(fd);
}
int main() {
signal(SIGUSR1, handleSignal);
while (1)
getchar();
}
~~META:
language = en
~~