home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / FILE39.ZIP / softmagic.c < prev    next >
C/C++ Source or Header  |  1993-04-10  |  9KB  |  347 lines

  1. /*
  2.  * softmagic - interpret variable magic from /etc/magic
  3.  *
  4.  * Copyright (c) Ian F. Darwin, 1987.
  5.  * Written by Ian F. Darwin.
  6.  *
  7.  * This software is not subject to any license of the American Telephone
  8.  * and Telegraph Company or of the Regents of the University of California.
  9.  *
  10.  * Permission is granted to anyone to use this software for any purpose on
  11.  * any computer system, and to alter it and redistribute it freely, subject
  12.  * to the following restrictions:
  13.  *
  14.  * 1. The author is not responsible for the consequences of use of this
  15.  *    software, no matter how awful, even if they arise from flaws in it.
  16.  *
  17.  * 2. The origin of this software must not be misrepresented, either by
  18.  *    explicit claim or by omission.  Since few users ever read sources,
  19.  *    credits must appear in the documentation.
  20.  *
  21.  * 3. Altered versions must be plainly marked as such, and must not be
  22.  *    misrepresented as being the original software.  Since few users
  23.  *    ever read sources, credits must appear in the documentation.
  24.  *
  25.  * 4. This notice may not be removed or altered.
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <time.h>
  31. #include <sys/types.h>
  32.  
  33. #include "file.h"
  34.  
  35. #ifndef    lint
  36. static char *moduleid = 
  37.     "@(#)$Id: softmagic.c,v 1.17 93/02/19 14:22:48 ian Exp $";
  38. #endif    /* lint */
  39.  
  40. static int match    __P((unsigned char *));
  41. static int mcheck    __P((unsigned char    *, struct magic *));
  42. static void mprint    __P((struct magic *, unsigned char *));
  43.  
  44. /*
  45.  * softmagic - lookup one file in database 
  46.  * (already read from /etc/magic by apprentice.c).
  47.  * Passed the name and FILE * of one file to be typed.
  48.  */
  49. /*ARGSUSED1*/        /* nbytes passed for regularity, maybe need later */
  50. int
  51. softmagic(buf, nbytes)
  52. unsigned char *buf;
  53. int nbytes;
  54. {
  55.     if (match(buf))
  56.         return 1;
  57.  
  58.     return 0;
  59. }
  60.  
  61. /*
  62.  * Go through the whole list, stopping if you find a match.  Process all
  63.  * the continuations of that match before returning.
  64.  *
  65.  * We support multi-level continuations:
  66.  *
  67.  *    At any time when processing a successful top-level match, there is a
  68.  *    current continuation level; it represents the level of the last
  69.  *    successfully matched continuation.
  70.  *
  71.  *    Continuations above that level are skipped as, if we see one, it
  72.  *    means that the continuation that controls them - i.e, the
  73.  *    lower-level continuation preceding them - failed to match.
  74.  *
  75.  *    Continuations below that level are processed as, if we see one,
  76.  *    it means we've finished processing or skipping higher-level
  77.  *    continuations under the control of a successful or unsuccessful
  78.  *    lower-level continuation, and are now seeing the next lower-level
  79.  *    continuation and should process it.  The current continuation
  80.  *    level reverts to the level of the one we're seeing.
  81.  *
  82.  *    Continuations at the current level are processed as, if we see
  83.  *    one, there's no lower-level continuation that may have failed.
  84.  *
  85.  *    If a continuation matches, we bump the current continuation level
  86.  *    so that higher-level continuations are processed.
  87.  */
  88. static int
  89. match(s)
  90. unsigned char    *s;
  91. {
  92.     int magindex = 0;
  93.     int cont_level = 0;
  94.     int need_separator = 0;
  95.  
  96.     while (magindex < nmagic) {
  97.         /* if main entry matches, print it... */
  98.         if (mcheck(s, &magic[magindex])) {
  99.             mprint(&magic[magindex],s);
  100.             /*
  101.              * If we printed something, we'll need to print
  102.              * a blank before we print something else.
  103.              */
  104.             if (magic[magindex].desc[0])
  105.                 need_separator = 1;
  106.             /* and any continuations that match */
  107.             cont_level++;
  108.             while (magic[magindex+1].cont_level != 0 &&
  109.                 magindex < nmagic) {
  110.                 ++magindex;
  111.                 if (cont_level >=
  112.                     magic[magindex].cont_level) {
  113.                     if (cont_level >
  114.                         magic[magindex].cont_level) {
  115.                         /*
  116.                          * We're at the end of the
  117.                          * level-"cont_level"
  118.                          * continuations.
  119.                          */
  120.                         cont_level = 
  121.                           magic[magindex].cont_level;
  122.                     }
  123.                     if (mcheck(s, &magic[magindex])) {
  124.                         /*
  125.                          * This continuation matched.
  126.                          * Print its message, with
  127.                          * a blank before it if
  128.                          * the previous item printed
  129.                          * and this item isn't empty.
  130.                          */
  131.                         /* space if previous printed */
  132.                         if (need_separator
  133.                            && (magic[magindex].nospflag == 0)
  134.                            && (magic[magindex].desc[0] != '\0')
  135.                            ) {
  136.                             (void) putchar(' ');
  137.                             need_separator = 0;
  138.                         }
  139.                         mprint(&magic[magindex],s);
  140.                         if (magic[magindex].desc[0])
  141.                             need_separator = 1;
  142.  
  143.                         /*
  144.                          * If we see any continuations
  145.                          * at a higher level,
  146.                          * process them.
  147.                          */
  148.                         cont_level++;
  149.                     }
  150.                 }
  151.             }
  152.             return 1;        /* all through */
  153.         } else {
  154.             /* main entry didn't match, flush its continuation */
  155.             while (magic[magindex+1].cont_level != 0 &&
  156.                 magindex < nmagic) {
  157.                 ++magindex;
  158.             }
  159.         }
  160.         ++magindex;            /* on to the next */
  161.     }
  162.     return 0;                /* no match at all */
  163. }
  164.  
  165. #ifdef OS2
  166. static void
  167. printf_eol(fmt, str)
  168. char *fmt, *str;
  169. {
  170.     char    *rt, *nl;
  171.  
  172.     if ((nl = strchr(str, '\n')) != NULL)
  173.         *nl = '\0';
  174.     if ((rt = strrchr(str, '\r')) != NULL)
  175.         *rt = '\0';
  176.     (void) printf(fmt, str);
  177.     if (rt)
  178.         *rt = '\r';
  179.     if (nl)
  180.         *nl = '\n';
  181. }
  182. #endif
  183.  
  184. static void
  185. mprint(m, s)
  186. struct magic *m;
  187. unsigned char *s;
  188. {
  189.     register union VALUETYPE *p = (union VALUETYPE *)(s+m->offset);
  190.     char *pp;
  191. #ifndef OS2
  192.     char *rt;
  193. #endif
  194.  
  195.       switch (m->type) {
  196.       case BYTE:
  197.          (void) printf(m->desc,
  198.                    (m->reln & MASK) ? p->b & m->mask : p->b);
  199.           break;
  200.       case SHORT:
  201.       case BESHORT:
  202.       case LESHORT:
  203.          (void) printf(m->desc,
  204.                    (m->reln & MASK) ? p->h & m->mask : p->h);
  205.           break;
  206.       case LONG:
  207.       case BELONG:
  208.       case LELONG:
  209.          (void) printf(m->desc,
  210.                    (m->reln & MASK) ? p->l & m->mask : p->l);
  211.           break;
  212.       case STRING:
  213. #ifdef OS2                /* handle both "\r\n" and "\n" */
  214.         (void) printf_eol(m->desc, p->s);
  215. #else        
  216.         if ((rt=strchr(p->s, '\n')) != NULL)
  217.             *rt = '\0';
  218.         (void) printf(m->desc, p->s);
  219.         if (rt)
  220.             *rt = '\n';
  221. #endif
  222.         break;
  223.     case DATE:
  224.     case BEDATE:
  225.     case LEDATE:
  226.         pp = ctime((time_t*) &p->l);
  227. #ifdef OS2                /* handle both "\r\n" and "\n" */
  228.         (void) printf(m->desc, pp);
  229. #else        
  230.         if ((rt = strchr(pp, '\n')) != NULL)
  231.             *rt = '\0';
  232.         (void) printf(m->desc, pp);
  233.         if (rt)
  234.             *rt = '\n';
  235. #endif
  236.         break;
  237.     default:
  238.         error("invalid m->type (%d) in mprint().\n", m->type);
  239.         /*NOTREACHED*/
  240.     }
  241. }
  242.  
  243. static int
  244. mcheck(s, m)
  245. unsigned char    *s;
  246. struct magic *m;
  247. {
  248.     register union VALUETYPE *p = (union VALUETYPE *)(s+m->offset);
  249.     register long l = m->value.l;
  250.     register long mask = m->mask;
  251.     register long v;
  252.  
  253.     if (debug) {
  254.         (void) printf("mcheck: %10.10s ", s);
  255.         mdump(m);
  256.     }
  257.  
  258.     if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
  259.         printf("BOINK");
  260.         return 1;
  261.     }
  262.  
  263.     switch (m->type) {
  264.     case BYTE:
  265.         v = p->b; break;
  266.     case SHORT:
  267.         v = p->h; break;
  268.     case LONG:
  269.     case DATE:
  270.         v = p->l; break;
  271.     case STRING:
  272.         l = 0;
  273.         /* What we want here is:
  274.          * v = strncmp(m->value.s, p->s, m->vallen);
  275.          * but ignoring any nulls.  bcmp doesn't give -/+/0
  276.          * and isn't universally available anyway.
  277.          */
  278.         v = 0;
  279.         {
  280.             register unsigned char *a = (unsigned char*)m->value.s;
  281.             register unsigned char *b = (unsigned char*)p->s;
  282.             register int len = m->vallen;
  283.  
  284.             while (--len >= 0)
  285.                 if ((v = *b++ - *a++) != 0)
  286.                     break;
  287.         }
  288.         break;
  289.     case BESHORT:
  290.         v = (short)((p->hs[0]<<8)|(p->hs[1]));
  291.         break;
  292.     case BELONG:
  293.     case BEDATE:
  294.         v = (long)
  295. #ifdef MSC        /* bugfix, required for 16-bit int */
  296.             (((long) p->hl[0]<<24)|((long) p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  297. #else
  298.             ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  299. #endif
  300.         break;
  301.     case LESHORT:
  302.         v = (short)((p->hs[1]<<8)|(p->hs[0]));
  303.         break;
  304.     case LELONG:
  305.     case LEDATE:
  306.         v = (long)
  307. #ifdef MSC        /* bugfix, required for 16-bit int */
  308.             (((long) p->hl[3]<<24)|((long) p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  309. #else
  310.             ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  311. #endif
  312.         break;
  313.     default:
  314.         error("invalid type %d in mcheck().\n", m->type);
  315.         return -1;/*NOTREACHED*/
  316.     }
  317.  
  318.     if (m->mask != 0L)
  319.         v &= m->mask;
  320.  
  321.     switch (m->reln) {
  322.     case 'x':
  323.         return 1;
  324.     case '!':
  325.         return v != l;
  326.     case '=':
  327.         return v == l;
  328.     case '>':
  329.         return v > l;
  330.     case '<':
  331.         return v < l;
  332.     case '&':
  333.         return (v & l) == l;
  334.     case '^':
  335.         return (v & l) != l;
  336.     case MASK | '=':
  337.         return (v & mask) == l;
  338.     case MASK | '>':
  339.         return (v & mask) > l;
  340.     case MASK | '<':
  341.         return (v & mask) < l;
  342.     default:
  343.         error("mcheck: can't happen: invalid relation %d.\n", m->reln);
  344.         return -1;/*NOTREACHED*/
  345.     }
  346. }
  347.