perl match function for C program - perl

Trying to use perl API functions in C program. Couldn't find the function to do regular expression match. Wish there is a function like regexmatch in the following program.
#include <EXTERN.h> /* from the Perl distribution */
#include <perl.h> /* from the Perl distribution */
#include <sys/time.h>
typedef unsigned long ulong;
static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
int main(int argc, char **argv, char **env) {
int numOfArgs = 0;
PERL_SYS_INIT3(&numOfArgs, NULL, NULL);
my_perl = perl_alloc();
perl_construct(my_perl);
SV* str = newSVpv(argv[1], strlen(argv[1]));
if (regexmatch(str, "/hi (\S+)/")) {
printf("found a match\n");
}
return 0;
}
I know it's possible to use pcre library, just wonder if it's possible to get it from perl library here (libperl.so.5.14.2 on ubuntu 12.04)
Thanks!
UPDATE 1:
Did some google search and got the following simple program compiling. But when I ran the program as ./a.out ping pin, it gave "Segmentation fault" in the "pregcomp" function. Not sure why.
#include <EXTERN.h> /* from the Perl distribution */
#include <perl.h> /* from the Perl distribution */
#include <sys/time.h>
#include <embed.h>
typedef unsigned long ulong;
static PerlInterpreter *my_perl; /*** The Perl interpreter ***/
struct REGEXP * const engine;
int main(int argc, char **argv, char **env) {
int numOfArgs = 0;
PERL_SYS_INIT3(&numOfArgs, NULL, NULL);
my_perl = perl_alloc();
perl_construct(my_perl);
SV* reStr = newSVpv(argv[2], strlen(argv[2]));
printf("compiling regexp\n");
REGEXP * const compiled_regex = pregcomp(reStr, 0);
printf("execing regexp\n");
int len = strlen(argv[1]);
pregexec(compiled_regex, argv[1], argv[1] + len, argv[1], 5, NULL, 0);
return 0;
}

Don't mess with Perl's private internals. Call a Perl sub that uses the match operator.
Say you previously compiled the following in your interpreter (using eval_pv),
sub regex_match { $_[0] =~ $_[1] }
Then you can call
static bool regex_match_sv(SV* str, SV* re) {
dSP;
bool matched;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(str);
XPUSHs(re);
PUTBACK;
call_pv("regex_match", G_SCALAR);
SPAGAIN;
matched = SvTRUE(POPs);
PUTBACK;
FREETMPS;
LEAVE;
return matched;
}

Related

why setuid fails after capset is used?

trying to figure out the linux capabilities interface, i came across with an unexpected issue (for me at least). When seting the capabilities of a process with the capset syscall the kernel rejects a change of userid with the setuid syscall. Does anybody know why setuid fails?
This is code i wrote to test this behavior:
#undef _POSIX_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/capability.h>
#include <sys/capability.h>
#include <string.h>
int main(int argc, char** argv){
struct __user_cap_header_struct cap_header;
struct __user_cap_data_struct cap_data;
int cap_res;
FILE *file;
int sockfd;
cap_header.pid = getpid();
cap_header.version = _LINUX_CAPABILITY_VERSION_1;
__u32 cap_mask = 0;
cap_mask |= (1 << CAP_DAC_OVERRIDE);
cap_mask |= (1 << CAP_SETUID);
printf("You selected mask: %x\n", cap_mask);
cap_data.effective = cap_mask;
cap_data.permitted = cap_mask;
cap_data.inheritable = cap_mask;
cap_res = capset(&cap_header, &cap_data);
if(cap_res < 0){
printf("Trying to apply mask: FAIL\n", cap_mask);
} else {
printf("Capability set correctly\n");
}
int uid = atol(argv[1]);
int setuid_res = setuid(uid);
if (setuid_res == -1){
printf("7w7\n");
} else {
printf("UID set correctly\n");
}
}
compiled with:
$ gcc -g test1.c -o test1
Output is (for user id: 1000)
$ # ./test1 1000
You selected mask: 2
Capability set correctly
7w7
I think you might be missing a couple of steps in your question:
How do you give the binary some privilege?
It looks like you are trying to use cap_dac_override to achieve what cap_setuid is intended for.
Rewriting the program as follows:
#undef _POSIX_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <linux/capability.h>
#include <sys/capability.h>
#include <string.h>
int main(int argc, char** argv){
struct __user_cap_header_struct cap_header;
struct __user_cap_data_struct cap_data;
int cap_res;
// need to start from known data. C does not guarantee these are
// zero filled by default. You could declare them static to get
// that.
memset(&cap_header, 0, sizeof(cap_header));
memset(&cap_data, 0, sizeof(cap_data));
cap_header.pid = getpid();
cap_header.version = _LINUX_CAPABILITY_VERSION_1;
__u32 cap_mask = 0;
cap_mask |= (1 << CAP_SETUID);
printf("You selected mask: %x\n", cap_mask);
cap_data.effective = cap_mask;
cap_data.permitted = cap_mask;
// not needed: cap_data.inheritable = cap_mask;
cap_res = capset(&cap_header, &cap_data);
if(cap_res < 0){
printf("Trying to apply mask: FAIL\n", cap_mask);
exit(1);
} else {
printf("Capability set correctly\n");
}
if (argc != 2) {
printf("usage: %s <uid>\n", argv[0]);
exit(1);
}
int uid = atol(argv[1]);
int setuid_res = setuid(uid);
if (setuid_res == -1){
printf("7w7\n");
} else {
printf("UID set correctly to %d\n", uid);
}
}
You can run the program like this:
$ sudo ./test1 1000
You selected mask: 80
Capability set correctly
UID set correctly to 1000
Or, using a file capability:
$ sudo setcap cap_setuid=p ./test1
$ ./test1 1000
You selected mask: 80
Capability set correctly
UID set correctly to 1000
This will work if you want to use the first 32 capabilities. However, there are ~40 of them under Linux at present, so I'd suggest you look into using the libcap API instead which figures out all of the kernel ABI details for you.

