I am trying to parse uevent using this below code but I think my regular expression is not proper causing regcomp function to fail.
Can anyone help? I am trying to do something like this.
#include <stdio.h>
#include <string.h>
#include <regex.h>
int main ()
{
char * source = "change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
char * regexString = "(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
size_t maxGroups = 4;
regex_t regexCompiled;
regmatch_t groupArray[maxGroups];
if (regcomp(®exCompiled, regexString, REG_EXTENDED))
{
printf("Could not compile regular expression.\n");
return 1;
};
regfree(®exCompiled);
return 0;
}
I am getting "Could not compile regular expression.". It means regcomp didn't recognize the regex.
When I report on the error using the code:
#include <stdio.h>
#include <string.h>
#include <regex.h>
int main(void)
{
//char * source = "change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
char * regexString = "(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
//size_t maxGroups = 4;
regex_t regexCompiled;
//regmatch_t groupArray[maxGroups];
int rc;
if ((rc = regcomp(®exCompiled, regexString, REG_EXTENDED)) != 0)
{
char buffer[1024];
regerror(rc, ®exCompiled, buffer, sizeof(buffer));
printf("Could not compile regular expression (%d: %s).\n", rc, buffer);
return 1;
}
regfree(®exCompiled);
return 0;
}
I get the output:
Could not compile regular expression (13: repetition-operator operand invalid).
The problem is in the notation (? you are using:
"(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)"
That notation is for PCRE and not POSIX. And PCRE uses ? after ( precisely because it isn't valid in other regex systems (such as POSIX).
So, if you want to use PCRE regexes, install and use the PCRE library.
Otherwise, you'll need to use:
"([a-zA-Z]+)#\\/(.*)\\/([a-zA-z]+)\\/([a-zA-z]+)"
With that in place, and noting that you need a regmatch_t for the whole of the string that's matched plus 4 captured groups (for a total of 5 captures), you can write:
#include <stdio.h>
#include <string.h>
#include <regex.h>
int main(void)
{
char *source = "change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery";
// char * regexString = "(?<action>[a-zA-Z]+)#\\/(?<dev_path>.*)\\/(?<subsystem>[a-zA-z]+)\\/(?<name>[a-zA-z]+)";
size_t maxGroups = 5;
char *regexString = "([a-zA-Z]+)#\\/(.*)\\/([a-zA-z]+)\\/([a-zA-z]+)";
regex_t regexCompiled;
regmatch_t groupArray[maxGroups];
int rc;
if ((rc = regcomp(®exCompiled, regexString, REG_EXTENDED)) != 0)
{
char buffer[1024];
regerror(rc, ®exCompiled, buffer, sizeof(buffer));
printf("Could not compile regular expression (%d: %s).\n", rc, buffer);
return 1;
}
if ((rc = regexec(®exCompiled, source, maxGroups, groupArray, 0)) != 0)
{
char buffer[1024];
regerror(rc, ®exCompiled, buffer, sizeof(buffer));
printf("Could not execute regular expression (%d: %s).\n", rc, buffer);
return 1;
}
printf("Match successful:\n");
for (size_t i = 0; i < maxGroups; i++)
{
int so = groupArray[i].rm_so;
int eo = groupArray[i].rm_eo;
printf("%zu: %d..%d [%.*s]\n", i, so, eo, eo - so, &source[so]);
}
regfree(®exCompiled);
return 0;
}
and the output is:
Match successful:
0: 0..64 [change#/devices/soc/799999.i2c/i2c-3/3-0015/power_supply/battery]
1: 0..6 [change]
2: 8..43 [devices/soc/799999.i2c/i2c-3/3-0015]
3: 44..56 [power_supply]
4: 57..64 [battery]
Related
I have a simplest possible example of sha256 written in C, using the openSSL library.
// compile with: gcc -o sha256 sha256.c -lcrypto
#include <openssl/sha.h>
#include <stdio.h>
int main(int argc, char **argv)
{
unsigned char buffer[BUFSIZ];
FILE *f;
SHA256_CTX ctx;
size_t len;
if (argc < 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
return 1;
}
f = fopen(argv[1], "r");
if (!f) {
fprintf(stderr, "couldn't open %s\n", argv[1]);
return 1;
}
SHA256_Init(&ctx);
do {
len = fread(buffer, 1, BUFSIZ, f);
SHA256_Update(&ctx, buffer, len);
} while (len == BUFSIZ);
SHA256_Final(buffer, &ctx);
fclose(f);
for (len = 0; len < SHA256_DIGEST_LENGTH; ++len)
printf("%02x", buffer[len]);
putchar('\n');
return 0;
}
I need the same for sha1, but I could not find similar simple example that actually works. The naive approach of replacing occurrences of SHA256 in the above code with SHA1 does not work (obviously).
How can I modify my program for SHA1 ?
UPDATE
as suggested by #dbush, I have used his EVP code, and integrated it into my program. My program now looks like this:
#include <stdio.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/err.h>
int main(int argc, char **argv)
{
FILE *f;
size_t len;
unsigned char buffer[BUFSIZ];
if (argc < 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
return 1;
}
f = fopen(argv[1], "r");
if (!f) {
fprintf(stderr, "couldn't open %s\n", argv[1]);
return 1;
}
EVP_MD_CTX hashctx;
//EVP_MD *hashptr = EVP_get_digestbyname("SHA256");
EVP_MD *hashptr = EVP_get_digestbyname("SHA1");
EVP_MD_CTX_init(&hashctx);
EVP_DigestInit_ex(&hashctx, hashptr, NULL));
do {
len = fread(buffer, 1, BUFSIZ, f);
EVP_DigestUpdate(&hashctx, buffer, len);
} while (len == BUFSIZ);
EVP_DigestFinal_ex(&hashctx, buffer, &len);
EVP_MD_CTX_cleanup(&hashctx);
fclose(f);
int i;
for (i = 0; i < len; ++i)
printf("%02x", buffer[i]);
return 0;
}
When I compile it using gcc -o evp evp.c -lcrypto, I get couple of errors, such as:
evp.c: In function ‘main’:
evp.c:29:19: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default]
evp.c:32:43: error: expected ‘;’ before ‘)’ token
evp.c:32:43: error: expected statement before ‘)’ token
evp.c:39:1: warning: passing argument 3 of ‘EVP_DigestFinal_ex’ from incompatible pointer type [enabled by default]
In file included from evp.c:4:0:
/usr/include/openssl/evp.h:574:5: note: expected ‘unsigned int *’ but argument is of type ‘size_t *’
Rather than using the SHA1 or SHA256 specific functions, use the EVP_Digest* family of functions which work with any hash.
...
// makes all algorithms available to the EVP* routines
OpenSSL_add_all_algorithms();
// load the error strings for ERR_error_string
ERR_load_crypto_strings();
EVP_MD_CTX hashctx;
//const EVP_MD *hashptr = EVP_get_digestbyname("SHA256");
const EVP_MD *hashptr = EVP_get_digestbyname("SHA1");
EVP_MD_CTX_init(&hashctx);
EVP_DigestInit_ex(&hashctx, hashptr, NULL);
do {
len = fread(buffer, 1, BUFSIZ, f);
EVP_DigestUpdate(&hashctx, buffer, len);
} while (len == BUFSIZ);
unsigned int outlen;
EVP_DigestFinal_ex(&hashctx, buffer, &outlen);
EVP_MD_CTX_cleanup(&hashctx);
fclose(f);
int i;
for (i = 0; i < outlen; ++i)
printf("%02x", buffer[i]);
I've omitted the error checking for brevity. To check for errors, do the following:
if (function_to_check() == 0) {
char errstr[1000];
ERR_error_string(ERR_get_error(), errstr);
printf("error: %s\n", errstr;
}
EDIT:
There were some error in the above code that have been corrected:
hashptr was declared EVP_MD *, is now const EVP_MD *.
The call to EVP_DigestInit_ex had an extra parenthesis at the end
The third parameter to EVP_DigestFinal_ex is specifically given an unsigned int * instead a size_t *, which may not necessarily be the same.
Added calls to two OpenSSL initialization functions at the top
You can simply do like this:-
#include <openssl/sha.h>
#include <stdio.h>
int main(int argc, char **argv)
{
unsigned char buffer[BUFSIZ];
FILE *f;
SHA_CTX ctx;
size_t len;
if (argc < 2) {
fprintf(stderr, "usage: %s <file>\n", argv[0]);
return 1;
}
f = fopen(argv[1], "r");
if (!f) {
fprintf(stderr, "couldn't open %s\n", argv[1]);
return 1;
}
SHA1_Init(&ctx);
do {
len = fread(buffer, 1, BUFSIZ, f);
SHA1_Update(&ctx, buffer, len);
} while (len == BUFSIZ);
SHA1_Final(buffer, &ctx);
fclose(f);
for (len = 0; len < SHA_DIGEST_LENGTH; ++len)
printf("%02x", buffer[len]);
putchar('\n');
return 0;
}
So I want to make a file named genData.c that when executed for example: ./genData filename.txt will write 1 character to that file 1000 times.
In essence creating a 1kb file.
I would like to be able to modify the for loop, say 100000 times, to generate a 1MB file and so on.
Here is what I have tried and it compiles but when executed causes a segmentation fault.
Any suggestions? Sorry C is a language I've never dabbled in.
#include <stdio.h>
int main (int argc, char *argv) {
char ch = 'A';
FILE *fp;
fp = fopen(argv[1], "wb");
int i;
for (i = 0; i < 1000; i++) {
fwrite(&ch, sizeof(char), 1, fp);
}
fclose(fp);
return 0;
}
If you compile with warnings, you get a hint as to the exact problem:
test.c:3:5: warning: second argument of ‘main’ should be ‘char **’ [-Wmain]
int main (int argc, char *argv) {
^
All your troubles start downstream of this error. Fix this argument, and your code will work.
In the future, get into the habit of compiling with warnings turned on:
$ gcc -Wall foo.c
...
This will help catch typos and other oddities that will cause problems.
Since you tagged it Linux, this is how you can do it with the system-level functions (this should be a correct, most efficient way to do it):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sysexits.h>
#include <fcntl.h>
#include <string.h>
ssize_t /* Write "n" bytes to a descriptor */
writen(int fd, const void *ptr, size_t n);
int
main (int argc, char** argv) {
char buf[1000];
memset(buf, 'A', sizeof(buf));
int fd;
if((fd = open(argv[1], O_WRONLY|O_CREAT, 0666))<0){
perror(argv[1]);
exit(EX_NOPERM);
}
ssize_t left = writen(fd, buf, sizeof(buf));
if(left)
perror("write error\n");
return !!left;
}
ssize_t /* Write "n" bytes to a descriptor */
writen(int fd, const void *ptr, size_t n) {
size_t nleft;
ssize_t nwritten;
nleft = n;
while (nleft > 0) {
if ((nwritten = write(fd, ptr, nleft)) < 0) {
if (nleft == n)
return(-1); /* error, return -1 */
else
break; /* error, return amount written so far */
} else if (nwritten == 0) {
break;
}
nleft -= nwritten;
ptr += nwritten;
}
return(n - nleft); /* return >= 0 */
}
#include <stdio.h>
#include <stdlib.h>
#define SIZE_OF_FILE 1024
int main(int argc, char *argv[])
{
FILE *fdest;
char ch = '\n';
if(argc != 2)
exit(EXIT_FAILURE);
fdest = fopen(argv[1], "wb");
if (fdest == NULL)
exit(EXIT_FAILURE);
fseek(fdest, SIZE_OF_FILE - 1, SEEK_CUR);
fwrite(&ch, sizeof(char), 1, fdest);
fclose(fdest);
return 0;
}
In essence creating a 1kb file
if the only purpose is creating a file with sizeof x, it is more simple i belive.
I am trying to read data from 2 named pipe and write it to another named pipe concatenating the content from 2 inputs. But why my output only shows the string from first input?
Here is my code:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define MAX_REC_SIZE 1024
int open_fifo(char *name, int mode) {
mode = mode == O_RDONLY ? (O_RDONLY | O_NONBLOCK): mode;
int fd;
if (access(name, F_OK) == -1) {
if(mkfifo(name, 0777) != 0) {
fprintf(stderr, "Could not create fifo %s\n", name);
exit(EXIT_FAILURE);
}
}
fd = open(name, mode);;
return fd;
}
void read_fifo(int fd, char *out_r) {
memset (out_r, '\0', MAX_REC_SIZE);
do {
if(read(fd, out_r, MAX_REC_SIZE) > 0) {
out_r = strtok(out_r, "\n");
return;
}
} while (1);
}
void write_fifo(int fd, char *out_w) {
write(fd, out_w, sizeof(out_w));
}
int main()
{
int pipe_fd[3], i;
char *pipe_nm[] = {"./in_pipe_1", "./in_pipe_2", "./out_pipe_1"};
int read_mode = O_RDONLY;
int write_mode = O_WRONLY;
char out[MAX_REC_SIZE];
char out_store[MAX_REC_SIZE];
for(i=0; i<3; i++) {
pipe_fd[i] = open_fifo(pipe_nm[i], i == 2 ? write_mode : read_mode);
}
read_fifo(pipe_fd[0], out);
strcpy(out_store, out);
read_fifo(pipe_fd[1], out);
strcat(out_store, out);
strcat(out_store, "\n");
write_fifo(pipe_fd[2], out_store);
return 0;
}
A suspicious part of your code is:
write(fd, out_w, sizeof(out_w))
Here, out_w is not an array, and the sizeof operator would yield the size of a char * pointer, not the length of the block.
You should pass the length of out_store to your write_fifo function.
Also, I'm not really sure what your intent is when using the strtok function.
#include <stdio.h>
#include <string.h>
#include <pcre.h>
#define OVECCOUNT 30
#define SRCBUFFER 1024*1024
int main(int argc, char **argv){
pcre *re;
const char *error;
int erroffset;
int ovector[OVECCOUNT];
int rc, i;
if (argc != 2){
fprintf(stderr, "Usage : %s PATTERN\n", argv[0]);
return 1;
}
char *src=malloc(SRCBUFFER);
int srclen = fread(src, sizeof(char), SRCBUFFER, stdin);
re = pcre_compile(argv[1], 0, &error, &erroffset, NULL);
if (re == NULL){
fprintf(stderr, "PCRE compilation failed at offset %d: %s\n", erroffset, error);
return 1;
}
rc = pcre_exec(re, NULL, src, srclen, 0, 0, ovector, OVECCOUNT);
if (rc < 0){
if (rc == PCRE_ERROR_NOMATCH) fprintf(stderr, "Sorry, no match...\n");
else fprintf(stderr, "Matching error %d\n", rc);
return 1;
}
for (i = 0; i < rc; i++){
char *substring_start = src + ovector[2 * i];
int substring_length = ovector[2 * i + 1] - ovector[2 * i];
fprintf(stdout, "%2d: %.*s\n", i, substring_length, substring_start);
}
return 0;
}
run it
echo "apple banana africa" | ./program '\ba\w+\b'
and it print
0: apple
I've tried to use the PCRE_MULTILINE option,but no use.How to make it print all matchs?
It sounds like what you're looking for is the equivalent of the Perl /g regex flag to repeat the match as many times as possible and return the results of all the matches. I don't believe PCRE has anything like that.
Instead, you will need to add a loop around pcre_exec. Each time you call it, it will return the byte offset of the start and end of the match. You want to then run pcre_exec again on the string starting at the end of the match. Repeat until pcre_exec doesn't match.
need some advice on this one as im struggling abit and cannot figure it out.
i have a file that gets updated on a PC to indicate a system ran and what time it ran. i am writing a very simple linux console app (will eventually be a nagios plugin). that reads this file and responds depending on what it found within the file.
i am a total newbie to programming on Linux and using C so please be patient and if you would explain any answers it would really be appreciated.
basically i want to convert a char array containing 5 characters into an integer, however the 5th char in the array is always a letter. so technically all i want to-do is convert the first 4 chars in the array to a integer... how?? ive tried multiple ways with no success, my problem is that presently i do not have a good grasp of the language so have no real ideas on what it can and cannot do.
here is the source to my program.
basically the buf array will be holding a string taken from the file that will look something like this
3455Y (the number will be random but always 4 chars long).
Sorry for the poor formatting of the code, but i cannot get this stupid window for love nor money to format it correctly....
include <fcntl.h>
include <unistd.h>
include <stdio.h>
include <stdlib.h>
include <time.h>
include <string.h>
define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
}
else
{
return STATE_OK;
}
time_t ltime; /* calendar time */
struct tm *Tm;
ltime=time(NULL); /* get current cal time */
Tm=localtime(<ime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d", test);
printf("%d", strtoi(buf));
}
You can use sscanf to do the job:
int num = 0;
sscanf(buf, "%4d", &num);
Then num should hold the number from the line in the file.
You can use atoi
atoi requires one char * argument and returns an int.
If the string is empty, or first character isn't a number or a minus sign, then atoi returns 0.If atoi encounters a non-number character, it returns the number formed up until that point
int num = atoi(buf);
if you want to convert the first four characters of a string to an integer do this:
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
uint8_t convertFirstFourChars(char * str, uint32_t *value){
char tmp[5] = {0};
strncpy((char *) tmp, str, 4);
*value = strtoul(tmp);
return errno;
}
then call / test this function like this
#include <stdint.h>
#include <stdio.h>
int main(int argc, char **argv){
char test1[5] = "1234A";
char test2[5] = "ABCDE";
uint32_t val = 0;
if(convertFirstFourChars((char *) test1, &val) == 0){
printf("conversion of %s succeeded, value = %ld\n", test1, val);
}
else{
printf("conversion of %s failed!\n", test1);
}
if(convertFirstFourChars((char *) test2, &val) == 0){
printf("conversion succeeded of %s, value = %ld\n", test2, val);
}
else{
printf("conversion of %s failed!\n", test2);
}
return 0;
}
FWIW, don't use atoi(...) because it converts any string to an integer regardless of its validity as a number. atoi("foo") === 0.
this is as much of your code as I was able to recover from the formatting:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
} else {
return STATE_OK;
}
time_t ltime; /* calendar time /
struct tm Tm;
ltime=time(NULL); / get current cal time */
Tm=localtime(<ime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d", test);
printf("%d", strtoi(buf));
}
this is the version that does what you specified:
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#define COPYMODE 0644
int main(int argc, char *argv[])
{
int i, nRead, fd;
int source;
int STATE_OK = 0;
int STATE_WARNING = 1;
int STATE_CRITICAL = 2;
int STATE_UNKNOWN = 3;
int system_paused = 0;
char buf[5];
int testnumber;
if((fd = open(argv[1], O_RDONLY)) == -1)
{
printf("failed open : %s", argv[1]);
return STATE_UNKNOWN;
}
else
{
nRead = read(fd, buf, 5);
}
close(source);
if (buf[4] == 'P')
{
printf("Software Paused");
return STATE_WARNING;
}/* else {
return STATE_OK;
buf[4] = 0;
} */
time_t ltime; /* calendar time */
struct tm *Tm;
ltime=time(NULL); /* get current cal time */
Tm=localtime(<ime);
int test;
test = Tm->tm_hour + Tm->tm_min;
printf("%d\n", test);
printf("%d\n", atoi(buf));
}
The biggest problem with your code was the if statement with the returns in each branch, insuring that nothing after the if statement was ever executed.