From 4f7dc3b92e21022eeab817d3059b70da6be80863 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Fri, 1 Oct 2004 14:59:37 +0000 Subject: [PATCH] Going on --- src/ls.c | 150 ++++++++++++++++++++++++++++++++++++++--------------- src/uniq.c | 50 +++++++++++++----- 2 files changed, 145 insertions(+), 55 deletions(-) diff --git a/src/ls.c b/src/ls.c index f0f9303..2aec30e 100644 --- a/src/ls.c +++ b/src/ls.c @@ -5,13 +5,13 @@ #include #include #include -extern int optind; #include #include #include #include #include #include +#include /* FIXME */ @@ -20,24 +20,26 @@ extern int optind; /* Prefs */ typedef int Prefs; #define PREFS_a 1 -#define PREFS_d 2 -#define PREFS_l 4 -#define PREFS_1 8 -#define PREFS_R 16 +#define PREFS_c 2 +#define PREFS_d 4 +#define PREFS_l 8 +#define PREFS_u 16 +#define PREFS_1 32 +#define PREFS_R 64 static int _prefs_parse(Prefs * prefs, int argc, char * argv[]) { int o; memset(prefs, 0, sizeof(Prefs)); - while((o = getopt(argc, argv, "CFRadl1")) != -1) + while((o = getopt(argc, argv, "CFRacdlu1")) != -1) { switch(o) { case 'C': case 'F': fprintf(stderr, "%s%c%s", "ls: -", o, - ": Not yet implemented\n"); + ": Not implemented yet\n"); return 1; case 'R': *prefs |= PREFS_R; @@ -45,12 +47,20 @@ static int _prefs_parse(Prefs * prefs, int argc, char * argv[]) case 'a': *prefs |= PREFS_a; break; + case 'c': + *prefs -= *prefs & PREFS_u; + *prefs |= PREFS_c; + break; case 'd': *prefs |= PREFS_d; break; case 'l': *prefs |= PREFS_l; break; + case 'u': + *prefs -= *prefs & PREFS_c; + *prefs |= PREFS_u; + break; case '1': *prefs |= PREFS_1; break; @@ -125,15 +135,15 @@ static void slist_next(SList * slist) *slist = (*slist)->next; } -static void slist_last(SList * slist) +/* static void slist_last(SList * slist) { if(*slist == NULL) return; while((*slist)->next != NULL) *slist = (*slist)->next; -} +} */ -static int slist_append(SList * slist, void * data) +/* static int slist_append(SList * slist, void * data) { SList sl = *slist; @@ -145,7 +155,7 @@ static int slist_append(SList * slist, void * data) slist_last(&sl); sl->next = _slistcell_new(data, NULL); return sl->next != NULL ? 0 : 2; -} +} */ 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; } -static size_t slist_length(SList * slist) +/* static size_t slist_length(SList * slist) { SListCell * slc = *slist; size_t len; @@ -191,7 +201,7 @@ static size_t slist_length(SList * slist) for(len = 0; slc != NULL; len++) slc = slc->next; return len; -} +} */ /* ls */ @@ -200,6 +210,7 @@ static int _ls_directory_do(char * dir, Prefs * prefs); static int _ls_args(SList ** files, SList ** dirs); static int _is_directory(char * dir, 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) { SList * files; @@ -227,10 +238,12 @@ static int _ls(int argc, char * argv[], Prefs * prefs) } if(*prefs & PREFS_d) { - res += slist_insert_sorted(files, str, strcmp); + res += slist_insert_sorted(files, str, + (compare_func)strcmp); 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); return res == 1 ? 2 : res; @@ -252,6 +265,7 @@ static int _ls_directory_do(char * directory, Prefs * prefs) struct dirent * de; char * file = NULL; char * p; + int pos = 0; #ifdef DEBUG 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) return _ls_error(directory, 2); _ls_args(&files, &dirs); - readdir(dir); - readdir(dir); 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) + strlen(de->d_name) + 2)) == NULL) @@ -274,7 +292,8 @@ static int _ls_directory_do(char * directory, Prefs * prefs) file = p; sprintf(file, "%s/%s", directory, de->d_name); 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); 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_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) { int res = 0; res += _ls_do_files(directory, files, prefs); - res += _ls_do_dirs(directory, dirs, prefs); + res += _ls_do_dirs(dirs, prefs); 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 char * _long_owner(uid_t uid); 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) { SList cur; @@ -383,7 +402,7 @@ static int _ls_do_files_long(char * directory, SList * files, Prefs * prefs) char mode[11]; char * owner; char * group; - char * date; + char date[15]; #ifdef DEBUG 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)) { /* FIXME */ - if((p = realloc(file, strlen(directory) - + strlen(slist_data(&cur)) - + 2)) == NULL) + p = slist_data(&cur); + if((p = realloc(file, strlen(directory) + strlen(p) + 2)) + == NULL) { _ls_error("malloc", 0); continue; } 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) { _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); owner = _long_owner(st.st_uid); 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, - owner, group, st.st_size, date, - slist_data(&cur)); + owner, group, st.st_size, date, p); } free(file); return 0; @@ -421,10 +445,43 @@ static void _long_mode(char str[11], mode_t mode) { unsigned int i; - str[10] = '\0'; - /* FIXME */ - for(i = 0; i < 10; i++) + str[0] = '-'; + if(!S_ISREG(mode)) + { + 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] = '-'; + 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) @@ -445,10 +502,18 @@ static char * _long_group(gid_t gid) return grp->gr_name; } -static char * _long_date(time_t date) +static void _long_date(time_t date, char buf[15]) { - /* FIXME */ - return NULL; + struct tm tm; + 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) @@ -458,16 +523,12 @@ static int _ls_free(void * data, void * 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; SList cur; 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)) { dir = slist_data(&cur); @@ -483,7 +544,12 @@ static int _ls_do_dirs(char * directory, SList * dirs, Prefs * prefs) /* usage */ 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; } diff --git a/src/uniq.c b/src/uniq.c index d8c0e7d..b7d1190 100644 --- a/src/uniq.c +++ b/src/uniq.c @@ -19,9 +19,10 @@ * 0 success * else error(s) occured */ 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); -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 * outfp = stdout; @@ -34,7 +35,7 @@ static int _uniq(int opts, char * fields, int chars, char * in, char * out) fclose(infp); return _uniq_error(out, 2); } - ret = _uniq_do(opts, fields, chars, infp, outfp); + ret = _uniq_do(opts, fields, skip, infp, outfp); if(in == NULL) { fclose(infp); @@ -51,8 +52,8 @@ static int _uniq_error(char * message, int ret) return ret; } -static void _do_count(int opts, char * line, FILE * fp); -static int _uniq_do(int opts, char * fields, int chars, +static void _do_count(int opts, unsigned int skip, char * line, FILE * fp); +static int _uniq_do(int opts, char * fields, unsigned int skip, FILE * infp, FILE * outfp) { #define BUF 80 @@ -84,15 +85,16 @@ static int _uniq_do(int opts, char * fields, int chars, #ifdef DEBUG fprintf(stderr, "%s%s%s", "DEBUG: Got line \"", line, "\"\n"); #endif - _do_count(opts, line, outfp); + _do_count(opts, skip, line, outfp); line = NULL; len = 0; } - _do_count(opts, NULL, outfp); + _do_count(opts, skip, NULL, outfp); 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 unsigned int cnt = 1; @@ -102,7 +104,7 @@ static void _do_count(int opts, char * line, FILE * fp) lastline = line; return; } - if(line != NULL && strcmp(lastline, line) == 0) + if(line != NULL && _count_repeated(lastline, line, skip)) { cnt++; return; @@ -120,12 +122,29 @@ static void _do_count(int opts, char * line, FILE * fp) 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 */ static int _usage(void) { 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; } @@ -133,7 +152,8 @@ int main(int argc, char * argv[]) { int opts = 0; char * fields = NULL; - int chars = 0; + int skip = 0; + char * p; char * in = NULL; char * out = NULL; int o; @@ -148,11 +168,15 @@ int main(int argc, char * argv[]) case 'd': opts |= OPTS_d; break; + case 's': + skip = strtol(optarg, &p, 10); + if(*optarg == '\0' || *p != '\0' || skip < 0) + return _usage(); + break; case 'u': opts |= OPTS_u; break; case 'f': - case 's': fprintf(stderr, "%s%c%s", "uniq: -", o, ": Not implemented yet\n"); return _usage(); @@ -168,5 +192,5 @@ int main(int argc, char * argv[]) else if(argc - optind > 2) return _usage(); } - return _uniq(opts, fields, chars, in, out); + return _uniq(opts, fields, skip, in, out); }