STM32 GSM AT command response parser

I am sending AT command to get IMEI no.
char CGSN[] = "AT+CGSN\r\n";
// in while loop
HAL_UART_Transmit(&huart2,(uint8_t *)CGSN, sizeof(CGSN),100);
HAL_Delay(1000);
HAL_UART_Receive_IT(&huart2,(uint8_t *)&ch,1);
// Callback
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2){
if(buf[i]!=13){
buf[i]=ch;
i++;
}
}
HAL_UART_Receive_IT(&huart2,(uint8_t *)&ch,1);
buf[i]=0;
}
the response stored in buffer is - \r\n9876543212345\r\n\r\nOK\r\n
What is best way to receive response and filter out n"9876543212345" & "OK" and store separately in a array to further process
Thanks
You can use sscanf for this purpose. Below is the quick implementation of the scenario in C.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void) {
unsigned long a;
char array[10];
char string[] = "\r\n9876543212345\r\n\r\nOK\r\n";
sscanf(string , "\r\n%ld\r\n\r\n%s\r\n", &a, array);
printf("%ld %s\n", a, array);
return 0;
}
Problem is simple! Your buf[] dont include '\r' (in decimal 13).
Correct value buf[] is "AT+CGSN\n9876543212345\n\nOK\n\0".

Behavior of select() on stdin when used on a pipe

I am trying to understand an observation on behavior of select() when used on stdin, when it is receiving data from a pipe.
Basically I had a simple C program using the following code:
hello.c:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <termios.h>
int main(int argc, char *argv[])
{
int flags, opt;
int nsecs, tfnd;
fd_set rfds;
struct timeval tv;
int retval;
int stdin_fileno_p1 = STDIN_FILENO+1;
char c;
int n;
/* Turn off canonical processing on stdin*/
static struct termios oldt, newt;
tcgetattr( STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON);
tcsetattr( STDIN_FILENO, TCSANOW, &newt);
while (1)
{
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
retval = select(stdin_fileno_p1, &rfds, NULL, NULL, &tv);
if ( retval && (retval!=-1) )
{
n = read(STDIN_FILENO, &c, 1);
write(STDOUT_FILENO, &c, 1);
}
else printf("No Data\n");
usleep(100000);
}
tcsetattr( STDIN_FILENO, TCSANOW, &oldt);
}
If I ran the program as follows I could see characters echoing when I type keys on while the program is running. When keys are not pressed, it displays "No Data" as expected.
./hello
However, if use the program as follows, the program never gets to a state where is displays "No Data". Instead last character "c" is repeatedly displayed.
echo -n abc | ./hello
I'm a bit puzzled by this observation, and would be grateful if you could help me to understand the observed behavior.
The problem is that your program does not detect an end-of-file condition when it reads from the STDIN_FILENO descriptor. After echo has written the c character it will close its end of the pipe, which will cause the select in your program to return immediately and your read to return 0 as an indication that no more data will ever be available from that descriptor. Your program doesn't detect that condition. Instead it just calls write with whatever character was left in the buffer by the last successful read and then repeats the loop.
To fix, do if (n==0) break; after the read.

