FOSSology  4.7.0-rc1
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 
243  /* pre-compile all non-plain patterns once; idx_regc[] reused in idxGrep_base() */
244  for (i = 0; i < NFOOTPRINTS; i++) {
245  if (!licText[i].plain && licText[i].regex != NULL_STR) {
246  int rc = regcomp(&idx_regc[i], licText[i].regex, REG_ICASE | REG_EXTENDED);
247  if (rc == 0) {
248  licText[i].compiled = 1;
249  } else {
250  LOG_WARNING("nomos: failed to pre-compile regex #%d: %s", i, licText[i].regex);
251  }
252  }
253  }
254  return;
255 }
256 
257 void licenseRegexFree(void)
258 {
259  int i;
260  for (i = 0; i < NFOOTPRINTS; i++) {
261  if (licText[i].compiled) {
262  regfree(&idx_regc[i]);
263  licText[i].compiled = 0;
264  }
265  }
266 }
267 
268 #define LINE_BYTES 50
269 #define LINE_WORDS 8
270 #define WC_BYTES 30
271 #define WC_WORDS 3
272 #define PUNT_LINES 3
273 #define MIN_LINES 1
296 static int searchStrategy(int index, char *regex, int aboveCalc) {
297  char *start;
298  char *cp;
299  char *s;
300  char seed[myBUFSIZ];
301  int words;
302  int lines;
303  int bytes;
304  int minLines;
305  int matchWild;
306  int matchSeed;
307 
308 #ifdef PROC_TRACE
309  traceFunc("== searchStrategy(%d(%s), \"%s\", %d)\n", index,
310  _SEED(index), regex, aboveCalc);
311 #endif /* PROC_TRACE */
312 
313  s = _SEED(index);
314  if (s == NULL_STR || strlen(s) == 0) {
315 #ifdef LICENSE_DEBUG
316  LOG_NOTICE("Lic[%d] has NULL seed", index)
317 #endif /* LICENSE_DEBUG */
318  return (0);
319  }
320  if (regex == NULL_STR || strlen(regex) == 0) {
321 #ifdef LICENSE_DEBUG
322  Assert(NO, "searchStrategy(%d) called with NULL data", index);
323 #endif /* LICENSE_DEBUG */
324  return (0);
325  }
326  if (strcmp(s, regex) == 0) {
327  return (0);
328  }
329  bytes = words = lines = 0;
330  (void) strcpy(seed, s);
331  while (seed[strlen(seed) - 1] == ' ') {
332  seed[strlen(seed) - 1] = NULL_CHAR;
333  }
334  /* how far ABOVE to look depends on location of the seed in footprint */
335  if (aboveCalc) {
336  if (strGrep(seed, regex, REG_ICASE) == 0) {
337 #ifdef LICENSE_DEBUG
338  printf("DEBUG: seed(%d) no hit in regex!\n", index);
339 #endif /* LICENSE_DEBUG */
340  return (PUNT_LINES); /* guess */
341  }
342  start = regex;
343  cp = start;
344  for (minLines = 0; cp != NULL; start = cp + 1) {
345  matchWild = matchSeed = 0;
346  if ((cp = strchr(start, ' ')) != NULL_STR) {
347  *cp = NULL_CHAR;
348  }
349  matchWild = (strcmp(start, any) == 0 || strcmp(start, some) == 0
350  || strcmp(start, few));
351  matchSeed = strcmp(start, seed) == 0;
352  if (!matchSeed) {
353  bytes += (matchWild ? WC_BYTES : strlen(start) + 1);
354  words += (matchWild ? WC_WORDS : 1);
355  }
356  if (cp != NULL_STR) {
357  *cp = ' ';
358  }
359  if (matchSeed) { /* found seed? */
360  break;
361  }
362  }
363  /* optimization for single-lines: */
364  minLines += (words >= LINE_WORDS / 2 && words < LINE_WORDS);
365  lines = MAX(bytes/LINE_BYTES, words/LINE_WORDS) + minLines;
366 #ifdef LICENSE_DEBUG
367  printf("ABOVE: .... bytes=%d, words=%d; max(%d,%d)+%d == %d\n",
368  bytes, words, bytes/LINE_BYTES, words/LINE_WORDS,
369  minLines, lines);
370 #endif /* LICENSE_DEBUG */
371  return (words == 0 ? 0 : lines);
372  }
373  /* calculate how far below to look -- depends on length of footprint */
374  for (minLines = MIN_LINES, cp = start = regex; cp; start = cp + 1) {
375  matchWild = matchSeed = 0;
376  if ((cp = strchr(start, ' ')) != NULL_STR) {
377  *cp = NULL_CHAR;
378  }
379  matchWild = (strcmp(start, any) == 0 || strcmp(start, some) == 0
380  || strcmp(start, few));
381  matchSeed = strcmp(start, seed) == 0;
382  if (matchSeed) {
383  bytes = words = 0;
384  /*minLines = MIN_LINES+1;*/
385  }
386  else {
387  bytes += (matchWild ? WC_BYTES : strlen(start) + 1);
388  words += (matchWild ? WC_WORDS : 1);
389  }
390  if (cp != NULL_STR) {
391  *cp = ' ';
392  }
393  }
394  lines = MAX(bytes/LINE_BYTES, words/LINE_WORDS) + minLines;
395 #ifdef LICENSE_DEBUG
396  printf("BELOW: .... bytes=%d, words=%d; max(%d,%d)+%d == %d\n",
397  bytes, words, bytes/LINE_BYTES, words/LINE_WORDS, minLines, lines);
398 #endif /* LICENSE_DEBUG */
399  return (lines);
400 }
401 
402 #ifdef FIX_STRINGS
403 static void fixSearchString(char *s, int size, int i, int wildcardBad)
404 {
405  char *cp;
406  int len;
407  char wildCard[16];
408  /* */
409 #ifdef PROC_TRACE
410  traceFunc("== fixSearchString(\"%s\", %d, %d, %d)\n", s, size, i,
411  wildcardBad);
412 #endif /* PROC_TRACE */
413  /* */
426  cp = s;
427  while (isspace(*cp)) {
428  cp++;
429  }
430  if (strncmp(cp, any, sizeof(any)-1) == 0 ||
431  strncmp(cp, some, sizeof(some)-1) == 0 ||
432  strncmp(cp, few, sizeof(few)-1) == 0) {
433  printf("string %d == \"%s\"\n", i, cp);
434  LOG_FATAL("Text-spec %d begins with a wild-card", i)
435  Bail(-__LINE__);
436  }
437  /*
438  * We'll replace the string " =ANY=" (6 chars) with ".*" (2 chars).
439  * The token MUST OCCUR BY ITSELF (e.g., not a substring)!
440  */
441  (void) sprintf(wildCard, " %s", any);
442  len = strlen(wildCard);
443  for (cp = s; strGrep(wildCard, cp, 0); ) {
444  if (wildcardBad) {
445  LOG_FATAL("OOPS, regex %d, wild-card not allowed here", i)
446  Bail(-__LINE__);
447  }
448  if (*(cp+cur.regm.rm_eo) == NULL_CHAR) {
449  LOG_FATAL("String %d ends in a wild-card", i)
450  Bail(-__LINE__);
451  }
452  else if (*(cp+cur.regm.rm_eo) == ' ') {
453 #ifdef DEBUG
454  printf("BEFORE(any): %s\n", s);
455 #endif /* DEBUG */
456  cp += cur.regm.rm_so;
457  *cp++ = '.';
458  *cp++ = '*';
459  memmove(cp, cp+len-1, strlen(cp+len)+2);
460 #ifdef DEBUG
461  printf("_AFTER(any): %s\n", s);
462 #endif /* DEBUG */
463  }
464  else {
465  LOG_NOTICE("Wild-card \"%s\" sub-string, phrase %d", wildCard, i)
466  cp += cur.regm.rm_eo;
467  }
468  }
469  /*
470  * Ditto for replacing " =SOME= " (8 chars) with ".{0,60}" (7 chars)
471  */
472  (void) sprintf(wildCard, " %s", some);
473  len = strlen(wildCard);
474  for (cp = s; strGrep(wildCard, cp, 0); ) {
475  if (wildcardBad) {
476  LOG_FATAL("OOPS, regex %d, wild-card not allowed here", i)
477  Bail(-__LINE__);
478  }
479  if (*(cp+cur.regm.rm_eo) == NULL_CHAR) {
480  LOG_FATAL("String %d ends in a wild-card", i)
481  Bail(-__LINE__);
482  }
483  else if (*(cp+cur.regm.rm_eo) == ' ') {
484 #ifdef DEBUG
485  printf("BEFORE(some): %s\n", s);
486 #endif /* DEBUG */
487  cp += cur.regm.rm_so;
488  *cp++ = '.';
489  *cp++ = '{';
490  *cp++ = '0';
491  *cp++ = ',';
492  *cp++ = '6';
493  *cp++ = '0';
494  *cp++ = '}';
495  memmove(cp, cp+len-6, strlen(cp+len)+7);
496 #ifdef DEBUG
497  printf("_AFTER(some): %s\n", s);
498 #endif /* DEBUG */
499  }
500  else {
501  LOG_NOTICE("Wild-card \"%s\" sub-string, phrase %d", wildCard, i)
502  cp += cur.regm.rm_eo;
503  }
504  }
505  /*
506  * And, same for replacing " =FEW= " (7 chars) with ".{0,15}" (7 chars)
507  */
508  (void) sprintf(wildCard, " %s", few);
509  len = strlen(wildCard);
510  for (cp = s; strGrep(wildCard, cp, 0); ) {
511  if (wildcardBad) {
512  LOG_FATAL("OOPS, regex %d, wild-card not allowed here", i)
513  Bail(-__LINE__);
514  }
515  if (*(cp+cur.regm.rm_eo) == NULL_CHAR) {
516  LOG_FATAL("String %d ends in a wild-card", i)
517  Bail(-__LINE__);
518  }
519  else if (*(cp+cur.regm.rm_eo) == ' ') {
520 #ifdef DEBUG
521  printf("BEFORE(few): %s\n", s);
522 #endif /* DEBUG */
523  cp += cur.regm.rm_so;
524  *cp++ = '.';
525  *cp++ = '{';
526  *cp++ = '0';
527  *cp++ = ',';
528  *cp++ = '3';
529  *cp++ = '0';
530  *cp++ = '}';
531  memmove(cp, cp+len-6, strlen(cp+len)+7);
532 #ifdef DEBUG
533  printf("_AFTER(few): %s\n", s);
534 #endif /* DEBUG */
535  }
536  else {
537  LOG_NOTICE("Wild-card \"%s\" sub-string, phrase %d", wildCard, i)
538  cp += cur.regm.rm_eo;
539  }
540  }
541  /*
542  * AND, replace the string "=YEAR=" with "[12][0-9][0-9][0-9][,- ]*".
543  * The former is 6 chars in length, the latter is 24. We must be careful
544  * not to overflow the buffer we're passed.
545  */
546  len = strlen(year);
547  while (strGrep(year, s, 0)) {
548  if (strlen(s)+25 >= size) { /* 24 plus 1(NULL) */
549  LOG_FATAL("buffer overflow, text-spec %d", i)
550  Bail(-__LINE__);
551  }
552  cp = (char *)(s+cur.regm.rm_so);
553 #ifdef DEBUG
554  printf("BEFORE: %s\n", s);
555 #endif /* DEBUG */
556  memmove(cp+25, cp+6, strlen(cp+len)+1); /* was 26, 6 */
557  memset(cp+6, '_', 19);
558 #ifdef DEBUG
559  printf("_MOVED: %s\n", s);
560 #endif /* DEBUG */
561  *cp = *(cp+4) = *(cp+9) = *(cp+14) = *(cp+19) = '[';
562  *(cp+1) = '1';
563  *(cp+2) = '2';
564  *(cp+5) = *(cp+10) = *(cp+15) = '0';
565  *(cp+6) = *(cp+11) = *(cp+16) = '-';
566  *(cp+7) = *(cp+12) = *(cp+17) = '9';
567  *(cp+3) = *(cp+8) = *(cp+13) = *(cp+18) = *(cp+23) = ']';
568  *(cp+20) = ' ';
569  *(cp+21) = ',';
570  *(cp+22) = '-';
571  *(cp+24) = '*';
572 #ifdef DEBUG
573  printf("_AFTER: %s\n", s);
574 #endif /* DEBUG */
575  }
576  return;
577 }
578 #endif /* FIX_STRINGS */
579 
580 char* createRelativePath(item_t *p, scanres_t *scp)
581 {
582  char* cp;
583  if (*(p->str) == '/')
584  {
585  strcpy(scp->fullpath, p->str);
586  scp->nameOffset = (size_t) (cur.targetLen + 1);
587  cp = scp->fullpath; /* full pathname */
588  }
589  else
590  {
591  strncpy(scp->fullpath, cur.cwd, sizeof(scp->fullpath)-1);
592  strncat(scp->fullpath, "/", sizeof(scp->fullpath)-1);
593  strncat(scp->fullpath, p->str, sizeof(scp->fullpath)-1);
594  scp->nameOffset = (size_t) (cur.cwdLen + 1);
595  cp = p->str; /* relative path == faster open() */
596  }
597 
598  return cp;
599 }
600 
617 void scanForKeywordsAndSetScore(scanres_t* scores, list_t* licenseList)
618 {
619  /*
620  CDB -- Some other part of FOSSology has already decided we
621  want to scan this file, so we need to look into removing this
622  file scoring stuff.
623  */
624  scanres_t* scp;
625  int c;
626  item_t* p;
627  char* textp;
628  char* cp;
629  for (scp = scores; (p = listIterate(licenseList)) != NULL_ITEM ; scp++)
630  {
631 
632  /*
633  * Use *relative* pathnames wherever possible -- we'll spend less time in
634  * the kernel looking up inodes and pathname components that way.
635  */
636  cp = createRelativePath(p, scp);
637 
638 #ifdef DEBUG
639  printf("licenseScan: scan %s\n",
640  (char *)(scp->fullpath+scp->nameOffset));
641 #endif /* DEBUG */
642  /*
643  * Zero-length files are of no interest; there's nothing in them!
644  * CDB - We need to report this error somehow... and clean up
645  * /tmp/nomos.tmpdir (or equivalent).
646  */
647  if ((textp = mmapFile(cp)) == NULL_STR) {
648  /* perror(cp); */
649  /*printf("Zero length file: %s\n", cp); */
650  continue;
651  }
652  scp->size = cur.stbuf.st_size; /* Where did this get set ? CDB */
653  /*
654  * Disinterest #3 (discriminate-by-file-content):
655  * Files not of a known-good type (as reported by file(1)/magic(3)) should
656  * also be skipped (some are quite large!). _UTIL_MAGIC (see _autodata.c)
657  * contains a regex for MOST of the files we're interested in, but there
658  * ARE some exceptions (logged below).
659  *
660  *****
661  * exception (A): patch/diff files are sometimes identified as "data".
662  *****
663  * FIX-ME: we don't currently use _UTIL_FILTER, which is set up to
664  * exclude some files by filename.
665  */
666  /*
667  * Scan for keywords (_KW_), and use the number found for the score.
668  */
669  assert(NKEYWORDS >= sizeof(scp->kwbm));
670 
671  for (scp->kwbm = c = 0; c < NKEYWORDS; c++)
672  {
673  if (idxGrep_recordPosition(c + _KW_first, textp, REG_EXTENDED | REG_ICASE))
674  {
675  scp->kwbm |= (1 << c); // put a one at c'th position in kwbm (KeywordByteMap)
676  scp->score++;
677 #if (DEBUG > 5)
678  printf("Keyword %d (\"%s\"): YES\n", c, _REGEX(c+_KW_first));
679 #endif /* DEBUG > 5 */
680  }
681  }
682  munmapFile(textp);
683 #if (DEBUG > 5)
684  printf("%s = %d\n", (char *)(scp->fullpath+scp->nameOffset),
685  scp->score);
686 #endif /* DEBUG > 5 */
687 
688  }
689  return;
690 }
691 
703 {
704  /*
705  * CDB - It is always the case that we are doing one file at a time.
706  */
707  if (scores->score == 0)
708  {
709  scores->score = 1;
710  }
711 }
712 
724 int fiterResultsOfKeywordScan(int lowWater, scanres_t* scores, int nFiles)
725 {
726  int nCand;
727 
728  scanres_t* scp;
729  int i;
730 
731  for (scp = scores, i = nCand = 0; i < nFiles; i++, scp++)
732  {
733  scp->relpath = (char *) (scp->fullpath + scp->nameOffset);
734  if (idxGrep(_FN_LICENSEPATT, pathBasename(scp->relpath), REG_ICASE
735  | REG_EXTENDED)) {
736  scp->flag = 1;
737  if (idxGrep(_FN_DEBCPYRT, scp->relpath, REG_ICASE)) {
738  scp->flag = 2;
739  }
740  }
741  else if (scp->score >= lowWater) {
742  scp->flag |= 1;
743  }
744  /*
745  * So now, save any license candidate EITHER named "debian/copyright*"
746  * OR having a score > 0
747  */
748  if (scp->flag == 2 || (scp->score && scp->flag)) {
749 #if (DEBUG > 3)
750  printf("%s [score: %d], %07o\n", scp->fullpath,
751  scp->score, scp->kwbm);
752 #endif /* DEBUG > 3 */
753  nCand++;
754  }
755  }
756  return nCand;
757 }
758 
770 void licenseScan(list_t *licenseList)
771 {
772  int lowWater = 1; // constant
773 
774  int nCand; //relevant output
775 
776  //fields
777  int counts[NKEYWORDS + 1];
778  scanres_t *scores;
779 
780  //recycled temp variables
781  scanres_t *scp;
782  int nFilesInList;
783 
784 #ifdef PROC_TRACE
785  traceFunc("== licenseScan(%p, %d)\n", l);
786 #endif /* PROC_TRACE */
787 
788 #ifdef MEMSTATS
789  printf("... allocating %d bytes for scanres_t[] array\n",
790  sizeof(*scp)*licenseList->used);
791 #endif /* MEMSTATS */
792 
793  scores = (scanres_t *) memAlloc(sizeof(*scp) * licenseList->used, MTAG_SCANRES);
794  memset((void *) counts, 0, (size_t) ((NKEYWORDS + 1) * sizeof(int)));
795 
796  scanForKeywordsAndSetScore(scores, licenseList);
798 
799 #ifdef PROC_TRACE
800  traceFunc("=> invoking qsort(): callback == scoreCompare()\n");
801 #endif /* PROC_TRACE */
802 
803  nFilesInList = licenseList->used;
804  qsort(scores, (size_t) nFilesInList, sizeof(*scp), scoreCompare);
805 
806  //recycled temp variables
807  nCand = fiterResultsOfKeywordScan(lowWater, scores, nFilesInList);
808  /*
809  * OF SPECIAL INTEREST: saveLicenseData() changes directory (to "..")!!!
810  */
811  /* DBug: printf("licenseScan: gl.initwd is:%s\n",gl.initwd); */
812  saveLicenseData(scores, nCand, nFilesInList, lowWater);
813  /*
814  * At this point, we don't need either the raw-source directory or the
815  * unpacked results anymore, so get rid of 'em.
816  */
817  if (scores->licenses) free(scores->licenses);
818  memFree((char *) scores, "scores table");
819  return;
820 } /* licenseScan */
821 
832 static int scoreCompare(const void *arg1, const void *arg2) {
833  scanres_t *sc1 = (scanres_t *) arg1;
834  scanres_t *sc2 = (scanres_t *) arg2;
835 
836  if (sc1->score > sc2->score) {
837  return (-1);
838  }
839  else if (sc1->score < sc2->score) {
840  return (1);
841  }
842  else if ((sc1->fullpath != NULL_STR) && (sc2->fullpath == NULL_STR)) {
843  return (-1);
844  }
845  else if ((sc2->fullpath != NULL_STR) && (sc1->fullpath == NULL_STR)) {
846  return (1);
847  }
848  else {
849  return (-strcmp(sc1->fullpath, sc2->fullpath));
850  }
851 }
852 
856 static void noLicenseFound() {
857 
858 #ifdef PROC_TRACE
859  traceFunc("== noLicenseFound\n");
860 #endif /* PROC_TRACE */
861 
862  (void) strcpy(cur.compLic, LS_NOSUM);
863  return;
864 }
865 
877 static void printHighlightInfo(GArray* keyWords, GArray* theMatches){
878  if ( optionIsSet(OPTS_HIGHLIGHT_STDOUT) )
879  {
880  printf(" Highlighting Info at");
881  int currentKeyw;
882  for (currentKeyw=0; currentKeyw < keyWords->len; ++currentKeyw ) {
883  MatchPositionAndType* ourMatchv = getMatchfromHighlightInfo(keyWords,currentKeyw );
884  printf(" Keyword at %i, length %i, index = 0,", ourMatchv->start, ourMatchv->end - ourMatchv->start );
885  }
886  int currentLicence;
887  for (currentLicence = 0; currentLicence < theMatches->len; ++currentLicence)
888  {
889  LicenceAndMatchPositions* theLicence = getLicenceAndMatchPositions(theMatches, currentLicence);
890 
891  int highl;
892  for (highl = 0; highl < theLicence->matchPositions->len; ++highl)
893  {
894  MatchPositionAndType* ourMatchv = getMatchfromHighlightInfo(theLicence->matchPositions, highl);
895  printf(" License #%s# at %i, length %i, index = %i,", theLicence->licenceName , ourMatchv->start, ourMatchv->end - ourMatchv->start, ourMatchv->index );
896 
897  }
898  }
899  }
900  printf("\n");
901  return;
902 }
903 
907 static void printKeyWordMatches(scanres_t *scores, int idx)
908 {
909  int c;
910  int base;
911  char miscbuf[myBUFSIZ];
912  int offset;
913  /*
914  * construct the list of keywords that matched in licenseScan()
915  */
916  (void) strcpy(miscbuf, "Matches: ");
917  offset = 9; /* e.g., strlen("Matches: ") */
918  for (base = c = 0; c < NKEYWORDS; c++)
919  {
920  if (scores[idx].kwbm & (1 << c))
921  {
922  if (base++)
923  {
924  miscbuf[offset++] = ',';
925  miscbuf[offset++] = ' ';
926  }
927  offset += sprintf(miscbuf + offset, "%s", _REGEX(c + _KW_first));
928  }
929  }
930 
931  printf("%s\n", miscbuf);
932 
933 }
934 
939 static gint compare_integer(gconstpointer a, gconstpointer b)
940 {
941  gint out;
942 
943  if (a < b)
944  out = -1;
945  else if (a == b)
946  out = 0;
947  else
948  out = 1;
949  return out;
950 
951 }
952 
959 static void rescanOriginalTextForFoundLicences(char* textp, int isFileMarkupLanguage, int isPS){
960  if (cur.theMatches->len > 0 )
961  {
962  if (cur.cliMode == 1 && !optionIsSet(OPTS_HIGHLIGHT_STDOUT) ) return;
963  // do a fresh doctoring of the buffer
964  g_array_free(cur.docBufferPositionsAndOffsets, TRUE);
965  cur.docBufferPositionsAndOffsets = g_array_new(FALSE, FALSE, sizeof(pairPosOff));
966  doctorBuffer(textp, isFileMarkupLanguage, isPS, NO);
967 
968  for (cur.currentLicenceIndex = 0; cur.currentLicenceIndex < cur.theMatches->len; ++cur.currentLicenceIndex)
969  {
970  LicenceAndMatchPositions* currentLicence = getLicenceAndMatchPositions(cur.theMatches, cur.currentLicenceIndex);
971 
972  //we want to only look for each found index once
973  g_array_sort(currentLicence->indexList, compare_integer);
974 
975  int myIndex;
976  int lastindex = -1;
977  for (myIndex = 0; myIndex < currentLicence->indexList->len; ++myIndex)
978  {
979  int currentIndex = g_array_index(currentLicence->indexList, int, myIndex);
980  if (currentIndex == lastindex) continue;
981  idxGrep_recordPositionDoctored(currentIndex, textp, REG_ICASE | REG_EXTENDED);
982  lastindex = currentIndex;
983  }
984  }
985  }
986 }
987 
1005 static void saveLicenseData(scanres_t *scores, int nCand, int nElem,
1006  int lowWater) {
1007  int i;
1008  // int c;
1009  // int base;
1010  int size;
1011  int highScore = scores->score;
1012  int isFileMarkupLanguage = 0;
1013  int isPS = 0;
1014  // int offset;
1015  int idx;
1016  char *fileName;
1017  char *textp;
1018  item_t *p;
1019  char realPathOfTarget[PATH_MAX];
1020 
1021 #ifdef PROC_TRACE
1022  traceFunc("== saveLicenseData(%p, %d, %d, %d, %d)\n", scores, nCand,
1023  nElem, lowWater);
1024 #endif /* PROC_TRACE */
1025 
1026  /* DBug: printf("saveLicenseData on entry gl.initwd is:%s\n",gl.initwd); */
1027  /*
1028  * Save the necessary licensing information in a list of files...
1029  */
1030 #ifdef DEBUG
1031  printf("saveLicenseData: %d candidates\n", nCand);
1032 #endif /* DEBUG */
1033 
1034  /* changeDir("..");*//* CDB- Why?!!!! */
1035 
1036  /* BE PERFORMANCE-CONSCIOUS WITHIN THIS LOOP (it runs a LOT!) */
1037  /*
1038  * OPTIMIZE-ME: should we store local variables and use lots of
1039  * registers instead of accessing everything through the scanres
1040  * array? We've got to be doing some serious address calculations.
1041  */
1042  i = 1;
1043 
1044  for (idx = 0; i <= nCand; idx++) {
1045  /*
1046  * If we didn't flag this file as needing to be saved, ignore it.
1047  */
1048  if (scores[idx].flag == 0) {
1049  continue;
1050  }
1051  (void) sprintf(scores[idx].linkname, "Link%03d.txt", i++);
1052 #if DEBUG > 5
1053  printf("name: %s\n[%s]\n", scores[idx].relpath, scores[idx].fullpath);
1054 #endif /* DEBUG > 5 */
1055  /*
1056  * Kludge up the pointer to the relative-path in scores[idx].fullpath
1057  * so we don't
1058  * have to as many directory entries to open each file... this works for
1059  * anything EXCEPT 'distribution files'.
1060  */
1061  fileName = scores[idx].fullpath;
1062  if (optionIsSet(OPTS_DEBUG)) {
1063  printf("File name: %s\n", fileName);
1064  }
1065  if ((textp = mmapFile(fileName)) == NULL_STR) {
1066 
1067  /* Fatal("Null mmapFile(), path=%s", fileName); */
1068  noLicenseFound();
1069  continue;
1070  }
1071  /* CDB size = (int) cur.stbuf.st_size; */
1072  size = scores[idx].size;
1073  if (scores[idx].dataOffset) {
1074  textp += scores[idx].dataOffset;
1075  }
1076 
1077  /* wordCount() sets nLines in global structure "cur". */
1078  wordCount(textp);
1079 
1080  /*
1081  * Report which package (if any) this file came from
1082  */
1083 
1084  /*
1085  * Since we hard-wire the score of every file (invoked as --file), a score
1086  * of 1 could be either 0 or 1, so scores[idx].kwbm tells the real story...
1087  */
1088  if (optionIsSet(OPTS_DEBUG)) {
1089  printf("File score: %d (0x%06x)\n",
1090  (scores[idx].kwbm ? scores[idx].score : scores[idx].kwbm),
1091  scores[idx].kwbm);
1092  if (scores[idx].kwbm) {
1093  printKeyWordMatches(scores, idx);
1094  }
1095  }
1096  /*
1097  * Print the license claim (e.g., what's listed in the package)
1098  */
1099  /*
1100  * determine licenses in the file, and record 'em; wrap up by including
1101  * the file contents
1102  *****
1103  * FIX-ME: we should filter some names out like the shellscript does.
1104  * For instance, word-spell-dictionary files will score high but will
1105  * likely NOT contain a license. But the shellscript filters these
1106  * names AFTER they're already scanned. Think about it.
1107  *****
1108  FILTERPATTERNS="(/man|\.[0-9]|\.[0-9][a-z]|rfc[0-9].*|.po|.pot"
1109  FILTERPATTERNS="$FILTERPATTERNS|words.*|.*spelling.*|spell)$"
1110  */
1111 #if defined(DEBUG) || defined(DOCTOR_DEBUG) || defined(LTSR_DEBUG) \
1112  || defined(BATCH_DEBUG) || defined(PARSE_STOPWATCH) || defined(MEMSTATS) \
1113  || defined(MEM_DEBUG) || defined(UNKNOWN_CHECK_DEBUG)
1114  printf("*** PROCESS File: %s\n", scores[idx].relpath);
1115  printf("... %d bytes, score %d\n", scores[idx].size, scores[idx].score);
1116 #endif /* DEBUG || DOCTOR_DEBUG || LTSR_DEBUG || BATCH_DEBUG || PARSE_STOPWATCH || MEMSTATS || MEM_DEBUG || defined(UNKNOWN_CHECK_DEBUG)*/
1117 
1118  isFileMarkupLanguage = idxGrep(_UTIL_MARKUP, textp, REG_ICASE | REG_EXTENDED);
1119 
1120 #ifdef DOCTOR_DEBUG
1121  printf("idxGrep(ML) returns %d\n", isFileMarkupLanguage);
1122  if (isFileMarkupLanguage)
1123  {
1124  int n;
1125  printf("isMarkUp@%d: [", cur.regm.rm_so);
1126  for (n = cur.regm.rm_so; n <= cur.regm.rm_eo; n++) {
1127  printf("%c", *(textp+n));
1128  }
1129  printf("]\n");
1130  }
1131 #endif /* DOCTOR_DEBUG */
1132  /*
1133  * BUG: When _FTYP_POSTSCR is "(postscript|utf-8 unicode)", the resulting
1134  * license-parse yields 'NoLicenseFound' but when both "postscript" and
1135  * "utf-8 unicode" are searched independently, parsing definitely finds
1136  * quantifiable licenses. WHY?
1137  */
1138 #ifdef DOCTOR_DEBUG
1139  printf("idxGrep(PS) returns %d\n", isPS);
1140  if (isPS) {
1141  int n;
1142  printf("isPostScript@%d: [", cur.regm.rm_so);
1143  printf("]\n");
1144  }
1145 #endif /* DOCTOR_DEBUG */
1146  /*
1147  * Interesting - copyString(parseLicenses(args), MTAG_FILELIC)...
1148  * will randomly segfault on 32-bit Debian releases. Split the calls.
1149  */
1150  fileName = parseLicenses(textp, size, &scores[idx], isFileMarkupLanguage, isPS);
1151  scores[idx].licenses = copyString(fileName, MTAG_FILELIC);
1152 #ifdef QA_CHECKS
1153  if (fileName == NULL_STR) {
1154  Assert(NO, "Expected non-null parseLicenses return!");
1155  }
1156  if (scores[idx].licenses == NULL_STR) {
1157  Assert(NO, "Expected non-null license summary!");
1158  }
1159 #endif /* QA_CHECKS */
1160 #ifdef STOPWATCH
1161  timerBytes += size;
1162 #endif /* STOPWATCH */
1163 #ifdef FLAG_NO_COPYRIGHT
1164  if (gl.flags & FL_NOCOPYRIGHT) {
1165  p = listGetItem(&cur.nocpyrtList, scores[idx].relpath);
1166  p->buf = copyString(scores[idx].linkname, MTAG_PATHBASE);
1167  p->num = scores[idx].score;
1168  }
1169 #endif /* FLAG_NO_COPYRIGHT */
1170  if (cur.licPara != NULL_STR) {
1171  memFree(cur.licPara, MTAG_TEXTPARA); /* be free! */
1172  cur.licPara = NULL_STR; /* remember */
1173  }
1174 
1175 
1176  if( !optionIsSet(OPTS_NO_HIGHLIGHTINFO) ) {
1177  //careful this function changes the content of textp
1178  rescanOriginalTextForFoundLicences(textp, isFileMarkupLanguage, isPS);
1179  //but as it is freed right here we do not make a copy..
1180  }
1181 
1182  munmapFile(textp);
1183 
1184  /*
1185  * Remember this license in this file...
1186  */
1187  p = listGetItem(&cur.lList, scores[idx].licenses);
1188  p->refCount++;
1189  /*
1190  * Clear out the buffer-offsets list
1191  */
1192 #ifdef fix_later
1193  /* CDB - need to move this code to a point after we save the license info */
1194 #ifdef PHRASE_DEBUG
1195  listDump(&cur.offList, NO);
1196 #endif /* PHRASE_DEBUG */
1197  while ((p = listIterate(&cur.offList)) != 0) {
1198  listClear(p->buf, YES);
1199  }
1200  listClear(&cur.offList, NO);
1201 #endif /* fix_later */
1202  }
1203 
1204  listSort(&cur.lList, SORT_BY_COUNT_DSC);
1205 
1206 #ifdef QA_CHECKS
1207  if (cur.lList.used == 0) {
1208  Assert(NO, "No entries in license-list");
1209  }
1210 #endif /* QA_CHECKS */
1211 
1212  /*
1213  * Construct a 'computed license'. Wherever possible, leave off the
1214  * entries for None and LikelyNot; those are individual-file results
1215  * and we're making an 'aggregate summary' here.
1216  */
1217  if (cur.parseList.used == 0) {
1218  noLicenseFound();
1219  }
1220  else {
1221  makeLicenseSummary(&cur.parseList, highScore, cur.compLic,
1222  sizeof(cur.compLic));
1223  }
1224  if (optionIsSet(OPTS_DEBUG)) {
1225  printf("==> ");
1226  }
1227  /* CDB - Debug code */
1228  /*
1229  printf("saveLicData: the offset list is:\n");
1230  listDump(&cur.offList, YES);
1231 
1232  while ((p = listIterate(&cur.offList)) != 0) {
1233  listDump(p->buf, YES);
1234  }
1235  */
1236  /* print results if running from the command line */
1237  /* DBug: printf("saveLicenseData on return gl.initwd is:%s\n",gl.initwd); */
1238  if(cur.cliMode)
1239  {
1240  if (optionIsSet(OPTS_JSON_OUTPUT))
1241  {
1242  writeJson();
1243  } else {
1244  if (optionIsSet(OPTS_LONG_CMD_OUTPUT) && realpath(cur.targetFile, realPathOfTarget))
1245  {
1246  printf("File %s contains license(s) %s", realPathOfTarget, cur.compLic);
1247  }
1248  else
1249  {
1250  printf("File %s contains license(s) %s", basename(cur.targetFile), cur.compLic);
1251  }
1253  }
1254  }
1255  return;
1256 } /* saveLicenseData */
1257 
1258 
1287 static void makeLicenseSummary(list_t *l, int highScore, char *target, int size) {
1288  item_t *p;
1289  int printCount = 0;
1290  int len = 0;
1291  int new;
1292  int goodStuff;
1293 
1294 #ifdef PROC_TRACE
1295  traceFunc("== makeLicenseSummary(%p, %d, %p, %d)\n", l, highScore,
1296  target, size);
1297 #endif /* PROC_TRACE */
1298 
1299  if (l->used == 0) { /* zero/nothing */
1300  (void) strcpy(target, LS_NOSUM);
1301  return;
1302  }
1303  /*
1304  * Now we know there's something in the list of AT LEAST marginal interest
1305  * in the component-list. If listCount() is zero, ALL data is 'marginal';
1306  * else we have 'good stuff'. For the latter, we only summarize items with
1307  * a 'val' > 0 (the really interesting stuff).
1308  */
1309  listSort(l, SORT_BY_COUNT_DSC); /* sort components */
1310  size--; /* maximum strlen, adjust to allow *1* NULL */
1311  for (goodStuff = 0; (p = listIterate(l)) != NULL_ITEM; /*nada */) {
1312  if (p->iLevel) {
1313  goodStuff = 1; /* interesting license */
1314  l->ix = -1; /* reset saved index */
1315  break;
1316  }
1317  }
1318  while ((p = listIterate(l)) != NULL_ITEM) {
1319  if (goodStuff && (p->iLevel <= IL_LOW)) { /* uninteresting */
1320  continue;
1321  }
1322  if (printCount) {
1323  target[len++] = ',';
1324  }
1325  printCount++;
1326  new = sprintf(target + len, "%s", p->str);
1327  if ((len += new) > size) {
1328  LOG_FATAL("Buffer-overwrite, marginal license components")
1329  Bail(-__LINE__);
1330  }
1331  new = 0;
1332  }
1333  return;
1334 }
1335 
1336 #ifdef LICENSE_DEBUG
1337 dumpLicenses()
1338 {
1339  int i;
1340 
1341 #ifdef PROC_TRACE
1342  traceFunc("== dumpLicenses()\n");
1343 #endif /* PROC_TRACE */
1344 
1345  for (i = 0; i < NFOOTPRINTS; i++) {
1346  printf("License[%d]: seedlen=%d, regexlen=%d\n", i,
1347  licSpec[i].seed.csLen, licSpec[i].text.csLen);
1348  }
1349  printf("[NFOOTPRINTS = %d\n", NFOOTPRINTS);
1350 }
1351 #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:31
static void printHighlightInfo(GArray *keyWords, GArray *theMatches)
Print highlight info about matches.
Definition: licenses.c:877
static gint compare_integer(gconstpointer a, gconstpointer b)
Compare two integers.
Definition: licenses.c:939
static void saveLicenseData(scanres_t *, int, int, int)
Save/creates all the license-data in a specific directory temp directory?
Definition: licenses.c:1005
int fiterResultsOfKeywordScan(int lowWater, scanres_t *scores, int nFiles)
Run through the list once more.
Definition: licenses.c:724
void scanForKeywordsAndSetScore(scanres_t *scores, list_t *licenseList)
Definition: licenses.c:617
#define WC_WORDS
Definition: licenses.c:271
static void printKeyWordMatches(scanres_t *scores, int idx)
Prints keywords match to STDOUT.
Definition: licenses.c:907
#define MIN(a, b)
Min of two.
Definition: licenses.c:64
#define MIN_LINES
Definition: licenses.c:273
static int searchStrategy(int, char *, int)
Definition: licenses.c:296
void licenseScan(list_t *licenseList)
scan the list for a license(s)
Definition: licenses.c:770
void licenseInit()
license initialization
Definition: licenses.c:70
#define WC_BYTES
Definition: licenses.c:270
#define LINE_BYTES
Definition: licenses.c:268
static void noLicenseFound()
Mark curent scan as LS_NOSUM (No_license_found)
Definition: licenses.c:856
void relaxScoreCriterionForSingleFile(scanres_t *scores)
Reset scores to 1 if it is 0.
Definition: licenses.c:702
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:1287
#define PUNT_LINES
Definition: licenses.c:272
static void rescanOriginalTextForFoundLicences(char *textp, int isFileMarkupLanguage, int isPS)
Rescan original content for the licenses already found.
Definition: licenses.c:959
#define LINE_WORDS
Definition: licenses.c:269
static int scoreCompare(const void *, const void *)
Compare two scores.
Definition: licenses.c:832
#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:1204
char * pathBasename(char *path)
Get the basename from a file path.
Definition: util.c:616
char * copyString(char *s, char *label)
Create a copy of a string.
Definition: util.c:594
void Assert(int fatalFlag, const char *fmt,...)
Raise an assert.
Definition: util.c:1408
char * wordCount(char *textp)
VERY simple line count, does NOT have to be perfect!
Definition: util.c:552
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:1088
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:538
#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:567
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:913
FUNCTION LicenceAndMatchPositions * getLicenceAndMatchPositions(GArray *in, int index)
Get the LicenceAndMatchPositions for a given index in match array.
Definition: nomos_utils.c:925
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