Added new tests examples with vstr

This commit is contained in:
Randy Jordan 2024-11-23 09:46:38 -06:00
parent 28799e4770
commit 8154311739
Signed by: Randy-Jordan
GPG Key ID: D57FA29E3B54663E
5 changed files with 386 additions and 6 deletions

35
include/vstr.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef VSTR_INCLUDED
#define VSTR_INCLUDED
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
struct Vstr {
size_t len; // String len
char *buf; // String data
};
typedef struct Vstr Vstr;
#define Vstr_Fmt "%.*s"
#define Vstr_Arg(vstr) (int) (vstr).len, (vstr).buf
#define VSTR(cstr) vstr_n(cstr, sizeof(cstr) - 1)
#define VSTR_NULL vstr_n(NULL, 0)
size_t pack_vstr(unsigned char *buffer, Vstr *vstr);
void unpack_vstr(unsigned char *buffer, Vstr *vstr);
size_t pack_vstr_array(unsigned char *buffer, Vstr *array, size_t count);
Vstr *unpack_vstr_array(unsigned char *buffer, size_t *count);
Vstr vstr_s(const char *s);
Vstr vstr_n(const char *s, size_t n);
bool vstr_cmp(const Vstr v1, const Vstr v2);
const char *vstr_str(const Vstr haystack, const Vstr needle);
Vstr vstr_after_delim(const Vstr v, const char *delims);
Vstr vstr_before_delim(const Vstr v, const char *delims);
Vstr vstr_substr(Vstr v, size_t start, size_t stop);
Vstr vstr_trim(Vstr v);
Vstr vstr_trim_left(Vstr v);
Vstr vstr_trim_right(Vstr v);
#endif

215
src/vstr.c Normal file
View File

