I know other people have done it in different languages but I cannot find a C code example at all, the most common was in Perl and it was really confusing because I don't know Perl
and I just want to load a binary file (from disk) into memory and then execute it
https://magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html
Here you go, an example writen in C (compiled on linux 5.4 and run as expected):
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
size_t min(size_t x, size_t y)
{
return x > y ? y : x;
}
/**
* #param len != 0
*/
void fdput(int fd, const char *str, size_t len)
{
size_t cnt = 0;
do {
ssize_t result = write(fd, str + cnt, min(len - cnt, 0x7ffff000));
if (result == -1) {
if (errno == EINTR)
continue;
err(1, "%s failed", "write");
}
cnt += result;
} while (cnt != len);
}
#define fdputc(fd, constant_str) fdput((fd), (constant_str), sizeof(constant_str) - 1)
int main(int argc, char* argv[])
{
int fd = memfd_create("script", 0);
if (fd == -1)
err(1, "%s failed", "memfd_create");
fdputc(fd, "#!/bin/bash\necho Hello, world!");
{
const char * const argv[] = {"script", NULL};
const char * const envp[] = {NULL};
fexecve(fd, (char * const *) argv, (char * const *) envp);
}
err(1, "%s failed", "fexecve");
}
I also tested with calling fork() just before fexecve, and it also works as expected.
Here's the code (mostly identical to the one provides above):
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
size_t min(size_t x, size_t y)
{
return x > y ? y : x;
}
/**
* #param len != 0
*/
void fdput(int fd, const char *str, size_t len)
{
size_t cnt = 0;
do {
ssize_t result = write(fd, str + cnt, min(len - cnt, 0x7ffff000));
if (result == -1) {
if (errno == EINTR)
continue;
err(1, "%s failed", "write");
}
cnt += result;
} while (cnt != len);
}
#define fdputc(fd, constant_str) fdput((fd), (constant_str), sizeof(constant_str) - 1)
int main(int argc, char* argv[])
{
int fd = memfd_create("script", 0);
if (fd == -1)
err(1, "%s failed", "memfd_create");
fdputc(fd, "#!/bin/bash\necho Hello, world!");
pid_t pid = fork();
if (pid == 0) {
const char * const argv[] = {"script", NULL};
const char * const envp[] = {NULL};
fexecve(fd, (char * const *) argv, (char * const *) envp);
err(1, "%s failed", "fexecve");
} else if (pid == -1)
err(1, "%s failed", "fork");
wait(NULL);
return 0;
}
Related
I'm trying to test an ncurses application in a pty. Which bytes should be sent to the pty master to trigger key codes for KEY_RESIZE, KEY_HOME, KEY_END, etc.?
There is some code posted below which I truly hope no-one ever wastes time looking at, but will include for completeness. This code behaves as follows:
$ perl -e "print pack('c', 8)" | ./wrappty ./show-key
KEY_BACKSPACE
That is, if I write 0x08 to the pty, the ncurses application treats it as a backspace. What byte sequences should be written to trigger the other key codes? I would hazard a guess that the particular byte sequence depends on the terminal, so I'm wondering if there is a standard for ptys, or if there is a reasonable method to determine the correct byte sequence.
wrappty.c:
#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <unistd.h>
#ifdef __linux__
# include <pty.h>
# include <utmp.h>
#else
# include <util.h>
#endif
static void
show_data(const char *t, ssize_t s)
{
for( ; s > 0; t++, s-- ) {
const char *fmt = isprint(*t) ? "%c" : "0x%02x";
fprintf(stderr, fmt, *(unsigned char *)t);
}
fflush(stderr);
}
static ssize_t
send_msg(int fd, int b)
{
char buf[1024];
if( b != EOF ) {
write(fd, &b, 1);
}
ssize_t s;
while( (s = read(fd, buf, sizeof buf)) == sizeof buf ) {
show_data(buf, s);
}
show_data(buf, s);
return s;
}
static void
wait_for(int fd, const char *expect, size_t siz)
{
int rc = 0;
char buf[1024];
char *a = buf;
assert(siz < sizeof buf);
char *end = buf + siz;
while( a < end ) {
ssize_t s = read(fd, a, end - a);
char *e = a + s;
rc += 1;
while( a < e && *a++ == *expect++ ) {
;
}
if( s < 1 || a < e ) {
fprintf(stderr, "Ivalid data\nReceived: ");
show_data(buf, e - buf);
fprintf(stderr, "\nExpected: ");
show_data(expect, siz);
fputc('\n', stderr);
exit(1);
}
}
}
void noop(int sig, siginfo_t *i, void *v) { (void)sig; (void)i; (void)v; }
int
main(int argc, char **argv)
{
int primary, secondary, c;
struct winsize ws = { .ws_row = 24, .ws_col = 80 };
(void) argc;
if( openpty(&primary, &secondary, NULL, NULL, &ws) ) {
err(EXIT_FAILURE, "openpty");
}
switch( fork() ) {
case -1:
err(1, "fork");
break;
case 0:
if( close(primary) ) {
err(EXIT_FAILURE, "close");
}
if( login_tty(secondary) ) {
err(EXIT_FAILURE, "login_tty");
}
execvp(argv[1], argv + 1);
err(EXIT_FAILURE, "execvp %s", argv[1]);
}
/* Parent */
if( close(secondary) ) {
err(EXIT_FAILURE, "close");
}
/* Initialization sequence from ncurses on macos */
char *expected = "\x1b(B\x1b)0\x1b[?1049h\x1b[1;24r\x1b[m\x0f\x1b[4l"
"\x1b[?1h\x1b=\x1b[H\x1b[J";
struct sigaction act;
memset(&act, 0, sizeof act);
act.sa_sigaction = noop;
if( sigaction( SIGALRM, &act, NULL ) ) {
perror("sigaction");
return EXIT_FAILURE;
}
struct timeval tp = {.tv_sec = 0, .tv_usec = 500000 };
struct itimerval t = { .it_interval = tp, .it_value = tp };
setitimer(ITIMER_REAL, &t, NULL);
wait_for(primary, expected, strlen(expected));
while( (c = getchar()) != EOF ) {
send_msg(primary, c);
}
send_msg(primary, EOF);
fputc('\n', stderr);
return 0;
}
show-key.c:
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 600
#define _XOPEN_SOURCE_EXTENDED
#define _DARWIN_C_SOURCE
#include <ctype.h>
#include <curses.h>
#include <err.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
int xopen(const char *path, int flags);
void
handle(int sig, siginfo_t *i, void *v)
{
(void)i;
(void)v;
char *n = NULL;
switch(sig) {
case SIGHUP: n = "SIGHUP\n"; break;
case SIGTERM: n = "SIGTERM\n"; break;
case SIGINT: n = "SIGINT\n"; break;
}
if(n)
write(2, n, strlen(n));
return;
}
int
main(int argc, char **argv)
{
int r;
wint_t w = 0;
if( argc > 1 ) {
int fd = xopen(argv[1], O_WRONLY);
dup2(fd, STDERR_FILENO);
}
unsetenv("COLUMNS");
unsetenv("LINES");
struct sigaction act;
memset(&act, 0, sizeof act);
act.sa_sigaction = handle;
if( sigaction( SIGTERM, &act, NULL ) ) { perror("sigaction"); exit(1); }
if( sigaction( SIGINT, &act, NULL ) ) { perror("sigaction"); exit(1); }
if( sigaction( SIGHUP, &act, NULL ) ) { perror("sigaction"); exit(1); }
if( initscr() == NULL ) {
err(1, "initscr");
}
noecho();
keypad(stdscr, true);
while( (r = get_wch(&w)) != ERR ) {
char *d = NULL;
if( r == KEY_CODE_YES ) switch(w) {
case KEY_RESIZE: d = "KEY_RESIZE"; break;
case KEY_HOME: d = "KEY_HOME"; break;
case KEY_END: d = "KEY_END"; break;
case KEY_PPAGE: d = "KEY_PPAGE"; break;
case KEY_NPAGE: d = "KEY_NPAGE"; break;
case KEY_BACKSPACE: d = "KEY_BACKSPACE"; break;
case KEY_DC: d = "KEY_DC"; break;
case KEY_IC: d = "KEY_IC"; break;
case KEY_BTAB: d = "KEY_BTAB"; break;
case KEY_ENTER: d = "KEY_ENTER"; break;
case KEY_UP: d = "KEY_UP"; break;
case KEY_DOWN: d = "KEY_DOWN"; break;
case KEY_RIGHT: d = "KEY_RIGHT"; break;
case KEY_LEFT: d = "KEY_LEFT"; break;
}
if( d != NULL ) {
/*printw("(%s)", d);*/
fprintf(stderr, "%s", d);
} else {
/*printw("%lc", w);*/
fprintf(stderr, "%lc", w);
}
/*doupdate();*/
fflush(stderr);
}
endwin();
fprintf(stderr, "ERR\n");
return 0;
}
int
xopen(const char *path, int flags)
{
int f = open(path, flags);
if( f == -1 ) {
perror(path);
exit(EXIT_FAILURE);
}
return f;
}
Use tigetstr for fetching strings that correspond to the keys. Most are easily related to the curses names (which are listed in the getch manpage):
foo = tigetstr("khome"); // KEY_HOME
It would be nice to have a table, but since the naming convention is intuitive, no one seems to feel the need...
This question already has answers here:
When using regex in C, \d does not work but [0-9] does
(4 answers)
Closed 3 years ago.
In the following code, I am trying to filter out using regex ONLY, the file called test.jpg, what am I doing wrong as the code below is not filtering this out?
I know there are simpler ways, but eventually I would like to change the regex to ^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)
and also my folder contains 100,000+ files, so I can only use the c getdents function which is super fast compared to any other way
I get the following output:
**************found*******
image_0179_20141212_060714.jpg
#define _GNU_SOURCE
#include <dirent.h> /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <string.h>
#include <regex.h>
#include <stdio.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
#define BUF_SIZE 1024*1024*5
int
main(int argc, char *argv[])
{
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
regex_t reg;
regmatch_t pmatch[40];
#define NAME "image_0179_20141212_060714.jpg"
const char *pattern = "^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)";
regcomp(®, pattern, REG_ICASE | REG_EXTENDED);
int retval = 0;
char buffer[1024] = "";
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
handle_error("open");
for ( ; ; )
{
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
handle_error("getdents");
if (nread == 0)
break;
for (bpos = 0; bpos < nread;)
{
d = (struct linux_dirent *) (buf + bpos);
d_type = *(buf + bpos + d->d_reclen - 1);
if( d->d_ino != 0 && d_type == DT_REG )
{
//printf("%s\n", (char *)d->d_name );
if (strstr(d->d_name, NAME) != NULL)
{
printf("**************found*******\n");
printf("%s\n", (char *)d->d_name );
};
retval = regexec(®, d->d_name, 2, pmatch, 0);
//printf("%d\n",retval);
if(retval==0)
{
printf("**************found regex*******\n");
printf("%s\n", (char *)d->d_name );
}
}
bpos += d->d_reclen;
}
}
regfree(®);
exit(EXIT_SUCCESS);
}
use the following regex instead
^image_[0-9]{3,6}_201412[0-9]{2}_[0-9]{6}\.jpg$
I'm actually implementing a very simple version of tail(1). In FreeBSD, I use kqueue to monitor a file for changes and then printing appended lines to the output. But this is not a portable way, as kqueue is only available in BSD family. Is there a general, efficient and platform-independent way to monitor files for changes in UNIX? I prefer not to use external libraries.
This is the code I've written:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>
void die(const char*);
#define MAXLINE 1024
int main(int argc, char *argv[])
{
int fdes;
int kq;
int nev;
int flags;
off_t curoff;
char line[MAXLINE + 1];
ssize_t nbytes;
struct kevent change, event;
if (2 != argc)
{
fprintf(stderr, "Usage: %s path\n", argv[0]);
exit(EXIT_FAILURE);
}
if (-1 == (fdes = open(argv[1], O_RDONLY)))
die("open()");
if (-1 == (curoff = lseek(fdes, 0, SEEK_END)))
die("lseek()");
int ch = 0;
int i = 0;
while (i < 10)
{
read(fdes, &ch, 1);
if (ch == '\n')
i++;
if (10 > i)
lseek(fdes, --curoff, SEEK_SET);
}
if (-1 == (flags = fcntl(fdes, F_GETFL)))
die("fcntl()");
flags |= O_NONBLOCK;
if (-1 == fcntl(fdes, F_SETFL, flags))
die("fcntl()1");
while ((nbytes = read(fdes, line, MAXLINE)) > 0)
if (write(STDOUT_FILENO, line, nbytes) != nbytes)
die("write()");
if (-1 == (kq = kqueue()))
die("kqueue()");
EV_SET(&change, fdes, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
NOTE_EXTEND | NOTE_WRITE | NOTE_DELETE, 0, NULL);
if (-1 == kevent(kq, &change, 1, NULL, 0, NULL))
die("kevent()");
for (;;)
{
if (-1 == (nev = kevent(kq, NULL, 0, &event, 1, NULL)))
die("kevent()");
if (nev > 0)
{
if (event.fflags & NOTE_WRITE || event.fflags & NOTE_EXTEND)
{
while ((nbytes = read(fdes, line, MAXLINE)) > 0)
if (write(STDOUT_FILENO, line, nbytes) != nbytes)
die("write()");
}
else if (NOTE_DELETE & event.fflags)
{
printf("The file has been deleted\n");
break;
}
}
}
return 0;
}
void die(const char *str)
{
perror(str);
exit(EXIT_FAILURE);
}
You can just keep doing the read() in a loop. If you read zero bytes,
check for an error. If there is no error, then you've hit EOF. At
EOF, stat() the filename, if it's gone, then the file was deleted. If
stat returns, compare the st_dev and st_ino fields of the stat to
the results from fstat (cache this when you open the file). If they're
different, the path was deleted and re-created. Sleep as long as you
care to after the delete check before trying another read.
I am trying to write a C Code to do the same Job as:
netstat -vatp
List all Remote/Local Addresses and Processes using them. But I dunno which files should I be reading?
I tried looking into /proc/net/tcp and /proc/net/udp, but they don't have the process name or process identifier like netstat displays it!
Thanks.
You could check the source code http://freecode.com/projects/net-tools. Just download, unpack the bz2 file and you'll find the netstat.c source code
Quick analyse:
/proc/net/tcp for example has an inode tab, in /proc there is a subfolder for each of these inodes, which contains the information you need.
Some more analysing:
I think it's even worse. netstat just loops through the /proc directory and checks the contents of the numeric sub-directories to find the actual process matching the inode. Not sure as I'm just analysing
http://linux.die.net/man/5/proc is very nice reading :)
For your answer, see How can i match each /proc/net/tcp entry to each opened socket?
You could call the netstat application from within your code. Have a look at execve to capture stdout and stderr.
EDIT:
Since code says more than words:
IEFTask.h
#ifndef IEFTASK_H
#define IEFTASK_H
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <signal.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* MARK: Structure */
struct IEFTask {
const char **arguments; /* last argument should be NULL */
int standardInput;
void *callbackArgument;
void (*callback)(int term, char *out, size_t outLen,
char *err, size_t errLen, void *arg);
};
typedef struct IEFTask IEFTask;
/* MARK: Running */
int
IEFTaskRun(IEFTask *theTask);
#endif /* IEFTASK_H */
IEFTask.c
#include "IEFTask.h"
/* MARK: DECLARATION: Data Conversion */
char *
IEFTaskCreateBufferFromPipe(int fd, size_t *bufLen);
/* MARK: Running */
int
IEFTaskRun(IEFTask *myTask) {
pid_t pid;
int exitStatus, status;
int outPipe[2], errPipe[2];
assert(myTask != NULL);
/* Create stdout and stderr pipes */
{
status = pipe(outPipe);
if(status != 0) {
return -1;
}
status = pipe(errPipe);
if(status != 0) {
close(errPipe[0]);
close(errPipe[1]);
return -1;
}
}
/* Fork the process and wait pid */
{
pid = fork();
if(pid < 0) { /* error */
return -1;
} else if(pid > 0) { /* parent */
waitpid(pid, &exitStatus, 0);
exitStatus = WEXITSTATUS(exitStatus);
} else { /* child */
/* close unneeded pipes */
close(outPipe[0]);
close(errPipe[0]);
/* redirect stdout, stdin, stderr */
if(myTask->standardInput >= 0) {
close(STDIN_FILENO);
dup2(myTask->standardInput, STDIN_FILENO);
close(myTask->standardInput);
}
close(STDOUT_FILENO);
dup2(outPipe[1], STDOUT_FILENO);
close(outPipe[1]);
close(STDERR_FILENO);
dup2(errPipe[1], STDERR_FILENO);
close(errPipe[1]);
execve(myTask->arguments[0],
(char *const *)myTask->arguments, NULL);
exit(127);
}
}
/* Parent continues */
{
char *output, *error;
size_t outLen, errLen;
/* 127 = execve failed */
if(exitStatus == 127) {
close(errPipe[0]);
close(errPipe[1]);
close(outPipe[0]);
close(outPipe[1]);
return -1;
}
/* Read in data */
close(errPipe[1]);
close(outPipe[1]);
output = IEFTaskCreateBufferFromPipe(outPipe[0], &outLen);
error = IEFTaskCreateBufferFromPipe(errPipe[0], &errLen);
close(errPipe[0]);
close(outPipe[0]);
/* Call callback */
(*myTask->callback)(exitStatus,
output, outLen,
error, errLen, myTask->callbackArgument);
if(output) free(output);
if(error) free(error);
}
return 0;
}
/* MARK: Data Conversion */
#define READ_BUF_SIZE (128)
char *
IEFTaskCreateBufferFromPipe(int fd, size_t *bufLen) {
ssize_t totalRead = 0, nowRead;
char readBuffer[READ_BUF_SIZE], *myBuffer = NULL;
char *ptr;
while(1) {
nowRead = read(fd, readBuffer, READ_BUF_SIZE);
if(nowRead == -1) {
free(myBuffer);
return NULL;
} else if(nowRead == 0) {
break;
} else {
ptr = realloc(myBuffer, totalRead + nowRead);
if(ptr == NULL) {
free(myBuffer);
return NULL;
}
myBuffer = ptr;
memcpy(&(myBuffer[totalRead]), readBuffer, nowRead);
totalRead += nowRead;
}
}
if(bufLen) *bufLen = (size_t)totalRead;
return myBuffer;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "IEFTask.h"
void taskCallback(int term,
char *out, size_t outlen,
char *err, size_t errlen)
{
char *ptr;
printf("Task terminated: %d\n", term);
ptr = malloc(outlen + 1);
memcpy(ptr, out, outlen);
ptr[outlen] = '\0';
printf("***STDOUT:\n%s\n***END\n", ptr);
free(ptr);
ptr = malloc(errlen + 1);
memcpy(ptr, err, errlen);
ptr[errlen] = '\0';
printf("***STDERR:\n%s\n***END\n", ptr);
free(ptr);
}
int main() {
const char *arguments[] = {
"/bin/echo",
"Hello",
"World",
NULL
};
IEFTask myTask;
myTask.arguments = arguments;
myTask.standardInput = -1;
myTask.callback = &taskCallback;
int status;
status = IEFTaskRun(&myTask);
if(status != 0) {
printf("Failed: %s\n", strerror(errno));
}
return 0;
}
Why does the following code print ‘read(): Resource temporarily unavailable’ 80% of the time? That is the EAGAIN code, which is the same as WOULD BLOCK which means there is no data waiting to be read, but select is returning 1 saying there is data (tested in Linux):
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/errno.h>
int main(int argc, char** argv)
{
int fd = open("/dev/lp0", O_RDWR | O_NONBLOCK);
int ret = 0;
int status = 0;
char buffer[1024];
char teststr[] = "This is a test\n";
char XMIT_STATUS_OFFLINE[] = {0x10,0x04,0x02};
char XMIT_STATUS_ERROR[] = {0x10,0x04,0x03};
char XMIT_STATUS_ROLL[] = {0x10,0x04,0x04};
char XMIT_STATUS_SLIP[] = {0x10,0x04,0x05};
fd_set rfds;
FD_ZERO( &rfds );
FD_SET( fd, &rfds );
struct timeval sleep;
sleep.tv_sec = 5;
sleep.tv_usec = 0;
/* Offline status */
ret = write(fd, XMIT_STATUS_OFFLINE, sizeof(XMIT_STATUS_OFFLINE));
//printf("write() returned %d\n", ret);
do {
ret = select( fd + 1, &rfds, NULL, NULL, &sleep );
} while (ret < 0 && (errno == EINTR));
ret = read(fd, buffer, 1024);
if(ret == -1) {
perror("read(): ");
} else {
status = buffer[0];
if((status & 0x04) != 0)
{
printf("The cover is open.\n");
} else {
printf("OFFLINE is good.\n");
}
}
close(fd);
return 0;
}
Your select call will return 0 after the 5 second timeout elapses if no data is available. Your code will ignore this and try to read from the device anyways. Check for ret == 0 and that will fix your problem.