示例#1
0
int main(int argc, char** argv)
{
  fo_scheduler_connect(&argc, argv, NULL);
  if(fo_scheduler_next() == NULL)
    fo_scheduler_disconnect(0);
  else
    fo_scheduler_disconnect(-1);

  return 0;
}
示例#2
0
/**
 * @brief Exit function.  This does all cleanup and should be used
 *        instead of calling exit() or main() return.
 *
 * @param ExitVal Exit value
 * @returns void Calls exit()
 */
void exitNow(int exitVal)
{
  if (pgConn) PQfinish(pgConn);

  if (exitVal) LOG_ERROR("Exiting with status %d", exitVal);

  fo_scheduler_disconnect(exitVal);
  exit(exitVal);
} /* exitNow() */
示例#3
0
int main(int argc, char** argv)
{
  fo_scheduler_connect(&argc, argv, NULL);

  while(1)
  {
    fo_scheduler_next();
  }

  fo_scheduler_disconnect(0);
  return 0;
}
示例#4
0
/**
 * \brief Close connections and exit
 *
 * The function closes DB and scheduler connections and calls exit() with the
 * return code passed
 * \param exitval Return code to pass to exit()
 */
FUNCTION void Bail(int exitval)
{
#ifdef PROC_TRACE
  traceFunc("== Bail(%d)\n", exitval);
#endif /* PROC_TRACE */

#if defined(MEMORY_TRACING) && defined(MEM_ACCT)
  if (exitval)
  {
    memCacheDump("Mem-cache @ Bail() time:");
  }
#endif /* MEMORY_TRACING && MEM_ACCT */

  /* close database and scheduler connections */
  if (gl.pgConn) {
    fo_dbManager_free(gl.dbManager);
    PQfinish(gl.pgConn);
  }
  fo_scheduler_disconnect(exitval);
  exit(exitval);
}
示例#5
0
int	main	(int argc, char *argv[])
{
  int  nonoptargs;
  int  c, retCode;

  regex_t regex;

  char regexStr[1024];  /* string storage for the regex expression */
  bool regexSet = false;

  char fileName[1000];
  FILE *scanFilePtr;

  char uploadNum[10];

  int  scannedCount = 0;

  int   user_pk;
  long  UploadPK=-1;

  char *COMMIT_HASH;
  char *VERSION;
  char agent_rev[myBUFSIZ];

  /* connect to scheduler.  Noop if not run from scheduler.  */
  fo_scheduler_connect(&argc, argv, &pgConn);

/*
  Version reporting.
*/
  COMMIT_HASH = fo_sysconfig("regexscan", "COMMIT_HASH");
  VERSION = fo_sysconfig("regexscan", "VERSION");
  sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH);
#ifdef REGEX_DEBUG
  fprintf(stdout, "regexscan reports version info as '%s.%s'.\n", VERSION, COMMIT_HASH);
