I have a simple code that uses the PCRE library. I just wanted to know about the c code with pcre thus copied the code from http://www.mitchr.me/SS/exampleCode/AUPG/pcre_example.c.html
#include <pcre.h> /* PCRE lib NONE */
#include <stdio.h> /* I/O lib C89 */
#include <stdlib.h> /* Standard Lib C89 */
#include <string.h> /* Strings C89 */
/**********************************************************************************************************************************/
int main(int argc, char *argv[]) {
pcre *reCompiled;
pcre_extra *pcreExtra;
int pcreExecRet;
int subStrVec[30];
const char *pcreErrorStr;
int pcreErrorOffset;
char *aStrRegex;
char **aLineToMatch;
const char *psubStrMatchStr;
int j;
char *testStrings[] = { "This should match... hello",
"This could match... hello!",
"More than one hello.. hello",
"No chance of a match...",
NULL};
aStrRegex = "(.*)(hello)+";
printf("Regex to use: %s\n", aStrRegex);
// First, the regex string must be compiled.
reCompiled = pcre_compile(aStrRegex, 0, &pcreErrorStr, &pcreErrorOffset, NULL);
/* OPTIONS (second argument) (||'ed together) can be:
PCRE_ANCHORED -- Like adding ^ at start of pattern.
PCRE_CASELESS -- Like m//i
PCRE_DOLLAR_ENDONLY -- Make $ match end of string regardless of \n's
No Perl equivalent.
PCRE_DOTALL -- Makes . match newlins too. Like m//s
PCRE_EXTENDED -- Like m//x
PCRE_EXTRA --
PCRE_MULTILINE -- Like m//m
PCRE_UNGREEDY -- Set quantifiers to be ungreedy. Individual quantifiers
may be set to be greedy if they are followed by "?".
PCRE_UTF8 -- Work with UTF8 strings.
*/
// pcre_compile returns NULL on error, and sets pcreErrorOffset & pcreErrorStr
if(reCompiled == NULL) {
printf("ERROR: Could not compile '%s': %s\n", aStrRegex, pcreErrorStr);
exit(1);
} /* end if */
// Optimize the regex
pcreExtra = pcre_study(reCompiled, 0, &pcreErrorStr);
/* pcre_study() returns NULL for both errors and when it can not optimize the regex. The last argument is how one checks for
errors (it is NULL if everything works, and points to an error string otherwise. */
if(pcreErrorStr != NULL) {
printf("ERROR: Could not study '%s': %s\n", aStrRegex, pcreErrorStr);
exit(1);
} /* end if */
for(aLineToMatch=testStrings; *aLineToMatch != NULL; aLineToMatch++) {
printf("String: %s\n", *aLineToMatch);
printf(" %s\n", "0123456789012345678901234567890123456789");
printf(" %s\n", "0 1 2 3");
/* Try to find the regex in aLineToMatch, and report results. */
pcreExecRet = pcre_exec(reCompiled,
pcreExtra,
*aLineToMatch,
strlen(*aLineToMatch), // length of string
0, // Start looking at this point
0, // OPTIONS
subStrVec,
30); // Length of subStrVec
/* pcre_exec OPTIONS (||'ed together) can be:
PCRE_ANCHORED -- can be turned on at this time.
PCRE_NOTBOL
PCRE_NOTEOL
PCRE_NOTEMPTY */
// Report what happened in the pcre_exec call..
//printf("pcre_exec return: %d\n", pcreExecRet);
if(pcreExecRet < 0) { // Something bad happened..
switch(pcreExecRet) {
case PCRE_ERROR_NOMATCH : printf("String did not match the pattern\n"); break;
case PCRE_ERROR_NULL : printf("Something was null\n"); break;
case PCRE_ERROR_BADOPTION : printf("A bad option was passed\n"); break;
case PCRE_ERROR_BADMAGIC : printf("Magic number bad (compiled re corrupt?)\n"); break;
case PCRE_ERROR_UNKNOWN_NODE : printf("Something kooky in the compiled re\n"); break;
case PCRE_ERROR_NOMEMORY : printf("Ran out of memory\n"); break;
default : printf("Unknown error\n"); break;
} /* end switch */
} else {
printf("Result: We have a match!\n");
// At this point, rc contains the number of substring matches found...
if(pcreExecRet == 0) {
printf("But too many substrings were found to fit in subStrVec!\n");
// Set rc to the max number of substring matches possible.
pcreExecRet = 30 / 3;
} /* end if */
// Do it yourself way to get the first substring match (whole pattern):
// char subStrMatchStr[1024];
// int i, j
// for(j=0,i=subStrVec[0];i<subStrVec[1];i++,j++)
// subStrMatchStr[j] = (*aLineToMatch)[i];
// subStrMatchStr[subStrVec[1]-subStrVec[0]] = 0;
//printf("MATCHED SUBSTRING: '%s'\n", subStrMatchStr);
// PCRE contains a handy function to do the above for you:
for(j=0; j<pcreExecRet; j++) {
pcre_get_substring(*aLineToMatch, subStrVec, pcreExecRet, j, &(psubStrMatchStr));
printf("Match(%2d/%2d): (%2d,%2d): '%s'\n", j, pcreExecRet-1, subStrVec[j*2], subStrVec[j*2+1], psubStrMatchStr);
} /* end for */
// Free up the substring
pcre_free_substring(psubStrMatchStr);
} /* end if/else */
printf("\n");
} /* end for */
// Free up the regular expression.
pcre_free(reCompiled);
// Free up the EXTRA PCRE value (may be NULL at this point)
if(pcreExtra != NULL)
pcre_free(pcreExtra);
// We are all done..
return 0;
} /* end func main */
while running the program as
gcc -o test -I/usr/local/Cellar/pcre/8.35/include -L/usr/local/Cellar/pcre/8.35/lib simple_pcre.c
gives the error as
Undefined symbols for architecture x86_64:
"_pcre_compile", referenced from:
_main in ccn0k76z.o
"_pcre_exec", referenced from:
_main in ccn0k76z.o
"_pcre_free", referenced from:
_main in ccn0k76z.o
"_pcre_free_substring", referenced from:
_main in ccn0k76z.o
"_pcre_get_substring", referenced from:
_main in ccn0k76z.o
"_pcre_study", referenced from:
_main in ccn0k76z.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
how should I compile the C code using Pcre library??
You're compiling with the -L flag which tells the linker where to find the library but I don't see a -l flag with the actual library to link.
Related
I'm working on a C program to manipulate large volumes of CSV data. It was running fine in develoment with a smallish test file. But when the size of the file increases, it starts to fail. Depending on whether I compile it with gcc or minGW's gcc, it fails with segmentation error or 3221225477 / 0xC0000005 at different places, always either :
if (fclose(fp)) {
printf("Error closing file: %s, %s, %d.\n", fileName, __func__, __LINE__);
exit(300);
}
Note it doesn't get past the fclose(). Or one of these:
data_PE_T12 = calloc(width_T*dataDepthDay, sizeof(*data_PE_T12));
It's long, so I'll try to show the relevant parts. First the Main function:
#include <stdio.h>
#include <string.h> // strtok
#include <stdlib.h> // atoi & atof
#include <time.h> // time functions
#include <math.h> // expf()
...
// Array Sizes
static int dataDepth, dataDepthDay;
static int fromTime, toTime;
static int width, width_T, width_H, width_C;
// Array Pointers
static int *timeArray, *timeArrayDay, *timeArrayPE;
static struct sensorHeader_t *headerArray, *headerArray_T, *headerArray_H, *headerArray_C;
// of depth dataDepthDay
static float *data_E_T25, *data_E_T30;
static float *data_E_T12, *data_E_T18, *data_E_H60, *data_E_H70, *data_E_C1500;
static float *data_PE_T12, *data_PE_T18, *data_PE_H60, *data_PE_H70, *data_PE_C1500;
... plus loads more.
// functions
void grabDepth(void); // OK
void grabPayload(void); // OK
... plus loads more.
int main(int argc, char **argv)
{
// Grab Input File Name
if (argc == 2) {
strcpy(rawFile, "in/");
strcat(rawFile, argv[1]);
} else { // dev
strcpy(rawFile, "in/sensor_report.csv");
}
printf("size max = %d", __SIZE_MAX__);
// Parse and Copy File
grabDepth();
grabPayload();
// Run functions
genRawData(); // Raw T, H & C files
genExposureE(); //
genExposureAPE(); //
return 0;
}
Next the first function that is called. This one opens the main input file and pulls out a number of array widths and depths that are used to calloc for arrays already declared as static pointers. The idea is that this will make the memory handling nice and flexible as the file size increases...
void grabDepth(void)
{
// 1. Open File
FILE *fp = fopen(rawFile, "r");
char buf[15000]; // Big enough to deal with lots of devices.
if (!fp) {
printf("Can't open the file: %s: %s, %d.\n", rawFile, __func__, __LINE__);
exit(100);
}
while (fgets (buf, sizeof(buf), fp)) {
int lineLen = strlen(buf);
int colNum = 1;
char *field = strtok(buf, ",");
if (field && strcmp(field, "From") == 0) {
// printf("\n\n*** row 2 ***\n\n");
// int fromTime, toTime = 0;
while (field) {
if (colNum == 2) {
fromTime = atof(field);
}
if (colNum == 4) {
toTime = atof(field);
}
field = strtok(NULL, ",");
colNum++;
}
// printf("FromTime = %d. ToTime = %d.\n", fromTime, toTime);
dataDepth = ( toTime - fromTime )/900;
// printf("dataDepth = %d.\n", dataDepth);
continue; // to next iteration.
}
// 3. Grab file width from line 10 (commsType) Check if buf Overruns too
if (field && strcmp(field, "TimeStamp") == 0) {
// First Check Line is long enough!
if (lineLen == sizeof(buf)-1) { // buf has overrun!
printf("File Read-Line Overrun: %s, %d.\n", rawFile, __func__, __LINE__);
exit(200);
}
// printf("Line Length = %d\n", lineLen);
// printf("Buf Size = %d\n", sizeof(buf));
width = -2; // ignore timestamps : I ballsed up the commas in csv file (-2 instead of -1)
while (field) {
if(field = strtok(NULL, ",")) {
width ++;
}
}
break; // out of loop!
}
}
//dataDepthDay = dataDepth/96 + (dataDepth % 96 !=0); // round up?!
dataDepthDay = dataDepth/96; // round down?!
printf("\n 1. grabDepth() Results\n");
printf( "------------------------\n");
printf("Raw Data Width = %d\n", width);
printf("Raw Data Depth = %d\n", dataDepth);
printf("dataDepthDay Depth = %d\n\n", dataDepthDay);
if (fclose(fp)) {
printf("Error closing file: %s, %d.\n", rawFile, __func__, __LINE__);
exit(300);
}
}
After that, it's just calling one function after another, all of which follow the general pattern of:
void _genRawData(char* sensorType, struct sensorHeader_t *sensorHeader, float *dataArray, int *timeArray, size_t dataDepth, size_t width) {
FILE *fp;
strcpy(fileName, "out/");
strcat(fileName, sensorType);
strcat(fileName, "_raw.csv");
fp = fopen(fileName, "w");
// check file opened OK.
if (fp == NULL) {
printf("Error! Couldn't Create file: %s\n", fileName);
return;
}
printf("building file : %s\n", fileName);
// Allocate Memory
timeArrayDay = calloc(dataDepthDay, sizeof(*timeArrayDay));
timeArrayPE = calloc(dataDepthDay, sizeof(*timeArrayPE)); // xxxx same array as day time array!?
data_E_T12 = calloc(width_T*dataDepthDay, sizeof(*data_E_T12));
data_E_T18 = calloc(width_T*dataDepthDay, sizeof(*data_E_T18));
data_E_H60 = calloc(width_H*dataDepthDay, sizeof(*data_E_H60));
data_E_H70 = calloc(width_H*dataDepthDay, sizeof(*data_E_H70));
// do stuff and build new arrays up and put into files...
if (fclose(fp)) {
printf("Error closing file: %s, %d.\n", rawFile, __func__, __LINE__);
exit(300);
}
}
I've only called calloc once on each 2-D array, and for the sake of debugging I've removed the free() calls.
I figure I'm doing something wrong with memory management, which is biting me when the array sizes grow past a certain point, but I can't figure out what's wrong. I've tried to make sure the memory I access has been allocated correctly and working on a big powerful actual computer (I'm an embedded person usually), I wouldn't expect any issues with OS handing out data? Isn't there plenty to go around!?
In case the outcome is of use to others. I suspected there was an issue with the calloc and subsequent use of the allocated memory. So I tried 2 things:
1: Checked the memory usage in the code:
// Add Values & Write Line on new Day & Reset Accumulator
for (i=0; i < dataDepth; i++) {
for (j=0; j < width; j++) {
if (newDay) {
fprintf(fp, ",%.2f", APE_Accum[j]);
data_E_Array[(data_E_Index-1)*width+j] = APE_Accum[j];
if ((data_E_Index-1)*width+j+1 > (width_T*dataDepthDay)) {
printf("Oh bugger...\n");
printf("width_T*dataDepthDay = %d\n", width_T*dataDepthDay);
printf("data_E_Index-1 = %d\n", data_E_Index-1);
printf("width = %d\n", width);
printf("dataDepthDay = %d\n", dataDepthDay);
printf("width_T = %d\n", width_T);
printf("j = %d\n\n", j);
Really messy code, so you can understand how I lost track of the array bounds. Basically, it became obvious that I'd messed up my calculation of the size of the calloc. I was possible to find the problem like this, but I don't think it's a vaiable answer to my question, since it would scale to large or even more convoluted code.
2: Valgrind. Following #dbush s advice. I moved over to Ubuntu, installed Valgrind, and recompiled...
$ sudo apt install valgrind
$ ps aux | grep-i apt
$ gcc -o graphomatic ./graphomatic.c -lm -g
$ valgrind --leak-check=full --show-leak-kinds=all --verbose --track-origins=yes --log-file=valgrind-log
$ less valgrind-log
And Bob's your uncle. The problems jumped right out. I needed to add the -lm to link to the math library. And teh -g to make sure line numbers were included in the Valgrind output.
==15878== Invalid write of size 4
==15878== at 0x4038EA: _genExposureE (graphomatic.c:867)
==15878== by 0x404A0C: genExposureE (graphomatic.c:1235)
==15878== by 0x400EAA: main (graphomatic.c:122)
==15878== Address 0x75cd604 is 0 bytes after a block of size 660 alloc'd
==15878== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15878== by 0x404911: genExposureE (graphomatic.c:1222)
==15878== by 0x400EAA: main (graphomatic.c:122)
The code=3221225477 in terminal/shell.
This error/exception is thrown at times when you have segmentation errors.
By segmentation error, I mean that either you are trying to access a memory not allocated in an array.
Example:
vector<int> arr={1,2,3,4,5,6,7,8,9};
cout<<arr.at(arr.size());
This error code can also be shown as out of bound error, out of range error, or segmentation error, etc.
I'm using xmlTextReader to process large xml files. Now i need to validate the instance against an xsd schema. The api from libxml2 is a little bit confusing, how this is done.
With my approach, im getting the validation errors in the schemaParseErrorHandler function, but without any line numbers or column numbers.
How can i get these informations?
#include <stdio.h>
#include <libxml/xmlreader.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
static void schemaParseErrorHandler(void *arg, xmlErrorPtr error)
{
fprintf( stderr, "Error at line %d, column %d\n%s",
error->line, error->int2, error->message);
*((bool*)arg) = true;
}
int main( int argc, char **argv )
{
xmlInitParser();
xmlSchemaPtr schema = NULL;
xmlSchemaParserCtxtPtr schema_parser_ctxt = NULL;
int has_schema_errors = 0;
int ret = -1;
xmlSchemaValidCtxtPtr valid_ctxt = NULL;
if ((schema_parser_ctxt = xmlSchemaNewParserCtxt("example.xsd")))
{
schema = xmlSchemaParse(schema_parser_ctxt);
xmlSchemaFreeParserCtxt(schema_parser_ctxt);
if (schema)
{
valid_ctxt = xmlSchemaNewValidCtxt(schema);
}
}
xmlTextReaderPtr reader = NULL;
reader = xmlReaderForFile(filename, RPCXmlStream::STD_ENCODING, 0);
if (reader != NULL)
{
if (valid_ctxt)
{
xmlTextReaderSchemaValidateCtxt(reader, valid_ctxt, 0);
xmlSchemaSetValidStructuredErrors(valid_ctxt, schemaParseErrorHandler, &has_schema_errors);
}
ret = xmlTextReaderRead(reader);
while (ret == 1 && !has_schema_errors)
{
//... procesing informations
ret = xmlTextReaderRead(reader);
}
}
if (ret != 0)
{
xmlErrorPtr err = xmlGetLastError();
TRACE("%s: failed to parse in line %d, col %d. Error %d: %s\n",
err->file,
err->line,
err->int2,
err->code,
err->message);
}
xmlFreeTextReader(reader);
xmlCleanupParser();
return 0;
}
Another try was to use the function
xmlTextReaderSchemaValidate(reader, "example.xsd");
instead of creating an xmlSchemaNewValidCtxt, but than the programm is crashing on the first call to xmlTextReaderRead.
So how is validation done right, so that the error informations includes line and column numbers?
So, your questions got me thinking and when I looked in the libxml2 documentation,
Structure xmlError
struct _xmlError {
int domain : What part of the library raised this er
int code : The error code, e.g. an xmlParserError
char * message : human-readable informative error messag
xmlErrorLevel level : how consequent is the error
char * file : the filename
int line : the line number if available
char * str1 : extra string information
char * str2 : extra string information
char * str3 : extra string information
int int1 : extra number information
int int2 : error column # or 0 if N/A (todo: renam
void * ctxt : the parser context if available
void * node : the node in the tree
}
where we can clearly see that the xmlErrorPtr which is returned by the function xmlGetLastError() clearly contains information about the filename and the line number and the column number.
char * file : the filename
int line : the line number if available
...
int int2 : error column
So to test if this was possible or not, here is the code that I used (basically your code with minor changes to make it run on my system):
#include <stdio.h>
#include <stdbool.h>
#include <libxml/xmlreader.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
static void schemaParseErrorHandler(void *arg, xmlErrorPtr error)
{
fprintf(stderr, "Error at line %d, column %d\n%s", error->line, error->int2, error->message);
*((bool*)arg) = true;
}
int main( int argc, char **argv )
{
xmlInitParser();
xmlSchemaPtr schema = NULL;
xmlSchemaParserCtxtPtr schema_parser_ctxt = NULL;
int has_schema_errors = 0;
int ret = -1;
xmlSchemaValidCtxtPtr valid_ctxt = NULL;
if ((schema_parser_ctxt = xmlSchemaNewParserCtxt("/home/junglefox/shiporder.xsd")))
{
schema = xmlSchemaParse(schema_parser_ctxt);
xmlSchemaFreeParserCtxt(schema_parser_ctxt);
if (schema)
{
valid_ctxt = xmlSchemaNewValidCtxt(schema);
}
}
xmlTextReaderPtr reader = NULL;
const char* filename = "/home/junglefox/shiporder.xml";
reader = xmlReaderForFile(filename, /*RPCXmlStream::STD_ENCODING,*/ NULL, 0);
if (reader != NULL)
{
if (valid_ctxt)
{
xmlTextReaderSchemaValidateCtxt(reader, valid_ctxt, 0);
xmlSchemaSetValidStructuredErrors(valid_ctxt, schemaParseErrorHandler, &has_schema_errors);
}
ret = xmlTextReaderRead(reader);
while (ret == 1 && !has_schema_errors)
{
//... procesing informations
ret = xmlTextReaderRead(reader);
}
}
if (ret != 0)
{
xmlErrorPtr err = xmlGetLastError();
fprintf(stdout, "%s: failed to parse in line %d, col %d. Error %d: %s\n",
err->file,
err->line,
err->int2,
err->code,
err->message);
}
xmlFreeTextReader(reader);
xmlCleanupParser();
return 0;
}
where, the shiporder.xml and shiporder.xsd used in that program were copied from the url and saved locally.
I compiled and ran the code like this:
junglefox#ubuntu:~$ gcc -o test_xsd main.c -I/usr/include/libxml2/ -lxml2 -L/usr/lib/x86_64-linux-gnu/
junglefox#ubuntu:~$ ./test_xsd
junglefox#ubuntu:~$
The output this time was nothing. As it should be as there were no errors.
If however now I make an intentional error in the shiporder.xml file, as shown below:
Here is the partial-snippet from the buggy shiporder.xml:
<?xml version="1.0" encoding="UTF-8"?>
...
<item>
<title>Hide your heart</title>
<quantity>1</quantity>
price>9.90</price>
</item>
</shiporder>
Notice the missing < before price!
Now I run the program again,
junglefox#ubuntu:~$ ./test_xsd
Error at line 22, column 0
Element 'item': Character content other than whitespace is not allowed because the content type is 'element-only'.
which answers your question(s):
With my approach, im getting the validation errors in the schemaParseErrorHandler function, but without any line numbers or column numbers. How can i get these informations?
and,
So how is validation done right, so that the error informations includes line and column numbers?
as the output clearly shows the line number 22 and column 0, where there was an unexpected empty space due to the missing <.
I'm trying to compile some example C code with GCC/MinGW on Windows 7. The example code includes some local header files which ultimately include stdio.h, and I get this error when I try to compile:
c:\mingw\include\stdio.h:345:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before '__mingw__snprintf'
extern int __mingw_stdio_redirect__(snprintf)(char*, size_t, const char*, ...);
This is a weird one to me. How could there possibly be errors in stdio.h?
regarding:
if (i == 0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return 0;
}
pcap_freealldevs(alldevs);
since the variable i is initialized to 0 and never modified, this if() statement will always be true. One result is the call to: pcap_freealldev() will never be called.
the scope of variables should be limited as much as reasonable.
Code should never depend on the OS to clean up after itself. suggest
#include <stdio.h>
#include <stdlib.h>
#include "pcap.h"
int main( void )
{
pcap_if_t *alldevs = NULL;
char errbuf[PCAP_ERRBUF_SIZE];
/* Retrieve the device list from the local machine */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs_ex: %s\n", errbuf);
exit(1);
}
/* Print the list */
for( pcap_if_t *d = alldevs; d != NULL; d= d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (No description available)\n");
}
if ( ! alldevs )
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
}
/* We don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
}
I have written UDP packet forwarder which opens UDP port and it continuously listen on perticolar socket and when data comes to it, it forwards data to another end point.
Problem I am facing is while running process for longer duration its process eats up almost 50% of system memory and other process suffers from it.
I have use PCRE library for some regex checking but it seems like main cause of problem how can i optimize my code that can run for infinite without any memory issue.
below is my code i have use of PCRE regex and socket forwarder.
int parse(char *str){
pcre *reCompiled;
pcre_extra *pcreExtra;
int pcreExecRet;
int subStrVec[30];
const char *pcreErrorStr;
int pcreErrorOffset;
int returnval;
char *aStrRegex;
char **aLineToMatch;
const char *psubStrMatchStr;
int j;
//*aLineToMatch = str;
aStrRegex = "(.*)(\"ABC\":)(\\d+)+";
//printf("Regex to use: %s\n", aStrRegex);
// First, the regex string must be compiled.
reCompiled = pcre_compile(aStrRegex, 0, &pcreErrorStr, &pcreErrorOffset, NULL);
/* OPTIONS (second argument) (||'ed together) can be:
PCRE_ANCHORED -- Like adding ^ at start of pattern.
PCRE_CASELESS -- Like m//i
PCRE_DOLLAR_ENDONLY -- Make $ match end of string regardless of \n's
No Perl equivalent.
PCRE_DOTALL -- Makes . match newlins too. Like m//s
PCRE_EXTENDED -- Like m//x
PCRE_EXTRA --
PCRE_MULTILINE -- Like m//m
PCRE_UNGREEDY -- Set quantifiers to be ungreedy. Individual quantifiers
may be set to be greedy if they are followed by "?".
PCRE_UTF8 -- Work with UTF8 strings.
*/
// pcre_compile returns NULL on error, and sets pcreErrorOffset & pcreErrorStr
if(reCompiled == NULL) {
printf("ERROR: Could not compile '%s': %s\n", aStrRegex, pcreErrorStr);
exit(1);
} /* end if */
// Optimize the regex
pcreExtra = pcre_study(reCompiled, 0, &pcreErrorStr);
/* pcre_study() returns NULL for both errors and when it can not optimize the regex. The last argument is how one checks for
errors (it is NULL if everything works, and points to an error string otherwise. */
if(pcreErrorStr != NULL) {
printf("ERROR: Could not study '%s': %s\n", aStrRegex, pcreErrorStr);
exit(1);
}
/* Try to find the regex in aLineToMatch, and report results. */
pcreExecRet = pcre_exec(reCompiled,
pcreExtra,
str,
strlen(str), // length of string
0, // Start looking at this point
0, // OPTIONS
subStrVec,
30); // Length of subStrVec
/* pcre_exec OPTIONS (||'ed together) can be:
PCRE_ANCHORED -- can be turned on at this time.
PCRE_NOTBOL
PCRE_NOTEOL
PCRE_NOTEMPTY */
// Report what happened in the pcre_exec call..
//printf("pcre_exec return: %d\n", pcreExecRet);
if(pcreExecRet < 0) { // Something bad happened..
returnval = -1;
switch(pcreExecRet) {
case PCRE_ERROR_NOMATCH : log_message("String did not match the pattern"); break;
case PCRE_ERROR_NULL : log_message("Something was null"); break;
case PCRE_ERROR_BADOPTION : log_message("A bad option was passed"); break;
case PCRE_ERROR_BADMAGIC : log_message("Magic number bad (compiled re corrupt?)"); break;
case PCRE_ERROR_UNKNOWN_NODE : log_message("Something kooky in the compiled re"); break;
case PCRE_ERROR_NOMEMORY : log_message("Ran out of memory"); break;
default : log_message("Unknown error"); break;
} /* end switch */
} else {
//printf("Result: We have a match!\n");
// At this point, rc contains the number of substring matches found...
if(pcreExecRet == 0) {
pcreExecRet = 30 / 3;
} /* end if */
// PCRE contains a handy function to do the above for you:
for(j=0; j<pcreExecRet; j++) {
pcre_get_substring(str, subStrVec, pcreExecRet, j, &(psubStrMatchStr));
} /* end for */
returnval = atoi(psubStrMatchStr);
// Free up the substring
pcre_free_substring(psubStrMatchStr);
} /* end if/else */
// Free up the regular expression.
pcre_free(reCompiled);
// Free up the EXTRA PCRE value (may be NULL at this point)
if(pcreExtra != NULL) {
#ifdef PCRE_CONFIG_JIT
pcre_free_study(pcreExtra);
#else
pcre_free(pcreExtra);
#endif
}
return returnval;
}
-------------------Udp Listener---------------
while (1) {
n = recvfrom(sock_receiver,buf,2048,0,(struct sockaddr *)&from,&sender_length);
if (n < 0) error("recvfrom");
//write(1,"Received a datagram: ",21);
// printf("n = %d\n", n);
// printf("length of buffer = %lu\n", strlen(buf));
// write(1,buf,n);
strncpy(str, buf, n);
str[n] = '\0'; // IMPORTANT!
value = parse(str);
if(curTime != get_hour()){
//sprintf(temp_str,"Counter",minute,get_minute());
log_message("Counter reset");
reset_component_hits(components);
//reset_component_hits(dropped_msg);
curTime = get_hour();
}
if(value >=0 && components[value] < component_limit && value < max_component){
n = sendto(sock_forwarder,buf,n,0,(const struct sockaddr *)&sender,sender_length);
if (n < 0){
error("sendto");
}
components[value] = components[value]+1;
}else{
if(value < 0 ) {
error_msg = "Unable to parse component";
}else if(value >= max_component){
error_msg = "value not found in valid component list";
}else if(components[value] >= component_limit) {
error_msg = "Rate limit exceeded";
}else {
error_msg = "Message dropped for Unknown reason";
}
sprintf(temp_str,"[Component:%d] %s",value,error_msg);
log_message(temp_str);
bzero(temp_str,100);
bzero(error_msg,100);
}
// print_array(components);
// print_array(dropped_msg);
bzero(buf,2048);
bzero(str,2048);
}
I am trying to add as option in the command $ printenv the command date . e.g. if you try to run $ printenv -d it should return the date output.
I have the src code from the link ftp://ftp.ntua.gr/pub/gnu/coreutils/coreutils-8.23.tar.xz that contains all the coreutils in a linux distribution.
I have already change the source code of src/printenv.c (this file is in the coreutils.tar file). But what is my next move ?
I can not compile it with gcc printenv.c
Compile error: fatal error: config.h: No such file or directory
compilation terminated.
Should I make the makefiles/configs etc and install it manually? How?
I post my changed code (printenv.c)
/* printenv -- print all or part of environment
Copyright (C) 1989-2014 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Usage: printenv [variable...]
If no arguments are given, print the entire environment.
If one or more variable names are given, print the value of
each one that is set, and nothing for ones that are not set.
Exit status:
0 if all variables specified were found
1 if not
2 if some other error occurred
David MacKenzie and Richard Mlynarik */
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#include <getopt.h>
#include "system.h"
/* Exit status for syntax errors, etc. */
enum { PRINTENV_FAILURE = 2 };
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "printenv"
#define AUTHORS \
proper_name ("David MacKenzie"), \
proper_name ("Richard Mlynarik")
static struct option const longopts[] =
{
{"null", no_argument, NULL, '0'},
{"date", required_argument, NULL, 'd'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
};
/* Forward declarations. */
static void dateMachine (void);
void
usage (int status)
{
if (status != EXIT_SUCCESS)
emit_try_help ();
else
{
printf (_("\
Usage: %s [OPTION]... [VARIABLE]...\n\
Print the values of the specified environment VARIABLE(s).\n\
If no VARIABLE is specified, print name and value pairs for them all.\n\
\n\
"),
program_name);
fputs (_("\
-0, --null end each output line with NUL, not newline\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
emit_ancillary_info ();
}
exit (status);
}
int
main (int argc, char **argv)
{
char **env;
char *ep, *ap;
int i;
bool ok;
int optc;
bool opt_nul_terminate_output = false;
initialize_main (&argc, &argv);
set_program_name (argv[0]);
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
initialize_exit_failure (PRINTENV_FAILURE);
atexit (close_stdout);
while ((optc = getopt_long (argc, argv, "+iu:0d", longopts, NULL)) != -1)
{
switch (optc)
{
case '0':
opt_nul_terminate_output = true;
break;
case 'd':
dateMachine ();
break;
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
usage (PRINTENV_FAILURE);
}
}
if (optind >= argc)
{
for (env = environ; *env != NULL; ++env)
printf ("%s%c", *env, opt_nul_terminate_output ? '\0' : '\n');
ok = true;
}
else
{
int matches = 0;
for (i = optind; i < argc; ++i)
{
bool matched = false;
/* 'printenv a=b' is silent, even if 'a=b=c' is in environ. */
if (strchr (argv[i], '='))
continue;
for (env = environ; *env; ++env)
{
ep = *env;
ap = argv[i];
while (*ep != '\0' && *ap != '\0' && *ep++ == *ap++)
{
if (*ep == '=' && *ap == '\0')
{
printf ("%s%c", ep + 1,
opt_nul_terminate_output ? '\0' : '\n');
matched = true;
break;
}
}
}
matches += matched;
}
ok = (matches == argc - optind);
}
exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
static void
dateMachine (void)
{
system(date);
}
If you google "printenv.c" You'll find several versions of just that file, that you can compile and run with minimal jiggery-pokery.
Example: "http://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/printenv/printenv.c"
./configure && make (without sudo). It compiles every .c program locally.
It compiles only the .c files that have been changed, due to datestamp.