[9] | 1 | /* dir2html.c by Michael Temari 3/3/96 */
|
---|
| 2 |
|
---|
| 3 | #include <sys/types.h>
|
---|
| 4 | #include <stddef.h>
|
---|
| 5 | #include <stdio.h>
|
---|
| 6 | #include <stdlib.h>
|
---|
| 7 | #include <dirent.h>
|
---|
| 8 | #include <string.h>
|
---|
| 9 | #include <unistd.h>
|
---|
| 10 | #include <errno.h>
|
---|
| 11 | #include <time.h>
|
---|
| 12 | #include <sys/stat.h>
|
---|
| 13 |
|
---|
| 14 | typedef struct namelist { /* Obviously a list of names. */
|
---|
| 15 | struct namelist *next;
|
---|
| 16 | char name[1];
|
---|
| 17 | } namelist_t;
|
---|
| 18 |
|
---|
| 19 | _PROTOTYPE(static void sort, (namelist_t **anl));
|
---|
| 20 | _PROTOTYPE(static namelist_t *collect, (char *dir));
|
---|
| 21 | _PROTOTYPE(int main, (int argc, char *argv[]));
|
---|
| 22 |
|
---|
| 23 | static void sort(anl)
|
---|
| 24 | namelist_t **anl;
|
---|
| 25 | /* A stable mergesort disguised as line noise. Must be called like this:
|
---|
| 26 | * if (L != NULL && L->next != NULL) sort(&L);
|
---|
| 27 | */
|
---|
| 28 | {
|
---|
| 29 | /* static */ namelist_t *nl1, **mid; /* Need not be local */
|
---|
| 30 | namelist_t *nl2;
|
---|
| 31 |
|
---|
| 32 | nl1 = *(mid = &(*anl)->next);
|
---|
| 33 | do {
|
---|
| 34 | if ((nl1 = nl1->next) == NULL) break;
|
---|
| 35 | mid = &(*mid)->next;
|
---|
| 36 | } while ((nl1 = nl1->next) != NULL);
|
---|
| 37 |
|
---|
| 38 | nl2 = *mid;
|
---|
| 39 | *mid = NULL;
|
---|
| 40 |
|
---|
| 41 | if ((*anl)->next != NULL) sort(anl);
|
---|
| 42 | if (nl2->next != NULL) sort(&nl2);
|
---|
| 43 |
|
---|
| 44 | nl1 = *anl;
|
---|
| 45 | for (;;) {
|
---|
| 46 | if (strcmp(nl1->name, nl2->name) <= 0) {
|
---|
| 47 | if ((nl1 = *(anl = &nl1->next)) == NULL) {
|
---|
| 48 | *anl = nl2;
|
---|
| 49 | break;
|
---|
| 50 | }
|
---|
| 51 | } else {
|
---|
| 52 | *anl = nl2;
|
---|
| 53 | nl2 = *(anl = &nl2->next);
|
---|
| 54 | *anl = nl1;
|
---|
| 55 | if (nl2 == NULL) break;
|
---|
| 56 | }
|
---|
| 57 | }
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | static namelist_t *collect(dir)
|
---|
| 61 | char *dir;
|
---|
| 62 | /* Return a sorted list of directory entries. Returns null with errno != 0
|
---|
| 63 | * on error.
|
---|
| 64 | */
|
---|
| 65 | {
|
---|
| 66 | namelist_t *names, **pn = &names;
|
---|
| 67 | DIR *dp;
|
---|
| 68 | struct dirent *entry;
|
---|
| 69 |
|
---|
| 70 | if ((dp = opendir(dir)) == NULL) return NULL;
|
---|
| 71 |
|
---|
| 72 | while ((entry = readdir(dp)) != NULL) {
|
---|
| 73 | if (strcmp(entry->d_name, ".") == 0) continue;
|
---|
| 74 | *pn = malloc(offsetof(namelist_t, name) + strlen(entry->d_name) + 1);
|
---|
| 75 | if (*pn == NULL) {
|
---|
| 76 | closedir(dp);
|
---|
| 77 | errno = ENOMEM;
|
---|
| 78 | return NULL;
|
---|
| 79 | }
|
---|
| 80 | strcpy((*pn)->name, entry->d_name);
|
---|
| 81 | pn = &(*pn)->next;
|
---|
| 82 | }
|
---|
| 83 | closedir(dp);
|
---|
| 84 | *pn = NULL;
|
---|
| 85 | if (names != NULL && names->next != NULL) sort(&names);
|
---|
| 86 | errno = 0;
|
---|
| 87 | return names;
|
---|
| 88 | }
|
---|
| 89 |
|
---|
| 90 | int main(argc, argv)
|
---|
| 91 | int argc;
|
---|
| 92 | char *argv[];
|
---|
| 93 | {
|
---|
| 94 | namelist_t *np;
|
---|
| 95 | char *rpath, *vpath;
|
---|
| 96 | static char cwd[1024];
|
---|
| 97 | static char work[64];
|
---|
| 98 | char *filename;
|
---|
| 99 | struct stat st;
|
---|
| 100 | struct tm *tmp;
|
---|
| 101 | static char month[][4] = {
|
---|
| 102 | "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
---|
| 103 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
|
---|
| 104 | };
|
---|
| 105 |
|
---|
| 106 | if(argc > 1) {
|
---|
| 107 | rpath = argv[1];
|
---|
| 108 | if (chdir(rpath) < 0) {
|
---|
| 109 | fprintf(stderr, "dir2html: %s: %s\n", rpath, strerror(errno));
|
---|
| 110 | return(-1);
|
---|
| 111 | }
|
---|
| 112 | } else {
|
---|
| 113 | if(getcwd(cwd, sizeof(cwd)) == NULL) {
|
---|
| 114 | fprintf(stderr, "dir2html: getcwd(): %s", strerror(errno));
|
---|
| 115 | return(-1);
|
---|
| 116 | }
|
---|
| 117 | rpath = cwd;
|
---|
| 118 | }
|
---|
| 119 |
|
---|
| 120 | if(argc > 2) {
|
---|
| 121 | vpath = argv[2];
|
---|
| 122 | } else {
|
---|
| 123 | vpath = rpath;
|
---|
| 124 | }
|
---|
| 125 |
|
---|
| 126 | if ((np = collect(".")) == NULL && errno != 0) {
|
---|
| 127 | fprintf(stderr, "dir2html: %s: %s\n", vpath, strerror(errno));
|
---|
| 128 | return(-1);
|
---|
| 129 | }
|
---|
| 130 |
|
---|
| 131 | printf("<HTML><HEAD><TITLE>Index of %s</TITLE></HEAD>\n", vpath);
|
---|
| 132 | printf("<BODY>\n");
|
---|
| 133 | printf("<H1>Index of %s</H1>\n", vpath);
|
---|
| 134 |
|
---|
| 135 | printf("<PRE>\n");
|
---|
| 136 | printf("%-22s %-17s %s\n", "Name", "Last modified", "Size/Type");
|
---|
| 137 | printf("<HR>\n");
|
---|
| 138 |
|
---|
| 139 | while (np != NULL) {
|
---|
| 140 | errno = 0;
|
---|
| 141 | filename = np->name;
|
---|
| 142 | np= np->next;
|
---|
| 143 |
|
---|
| 144 | if (stat(filename, &st) < 0) continue;
|
---|
| 145 |
|
---|
| 146 | printf("<A HREF=\"%s%s\">",
|
---|
| 147 | filename, S_ISDIR(st.st_mode) ? "/" : "");
|
---|
| 148 | sprintf(work, "%.23s%s",
|
---|
| 149 | filename, S_ISDIR(st.st_mode) ? "/" : "");
|
---|
| 150 | if (strcmp(filename, "..") == 0) strcpy(work, "Parent Directory");
|
---|
| 151 | printf("%-22.22s%s</A>",
|
---|
| 152 | work, strlen(work) > 22 ? ">" : " ");
|
---|
| 153 | tmp = localtime(&st.st_mtime);
|
---|
| 154 | printf(" %02d %s %d %02d:%02d",
|
---|
| 155 | tmp->tm_mday, month[tmp->tm_mon], 1900+tmp->tm_year,
|
---|
| 156 | tmp->tm_hour, tmp->tm_min);
|
---|
| 157 | if (S_ISREG(st.st_mode)) {
|
---|
| 158 | if (st.st_size < 10240) {
|
---|
| 159 | sprintf(work, "%lu ", (unsigned long) st.st_size);
|
---|
| 160 | } else
|
---|
| 161 | if (st.st_size < 10240 * 1024L) {
|
---|
| 162 | sprintf(work, "%luK",
|
---|
| 163 | ((unsigned long) st.st_size - 1) / 1024 + 1);
|
---|
| 164 | } else {
|
---|
| 165 | sprintf(work, "%luM",
|
---|
| 166 | ((unsigned long) st.st_size - 1) / (1024 * 1024L) + 1);
|
---|
| 167 | }
|
---|
| 168 | } else {
|
---|
| 169 | strcpy(work,
|
---|
| 170 | S_ISDIR(st.st_mode) ? "[dir]" :
|
---|
| 171 | S_ISBLK(st.st_mode) ? "[block]" :
|
---|
| 172 | S_ISCHR(st.st_mode) ? "[char]" :
|
---|
| 173 | S_ISFIFO(st.st_mode) ? "[pipe]" :
|
---|
| 174 | "[???]");
|
---|
| 175 | }
|
---|
| 176 | printf(" %8s\n", work);
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | printf("</PRE>\n");
|
---|
| 180 |
|
---|
| 181 | printf("<HR>\n");
|
---|
| 182 | printf("<SMALL><i>Minix httpd 0.99</i></SMALL>\n");
|
---|
| 183 | printf("</BODY>\n");
|
---|
| 184 | printf("</HTML>\n");
|
---|
| 185 |
|
---|
| 186 | return(0);
|
---|
| 187 | }
|
---|