I'm building a simple shell for a class. There are two programs in my shell directory, called "alomundo" and "echo". "./alomundo" prints "Alo mundo!" to console, and ./echo executes the ubuntu echo with given args.
The thing is my program only works if I declare the char aux[15]. Notice I don't use it aux for nothing. Can anyone understand whats wrong?
An example input would be
./shell echo a b, alomundo, echo abc
The correct output is
a b
Alo mundo!
abc
The output when char aux[15] is not declared is just:
Alo mundo!
abc
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char aux[15]; // <---- GRRRR
int child; // will hold the childs PID after fork()
int i = 0; // counter to loop through this mains *argv[]
int t = 0; // auxiliar counter to loops
int arg_len; // will hold the length of each argument while the argument is being processed
int args = 0; // current number of arguments in the argv1 vector
int send = 0; // boolean to check if the command should be executed in the current loop or not
char *command; // string to hold the main command name
char *argv1[15]; // vector to hold the arguments passed to execve
for(i=1; i<argc; i++) {
arg_len = strlen(argv[i]);
argv1[args] = (char *) malloc(sizeof(char) * 25);
for(t=0; t<25; t++) {
argv1[args][t] = '\0';
}
if (argv[i][arg_len-1] == ',') {
argv[i][arg_len-1] = '\0';
send = 1;
}
else if (i == (argc-1)) {
send = 1;
}
if (args == 0) {
command = (char *) malloc(sizeof(char) * 255);
strcpy(command, "./");
strcpy(argv1[args], "./");
strcat(command, argv[i]);
}
strcat(argv1[args], argv[i]);
args++;
if (send) {
child = fork();
if (child == 0) {
argv1[args+1] = 0;
execve(command, &argv1[0], envp);
return 0;
}
else {
waitpid(child);
free(command);
for (t=0; t<args; t++) {
free(argv1[t]);
argv1[t] = NULL;
}
args = 0;
send = 0;
}
}
}
return 0;
}
waitpid(child) seems wrong. Try:
// ...
#include <sys/wait.h>
// ...
pid_t child;
int wstatus;
// ...
else {
wait(&wstatus);
envp is not declared. Try:
// ...
int main(int argc, char *argv[], char *envp[]) {
// ...
Off-by-one error in argv1 processing. Try:
// ...
if (child == 0) {
argv1[args] = 0;
execve(command, argv1, envp); // why use &argv1[0] ?
// ...
I think (3) is the culprit.
Compiling with different levels of optimisation (-O, etc) seems to affect whether or not the erroneous +1 causes a problem.
Related
I am creating a struct called Job and I want to create an array of struct Job. The name of my array is jobQueue I populate the array using commandline args. The instructor has it set up to where **args is being used. After the user inputs the name of the job and the execution time it gets added to the array. However, when I try to print jobQueue[0].name using the list() funct I have written, the name does not get printed. I'm trying to get my code set up to where I can print the name. I have provided a minimal version of my overall project that just focuses on the specific problem I am encountering and should compile and run fine.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <sys/wait.h>
#include <stdint.h>
#define EINVAL 1
#define E2BIG 2
#define MAXMENUARGS 7
//structure job initialize
struct Job {
//initializing name variable
char *name;
int executionTime;
};
//init the array
struct Job jobQueue[5] = {0};
//cmd function provided by intructor
int cmd_run(int nargs, char **args) {
int execT;
sscanf(args[2], "%d", &execT);
run(args[1], execT);
return 0;
}
//cmd function provided by intructor
void cmd_list() {
list();
}
//cmd function provided by intructor
static struct {
const char *name;
int (*func)(int nargs, char **args);
} cmdtable[] = {
/* commands: single command must end with \n */
{ "r", cmd_run},
{ "run", cmd_run},
{ "list\n", cmd_list}
};
//cmd function provided by intructor
//this is the function that handles the arguments entered by the user
//provided it just in case someone needs to see how arguments are being
//processed
int cmd_dispatch(char *cmd) {
time_t beforesecs, aftersecs, secs;
u_int32_t beforensecs, afternsecs, nsecs;
char *args[MAXMENUARGS];
int nargs = 0;
char *word;
char *context;
int i, result;
void *Dispatcher(void *arg);
for (word = strtok_r(cmd, " ", &context);
word != NULL;
word = strtok_r(NULL, " ", &context)) {
if (nargs >= MAXMENUARGS) {
printf("Command line has too many words\n");
return E2BIG;
}
args[nargs++] = word;
}
if (nargs == 0) {
return 0;
}
for (i = 0; cmdtable[i].name; i++) {
if (*cmdtable[i].name && !strcmp(args[0], cmdtable[i].name)) {
assert(cmdtable[i].func != NULL);
/* Call function through the cmd_table */
result = cmdtable[i].func(nargs, args);
return result;
}
}
printf("%s: Command not found\n", args[0]);
return EINVAL;
}
//adds job to the array using user arguments
void run(char name[], int executionTime) {
//creates a job using the arguments specified by user
struct Job job = {name, executionTime};
jobQueue[0] = job;
printf("\nJob added to queue now please type 'list'\n");
}
//name will not print here
void list() {
printf("\nSee how the name will not print below?\n");
char executionTimeStr[5];
for (int c = 0; c < sizeof (jobQueue) / sizeof (jobQueue[0]); c++) {
//prints job info formatted
if (jobQueue[c].name != NULL) {
sprintf(executionTimeStr, "%d", jobQueue[c].executionTime);
//job name will not print here, output is just left blank
printf("%s %20.8s", "Name", "ExecTime");
printf("%-10.15s %11.3s\n",
jobQueue[c].name,
executionTimeStr
);
}
}
}
int main(int argc, char *argv[]) {
printf("Welcome to our batch job scheduler\n");
printf("Please enter the following exactly: 'run job1 10' \n");
//ignore this, it handles my commandline parser
char *buffer;
size_t bufsize = 64;
buffer = (char*) malloc(bufsize * sizeof (char));
if (buffer == NULL) {
perror("Unable to malloc buffer");
exit(1);
}
while (1) {
printf("User Input: ");
getline(&buffer, &bufsize, stdin);
cmd_dispatch(buffer);
}
//ignore this, it handles my commandline parser
return 0;
}
I'm trying to make an FFI call but I get a segmentation fault inside the function called by ffi_call (gtk_init in this case). I'm not sure where I screwed up.
/*
* gtk_init.cc
*/
#include <ffi.h>
#include <gtk/gtk.h>
void test();
int main(int argc, char *argv[]) {
test();
return 0;
}
void test() {
ffi_cif cif;
ffi_type *arg_types[2];
void *arg_values[2];
ffi_status status;
ffi_arg result;
arg_types[0] = &ffi_type_uint;
arg_types[1] = &ffi_type_pointer;
status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_void, arg_types);
if (status != FFI_OK) {
printf("Failed to prep_ffi\n");
return;
}
int argc = 4;
char **argv = (char**)malloc(sizeof(char*) * argc);
argv[0] = strcpy((char*)malloc(sizeof(char) * 6), "test");
argv[1] = strcpy((char*)malloc(sizeof(char) * 13), "--gtk-debug");
argv[2] = strcpy((char*)malloc(sizeof(char) * 6), "misc");
argv[3] = strcpy((char*)malloc(sizeof(char) * 6), "last");
arg_values[0] = &argc;
arg_values[1] = &argv;
ffi_call(&cif, FFI_FN(gtk_init), &result, arg_values);
// gtk_init(&argc, &argv);
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
free(argv[i]);
}
free(argv);
}
The complete gist can be found here.
The problem is that ffi_call() take the address of the argument as gtk_init() take int * and char *** you need to take the address of these so that give int ** and char ****, fun ?
As said in comment gtk_init() also expect argv to be NULL terminated.
And the final problem is that ffi_type_uint is the wrong type you must use ffi_type_pointer in this case (and by the way int need ffi_type_sint).
So the final fixed code is:
#include <ffi.h>
#include <gtk/gtk.h>
void test(void);
int main(void) { test(); }
void test(void) {
ffi_type *arg_types[] = {&ffi_type_pointer, &ffi_type_pointer};
ffi_cif cif;
ffi_status status =
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, sizeof arg_types / sizeof *arg_types,
&ffi_type_void, arg_types);
if (status != FFI_OK) {
printf("Failed to prep_ffi\n");
return;
}
// bad we don't check malloc() !!! ;)
int argc = 4;
char **argv = malloc(sizeof *argv * (argc + 1));
#define X(x) strcpy(malloc(sizeof x), x);
argv[0] = X("test");
argv[1] = X("--gtk-debug");
argv[2] = X("misc");
argv[3] = X("last");
argv[4] = NULL;
#undef X
int *p_argc = &argc; // This is what expect gtk_init
char ***p_argv = &argv;
void *arg_values[] = {&p_argc, &p_argv}; // so ffi need their address
ffi_arg result;
ffi_call(&cif, FFI_FN(>k_init), &result, arg_values);
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
free(argv[i]);
}
free(argv);
}
Disclaimer: Not tested.
I am trying to create a shared library in Linux. How can I pass an argument to function my_load() when library is loaded? In my C application, I make a call to test_func() then it automatically executes my_load() first before the called function then lastly it executes my_unload()
#include <stdio.h>
void __attribute__ ((constructor)) my_load(int argc, char *argv[]);
void __attribute__ ((destructor)) my_unload(void);
void test_func(void);
void my_load(int argc, char *argv[]) {
printf("my_load: %d\n", argc);
}
void my_unload(void) {
printf("my_unload\n");
}
void test_func(void) {
printf("test_func()\n");
}
Your dynamic library can always read /proc/self/cmdline to see what the command-line parameters used to execute the current executable are. example.c:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
static char **get_argv(int *const argcptr)
{
char **argv;
char *data = NULL;
size_t size = 0; /* Allocated to data */
size_t used = 0;
size_t argc, i;
ssize_t bytes;
int fd;
if (argcptr)
*argcptr = 0;
do {
fd = open("/proc/self/cmdline", O_RDONLY | O_NOCTTY);
} while (fd == -1 && errno == EINTR);
if (fd == -1)
return NULL;
while (1) {
if (used >= size) {
char *old_data = data;
size = (used | 4095) + 4096;
data = realloc(data, size + 1);
if (data == NULL) {
free(old_data);
close(fd);
errno = ENOMEM;
return NULL;
}
}
do {
bytes = read(fd, data + used, size - used);
} while (bytes == (ssize_t)-1 && errno == EINTR);
if (bytes < (ssize_t)0) {
free(data);
close(fd);
errno = EIO;
return NULL;
} else
if (bytes == (ssize_t)0)
break;
else
used += bytes;
}
if (close(fd)) {
free(data);
errno = EIO;
return NULL;
}
/* Let's be safe and overallocate one pointer here. */
argc = 1;
for (i = 0; i < used; i++)
if (data[i] == '\0')
argc++;
/* Reallocate to accommodate both pointers and data. */
argv = realloc(data, (argc + 1) * sizeof (char *) + used + 1);
if (argv == NULL) {
free(data);
errno = ENOMEM;
return NULL;
}
data = (char *)(argv + argc + 1);
memmove(data, argv, used);
/* In case the input lacked a trailing NUL byte. */
data[used] = '\0';
/* Assign the pointers. */
argv[0] = data;
argc = 0;
for (i = 0; i < used; i++)
if (data[i] == '\0')
argv[++argc] = data + i + 1;
/* Final pointer points to past data. Make it end the array. */
argv[argc] = NULL;
if (argcptr)
*argcptr = (int)argc;
return argv;
}
/* Example standard error functions, that avoid the use of stdio.h.
*/
static void wrerr(const char *p)
{
if (p != NULL) {
const char *const q = p + strlen(p);
ssize_t n;
while (p < q) {
n = write(STDERR_FILENO, p, (size_t)(q - p));
if (n > (ssize_t)0)
p += n;
else
if (n != (ssize_t)-1)
return;
else
if (errno != EINTR)
return;
}
}
}
static void wrerrint(const int i)
{
char buffer[32];
char *p = buffer + sizeof buffer;
unsigned int u;
if (i < 0)
u = (unsigned int)(-i);
else
u = (unsigned int)i;
*(--p) = '\0';
do {
*(--p) = '0' + (u % 10U);
u /= 10U;
} while (u > 0U);
if (i < 0)
*(--p) = '-';
wrerr(p);
}
static void init(void) __attribute__((constructor));
static void init(void)
{
int argc, i, saved_errno;
char **argv;
saved_errno = errno;
argv = get_argv(&argc);
if (argv == NULL) {
const char *const errmsg = strerror(errno);
wrerr("libexample.so: get_argv() failed: ");
wrerr(errmsg);
wrerr(".\n");
errno = saved_errno;
return;
}
for (i = 0; i < argc; i++) {
wrerr("libexample.so: argv[");
wrerrint((int)i);
wrerr("] = '");
wrerr(argv[i]);
wrerr("'\n");
}
free(argv);
errno = saved_errno;
return;
}
Compile using e.g.
gcc -Wall -fPIC -shared example.c -ldl -Wl,-soname,libexample.so -o libexample.so
and test using e.g.
LD_PRELOAD=./libexample.so /bin/echo foo bar baz baaz
(Note that plain echo is a shell built-in, and you need to execute another binary like /bin/echo to load the preload library.)
However, most dynamic libraries take arguments in environment variables instead; for example, YOURLIB_MEM for some memory size hint, or YOURLIB_DEBUG for enabling verbose debugging output during runtime.
(My example code does not use stdio.h output, because not all binaries use it, especially if written in some other language. Instead, the wrerr() and wrerrint() are small stupid helper functions that use low-level unistd.h I/O to write directly to standard error; this always works, and causes minimal side effects at run time.)
Questions?
You can't.
__attribute__((constructor)) simply doesn't support this.
There doesn't seem to be any reason you can't just call my_load(argc, argv) at the very beginning of main().
You can use atexit to register a function to be called when your program exits normally, or returns from main.
int main(int argc, char **argv)
{
my_load(argc, argv);
atexit(my_unload);
// ...
}
AFAIK, there is no way to pass arguments to gcc constructor and destructor functions. The best you can do is to use global variables.
In you example, you could try :
In main :
int Argc;
char *Argv[];
int main(int argc, char *argv[]) {
Argc = argc;
Argv = argv;
...
}
In shared library :
extern int Argc;
...
void __attribute__ ((constructor)) my_load();
...
void my_load() {
printf("my_load: %d\n", Argc);
}
But anyway, it can only work if you explicitely load the shared library through dlopen. It it is directly referenced at link time, the constructor function will be called before first instruction in main and you will always find the original value or 0 in Argc.
Sorry to resurrect an oldie here but I just tested this on both Linux and Mac OS:
$ gcc -x c -o test_prog -
#include <stdio.h>
void __attribute__ ((constructor)) my_load(int argc, char *argv[]);
void __attribute__ ((destructor)) my_unload(void);
void test_func(void);
void my_load(int argc, char *argv[]) {
printf("my_load: %d\n", argc);
}
void my_unload(void) {
printf("my_unload\n");
}
void test_func(void) {
printf("test_func()\n");
}
int main() { return 0; }
And it prints this result on both systems:
$ ./test_prog foo bar baz
my_load: 4
my_unload
In order for it to work as a shared library I did have to add the linker option -Wl,--no-gc-sections because it otherwise aggressively removed the constructor & destructor. But otherwise yeah this works already.
This doesn’t use the __attribute__ ((constructor)) syntax, but if you specify a custom _init function, you can do so:
// foo.c
#include <stdio.h>
void my_constructor(int argc, char**argv) {
printf("my_constructor init: %s\n", argv[1]);
}
To do so you need to pass ld -init my_constructor or gcc -Wl,-init,my_constructor, e.g.
gcc foo.c -shared -o libfoo.so -Wl,-init,my_constructor
I have to build a simple shell program using lex and c code. The lex portion is for breaking down the input. It has been provided for me and I'm not expected to change it. I'm in the process of getting my code to run basic commands like "ls". It seems to work the first few times I run the command but eventually always seg faults. Here is the lex code provided:
%{
int _numargs = 10;
char *_args[10];
int _argcount = 0;
%}
WORD [a-zA-Z0-9\/\.-]+
SPECIAL [()><|&;*]
%%
_argcount=0;
_args[0]=NULL;
{WORD}|{SPECIAL} {
if(_argcount < _numargs-1) {
_args[_argcount++]= (char *)strdup(yytext);
_args[_argcount]= NULL;
}
}
\n return (int)_args;
[ \t]+
.
%%
char **getln() {
return (char **)yylex();
}
This is the C code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
extern char **getln();
int main() {
int i;
char **args;
int child1;
int status1;
int counter=0;
int argCount = 1;
char **array = (char **)malloc(1500 * sizeof(char *));
for (i = 0; i < 1500; ++i) {
array[i] = (char *)malloc(500);
}
strcpy(array[0],"ls\0");
array[1] = NULL;
while(1) {
args = getln();
printf("is error here?");
strcpy(array[0], args[counter]);
for(i = (counter+1); args[i] != NULL; i++) {
printf("\nRight before copying to subarray");
strcpy(array[argCount], args[i]);
argCount++;
}
array[argCount] = NULL;
if (strcmp(args[counter],"exit")==0) exit(0);
child1 = fork();
if(child1==0){
execvp(array[0], array);
printf("Unknown command, please try again.");
exit(1);
}
else{
while (wait(&status1) != child1);
}
for(i = 0; args[i] != NULL; i++) {
printf("Argument %d: %s\n argCount: %d", i, args[i], argCount);
}
argCount = 1;
counter++;
}
}
Thanks in advance for any advice. If there is some simple way to adjust the getln() function to overwrite the args array each time it is called that might be easier than what I am attempting but I have no idea how to go about that.
It seems like you have put
_argcount=0;
_args[0]=NULL;
at the top of the rules section in hopes that these statements would be executed at the beginning of yylex(). And you've noticed that they aren't executed (it keeps appending to the previous values because _argcount never goes back to 0).
The obvious thing to do is move those statements into getln() just before the yylex().
What you have now is a lexer that will ignore the string _argcount=0; in the input because it will match that pattern and there's no action to go with it. The second line is even cooler since the [0] is a character class. It makes the lexer ignore the string _args0=NULL;
I don't think I properly understand how to allocate memory for what I want to do.
I would like my program to store arguments from the command line into an array of stucts called Command which has char **args in it. for example if I run
./test.c echo hello : ls -l
I want it to store it as this
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[1].args[0]= ls
commands[1].args[1]= -l
But instead my code is storing it in this way
commands[0].args[0]= echo
commands[0].args[1]= hello
commands[0].args[2]= ls
commands[0].args[3]= -l
commands[1].args[0]= ls
commands[1].args[1]= -l
Could someone help me understand why it is storing ls -l in 2 places? Here is my code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct test {
char **args;
} Command;
int main(int argc, char *argv[])
{
int i, j, k;
Command *commands;
j = k = 0;
commands = (Command *)malloc(argc * sizeof(Command));
for (i = 1; i < argc; i++)
{
if (strcmp(argv[i], ":") == 0)
{
j++;
k = 0;
}
else {
commands[j].args = (char **)realloc(commands[j].args, (k+1) * sizeof(char*));
commands[j].args[k++] = argv[i];
}
}
for (i = 0; i <= j; i++)
{
for (k = 0; k < 5; k++)
{
printf("commands[%d].args[%d]= %s\n", i, k, commands[i].args[k]);
}
}
return EXIT_SUCCESS;
}
Your data storage structure has no way of telling how many strings in commands[j] are valid. So I think it's putting two pointers each in commands[0] and commands[1] just like you expect. But then your print loop looks at commands[0].args[k] for k all the way up to 4, even though it's only valid to look at the first two. When you get up to looking at commands[0].args[2], the result is undefined. (Showing memory from somewhere else in your program, crashing, and catching fire are just a few of the things a program is allowed to do if you use undefined behavior.)
To figure out how many arguments are in each command, you could add a counter member to your struct test. Or maybe allocate one more pointer than there are arguments, and put a NULL after the last argument.
Here is how I would allocate the memory:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct cmd_s {
int num;
char **args;
} cmd_t;
void print_cmds(cmd_t *c, int num) {
int i, j;
for (i=0;i<=num;i++) {
for (j=0;j<c[i].num;j++)
printf("cmds[%d][%d] = %s\n", i, j,c[i].args[j]);
}
}
int main(int argc, char *argv[]) {
int i, j = 0, k = 0;
cmd_t *cmds;
cmds = (cmd_t *)malloc(sizeof(cmd_t));
cmds[0].args = NULL;
cmds[0].num = 0;
for (i=1;i<argc;i++) {
if (strcmp(argv[i], ":") == 0) {
cmds = (cmd_t *)realloc(cmds, (sizeof(cmd_t) * ++j) + 1);
cmds[j].args = NULL;
cmds[j].num = 0;
continue;
}
cmds[j].args = (char **)realloc(cmds[j].args, sizeof(char *) * ++cmds[j].num);
cmds[j].args[cmds[j].num-1] = (char *)malloc(50);
strcpy(cmds[j].args[cmds[j].num-1], argv[i]);
}
print_cmds(cmds, j);
for (i=0;i<=j;i++) {
for(k=0;k<cmds[i].num;k++)
free(cmds[i].args[k]);
free(cmds[i].args);
}
free(cmds);
return 0;
}
Each of your Command structs only have one arg
Perhaps you should consider
typedef struct test {
char **args[5];
} Command;
and then design a better data structure, like a list of lists.
Perhaps you should store the length of args in the struct?
typedef struct test {
char ** args;
unsigned length;
} Command;
Also, maybe you should consider using some of the built in functionality of the C string library. For example, strtok splits a string using the delimiters you give it.