#endif

  /* Process command-line */
  while((c = getopt(argc,argv,"chir:v")) != -1)
  {
    switch(c)
    {
    case 'c':
      break;  /* handled by fo_scheduler_connect()  */
    case 'i':
      PQfinish(pgConn);
      return(0);
    case 'r':
      sprintf(regexStr, "%s", optarg);
      regexSet = true;
      break;
    case 'v':
      agent_verbose++;
      break;
    case 'h':
    default:
      Usage(argv[0]);
      fflush(stdout);
      PQfinish(pgConn);
      exit(-1);
    }
  }

  /* Sanity check for regex value required here. */
  if (!regexSet)
  {
    fprintf (stderr, "No regex value has been requested!\n");
    PQfinish(pgConn);
    fo_scheduler_disconnect(0);
    return 1;
  }

  /* process filename after switches. How many non-option arguments are there ? */
  nonoptargs = argc - optind; /* total argument count minus the option count */

  if (nonoptargs == 0)
  {
    /* Assume it was a scheduler call */
    user_pk = fo_scheduler_userID();

    while(fo_scheduler_next())
    {
      UploadPK = atol(fo_scheduler_current());

      printf("UploadPK is: %ld\n", UploadPK);
      sprintf(uploadNum, "%ld", UploadPK);
	    scannedCount = regexScanUpload(uploadNum, regexStr);
      if (scannedCount == 0)
      {
        fprintf(stderr, "Failed to successfully scan: upload - %s!\n", uploadNum);
      }
    }
  }
  else
  {
    /* File access initialization - For Stage 3 use first arg as fileName */
    sprintf(fileName, "%s", argv[optind]);      /* Grab first non-switch argument as filename */

    scanFilePtr = fopen(fileName, "r");
    if (!scanFilePtr)
    {
      fprintf(stderr, "ERROR: Unable to open '%s'\n", fileName);
      PQfinish(pgConn);
      fo_scheduler_disconnect(0);
    }

    /* Compile the regex for improved performance */
    retCode = regcomp(&regex, regexStr, REG_ICASE+REG_EXTENDED);
    if (retCode)
    {
      fprintf(stderr, "regex %s failed to compile\n", regexStr);
      PQfinish(pgConn);
      fo_scheduler_disconnect(0);
    }

    /* Now call the function that scans a file for a regex */
    retCode = regexScan(&regex, (char *)regexStr, scanFilePtr, (char *)fileName);
//    retCode = regexScan(uploadNum, regexStr);
    if (retCode != 0)
    {
      fprintf(stderr, "Failed to successfully scan: %s!\n", fileName);
    }

  }

  PQfinish(pgConn);
  fo_scheduler_disconnect(0);

  return 0;
} /* main() */
示例#6
0
/**
 * \brief Get the mimetype for a package
 * \param argc the number of command line arguments
 * \param argv the command line arguments
 * \return 0 on a successful program execution
 */
