Shell-like program C - c

The code below is supposed to work as a shell. It has the previous and next option, a history like feature, the exit and the execute command.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUFFER_SIZE 256
#define HISTORY_LENGTH 128
int executeCommand(char*cmd)
{
return(!strcmp(cmd,"e\n"));
}
int exitCommand(char*cmd)
{
return (!strcmp(cmd,"exit\n"));
}
int previousCommand(char*cmd)
{
return (!strcmp(cmd,"p\n"));
}
int nextCommand(char*cmd)
{
return (!strcmp(cmd,"n\n"));
}
void execute(char *line)
{
line[strlen(line)-1]='\0';
char **arguments;
char* temp;
int i=0;
arguments=(char**)malloc(sizeof(char)*10);
temp=strtok(line," ");
arguments[i]=malloc(strlen(temp)*sizeof(char));
if(arguments[i]!=NULL)
{
strcpy(arguments[i],temp);
i++;
}
else
{
printf("Out of memory");
}
while(temp!=NULL)
{
temp=strtok(NULL," ");
if(temp==NULL){
arguments[i]=NULL;
}
else{
arguments[i]=malloc(strlen(temp)*sizeof(char));
if(arguments[i]!=NULL)
{
strcpy(arguments[i],temp);
i++;
}
}
}
printf("%s ",arguments[0]);
printf("%s ",arguments[1]);
printf("%s ",arguments[2]);
execvp(arguments[0],arguments);
}
int main(int argc, char*argV[]) {
int i;
char *cmd=(char*)malloc(sizeof(char)*BUFFER_SIZE);
char **history=NULL;
int historylength=0;
int currentCommand=0;
history=(char**)malloc(sizeof(char)*BUFFER_SIZE);
do{
fgets(cmd,BUFFER_SIZE-1,stdin);
if(exitCommand(cmd))
break;
else
if(previousCommand(cmd))
{
if(currentCommand>0)
printf("%s",history[--currentCommand]);
else if(currentCommand==0)
{
currentCommand=historylength;
printf("%s",history[--currentCommand]);
}
}
else
if(nextCommand(cmd))
{
if(currentCommand<historylength)
printf("%s",history[currentCommand++]);
}
else
if(executeCommand(cmd))
{
execute(history[--currentCommand]);
}
else
{
history[historylength]=malloc(strlen(cmd)*sizeof(char));
if(history[historylength]!=NULL)
{
strcpy(history[historylength],cmd);
currentCommand=++historylength;
}
else
{
printf("Out of memory");
break;
}
}
} while(1);
free(cmd);
for(i=0;i<historylength;i++)
free(history[i]);
free(history);
return 0;
}
I want to make this work for the function cat. I type in the e cat main.c and I expect it to execute the cat command but it's not doing anything, what am I doing wrong here? I'm not a pro at this so I appreciate all the help.

This is incorrect:
arguments=(char**)malloc(sizeof(char)*10);
as arguments is a char**, so the code needs to allocate sizeof(char*). Change to:
arguments = malloc(10 * sizeof(*arguments));
Same mistake for history also. Additionally, see Do I cast the result of malloc?
There is one char less than required being allocated for the char* as strcpy() writes a terminating null character. Change:
arguments[i]=malloc(strlen(temp)*sizeof(char));
to:
arguments[i] = malloc(strlen(temp) + 1);
sizeof(char) is guaranteed to be 1 and can be omitted from the size calculation.
Prevent i from exceeding the bounds of the memory allocated for arguments. As the code currently stands there is no protection to prevent i from exceeding 9 (0 to 9 are the valid values for i as arguments was allocated 10 elements).

Related

search of string in an array of strings

