FOSSology  4.4.0
Open Source License Compliance by Open Source Software
wc_agent.c
Go to the documentation of this file.
1 /*
2  wc_agent: the word count agent
3  SPDX-FileCopyrightText: © 2007-2011 Hewlett-Packard Development Company, L.P.
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <signal.h>
30 #include <libgen.h>
31 
32 #include "libfossology.h"
33 
34 #ifdef COMMIT_HASH
35 char BuildVersion[]="Build version: " COMMIT_HASH ".\n";
36 #endif
37 
38 #define MAXCMD 2048
39 
40 /* for the DB */
41 void *pgConn = NULL;
42 
43 /* input for this system */
44 long GlobalPfileFk=-1;
45 char GlobalPfile[MAXCMD];
55 int IsFile(long mode)
56 {
63  if (((mode & 1<<18) + (mode & 0040000) == 0) && ((mode & 1<<28) == 0) && ((mode & 1<<29) != 0)) return 1;
64  else return 0;
65 }
66 
79 int ProcessData(long PfileFk, char *Pfile)
80 {
81  char *RepFile;
82  char Cmd[MAXCMD];
83  char SQL[MAXCMD];
84  long Bytes,Words,Lines;
85  FILE *Fin;
86  PGresult *result;
87 
88  /* Get the path to the actual file */
89  RepFile = fo_RepMkPath("files",Pfile);
90  if (!RepFile)
91  {
92  LOG_FATAL("pfile %ld Word count unable to open file.\n",GlobalPfileFk);
93  printf("LOG pfile %ld Word count unable to open file: pfile_fk=%ld pfile=%s\n",GlobalPfileFk,GlobalPfileFk,GlobalPfile);
94  PQfinish(pgConn);
95  exit(-1);
96  }
97 
98  /* Create the command to run */
99  memset(Cmd,'\0',MAXCMD);
100  snprintf(Cmd,MAXCMD,"/usr/bin/wc '%s' 2>/dev/null",RepFile);
101 
102  /* Run the command and read the results */
103  Fin = popen(Cmd,"r");
104  if (!Fin)
105  {
106  LOG_FATAL("pfile %ld Word count unable to count words.\n",GlobalPfileFk);
107  printf("LOG pfile %ld Word count unable to run command: %s\n",GlobalPfileFk,Cmd);
108  PQfinish(pgConn);
109  exit(-1);
110  }
111 
112  /* Read the results */
113  fscanf(Fin,"%ld %ld %ld",&Lines,&Words,&Bytes);
114 
115  /* Store the results */
116  if (!pgConn)
117  {
118  printf("%s: Bytes=%ld Words=%ld Lines=%ld\n",Pfile,Bytes,Words,Lines);
119  }
120  else
121  {
122  /* Store results in the database */
123  memset(Cmd,'\0',MAXCMD);
124  snprintf(Cmd,MAXCMD,"INSERT INTO agent_wc (pfile_fk,wc_words,wc_lines) VALUES (%ld,%ld,%ld);",
125  PfileFk,Words,Lines);
126  result = PQexec(pgConn, SQL);
127  if (fo_checkPQcommand(pgConn, result, SQL, __FILE__, __LINE__))
128  {
129  LOG_FATAL("pfile %ld Database insert failed.\n",GlobalPfileFk);
130  printf("LOG pfile %ld Database insert failed: %s\n",GlobalPfileFk,SQL);
131  PQfinish(pgConn);
132  exit(-1);
133  }
134  PQclear(result);
135  }
136 
137  /* Clean up */
138  pclose(Fin);
139  if(RepFile)
140  {
141  free(RepFile);
142  RepFile = NULL;
143  }
144  return(0);
145 } /* ProcessData() */
146 
154 void Usage(char *Name)
155 {
156  printf("Usage: %s [options]\n",Name);
157  printf(" -i :: Initialize the DB connection then exit (nothing downloaded)\n");
158  printf(" -c :: Specify the directory for the system configuration.\n");
159  printf(" -C :: Run from command line.\n");
160 } /* Usage() */
161 
166 int main(int argc, char *argv[])
167 {
168  int c;
169  int InitFlag=0; /* is the system just going to initialize? */
170  int CmdlineFlag = 0; /* run from command line flag, 1 yes, 0 not */
171  char *Parm = NULL;
172  char *agent_desc = "File character, line, word count.";
173  int pfile_count = 0;
174  int Agent_pk = 0;
175  int ars_pk = 0;
176  char *COMMIT_HASH;
177  char *VERSION;
178  char agent_rev[MAXCMD];
179 
180  int upload_pk = 0; // the upload primary key
181  char *AgentARSName = "wc_agent_ars";
182  int rv;
183  PGresult *result;
184  char sqlbuf[MAXCMD];
185  char *DBConfFile = NULL; /* use default Db.conf */
186  char *ErrorBuf;
187 
188 
189  /* initialize the scheduler connection */
190  fo_scheduler_connect(&argc, argv);
191 
192  /* Process command-line */
193  while((c = getopt(argc,argv,"iCc:")) != -1)
194  {
195  switch(c)
196  {
197  case 'i':
198  InitFlag=1;
199  break;
200  case 'c': break; /* handled by fo_scheduler_connect() */
201  case 'C':
202  CmdlineFlag = 1;
203  break;
204  default:
205  Usage(argv[0]);
206  exit(-1);
207  }
208  }
209 
210  /* Init */
211  pgConn = fo_dbconnect(DBConfFile, &ErrorBuf);
212  if (!pgConn )
213  {
214  LOG_FATAL("Unable to connect to database\n");
215  exit(-1);
216  }
217 
218  COMMIT_HASH = fo_sysconfig("wc_agent", "COMMIT_HASH");
219  VERSION = fo_sysconfig("wc_agent", "VERSION");
220  sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH);
221 
222  Agent_pk = fo_GetAgentKey(pgConn , basename(argv[0]), 0, agent_rev, agent_desc);
223 
224  /* When initializing the DB, don't do anything else */
225  if (InitFlag)
226  {
227  PQfinish(pgConn);
228  return(0);
229  }
230 
231  /* Run from scheduler! */
232  if (0 == CmdlineFlag)
233  {
234  while(fo_scheduler_next())
235  {
236  Parm = fo_scheduler_current();
237  if (Parm[0] != '\0')
238  {
239 
241  /* 1 parameter: upload_pk */
242  upload_pk = atoi(Parm);
243  /* does ars table exist?
244  * If not, create it.
245  */
246  rv = fo_tableExists(pgConn, AgentARSName);
247  if (!rv)
248  {
249  rv = fo_CreateARSTable(pgConn, AgentARSName);
250  if (!rv) return(0);
251  }
252 
253  /* check ars table if this is duplicate request*/
254  memset(sqlbuf, 0, sizeof(sqlbuf));
255  snprintf(sqlbuf, sizeof(sqlbuf),
256  "select ars_pk from wc_agent_ars,agent \
257  where agent_pk=agent_fk and ars_success=true \
258  and upload_fk='%d' and agent_fk='%d'",
260  result = PQexec(pgConn, sqlbuf);
261  if (fo_checkPQresult(pgConn, result, sqlbuf, __FILE__, __LINE__))
262  {
263  PQfinish(pgConn);
264  exit(-1);
265  }
266  if (PQntuples(result) > 0)
267  {
268  PQclear(result);
269  LOG_WARNING("Ignoring requested wc_agent analysis of upload %d - Results are already in database.\n",upload_pk);
270  continue;
271  }
272  PQclear(result);
273  /* Record analysis start in wc_agent_ars, the wc_agent audit trail. */
274  ars_pk = fo_WriteARS(pgConn, ars_pk, upload_pk, Agent_pk, AgentARSName, 0, 0);
275 
276  /* get all pfile ids on a upload record */
277  memset(sqlbuf, 0, sizeof(sqlbuf));
278  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT DISTINCT(pfile_pk) as pfile_id,"
279  " pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size AS pfile_path,"
280  " ufile_mode FROM uploadtree, pfile"
281  " WHERE uploadtree.pfile_fk = pfile.pfile_pk"
282  " AND pfile.pfile_pk not in(SELECT pfile_fk from agent_wc)"
283  " AND upload_fk = '%d' LIMIT 5000;", upload_pk);
284  result = PQexec(pgConn, sqlbuf);
285  if (fo_checkPQresult(pgConn, result, sqlbuf, __FILE__, __LINE__))
286  {
287  PQfinish(pgConn);
288  exit(-1);
289  }
290  pfile_count = PQntuples(result);
291  int i;
292  long ufile_mode = 0;
293  for(i=0; i < pfile_count; i++)
294  {
295  ufile_mode = atoi(PQgetvalue(result, i, 2));
296  if (IsFile(ufile_mode))
297  {
298  GlobalPfileFk = atoi(PQgetvalue(result, i, 0));
299  strncpy(GlobalPfile, PQgetvalue(result, i, 1), sizeof(GlobalPfile));
300  if (ProcessData(GlobalPfileFk,GlobalPfile) != 0)
301  {
302  LOG_FATAL("pfile %ld Word count failed.\n",GlobalPfileFk);
303  printf("LOG pfile %ld Word count failed: pfile_fk=%ld pfile=%s\n",GlobalPfileFk,GlobalPfileFk,GlobalPfile);
304  PQfinish(pgConn);
305  PQclear(result);
306  exit(-1);
307  }
308  }
309  }
310  PQclear(result);
311  }
312  }
313  } /* if run from scheduler */
314 
315  /* Clean up */
316  PQfinish(pgConn);
318  return(0);
319 } /* main() */
320 
321 
char SQL[256]
SQL query to execute.
Definition: adj2nest.c:78
char BuildVersion[]
Definition: buckets.c:68
char * Pfile
Pfile name (SHA1.MD5.Size)
int Agent_pk
agent identifier
Definition: finder.c:19
FUNCTION int fo_CreateARSTable(PGconn *pgConn, const char *tableName)
Create ars table if it doesn't already exist.
Definition: libfossagent.c:270
FUNCTION int fo_WriteARS(PGconn *pgConn, int ars_pk, int upload_pk, int agent_pk, const char *tableName, const char *ars_status, int ars_success)
Write ars record.
Definition: libfossagent.c:214
FUNCTION int fo_GetAgentKey(PGconn *pgConn, const char *agent_name, long Upload_pk, const char *rev, const char *agent_desc)
Get the latest enabled agent key (agent_pk) from the database.
Definition: libfossagent.c:158
PGconn * fo_dbconnect(char *DBConfFile, char **ErrorBuf)
Connect to a database. The default is Db.conf.
Definition: libfossdb.c:29
int fo_checkPQresult(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres SELECT.
Definition: libfossdb.c:170
int fo_tableExists(PGconn *pgConn, const char *tableName)
Check if table exists. Note, this assumes the database name is 'fossology'.
Definition: libfossdb.c:232
int fo_checkPQcommand(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres commands (not select) If an error occured, write the error to s...
Definition: libfossdb.c:204
The main FOSSology C library.
char * fo_RepMkPath(const char *Type, char *Filename)
Given a filename, construct the full path to the file.
Definition: libfossrepo.c:352
void fo_scheduler_disconnect(int retcode)
Disconnect the scheduler connection.
void fo_scheduler_heart(int i)
This function must be called by agents to let the scheduler know they are alive and how many items th...
char * fo_sysconfig(const char *sectionname, const char *variablename)
gets a system configuration variable from the configuration data.
char * fo_scheduler_current()
Get the last read string from the scheduler.
char * fo_scheduler_next()
Get the next data to process from the scheduler.
void fo_scheduler_connect(int *argc, char **argv, PGconn **db_conn)
Establish a connection between an agent and the scheduler.
const char * upload_pk
Definition: sqlstatements.h:82
char * DBConfFile
DB conf file location.
Definition: testRun.c:21
void * pgConn
Database connection.
Definition: wc_agent.c:41
int main(int argc, char *argv[])
main function
Definition: wc_agent.c:166
void Usage(char *Name)
Say how to run this program.
Definition: wc_agent.c:154
int IsFile(long mode)
Check if the pfile_id is a file.
Definition: wc_agent.c:55
int ProcessData(long PfileFk, char *Pfile)
This function does the work.
Definition: wc_agent.c:79
char GlobalPfile[MAXCMD]
Definition: wc_agent.c:45