FOSSology  4.4.0
Open Source License Compliance by Open Source Software
licenses.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2006-2013 Hewlett-Packard Development Company, L.P.
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
6 /* Equivalent to core nomos v1.48 */
7 
15 #define _GNU_SOURCE
16 
17 #include <stdio.h>
18 #include <string.h>
19 #include <ctype.h>
20 #include <time.h>
21 #include <signal.h>
22 #include <libgen.h>
23 #include <limits.h>
24 #include <stdlib.h>
25 
26 #include "nomos.h"
27 #include "licenses.h"
28 #include "nomos_utils.h"
29 #include "util.h"
30 #include "list.h"
31 #include "nomos_regex.h"
32 #include "parse.h"
33 #include <_autodefs.h>
34 
35 #define HASHES "#####################"
36 #define DEBCPYRIGHT "debian/copyright"
37 
38 static void makeLicenseSummary(list_t *, int, char *, int);
39 static void noLicenseFound();
40 #ifdef notdef
41 static void licenseStringChecks();
42 static void findLines(char *, char *, int, int, list_t *);
43 #endif /* notdef */
44 static int searchStrategy(int, char *, int);
45 static void saveLicenseData(scanres_t *, int, int, int);
46 static int scoreCompare(const void *, const void *);
47 static void printHighlightInfo(GArray* keyWords, GArray* theMatches);
48 static char any[6];
49 static char some[7];
50 static char few[6];
51 static char year[7];
52 
53 #ifdef MEMSTATS
54 extern void memStats();
55 #endif /* MEMSTATS */
56 #ifdef STOPWATCH
57 DECL_TIMER;
58 int timerBytes;
59 char timerName[64];
60 #endif /* STOPWATCH */
61 
62 #ifndef MAX
63 #define MAX(a, b) ((a) > (b) ? a : b)
64 #define MIN(a, b) ((a) < (b) ? a : b)
65 #endif
66 
70 void licenseInit() {
71 
72  int i;
73  int len;
74  int same;
75  int ssAbove = 0;
76  int ssBelow = 0;
77  item_t *p;
78  char *cp;
79  char buf[myBUFSIZ];
80 
81 #ifdef PROC_TRACE
82  traceFunc("== licenseInit()\n");
83 #endif /* PROC_TRACE */
84 
85  strcpy(any, "=ANY=");
86  strcpy(some, "=SOME=");
87  strcpy(few, "=FEW=");
88  strcpy(year, "=YEAR=");
89  listInit(&gl.sHash, 0, "search-cache"); /* CDB - Added */
90 
98  for (i = 0; i < NFOOTPRINTS; i++) {
99  same = 0;
100  len = licSpec[i].seed.csLen;
101  if (licSpec[i].text.csData == NULL_STR) {
102  licText[i].tseed = "(null)";
103  }
104  if ((licSpec[i].text.csLen == 1) && (*(licSpec[i].text.csData) == '.')) {
105  same++;
106  /*CDB -- CHanged next line to use ! */
107  }
108  else if ((licSpec[i].seed.csLen == licSpec[i].text.csLen) && !memcmp(
109  licSpec[i].seed.csData, licSpec[i].text.csData, len)) {
110  same++;
111  }
118 #ifdef FIX_STRINGS
119  fixSearchString(buf, sizeof(buf), i, YES);
120 #endif /* FIX_STRINGS */
121 
122  licText[i].tseed = licSpec[i].seed.csData;
123 
124  /*---------------------------------------*/
125  /* CDB - This is the code that I inadvertently removed. */
129  if ((p = listGetItem(&gl.sHash, licText[i].tseed)) == NULL_ITEM) {
130  LOG_FATAL("Cannot enqueue search-cache item \"%s\"", licText[i].tseed)
131  Bail(-__LINE__);
132  }
133  p->refCount++;
134 
135  /*--------------------------------*/
136 
140  if (strcmp(licText[i].tseed, "=NULL=") == 0) { /* null */
141 #ifdef OLD_DECRYPT
142  memFree(licText[i].tseed, MTAG_SEEDTEXT);
143 #endif /* OLD_DECRYPT */
144  licText[i].tseed = NULL_STR;
145  licText[i].nAbove = licText->nBelow = -1;
146  }
147  if (same) { /* seed == phrase */
148  licText[i].regex = licText[i].tseed;
149 #if 0
150  ssBelow = searchStrategy(i, buf, NO);
151  licText[i].nBelow = MIN(ssBelow, 2);
152 #endif
153  licText[i].nAbove = licText[i].nBelow = 0;
154  }
160  else { /* seed != phrase */
161  len = licSpec[i].text.csLen;
162  memcpy(buf, licSpec[i].text.csData, (size_t)(len + 1));
163 #ifdef OLD_DECRYPT
164  decrypt(buf, len);
165 #endif /* OLD_DECRYPT */
166  ssAbove = searchStrategy(i, buf, YES);
167  ssBelow = searchStrategy(i, buf, NO);
168 #if 0
169  licText[i].nAbove = MIN(ssAbove, 3);
170  licText[i].nBelow = MIN(ssBelow, 6);
171 #endif
172  licText[i].nAbove = licText[i].nBelow = 1; /* for now... */
173 #ifdef FIX_STRINGS
174  fixSearchString(buf, sizeof(buf), i, NO);
175 #endif /* FIX_STRINGS */
176  licText[i].regex = copyString(buf, MTAG_SRCHTEXT);
177  }
178  if (p->ssComp < (ssAbove * 100) + ssBelow) {
179  p->ssComp = (ssAbove * 100) + ssBelow;
180  }
181  licText[i].compiled = 0;
182  licText[i].plain = 1; /* assume plain-text for now */
183  }
191  for (i = 0; i < NFOOTPRINTS; i++) {
192  if (licText[i].tseed == NULL_STR) {
193 #ifdef LICENSE_DEBUG
194  LOG_NOTICE("License[%d] configured with NULL seed", i)
195 #endif /* LICENSE_DEBUG */
196  continue;
197  }
198  if (licText[i].tseed == licText[i].regex) {
199 #ifdef LICENSE_DEBUG
200  LOG_NOTICE("License[%d] seed == regex", i)
201 #endif /* LICENSE_DEBUG */
202  continue;
203  }
204  licText[i].nAbove = p->ssComp / 100;
205  licText[i].nBelow = p->ssComp % 100;
206  }
207 
214  for (i = 0; i < NFOOTPRINTS; i++) {
215  for (cp = _REGEX(i); licText[i].plain && *cp; cp++) {
216  switch (*cp) {
217  case '.':
218  case '*':
219  case '+':
220  case '|':
221  case '[':
222  case ']':
223  case '(':
224  case ')':
225  case '^':
226  case '$':
227  case '?':
228  case ',':
229  case '<':
230  case '>':
231  case '{':
232  case '}':
233  case '\\':
234  licText[i].plain = 0;
235  break;
236  }
237  }
238  if (i >= _CR_first && i <= _CR_last) {
239  continue;
240  }
241  }
242  return;
243 }
244 
245 #define LINE_BYTES 50
246 #define LINE_WORDS 8
247 #define WC_BYTES 30
248 #define WC_WORDS 3
249 #define PUNT_LINES 3
250 #define MIN_LINES 1
273 static int searchStrategy(int index, char *regex, int aboveCalc) {
274  char *start;
275  char *cp;
276  char *s;
277  char seed[myBUFSIZ];
278  int words;
279  int lines;
280  int bytes;
281  int minLines;
282  int matchWild;
283  int matchSeed;
284 
285 #ifdef PROC_TRACE
286  traceFunc("== searchStrategy(%d(%s), \"%s\", %d)\n", index,
287  _SEED(index), regex, aboveCalc);
288 #endif /* PROC_TRACE */
289 
290  s = _SEED(index);
291  if (s == NULL_STR || strlen(s) == 0) {
292 #ifdef LICENSE_DEBUG
293  LOG_NOTICE("Lic[%d] has NULL seed", index)
294 #endif /* LICENSE_DEBUG */
295  return (0);
296  }
297  if (regex == NULL_STR || strlen(regex) == 0) {
298 #ifdef LICENSE_DEBUG
299  Assert(NO, "searchStrategy(%d) called with NULL data", index);
300 #endif /* LICENSE_DEBUG */
301  return (0);
302  }
303  if (strcmp(s, regex) == 0) {
304  return (0);
305  }
306  bytes = words = lines = 0;
307  (void) strcpy(seed, s);
308  while (seed[strlen(seed) - 1] == ' ') {
309  seed[strlen(seed) - 1] = NULL_CHAR;
310  }
311  /* how far ABOVE to look depends on location of the seed in footprint */
312  if (aboveCalc) {
313  if (strGrep(seed, regex, REG_ICASE) == 0) {
314 #ifdef LICENSE_DEBUG
315  printf("DEBUG: seed(%d) no hit in regex!\n", index);
316 #endif /* LICENSE_DEBUG */
317  return (PUNT_LINES); /* guess */
318  }
319  start = regex;
320  cp = start;
321  for (minLines = 0; cp != NULL; start = cp + 1) {
322  matchWild = matchSeed = 0;
323  if ((cp = strchr(start, ' ')) != NULL_STR) {
324  *cp = NULL_CHAR;
325  }
326  matchWild = (strcmp(start, any) == 0 || strcmp(start, some) == 0
327  || strcmp(start, few));
328  matchSeed = strcmp(start, seed) == 0;
329  if (!matchSeed) {
330  bytes += (matchWild ? WC_BYTES : strlen(start) + 1);
331  words += (matchWild ? WC_WORDS : 1);
332  }
333  if (cp != NULL_STR) {
334  *cp = ' ';
335  }
336  if (matchSeed) { /* found seed? */
337  break;
338  }
339  }
340  /* optimization for single-lines: */
341  minLines += (words >= LINE_WORDS / 2 && words < LINE_WORDS);
342  lines = MAX(bytes/LINE_BYTES, words/LINE_WORDS) + minLines;
343 #ifdef LICENSE_DEBUG
344  printf("ABOVE: .... bytes=%d, words=%d; max(%d,%d)+%d == %d\n",
345  bytes, words, bytes/LINE_BYTES, words/LINE_WORDS,
346  minLines, lines);
347 #endif /* LICENSE_DEBUG */
348  return (words == 0 ? 0 : lines);
349  }
350  /* calculate how far below to look -- depends on length of footprint */
351  for (minLines = MIN_LINES, cp = start = regex; cp; start = cp + 1) {
352  matchWild = matchSeed = 0;
353  if ((cp = strchr(start, ' ')) != NULL_STR) {
354  *cp = NULL_CHAR;
355  }
356  matchWild = (strcmp(start, any) == 0 || strcmp(start, some) == 0
357  || strcmp(start, few));
358  matchSeed = strcmp(start, seed) == 0;
359  if (matchSeed) {
360  bytes = words = 0;
361  /*minLines = MIN_LINES+1;*/
362  }
363  else {
364  bytes += (matchWild ? WC_BYTES : strlen(start) + 1);
365  words += (matchWild ? WC_WORDS : 1);
366  }
367  if (cp != NULL_STR) {
368  *cp = ' ';
369  }
370  }
371  lines = MAX(bytes/LINE_BYTES, words/LINE_WORDS) + minLines;
372 #ifdef LICENSE_DEBUG
373  printf("BELOW: .... bytes=%d, words=%d; max(%d,%d)+%d == %d\n",
374  bytes, words, bytes/LINE_BYTES, words/LINE_WORDS, minLines, lines);
375 #endif /* LICENSE_DEBUG */
376  return (lines);
377 }
378 
379 #ifdef FIX_STRINGS
380 static void fixSearchString(char *s, int size, int i, int wildcardBad)
381 {
382  char *cp;
383  int len;
384  char wildCard[16];
385  /* */
386 #ifdef PROC_TRACE
387  traceFunc("== fixSearchString(\"%s\", %d, %d, %d)\n", s, size, i,
388  wildcardBad);
389 #endif /* PROC_TRACE */
390  /* */
403  cp = s;
404  while (isspace(*cp)) {
405  cp++;
406  }
407  if (strncmp(cp, any, sizeof(any)-1) == 0 ||
408  strncmp(cp, some, sizeof(some)-1) == 0 ||
409  strncmp(cp, few, sizeof(few)-1) == 0) {
410  printf("string %d == \"%s\"\n", i, cp);
411  LOG_FATAL("Text-spec %d begins with a wild-card", i)
412  Bail(-__LINE__);
413  }
414  /*
415  * We'll replace the string " =ANY=" (6 chars) with ".*" (2 chars).
416  * The token MUST OCCUR BY ITSELF (e.g., not a substring)!
417  */
418  (void) sprintf(wildCard, " %s", any);
419  len = strlen(wildCard);
420  for (cp = s; strGrep(wildCard, cp, 0); ) {
421  if (wildcardBad) {
422  LOG_FATAL("OOPS, regex %d, wild-card not allowed here", i)
423  Bail(-__LINE__);
424  }
425  if (*(cp+cur.regm.rm_eo) == NULL_CHAR) {
426  LOG_FATAL("String %d ends in a wild-card", i)
427  Bail(-__LINE__);
428  }
429  else if (*(cp+cur.regm.rm_eo) == ' ') {
430 #ifdef DEBUG
431  printf("BEFORE(any): %s\n", s);
432 #endif /* DEBUG */
433  cp += cur.regm.rm_so;
434  *cp++ = '.';
435  *cp++ = '*';
436  memmove(cp, cp+len-1, strlen(cp+len)+2);
437 #ifdef DEBUG
438  printf("_AFTER(any): %s\n", s);
439 #endif /* DEBUG */
440  }
441  else {
442  LOG_NOTICE("Wild-card \"%s\" sub-string, phrase %d", wildCard, i)
443  cp += cur.regm.rm_eo;
444  }
445  }
446  /*
447  * Ditto for replacing " =SOME= " (8 chars) with ".{0,60}" (7 chars)
448  */
449  (void) sprintf(wildCard, " %s", some);
450  len = strlen(wildCard);
451  for (cp = s; strGrep(wildCard, cp, 0); ) {
452  if (wildcardBad) {
453  LOG_FATAL("OOPS, regex %d, wild-card not allowed here", i)
454  Bail(-__LINE__);
455  }
456  if (*(cp+cur.regm.rm_eo) == NULL_CHAR) {
457  LOG_FATAL("String %d ends in a wild-card", i)
458  Bail(-__LINE__);
459  }
460  else if (*(cp+cur.regm.rm_eo) == ' ') {
461 #ifdef DEBUG
462  printf("BEFORE(some): %s\n", s);
463 #endif /* DEBUG */
464  cp += cur.regm.rm_so;
465  *cp++ = '.';
466  *cp++ = '{';
467  *cp++ = '0';
468  *cp++ = ',';
469  *cp++ = '6';
470  *cp++ = '0';
471  *cp++ = '}';
472  memmove(cp, cp+len-6, strlen(cp+len)+7);
473 #ifdef DEBUG
474  printf("_AFTER(some): %s\n", s);
475 #endif /* DEBUG */
476  }
477  else {
478  LOG_NOTICE("Wild-card \"%s\" sub-string, phrase %d", wildCard, i)
479  cp += cur.regm.rm_eo;
480  }
481  }
482  /*
483  * And, same for replacing " =FEW= " (7 chars) with ".{0,15}" (7 chars)
484  */
485  (void) sprintf(wildCard, " %s", few);
486  len = strlen(wildCard);
487  for (cp = s; strGrep(wildCard, cp, 0); ) {
488  if (wildcardBad) {
489  LOG_FATAL("OOPS, regex %d, wild-card not allowed here", i)
490  Bail(-__LINE__);
491  }
492  if (*(cp+cur.regm.rm_eo) == NULL_CHAR) {
493  LOG_FATAL("String %d ends in a wild-card", i)
494  Bail(-__LINE__);
495  }
496  else if (*(cp+cur.regm.rm_eo) == ' ') {
497 #ifdef DEBUG
498  printf("BEFORE(few): %s\n", s);
499 #endif /* DEBUG */
500  cp += cur.regm.rm_so;
501  *cp++ = '.';
502  *cp++ = '{';
503  *cp++ = '0';
504  *cp++ = ',';
505  *cp++ = '3';
506  *cp++ = '0';
507  *cp++ = '}';
508  memmove(cp, cp+len-6, strlen(cp+len)+7);
509 #ifdef DEBUG
510  printf("_AFTER(few): %s\n", s);
511 #endif /* DEBUG */
512  }
513  else {
514  LOG_NOTICE("Wild-card \"%s\" sub-string, phrase %d", wildCard, i)
515  cp += cur.regm.rm_eo;
516  }
517  }
518  /*
519  * AND, replace the string "=YEAR=" with "[12][0-9][0-9][0-9][,- ]*".
520  * The former is 6 chars in length, the latter is 24. We must be careful
521  * not to overflow the buffer we're passed.
522  */
523  len = strlen(year);
524  while (strGrep(year, s, 0)) {
525  if (strlen(s)+25 >= size) { /* 24 plus 1(NULL) */
526  LOG_FATAL("buffer overflow, text-spec %d", i)
527  Bail(-__LINE__);
528  }
529  cp = (char *)(s+cur.regm.rm_so);
530 #ifdef DEBUG
531  printf("BEFORE: %s\n", s);
532 #endif /* DEBUG */
533  memmove(cp+25, cp+6, strlen(cp+len)+1); /* was 26, 6 */
534  memset(cp+6, '_', 19);
535 #ifdef DEBUG
536  printf("_MOVED: %s\n", s);
537 #endif /* DEBUG */
538  *cp = *(cp+4) = *(cp+9) = *(cp+14) = *(cp+19) = '[';
539  *(cp+1) = '1';
540  *(cp+2) = '2';
541  *(cp+5) = *(cp+10) = *(cp+15) = '0';
542  *(cp+6) = *(cp+11) = *(cp+16) = '-';
543  *(cp+7) = *(cp+12) = *(cp+17) = '9';
544  *(cp+3) = *(cp+8) = *(cp+13) = *(cp+18) = *(cp+23) = ']';
545  *(cp+20) = ' ';
546  *(cp+21) = ',';
547  *(cp+22) = '-';
548  *(cp+24) = '*';
549 #ifdef DEBUG
550  printf("_AFTER: %s\n", s);
551 #endif /* DEBUG */
552  }
553  return;
554 }
555 #endif /* FIX_STRINGS */
556 
557 char* createRelativePath(item_t *p, scanres_t *scp)
558 {
559  char* cp;
560  if (*(p->str) == '/')
561  {
562  strcpy(scp->fullpath, p->str);
563  scp->nameOffset = (size_t) (cur.targetLen + 1);
564  cp = scp->fullpath; /* full pathname */
565  }
566  else
567  {
568  strncpy(scp->fullpath, cur.cwd, sizeof(scp->fullpath)-1);
569  strncat(scp->fullpath, "/", sizeof(scp->fullpath)-1);
570  strncat(scp->fullpath, p->str, sizeof(scp->fullpath)-1);
571  scp->nameOffset = (size_t) (cur.cwdLen + 1);
572  cp = p->str; /* relative path == faster open() */
573  }
574 
575  return cp;
576 }
577 
594 void scanForKeywordsAndSetScore(scanres_t* scores, list_t* licenseList)
595 {
596  /*
597  CDB -- Some other part of FOSSology has already decided we
598  want to scan this file, so we need to look into removing this
599  file scoring stuff.
600  */
601  scanres_t* scp;
602  int c;
603  item_t* p;
604  char* textp;
605  char* cp;
606  for (scp = scores; (p = listIterate(licenseList)) != NULL_ITEM ; scp++)
607  {
608 
609  /*
610  * Use *relative* pathnames wherever possible -- we'll spend less time in
611  * the kernel looking up inodes and pathname components that way.
612  */
613  cp = createRelativePath(p, scp);
614 
615 #ifdef DEBUG
616  printf("licenseScan: scan %s\n",
617  (char *)(scp->fullpath+scp->nameOffset));
618 #endif /* DEBUG */
619  /*
620  * Zero-length files are of no interest; there's nothing in them!
621  * CDB - We need to report this error somehow... and clean up
622  * /tmp/nomos.tmpdir (or equivalent).
623  */
624  if ((textp = mmapFile(cp)) == NULL_STR) {
625  /* perror(cp); */
626  /*printf("Zero length file: %s\n", cp); */
627  continue;
628  }
629  scp->size = cur.stbuf.st_size; /* Where did this get set ? CDB */
630  /*
631  * Disinterest #3 (discriminate-by-file-content):
632  * Files not of a known-good type (as reported by file(1)/magic(3)) should
633  * also be skipped (some are quite large!). _UTIL_MAGIC (see _autodata.c)
634  * contains a regex for MOST of the files we're interested in, but there
635  * ARE some exceptions (logged below).
636  *
637  *****
638  * exception (A): patch/diff files are sometimes identified as "data".
639  *****
640  * FIX-ME: we don't currently use _UTIL_FILTER, which is set up to
641  * exclude some files by filename.
642  */
643  /*
644  * Scan for keywords (_KW_), and use the number found for the score.
645  */
646  assert(NKEYWORDS >= sizeof(scp->kwbm));
647 
648  for (scp->kwbm = c = 0; c < NKEYWORDS; c++)
649  {
650  if (idxGrep_recordPosition(c + _KW_first, textp, REG_EXTENDED | REG_ICASE))
651  {
652  scp->kwbm |= (1 << c); // put a one at c'th position in kwbm (KeywordByteMap)
653  scp->score++;
654 #if (DEBUG > 5)
655  printf("Keyword %d (\"%s\"): YES\n", c, _REGEX(c+_KW_first));
656 #endif /* DEBUG > 5 */
657  }
658  }
659  munmapFile(textp);
660 #if (DEBUG > 5)
661  printf("%s = %d\n", (char *)(scp->fullpath+scp->nameOffset),
662  scp->score);
663 #endif /* DEBUG > 5 */
664 
665  }
666  return;
667 }
668 
680 {
681  /*
682  * CDB - It is always the case that we are doing one file at a time.
683  */
684  if (scores->score == 0)
685  {
686  scores->score = 1;
687  }
688 }
689 
701 int fiterResultsOfKeywordScan(int lowWater, scanres_t* scores, int nFiles)
702 {
703  int nCand;
704 
705  scanres_t* scp;
706  int i;
707 
708  for (scp = scores, i = nCand = 0; i < nFiles; i++, scp++)
709  {
710  scp->relpath = (char *) (scp->fullpath + scp->nameOffset);
711  if (idxGrep(_FN_LICENSEPATT, pathBasename(scp->relpath), REG_ICASE
712  | REG_EXTENDED)) {
713  scp->flag = 1;
714  if (idxGrep(_FN_DEBCPYRT, scp->relpath, REG_ICASE)) {
715  scp->flag = 2;
716  }
717  }
718  else if (scp->score >= lowWater) {
719  scp->flag |= 1;
720  }
721  /*
722  * So now, save any license candidate EITHER named "debian/copyright*"
723  * OR having a score > 0
724  */
725  if (scp->flag == 2 || (scp->score && scp->flag)) {
726 #if (DEBUG > 3)
727  printf("%s [score: %d], %07o\n", scp->fullpath,
728  scp->score, scp->kwbm);
729 #endif /* DEBUG > 3 */
730  nCand++;
731  }
732  }
733  return nCand;
734 }
735 
747 void licenseScan(list_t *licenseList)
748 {
749  int lowWater = 1; // constant
750 
751  int nCand; //relevant output
752 
753  //fields
754  int counts[NKEYWORDS + 1];
755  scanres_t *scores;
756 
757  //recycled temp variables
758  scanres_t *scp;
759  int nFilesInList;
760 
761 #ifdef PROC_TRACE
762  traceFunc("== licenseScan(%p, %d)\n", l);
763 #endif /* PROC_TRACE */
764 
765 #ifdef MEMSTATS
766  printf("... allocating %d bytes for scanres_t[] array\n",
767  sizeof(*scp)*licenseList->used);
768 #endif /* MEMSTATS */
769 
770  scores = (scanres_t *) memAlloc(sizeof(*scp) * licenseList->used, MTAG_SCANRES);
771  memset((void *) counts, 0, (size_t) ((NKEYWORDS + 1) * sizeof(int)));
772 
773  scanForKeywordsAndSetScore(scores, licenseList);
775 
776 #ifdef PROC_TRACE
777  traceFunc("=> invoking qsort(): callback == scoreCompare()\n");
778 #endif /* PROC_TRACE */
779 
780  nFilesInList = licenseList->used;
781  qsort(scores, (size_t) nFilesInList, sizeof(*scp), scoreCompare);
782 
783  //recycled temp variables
784  nCand = fiterResultsOfKeywordScan(lowWater, scores, nFilesInList);
785  /*
786  * OF SPECIAL INTEREST: saveLicenseData() changes directory (to "..")!!!
787  */
788  /* DBug: printf("licenseScan: gl.initwd is:%s\n",gl.initwd); */
789  saveLicenseData(scores, nCand, nFilesInList, lowWater);
790  /*
791  * At this point, we don't need either the raw-source directory or the
792  * unpacked results anymore, so get rid of 'em.
793  */
794  if (scores->licenses) free(scores->licenses);
795  memFree((char *) scores, "scores table");
796  return;
797 } /* licenseScan */
798 
809 static int scoreCompare(const void *arg1, const void *arg2) {
810  scanres_t *sc1 = (scanres_t *) arg1;
811  scanres_t *sc2 = (scanres_t *) arg2;
812 
813  if (sc1->score > sc2->score) {
814  return (-1);
815  }
816  else if (sc1->score < sc2->score) {
817  return (1);
818  }
819  else if ((sc1->fullpath != NULL_STR) && (sc2->fullpath == NULL_STR)) {
820  return (-1);
821  }
822  else if ((sc2->fullpath != NULL_STR) && (sc1->fullpath == NULL_STR)) {
823  return (1);
824  }
825  else {
826  return (-strcmp(sc1->fullpath, sc2->fullpath));
827  }
828 }
829 
833 static void noLicenseFound() {
834 
835 #ifdef PROC_TRACE
836  traceFunc("== noLicenseFound\n");
837 #endif /* PROC_TRACE */
838 
839  (void) strcpy(cur.compLic, LS_NOSUM);
840  return;
841 }
842 
854 static void printHighlightInfo(GArray* keyWords, GArray* theMatches){
855  if ( optionIsSet(OPTS_HIGHLIGHT_STDOUT) )
856  {
857  printf(" Highlighting Info at");
858  int currentKeyw;
859  for (currentKeyw=0; currentKeyw < keyWords->len; ++currentKeyw ) {
860  MatchPositionAndType* ourMatchv = getMatchfromHighlightInfo(keyWords,currentKeyw );
861  printf(" Keyword at %i, length %i, index = 0,", ourMatchv->start, ourMatchv->end - ourMatchv->start );
862  }
863  int currentLicence;
864  for (currentLicence = 0; currentLicence < theMatches->len; ++currentLicence)
865  {
866  LicenceAndMatchPositions* theLicence = getLicenceAndMatchPositions(theMatches, currentLicence);
867 
868  int highl;
869  for (highl = 0; highl < theLicence->matchPositions->len; ++highl)
870  {
871  MatchPositionAndType* ourMatchv = getMatchfromHighlightInfo(theLicence->matchPositions, highl);
872  printf(" License #%s# at %i, length %i, index = %i,", theLicence->licenceName , ourMatchv->start, ourMatchv->end - ourMatchv->start, ourMatchv->index );
873 
874  }
875  }
876  }
877  printf("\n");
878  return;
879 }
880 
884 static void printKeyWordMatches(scanres_t *scores, int idx)
885 {
886  int c;
887  int base;
888  char miscbuf[myBUFSIZ];
889  int offset;
890  /*
891  * construct the list of keywords that matched in licenseScan()
892  */
893  (void) strcpy(miscbuf, "Matches: ");
894  offset = 9; /* e.g., strlen("Matches: ") */
895  for (base = c = 0; c < NKEYWORDS; c++)
896  {
897  if (scores[idx].kwbm & (1 << c))
898  {
899  if (base++)
900  {
901  miscbuf[offset++] = ',';
902  miscbuf[offset++] = ' ';
903  }
904  offset += sprintf(miscbuf + offset, "%s", _REGEX(c + _KW_first));
905  }
906  }
907 
908  printf("%s\n", miscbuf);
909 
910 }
911 
916 static gint compare_integer(gconstpointer a, gconstpointer b)
917 {
918  gint out;
919 
920  if (a < b)
921  out = -1;
922  else if (a == b)
923  out = 0;
924  else
925  out = 1;
926  return out;
927 
928 }
929 
936 static void rescanOriginalTextForFoundLicences(char* textp, int isFileMarkupLanguage, int isPS){
937  if (cur.theMatches->len > 0 )
938  {
939  if (cur.cliMode == 1 && !optionIsSet(OPTS_HIGHLIGHT_STDOUT) ) return;
940  // do a fresh doctoring of the buffer
941  g_array_free(cur.docBufferPositionsAndOffsets, TRUE);
942  cur.docBufferPositionsAndOffsets = g_array_new(FALSE, FALSE, sizeof(pairPosOff));
943  doctorBuffer(textp, isFileMarkupLanguage, isPS, NO);
944 
945  for (cur.currentLicenceIndex = 0; cur.currentLicenceIndex < cur.theMatches->len; ++cur.currentLicenceIndex)
946  {
947  LicenceAndMatchPositions* currentLicence = getLicenceAndMatchPositions(cur.theMatches, cur.currentLicenceIndex);
948 
949  //we want to only look for each found index once
950  g_array_sort(currentLicence->indexList, compare_integer);
951 
952  int myIndex;
953  int lastindex = -1;
954  for (myIndex = 0; myIndex < currentLicence->indexList->len; ++myIndex)
955  {
956  int currentIndex = g_array_index(currentLicence->indexList, int, myIndex);
957  if (currentIndex == lastindex) continue;
958  idxGrep_recordPositionDoctored(currentIndex, textp, REG_ICASE | REG_EXTENDED);
959  lastindex = currentIndex;
960  }
961  }
962  }
963 }
964 
982 static void saveLicenseData(scanres_t *scores, int nCand, int nElem,
983  int lowWater) {
984  int i;
985  // int c;
986  // int base;
987  int size;
988  int highScore = scores->score;
989  int isFileMarkupLanguage = 0;
990  int isPS = 0;
991  // int offset;
992  int idx;
993  char *fileName;
994  char *textp;
995  item_t *p;
996  char realPathOfTarget[PATH_MAX];
997 
998 #ifdef PROC_TRACE
999  traceFunc("== saveLicenseData(%p, %d, %d, %d, %d)\n", scores, nCand,
1000  nElem, lowWater);
1001 #endif /* PROC_TRACE */
1002 
1003  /* DBug: printf("saveLicenseData on entry gl.initwd is:%s\n",gl.initwd); */
1004  /*
1005  * Save the necessary licensing information in a list of files...
1006  */
1007 #ifdef DEBUG
1008  printf("saveLicenseData: %d candidates\n", nCand);
1009 #endif /* DEBUG */
1010 
1011  /* changeDir("..");*//* CDB- Why?!!!! */
1012 
1013  /* BE PERFORMANCE-CONSCIOUS WITHIN THIS LOOP (it runs a LOT!) */
1014  /*
1015  * OPTIMIZE-ME: should we store local variables and use lots of
1016  * registers instead of accessing everything through the scanres
1017  * array? We've got to be doing some serious address calculations.
1018  */
1019  i = 1;
1020 
1021  for (idx = 0; i <= nCand; idx++) {
1022  /*
1023  * If we didn't flag this file as needing to be saved, ignore it.
1024  */
1025  if (scores[idx].flag == 0) {
1026  continue;
1027  }
1028  (void) sprintf(scores[idx].linkname, "Link%03d.txt", i++);
1029 #if DEBUG > 5
1030  printf("name: %s\n[%s]\n", scores[idx].relpath, scores[idx].fullpath);
1031 #endif /* DEBUG > 5 */
1032  /*
1033  * Kludge up the pointer to the relative-path in scores[idx].fullpath
1034  * so we don't
1035  * have to as many directory entries to open each file... this works for
1036  * anything EXCEPT 'distribution files'.
1037  */
1038  fileName = scores[idx].fullpath;
1039  if (optionIsSet(OPTS_DEBUG)) {
1040  printf("File name: %s\n", fileName);
1041  }
1042  if ((textp = mmapFile(fileName)) == NULL_STR) {
1043 
1044  /* Fatal("Null mmapFile(), path=%s", fileName); */
1045  noLicenseFound();
1046  continue;
1047  }
1048  /* CDB size = (int) cur.stbuf.st_size; */
1049  size = scores[idx].size;
1050  if (scores[idx].dataOffset) {
1051  textp += scores[idx].dataOffset;
1052  }
1053 
1054  /* wordCount() sets nLines in global structure "cur". */
1055  wordCount(textp);
1056 
1057  /*
1058  * Report which package (if any) this file came from
1059  */
1060 
1061  /*
1062  * Since we hard-wire the score of every file (invoked as --file), a score
1063  * of 1 could be either 0 or 1, so scores[idx].kwbm tells the real story...
1064  */
1065  if (optionIsSet(OPTS_DEBUG)) {
1066  printf("File score: %d (0x%06x)\n",
1067  (scores[idx].kwbm ? scores[idx].score : scores[idx].kwbm),
1068  scores[idx].kwbm);
1069  if (scores[idx].kwbm) {
1070  printKeyWordMatches(scores, idx);
1071  }
1072  }
1073  /*
1074  * Print the license claim (e.g., what's listed in the package)
1075  */
1076  /*
1077  * determine licenses in the file, and record 'em; wrap up by including
1078  * the file contents
1079  *****
1080  * FIX-ME: we should filter some names out like the shellscript does.
1081  * For instance, word-spell-dictionary files will score high but will
1082  * likely NOT contain a license. But the shellscript filters these
1083  * names AFTER they're already scanned. Think about it.
1084  *****
1085  FILTERPATTERNS="(/man|\.[0-9]|\.[0-9][a-z]|rfc[0-9].*|.po|.pot"
1086  FILTERPATTERNS="$FILTERPATTERNS|words.*|.*spelling.*|spell)$"
1087  */
1088 #if defined(DEBUG) || defined(DOCTOR_DEBUG) || defined(LTSR_DEBUG) \
1089  || defined(BATCH_DEBUG) || defined(PARSE_STOPWATCH) || defined(MEMSTATS) \
1090  || defined(MEM_DEBUG) || defined(UNKNOWN_CHECK_DEBUG)
1091  printf("*** PROCESS File: %s\n", scores[idx].relpath);
1092  printf("... %d bytes, score %d\n", scores[idx].size, scores[idx].score);
1093 #endif /* DEBUG || DOCTOR_DEBUG || LTSR_DEBUG || BATCH_DEBUG || PARSE_STOPWATCH || MEMSTATS || MEM_DEBUG || defined(UNKNOWN_CHECK_DEBUG)*/
1094 
1095  isFileMarkupLanguage = idxGrep(_UTIL_MARKUP, textp, REG_ICASE | REG_EXTENDED);
1096 
1097 #ifdef DOCTOR_DEBUG
1098  printf("idxGrep(ML) returns %d\n", isFileMarkupLanguage);
1099  if (isFileMarkupLanguage)
1100  {
1101  int n;
1102  printf("isMarkUp@%d: [", cur.regm.rm_so);
1103  for (n = cur.regm.rm_so; n <= cur.regm.rm_eo; n++) {
1104  printf("%c", *(textp+n));
1105  }
1106  printf("]\n");
1107  }
1108 #endif /* DOCTOR_DEBUG */
1109  /*
1110  * BUG: When _FTYP_POSTSCR is "(postscript|utf-8 unicode)", the resulting
1111  * license-parse yields 'NoLicenseFound' but when both "postscript" and
1112  * "utf-8 unicode" are searched independently, parsing definitely finds
1113  * quantifiable licenses. WHY?
1114  */
1115 #ifdef DOCTOR_DEBUG
1116  printf("idxGrep(PS) returns %d\n", isPS);
1117  if (isPS) {
1118  int n;
1119  printf("isPostScript@%d: [", cur.regm.rm_so);
1120  printf("]\n");
1121  }
1122 #endif /* DOCTOR_DEBUG */
1123  /*
1124  * Interesting - copyString(parseLicenses(args), MTAG_FILELIC)...
1125  * will randomly segfault on 32-bit Debian releases. Split the calls.
1126  */
1127  fileName = parseLicenses(textp, size, &scores[idx], isFileMarkupLanguage, isPS);
1128  scores[idx].licenses = copyString(fileName, MTAG_FILELIC);
1129 #ifdef QA_CHECKS
1130  if (fileName == NULL_STR) {
1131  Assert(NO, "Expected non-null parseLicenses return!");
1132  }
1133  if (scores[idx].licenses == NULL_STR) {
1134  Assert(NO, "Expected non-null license summary!");
1135  }
1136 #endif /* QA_CHECKS */
1137 #ifdef STOPWATCH
1138  timerBytes += size;
1139 #endif /* STOPWATCH */
1140 #ifdef FLAG_NO_COPYRIGHT
1141  if (gl.flags & FL_NOCOPYRIGHT) {
1142  p = listGetItem(&cur.nocpyrtList, scores[idx].relpath);
1143  p->buf = copyString(scores[idx].linkname, MTAG_PATHBASE);
1144  p->num = scores[idx].score;
1145  }
1146 #endif /* FLAG_NO_COPYRIGHT */
1147  if (cur.licPara != NULL_STR) {
1148  memFree(cur.licPara, MTAG_TEXTPARA); /* be free! */
1149  cur.licPara = NULL_STR; /* remember */
1150  }
1151 
1152 
1153  if( !optionIsSet(OPTS_NO_HIGHLIGHTINFO) ) {
1154  //careful this function changes the content of textp
1155  rescanOriginalTextForFoundLicences(textp, isFileMarkupLanguage, isPS);
1156  //but as it is freed right here we do not make a copy..
1157  }
1158 
1159  munmapFile(textp);
1160 
1161  /*
1162  * Remember this license in this file...
1163  */
1164  p = listGetItem(&cur.lList, scores[idx].licenses);
1165  p->refCount++;
1166  /*
1167  * Clear out the buffer-offsets list
1168  */
1169 #ifdef fix_later
1170  /* CDB - need to move this code to a point after we save the license info */
1171 #ifdef PHRASE_DEBUG
1172  listDump(&cur.offList, NO);
1173 #endif /* PHRASE_DEBUG */
1174  while ((p = listIterate(&cur.offList)) != 0) {
1175  listClear(p->buf, YES);
1176  }
1177  listClear(&cur.offList, NO);
1178 #endif /* fix_later */
1179  }
1180 
1181  listSort(&cur.lList, SORT_BY_COUNT_DSC);
1182 
1183 #ifdef QA_CHECKS
1184  if (cur.lList.used == 0) {
1185  Assert(NO, "No entries in license-list");
1186  }
1187 #endif /* QA_CHECKS */
1188 
1189  /*
1190  * Construct a 'computed license'. Wherever possible, leave off the
1191  * entries for None and LikelyNot; those are individual-file results
1192  * and we're making an 'aggregate summary' here.
1193  */
1194  if (cur.parseList.used == 0) {
1195  noLicenseFound();
1196  }
1197  else {
1198  makeLicenseSummary(&cur.parseList, highScore, cur.compLic,
1199  sizeof(cur.compLic));
1200  }
1201  if (optionIsSet(OPTS_DEBUG)) {
1202  printf("==> ");
1203  }
1204  /* CDB - Debug code */
1205  /*
1206  printf("saveLicData: the offset list is:\n");
1207  listDump(&cur.offList, YES);
1208 
1209  while ((p = listIterate(&cur.offList)) != 0) {
1210  listDump(p->buf, YES);
1211  }
1212  */
1213  /* print results if running from the command line */
1214  /* DBug: printf("saveLicenseData on return gl.initwd is:%s\n",gl.initwd); */
1215  if(cur.cliMode)
1216  {
1217  if (optionIsSet(OPTS_JSON_OUTPUT))
1218  {
1219  writeJson();
1220  } else {
1221  if (optionIsSet(OPTS_LONG_CMD_OUTPUT) && realpath(cur.targetFile, realPathOfTarget))
1222  {
1223  printf("File %s contains license(s) %s", realPathOfTarget, cur.compLic);
1224  }
1225  else
1226  {
1227  printf("File %s contains license(s) %s", basename(cur.targetFile), cur.compLic);
1228  }
1230  }
1231  }
1232  return;
1233 } /* saveLicenseData */
1234 
1235 
1264 static void makeLicenseSummary(list_t *l, int highScore, char *target, int size) {
1265  item_t *p;
1266  int printCount = 0;
1267  int len = 0;
1268  int new;
1269  int goodStuff;
1270 
1271 #ifdef PROC_TRACE
1272  traceFunc("== makeLicenseSummary(%p, %d, %p, %d)\n", l, highScore,
1273  target, size);
1274 #endif /* PROC_TRACE */
1275 
1276  if (l->used == 0) { /* zero/nothing */
1277  (void) strcpy(target, LS_NOSUM);
1278  return;
1279  }
1280  /*
1281  * Now we know there's something in the list of AT LEAST marginal interest
1282  * in the component-list. If listCount() is zero, ALL data is 'marginal';
1283  * else we have 'good stuff'. For the latter, we only summarize items with
1284  * a 'val' > 0 (the really interesting stuff).
1285  */
1286  listSort(l, SORT_BY_COUNT_DSC); /* sort components */
1287  size--; /* maximum strlen, adjust to allow *1* NULL */
1288  for (goodStuff = 0; (p = listIterate(l)) != NULL_ITEM; /*nada */) {
1289  if (p->iLevel) {
1290  goodStuff = 1; /* interesting license */
1291  l->ix = -1; /* reset saved index */
1292  break;
1293  }
1294  }
1295  while ((p = listIterate(l)) != NULL_ITEM) {
1296  if (goodStuff && (p->iLevel <= IL_LOW)) { /* uninteresting */
1297  continue;
1298  }
1299  if (printCount) {
1300  target[len++] = ',';
1301  }
1302  printCount++;
1303  new = sprintf(target + len, "%s", p->str);
1304  if ((len += new) > size) {
1305  LOG_FATAL("Buffer-overwrite, marginal license components")
1306  Bail(-__LINE__);
1307  }
1308  new = 0;
1309  }
1310  return;
1311 }
1312 
1313 #ifdef LICENSE_DEBUG
1314 dumpLicenses()
1315 {
1316  int i;
1317 
1318 #ifdef PROC_TRACE
1319  traceFunc("== dumpLicenses()\n");
1320 #endif /* PROC_TRACE */
1321 
1322  for (i = 0; i < NFOOTPRINTS; i++) {
1323  printf("License[%d]: seedlen=%d, regexlen=%d\n", i,
1324  licSpec[i].seed.csLen, licSpec[i].text.csLen);
1325  }
1326  printf("[NFOOTPRINTS = %d\n", NFOOTPRINTS);
1327 }
1328 #endif /* LICENSE_DEBUG */
void doctorBuffer(char *buf, int isML, int isPS, int isCR)
Convert a buffer of multiple stuff to text-only, separated by spaces.
int s
The socket that the CLI will use to communicate.
Definition: fo_cli.c:37
void writeJson()
Write the scan output as a JSON.
Definition: json_writer.c:13
static void printHighlightInfo(GArray *keyWords, GArray *theMatches)
Print highlight info about matches.
Definition: licenses.c:854
static gint compare_integer(gconstpointer a, gconstpointer b)
Compare two integers.
Definition: licenses.c:916
static void saveLicenseData(scanres_t *, int, int, int)
Save/creates all the license-data in a specific directory temp directory?
Definition: licenses.c:982
int fiterResultsOfKeywordScan(int lowWater, scanres_t *scores, int nFiles)
Run through the list once more.
Definition: licenses.c:701
void scanForKeywordsAndSetScore(scanres_t *scores, list_t *licenseList)
Definition: licenses.c:594
#define WC_WORDS
Definition: licenses.c:248
static void printKeyWordMatches(scanres_t *scores, int idx)
Prints keywords match to STDOUT.
Definition: licenses.c:884
#define MIN(a, b)
Min of two.
Definition: licenses.c:64
#define MIN_LINES
Definition: licenses.c:250
static int searchStrategy(int, char *, int)
Definition: licenses.c:273
void licenseScan(list_t *licenseList)
scan the list for a license(s)
Definition: licenses.c:747
void licenseInit()
license initialization
Definition: licenses.c:70
#define WC_BYTES
Definition: licenses.c:247
#define LINE_BYTES
Definition: licenses.c:245
static void noLicenseFound()
Mark curent scan as LS_NOSUM (No_license_found)
Definition: licenses.c:833
void relaxScoreCriterionForSingleFile(scanres_t *scores)
Reset scores to 1 if it is 0.
Definition: licenses.c:679
static void makeLicenseSummary(list_t *, int, char *, int)
Construct a 'computed license'. Wherever possible, leave off the entries for None and LikelyNot; thos...
Definition: licenses.c:1264
#define PUNT_LINES
Definition: licenses.c:249
static void rescanOriginalTextForFoundLicences(char *textp, int isFileMarkupLanguage, int isPS)
Rescan original content for the licenses already found.
Definition: licenses.c:936
#define LINE_WORDS
Definition: licenses.c:246
static int scoreCompare(const void *, const void *)
Compare two scores.
Definition: licenses.c:809
#define MAX(a, b)
Max of two.
Definition: licenses.c:63
void listDump(list_t *l, int verbose)
print the passed in list
Definition: list.c:829
item_t * listGetItem(list_t *l, char *s)
get an item from the itemlist. If the item is not in the itemlist, then add it to the itemlist.
Definition: list.c:246
void listInit(list_t *l, int size, char *label)
intialize a list, if the list is not empty, empty it (initialize it to zero's).
Definition: list.c:54
item_t * listIterate(list_t *l)
return a pointer to listitem, returns a NULL_ITEM when no more items to return.
Definition: list.c:477
void listSort(list_t *l, int sortType)
Sort the list as per the sortType passed.
Definition: list.c:631
void listClear(list_t *l, int deallocFlag)
Destroy list_t.
Definition: list.c:106
void munmapFile(void *ptr)
Definition: util.c:1197
char * pathBasename(char *path)
Get the basename from a file path.
Definition: util.c:615
char * copyString(char *s, char *label)
Create a copy of a string.
Definition: util.c:593
void Assert(int fatalFlag, const char *fmt,...)
Raise an assert.
Definition: util.c:1395
char * wordCount(char *textp)
VERY simple line count, does NOT have to be perfect!
Definition: util.c:551
char * mmapFile(char *pathname)
Blarg. Files that are EXACTLY a multiple of the system pagesize do not get a NULL on the end of the b...
Definition: util.c:1082
licText_t licText[]
Nomos header file.
#define NULL_ITEM
NULL item.
Definition: nomos.h:231
#define memFree(x, y)
Definition: nomos.h:531
#define NULL_STR
NULL string.
Definition: nomos.h:235
#define MTAG_SEEDTEXT
Definition: nomos.h:493
#define _SEED(x)
Definition: nomos.h:451
#define _REGEX(x)
Definition: nomos.h:447
#define YES
Definition: nomos.h:175
#define NO
Definition: nomos.h:171
void Bail(int exitval)
Close connections and exit.
Definition: nomos_utils.c:533
#define NULL_CHAR
NULL character.
Definition: nomos.h:234
#define OPTS_DEBUG
Definition: nomos.h:138
int optionIsSet(int val)
Check if an CLI option is set.
Definition: nomos_utils.c:560
int idxGrep_recordPosition(int index, char *data, int flags)
compile a regex, perform the search and record findings
Definition: nomos_regex.c:220
int idxGrep(int index, char *data, int flags)
compile a regex, and perform the search (on data?)
Definition: nomos_regex.c:205
int strGrep(char *regex, char *data, int flags)
General-purpose grep function, used for one-time-only searches.
Definition: nomos_regex.c:139
int idxGrep_recordPositionDoctored(int index, char *data, int flags)
compile a regex, perform the search and record findings
Definition: nomos_regex.c:241
FUNCTION MatchPositionAndType * getMatchfromHighlightInfo(GArray *in, int index)
Get the MatchPositionAndType for a given index in highlight array.
Definition: nomos_utils.c:901
FUNCTION LicenceAndMatchPositions * getLicenceAndMatchPositions(GArray *in, int index)
Get the LicenceAndMatchPositions for a given index in match array.
Definition: nomos_utils.c:913
char * parseLicenses(char *filetext, int size, scanres_t *scp, int isML, int isPS)
Parse a file to check all the possible licenses and add them to matches.
Definition: parse.c:359
start($application)
start the application Assumes application is restartable via /etc/init.d/<script>....
Definition: pkgConfig.php:1214
GArray * matchPositions
Match positions.
Definition: nomos.h:379
GArray * indexList
License indexes.
Definition: nomos.h:380
char * licenceName
License names.
Definition: nomos.h:381
int start
Start position of match.
Definition: nomos.h:370
int index
Enums from index (Entrynumber) in STRINGS.in.
Definition: nomos.h:372
int end
End position of match.
Definition: nomos.h:371
char cwd[myBUFSIZ]
Definition: nomos.h:392
GArray * theMatches
Definition: nomos.h:417
GArray * keywordPositions
Definition: nomos.h:418
char compLic[myBUFSIZ]
Definition: nomos.h:409
char targetFile[myBUFSIZ]
Definition: nomos.h:394
int cliMode
Definition: nomos.h:412
list_t sHash
Hashes.
Definition: nomos.h:357
int flags
Flags.
Definition: nomos.h:348
searchString_t text
License text.
Definition: nomos.h:335
searchString_t seed
License seed.
Definition: nomos.h:334
char * regex
License regex.
Definition: nomos.h:435
char * tseed
unencrypted license text
Definition: nomos.h:436
list_t type structure used to keep various lists. (e.g. there are multiple lists).
Definition: nomos.h:308
int used
Definition: nomos.h:310
int ix
Definition: nomos.h:312
tricky data structure used for a list of 'items'
Definition: nomos.h:274
void * buf
Definition: nomos.h:279
char * str
Definition: nomos.h:278
int flag
Flags.
Definition: nomos.h:460
int score
License match score.
Definition: nomos.h:457
int csLen
String length.
Definition: nomos.h:325
char * csData
String data.
Definition: nomos.h:326