int main(int argc, char *argv[])
{
  int arg;
  char *Parm = NULL;
  char *Path = NULL;
  int c;
  char *agent_desc = "Determines mimetype for each file";
  int pfile_count = 0;
  int Agent_pk;
  int ars_pk = 0;

  int upload_pk = 0;           // the upload primary key
  int user_pk = 0;
  char *AgentARSName = "mimetype_ars";
  int rv;
  PGresult *result;
  char sqlbuf[1024];
  int CmdlineFlag = 0;        ///< run from command line flag, 1 yes, 0 not
  char *COMMIT_HASH;
  char *VERSION;
  char agent_rev[MAXCMD];

  /* initialize the scheduler connection */
  fo_scheduler_connect(&argc, argv, &pgConn);

  /* Process command-line */
  while((c = getopt(argc,argv,"iCc:hvV")) != -1)
  {
    switch(c)
    {
      case 'i':
        PQfinish(pgConn);
        return(0);
      case 'c':
        /* do nothing with this option */
        break;
      case 'C':
        CmdlineFlag = 1;
        break;
      case 'v':
        agent_verbose++;
        break;
      case 'V':
        printf("%s", BuildVersion);
        PQfinish(pgConn);
        return(0);
      default:
        Usage(argv[0]);
        PQfinish(pgConn);
        exit(-1);
    }
  }

  COMMIT_HASH = fo_sysconfig("mimetype", "COMMIT_HASH");
  VERSION = fo_sysconfig("mimetype", "VERSION");
  sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH);
  /* Get the Agent Key from the DB */
  Agent_pk = fo_GetAgentKey(pgConn, basename(argv[0]), 0, agent_rev, agent_desc);

  FMimetype = fopen("/etc/mime.types","rb");
  if (!FMimetype)
  {
    LOG_WARNING("Unable to open /etc/mime.types\n");
  }

  MagicCookie = magic_open(MAGIC_PRESERVE_ATIME|MAGIC_MIME);
  if (MagicCookie == NULL)
  {
    LOG_FATAL("Failed to initialize magic cookie\n");
    PQfinish(pgConn);
    exit(-1);
  }
  if (magic_load(MagicCookie,NULL) != 0)
  {
    LOG_FATAL("Failed to load magic file: UnMagic\n");
    PQfinish(pgConn);
    exit(-1);
  }

  /* Run from the command-line (for testing) */
  for(arg=optind; arg < argc; arg++)
  {
    Akey = -1;
    memset(A,'\0',sizeof(A));
    strncpy(A,argv[arg],sizeof(A));
    DBCheckMime(A);
  }

  /* Run from scheduler! */
  if (0 == CmdlineFlag)
  {
    user_pk = fo_scheduler_userID(); /* get user_pk for user who queued the agent */

    while(fo_scheduler_next())
    {
      /* get piece of information, including upload_pk, others */
      Parm = fo_scheduler_current();
      if (Parm && Parm[0])
      {
        upload_pk = atoi(Parm);

        /* Check Permissions */
        if (GetUploadPerm(pgConn, upload_pk, user_pk) < PERM_WRITE)
        {
          LOG_ERROR("You have no update permissions on upload %d", upload_pk);
          continue;
        }

        /* does ars table exist?
         * If not, create it.
         */
        rv = fo_tableExists(pgConn, AgentARSName);
        if (!rv)
        {
          rv = fo_CreateARSTable(pgConn, AgentARSName);
          if (!rv) return(0);
        }

        /* check ars table if this is duplicate request*/
        memset(sqlbuf, 0, sizeof(sqlbuf));
        snprintf(sqlbuf, sizeof(sqlbuf),
            "select ars_pk from mimetype_ars,agent \
            where agent_pk=agent_fk and ars_success=true \
            and upload_fk='%d' and agent_fk='%d'",
            upload_pk, Agent_pk);
        result = PQexec(pgConn, sqlbuf);
        if (fo_checkPQresult(pgConn, result, sqlbuf, __FILE__, __LINE__)) exit(-1);
        if (PQntuples(result) > 0)
        {
          PQclear(result);
          LOG_WARNING("Ignoring requested mimetype analysis of upload %d - Results are already in database.\n",upload_pk);
          continue;
        }
        PQclear(result);

        /* Record analysis start in mimetype_ars, the mimetype audit trail. */
        ars_pk = fo_WriteARS(pgConn, ars_pk, upload_pk, Agent_pk, AgentARSName, 0, 0);

        /* get all pfile ids on a upload record */
        memset(sqlbuf, 0, sizeof(sqlbuf));
        snprintf(sqlbuf, sizeof(sqlbuf), "SELECT DISTINCT(pfile_pk) as Akey, pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size AS A FROM uploadtree, pfile WHERE uploadtree.pfile_fk = pfile.pfile_pk AND pfile_mimetypefk is NULL AND upload_fk = '%d';", upload_pk);
        result = PQexec(pgConn, sqlbuf);
        if (fo_checkPQresult(pgConn, result, sqlbuf, __FILE__, __LINE__)) exit(-1);
        pfile_count = PQntuples(result);
        int i;
        for(i=0; i < pfile_count; i++)
        {
          Akey = atoi(PQgetvalue(result, i, 0));
          strncpy(A, PQgetvalue(result, i, 1), sizeof(A));
          if (Akey <= 0 || A[0]=='\0')
          {
            printf("ERROR: Data is in an unknown format.\n");
            PQfinish(pgConn);
            exit(-1);
          }

          /* Process the repository file */
          /* Find the path */
          Path = fo_RepMkPath("files",A);
          if (Path && fo_RepExist("files",A))
          {
            /* Get the mimetype! */
            DBCheckMime(Path);
          }
          else
          {
            printf("ERROR pfile %d Unable to process.\n",Akey);
            printf("LOG pfile %d File '%s' not found.\n",Akey,A);
            PQfinish(pgConn);
            exit(-1);
          }
          /* Clean up Path memory */
          if(Path)
          {
            free(Path);
            Path = NULL;
          }
          fo_scheduler_heart(1);
        }
        PQclear(result);

        /* Record analysis success in mimetype_ars. */
        if (ars_pk) fo_WriteARS(pgConn, ars_pk, upload_pk, Agent_pk, AgentARSName, 0, 1);
      }
    }
  } /* if run from scheduler */

  /* Clean up */
  if (FMimetype) fclose(FMimetype);
  magic_close(MagicCookie);
  if (DBMime) PQclear(DBMime);
  if (pgConn) PQfinish(pgConn);
  /* after cleaning up agent, disconnect from the scheduler, this doesn't return */
  fo_scheduler_disconnect(0);
  return(0);
} /* main() */
示例#7
0
文件: main.c 项目: rlintu/fossology
/**
 * \brief main function for the pkgagent
 *
 * There are 2 ways to use the pkgagent agent:
 *   1. Command Line Analysis :: test a rpm file from the command line
 *   2. Agent Based Analysis  :: run from the scheduler
 *
 * +-----------------------+
 * | Command Line Analysis |
 * +-----------------------+
 *
 * To analyze a rpm file from the command line:
 *   file :: if files are rpm package listed, display their meta data
 *   -v   :: verbose (-vv = more verbose)
 *
 *   example:
 *     $ ./pkgagent rpmfile
 *
 * +----------------------+
 * | Agent Based Analysis |
 * +----------------------+
 *
 * To run the pkgagent as an agent simply run with no command line args
 *   no file :: process data from the scheduler
 *   -i      :: initialize the database, then exit
 *
 *   example:
 *     $ upload_pk | ./pkgagent
 *
 * \param argc the number of command line arguments
 * \param argv the command line arguments
 * \return 0 on a successful program execution
 */
