softmagic.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. /*
  2. * softmagic - interpret variable magic from 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. #include <stdio.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <stdlib.h>
  31. #include <time.h>
  32. #include <sys/types.h>
  33. #include "file.h"
  34. #ifndef lint
  35. FILE_RCSID("@(#)$Id: softmagic.c,v 1.46 2001/07/23 00:02:32 christos Exp $")
  36. #endif /* lint */
  37. static int match __P((struct magic *, uint32, unsigned char *, int));
  38. static int mget __P((union VALUETYPE *,
  39. unsigned char *, struct magic *, int));
  40. static int mcheck __P((union VALUETYPE *, struct magic *));
  41. static int32 mprint __P((union VALUETYPE *, struct magic *));
  42. static void mdebug __P((int32, char *, int));
  43. static int mconvert __P((union VALUETYPE *, struct magic *));
  44. extern int kflag;
  45. /*
  46. * softmagic - lookup one file in database
  47. * (already read from /etc/magic by apprentice.c).
  48. * Passed the name and FILE * of one file to be typed.
  49. */
  50. /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
  51. int
  52. softmagic(buf, nbytes)
  53. unsigned char *buf;
  54. int nbytes;
  55. {
  56. struct mlist *ml;
  57. for (ml = mlist.next; ml != &mlist; ml = ml->next)
  58. if (match(ml->magic, ml->nmagic, buf, nbytes))
  59. return 1;
  60. return 0;
  61. }
  62. /*
  63. * Go through the whole list, stopping if you find a match. Process all
  64. * the continuations of that match before returning.
  65. *
  66. * We support multi-level continuations:
  67. *
  68. * At any time when processing a successful top-level match, there is a
  69. * current continuation level; it represents the level of the last
  70. * successfully matched continuation.
  71. *
  72. * Continuations above that level are skipped as, if we see one, it
  73. * means that the continuation that controls them - i.e, the
  74. * lower-level continuation preceding them - failed to match.
  75. *
  76. * Continuations below that level are processed as, if we see one,
  77. * it means we've finished processing or skipping higher-level
  78. * continuations under the control of a successful or unsuccessful
  79. * lower-level continuation, and are now seeing the next lower-level
  80. * continuation and should process it. The current continuation
  81. * level reverts to the level of the one we're seeing.
  82. *
  83. * Continuations at the current level are processed as, if we see
  84. * one, there's no lower-level continuation that may have failed.
  85. *
  86. * If a continuation matches, we bump the current continuation level
  87. * so that higher-level continuations are processed.
  88. */
  89. static int
  90. match(magic, nmagic, s, nbytes)
  91. struct magic *magic;
  92. uint32 nmagic;
  93. unsigned char *s;
  94. int nbytes;
  95. {
  96. int magindex = 0;
  97. int cont_level = 0;
  98. int need_separator = 0;
  99. union VALUETYPE p;
  100. static int32 *tmpoff = NULL;
  101. static size_t tmplen = 0;
  102. int32 oldoff = 0;
  103. int returnval = 0; /* if a match is found it is set to 1*/
  104. int firstline = 1; /* a flag to print X\n X\n- X */
  105. if (tmpoff == NULL)
  106. if ((tmpoff = (int32 *) malloc(tmplen = 20)) == NULL)
  107. error("out of memory\n");
  108. for (magindex = 0; magindex < nmagic; magindex++) {
  109. /* if main entry matches, print it... */
  110. if (!mget(&p, s, &magic[magindex], nbytes) ||
  111. !mcheck(&p, &magic[magindex])) {
  112. /*
  113. * main entry didn't match,
  114. * flush its continuations
  115. */
  116. while (magindex < nmagic &&
  117. magic[magindex + 1].cont_level != 0)
  118. magindex++;
  119. continue;
  120. }
  121. if (! firstline) { /* we found another match */
  122. /* put a newline and '-' to do some simple formatting*/
  123. printf("\n- ");
  124. }
  125. tmpoff[cont_level] = mprint(&p, &magic[magindex]);
  126. /*
  127. * If we printed something, we'll need to print
  128. * a blank before we print something else.
  129. */
  130. if (magic[magindex].desc[0])
  131. need_separator = 1;
  132. /* and any continuations that match */
  133. if (++cont_level >= tmplen)
  134. if ((tmpoff = (int32 *) realloc(tmpoff,
  135. tmplen += 20)) == NULL)
  136. error("out of memory\n");
  137. while (magic[magindex+1].cont_level != 0 &&
  138. ++magindex < nmagic) {
  139. if (cont_level >= magic[magindex].cont_level) {
  140. if (cont_level > magic[magindex].cont_level) {
  141. /*
  142. * We're at the end of the level
  143. * "cont_level" continuations.
  144. */
  145. cont_level = magic[magindex].cont_level;
  146. }
  147. if (magic[magindex].flag & OFFADD) {
  148. oldoff=magic[magindex].offset;
  149. magic[magindex].offset +=
  150. tmpoff[cont_level-1];
  151. }
  152. if (mget(&p, s, &magic[magindex], nbytes) &&
  153. mcheck(&p, &magic[magindex])) {
  154. /*
  155. * This continuation matched.
  156. * Print its message, with
  157. * a blank before it if
  158. * the previous item printed
  159. * and this item isn't empty.
  160. */
  161. /* space if previous printed */
  162. if (need_separator
  163. && (magic[magindex].nospflag == 0)
  164. && (magic[magindex].desc[0] != '\0')
  165. ) {
  166. (void) putchar(' ');
  167. need_separator = 0;
  168. }
  169. tmpoff[cont_level] =
  170. mprint(&p, &magic[magindex]);
  171. if (magic[magindex].desc[0])
  172. need_separator = 1;
  173. /*
  174. * If we see any continuations
  175. * at a higher level,
  176. * process them.
  177. */
  178. if (++cont_level >= tmplen)
  179. if ((tmpoff =
  180. (int32 *) realloc(tmpoff,
  181. tmplen += 20)) == NULL)
  182. error("out of memory\n");
  183. }
  184. if (magic[magindex].flag & OFFADD) {
  185. magic[magindex].offset = oldoff;
  186. }
  187. }
  188. }
  189. firstline = 0;
  190. returnval = 1;
  191. if (!kflag) {
  192. return 1; /* don't keep searching */
  193. }
  194. }
  195. return returnval; /* This is hit if -k is set or there is no match */
  196. }
  197. static int32
  198. mprint(p, m)
  199. union VALUETYPE *p;
  200. struct magic *m;
  201. {
  202. uint32 v;
  203. int32 t=0 ;
  204. switch (m->type) {
  205. case BYTE:
  206. v = signextend(m, p->b);
  207. (void) printf(m->desc, (unsigned char) v);
  208. t = m->offset + sizeof(char);
  209. break;
  210. case SHORT:
  211. case BESHORT:
  212. case LESHORT:
  213. v = signextend(m, p->h);
  214. (void) printf(m->desc, (unsigned short) v);
  215. t = m->offset + sizeof(short);
  216. break;
  217. case LONG:
  218. case BELONG:
  219. case LELONG:
  220. v = signextend(m, p->l);
  221. (void) printf(m->desc, (uint32) v);
  222. t = m->offset + sizeof(int32);
  223. break;
  224. case STRING:
  225. case PSTRING:
  226. if (m->reln == '=') {
  227. (void) printf(m->desc, m->value.s);
  228. t = m->offset + strlen(m->value.s);
  229. }
  230. else {
  231. if (*m->value.s == '\0') {
  232. char *cp = strchr(p->s,'\n');
  233. if (cp)
  234. *cp = '\0';
  235. }
  236. (void) printf(m->desc, p->s);
  237. t = m->offset + strlen(p->s);
  238. }
  239. break;
  240. case DATE:
  241. case BEDATE:
  242. case LEDATE:
  243. (void) printf(m->desc, fmttime(p->l, 1));
  244. t = m->offset + sizeof(time_t);
  245. break;
  246. case LDATE:
  247. case BELDATE:
  248. case LELDATE:
  249. (void) printf(m->desc, fmttime(p->l, 0));
  250. t = m->offset + sizeof(time_t);
  251. break;
  252. default:
  253. error("invalid m->type (%d) in mprint().\n", m->type);
  254. /*NOTREACHED*/
  255. }
  256. return(t);
  257. }
  258. /*
  259. * Convert the byte order of the data we are looking at
  260. * While we're here, let's apply the mask operation
  261. * (unless you have a better idea)
  262. */
  263. static int
  264. mconvert(p, m)
  265. union VALUETYPE *p;
  266. struct magic *m;
  267. {
  268. switch (m->type) {
  269. case BYTE:
  270. if (m->mask)
  271. switch (m->mask_op&0x7F) {
  272. case OPAND:
  273. p->b &= m->mask;
  274. break;
  275. case OPOR:
  276. p->b |= m->mask;
  277. break;
  278. case OPXOR:
  279. p->b ^= m->mask;
  280. break;
  281. case OPADD:
  282. p->b += m->mask;
  283. break;
  284. case OPMINUS:
  285. p->b -= m->mask;
  286. break;
  287. case OPMULTIPLY:
  288. p->b *= m->mask;
  289. break;
  290. case OPDIVIDE:
  291. p->b /= m->mask;
  292. break;
  293. case OPMODULO:
  294. p->b %= m->mask;
  295. break;
  296. }
  297. if (m->mask_op & OPINVERSE)
  298. p->b = ~p->b;
  299. return 1;
  300. case SHORT:
  301. if (m->mask)
  302. switch (m->mask_op&0x7F) {
  303. case OPAND:
  304. p->h &= m->mask;
  305. break;
  306. case OPOR:
  307. p->h |= m->mask;
  308. break;
  309. case OPXOR:
  310. p->h ^= m->mask;
  311. break;
  312. case OPADD:
  313. p->h += m->mask;
  314. break;
  315. case OPMINUS:
  316. p->h -= m->mask;
  317. break;
  318. case OPMULTIPLY:
  319. p->h *= m->mask;
  320. break;
  321. case OPDIVIDE:
  322. p->h /= m->mask;
  323. break;
  324. case OPMODULO:
  325. p->h %= m->mask;
  326. break;
  327. }
  328. if (m->mask_op & OPINVERSE)
  329. p->h = ~p->h;
  330. return 1;
  331. case LONG:
  332. case DATE:
  333. case LDATE:
  334. if (m->mask)
  335. switch (m->mask_op&0x7F) {
  336. case OPAND:
  337. p->l &= m->mask;
  338. break;
  339. case OPOR:
  340. p->l |= m->mask;
  341. break;
  342. case OPXOR:
  343. p->l ^= m->mask;
  344. break;
  345. case OPADD:
  346. p->l += m->mask;
  347. break;
  348. case OPMINUS:
  349. p->l -= m->mask;
  350. break;
  351. case OPMULTIPLY:
  352. p->l *= m->mask;
  353. break;
  354. case OPDIVIDE:
  355. p->l /= m->mask;
  356. break;
  357. case OPMODULO:
  358. p->l %= m->mask;
  359. break;
  360. }
  361. if (m->mask_op & OPINVERSE)
  362. p->l = ~p->l;
  363. return 1;
  364. case STRING:
  365. {
  366. int n;
  367. /* Null terminate and eat *trailing* return */
  368. p->s[sizeof(p->s) - 1] = '\0';
  369. n = strlen(p->s) - 1;
  370. if (p->s[n] == '\n')
  371. p->s[n] = '\0';
  372. return 1;
  373. }
  374. case PSTRING:
  375. {
  376. char *ptr1 = p->s, *ptr2 = ptr1 + 1;
  377. int n = *p->s;
  378. if (n >= sizeof(p->s))
  379. n = sizeof(p->s) - 1;
  380. while (n--)
  381. *ptr1++ = *ptr2++;
  382. *ptr1 = '\0';
  383. n = strlen(p->s) - 1;
  384. if (p->s[n] == '\n')
  385. p->s[n] = '\0';
  386. return 1;
  387. }
  388. case BESHORT:
  389. p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  390. if (m->mask)
  391. switch (m->mask_op&0x7F) {
  392. case OPAND:
  393. p->h &= m->mask;
  394. break;
  395. case OPOR:
  396. p->h |= m->mask;
  397. break;
  398. case OPXOR:
  399. p->h ^= m->mask;
  400. break;
  401. case OPADD:
  402. p->h += m->mask;
  403. break;
  404. case OPMINUS:
  405. p->h -= m->mask;
  406. break;
  407. case OPMULTIPLY:
  408. p->h *= m->mask;
  409. break;
  410. case OPDIVIDE:
  411. p->h /= m->mask;
  412. break;
  413. case OPMODULO:
  414. p->h %= m->mask;
  415. break;
  416. }
  417. if (m->mask_op & OPINVERSE)
  418. p->h = ~p->h;
  419. return 1;
  420. case BELONG:
  421. case BEDATE:
  422. case BELDATE:
  423. p->l = (int32)
  424. ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  425. if (m->mask)
  426. switch (m->mask_op&0x7F) {
  427. case OPAND:
  428. p->l &= m->mask;
  429. break;
  430. case OPOR:
  431. p->l |= m->mask;
  432. break;
  433. case OPXOR:
  434. p->l ^= m->mask;
  435. break;
  436. case OPADD:
  437. p->l += m->mask;
  438. break;
  439. case OPMINUS:
  440. p->l -= m->mask;
  441. break;
  442. case OPMULTIPLY:
  443. p->l *= m->mask;
  444. break;
  445. case OPDIVIDE:
  446. p->l /= m->mask;
  447. break;
  448. case OPMODULO:
  449. p->l %= m->mask;
  450. break;
  451. }
  452. if (m->mask_op & OPINVERSE)
  453. p->l = ~p->l;
  454. return 1;
  455. case LESHORT:
  456. p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  457. if (m->mask)
  458. switch (m->mask_op&0x7F) {
  459. case OPAND:
  460. p->h &= m->mask;
  461. break;
  462. case OPOR:
  463. p->h |= m->mask;
  464. break;
  465. case OPXOR:
  466. p->h ^= m->mask;
  467. break;
  468. case OPADD:
  469. p->h += m->mask;
  470. break;
  471. case OPMINUS:
  472. p->h -= m->mask;
  473. break;
  474. case OPMULTIPLY:
  475. p->h *= m->mask;
  476. break;
  477. case OPDIVIDE:
  478. p->h /= m->mask;
  479. break;
  480. case OPMODULO:
  481. p->h %= m->mask;
  482. break;
  483. }
  484. if (m->mask_op & OPINVERSE)
  485. p->h = ~p->h;
  486. return 1;
  487. case LELONG:
  488. case LEDATE:
  489. case LELDATE:
  490. p->l = (int32)
  491. ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  492. if (m->mask)
  493. switch (m->mask_op&0x7F) {
  494. case OPAND:
  495. p->l &= m->mask;
  496. break;
  497. case OPOR:
  498. p->l |= m->mask;
  499. break;
  500. case OPXOR:
  501. p->l ^= m->mask;
  502. break;
  503. case OPADD:
  504. p->l += m->mask;
  505. break;
  506. case OPMINUS:
  507. p->l -= m->mask;
  508. break;
  509. case OPMULTIPLY:
  510. p->l *= m->mask;
  511. break;
  512. case OPDIVIDE:
  513. p->l /= m->mask;
  514. break;
  515. case OPMODULO:
  516. p->l %= m->mask;
  517. break;
  518. }
  519. if (m->mask_op & OPINVERSE)
  520. p->l = ~p->l;
  521. return 1;
  522. default:
  523. error("invalid type %d in mconvert().\n", m->type);
  524. return 0;
  525. }
  526. }
  527. static void
  528. mdebug(offset, str, len)
  529. int32 offset;
  530. char *str;
  531. int len;
  532. {
  533. (void) fprintf(stderr, "mget @%d: ", offset);
  534. showstr(stderr, (char *) str, len);
  535. (void) fputc('\n', stderr);
  536. (void) fputc('\n', stderr);
  537. }
  538. static int
  539. mget(p, s, m, nbytes)
  540. union VALUETYPE* p;
  541. unsigned char *s;
  542. struct magic *m;
  543. int nbytes;
  544. {
  545. int32 offset = m->offset;
  546. if (offset + sizeof(union VALUETYPE) <= nbytes)
  547. memcpy(p, s + offset, sizeof(union VALUETYPE));
  548. else {
  549. /*
  550. * the usefulness of padding with zeroes eludes me, it
  551. * might even cause problems
  552. */
  553. int32 have = nbytes - offset;
  554. memset(p, 0, sizeof(union VALUETYPE));
  555. if (have > 0)
  556. memcpy(p, s + offset, have);
  557. }
  558. if (debug) {
  559. mdebug(offset, (char *) p, sizeof(union VALUETYPE));
  560. mdump(m);
  561. }
  562. if (m->flag & INDIR) {
  563. switch (m->in_type) {
  564. case BYTE:
  565. if (m->in_offset)
  566. switch (m->in_op&0x7F) {
  567. case OPAND:
  568. offset = p->b & m->in_offset;
  569. break;
  570. case OPOR:
  571. offset = p->b | m->in_offset;
  572. break;
  573. case OPXOR:
  574. offset = p->b ^ m->in_offset;
  575. break;
  576. case OPADD:
  577. offset = p->b + m->in_offset;
  578. break;
  579. case OPMINUS:
  580. offset = p->b - m->in_offset;
  581. break;
  582. case OPMULTIPLY:
  583. offset = p->b * m->in_offset;
  584. break;
  585. case OPDIVIDE:
  586. offset = p->b / m->in_offset;
  587. break;
  588. case OPMODULO:
  589. offset = p->b % m->in_offset;
  590. break;
  591. }
  592. if (m->in_op & OPINVERSE)
  593. offset = ~offset;
  594. break;
  595. case BESHORT:
  596. if (m->in_offset)
  597. switch (m->in_op&0x7F) {
  598. case OPAND:
  599. offset = (short)((p->hs[0]<<8)|
  600. (p->hs[1])) &
  601. m->in_offset;
  602. break;
  603. case OPOR:
  604. offset = (short)((p->hs[0]<<8)|
  605. (p->hs[1])) |
  606. m->in_offset;
  607. break;
  608. case OPXOR:
  609. offset = (short)((p->hs[0]<<8)|
  610. (p->hs[1])) ^
  611. m->in_offset;
  612. break;
  613. case OPADD:
  614. offset = (short)((p->hs[0]<<8)|
  615. (p->hs[1])) +
  616. m->in_offset;
  617. break;
  618. case OPMINUS:
  619. offset = (short)((p->hs[0]<<8)|
  620. (p->hs[1])) -
  621. m->in_offset;
  622. break;
  623. case OPMULTIPLY:
  624. offset = (short)((p->hs[0]<<8)|
  625. (p->hs[1])) *
  626. m->in_offset;
  627. break;
  628. case OPDIVIDE:
  629. offset = (short)((p->hs[0]<<8)|
  630. (p->hs[1])) /
  631. m->in_offset;
  632. break;
  633. case OPMODULO:
  634. offset = (short)((p->hs[0]<<8)|
  635. (p->hs[1])) %
  636. m->in_offset;
  637. break;
  638. }
  639. if (m->in_op & OPINVERSE)
  640. offset = ~offset;
  641. break;
  642. case LESHORT:
  643. if (m->in_offset)
  644. switch (m->in_op&0x7F) {
  645. case OPAND:
  646. offset = (short)((p->hs[1]<<8)|
  647. (p->hs[0])) &
  648. m->in_offset;
  649. break;
  650. case OPOR:
  651. offset = (short)((p->hs[1]<<8)|
  652. (p->hs[0])) |
  653. m->in_offset;
  654. break;
  655. case OPXOR:
  656. offset = (short)((p->hs[1]<<8)|
  657. (p->hs[0])) ^
  658. m->in_offset;
  659. break;
  660. case OPADD:
  661. offset = (short)((p->hs[1]<<8)|
  662. (p->hs[0])) +
  663. m->in_offset;
  664. break;
  665. case OPMINUS:
  666. offset = (short)((p->hs[1]<<8)|
  667. (p->hs[0])) -
  668. m->in_offset;
  669. break;
  670. case OPMULTIPLY:
  671. offset = (short)((p->hs[1]<<8)|
  672. (p->hs[0])) *
  673. m->in_offset;
  674. break;
  675. case OPDIVIDE:
  676. offset = (short)((p->hs[1]<<8)|
  677. (p->hs[0])) /
  678. m->in_offset;
  679. break;
  680. case OPMODULO:
  681. offset = (short)((p->hs[1]<<8)|
  682. (p->hs[0])) %
  683. m->in_offset;
  684. break;
  685. }
  686. if (m->in_op & OPINVERSE)
  687. offset = ~offset;
  688. break;
  689. case SHORT:
  690. if (m->in_offset)
  691. switch (m->in_op&0x7F) {
  692. case OPAND:
  693. offset = p->h & m->in_offset;
  694. break;
  695. case OPOR:
  696. offset = p->h | m->in_offset;
  697. break;
  698. case OPXOR:
  699. offset = p->h ^ m->in_offset;
  700. break;
  701. case OPADD:
  702. offset = p->h + m->in_offset;
  703. break;
  704. case OPMINUS:
  705. offset = p->h - m->in_offset;
  706. break;
  707. case OPMULTIPLY:
  708. offset = p->h * m->in_offset;
  709. break;
  710. case OPDIVIDE:
  711. offset = p->h / m->in_offset;
  712. break;
  713. case OPMODULO:
  714. offset = p->h % m->in_offset;
  715. break;
  716. }
  717. if (m->in_op & OPINVERSE)
  718. offset = ~offset;
  719. break;
  720. case BELONG:
  721. if (m->in_offset)
  722. switch (m->in_op&0x7F) {
  723. case OPAND:
  724. offset = (int32)((p->hl[0]<<24)|
  725. (p->hl[1]<<16)|
  726. (p->hl[2]<<8)|
  727. (p->hl[3])) &
  728. m->in_offset;
  729. break;
  730. case OPOR:
  731. offset = (int32)((p->hl[0]<<24)|
  732. (p->hl[1]<<16)|
  733. (p->hl[2]<<8)|
  734. (p->hl[3])) |
  735. m->in_offset;
  736. break;
  737. case OPXOR:
  738. offset = (int32)((p->hl[0]<<24)|
  739. (p->hl[1]<<16)|
  740. (p->hl[2]<<8)|
  741. (p->hl[3])) ^
  742. m->in_offset;
  743. break;
  744. case OPADD:
  745. offset = (int32)((p->hl[0]<<24)|
  746. (p->hl[1]<<16)|
  747. (p->hl[2]<<8)|
  748. (p->hl[3])) +
  749. m->in_offset;
  750. break;
  751. case OPMINUS:
  752. offset = (int32)((p->hl[0]<<24)|
  753. (p->hl[1]<<16)|
  754. (p->hl[2]<<8)|
  755. (p->hl[3])) -
  756. m->in_offset;
  757. break;
  758. case OPMULTIPLY:
  759. offset = (int32)((p->hl[0]<<24)|
  760. (p->hl[1]<<16)|
  761. (p->hl[2]<<8)|
  762. (p->hl[3])) *
  763. m->in_offset;
  764. break;
  765. case OPDIVIDE:
  766. offset = (int32)((p->hl[0]<<24)|
  767. (p->hl[1]<<16)|
  768. (p->hl[2]<<8)|
  769. (p->hl[3])) /
  770. m->in_offset;
  771. break;
  772. case OPMODULO:
  773. offset = (int32)((p->hl[0]<<24)|
  774. (p->hl[1]<<16)|
  775. (p->hl[2]<<8)|
  776. (p->hl[3])) %
  777. m->in_offset;
  778. break;
  779. }
  780. if (m->in_op & OPINVERSE)
  781. offset = ~offset;
  782. break;
  783. case LELONG:
  784. if (m->in_offset)
  785. switch (m->in_op&0x7F) {
  786. case OPAND:
  787. offset = (int32)((p->hl[3]<<24)|
  788. (p->hl[2]<<16)|
  789. (p->hl[1]<<8)|
  790. (p->hl[0])) &
  791. m->in_offset;
  792. break;
  793. case OPOR:
  794. offset = (int32)((p->hl[3]<<24)|
  795. (p->hl[2]<<16)|
  796. (p->hl[1]<<8)|
  797. (p->hl[0])) |
  798. m->in_offset;
  799. break;
  800. case OPXOR:
  801. offset = (int32)((p->hl[3]<<24)|
  802. (p->hl[2]<<16)|
  803. (p->hl[1]<<8)|
  804. (p->hl[0])) ^
  805. m->in_offset;
  806. break;
  807. case OPADD:
  808. offset = (int32)((p->hl[3]<<24)|
  809. (p->hl[2]<<16)|
  810. (p->hl[1]<<8)|
  811. (p->hl[0])) +
  812. m->in_offset;
  813. break;
  814. case OPMINUS:
  815. offset = (int32)((p->hl[3]<<24)|
  816. (p->hl[2]<<16)|
  817. (p->hl[1]<<8)|
  818. (p->hl[0])) -
  819. m->in_offset;
  820. break;
  821. case OPMULTIPLY:
  822. offset = (int32)((p->hl[3]<<24)|
  823. (p->hl[2]<<16)|
  824. (p->hl[1]<<8)|
  825. (p->hl[0])) *
  826. m->in_offset;
  827. break;
  828. case OPDIVIDE:
  829. offset = (int32)((p->hl[3]<<24)|
  830. (p->hl[2]<<16)|
  831. (p->hl[1]<<8)|
  832. (p->hl[0])) /
  833. m->in_offset;
  834. break;
  835. case OPMODULO:
  836. offset = (int32)((p->hl[3]<<24)|
  837. (p->hl[2]<<16)|
  838. (p->hl[1]<<8)|
  839. (p->hl[0])) %
  840. m->in_offset;
  841. break;
  842. }
  843. if (m->in_op & OPINVERSE)
  844. offset = ~offset;
  845. break;
  846. case LONG:
  847. if (m->in_offset)
  848. switch (m->in_op&0x7F) {
  849. case OPAND:
  850. offset = p->l & m->in_offset;
  851. break;
  852. case OPOR:
  853. offset = p->l | m->in_offset;
  854. break;
  855. case OPXOR:
  856. offset = p->l ^ m->in_offset;
  857. break;
  858. case OPADD:
  859. offset = p->l + m->in_offset;
  860. break;
  861. case OPMINUS:
  862. offset = p->l - m->in_offset;
  863. break;
  864. case OPMULTIPLY:
  865. offset = p->l * m->in_offset;
  866. break;
  867. case OPDIVIDE:
  868. offset = p->l / m->in_offset;
  869. break;
  870. case OPMODULO:
  871. offset = p->l % m->in_offset;
  872. break;
  873. /* case TOOMANYSWITCHBLOCKS:
  874. * ugh = p->eye % m->strain;
  875. * rub;
  876. * case BEER:
  877. * off = p->tab & m->in_gest;
  878. * sleep;
  879. */
  880. }
  881. if (m->in_op & OPINVERSE)
  882. offset = ~offset;
  883. break;
  884. }
  885. if (offset + sizeof(union VALUETYPE) > nbytes)
  886. return 0;
  887. memcpy(p, s + offset, sizeof(union VALUETYPE));
  888. if (debug) {
  889. mdebug(offset, (char *) p, sizeof(union VALUETYPE));
  890. mdump(m);
  891. }
  892. }
  893. if (!mconvert(p, m))
  894. return 0;
  895. return 1;
  896. }
  897. static int
  898. mcheck(p, m)
  899. union VALUETYPE* p;
  900. struct magic *m;
  901. {
  902. uint32 l = m->value.l;
  903. uint32 v;
  904. int matched;
  905. if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
  906. fprintf(stderr, "BOINK");
  907. return 1;
  908. }
  909. switch (m->type) {
  910. case BYTE:
  911. v = p->b;
  912. break;
  913. case SHORT:
  914. case BESHORT:
  915. case LESHORT:
  916. v = p->h;
  917. break;
  918. case LONG:
  919. case BELONG:
  920. case LELONG:
  921. case DATE:
  922. case BEDATE:
  923. case LEDATE:
  924. case LDATE:
  925. case BELDATE:
  926. case LELDATE:
  927. v = p->l;
  928. break;
  929. case STRING:
  930. case PSTRING:
  931. {
  932. /*
  933. * What we want here is:
  934. * v = strncmp(m->value.s, p->s, m->vallen);
  935. * but ignoring any nulls. bcmp doesn't give -/+/0
  936. * and isn't universally available anyway.
  937. */
  938. unsigned char *a = (unsigned char*)m->value.s;
  939. unsigned char *b = (unsigned char*)p->s;
  940. int len = m->vallen;
  941. l = 0;
  942. v = 0;
  943. if (0L == m->mask) { /* normal string: do it fast */
  944. while (--len >= 0)
  945. if ((v = *b++ - *a++) != '\0')
  946. break;
  947. } else { /* combine the others */
  948. while (--len >= 0) {
  949. if ((m->mask & STRING_IGNORE_LOWERCASE) &&
  950. islower(*a)) {
  951. if ((v = tolower(*b++) - *a++) != '\0')
  952. break;
  953. } else if ((m->mask & STRING_COMPACT_BLANK) &&
  954. isspace(*a)) {
  955. a++;
  956. if (isspace(*b++)) {
  957. while (isspace(*b))
  958. b++;
  959. } else {
  960. v = 1;
  961. break;
  962. }
  963. } else if (isspace(*a) &&
  964. (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
  965. a++;
  966. while (isspace(*b))
  967. b++;
  968. } else {
  969. if ((v = *b++ - *a++) != '\0')
  970. break;
  971. }
  972. }
  973. }
  974. break;
  975. }
  976. default:
  977. error("invalid type %d in mcheck().\n", m->type);
  978. return 0;/*NOTREACHED*/
  979. }
  980. if(m->type != STRING && m->type != PSTRING)
  981. v = signextend(m, v);
  982. switch (m->reln) {
  983. case 'x':
  984. if (debug)
  985. (void) fprintf(stderr, "%u == *any* = 1\n", v);
  986. matched = 1;
  987. break;
  988. case '!':
  989. matched = v != l;
  990. if (debug)
  991. (void) fprintf(stderr, "%u != %u = %d\n",
  992. v, l, matched);
  993. break;
  994. case '=':
  995. matched = v == l;
  996. if (debug)
  997. (void) fprintf(stderr, "%u == %u = %d\n",
  998. v, l, matched);
  999. break;
  1000. case '>':
  1001. if (m->flag & UNSIGNED) {
  1002. matched = v > l;
  1003. if (debug)
  1004. (void) fprintf(stderr, "%u > %u = %d\n",
  1005. v, l, matched);
  1006. }
  1007. else {
  1008. matched = (int32) v > (int32) l;
  1009. if (debug)
  1010. (void) fprintf(stderr, "%d > %d = %d\n",
  1011. v, l, matched);
  1012. }
  1013. break;
  1014. case '<':
  1015. if (m->flag & UNSIGNED) {
  1016. matched = v < l;
  1017. if (debug)
  1018. (void) fprintf(stderr, "%u < %u = %d\n",
  1019. v, l, matched);
  1020. }
  1021. else {
  1022. matched = (int32) v < (int32) l;
  1023. if (debug)
  1024. (void) fprintf(stderr, "%d < %d = %d\n",
  1025. v, l, matched);
  1026. }
  1027. break;
  1028. case '&':
  1029. matched = (v & l) == l;
  1030. if (debug)
  1031. (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
  1032. v, l, l, matched);
  1033. break;
  1034. case '^':
  1035. matched = (v & l) != l;
  1036. if (debug)
  1037. (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
  1038. v, l, l, matched);
  1039. break;
  1040. default:
  1041. matched = 0;
  1042. error("mcheck: can't happen: invalid relation %d.\n", m->reln);
  1043. break;/*NOTREACHED*/
  1044. }
  1045. return matched;
  1046. }