Вот код:
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#define _GNU_SOURCE
#include <getopt.h>
void itoa(register unsigned long n, register char s[]);
void dchk(int f);
int ferr();
int usage();
int main(int argc, char** argv){
register int ch;
int longIndex;
register short sht, shn, shcc, num;
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, "ETAethun",longOpts,&longIndex))!= -1){
switch (ch) {
case 'n':
num = 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(1,"sysccat version 0.1\n",20);
_exit(0);
}
else usage();
}
}
argv+=optind;
argc-=optind;
if(argc==0)usage();
if(!sht&&!shn&&!shcc&&!num)for(int x=0;x<argc;++x){
int fd=open(argv[x],O_RDONLY);
if(fd<0)ferr();
dchk(fd);
char a;
while(read(fd,&a,1)>0)write(0,&a,1);
close(fd);
}
else for(int x=0;x<argc;++x){
int fd=open(argv[x],O_RDONLY);
if(fd<0)ferr();
dchk(fd);
if(num)write(0,"1: ",3);
register int i=1;
char a;
while(read(fd,&a,1)>0){
if(num&&a=='\n'){
if(read(fd,&a,1)==0){
if(shn)write(0,"$",1);
write(0,&a,1);
}
else{
if(shn)write(0,"$",1);
write(0,"\n",1);
char b[11];
++i;
itoa(i,b);
write(0,&b,strlen(b));
write(0,": ",2);
lseek(fd, -1, SEEK_CUR);
}
}
else if(sht&&a=='\t')write(1,"^I",2);
else if((shn==1)&&a=='\n')write(1,"$\n",2);
else if(shcc&&iscntrl(a)&&a!='\n'&&a!='\t'){
char c=a+64;
write(1,"^",1);
write(1,&c,1);
}
else write(1,&a,1);
}
close(fd);
}
_exit(0);
}
int usage(){
write(1,"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);
}
void itoa(register unsigned long n, register char s[]){
register short i,j;
register char c;
i=0;
do{
s[i++] = n % 10 + '0';
}while((n/=10)>0);
s[i]='\0';
for(i=0,j=strlen(s)-1;i<j;i++,j--){
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
int ferr(){
switch(errno){
case ENOENT:
write(0,"No such file or directory.\n",27);
break;
case EACCES:
write(0,"Access denied.\n",15);
break;
default:
write(0,"Unknown error\n",14);
break;
}
_exit(1);
}
void dchk(int f){
struct stat fs;
fstat(f,&fs);
if(S_ISDIR(fs.st_mode)){
write(0,"It's a directory.\n",18);
close(f);
_exit(1);
}
}