int	main	(int argc, char *argv[])
{
    int c;
    char *agent_desc = "Pulls metadata out of RPM or DEBIAN packages";
    //struct rpmpkginfo *glb_rpmpi;
    //struct debpkginfo *glb_debpi;
    int Agent_pk;
    int ars_pk = 0;

    int upload_pk = 0;           // the upload primary key
    int user_pk = 0;           // the upload primary key
    char *AgentARSName = "pkgagent_ars";
    int rv;
    PGresult *ars_result;
    char sqlbuf[1024];
    char *COMMIT_HASH;
    char *VERSION;
    char agent_rev[MAXCMD];
    int CmdlineFlag = 0; /* run from command line flag, 1 yes, 0 not */

    fo_scheduler_connect(&argc, argv, &db_conn);

    //glb_rpmpi = (struct rpmpkginfo *)malloc(sizeof(struct rpmpkginfo));
    //glb_debpi = (struct debpkginfo *)malloc(sizeof(struct debpkginfo));

    COMMIT_HASH = fo_sysconfig("pkgagent", "COMMIT_HASH");
    VERSION = fo_sysconfig("pkgagent", "VERSION");
    sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH);
    Agent_pk = fo_GetAgentKey(db_conn, basename(argv[0]), 0, agent_rev, agent_desc);

    /* Process command-line */
    while((c = getopt(argc,argv,"ic:CvVh")) != -1)
    {
        switch(c)
        {
        case 'i':
            PQfinish(db_conn);  /* DB was opened above, now close it and exit */
            exit(0);
        case 'v':
            Verbose++;
            break;
        case 'c':
            break; /* handled by fo_scheduler_connect() */
        case 'C':
            CmdlineFlag = 1;
            break;
        case 'V':
            printf("%s", BuildVersion);
            PQfinish(db_conn);
            return(0);
        default:
            Usage(argv[0]);
            PQfinish(db_conn);
            exit(-1);
        }
    }
    /* If no args, run from scheduler! */
    if (CmdlineFlag == 0)
    {
        user_pk = fo_scheduler_userID(); /* get user_pk for user who queued the agent */

        while(fo_scheduler_next())
        {
            upload_pk = atoi(fo_scheduler_current());

            /* Check Permissions */
            if (GetUploadPerm(db_conn, upload_pk, user_pk) < PERM_WRITE)
            {
                LOG_ERROR("You have no update permissions on upload %d", upload_pk);
                continue;
            }

            if (Verbose) {
                printf("PKG: pkgagent read %d\n", upload_pk);
            }
            if (upload_pk ==0) continue;

            /* check if pkgagent ars table exist?
             * if exist, check duplicate request
             * if not exist, don't check duplicate request
             */
            rv = fo_tableExists(db_conn, AgentARSName);
            if (rv)
            {
                /* check ars table to see if this is duplicate request*/
                snprintf(sqlbuf, sizeof(sqlbuf),
                         "select ars_pk from pkgagent_ars,agent \
          where agent_pk=agent_fk and ars_success=true \
          and upload_fk='%d' and agent_fk='%d'",
                         upload_pk, Agent_pk);
                ars_result = PQexec(db_conn, sqlbuf);
                if (fo_checkPQresult(db_conn, ars_result, sqlbuf, __FILE__, __LINE__)) exit(-1);
                if (PQntuples(ars_result) > 0)
                {
                    PQclear(ars_result);
                    LOG_WARNING("Ignoring requested pkgagent analysis of upload %d - Results are already in database.\n",upload_pk);
                    continue;
                }
                PQclear(ars_result);
            }
            /* Record analysis start in pkgagent_ars, the pkgagent audit trail. */
            ars_pk = fo_WriteARS(db_conn, ars_pk, upload_pk, Agent_pk, AgentARSName, 0, 0);

            /* process the upload_pk pkgagent */
            if(ProcessUpload(upload_pk) != 0) return -1;

            /* Record analysis success in pkgagent_ars. */
            if (ars_pk) fo_WriteARS(db_conn, ars_pk, upload_pk, Agent_pk, AgentARSName, 0, 1);
        }
    }
    else
    {
        if (Verbose) {
            printf("DEBUG: running in cli mode, processing file(s)\n");
        }
        for (; optind < argc; optind++)
        {
            struct rpmpkginfo *rpmpi;
            rpmpi = (struct rpmpkginfo *)malloc(sizeof(struct rpmpkginfo));
            rpmReadConfigFiles(NULL, NULL);
            //if(ProcessUpload(atoi(argv[optind])) == 0)
            if(GetMetadata(argv[optind],rpmpi) != -1)
                printf("OK\n");
            else
                printf("Fail\n");
#ifdef _RPM_4_4_COMPAT
            rpmFreeCrypto();
            int i;
            for(i=0; i< rpmpi->req_size; i++)
                free(rpmpi->requires[i]);
#endif /* After RPM4.4 version*/
            free(rpmpi->requires);
            free(rpmpi);
            rpmFreeMacros(NULL);
        }
    }

    PQfinish(db_conn);
    fo_scheduler_disconnect(0);
    return(0);
} /* main() */
示例#8
0
/**
 * \brief main function for the delagent
 *
 * There are 2 ways to use the delagent agent:
 *   1. Command Line :: delete/list upload/folder/license from the command line
 *   2. Agent Based  :: run from the scheduler
 *
 * +-----------------------+
 * | Command Line Analysis |
 * +-----------------------+
 *
 * List or delete uploads.
 *   -h            :: help (print this message), then exit.
 *   -i            :: Initialize the DB
 *   -u            :: List uploads IDs.
 *   -U #          :: Delete upload ID.
 *   -L #          :: Delete ALL licenses associated with upload ID.
 *   -f            :: List folder IDs.
 *   -F #          :: Delete folder ID and all uploads under this folder.
 *   -T            :: TEST -- do not update the DB or delete any files (just pretend).
 *   -v            :: Verbose (-vv for more verbose).
 *   -V            :: print the version info, then exit.
 *   -c SYSCONFDIR :: Specify the directory for the system configuration.
 *   --user #      :: user name
 *   --password #  :: password
 *
 * +----------------------+
 * | Agent Based Analysis |
 * +----------------------+
 *
 * To run the delagent as an agent
 *   -s :: Run from the scheduler
 *
 *
 * \param argc the number of command line arguments
 * \param argv the command line arguments
 * \return 0 on a successful program execution
 */
