uuprog
diff ls.c @ 0:4f628556fa3e
uuprog initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 25 Aug 2011 08:53:01 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ls.c Thu Aug 25 08:53:01 2011 +0300 1.3 @@ -0,0 +1,313 @@ 1.4 +/*! gcc -pedantic -Wall -g -o ls ls.c */ 1.5 +#include <stdio.h> 1.6 +#include <stdlib.h> 1.7 +#include <string.h> 1.8 +#include <errno.h> 1.9 +#include <time.h> 1.10 +#include <unistd.h> 1.11 +#include <fcntl.h> 1.12 +#include <dirent.h> 1.13 +#include <pwd.h> 1.14 +#include <grp.h> 1.15 +#include <sys/types.h> 1.16 +#include <sys/stat.h> 1.17 + 1.18 +enum {SORT_NONE, SORT_NAME}; 1.19 + 1.20 +enum { 1.21 + OPT_LONG = 1, 1.22 + OPT_ALL = 2, 1.23 + OPT_DIR = 4, 1.24 + OPT_CLASS = 8, 1.25 + OPT_HUMAN = 16, 1.26 + OPT_INODES = 32 1.27 +}; 1.28 + 1.29 +int proc_opt(char opt); 1.30 +int ls_dir(char *dir); 1.31 + 1.32 +unsigned int flags = 0; 1.33 +int sort_by = SORT_NAME; 1.34 +int term_col = 80; /* TODO: detect columns */ 1.35 + 1.36 +int main(int argc, char **argv) 1.37 +{ 1.38 + int i, did_one = 0; 1.39 + 1.40 + for(i=1; i<argc; i++) { 1.41 + if(argv[i][0] == '-') { 1.42 + char *ptr = argv[i] + 1; 1.43 + while(ptr && *ptr) { 1.44 + if(proc_opt(*ptr++) == -1) { 1.45 + fprintf(stderr, "%s: invalid option -- %c\n", argv[0], *(ptr - 1)); 1.46 + return 1; 1.47 + } 1.48 + } 1.49 + } else { 1.50 + printf("%s:\n", argv[i]); 1.51 + if(ls_dir(argv[i]) == -1) { 1.52 + fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i], strerror(errno)); 1.53 + } 1.54 + did_one = 1; 1.55 + } 1.56 + } 1.57 + 1.58 + if(!did_one) { 1.59 + ls_dir("."); 1.60 + } 1.61 + 1.62 + return 0; 1.63 +} 1.64 + 1.65 +int proc_opt(char opt) 1.66 +{ 1.67 + switch(opt) { 1.68 + case 'a': 1.69 + flags |= OPT_ALL; 1.70 + break; 1.71 + 1.72 + case 'l': 1.73 + flags |= OPT_LONG; 1.74 + break; 1.75 + 1.76 + case 'F': 1.77 + flags |= OPT_CLASS; 1.78 + break; 1.79 + 1.80 + case 'h': 1.81 + flags |= OPT_HUMAN; 1.82 + break; 1.83 + 1.84 + case 'i': 1.85 + flags |= OPT_INODES; 1.86 + break; 1.87 + 1.88 + default: 1.89 + return -1; 1.90 + } 1.91 + return 0; 1.92 +} 1.93 + 1.94 +struct entry { 1.95 + char *name; 1.96 + struct stat st; 1.97 + struct entry *next; 1.98 +}; 1.99 + 1.100 +int print_entry(struct entry *ent) 1.101 +{ 1.102 + int len = strlen(ent->name); 1.103 + 1.104 + if(flags & OPT_LONG) { 1.105 + int i; 1.106 + struct passwd *pwd; 1.107 + struct group *grp; 1.108 + char tmbuf[128]; 1.109 + 1.110 + switch(ent->st.st_mode & S_IFMT) { 1.111 + case S_IFSOCK: 1.112 + putchar('s'); 1.113 + break; 1.114 + case S_IFLNK: 1.115 + putchar('l'); 1.116 + break; 1.117 + case S_IFBLK: 1.118 + putchar('b'); 1.119 + break; 1.120 + case S_IFDIR: 1.121 + putchar('d'); 1.122 + break; 1.123 + case S_IFCHR: 1.124 + putchar('c'); 1.125 + break; 1.126 + case S_IFIFO: 1.127 + putchar('f'); 1.128 + break; 1.129 + default: 1.130 + putchar('-'); 1.131 + } 1.132 + 1.133 + for(i=0; i<3; i++) { 1.134 + int s = (2 - i) * 3; 1.135 + unsigned int val = (ent->st.st_mode >> s) & 7; 1.136 + 1.137 + putchar(val & 4 ? 'r' : '-'); 1.138 + putchar(val & 2 ? 'w' : '-'); 1.139 + putchar(val & 1 ? 'x' : '-'); 1.140 + } 1.141 + printf(" %3d ", (int)ent->st.st_nlink); 1.142 + 1.143 + if(!(pwd = getpwuid(ent->st.st_uid))) { 1.144 + printf("%d ", ent->st.st_uid); 1.145 + } else { 1.146 + printf("%s ", pwd->pw_name); 1.147 + } 1.148 + if(!(grp = getgrgid(ent->st.st_gid))) { 1.149 + printf("%d ", ent->st.st_gid); 1.150 + } else { 1.151 + printf("%s ", grp->gr_name); 1.152 + } 1.153 + 1.154 + sprintf(tmbuf, "%s", ctime(&ent->st.st_mtime)); 1.155 + tmbuf[strlen(tmbuf) - 1] = 0; 1.156 + 1.157 + printf("%6ld %s ", (long)ent->st.st_size, tmbuf); 1.158 + } 1.159 + 1.160 + fputs(ent->name, stdout); 1.161 + 1.162 + if(flags & OPT_CLASS) { 1.163 + if(S_ISDIR(ent->st.st_mode)) { 1.164 + putchar('/'); 1.165 + len++; 1.166 + } else if(ent->st.st_mode & S_IXUSR) { 1.167 + putchar('*'); 1.168 + len++; 1.169 + } 1.170 + } 1.171 + 1.172 + return len; 1.173 +} 1.174 + 1.175 +void print_list(struct entry *arr, int count) 1.176 +{ 1.177 + int i, j, ncol, longest = 0; 1.178 + 1.179 + for(i=0; i<count; i++) { 1.180 + int len = strlen(arr[i].name) + 2; 1.181 + if(len > longest) { 1.182 + longest = len; 1.183 + } 1.184 + } 1.185 + 1.186 + if(isatty(1) && !(flags & OPT_LONG)) { 1.187 + ncol = term_col / longest; 1.188 + if(!ncol) ncol = 1; 1.189 + } else { 1.190 + ncol = 1; 1.191 + } 1.192 + 1.193 + for(i=0; i<count; i++) { 1.194 + int len; 1.195 + 1.196 + len = print_entry(&arr[i]); 1.197 + 1.198 + if(i < count - 1 && (i % ncol) == ncol - 1) { 1.199 + putchar('\n'); 1.200 + } else { 1.201 + for(j=0; j<longest - len; j++) { 1.202 + putchar(' '); 1.203 + } 1.204 + } 1.205 + } 1.206 + putchar('\n'); 1.207 +} 1.208 + 1.209 +int cmp_func(const void *e1, const void *e2) 1.210 +{ 1.211 + const struct entry *ent1, *ent2; 1.212 + const char *n1, *n2; 1.213 + 1.214 + ent1 = e1; 1.215 + ent2 = e2; 1.216 + 1.217 + switch(sort_by) { 1.218 + case SORT_NAME: 1.219 + default: 1.220 + n1 = ent1->name; 1.221 + n2 = ent2->name; 1.222 + } 1.223 + return strcmp(n1, n2); 1.224 +} 1.225 + 1.226 +int ls_dir(char *dname) 1.227 +{ 1.228 + int i, cwd_fd = -1, saved_err, ent_count = 0; 1.229 + DIR *dir = 0; 1.230 + struct dirent *ent = 0; 1.231 + struct entry *earr = 0, *elist = 0, *enode = 0; 1.232 + 1.233 + 1.234 + if(strcmp(dname, ".") != 0) { 1.235 + if((cwd_fd = open(".", O_RDONLY)) == -1) { 1.236 + goto err; 1.237 + } 1.238 + chdir(dname); 1.239 + } 1.240 + 1.241 + if(!(dir = opendir("."))) { 1.242 + goto err; 1.243 + } 1.244 + 1.245 + if(!(elist = malloc(sizeof *elist))) { 1.246 + goto err; 1.247 + } 1.248 + elist->name = 0; 1.249 + elist->next = 0; 1.250 + 1.251 + while((ent = readdir(dir))) { 1.252 + struct stat st; 1.253 + 1.254 + if(ent->d_name[0] == '.' && !(flags & OPT_ALL)) { 1.255 + continue; 1.256 + } 1.257 + 1.258 + if(lstat(ent->d_name, &st) == -1) { 1.259 + goto err; 1.260 + } 1.261 + 1.262 + if(!(enode = malloc(sizeof *enode))) { 1.263 + goto err; 1.264 + } 1.265 + if(!(enode->name = malloc(strlen(ent->d_name) + 1))) { 1.266 + goto err; 1.267 + } 1.268 + strcpy(enode->name, ent->d_name); 1.269 + memcpy(&enode->st, &st, sizeof st); 1.270 + 1.271 + enode->next = elist->next; 1.272 + elist->next = enode; 1.273 + ent_count++; 1.274 + } 1.275 + closedir(dir); 1.276 + dir = 0; 1.277 + 1.278 + /* change the list into an array, don't feel like writing list mergesorts */ 1.279 + if(!(earr = malloc(ent_count * sizeof *earr))) { 1.280 + goto err; 1.281 + } 1.282 + 1.283 + i = 0; 1.284 + enode = elist->next; 1.285 + while(enode) { 1.286 + earr[i].name = enode->name; 1.287 + earr[i++].st = enode->st; 1.288 + enode = enode->next; 1.289 + } 1.290 + if(sort_by != SORT_NONE) { 1.291 + qsort(earr, ent_count, sizeof *earr, cmp_func); 1.292 + } 1.293 + 1.294 + print_list(earr, ent_count); 1.295 + 1.296 + if(cwd_fd != -1) { 1.297 + fchdir(cwd_fd); 1.298 + } 1.299 + return 0; 1.300 + 1.301 +err: 1.302 + saved_err = errno; 1.303 + free(earr); 1.304 + /*free_entry_list(elist);*/ 1.305 + free(enode->name); 1.306 + free(enode); 1.307 + if(dir) { 1.308 + closedir(dir); 1.309 + } 1.310 + if(cwd_fd != -1) { 1.311 + fchdir(cwd_fd); 1.312 + close(cwd_fd); 1.313 + } 1.314 + errno = saved_err; 1.315 + return -1; 1.316 +}