i wrote some code that is supposed to find the location of a given string in an array of strings.
problem is- it doesn't give the location. it gives something else.
i understand that probably the problem has to do with the differences between the pointers that are involved- a previous version that dealt with finding the position of a letter in a word worked well.
after a lot of attempts to figure out where is the bug, i ask your help.
kindly, explain me what should be done.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int what (char * token);
main()
{
int i=0;
char string[]="jsr";
char *token;
token=&string[0];
i=what(token);
printf(" location of input is %d \n", i);
return 0;
}
int what (char * token)
{
int i=1;
char *typtbl[]={"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
char * ptr;
ptr=(char *)typtbl;
while (!(strcmp(ptr,token)==0))
{
ptr=(char *)(typtbl+i);
i++;
}
return i;
}
As pointed out, you did not design function what properly. What value should it return if your search function go through all the pointers but does not find the desired string? Typically in that case return -1 would be a choice to indicate nothing found. Also in this case, using a for loop would probably be more suitable, you can just return the index immediately instead of going through all pointers.
int what(char *token)
{
char *typtbl[] = {
"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
for( size_t i = 0; i < sizeof(typtbl)/sizeof(char*); ++i )
{
char *ptr = typtbl[i];
if(strcmp(ptr, token) == 0)
{
return i; // found something
}
}
return -1; // found nothing
}
A cleaner working version.
Main issue is in the (char *)(typtbl+i) replaced by typtbl[i] in the following code. typtbl+i is equivalent to &typtbl[i], so if my memory is good, it's a pointer on the pointer of the string and not the pointer of string itself
I added a NULL at the end of the array to be able to stop if the string is not present and return -1 to clearly say it was not found.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int what(char *token);
int main()
{
int i = 0;
char string[] = "jsr";
i = what(string);
printf(" location of input is %d \n", i);
return 0;
}
int what(char *token)
{
char *typtbl[] = {
"mov",
"cmp",
"add",
"jsr",
"not",
"clr",
"lea",
NULL
};
int i = 0;
while(typtbl[i] && !(strcmp(typtbl[i], token) == 0)) {
++i;
}
if(!typtbl[i])
i = -1;
return i;
}
char *token; token=&string[0]; was useless because string == &string[0].
A few things:
Your main function is missing its return type.
The while loop in what doesn't stop when the element isn't found. Therefore you are reading out of bounds.
This should do the work w/o pointer arithmetic.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int what (char * token);
int main(){
int i=0;
char string[]="jsr";
char *token;
token=&string[0];
i=what(token);
printf(" location of input is %d \n", i);
return 0;
}
int what (char * token){
unsigned int i=0;
char *typtbl[]={"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
unsigned int typtbl_x_size = sizeof(typtbl)/sizeof(typtbl[0]);
char * ptr;
ptr=typtbl[i];
while (!(strcmp(ptr,token)==0)){
i += 1;
if (i >= typtbl_x_size){
printf("element not in list\n");
return -1;
}
ptr=typtbl[i];
}
return i;
}

Segmentation fault with multithreaded array

I am trying to make multithread array sorting program in c. But when I run the program, I get an "segmentation fault" error.
Can someone help?
What should I change? First array should be 300 the other should be 500. We sort sequences separately first. After that merge 2 sorted sequences. I use "gcc -pthreads -0 soru1 soru1.c" and "./soru1" commands.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#define size 800
int orginal_dizi[size], dizi1[300], dizi2[500], dizi3[size];
int sayi,a=1;
int boyutbul(int *the)
{
int number=-1;
while(the[++number]!='\0'){}
return number;
}
void*runner(void *param)
{
int temp,i,k;
int *bolum = param;
sayi = boyutbul(bolum);
printf("\n----------unsorted %d. array-----------\n\n",a);
for(i=0; i<sayi;i++)
printf("%d\n", bolum[i]);
for(i=0; i<sayi;i++)
{
for(k=0; k<(sayi-i-1);k++)
{
if(bolum[k]>bolum[k+1])
{
temp=bolum[k];
bolum[k]=bolum[k+1];
bolum[k+1]=temp;
}
}
}
printf("\n----------sorted %d. array-----------\n\n",a);
for(i=0; i<sayi;i++)
printf("%d\n", bolum[i]);
a++;
pthread_exit(0);
}
int main()
{
pthread_t tid1,tid2, tid3;
int i=0;
while(i<size)
{
int yenisayi=1+rand()%1500;
int aynimi=0, j=0;
while(j<i)
{
if(orginal_dizi[j]==yenisayi)
{
aynimi=1;
break;
}
j++;
}
if(aynimi)
continue;
orginal_dizi[i]=yenisayi;
i++;
}
for(i=0;i<size;i++)
{
if(i<(300))
{
dizi1[i]=orginal_dizi[i];
}
else
{
dizi2[i-(500)-1]= orginal_dizi[i];
}
}
pthread_create(&tid1,NULL,runner,(void *)dizi1);
pthread_join(tid1,NULL);
pthread_create(&tid2,NULL,runner,(void *)dizi2);
pthread_join(tid2,NULL);
for(i=0; i<size;i++)
{
if(i<300)
{
dizi3[i]=dizi1[i];
}
else
{
dizi3[i]=dizi2[i-500];
}
}
pthread_create(&tid3,NULL,runner,(void *)dizi3);
pthread_join(tid3,NULL);
FILE *fp;
if((fp=fopen("son.txt","w"))== NULL)
printf("Dosya acilamadi.");
for(i=0;i<size;i++)
{
fprintf(fp, "%d\n", dizi3[i]);
}
fclose(fp);
return 0;
}
There is no multithreading in this program: every thread is immediately joined; noting runs in parallel.
The real problem is in boyutbul, which tries to figure out the length of the array by looking for '\0'. The way you initialize the arrays, there is no guarantee that they would have the terminating 0 (in fact, they wouldn't have any zeroes), so the program is doomed to access them beyond the bounds. This is UB.

Seg Fault occurs while malloc-ing

This function is a part of program which will gain statistics about books (amount of specific letters, words etc.). Thing is that segmentation fault appears when trying to malloc:
*wordArray[arrayIndex] = malloc(sizeof(***wordArray)*(wcslen(newWord)+1));
after reallocing whole array
*wordArray = realloc(*wordArray, (arrayIndex+1)*sizeof(**wordArray));
I know that realloc isn't really efficent but the most important thing at the moment is to understand why it doesn't work at all. Thanks a lot.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <wctype.h>
#include <wchar.h>
#define X 2
void wordManager(wchar_t ***, int **, wchar_t *);
int main(int argc, char **argv){
setlocale(LC_ALL, "");
wchar_t **wordArray;
int *wordAmount;
wchar_t word[50];
for(int i=0; i<X; i++){
scanf("%ls", word);
wordManager(&wordArray, &wordAmount, word);
}
for(int i=0; i<X; i++){
printf("%ls; %d times\n", wordArray[i], wordAmount[i]);
}
}
void wordManager(wchar_t ***wordArray, int **wordAmount, wchar_t *newWord){
static int isArrayInitialised = 0;
static int isArrayEmpty = 1;
static int arrayIndex = 0;
int wordLocation;
if(!isArrayInitialised){
*wordArray = malloc(sizeof(**wordArray)*1);
if(*wordArray==NULL){
printf("Error mallocing wordArray");
exit(EXIT_FAILURE);
}
*wordAmount = calloc(1, sizeof(*wordAmount));
if(*wordAmount==NULL){
printf("Error callocing wordAmount");
exit(EXIT_FAILURE);
}
isArrayInitialised = 1;
}
if(isArrayEmpty){
*wordArray[0] = malloc(sizeof(***wordArray)*(wcslen(newWord)+1));
wcscpy(*wordArray[0], newWord);
*wordAmount[0] = 1;
isArrayEmpty = 0;
}
else{
//Check if word is already in an array.
wordLocation = 0;
for(; wordLocation<arrayIndex+1; wordLocation++){
if(!wcscmp(*wordArray[wordLocation], newWord)) break;
}
printf("%d\n", wordLocation);
//Word hasn't been found. Then:
if(wordLocation==arrayIndex+1){
arrayIndex++; //Increase arrays' volume.
*wordArray = realloc(*wordArray, (arrayIndex+1)*sizeof(**wordArray));
if(*wordArray==NULL){
printf("Error reallocating wordArray memory.\n Array index: %d", arrayIndex);
exit(EXIT_FAILURE);
}
*wordAmount = realloc(*wordAmount, (arrayIndex+1)*sizeof(**wordAmount));
if(*wordAmount==NULL){
printf("Error reallocating wordAmount memory.\n Array index: %d", arrayIndex);
exit(EXIT_FAILURE);
}
*wordArray[arrayIndex] = malloc(sizeof(***wordArray)*(wcslen(newWord)+1));
wcscpy(*wordArray[arrayIndex], newWord);
*wordAmount[arrayIndex] = 1;
}
//Word has been found in an array.
else{
(*wordAmount[wordLocation])++;
}
}
}

Segfault when a large parameter is passed

My program is supposed to print out every nth character in a string of text. The first parameter defines the "n" or the increment between characters to report on. The second parameter is optional, but if specified, defines how many characters to work on.
#include <stdio.h>
#include <stdlib.h>
#define MAX_STR_LEN 100
int main(int argc, char **argv) {
char string[MAX_STR_LEN];
char *testval="This is a test, this is only a test. For the next sixty seconds, this will be a test of the emergency broadcasting system.";
if (argc<2) {
printf("Expected at least one argument.\n");
return 1;
}
int inc=atoi(argv[1]);
if (inc <=0) {
printf("Expected first argument to be a positive number.\n");
return 1;
}
int max=MAX_STR_LEN;
if (argc==3) {
max=atoi(argv[2]);
if (max<0) max=MAX_STR_LEN;
}
int i=0;
while(i < max) {
string[i]=testval[i]; // gdb says this is where the seg fault occurs
i++;
}
string[i]=0;
i=0;
while(string[i]!=0) {
printf("The %d char is %c\n",i,string[i]);
i = i + inc;
}
return 0;
}
Running "./prog3 5 40" works fine, but running "./prog3 5 150" causes a seg fault.
./prog3 5 150
8
Segmentation Fault
This will work better. you need to make the string buffer large enough to hold all the data you put into it. The segmentation fault you had comes from writing to a memory address not allowed to be used by the program.
#include <stdio.h>
#include <stdlib.h>
#define MAX_STR_LEN 100
int main(int argc, char **argv) {
char *testval="This is a test, this is only a test. For the next sixty seconds, this will be a test of the emergency broadcasting system.";
if (argc<2) {
printf("Expected at least one argument.\n");
return 1;
}
int inc=atoi(argv[1]);
if (inc <=0) {
printf("Expected first argument to be a positive number.\n");
return 1;
}
int max=MAX_STR_LEN;
if (argc==3) {
max=atoi(argv[2]);
if (max<0) max=MAX_STR_LEN;
}
char string[max];
int i=0;
while(i < max) {
string[i]=testval[i];
i++;
}
string[i]=0;
i=0;
while(string[i]!=0) {
printf("The %d char is %c\n",i,string[i]);
i = i + inc;
}
return 0;
}

Wrong result when copying an array of strings

I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
char* passwd;
int nr;
void test()
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
for (i=0; i<argc; i++)
{
user=strdup(argv[i]);
}
test();
return 0;
}
The result is the argv[argc] on all the positions. How can I fix this? I wwant to have that test() outside the loop.
**
EDIT
**
After the ANSWERS here this is my new code, which is not working. Can anyone say why?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* user;
void test(int n)
{
int i=0;
for(i=0;i<n;i++)
printf("%s \n",user[i]);
}
int main(int argc,char*argv[])
{
user = (char*) malloc(argc*sizeof(char));
int i;
for (i=0;i<argc;i++)
{
user[i]=argv[i];
}
test(argc);
return 0;
}
You are assigning to both password and user at each iteration of the for loop. The final values you see are from the last iteration. Also, there is memory leak due to overwriting the pointers from previous strdup calls. In fact, you do not need a loop:
int main(int argc,char*argv[])
{
if(argc == 3) {
user=strdup(argv[1]);
passwd=strdup(argv[2]);
} else {
// error: usage
}
test();
return 0;
}
If you want to have multiple user/password combinations:
char *user[256], *passwd[256];
void test(int n) {
int i;
for(i=0;i<n;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
for(i = 0; i < argc && i < 256; i+=2) {
user[i]=strdup(argv[i]);
passwd[i]=strdup(argv[i+1]);
}
test(argc);
return 0;
}
Because you overwrite the pointers user and passwd in every iteration. Hence, you'll only see the last string.
If you can tell your aim of the program, a better answer can be provided. Because I am not sure whether you want to read one user and passwd Or an array of users and passwds.
After you edit, I see you want to read an array of strings:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** user;
// or char *user[100]; /* If you want a fix length array of pointers. Now, you dont have to malloc. /*
char* passwd;
int nr;
void test(int argc)
{
int i=0;
for(i=0;i<argc;i++)
printf("Hello %s \n",user[i]);
}
int main(int argc,char*argv[])
{
int i;
nr=argc;
user = malloc(argc*sizeof(char*));
for (i=0; i<argc; i++)
{
user[i]=strdup(argv[i]);
}
test(argc);
return 0;
}
Of course; in test() you don't use i other than a loop variable and in main() you keep overwriting the previous value of user and passwd. In effect, what you do is:
user = strdup(argv[0]); /* Note: argv[0] is the program name. */
passwd = strdup(argv[0]);
user = strdup(argv[1]);
passwd = strdup(argv[1]);
user = strdup(argv[2]);
passwd = strdup(argv[2]);
user = strdup(argv[3]);
passwd = strdup(argv[3]);
printf("%s %s \n", user, passwd);
With this information, can you fix your program?
$ cat trash.c
#include <stdio.h>
#include <string.h>
void test(FILE* stream, char* usr, char* pass) {
fprintf( stream, "%s#%s\n", usr, pass);
}
int main(int argc, char** argv) {
int i = 1;
if (argc % 2) {
while(argv[i]) {
test(stdout, argv[i], argv[i + 1]);
i += 2;
}
}
return 0;
}
$ clang trash.c
$ ./a.out user1 pass1 user2 pass2
user1#pass1
user2#pass2
$
also if you call strdup() don't forget to free memory, because strdup called malloc().

Resources