int main (int argc, char *argv[])
{
  int c;
  int listProj=0, listFolder=0;
  long delUpload=0, delFolder=0, delLicense=0, delFolderParent=0;
  int scheduler=0; /* should it run from the scheduler? */
  int gotArg=0;
  char *agent_desc = "Deletes upload.  Other list/delete options available from the command line.";
  char *COMMIT_HASH;
  char *VERSION;
  char agent_rev[myBUFSIZ];
  int option_index = 0;
  char *user_name = NULL;
  char *password = NULL;
  int user_id = -1;
  int user_perm = -1;
  int returnedCode = 0;

  fo_scheduler_connect(&argc, argv, &db_conn);

  static struct option long_options[] =
  {
    {"user", required_argument, 0, 'n'},
    {"password", required_argument, 0, 'p'},
    {0, 0, 0, 0}
  };

  while ((c = getopt_long (argc, argv, "n:p:ifF:lL:sTuU:P:vVc:h",
         long_options, &option_index)) != -1)
  {
    switch (c)
    {
      case 'n':
        user_name = optarg;
        break;
      case 'p':
        password = optarg;
        break;
      case 'i':
        PQfinish(db_conn);
        return(0);
      case 'f':
        listFolder=1;
        gotArg=1;
        break;
      case 'F':
        delFolder=atol(optarg);
        gotArg=1;
        break;
      case 'L':
        delLicense=atol(optarg);
        gotArg=1;
        break;
      case 'P':
        delFolderParent=atol(optarg);
        gotArg=1;
        break;
      case 's':
        scheduler=1;
        gotArg=1;
        break;
      case 'T':
        Test++;
        break;
      case 'u':
        listProj=1;
        gotArg=1;
        break;
      case 'U':
        delUpload=atol(optarg);
        gotArg=1;
        break;
      case 'v':
        Verbose++;
        break;
      case 'c':
        gotArg=1;
        break; /* handled by fo_scheduler_connect() */
      case 'V':
        printf("%s", BuildVersion);
        PQfinish(db_conn);
        return(0);
      default:
        usage(argv[0]);
        exit(-1);
    }
  }

  if (!gotArg)
  {
    usage(argv[0]);
    exit(-1);
  }

  if (scheduler != 1)
  {
    if (0 != authentication(user_name, password, &user_id, &user_perm))
    {
      LOG_FATAL("User name or password is invalid.\n");
      exit(-1);
    }

    COMMIT_HASH = fo_sysconfig("delagent", "COMMIT_HASH");
    VERSION = fo_sysconfig("delagent", "VERSION");
    sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH);
    /* Get the Agent Key from the DB */
    fo_GetAgentKey(db_conn, basename(argv[0]), 0, agent_rev, agent_desc);

    if (listProj)
    {
      returnedCode = listUploads(user_id, user_perm);
    }
    if (returnedCode < 0)
    {
      return returnedCode;
    }
    if (listFolder)
    {
      returnedCode = listFolders(user_id, user_perm);
    }
    if (returnedCode < 0)
    {
      return returnedCode;
    }

    alarm(60);  /* from this point on, handle the alarm */
    if (delUpload)
    {
      returnedCode = deleteUpload(delUpload, user_id, user_perm);

      writeMessageAfterDelete("upload", delUpload, user_name, returnedCode);
    }
    if (delFolder)
    {
      returnedCode = deleteFolder(delFolder, delFolderParent, user_id, user_perm);

      writeMessageAfterDelete("folder", delFolder, user_name, returnedCode);
    }
    if (delLicense)
    {
      returnedCode = deleteLicense(delLicense, user_perm);

      writeMessageAfterDelete("license", delLicense, user_name, returnedCode);
    }
  }
  else
  {
    /* process from the scheduler */
    doSchedulerTasks();
  }
  fo_scheduler_disconnect(0);

  PQfinish(db_conn);
  return(returnedCode);
} /* main() */
示例#9
0
文件: main.c 项目: gerv/fossology
/**
 * @brief main function for the copyright agent
 *
 * The copyright agent is used to automatically locate copyright statements
 * found in code.
 *
 * There are 3 ways to use the copyright agent:
 *   1. Command Line Analysis :: test a file from the command line
 *   2. Agent Based Analysis  :: waits for commands from stdin
 *   3. Accuracy Test         :: tests the accuracy of the copyright agent
 *
 * +-----------------------+
 * | Command Line Analysis |
 * +-----------------------+
 *
 * To analyze a file from the command line:
 *   -C <filename>      :: run copyright agent from command line
 *   -d                 :: turn on debugging information
 *   -T <Copyright Statements | URLs| Emails> :: Copyright Statements | URLs |Emails
 *
 *   example:
 *     $ ./copyright -C myfiletoscan
 *
 * +----------------------+
 * | Agent Based Analysis |
 * +----------------------+
 *
 * To run the copyright agent as an agent simply run with no command line args
 *   -i                 :: initialize a connection to the database
 *   -d                 :: turn on debugging information
 *
 *   example:
 *     $ upload_pk | ./copyright
 *
 * +---------------+
 * | Accuracy Test |
 * +---------------+
 *
 * To test the accuracy of the copyright agent run with a -t. Make sure to run the
 * accuracy tests in the source directory with the testdata directory:
 *   -t                 :: run the accuracy analysis
 *
 *   example:
 *     $ ./copyright -t
 *
 * Running the tests will create 3 files:
 * 1. Matches: contains all of the matches found by the copyright agent, information
 *             includes what file the match was found in, the dictionary element
 *             that it matched, the name that it matched and the text that was found
 * 2. False_Positives: contains all of the false positives found by the agent,
 *             information in the file includes the file the false positive was
 *             in, the dictionary match, the name match, and the text
 * 3. Flase_Negatives: contains all of the false negatives found by the agent,
 *             information in the file includes the file the false negative was
 *             in, and the text of the false negative
 *
 * NOTE: -d will produces the exact same style of Matches file that the accuracy
 *       testing does. Currently this is the only thing that -d will produce
 *
 * @param argc the number of command line arguments
 * @param argv the command line arguments
 * @return 0 on a successful program execution
 */
