
1: /* $Copyright: $ 2: * Copyright (c) 1996 - 2007 by Steve Baker (ice@mama.indstate.edu) 3: * All Rights reserved 4: * 5: * This program is free software; you can redistribute it and/or modify 6: * it under the terms of the GNU General Public License as published by 7: * the Free Software Foundation; either version 2 of the License, or 8: * (at your option) any later version. 9: * 10: * This program is distributed in the hope that it will be useful, 11: * but WITHOUT ANY WARRANTY; without even the implied warranty of 12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13: * GNU General Public License for more details. 14: * 15: * You should have received a copy of the GNU General Public License 16: * along with this program; if not, write to the Free Software 17: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18: */ 19: 20: #include <features.h> 21: #include <stdlib.h> 22: #include <stdio.h> 23: #include <time.h> 24: #include <string.h> 25: #include <sys/time.h> 26: #include <sys/types.h> 27: #include <sys/stat.h> 28: #include <dirent.h> 29: #include <sys/file.h> 30: #include <ctype.h> 31: #include <unistd.h> 32: #include <limits.h> 33: #include <pwd.h> 34: #include <grp.h> 35: #ifdef __EMX__ /* for OS/2 systems */ 36: # define INCL_DOSFILEMGR 37: # define INCL_DOSNLS 38: # include <os2.h> 39: # include <sys/nls.h> 40: # include <io.h> 41: /* On many systems stat() function is idential to lstat() function. 42: * But the OS/2 does not support symbolic links and doesn't have lstat() function. 43: */ 44: # define lstat stat 45: # define strcasecmp stricmp 46: /* Following two functions, getcwd() and chdir() don't support for drive letters. 47: * To implement support them, use _getcwd2() and _chdir2(). 48: */ 49: # define getcwd _getcwd2 50: # define chdir _chdir2 51: #endif 52: 53: #include <locale.h> 54: #include <wchar.h> 55: #include <wctype.h> 56: 57: static char *version ="$Version: $ tree v1.5.1.1 (c) 1996 - 2007 by Steve Baker, Thomas Moore, Francesc Rocher, Kyosuke Tokoro $"; 58: static char *hversion="\t\t\t tree v1.5.1.1 %s 1996 - 2007 by Steve Baker and Thomas Moore <br>\n" 59: "\t\t\t HTML output hacked and copyleft %s 1998 by Francesc Rocher <br>\n" 60: "\t\t\t Charsets / OS/2 support %s 2001 by Kyosuke Tokoro\n"; 61: 62: 63: #define scopy(x) strcpy(xmalloc(strlen(x)+1),(x)) 64: #define MINIT 30 /* number of dir entries to initially allocate */ 65: #define MINC 20 /* allocation increment */ 66: 67: #ifndef TRUE 68: enum bool {FALSE=0, TRUE}; 69: #endif 70: 71: struct _info { 72: char *name; 73: char *lnk; 74: u_char isdir : 1; 75: u_char issok : 1; 76: u_char isexe : 1; 77: u_char isfifo : 1; 78: u_char orphan : 1; 79: u_short mode, lnkmode, uid, gid; 80: off_t size; 81: time_t atime, ctime, mtime; 82: dev_t dev; 83: ino_t inode; 84: #ifdef __EMX__ 85: long attr; 86: #endif 87: }; 88: 89: /* Faster uid/gid -> name lookup with hash(tm)(r)(c) tables! */ 90: #define HASH(x) ((x)&255) 91: struct xtable { 92: u_short xid; 93: char *name; 94: struct xtable *nxt; 95: } *gtable[256], *utable[256];gniibe: tree/1.5.1.1/tree.c:95-95 on Tue Jan 08 10:17:55 +0900 200896: 97: /* Record inode numbers of followed sym-links to avoid refollowing them */ 98: #define inohash(x) ((x)&255) 99: struct inotable { 100: ino_t inode; 101: dev_t device; 102: struct inotable *nxt; 103: } *itable[256];Should be static?
gniibe: tree/1.5.1.1/tree.c:103-103 on Tue Jan 08 10:18:28 +0900 2008104: 105: /* Hacked in DIR_COLORS support ---------------------------------------------- */ 106: enum { 107: CMD_COLOR, CMD_OPTIONS, CMD_TERM, CMD_EIGHTBIT, COL_NORMAL, COL_FILE, COL_DIR, 108: COL_LINK, COL_FIFO, COL_SOCK, COL_BLK, COL_CHR, COL_EXEC, DOT_EXTENSION, ERROR, 109: COL_ORPHAN, COL_MISSING, COL_LEFTCODE, COL_RIGHTCODE, COL_ENDCODE 110: }; 111: 112: char colorize = FALSE, ansilines = FALSE; 113: char *term, termmatch = FALSE, istty; 114: char *leftcode = NULL, *rightcode = NULL, *endcode = NULL; 115: 116: char *norm_flgs = NULL, *file_flgs = NULL, *dir_flgs = NULL, *link_flgs = NULL; 117: char *fifo_flgs = NULL, *sock_flgs = NULL, *block_flgs = NULL, *char_flgs = NULL; 118: char *exec_flgs = NULL, *orphan_flgs = NULL, *missing_flgs = NULL; 119: 120: char *vgacolor[] = { 121: "black", "red", "green", "yellow", "blue", "fuchsia", "aqua", "white", 122: NULL, NULL, 123: "transparent", "red", "green", "yellow", "blue", "fuchsia", "aqua", "black" 124: }; 125: 126: struct colortable { 127: char *term_flg, *CSS_name, *font_fg, *font_bg; 128: } colortable[11]; 129: 130: struct extensions { 131: char *ext; 132: char *term_flg, *CSS_name, *web_fg, *web_bg, *web_extattr; 133: struct extensions *nxt; 134: } *ext = NULL; 135: 136: const struct linedraw { 137: const char **name, *vert, *vert_left, *corner, *copy; 138: } *linedraw;Should be static?
gniibe: tree/1.5.1.1/tree.c:112-138 on Tue Jan 08 10:19:48 +0900 2008139: 140: /* Hacked in DIR_COLORS support ---------------------------------------------- */ 141: 142: /* Function prototypes: */ 143: int color(u_short, char *, char, char), cmd(char *), patmatch(char *, char *); 144: int alnumsort(struct _info **, struct _info **); 145: int reversealnumsort(struct _info **, struct _info **); 146: int timesort(struct _info **, struct _info **); 147: int dirsfirstsort(struct _info **, struct _info **); 148: int findino(ino_t, dev_t); 149: void *xmalloc(size_t), *xrealloc(void *, size_t); 150: void listdir(char *, int *, int *, u_long, dev_t), usage(int); 151: void parse_dir_colors(), printit(unsigned char *), free_dir(struct _info **), indent(); 152: void saveino(ino_t, dev_t); 153: char **split(char *, char *, int *); 154: char *gidtoname(int), *uidtoname(int), *do_date(time_t); 155: char *gnu_getcwd(); 156: struct _info **read_dir(char *, int *); 157: void html_encode(FILE *, char *), url_encode(FILE *, char *); 158: const char *getcharset(void); 159: void initlinedraw(int); 160: void psize(char *buf, off_t size); 161: #ifdef __EMX__ 162: char *prot(long); 163: #else 164: char *prot(u_short); 165: #endif 166: 167: /* Globals */ 168: int dflag, lflag, pflag, sflag, Fflag, aflag, fflag, uflag, gflag; 169: int qflag, Nflag, Dflag, inodeflag, devflag, hflag; 170: int noindent, force_color, nocolor, xdev, noreport, nolinks; 171: char *pattern = NULL, *ipattern = NULL, *host = NULL, *title = "Directory Tree", *sp = " "; 172: const char *charset=NULL; 173: 174: int (*cmpfunc)() = alnumsort; 175: 176: u_char Hflag, Rflag; 177: int Level; 178: char *sLevel, *curdir, *outfilename = NULL; 179: FILE *outfile; 180: int *dirs, maxdirs;Should be static?
gniibe: tree/1.5.1.1/tree.c:142-180 on Tue Jan 08 10:20:36 +0900 2008181: 182: #ifdef CYGWIN 183: extern int MB_CUR_MAX; 184: #else 185: extern size_t MB_CUR_MAX; 186: #endif 187: 188: int main(int argc, char **argv) 189: { 190: char **dirname = NULL; 191: int i,j,n,p,q,dtotal,ftotal,colored = FALSE; 192: struct stat st; 193: 194: q = p = dtotal = ftotal = 0; 195: aflag = dflag = fflag = lflag = pflag = sflag = Fflag = uflag = gflag = FALSE; 196: Dflag = qflag = Nflag = Hflag = Rflag = hflag = FALSE; 197: noindent = force_color = nocolor = xdev = noreport = nolinks = FALSE; 198: inodeflag = devflag = FALSE; 199: dirs = xmalloc(sizeof(int) * (maxdirs=4096)); 200: dirs[0] = 0; 201: Level = -1; 202: 203: setlocale(LC_CTYPE, ""); 204: 205: memset(utable,0,sizeof(utable)); 206: memset(gtable,0,sizeof(gtable)); 207: memset(itable,0,sizeof(itable)); 208: 209: for(n=i=1;i<argc;i=n) { 210: n++; 211: if (argv[i][0] == '-' && argv[i][1]) { 212: for(j=1;argv[i][j];j++) { 213: switch(argv[i][j]) {Most of them should be static?
guest: tree/1.5.1.1/tree.c:213-213 on Thu Jan 10 10:28:26 +0900 2008214: case 'N': 215: Nflag = TRUE; 216: break; 217: case 'q': 218: qflag = TRUE; 219: break; 220: case 'd': 221: dflag = TRUE; 222: break; 223: case 'l': 224: lflag = TRUE; 225: break; 226: case 's': 227: sflag = TRUE; 228: break; 229: case 'h': 230: hflag = TRUE; 231: sflag = TRUE; /* Assume they also want -s */ 232: break; 233: case 'u': 234: uflag = TRUE; 235: break; 236: case 'g': 237: gflag = TRUE; 238: break; 239: case 'f': 240: fflag = TRUE; 241: break; 242: case 'F': 243: Fflag = TRUE; 244: break; 245: case 'a': 246: aflag = TRUE; 247: break; 248: case 'p': 249: pflag = TRUE; 250: break; 251: case 'i': 252: noindent = TRUE; 253: break; 254: case 'C': 255: force_color = TRUE; 256: break; 257: case 'n': 258: nocolor = TRUE; 259: break; 260: case 'x': 261: xdev = TRUE; 262: break; 263: case 'P': 264: if (argv[n] == NULL) { 265: fprintf(stderr,"tree: missing argument to -P option.\n"); 266: exit(1); 267: } 268: pattern = argv[n++]; 269: break; 270: case 'I': 271: if (argv[n] == NULL) { 272: fprintf(stderr,"tree: missing argument to -I option.\n"); 273: exit(1); 274: } 275: ipattern = argv[n++]; 276: break; 277: case 'A': 278: ansilines = TRUE; 279: break; 280: case 'S': 281: charset="IBM437"; 282: break; 283: case 'D': 284: Dflag = TRUE; 285: break; 286: case 't': 287: cmpfunc = timesort; 288: break; 289: case 'r': 290: cmpfunc = reversealnumsort; 291: break; 292: case 'H': 293: Hflag = TRUE; 294: if (argv[n] == NULL) { 295: fprintf(stderr,"tree: missing argument to -H option.\n"); 296: exit(1); 297: } 298: host = argv[n++]; 299: sp = " "; 300: break; 301: case 'T': 302: if (argv[n] == NULL) { 303: fprintf(stderr,"tree: missing argument to -T option.\n"); 304: exit(1); 305: } 306: title = argv[n++]; 307: break; 308: case 'R': 309: Rflag = TRUE; 310: break; 311: case 'L': 312: if ((sLevel = argv[n++]) == NULL) { 313: fprintf(stderr,"tree: Missing argument to -L option.\n"); 314: exit(1); 315: } 316: Level = strtoul(sLevel,NULL,0)-1; 317: if (Level < 0) { 318: fprintf(stderr,"tree: Invalid level, must be greater than 0.\n"); 319: exit(1); 320: } 321: break; 322: case 'o': 323: if (argv[n] == NULL) { 324: fprintf(stderr,"tree: missing argument to -o option.\n"); 325: exit(1); 326: } 327: outfilename = argv[n++]; 328: break; 329: case '-': 330: if (j == 1) { 331: if (!strcmp("--help",argv[i])) usage(2); 332: if (!strcmp("--version",argv[i])) { 333: char *v = version+12; 334: printf("%.*s\n",(int)strlen(v)-1,v); 335: exit(0); 336: } 337: if (!strcmp("--inodes",argv[i])) { 338: j = strlen(argv[i])-1; 339: inodeflag=TRUE; 340: break; 341: } 342: if (!strcmp("--device",argv[i])) { 343: j = strlen(argv[i])-1; 344: devflag=TRUE; 345: break; 346: } 347: if (!strcmp("--noreport",argv[i])) { 348: j = strlen(argv[i])-1; 349: noreport = TRUE; 350: break; 351: } 352: if (!strcmp("--nolinks",argv[i])) { 353: j = strlen(argv[i])-1; 354: nolinks = TRUE; 355: break; 356: } 357: if (!strcmp("--dirsfirst",argv[i])) { 358: j = strlen(argv[i])-1; 359: cmpfunc = dirsfirstsort; 360: break; 361: } 362: if (!strncmp("--charset",argv[i],9)){ 363: j = 9; 364: if (*(argv[i]+j) == '=') { 365: if (*(charset=(argv[i]+10))) { 366: j = strlen(argv[i])-1; 367: break; 368: } 369: } 370: if (argv[n] != NULL) { 371: charset=argv[n++]; 372: j = strlen(argv[i])-1; 373: } else { 374: initlinedraw(1); 375: exit(1); 376: } 377: break; 378: } 379: } 380: default: 381: fprintf(stderr,"tree: Invalid argument -`%c'.\n",argv[i][j]); 382: usage(1); 383: exit(1); 384: break; 385: } 386: } 387: } else { 388: if (!dirname) dirname = (char **)xmalloc(sizeof(char *) * (q=MINIT)); 389: else if (p == (q-2)) dirname = (char **)xrealloc(dirname,sizeof(char *) * (q+=MINC)); 390: dirname[p++] = scopy(argv[i]); 391: } 392: } 393: if (p) dirname[p] = NULL; 394: 395: if (outfilename == NULL) { 396: #ifdef __EMX__ 397: _fsetmode(outfile=stdout,Hflag?"b":"t"); 398: #else 399: outfile = stdout; 400: #endif 401: } else { 402: #ifdef __EMX__ 403: outfile = fopen(outfilename,Hflag?"wb":"wt"); 404: #else 405: outfile = fopen(outfilename,"w"); 406: #endif 407: if (outfile == NULL) { 408: fprintf(stderr,"tree: invalid filename '%s'\n",outfilename); 409: exit(1); 410: } 411: } 412: 413: parse_dir_colors(); 414: initlinedraw(0); 415: 416: if (Rflag && (Level == -1)) 417: Rflag = FALSE; 418: 419: if (Hflag) { 420: fprintf(outfile,"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n"); 421: fprintf(outfile,"<html>\n"); 422: fprintf(outfile,"\t<head>\n"); 423: if (charset) 424: fprintf(outfile,"\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=%s\">\n",charset); 425: else 426: fprintf(outfile,"\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"); 427: 428: fprintf(outfile,"\t\t<meta name=\"Author\" content=\"Made by 'tree'\">\n"); 429: fprintf(outfile,"\t\t<meta name=\"GENERATOR\" content=\"%s\">\n",version); 430: fprintf(outfile,"\t\t<title>%s</title>\n",title); 431: fprintf(outfile,"\t\t<style type=\"text/css\">\n\t\t\t<!-- \n"); 432: fprintf(outfile,"\t\t\tBODY { font-family : courier, monospace, sans-serif; }\n"); 433: fprintf(outfile,"\t\t\tP { font-weight: normal; font-family : courier, monospace, sans-serif; color: black; background-color: transparent;}\n"); 434: fprintf(outfile,"\t\t\tB { font-weight: normal; color: black; background-color: transparent;}\n"); 435: fprintf(outfile,"\t\t\tA:visited { font-weight : normal; text-decoration : none; background-color : transparent; margin : 0px 0px 0px 0px; padding : 0px 0px 0px 0px; display: inline; }\n"); 436: fprintf(outfile,"\t\t\tA:link { font-weight : normal; text-decoration : none; margin : 0px 0px 0px 0px; padding : 0px 0px 0px 0px; display: inline; }\n"); 437: fprintf(outfile,"\t\t\tA:hover { color : #000000; font-weight : normal; text-decoration : underline; background-color : yellow; margin : 0px 0px 0px 0px; padding : 0px 0px 0px 0px; display: inline; }\n"); 438: fprintf(outfile,"\t\t\tA:active { color : #000000; font-weight: normal; background-color : transparent; margin : 0px 0px 0px 0px; padding : 0px 0px 0px 0px; display: inline; }\n"); 439: fprintf(outfile,"\t\t\t.VERSION { font-size: small; font-family : arial, sans-serif; }\n"); 440: 441: /* We can use CSS for nolinks as well */ 442: fprintf(outfile,"\t\t\t.NORM { color: black; background-color: transparent;}\n"); 443: fprintf(outfile,"\t\t\t.FIFO { color: purple; background-color: transparent;}\n"); 444: fprintf(outfile,"\t\t\t.CHAR { color: yellow; background-color: transparent;}\n"); 445: fprintf(outfile,"\t\t\t.DIR { color: blue; background-color: transparent;}\n"); 446: fprintf(outfile,"\t\t\t.BLOCK { color: yellow; background-color: transparent;}\n"); 447: fprintf(outfile,"\t\t\t.LINK { color: aqua; background-color: transparent;}\n"); 448: fprintf(outfile,"\t\t\t.SOCK { color: fuchsia; background-color: transparent;}\n"); 449: fprintf(outfile,"\t\t\t.EXEC { color: green; background-color: transparent;}\n"); 450: 451: fprintf(outfile,"\t\t\t-->\n\t\t</style>\n"); 452: fprintf(outfile,"\t</head>\n"); 453: fprintf(outfile,"\t<body>\n"); 454: fprintf(outfile,"\t\t<h1>%s</h1>\n\t\t\t<p>",title); 455: 456: fflag = FALSE; 457: if (nolinks) { 458: if (force_color) fprintf(outfile, "<b class=\"NORM\">%s</b>\n",host); 459: else fprintf(outfile,"%s\n",host); 460: } else { 461: if (force_color) fprintf(outfile,"<a class=\"NORM\" href=\"%s\">%s</a>\n",host,host); 462: else fprintf(outfile,"<a href=\"%s\">%s</a>\n",host,host); 463: } 464: curdir = gnu_getcwd(); 465: } 466: 467: if (dirname) { 468: for(colored=i=0;dirname[i];i++,colored=0) { 469: if (fflag) { 470: do { 471: j=strlen(dirname[i]); 472: if (j > 1 && dirname[i][j-1] == '/') dirname[i][--j] = 0; 473: } while (j > 1 && dirname[i][j-1] == '/'); 474: } 475: if ((n = lstat(dirname[i],&st)) >= 0) { 476: saveino(st.st_ino, st.st_dev); 477: if (colorize) colored = color(st.st_mode,dirname[i],n<0,FALSE); 478: } 479: if (!Hflag) printit(dirname[i]); 480: if (colored) fprintf(outfile,"%s",endcode); 481: if (!Hflag) listdir(dirname[i],&dtotal,&ftotal,0,0); 482: else { 483: if (chdir(dirname[i])) { 484: fprintf(outfile,"%s [error opening dir]\n",dirname[i]); 485: exit(1); 486: } else { 487: listdir(".",&dtotal,&ftotal,0,0); 488: chdir(curdir); 489: } 490: } 491: } 492: } else { 493: if ((n = lstat(".",&st)) >= 0) { 494: saveino(st.st_ino, st.st_dev); 495: if (colorize) colored = color(st.st_mode,".",n<0,FALSE); 496: } 497: if (!Hflag) fprintf(outfile,"."); 498: if (colored) fprintf(outfile,"%s",endcode); 499: listdir(".",&dtotal,&ftotal,0,0); 500: } 501: 502: if (Hflag) 503: fprintf(outfile,"\t\t<br><br>\n\t\t</p>\n\t\t<p>\n"); 504: 505: if (!noreport) { 506: if (dflag) 507: fprintf(outfile,"\n%d director%s\n",dtotal,(dtotalケースによって場合分け