implement multiple pipes in c

I'm trying to implement multiple pipes in c++. Namely, I want to write a program to simulate the execution of, for example, ls -l | head -n 10 | wc -l.
The code works all fine. But after all the commands are executed correctly, I need to hit enter to return to the command line. I guess I have to "wait()" somewhere
Here is the code I'm having now.
using namespace std;
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main(){
int pid;
int fd[4];
pipe(fd + 0); // pipe between the 1st and 2nd command
pipe(fd + 2); // pipe between the 2nd and 3rd command
for( int i = 0; i < 3; i++){ // 3 commands
pid = fork();
if(pid == 0){// child process
if( i == 0 ){// first command
char *arg[10];
arg[0] = "ls";
arg[1] = NULL;
close(fd[0]);
dup2(fd[1], 1);
execvp(arg[0], arg);
}
else if( i == 1){// second command
char *arg[10];
arg[0] = "head";
arg[1] = "-n1";
arg[2] = NULL;
dup2(fd[0], 0);
dup2(fd[3], 1);
execvp(arg[0], arg);
}
else if( i== 2){// third command
char *arg[10];
arg[0] = "wc";
arg[1] = "-l";
arg[2] = NULL;
close(fd[3]);
dup2(fd[2], 0);
execvp(arg[0], arg);
}
}
else{// parent
}
}
}
I think I have gone thru all posts similar to mine, but still can't figure this out.
Can anyone help?

Drawing currency symbol

How to draw a currency symbol in a custom label using CGContextShowTextAtPoint method in draw rect.
Here the symbol is in string format.
Any help!!
Thanks
You have to resort to C style strings, since this is what CGContextShowTextAtPoint() requires. In order to correctly handle the locale (the currency symbol changes with the locale) you must use setlocale(), then you format your string using strfmon() and finally you pass the string created with strfmon() to CGContextShowTextAtPoint().
Documentation is available as follows from the terminal:
man 3 setlocale
man 3 strfmon
EDIT/UPDATE: For your information, strfmon() internally uses struct lconv. The structure can be retrieved with the function localeconv(). See man 3 localeconv for a detailed description of the fields available in the structure.
for instance, try the following simple C program setting different locales
#include <stdio.h>
#include <locale.h>
#include <monetary.h>
int main(void)
{
char buf[BUFSIZ];
double val = 1234.567;
/* use your current locale */
setlocale(LC_ALL, "");
/* uncomment the next line and try this to use italian locale */
/* setlocale(LC_ALL, "it_IT"); */
strfmon(buf, sizeof buf, "You owe me %n (%i)\n", val, val);
fputs(buf, stdout);
return 0;
}
The following uses localeconv():
#include <stdio.h>
#include <limits.h>
#include <locale.h>
int main(void)
{
struct lconv l;
int i;
setlocale(LC_ALL, "");
l = *localeconv();
printf("decimal_point = [%s]\n", l.decimal_point);
printf("thousands_sep = [%s]\n", l.thousands_sep);
for (i = 0; l.grouping[i] != 0 && l.grouping[i] != CHAR_MAX; i++)
printf("grouping[%d] = [%d]\n", i, l.grouping[i]);
printf("int_curr_symbol = [%s]\n", l.int_curr_symbol);
printf("currency_symbol = [%s]\n", l.currency_symbol);
printf("mon_decimal_point = [%s]\n", l.mon_decimal_point);
printf("mon_thousands_sep = [%s]\n", l.mon_thousands_sep);
printf("positive_sign = [%s]\n", l.positive_sign);
printf("negative_sign = [%s]\n", l.negative_sign);
}
I don't really get what you're asking,
checking the documentation, the method would look something like that:
CGContextRef ctx = UIGraphicsGetCurrentContext();
const char *string = "$";
CGContextShowTextAtPoint (ctx, 160, 240, string, 1);
Haven't tested it, but this should draw $ in the center of the screen.
BTW, why not use images?
~ Natanavra.