This commit is contained in:
Pierre Pronchery 2004-10-01 14:59:37 +00:00
parent 65c7504898
commit 4f7dc3b92e
2 changed files with 145 additions and 55 deletions

150
src/ls.c
View File

@ -5,13 +5,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
extern int optind;
#include <dirent.h> #include <dirent.h>
#include <stdlib.h> #include <stdlib.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h>
/* FIXME */ /* FIXME */
@ -20,24 +20,26 @@ extern int optind;
/* Prefs */ /* Prefs */
typedef int Prefs; typedef int Prefs;
#define PREFS_a 1 #define PREFS_a 1
#define PREFS_d 2 #define PREFS_c 2
#define PREFS_l 4 #define PREFS_d 4
#define PREFS_1 8 #define PREFS_l 8
#define PREFS_R 16 #define PREFS_u 16
#define PREFS_1 32
#define PREFS_R 64
static int _prefs_parse(Prefs * prefs, int argc, char * argv[]) static int _prefs_parse(Prefs * prefs, int argc, char * argv[])
{ {
int o; int o;
memset(prefs, 0, sizeof(Prefs)); memset(prefs, 0, sizeof(Prefs));
while((o = getopt(argc, argv, "CFRadl1")) != -1) while((o = getopt(argc, argv, "CFRacdlu1")) != -1)
{ {
switch(o) switch(o)
{ {
case 'C': case 'C':
case 'F': case 'F':
fprintf(stderr, "%s%c%s", "ls: -", o, fprintf(stderr, "%s%c%s", "ls: -", o,
": Not yet implemented\n"); ": Not implemented yet\n");
return 1; return 1;
case 'R': case 'R':
*prefs |= PREFS_R; *prefs |= PREFS_R;
@ -45,12 +47,20 @@ static int _prefs_parse(Prefs * prefs, int argc, char * argv[])
case 'a': case 'a':
*prefs |= PREFS_a; *prefs |= PREFS_a;
break; break;
case 'c':
*prefs -= *prefs & PREFS_u;
*prefs |= PREFS_c;
break;
case 'd': case 'd':
*prefs |= PREFS_d; *prefs |= PREFS_d;
break; break;
case 'l': case 'l':
*prefs |= PREFS_l; *prefs |= PREFS_l;
break; break;
case 'u':
*prefs -= *prefs & PREFS_c;
*prefs |= PREFS_u;
break;
case '1': case '1':
*prefs |= PREFS_1; *prefs |= PREFS_1;
break; break;
@ -125,15 +135,15 @@ static void slist_next(SList * slist)
*slist = (*slist)->next; *slist = (*slist)->next;
} }
static void slist_last(SList * slist) /* static void slist_last(SList * slist)
{ {
if(*slist == NULL) if(*slist == NULL)
return; return;
while((*slist)->next != NULL) while((*slist)->next != NULL)
*slist = (*slist)->next; *slist = (*slist)->next;
} } */
static int slist_append(SList * slist, void * data) /* static int slist_append(SList * slist, void * data)
{ {
SList sl = *slist; SList sl = *slist;
@ -145,7 +155,7 @@ static int slist_append(SList * slist, void * data)
slist_last(&sl); slist_last(&sl);
sl->next = _slistcell_new(data, NULL); sl->next = _slistcell_new(data, NULL);
return sl->next != NULL ? 0 : 2; return sl->next != NULL ? 0 : 2;
} } */
static void slist_apply(SList * slist, int (*func)(void *, void *), void * user) static void slist_apply(SList * slist, int (*func)(void *, void *), void * user)
{ {
@ -183,7 +193,7 @@ static int slist_insert_sorted(SList * slist, void * data,
return 0; return 0;
} }
static size_t slist_length(SList * slist) /* static size_t slist_length(SList * slist)
{ {
SListCell * slc = *slist; SListCell * slc = *slist;
size_t len; size_t len;
@ -191,7 +201,7 @@ static size_t slist_length(SList * slist)
for(len = 0; slc != NULL; len++) for(len = 0; slc != NULL; len++)
slc = slc->next; slc = slc->next;
return len; return len;
} } */
/* ls */ /* ls */
@ -200,6 +210,7 @@ static int _ls_directory_do(char * dir, Prefs * prefs);
static int _ls_args(SList ** files, SList ** dirs); static int _ls_args(SList ** files, SList ** dirs);
static int _is_directory(char * dir, Prefs * prefs); static int _is_directory(char * dir, Prefs * prefs);
static int _ls_do(char * directory, SList * files, SList * dirs, Prefs * prefs); static int _ls_do(char * directory, SList * files, SList * dirs, Prefs * prefs);
typedef int (*compare_func)(void*, void*);
static int _ls(int argc, char * argv[], Prefs * prefs) static int _ls(int argc, char * argv[], Prefs * prefs)
{ {
SList * files; SList * files;
@ -227,10 +238,12 @@ static int _ls(int argc, char * argv[], Prefs * prefs)
} }
if(*prefs & PREFS_d) if(*prefs & PREFS_d)
{ {
res += slist_insert_sorted(files, str, strcmp); res += slist_insert_sorted(files, str,
(compare_func)strcmp);
continue; continue;
} }
res += slist_insert_sorted(j ? dirs : files, str, strcmp); res += slist_insert_sorted(j ? dirs : files, str,
(compare_func)strcmp);
} }
res += _ls_do(NULL, files, dirs, prefs); res += _ls_do(NULL, files, dirs, prefs);
return res == 1 ? 2 : res; return res == 1 ? 2 : res;
@ -252,6 +265,7 @@ static int _ls_directory_do(char * directory, Prefs * prefs)
struct dirent * de; struct dirent * de;
char * file = NULL; char * file = NULL;
char * p; char * p;
int pos = 0;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "_ls_directory_do(%s, ...)\n", directory); fprintf(stderr, "_ls_directory_do(%s, ...)\n", directory);
@ -259,11 +273,15 @@ static int _ls_directory_do(char * directory, Prefs * prefs)
if((dir = opendir(directory)) == NULL) if((dir = opendir(directory)) == NULL)
return _ls_error(directory, 2); return _ls_error(directory, 2);
_ls_args(&files, &dirs); _ls_args(&files, &dirs);
readdir(dir);
readdir(dir);
while((de = readdir(dir)) != NULL) while((de = readdir(dir)) != NULL)
{ {
slist_insert_sorted(files, strdup(de->d_name), strcmp); pos++;
if(*(de->d_name) == '.' && !(*prefs & PREFS_a))
continue;
slist_insert_sorted(files, strdup(de->d_name),
(compare_func)strcmp);
if(pos <= 2)
continue;
if((p = realloc(file, strlen(directory) if((p = realloc(file, strlen(directory)
+ strlen(de->d_name) + strlen(de->d_name)
+ 2)) == NULL) + 2)) == NULL)
@ -274,7 +292,8 @@ static int _ls_directory_do(char * directory, Prefs * prefs)
file = p; file = p;
sprintf(file, "%s/%s", directory, de->d_name); sprintf(file, "%s/%s", directory, de->d_name);
if((*prefs & PREFS_R) && _is_directory(file, prefs) == 1) if((*prefs & PREFS_R) && _is_directory(file, prefs) == 1)
slist_insert_sorted(dirs, strdup(file), strcmp); slist_insert_sorted(dirs, strdup(file),
(compare_func)strcmp);
} }
free(file); free(file);
closedir(dir); closedir(dir);
@ -304,13 +323,13 @@ static int _is_directory(char * file, Prefs * prefs)
} }
static int _ls_do_files(char * directory, SList * files, Prefs * prefs); static int _ls_do_files(char * directory, SList * files, Prefs * prefs);
static int _ls_do_dirs(char * directory, SList * dirs, Prefs * prefs); static int _ls_do_dirs(SList * dirs, Prefs * prefs);
static int _ls_do(char * directory, SList * files, SList * dirs, Prefs * prefs) static int _ls_do(char * directory, SList * files, SList * dirs, Prefs * prefs)
{ {
int res = 0; int res = 0;
res += _ls_do_files(directory, files, prefs); res += _ls_do_files(directory, files, prefs);
res += _ls_do_dirs(directory, dirs, prefs); res += _ls_do_dirs(dirs, prefs);
return res; return res;
} }
@ -373,7 +392,7 @@ static int _ls_do_files_short(SList * files, Prefs * prefs)
static void _long_mode(char str[11], mode_t mode); static void _long_mode(char str[11], mode_t mode);
static char * _long_owner(uid_t uid); static char * _long_owner(uid_t uid);
static char * _long_group(gid_t gid); static char * _long_group(gid_t gid);
static char * _long_date(time_t date); static void _long_date(time_t date, char buf[15]);
static int _ls_do_files_long(char * directory, SList * files, Prefs * prefs) static int _ls_do_files_long(char * directory, SList * files, Prefs * prefs)
{ {
SList cur; SList cur;
@ -383,7 +402,7 @@ static int _ls_do_files_long(char * directory, SList * files, Prefs * prefs)
char mode[11]; char mode[11];
char * owner; char * owner;
char * group; char * group;
char * date; char date[15];
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "DEBUG _ls_do_files_long(%s, ...)\n", directory); fprintf(stderr, "DEBUG _ls_do_files_long(%s, ...)\n", directory);
@ -391,15 +410,16 @@ static int _ls_do_files_long(char * directory, SList * files, Prefs * prefs)
for(cur = *files; cur != NULL; slist_next(&cur)) for(cur = *files; cur != NULL; slist_next(&cur))
{ {
/* FIXME */ /* FIXME */
if((p = realloc(file, strlen(directory) p = slist_data(&cur);
+ strlen(slist_data(&cur)) if((p = realloc(file, strlen(directory) + strlen(p) + 2))
+ 2)) == NULL) == NULL)
{ {
_ls_error("malloc", 0); _ls_error("malloc", 0);
continue; continue;
} }
file = p; file = p;
sprintf(file, "%s/%s", directory, slist_data(&cur)); p = slist_data(&cur);
sprintf(file, "%s/%s", directory, p);
if(stat(file, &st) != 0) if(stat(file, &st) != 0)
{ {
_ls_error(file, 0); _ls_error(file, 0);
@ -408,10 +428,14 @@ static int _ls_do_files_long(char * directory, SList * files, Prefs * prefs)
_long_mode(mode, st.st_mode); _long_mode(mode, st.st_mode);
owner = _long_owner(st.st_uid); owner = _long_owner(st.st_uid);
group = _long_group(st.st_gid); group = _long_group(st.st_gid);
date = _long_date(st.st_mtime); if(*prefs & PREFS_u)
_long_date(st.st_atime, date);
else if(*prefs & PREFS_c)
_long_date(st.st_ctime, date);
else
_long_date(st.st_mtime, date);
printf("%s %u %s %s %lu %s %s\n", mode, st.st_nlink, printf("%s %u %s %s %lu %s %s\n", mode, st.st_nlink,
owner, group, st.st_size, date, owner, group, st.st_size, date, p);
slist_data(&cur));
} }
free(file); free(file);
return 0; return 0;
@ -421,10 +445,43 @@ static void _long_mode(char str[11], mode_t mode)
{ {
unsigned int i; unsigned int i;
str[10] = '\0'; str[0] = '-';
/* FIXME */ if(!S_ISREG(mode))
for(i = 0; i < 10; i++) {
if(S_ISLNK(mode))
str[0] = 'l';
else if(S_ISBLK(mode))
str[0] = 'b';
else if(S_ISCHR(mode))
str[0] = 'c';
else if(S_ISFIFO(mode))
str[0] = 'p';
else if(S_ISDIR(mode))
str[0] = 'd';
}
for(i = 1; i < 10; i++)
str[i] = '-'; str[i] = '-';
if(mode & S_IRUSR)
str[1] = 'r';
if(mode & S_IWUSR)
str[2] = 'w';
if(mode & S_IXUSR)
str[3] = (mode & S_ISUID ? 's' : 'x');
else if(mode & S_ISUID)
str[3] = 'S';
if(mode & S_IRGRP)
str[4] = 'r';
if(mode & S_IWGRP)
str[5] = 'w';
if(mode & S_IXGRP)
str[6] = 'x';
if(mode & S_IROTH)
str[7] = 'r';
if(mode & S_IWOTH)
str[8] = 'w';
if(mode & S_IXOTH)
str[9] = 'x';
str[10] = '\0';
} }
static char * _long_owner(uid_t uid) static char * _long_owner(uid_t uid)
@ -445,10 +502,18 @@ static char * _long_group(gid_t gid)
return grp->gr_name; return grp->gr_name;
} }
static char * _long_date(time_t date) static void _long_date(time_t date, char buf[15])
{ {
/* FIXME */ struct tm tm;
return NULL; static time_t sixmonths = -1;
if(sixmonths == -1)
sixmonths = time(NULL) - 15552000;
localtime_r(&date, &tm);
if(date < sixmonths)
strftime(buf, 14, "%b %e %Y", &tm);
else
strftime(buf, 14, "%b %e %H:%M", &tm);
} }
static int _ls_free(void * data, void * user) static int _ls_free(void * data, void * user)
@ -458,16 +523,12 @@ static int _ls_free(void * data, void * user)
user = user; user = user;
} }
static int _ls_do_dirs(char * directory, SList * dirs, Prefs * prefs) static int _ls_do_dirs(SList * dirs, Prefs * prefs)
{ {
int res = 0; int res = 0;
SList cur; SList cur;
char * dir = NULL; char * dir = NULL;
char * p;
#ifdef DEBUG
fprintf(stderr, "DEBUG _ls_do_dirs(%s, ...)\n", directory);
#endif
for(cur = *dirs; cur != NULL; slist_next(&cur)) for(cur = *dirs; cur != NULL; slist_next(&cur))
{ {
dir = slist_data(&cur); dir = slist_data(&cur);
@ -483,7 +544,12 @@ static int _ls_do_dirs(char * directory, SList * dirs, Prefs * prefs)
/* usage */ /* usage */
static int _usage(void) static int _usage(void)
{ {
fprintf(stderr, "%s", "Usage: ls [-CFRadl1]\n"); fprintf(stderr, "%s", "Usage: ls [-CFRacdilqrtu1][-H | -L]\n\
-R recursively list subdirectories encountered\n\
-a write out all hidden directory entries\n\
-c use time of last modification of file status\n\
-l write out in long format\n\
-u use time of last access\n");
return 1; return 1;
} }

View File

@ -19,9 +19,10 @@
* 0 success * 0 success
* else error(s) occured */ * else error(s) occured */
static int _uniq_error(char * message, int ret); static int _uniq_error(char * message, int ret);
static int _uniq_do(int opts, char * fields, int chars, static int _uniq_do(int opts, char * fields, unsigned int skip,
FILE * infp, FILE * outfp); FILE * infp, FILE * outfp);
static int _uniq(int opts, char * fields, int chars, char * in, char * out) static int _uniq(int opts, char * fields, unsigned int skip,
char * in, char * out)
{ {
FILE * infp = stdin; FILE * infp = stdin;
FILE * outfp = stdout; FILE * outfp = stdout;
@ -34,7 +35,7 @@ static int _uniq(int opts, char * fields, int chars, char * in, char * out)
fclose(infp); fclose(infp);
return _uniq_error(out, 2); return _uniq_error(out, 2);
} }
ret = _uniq_do(opts, fields, chars, infp, outfp); ret = _uniq_do(opts, fields, skip, infp, outfp);
if(in == NULL) if(in == NULL)
{ {
fclose(infp); fclose(infp);
@ -51,8 +52,8 @@ static int _uniq_error(char * message, int ret)
return ret; return ret;
} }
static void _do_count(int opts, char * line, FILE * fp); static void _do_count(int opts, unsigned int skip, char * line, FILE * fp);
static int _uniq_do(int opts, char * fields, int chars, static int _uniq_do(int opts, char * fields, unsigned int skip,
FILE * infp, FILE * outfp) FILE * infp, FILE * outfp)
{ {
#define BUF 80 #define BUF 80
@ -84,15 +85,16 @@ static int _uniq_do(int opts, char * fields, int chars,
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "%s%s%s", "DEBUG: Got line \"", line, "\"\n"); fprintf(stderr, "%s%s%s", "DEBUG: Got line \"", line, "\"\n");
#endif #endif
_do_count(opts, line, outfp); _do_count(opts, skip, line, outfp);
line = NULL; line = NULL;
len = 0; len = 0;
} }
_do_count(opts, NULL, outfp); _do_count(opts, skip, NULL, outfp);
return 0; return 0;
} }
static void _do_count(int opts, char * line, FILE * fp) static int _count_repeated(char * lastline, char * line, unsigned int skip);
static void _do_count(int opts, unsigned int skip, char * line, FILE * fp)
{ {
static char * lastline = NULL; static char * lastline = NULL;
static unsigned int cnt = 1; static unsigned int cnt = 1;
@ -102,7 +104,7 @@ static void _do_count(int opts, char * line, FILE * fp)
lastline = line; lastline = line;
return; return;
} }
if(line != NULL && strcmp(lastline, line) == 0) if(line != NULL && _count_repeated(lastline, line, skip))
{ {
cnt++; cnt++;
return; return;
@ -120,12 +122,29 @@ static void _do_count(int opts, char * line, FILE * fp)
cnt = 1; cnt = 1;
} }
/* PRE line and lastline are valid strings
* POST */
static int _count_repeated(char * lastline, char * line, unsigned int skip)
{
if(strlen(lastline) < skip)
return strlen(line) < skip;
if(strlen(line) < skip)
return 0;
if(strcmp(&lastline[skip], &line[skip]) == 0)
return 1;
return 0;
}
/* usage */ /* usage */
static int _usage(void) static int _usage(void)
{ {
fprintf(stderr, "%s", "Usage: uniq [-c|-d|-u][-f fields][-s char]\ fprintf(stderr, "%s", "Usage: uniq [-c|-d|-u][-f fields][-s char]\
[input_file [output_file]]\n"); [input_file [output_file]]\n\
-c precede each output line with a count of the repetitions for the line\n\
-d suppress the writing of lines that are not repeated\n\
-s ignore the first char characters when doing comparisons\n\
-u suppress the writing of lines that are repeated\n");
return 1; return 1;
} }
@ -133,7 +152,8 @@ int main(int argc, char * argv[])
{ {
int opts = 0; int opts = 0;
char * fields = NULL; char * fields = NULL;
int chars = 0; int skip = 0;
char * p;
char * in = NULL; char * in = NULL;
char * out = NULL; char * out = NULL;
int o; int o;
@ -148,11 +168,15 @@ int main(int argc, char * argv[])
case 'd': case 'd':
opts |= OPTS_d; opts |= OPTS_d;
break; break;
case 's':
skip = strtol(optarg, &p, 10);
if(*optarg == '\0' || *p != '\0' || skip < 0)
return _usage();
break;
case 'u': case 'u':
opts |= OPTS_u; opts |= OPTS_u;
break; break;
case 'f': case 'f':
case 's':
fprintf(stderr, "%s%c%s", "uniq: -", o, fprintf(stderr, "%s%c%s", "uniq: -", o,
": Not implemented yet\n"); ": Not implemented yet\n");
return _usage(); return _usage();
@ -168,5 +192,5 @@ int main(int argc, char * argv[])
else if(argc - optind > 2) else if(argc - optind > 2)
return _usage(); return _usage();
} }
return _uniq(opts, fields, chars, in, out); return _uniq(opts, fields, skip, in, out);
} }