home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / xap / xfm / xfm-1.000 / xfm-1 / xfm-1.3.2 / src / magic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-04  |  10.5 KB  |  583 lines

  1. /*-----------------------------------------------------------------------------
  2.   Module magic.c
  3.  
  4.   (c) Juan D. Martin 1995
  5.   (c) CNM-US 1995
  6.                                                                            
  7.   magic headers related code.
  8. -----------------------------------------------------------------------------*/
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <ctype.h>
  14. #include <string.h>
  15. #include <fcntl.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include "magic.h"
  19.  
  20. /* ULTRIX apparently doesn't define these */
  21. #ifdef ultrix
  22. #define S_ISLNK(mode) (mode & S_IFMT) == S_IFLNK
  23. #define S_ISSOCK(mode) (mode & S_IFMT) == S_IFSOCK
  24. #endif
  25.  
  26. #define MAXLIN 1024
  27. #define ASCLEN 512    
  28. #define REGLEN 256    
  29.  
  30. static char    linebuf[MAXLIN];
  31. static hmagic *mtypes = 0;    /* Array of file-types. */
  32. static int     count = 0;    /* Number of types registered. */
  33. static int     allocated = 0;    /* Room in the array. */
  34. static int     top = 0;        /* Current top for sub-types. */
  35. static int     maxhdr = ASCLEN;    /* Maximum header size required. */
  36. static char   *hdrbuf = 0;    /* Header buffer allocated. */
  37. static int     hdrbufsiz = 0;    /* Size of header buffer. */
  38. static struct stat stbuf;    /* Stat buffer. */
  39. static struct stat lstbuf;    /* Lstat buffer. */
  40. static int bytes;        /* Bytes read from the file. */
  41. static int     mmatch();
  42. static char   *builtin_test();
  43. static char   *builtin_result;
  44. static char   *parse_string();
  45.  
  46. void magic_parse_file(name)
  47. char *name;
  48. {
  49.     FILE *fh;
  50.     int hsiz;
  51.  
  52.     if(!hdrbuf)
  53.     {
  54.     hdrbuf = (char *) malloc(maxhdr + 1);
  55.     hdrbufsiz = maxhdr;
  56.     }
  57.  
  58.     if(!name || !(fh = fopen(name, "r")))
  59.     return;
  60.  
  61.     while(fgets(linebuf, MAXLIN, fh))
  62.     {
  63.     char *cptr, *sptr;
  64.     int cnt = 0;
  65.     int l;
  66.  
  67.     l = strlen(linebuf);
  68.     while(l < MAXLIN && linebuf[--l] == '\n' && linebuf[--l] == '\\')
  69.     {
  70.         if(!fgets(linebuf + l, MAXLIN - l, fh))
  71.         break;
  72.         l = strlen(linebuf);
  73.     }
  74.  
  75.     if(count >= allocated)
  76.     {
  77.         if(!mtypes)
  78.         {
  79.         allocated = 25;
  80.         mtypes = (hmagic *) malloc(allocated * sizeof(hmagic));
  81.         }
  82.         else
  83.         {
  84.         allocated += 25;
  85.         mtypes = (hmagic *) realloc((char *) mtypes,
  86.                         allocated * sizeof(hmagic));
  87.         }
  88.     }
  89.  
  90.     cptr = linebuf;
  91.     if(cptr[0] == '>')    /* Sub-type */
  92.     {
  93.         cptr++;
  94.         mtypes[top].subtypes++;
  95.     }
  96.     else if(cptr[0] == '#' || cptr[0] == '\n' || cptr[0] == '\r')
  97.     {
  98.         continue;
  99.     }
  100.     else
  101.     {
  102.         top = count;
  103.         mtypes[top].subtypes = 0;
  104.     }
  105.  
  106.     mtypes[count].offset = strtol(cptr, &cptr, 0);
  107.     while(isspace(*cptr))
  108.         cptr++;
  109.  
  110.     while(islower(cptr[cnt]))
  111.         cnt++;
  112.  
  113.     if(!strncmp("string", cptr, cnt))
  114.     {
  115.         mtypes[count].flags = M_STRING;
  116.         cptr += cnt;
  117.  
  118.         sptr = parse_string(&cptr);
  119.         mtypes[count].mask = strlen(sptr);
  120.         mtypes[count].value.string = 
  121.         strcpy((char *)malloc(mtypes[count].mask + 1), sptr);
  122.  
  123.         hsiz = mtypes[count].offset + mtypes[count].mask;
  124.         if(hsiz > maxhdr)
  125.         maxhdr = hsiz;
  126.     }
  127.     else if(!strncmp("builtin", cptr, cnt))
  128.     {
  129.         mtypes[count].flags = M_BUILTIN;
  130.         cptr += cnt;
  131.  
  132.         sptr = parse_string(&cptr);
  133.         mtypes[count].value.string = 
  134.         strcpy((char *)malloc(strlen(sptr) + 1), sptr);
  135.     }
  136.     else if(!strncmp("regexp", cptr, cnt))
  137.     {
  138.         mtypes[count].flags = M_REGEXP;
  139.         cptr += cnt;
  140.  
  141.  
  142.         if(*cptr == '&')
  143.         {
  144.         cptr++;
  145.         mtypes[count].mask = strtol(cptr, &cptr, 0);
  146.         }
  147.         else
  148.         mtypes[count].mask = REGLEN;
  149.         hsiz = mtypes[count].offset + mtypes[count].mask;
  150.         if(hsiz > maxhdr)
  151.         maxhdr = hsiz;
  152.  
  153.         sptr = parse_string(&cptr);
  154.         mtypes[count].value.expr = regcomp(sptr);
  155.     }
  156.     else
  157.     {
  158.         if(!strncmp("byte", cptr, cnt))
  159.         {
  160.         mtypes[count].flags = M_BYTE;
  161.         hsiz = mtypes[count].offset + 1;
  162.         if(hsiz > maxhdr)
  163.             maxhdr = hsiz;
  164.         }
  165.         else if(!strncmp("short", cptr, cnt))
  166.         {
  167.         mtypes[count].flags = M_SHORT;
  168.         hsiz = mtypes[count].offset + 2;
  169.         if(hsiz > maxhdr)
  170.             maxhdr = hsiz;
  171.         }
  172.         else if(!strncmp("long", cptr, cnt))
  173.         {
  174.         mtypes[count].flags = M_LONG;
  175.         hsiz = mtypes[count].offset + 4;
  176.         if(hsiz > maxhdr)
  177.             maxhdr = hsiz;
  178.         }
  179.         else if(!strncmp("mode", cptr, cnt))
  180.         {
  181.         mtypes[count].flags = M_MODE;
  182.         }
  183.         else if(!strncmp("lmode", cptr, cnt))
  184.         {
  185.         mtypes[count].flags = M_LMODE;
  186.         }
  187.         else
  188.         continue;        /* Error. Skip line. */
  189.  
  190.         cptr += cnt;
  191.  
  192.         if(*cptr == '&')
  193.         {
  194.         mtypes[count].flags |= M_MASKED;
  195.         cptr++;
  196.         mtypes[count].mask = strtol(cptr, &cptr, 0);
  197.         }
  198.  
  199.         while(isspace(*cptr))
  200.         cptr++;
  201.         switch(*cptr)
  202.         {
  203.         case '=':
  204.         mtypes[count].flags |= M_EQ;
  205.         cptr++;
  206.         break;
  207.         case '<':
  208.         mtypes[count].flags |= M_LT;
  209.         cptr++;
  210.         break;
  211.         case '>':
  212.         mtypes[count].flags |= M_GT;
  213.         cptr++;
  214.         break;
  215.         case '&':
  216.         mtypes[count].flags |= M_SET;
  217.         cptr++;
  218.         break;
  219.         case '^':
  220.         mtypes[count].flags |= M_OR;
  221.         cptr++;
  222.         break;
  223.         case 'x':
  224.         mtypes[count].flags |= M_ANY;
  225.         cptr++;
  226.         break;
  227.         default:
  228.         mtypes[count].flags |= M_EQ;
  229.         }
  230.         mtypes[count].value.number = strtol(cptr, &cptr, 0);
  231.     }
  232.     while(isspace(*cptr))
  233.         cptr++;
  234.     sptr = cptr;
  235.     while(*cptr != '\n' && *cptr != '\r' && *cptr != '\0')
  236.         cptr++;
  237.     *cptr = '\0';
  238.     mtypes[count].message = strcpy((char *)malloc(strlen(sptr) + 1), sptr);
  239.     count++;
  240.     }
  241.     fclose(fh);
  242.  
  243.     if(maxhdr > hdrbufsiz)
  244.     {
  245.     free(hdrbuf);
  246.     hdrbuf = (char *) malloc(maxhdr + 1);
  247.     hdrbufsiz = maxhdr;
  248.     }
  249. }
  250.  
  251. void magic_get_type(name, buf)
  252. char *name;
  253. char *buf;
  254. {
  255.     int i;
  256.     int fd;
  257.  
  258.     if(lstat(name, &lstbuf) < 0)
  259.     {
  260.     stbuf.st_mode = 0;
  261.     lstbuf.st_mode = 0;
  262.     bytes = -1;
  263.     }
  264.     else
  265.     {
  266.     if(S_ISLNK(lstbuf.st_mode))
  267.     {
  268.         if(stat(name, &stbuf) < 0)
  269.         {
  270.         stbuf.st_mode = 0;
  271.         bytes = -1;
  272.         }
  273.     }
  274.     else
  275.         stbuf = lstbuf;
  276.     if(S_ISREG(stbuf.st_mode))
  277.     {
  278.         if(stbuf.st_size == 0)
  279.         bytes = 0;
  280.         if((fd = open(name, O_RDONLY, 0)) < 0)
  281.         bytes = -1;
  282.         else
  283.         {
  284.         bytes = read(fd, hdrbuf, maxhdr);
  285.         close(fd);
  286.         /* Make sure it is nul-terminated. */
  287.         if(bytes >= 0)
  288.             hdrbuf[bytes] = '\0'; 
  289.         }
  290.     }
  291.     else
  292.         bytes = 0;
  293.     }
  294.  
  295.     builtin_result = (char *)0;
  296.     for(i = 0; i < count; i++)
  297.     {
  298.     if(mmatch(i, buf))
  299.     {
  300.         if(mtypes[i].subtypes != 0)
  301.         {
  302.         char *nbuf;
  303.         int n;
  304.  
  305.         if(buf[0] != '\0')
  306.             strcat(buf, " ");
  307.         nbuf = buf + strlen(buf);
  308.         n = i + mtypes[i].subtypes + 1;
  309.         for(++i; i < n; i++)
  310.         {
  311.             if(mmatch(i, nbuf) && nbuf[0] != '\0')
  312.             {
  313.             strcat(nbuf, " ");
  314.             nbuf = nbuf + strlen(nbuf);
  315.             }
  316.         }
  317.         n = strlen(buf) - 1;
  318.         if(buf[n] == ' ')
  319.             buf[n] = '\0';
  320.         }
  321.         return;
  322.     }
  323.     else
  324.         i += mtypes[i].subtypes;
  325.     }
  326.     strcpy(buf, builtin_test());
  327. }
  328.  
  329. static int mmatch(i, buf)
  330. int i;
  331. char *buf;
  332. {
  333.     int t;
  334.     int o;
  335.     long v;
  336.     unsigned char *h;
  337.  
  338.     h = (unsigned char *) (hdrbuf + mtypes[i].offset);
  339.     t = mtypes[i].flags & M_TYPE;
  340.  
  341.     switch(t)
  342.     {
  343.     case M_STRING:
  344.     if(bytes >= mtypes[i].offset + mtypes[i].mask &&
  345.        !strncmp(hdrbuf + mtypes[i].offset, 
  346.             mtypes[i].value.string,
  347.             mtypes[i].mask))
  348.     {
  349.         strcpy(buf, mtypes[i].message);
  350.         return 1;
  351.     }
  352.     return 0;
  353.  
  354.     case M_BUILTIN:
  355.     if(!strcmp(mtypes[i].value.string, builtin_test()))
  356.     {
  357.         strcpy(buf, mtypes[i].message);
  358.         return 1;
  359.     }
  360.     return 0;
  361.  
  362.     case M_REGEXP:
  363.     {
  364.     char sav;
  365.     int len;
  366.     regexp *prog = mtypes[i].value.expr;
  367.  
  368.     if(bytes <= mtypes[i].offset || !prog)
  369.         return 0;
  370.  
  371.     if(bytes > mtypes[i].offset + mtypes[i].mask)
  372.     {
  373.         len = mtypes[i].mask;
  374.         sav = h[len];
  375.         h[len] = '\0';
  376.     }
  377.     else
  378.         len = -1;
  379.     
  380.     if(regexec(prog , h))
  381.     {
  382.         regsub(prog, mtypes[i].message, buf);
  383.         if(len >= 0)
  384.         h[len] = sav;
  385.         return 1;
  386.     }
  387.     if(len >= 0)
  388.         h[len] = sav;
  389.     }
  390.     return 0;
  391.  
  392.     case M_BYTE:
  393.     if(bytes < mtypes[i].offset + 1)
  394.         return 0;
  395.     else
  396.         v = h[0];
  397.     break;
  398.  
  399.     case M_SHORT:
  400.     if(bytes < mtypes[i].offset + 2)
  401.         return 0;
  402.     else
  403.         v = (h[0] << 8) | h[1];
  404.     break;
  405.  
  406.     case M_LONG:
  407.     if(bytes < mtypes[i].offset + 4)
  408.         return 0;
  409.     else
  410.         v = (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3];
  411.     break;
  412.  
  413.     case M_MODE:
  414.     v = stbuf.st_mode;
  415.     break;
  416.  
  417.     case M_LMODE:
  418.     v = lstbuf.st_mode;
  419.     break;
  420.  
  421.     default:
  422.     return 0;        /* Should never happen. */
  423.     }
  424.  
  425.     if (mtypes[i].flags & M_MASKED)
  426.     v &= mtypes[i].mask;
  427.  
  428.     o = mtypes[i].flags & M_OP;
  429.     switch(o)
  430.     {
  431.     case M_EQ:
  432.     if(v == mtypes[i].value.number)
  433.     {
  434.         sprintf(buf, mtypes[i].message, v);
  435.         return 1;
  436.     }
  437.     else
  438.         return 0;
  439.     case M_LT:
  440.     if(v < mtypes[i].value.number)
  441.     {
  442.         sprintf(buf, mtypes[i].message, v);
  443.         return 1;
  444.     }
  445.     else
  446.         return 0;
  447.     case M_GT:
  448.     if(v > mtypes[i].value.number)
  449.     {
  450.         sprintf(buf, mtypes[i].message, v);
  451.         return 1;
  452.     }
  453.     else
  454.         return 0;
  455.     case M_SET:
  456.     if((v & mtypes[i].value.number) == mtypes[i].value.number)
  457.     {
  458.         sprintf(buf, mtypes[i].message, v);
  459.         return 1;
  460.     }
  461.     else
  462.         return 0;
  463.     case M_OR:
  464.     if((v & mtypes[i].value.number) != 0)
  465.     {
  466.         sprintf(buf, mtypes[i].message, v);
  467.         return 1;
  468.     }
  469.     else
  470.         return 0;
  471.     case M_ANY:
  472.     sprintf(buf, mtypes[i].message, v);
  473.     return 1;
  474.     }
  475.     return 0;
  476. }
  477.  
  478. static char *builtin_test()
  479. {
  480.     int i;
  481.  
  482.     if(builtin_result)
  483.     return builtin_result;
  484.     if(bytes > 0)
  485.     {
  486.     if(bytes > ASCLEN)
  487.         bytes = ASCLEN;
  488.     for(i = 0; i < bytes; i++)
  489.         if(!isascii(hdrbuf[i]))
  490.         return builtin_result = "data";
  491.     return builtin_result = "ascii";
  492.     }
  493.     if (bytes == 0)
  494.     {
  495.     if(S_ISREG(stbuf.st_mode))
  496.         return builtin_result = "empty";
  497.     else
  498.         return builtin_result = "special";
  499.     }
  500.     return builtin_result = "unreadable";
  501. }
  502.  
  503. static char *parse_string(s)
  504. char **s;
  505. {
  506.     char cbuf[4];
  507.     int i;
  508.     char *vptr, *sptr, *cptr;
  509.  
  510.     cptr = *s;
  511.     while(isspace(*cptr))
  512.         cptr++;
  513.     vptr = sptr = cptr;
  514.  
  515.     while(!isspace(*cptr))
  516.     {
  517.     if(*cptr != '\\')
  518.     {
  519.         *vptr++ = *cptr++;
  520.         continue;
  521.     }
  522.     cptr++;
  523.     switch(*cptr)
  524.     {
  525.     case '\\':
  526.         *vptr++ = '\\';
  527.         cptr++;
  528.         break;
  529.     case 'n':
  530.         *vptr++ = '\n';
  531.         cptr++;
  532.         break;
  533.     case 'r':
  534.         *vptr++ = '\r';
  535.         cptr++;
  536.         break;
  537.     case 't':
  538.         *vptr++ = '\t';
  539.         cptr++;
  540.         break;
  541.     case 'v':
  542.         *vptr++ = '\v';
  543.         cptr++;
  544.         break;
  545.     case 'b':
  546.         *vptr++ = '\b';
  547.         cptr++;
  548.         break;
  549.     case 'f':
  550.         *vptr++ = '\f';
  551.         cptr++;
  552.         break;
  553.     case 'x':
  554.         cptr++;
  555.         for(i = 0; i < 3 && isxdigit(*cptr); i++, cptr++)
  556.         cbuf[i] = *cptr;
  557.         cbuf[i] = '\0';
  558.         *vptr++ = (char) strtol(cbuf, 0, 16);
  559.         break;
  560.     case '0':
  561.     case '1':
  562.     case '2':
  563.     case '3':
  564.     case '4':
  565.     case '5':
  566.     case '6':
  567.     case '7':
  568.         for(i = 0; i < 3 && *cptr >= '0' && *cptr <= '7';
  569.         i++, cptr++)
  570.         cbuf[i] = *cptr;
  571.         cbuf[i] = '\0';
  572.         *vptr++ = (char) strtol(cbuf, 0, 8);
  573.         break;
  574.     default:
  575.         *vptr++ = *cptr++;
  576.     }
  577.     }
  578.     *vptr = '\0';
  579.     cptr++;
  580.     *s = cptr;
  581.     return sptr;
  582. }
  583.