@ -0,0 +1,215 @@
#include "../include/vstr.h"
#include <stdlib.h>
size_t pack_vstr(unsigned char *buffer, Vstr *vstr) {
size_t offset = 0;
// Pack the length of the string first (size_t)
buffer[offset++] = (vstr->len >> 56) & 0xFF;
buffer[offset++] = (vstr->len >> 48) & 0xFF;
buffer[offset++] = (vstr->len >> 40) & 0xFF;
buffer[offset++] = (vstr->len >> 32) & 0xFF;
buffer[offset++] = (vstr->len >> 24) & 0xFF;
buffer[offset++] = (vstr->len >> 16) & 0xFF;
buffer[offset++] = (vstr->len >> 8) & 0xFF;
buffer[offset++] = vstr->len & 0xFF;
// Pack the string data
memcpy(&buffer[offset], vstr->buf, vstr->len);
offset += vstr->len;
return offset; // Return the total packed size
}
void unpack_vstr(unsigned char *buffer, Vstr *vstr) {
unsigned int offset = 0;
// Unpack the length of the string (size_t)
vstr->len = 0;
for (int i = 0; i < 8; i++) {
vstr->len = (vstr->len << 8) | buffer[offset++];
}
// Allocate memory for the string and copy it from the buffer
vstr->buf = (char *)malloc(vstr->len + 1); // +1 for null terminator
if (vstr->buf != NULL) {
memcpy(vstr->buf, &buffer[offset], vstr->len);
vstr->buf[vstr->len] = '\0'; // Null-terminate the string
} else {
vstr->len = 0; // If memory allocation fails, set len to 0
}
}
size_t pack_vstr_array(unsigned char *buffer, Vstr *array, size_t count) {
size_t offset = 0;
// Pack the number of elements in the array
buffer[offset++] = (count >> 56) & 0xFF;
buffer[offset++] = (count >> 48) & 0xFF;
buffer[offset++] = (count >> 40) & 0xFF;
buffer[offset++] = (count >> 32) & 0xFF;
buffer[offset++] = (count >> 24) & 0xFF;
buffer[offset++] = (count >> 16) & 0xFF;
buffer[offset++] = (count >> 8) & 0xFF;
buffer[offset++] = count & 0xFF;
// Pack each Vstr in the array
for (size_t i = 0; i < count; i++) {
// Pack the length of the string
buffer[offset++] = (array[i].len >> 56) & 0xFF;
buffer[offset++] = (array[i].len >> 48) & 0xFF;
buffer[offset++] = (array[i].len >> 40) & 0xFF;
buffer[offset++] = (array[i].len >> 32) & 0xFF;
buffer[offset++] = (array[i].len >> 24) & 0xFF;
buffer[offset++] = (array[i].len >> 16) & 0xFF;
buffer[offset++] = (array[i].len >> 8) & 0xFF;
buffer[offset++] = array[i].len & 0xFF;
// Pack the string data
memcpy(&buffer[offset], array[i].buf, array[i].len);
offset += array[i].len;
}
return offset; // Return the total packed size
}
Vstr *unpack_vstr_array(unsigned char *buffer, size_t *count) {
size_t offset = 0;
// Unpack the number of elements in the array
*count = 0;
for (int i = 0; i < 8; i++) {
*count = (*count << 8) | buffer[offset++];
}
// Allocate memory for the Vstr array
Vstr *array = malloc(*count * sizeof(Vstr));
if (!array) return NULL; // Memory allocation failure
// Unpack each Vstr in the array
for (size_t i = 0; i < *count; i++) {
// Unpack the length of the string
array[i].len = 0;
for (int j = 0; j < 8; j++) {
array[i].len = (array[i].len << 8) | buffer[offset++];
}
// Allocate memory for the string
array[i].buf = malloc(array[i].len + 1); // +1 for null terminator
if (!array[i].buf) {
// Free previously allocated memory in case of failure
for (size_t k = 0; k < i; k++) {
free(array[k].buf);
}
free(array);
return NULL;
}
// Copy the string data
memcpy(array[i].buf, &buffer[offset], array[i].len);
array[i].buf[array[i].len] = '\0'; // Null-terminate the string
offset += array[i].len;
}
return array;
}
Vstr vstr_s(const char *s){
Vstr v = {s == NULL ? 0 : strlen(s), (char *)s};
return v;
}
Vstr vstr_n(const char *s, size_t n){
Vstr v = {n,(char *)s};
return v;
}
bool vstr_cmp(const Vstr v1, const Vstr v2){
size_t i = 0;
while (i < v1.len && i < v2.len) {
int c1 = v1.buf[i];
int c2 = v2.buf[i];
if (c1 < c2) return false;
if (c1 > c2) return true;
i++;
}
if (i < v1.len) return true;
if (i < v2.len) return false;
return false;
}
const char *vstr_str(const Vstr haystack, const Vstr needle){
size_t i;
if (needle.len > haystack.len) return NULL;
if (needle.len == 0) return haystack.buf;
for (i = 0; i <= haystack.len - needle.len; i++) {
if (memcmp(haystack.buf + i, needle.buf, needle.len) == 0) {
return haystack.buf + i;
}
}
return NULL;
}
Vstr vstr_after_delim(const Vstr v, const char *delims) {
// Handle NULL pointer or empty string view
if (v.buf == NULL || delims == NULL) {
return vstr_n(NULL, 0);
}
size_t i = 0;
while (i < v.len) {
// Check if the current character is a delimiter
for (size_t j = 0; delims[j] != '\0'; j++) {
if (v.buf[i] == delims[j]) {
Vstr result = vstr_n(v.buf+i+1, v.len-i-1);
return result;
}
}
i++;
}
// Return the whole string if no delimiter was found
Vstr result = vstr_n(v.buf, i);
return result;
}
Vstr vstr_before_delim(const Vstr v, const char *delims) {
// Handle NULL pointer or empty string view
if (v.buf == NULL || delims == NULL) {
return vstr_n(NULL, 0);
}
size_t i = 0;
while (i < v.len) {
// Check if the current character is a delimiter
for (size_t j = 0; delims[j] != '\0'; j++) {
if (v.buf[i] == delims[j]) {
Vstr result = vstr_n(v.buf, i);
return result;
}
}
i++;
}
// Return the whole string if no delimiter was found
Vstr result = vstr_n(v.buf, i);
return result;
}
Vstr vstr_substr(Vstr v, size_t start, size_t stop) {
if (start >= v.len || stop > v.len || start >= stop) {
// Return an empty Vstr if indices are out of bounds or invalid
return vstr_n(NULL, 0);
}
size_t sub_len = stop - start;
return vstr_n(v.buf + start, sub_len);
}
static bool is_space(int c) {
return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f';
}
Vstr vstr_trim(Vstr v){
while (v.len > 0 && is_space((int) *v.buf)) v.buf++, v.len--;
while (v.len > 0 && is_space((int) *(v.buf + v.len - 1))) v.len--;
return v;
}
Vstr vstr_trim_left(Vstr v){
while (v.len > 0 && is_space((int) *v.buf)) v.buf++, v.len--;
return v;
}
Vstr vstr_trim_right(Vstr v){
while (v.len > 0 && is_space((int) *(v.buf + v.len - 1))) v.len--;
return v;
}

View File