int main(int argc, char** argv)
{
  /* primitives */
  char sql[512];                // buffer for database access
  int c, i = -1;                // temporary int containers
  int num_files = 0;            // the number of rows in a job
  int ars_pk = 0;               // the args primary key
  int user_pk = 0;
  long upload_pk = 0;           // the upload primary key
  long agent_pk = 0;            // the agents primary key
  char *SVN_REV = NULL;
  char *VERSION = NULL;
  char agent_rev[myBUFSIZ];
  char copy_buf[FILENAME_MAX];
  char name_buf[FILENAME_MAX];
  int report_type = 7;         // defaul as all. binary xxx 1st number as email, 2nd number as url, 3rd number as statement 
  int cli_run = 0;               // when run from command line, that mean -C option is set; 1: yes, 0: no

  /* Database structs */
  PGconn* pgConn = NULL;        // the connection to Database
  PGresult* pgResult = NULL;    // result of a database access

  /* copyright structs */
  copyright copy;               // the work horse of the copyright agent
  pair curr;                    // pair to push into the file list

  /* verbose data */
  FILE* mout = NULL;

  /* set the output streams */
  cout = stdout;
  cerr = stdout;
  cin = stdin;

  /* connect to the scheduler */
  fo_scheduler_connect(&argc, argv, &pgConn);

  /* initialize complex data strcutres */
  memset(copy_buf, '\0', sizeof(copy_buf));
  memset(name_buf, '\0', sizeof(copy_buf));
  snprintf(copy_buf, sizeof(copy_buf),
      "%s/mods-enabled/copyright/agent/copyright.dic",
      sysconfigdir);
  snprintf(name_buf, sizeof(name_buf),
      "%s/mods-enabled/copyright/agent/names.dic",
      sysconfigdir);

  if(!copyright_init(&copy, copy_buf, name_buf))
  {
    fprintf(cerr, "FATAL %s.%d: copyright initialization failed\n", __FILE__, __LINE__);
    fprintf(cerr, "FATAL %s\n", strerror(errno));
    fflush(cerr);
    return 1;
  }

  /* parse the command line options */
  while((c = getopt(argc, argv, "T:dc:C:tiVvh")) != -1)
  {
    switch(c)
    {
      case 'v': /* debugging */
        mout = fopen("Matches", "w");
        if(!mout)
        {
          fprintf(cerr, "ERROR could not open Matches for logging\n");
          fflush(cerr);
        }
        else
        {
          verbose = 1;
        }
        break;
      case 'C': /* run from command line */
        cli_run = 1;
        pair_init(&curr, string_function_registry(), int_function_registry());

        pair_set_first(curr, optarg);
        pair_set_second(curr, &i);
        num_files++;

        break;
      case 'T': /* report type, Copyright Statements | URLs| Emails */
        report_type = atoi(optarg);
        printf("report_type is:%d\n", report_type);
        break;
      case 't': /* run accuracy testing */
        run_test_files(copy);
        copyright_destroy(copy);
        return 0;
      case 'i': /* initialize database connections */
        copyright_destroy(copy);
        PQfinish(pgConn);
        return 0;
      case 'V':
        printf("%s", BuildVersion);
        copyright_destroy(copy);
        PQfinish(pgConn);
	return 0;
      default: /* error, print usage */
        copyright_usage(argv[0]);
        return 3;
    }
  }

  /** run from command line */
  if (1 == cli_run) {
    perform_analysis(pgConn, copy, curr, agent_pk, mout, report_type);
    pair_destroy(curr);
  }

  /* if there are no files in the file list then the agent is begin run from */
  /* the scheduler, open the database and grab the files to be analyzed      */
  if(num_files == 0)
  {
    /* create the sql copy structure */
    sqlcpy = fo_sqlCopyCreate(pgConn, "copyright", 32768, 7,
        "agent_fk", "pfile_fk", "copy_startbyte", "copy_endbyte", "content", "hash", "type");

    /* book keeping */
    pair_init(&curr, string_function_registry(), int_function_registry());
    db_connected = 1;
    SVN_REV = fo_sysconfig("copyright", "SVN_REV");
    VERSION = fo_sysconfig("copyright", "VERSION");
    sprintf(agent_rev, "%s.%s", VERSION, SVN_REV);
    agent_pk = fo_GetAgentKey(pgConn, AGENT_NAME, 0, agent_rev, AGENT_DESC);

    /* make sure that we are connected to the database */
    if(!check_copyright_table(pgConn))
    {
      return 5;
    }

    user_pk = fo_scheduler_userID(); /* get user_pk for user who queued the agent */

    /* enter the main agent loop */
    while(fo_scheduler_next())
    {
      upload_pk = atol(fo_scheduler_current());

      /* Check Permissions */
      if (GetUploadPerm(pgConn, upload_pk, user_pk) < PERM_WRITE)
      {
        LOG_ERROR("You have no update permissions on upload %ld", upload_pk);
        continue;
      }
                                               
      ars_pk = fo_WriteARS(pgConn, 0, upload_pk, agent_pk, AGENT_ARS, NULL, 0);

      sprintf(sql, fetch_pfile, upload_pk, agent_pk, agent_pk);
      pgResult = PQexec(pgConn, sql);
      num_files = PQntuples(pgResult);

      for(i = 0; i < num_files; i++)
      {
        c = atoi(PQgetvalue(pgResult, i, PQfnumber(pgResult, "pfile_pk")));
        pair_set_first(curr, PQgetvalue(pgResult, i, PQfnumber(pgResult, "pfilename")));
        pair_set_second(curr, &c);
        perform_analysis(pgConn, copy, curr, agent_pk, mout, REPORTALL);
      }

      fo_WriteARS(pgConn, ars_pk, upload_pk, agent_pk, AGENT_ARS, NULL, 1);
      PQclear(pgResult);
    }

    pair_destroy(curr);
  }

  if(db_connected)
  {
    fo_sqlCopyDestroy(sqlcpy, 1);
    PQfinish(pgConn);
  }

  if(verbose)
  {
    fclose(mout);
  }

  copyright_destroy(copy);
  fo_scheduler_disconnect(0);

  return 0;
}