Skip to content

Instantly share code, notes, and snippets.

@vergeev
Created September 11, 2016 07:43
Show Gist options
  • Save vergeev/a434ce4c20af225a61f570dc7862851f to your computer and use it in GitHub Desktop.
Save vergeev/a434ce4c20af225a61f570dc7862851f to your computer and use it in GitHub Desktop.
A copy of the command "tee" implemented using unix system calls.
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define MAX_READ 1024
#define MAX_OPEN 128
void printerr(char*);
int main(int argc, char *argv[]) {
int opt, i;
ssize_t bytes_read;
char buff[MAX_READ];
int fds[MAX_OPEN];
char* fnames[MAX_OPEN];
int flags = O_WRONLY | O_CREAT | O_TRUNC;
int opened = 0;
const mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
while ((opt = getopt(argc, argv, "a")) != -1)
switch (opt) {
case 'a':
flags ^= O_TRUNC;
flags |= O_APPEND;
}
/* open the files */
for (i = optind; i < argc; i++)
if (opened < MAX_OPEN) {
fnames[opened] = argv[i];
fds[opened] = open(fnames[opened], flags, perms);
if (fds[opened] == -1)
printerr(strcat(fnames[opened],
": can't be opened or created"));
else
opened++;
} else {
printerr(strcat(argv[i],
": too many files, skipping this and the rest"));
break;
}
/* read and write */
while((bytes_read = read(STDIN_FILENO, buff, MAX_READ)) > 0) {
if (write(STDOUT_FILENO, buff, bytes_read) < bytes_read)
printerr("error while writing to standard output");
for (i = 0; i < opened; i++)
if (write(fds[i], &buff, bytes_read) < bytes_read)
printerr(strcat(fnames[i],
": couldn't write some data"));
}
/* close the files */
for (i = 0; i < opened; i++)
if (close(fds[i]) == -1)
printerr(strcat(fnames[i],
": couldn't close, some data may be lost"));
if (bytes_read == -1)
return 1;
return 0;
}
void printerr(char* msg)
{
msg = strcat(msg, "\n");
write(STDERR_FILENO, msg, strlen(msg));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment