Код:
#define _LARGEFILE64_SOURCE
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#include "getopt.h"
#define block_size 4096
struct stat fs;
char* itoa(unsigned int val);
void dchk(int f);
int ferr();
int usage();
int main(int argc, char** argv){
register int ch, filenum;//filenum- FILE NUMber;
int longIndex;
register short sht=0, shn=0, shcc=0, num=0, num_nonblank=0;
//sht- SHow Tabulation; shn- SHow '\n' symbol(carriage return); shcc- SHow Control Characters; num- NUMber;
static const struct option longOpts[] = {
{ "show-nonprinting", no_argument, NULL, 'v' },
{ "show-tabs", no_argument, NULL, 'T' },
{ "show-ends", no_argument, NULL, 'E' },
{ "show-all", no_argument, NULL, 'A' },
{ "number", no_argument, NULL, 'n' },
{ "version", no_argument, NULL, 0 },
{ NULL, no_argument, NULL, 0 }
};
while((ch=getopt_long(argc, argv, "ETAethuni",longOpts,&longIndex))!= -1)
{
switch (ch)
{
case 'n':
num = 1;
break;
case 'i':
num_nonblank = 1;
break;
case 'E':
shn = 1;
break;
case 'T':
sht=1;
break;
case 'A':
{
shn=1;
sht=1;
shcc=1;
break;
}
case 'v':
shcc=1;
break;
case 'e':
{
shcc=1;
shn=1;
break;
}
case 't':
{
shcc=1;
sht=1;
break;
}
case '?':
case 'h':
usage();
case 'u':
break;
case 0:
if(strcmp( "version",longOpts[longIndex].name)==0)
{
write(STDOUT_FILENO,"sysccat version 0.1\n",20);
_exit(0);
}
else usage();
}
}
argv+=optind;
argc-=optind;
if(argc==0)usage();
if(!sht&&!shn&&!shcc&&!num)for(filenum=0;filenum<argc;++filenum)
{
int fd=open(argv[filenum],O_RDONLY);
if(fd<0)ferr();
fstat(fd,&fs);
dchk(fd);
if(S_ISCHR(fs.st_mode)||S_ISSOCK(fs.st_mode)||S_ISFIFO(fs.st_mode))
{
char c;
while(read(fd,&c,1)!=0)write(STDOUT_FILENO,&c,1);
}
else
{
off_t filesize=lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);
char c[block_size];
while(block_size<=filesize){
read(fd,&c,block_size);
write(STDOUT_FILENO,&c,block_size);
filesize-=block_size;
}
read(fd,&c,filesize);
write(STDOUT_FILENO,&c,filesize);
close(fd);
}
}
else for(filenum=0;filenum<argc;++filenum)
{
char a;
int fd=open(argv[filenum],O_RDONLY);
if(fd<0)ferr();
dchk(fd);
if(num)write(STDOUT_FILENO,"1: ",3);
register int numline=1;//numline- NUMber of Line
while(read(fd,&a,1)>0)
{
if(num&&a=='\n')
{
if(read(fd,&a,1)==0)
{
if(shn)write(STDOUT_FILENO,"$",1);
write(STDOUT_FILENO,&a,1);
}
else
{
if(shn)write(STDOUT_FILENO,"$",1);
write(STDOUT_FILENO,"\n",1);
++numline;
write(STDOUT_FILENO,itoa(numline),strlen(itoa(numline)));
write(STDOUT_FILENO,": ",2);
lseek(fd, -1, SEEK_CUR);
}
}
else if(sht&&a=='\t')write(STDOUT_FILENO,"^I",2);
else if(shn&&a=='\n')write(STDOUT_FILENO,"$\n",2);
else if(shcc&&iscntrl(a)&&a!='\n'&&a!='\t')
{
a+=64;
write(STDOUT_FILENO,"^",1);
write(STDOUT_FILENO,&a,1);
}
else write(STDOUT_FILENO,&a,1);
}
close(fd);
}
_exit(0);
}
int usage(){
write(STDOUT_FILENO,"Usage: sysccat [OPTIONS]... [FILE]...\n"
"-h or --help Displays this info and exit.\n"
"-n or --number Numbers the output strings.\n"
"--version Displays version and exit.\n"
"-v or --show-nonprinting Displays non-printing(control) characters, except for tabulation and carriage return/end-of-line symbols.\n"
"-A, -vET or --show-all Displays all control characters.\n"
"-t or -vT Displays all control characters, except for carriage return/end-of-line symbol.\n"
"-u Ignored; for POSIX compatibility.\n"
"-e or -vE Displays all control characters, except for tabulation symbol.\n",547);
_exit(0);
}
char* itoa(unsigned int val){
static char buf[11];
short i=10;
for(;val&&i;--i,val/=10)buf[i]=val%10+48;
return &buf[i+1];
}
int ferr(){
write(STDERR_FILENO,strerror(errno),strlen(strerror(errno)));
write(STDERR_FILENO,".\n",2);
_exit(1);
}
void dchk(int f){
if(S_ISDIR(fs.st_mode)){
write(STDERR_FILENO,"It's a directory.\n",18);
close(f);
_exit(1);
}
}
Блочный ввод-вывод нужно реализовать в части, начинающейся после //if any option defined Пока ничего путного в голову не пришло- бред один только лезет. Заранее спасибо.
P.S.: #include "getopt.h" ибо у меня свой getopt_long- не требующий #define _GNU_SOURCE, базирующийся на коде этой функции из Open и Net BSD.