@ -1,8 +1,15 @@
#include "../include/exectd.h"
int main() {
char *argv[] = {"/bin/ping", "-c","3","myrepos.dev", NULL}; // Example arguments
char *envp[] = {NULL}; // Example environment variables
int status = execute_job("/bin/ping", argv, envp);
// Arguments for the ls command
char *argv[] = {"ls", "-l", "-a", NULL};
// Custom environment variables
char *envp[] = {
"MY_ENV_VAR=example",
"PATH=/usr/bin:/bin", // Ensure PATH is set for executable lookup
NULL
};
int status = execute_job("/bin/ls", argv, envp);
if (status != 0) {
// Handle error
printf("my_execve returned error code: %d\n", status);

View File

@ -1,10 +1,19 @@
#include "../include/exectd.h"
int main() {
char *argv[] = {"/bin/ping", "-c","3","myrepos.dev", NULL}; // Example arguments
char *envp[] = {NULL}; // Example environment variables
// Arguments for the ls command
char *argv[] = {"ls", "-l", "-a", NULL};
// Custom environment variables
char *envp[] = {
"MY_ENV_VAR=example",
"PATH=/usr/bin:/bin", // Ensure PATH is set for executable lookup
NULL
};
int fd = ext_open("tests/bin/stdout_dup", O_WRONLY | O_CREAT);
int fd2 = ext_open("tests/bin/stderr_dup", O_WRONLY | O_CREAT);
int status = shell_job("/bin/ping", argv, envp, fd, fd2);
int status = shell_job("/bin/ls", argv, envp, fd, fd2);
if (status != 0) {
// Handle error
printf("Shell job returned error code: %d\n", status);

114
tests/04_packed.c Normal file
View File

@ -0,0 +1,114 @@
#include "../include/exectd.h"
#include "../include/vstr.h"
#include <stdlib.h>
size_t pack_execvpe_args(unsigned char *buffer, const char *file, char *const argv[], char *const envp[]) {
unsigned char *start = buffer;
// Pack the `file` string
Vstr file_vstr = vstr_s(file);
buffer += pack_vstr(buffer, &file_vstr);
// Pack `argv`
size_t argv_count = 0;
while (argv && argv[argv_count]) argv_count++;
memcpy(buffer, &argv_count, sizeof(size_t));
buffer += sizeof(size_t);
for (size_t i = 0; i < argv_count; i++) {
Vstr arg_vstr = vstr_s(argv[i]);
buffer += pack_vstr(buffer, &arg_vstr);
}
// Pack `envp`
size_t envp_count = 0;
while (envp && envp[envp_count]) envp_count++;
memcpy(buffer, &envp_count, sizeof(size_t));
buffer += sizeof(size_t);
for (size_t i = 0; i < envp_count; i++) {
Vstr env_vstr = vstr_s(envp[i]);
buffer += pack_vstr(buffer, &env_vstr);
}
return buffer - start; // Total packed size
}
void unpack_execvpe_args(unsigned char *buffer, char **file, char ***argv, char ***envp) {
// Unpack `file`
Vstr file_vstr;
unpack_vstr(buffer, &file_vstr);
buffer += sizeof(size_t) + file_vstr.len;
*file = strndup(file_vstr.buf, file_vstr.len);
free(file_vstr.buf);
// Unpack `argv`
size_t argv_count;
memcpy(&argv_count, buffer, sizeof(size_t));
buffer += sizeof(size_t);
*argv = malloc((argv_count + 1) * sizeof(char *));
for (size_t i = 0; i < argv_count; i++) {
Vstr arg_vstr;
unpack_vstr(buffer, &arg_vstr);
buffer += sizeof(size_t) + arg_vstr.len;
(*argv)[i] = strndup(arg_vstr.buf, arg_vstr.len);
free(arg_vstr.buf);
}
(*argv)[argv_count] = NULL;
// Unpack `envp`
size_t envp_count;
memcpy(&envp_count, buffer, sizeof(size_t));
buffer += sizeof(size_t);
*envp = malloc((envp_count + 1) * sizeof(char *));
for (size_t i = 0; i < envp_count; i++) {
Vstr env_vstr;
unpack_vstr(buffer, &env_vstr);
buffer += sizeof(size_t) + env_vstr.len;
(*envp)[i] = strndup(env_vstr.buf, env_vstr.len);
free(env_vstr.buf);
}
(*envp)[envp_count] = NULL;
}
int main(void) {
// Original arguments
const char *file = "/bin/ls";
// Arguments for the ls command
char *argv[] = {"ls", "-l", "-a", NULL};
// Custom environment variables
char *envp[] = {
"MY_ENV_VAR=example",
"PATH=/usr/bin:/bin", // Ensure PATH is set for executable lookup
NULL
};
// Buffer for packing
unsigned char buffer[1024]; // Adjust size as needed
size_t packed_size;
// Pack the arguments
packed_size = pack_execvpe_args(buffer, file, argv, envp);
(void)packed_size;
// Unpack the arguments
char *unpacked_file;
char **unpacked_argv;
char **unpacked_envp;
unpack_execvpe_args(buffer, &unpacked_file, &unpacked_argv, &unpacked_envp);
// Call execute_job with unpacked arguments
int status = execute_job(unpacked_file, unpacked_argv, unpacked_envp);
// Free unpacked arguments
free(unpacked_file);
for (char **arg = unpacked_argv; *arg; ++arg) free(*arg);
free(unpacked_argv);
for (char **env = unpacked_envp; *env; ++env) free(*env);
free(unpacked_envp);
// Check execution status
if (status != 0) {
printf("execute_job returned error code: %d\n", status);
}
printf("Job finished with %d \n",status);
// Code here will run after the child process has finished
return 0;
}