When i type ls i get this message twice : ls: cannot access : No such file or directory. But when i type something like that ls -l /tmp or executing a "c" code located in the path everything is fine. Any ideas what is going wrong?
My code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdarg.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
for (;;) {
char *cmd,*splitcmd,*pr0,*pr1,*pr2;
int i, j, nargc = 0, characters;
char **cmdArray;
size_t bufsize = 1024;
pid_t pid, wpid;
int status = 0;
printf("Type a command : \n");
cmd = (char *) malloc(bufsize * sizeof(char));
characters = getline(&cmd, &bufsize, stdin);
// printf("cmd===> %s characters===> %d \n",cmd,characters);
if (cmd[characters-1] == '\n')
{
cmd[characters-1] = '\0';
characters--;
}
// printf("cmd===> %s characters===> %d \n",cmd,characters);
cmdArray = (char**) malloc(bufsize * sizeof(char *));
for (i = 0 ; i < bufsize ; i++)
{
cmdArray[i] = (char*) malloc(bufsize*sizeof(char));
}
splitcmd = strtok(cmd," ");
// printf(" cmd==== %s\n",cmd);
while ((splitcmd))
{
cmdArray[nargc] = splitcmd;
if (cmdArray[nargc][(strlen(cmdArray[nargc])) - 1] == ' ')
cmdArray[nargc][(strlen(cmdArray[nargc]))-1] == '\0';
// printf(" nargc====%d cmdArray===[ %s ] \n",nargc,cmdArray[nargc]);
nargc++;
pr0 = cmdArray[0];
pr1 = cmdArray[1];
pr2 = cmdArray[2];
splitcmd = strtok(NULL," ");
//printf(" pr0 %s \n",pr0);
//printf(" pr1 %s \n",pr1);
//printf(" pr2 %s \n",pr2);
}
if ((pid = fork()) == 0)
{
char *argv[] = {pr0, pr1, pr2, NULL};
execvp(argv[0],argv);
for (int i = 0; i < 100; i++) {
free(cmdArray[i]);
}
free(cmdArray);
}
wait(&status);
}
}
Your code has a number of problems, many of which are identified by turning on warnings. Use -Weverything if your compiler supports it, or at least -Wall if it does not. However, your particular question is in how you're calling execvp().
char *argv[] = {pr0, pr1, pr2, NULL};
execvp(argv[0],argv);
This will always pass two arguments to ls. Even if pr1 and pr2 are empty, ls will still act like it was passed arguments. ls will determine how many arguments it has by looking for a NULL entry.
Your code has a flaw in that it is trying to hard code the number of arguments by splitting up the cmdArray into individual variables. This isn't going to work. For starters, commands take more than two arguments. You should instead leave cmdArray together, properly NULL terminate it, and pass that into execvp.
Related
I'm making a program that reads a text file with different numbers each line and put that numbers in a string. (could be in a array of integer but I need to use the function execvp so I guess i need do as a string). Then it uses a second program to calculate the square of that numbers.
The problem is: I can't pass the arguments to the functions execvp and function execvp is not working. (I guess is something with the fopen)
Edit: I tried with popen instead of execvp and didn't work as well
Here it goes part of my code:
#define LSIZ 128
#define RSIZ 10
char line[RSIZ][LSIZ];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
fptr = fopen("casosproduto.txt", "r");
while(fgets(line[i], LSIZ, fptr))
{
line[i][strlen(line[i]) - 1] = '\0';
i++;
}
fclose(fptr);
char* argument_list3[]={"produto",&line[i],NULL};
tot = i;
for(i = 0; i < tot; ++i)
{
execvp("./produto",argument_list3);
printf(" %s\n", line[i]);
}
execvp will load produto to the original process space, and then execute it, which is equivalent to executing the for loop only once, you can first fork a subprocess and call execvp in the subprocess, Like this
for (i = 0; i < tot; ++i) {
char *argument_list3[] = {"produto", line[i], NULL};
if (fork() == 0) {
execvp("./produto", argument_list3);
}
}
You can also call function system to execute, and you can read a line and execute it once, so it is not limited by the number of lines in the file, e.g:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define LSIZ 128
int main()
{
char line[LSIZ];
char cmd[LSIZ + 16];
FILE *fptr = NULL;
fptr = fopen("casosproduto.txt", "r");
if (fptr == NULL)
return -1;
while (fgets(line, LSIZ, fptr)) {
line[strlen(line) - 1] = '\0';
snprintf(cmd, sizeof(cmd), "./produto %s", line);
system(cmd);
}
fclose(fptr);
return 0;
}
Udpdate. I did some changes in my code but still dont work.
Here it goes the code updated:
#define LSIZ 128
#define RSIZ 10
char line[RSIZ][LSIZ];
FILE *fptr = NULL;
int i = 0;
int tot = 0;
fptr = fopen("casosproduto.txt", "rt");
while(fgets(line[i], LSIZ, fptr))
{
line[i][strlen(line[i]) - 1] = '\0';
i++;
}
fclose(fptr);
tot = i;
pid = fork();
for(i = 0; i < tot; i++)
{
char* argument_list3[]={"produto",line[i],NULL};
if (fork() == 0) {
execvp("./produto", argument_list3);
}
}
}
return 0;
}
There are two reasons for the execvp not working...
first- Something related with the fclose function. If i put the fclose function inside the loop (I know that doesn't make sense but just for tests) then it executes the execvp. Outside the loop it doesnt.
Second- Are my arguments to the execvp alright? (when I tested puting the fclose inside the loop i had to change to this "char* argument_list3[]={"produto","4",NULL};" to test with a number, otherwise the result would be always 1.
I am writing the code for a shell, but when i try to run the command cat filename.c it says:
cat: filename.c
:No such file or directory
even though the same command runs outside the shell. For other commands such as lsmod, it prints nothing.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 80 /* 80 chars per line, per command */
int main(void)
{
char *args[MAX_LINE/2 + 1]; /* command line (of 80) has max of 40 arguments */
int should_run = 1;
int i, upper, j;
char *w= (char *)malloc(80*sizeof(char)) ;
char *buffer;
size_t bufsize= 80;
while (should_run){
printf("osh> ");
fflush(stdout);
getline(&w, &bufsize , stdin);
buffer = strtok (w, " ");
i=0;
while (buffer)
{
args[i++] = buffer;
buffer = strtok (NULL, " ");
}
char *ls_arg[i+1];
for(j=0;j<i;j++)
{
ls_arg[j]=args[j];
}
ls_arg[j]=NULL;
int pid;
pid= fork();
if(!pid)//child process
{
execvp(ls_arg[0], ls_arg);
}
wait(5);
}
return 0;
}
I have an assignment wherein we have to create a shell. Part of that includes using generating paths to different unix commands. (example: /bash/ls). Using execv, I can get everything to work if I hardcode the path, but not if I generate it.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
void command(char *args[]);
int main (int argc, char **argv) {
//get the command and arguments
char buffer[32];
char *b = buffer;
size_t bufferSize = 32;
int counter = 0;
char *tokens[10];
char *delims = " \t\n";
printf("dash> ");
getline(&b, &bufferSize, stdin);
tokens[0] = strtok(buffer, delims);
while (tokens[counter] != NULL) {
counter++;
tokens[counter] = strtok(NULL, delims);
}
command(tokens);
}
void command(char *args[]) {
//create path
char *path = NULL;
int length = strlen(args[0]);
path = malloc(5 + length + 1);
strcat(path, "/bin/");
strcat(path, args[0]);
char *input[2];
input[0] = malloc(512);
strcpy(input[0], path);
printf(input[0]); //the path prints out properly
//input[0] = "/bin/ls"; <--- this works!
input[1] = NULL;
//start execv
pid_t pid;
pid = fork();
if(pid < 0) {
printf("ERROR: fork failed.");
exit(0);
}
else if (pid == 0) {
execv(input[0], input);
printf("error.");
}
free(path);
free(input[0]);
}
anyone have any ideas? i'm pretty sure its an issue with malloc, but i'm not sure how to circumvent that.
The problem with getline() since you are reading form stdin, this
getline(&b, &bufferSize, stdin);
store new line \n char at the end of buffer & when you pass tokens to command() function, args will be ls\n instead of ls which is why execv failed with
execv: No such file or directory
So remove that extra \n character to parse tokens correctly, for e.g
ssize_t read;
read = getline(&b, &bufferSize, stdin); /* always check the return value */
if(read != -1 ) {
b[read-1] = '\0'; /* replace \n with \0 */
}
I have to create a program that gets from the command line n arguments arg1, arg2 .... argn, creates n threads and each of them will read a text file argi and will print in reverse order even lines.
The problem is that my program creates the threads, finishes them, but actually he does nothing. He prints only some random characters, different at every runtime(characters from memory i think).
Below is my code:
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXLINE 100
pthread_t myThread[10];
pthread_mutex_t myMutex;
void * fileprint(void * numei) {
printf("Thread: %ld ...> %s\n", pthread_self(), (char*)numei);
FILE *fi;
char line[MAXLINE], *p;
pthread_mutex_lock(&myMutex);
int k=0;
fi = fopen((char*)numei, "r");
for ( ; ; ) {
k++;
p = fgets(line, MAXLINE, fi);
if (p == NULL) break;
line[strlen(line) - 1] = '\0';
if(k %2 ==0){
for(int j=strlen(line);j>=0;j++){
printf("%c", line[j]);
}
printf("%c","\n");
}
}
fclose(fi);
printf("Finished thread: %ld ...> %s\n", pthread_self(), (char*)numei);
pthread_mutex_unlock(&myMutex);
}
int main(int argc, char* argv[]) {
pthread_mutex_init(&myMutex, NULL);
printf("I'm the father...\n");
int i;
for (i = 1; argv[i]; i++) {
pthread_create(&myThread[i], NULL, fileprint, (void*)argv[i]);
printf("Created thread: %ld ...> %s\n", myThread[i], argv[i]);
}
for (i = 1; argv[i]; i++) {
pthread_join(myThread[i], NULL);
}
printf("I'm still the father...\n");
pthread_mutex_destroy(&myMutex);
return 1;
}
So, anyone can tell me what's the problem? I tried lots of things to modify but nothing...
If you walk the string backward, you have to decrement the index inside the loop (j--). Also you should start at strlen(x)-1.
This line is incorrect:
printf("%c","\n");
The operand of %c must be a char, not char*. It should be either:
printf("%c",'\n');
or:
printf("%s", "\n");
or:
printf("\n");
However, I don't think this will cause a segmentation fault, it will just cause a random character to be printed.
for (i = 1; argv[i]; i++) {
You can also use "argc", it's the arg-counter.
printf("Thread: %ld ...> %s\n", pthread_self(), (char*)numei);
FILE *fi;
char line[MAXLINE], *p;
pthread_mutex_lock(&myMutex);
In your fileprint(...), put the printf(...) behind the mutex, or other threads could interrupt it and you get half-printed, weird sentences on you output.
mfg
Currently attempting to get this program to use multithreading using pthread_create, pthread_join, pthread_exit, and pthread_self. I then intend to use crypt_r in place of crypt in my code.
It will only be able to go up to 8 threads, but I don't even know how to get started with two. I just have one line that declares pthread_t t1,t2,t3,t4,t5,t6,t7,t8.
The plan with these is to put them in to pthread_create but besides initializing these values, I don't know where to go from here.
I know that pthread_create's input would be something like pthread_create(t1, NULL, ... , ...) but I do not know how to go about making the 3rd input or what the 4th input even is.
I then have to make sure to split up the range of letters that each thread is checking based on the number of threads specified by a command line arg. I've designed this so far to work on one thread only, planning on moving it to crypt_r with multithreading...
Really confused as to how I could get to make this work.. If possible.
I know some sort of void function is the third entry in to pthread_create.. but does that function have to be what my passwordChecker is? Or what?
/*
crack.exe
*/
/* g++ -o crack crack.c -lcrypt -lpthread */
//#define _GNU_SOURCE
#include <crypt.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
void *passwordLooper(int ks, char target[9], char s[10]);
void *threadFunction(void *threads);
int main(int argc, char *argv[]){ /* usage = crack threads keysize target */
int i = 0;
/* arg[0] = crack, arg[1] = #of threads arg[2] = size of password, arg[3] = hashed password being cracked */
if (argc != 4) {
fprintf(stderr, "Too few/many arguements give.\n");
fprintf(stderr, "Proper usage: ./crack threads keysize target\n");
exit(0);
}
int threads = *argv[1]-'0'; // threads is now equal to the second command line argument number
int keysize = *argv[2]-'0'; // keysize is now equal to the third command line argument number
char target[9];
strcpy(target, argv[3]);
char salt[10];
while ( i < 2 ){ //Takes first two characters of the hashed password and assigns them to the salt variable
salt[i] = target[i];
i++;
}
printf("threads = %d\n", threads); /*used for testing */
printf("keysize = %d\n", keysize);
printf("target = %s\n", target);
printf("salt = %s\n", salt);
if (threads < 1 || threads > 8){
fprintf(stderr, "0 < threads <= 8\n");
exit(0);
} /*Checks to be sure that threads and keysize are*/
if (keysize < 1 || keysize > 8){ /*of the correct size */
fprintf(stderr, "0 < keysize <= 8\n");
exit(0);
}
pthread_t t1,t2,t3,t4,t5,t6,t7,t8;
if ( threads = 1 ){
pthread_create(&t1, NULL, *threadFunction, threads);
}
char unSalted[30];
int j = 0;
for (i = 2; target[i] != '\0'; i++){ /*generates variable from target that does not include salt*/
unSalted[j] = target[i];
j++;
}
printf("unSalted = %s\n", unSalted); //unSalted is the variable target without the first two characters (the salt)
char password[9] = {0};
passwordLooper(keysize, target, salt);
}
/*_____________________________________________________________________________________________________________*/
/*_____________________________________________________________________________________________________________*/
void *passwordLooper(int ks, char target[9], char s[10]){
char password[9] = {0};
struct crypt_data cd;
cd.initialized = 0;
int result;
for (;;){
int level = 0;
while (level < ks && strcmp( crypt(password, s), target ) != 0) {
if (password[level] == 0){
password[level] = 'a';
break;
}
if (password[level] >= 'a' && password[level] < 'z'){
password[level]++;
break;
}
if (password[level] == 'z'){
password[level] = 'a';
level++;
}
}
char *cryptPW = crypt(password, s);
result = strcmp(cryptPW, target);
if (result == 0){ //if result is zero, cryptPW and target are the same
printf("result = %d\n", result);
printf ("Password found: %s\n", password);
printf("Hashed version of password is %s\n", cryptPW);
break;
}
if (level >= ks){ //if level ends up bigger than the keysize, break, no longer checking for passwords
printf("Password not found\n");
break;
}
}
return 0;
}
With malloc'd structs
/*
crack.exe
By: Zach Corse
*/
/* g++ -o crack crack.c -lcrypt -lpthread */
//#define _GNU_SOURCE
#include <crypt.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
#include <malloc.h>
void *passwordLooper(void *passwordData);
//void *threadFunction(void *threads);
typedef struct{
int keysize;
char *target;
char *salt;
}passwordData;
int main(int argc, char *argv[]){ /* usage = crack threads keysize target */
int i = 0;
/* arg[0] = crack, arg[1] = #of threads arg[2] = size of password, arg[3] = hashed password being cracked */
if (argc != 4) {
fprintf(stderr, "Too few/many arguements give.\n");
fprintf(stderr, "Proper usage: ./crack threads keysize target\n");
exit(0);
}
int threads = *argv[1]-'0'; // threads is now equal to the second command line argument number
int keysize = *argv[2]-'0'; // keysize is now equal to the third command line argument number
char target[9];
strcpy(target, argv[3]);
char salt[10];
while ( i < 2 ){ //Takes first two characters of the hashed password and assigns them to the salt variable
salt[i] = target[i];
i++;
}
printf("threads = %d\n", threads); /*used for testing */
printf("keysize = %d\n", keysize);
printf("target = %s\n", target);
printf("salt = %s\n", salt);
if (threads < 1 || threads > 8){
fprintf(stderr, "0 < threads <= 8\n");
exit(0);
} /*Checks to be sure that threads and keysize are*/
if (keysize < 1 || keysize > 8){ /*of the correct size */
fprintf(stderr, "0 < keysize <= 8\n");
exit(0);
}
pthread_t t1,t2,t3,t4,t5,t6,t7,t8;
struct crypt_data data;
data.initialized = 0;
//~ passwordData.keysize = keysize;
//~ passwordData.target = target;
//~ passwordData.salt = salt;
passwordData *pwd = (passwordData *) malloc(sizeof(pwd));
pwd->keysize = keysize;
pwd->target = target;
pwd->salt = salt;
//~ if ( threads = 1 ){
//~ pthread_create(&t1, NULL, *threadFunction, threads);
//~ }
char unSalted[30];
int j = 0;
for (i = 2; target[i] != '\0'; i++){ /*generates variable from target that does not include salt*/
unSalted[j] = target[i];
j++;
}
printf("unSalted = %s\n", unSalted); //unSalted is the variable target without the first two characters (the salt)
char password[9] = {0};
passwordLooper(pwd);
}
/*_____________________________________________________________________________________________________________*/
/*_____________________________________________________________________________________________________________*/
void *passwordLooper(passwordData pwd){
char password[9] = {0};
int result;
int ks = pwd.keysize;
char *target = pwd.target;
char *s = pwd.salt;
for (;;){
int level = 0;
while (level < ks && strcmp( crypt(password, s), target ) != 0) {
if (password[level] == 0){
password[level] = 'a';
break;
}
if (password[level] >= 'a' && password[level] < 'z'){
password[level]++;
break;
}
if (password[level] == 'z'){
password[level] = 'a';
level++;
}
}
char *cryptPW = crypt(password, s);
result = strcmp(cryptPW, target);
if (result == 0){ //if result is zero, cryptPW and target are the same
printf("result = %d\n", result);
printf ("Password found: %s\n", password);
printf("Hashed version of password is %s\n", cryptPW);
break;
}
if (level >= ks){ //if level ends up bigger than the keysize, break, no longer checking for passwords
printf("Password not found\n");
break;
}
}
return 0;
}
Well, here's the prototype for pthread_create:
int
pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void *), void *restrict arg);
It shows that the 3rd arg is a pointer to a function that returns a pointer to void and takes a pointer to void as its sole argument. I see you have a prototype for:
void *threadFunction(void *threads);
which meets those specifications, but it's not actually written? The 4th argument in pthread_create is just a pointer to void, which can essentially contain anything you want it to.
I'm guessing that the function you want to thread is actually passwordLooper, which takes 3 arguments.. but pthread_create specifies a function that takes only 1. You have to find a workaround so that you can only accept a single argument to your passwordLooper function yet still pass all 3 variables that you care about. There are a few ways this can be done:
Global variables (yuck, not thread safe, don't really do this)
malloc() some memory, memcpy() your arguments into it (or pointers to them), and pass that newly malloc()ed memory to pthread_create(). In your called function you'll have to parse the 3 variables back out of the void * (hacky, but works in theory)
Define a struct that contains your 3 arguments, malloc a copy of that struct, copy your variables into the newly malloced struct, and pass it as your 4th argument. This greatly simplifies parsing the values back out and is the general way to accomplish passing multiple variables as pthread_create's 4th argument