//repstring.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LOOP 99999
#define STR_MAXLEN 300
#define USAGE_INFO "Usage: repstring <argument> <string> <amount of times to repeat>\n\nArguments:\n-s silence length of string output\n-a add space inbetween every string\n"
#define SILENT_ARG "-s"
#define SPACE_ARG "-a"
int main(int argc, char **argv)
{
if(argc == 3 || argc == 4)
{
//Initialize variables and pointers
int i;
char *deststr;
int loop;
//If second argument is space argument, add space inbetween every string
if(strncmp(argv[1], SPACE_ARG, sizeof(SPACE_ARG)) == 0)
{
//Change second argument to integer
loop = atoi(argv[3]);
//If loop is equal or under zero, terminate
if(loop <= 0)
{
printf("%s\n", USAGE_INFO);
return 1;
}
//If user requests to repeat string more than MAX_LOOP, terminate
if(loop > MAX_LOOP)
{
printf("Asked to repeat too many times, aborted.\n");
printf("Hardcoded maximum: %d\n", MAX_LOOP);
return 1;
}
//Allocate memory
deststr = malloc(strlen(argv[2]) * loop + 1);
//If memory allocation failed, terminate
if(deststr == NULL)
{
free(deststr);
printf("Error allocating memory!\n");
return 1;
}
//Append string in argument 2 to deststr for amount of times loop is set
for(i = 0; i < loop; i++)
{
strncat(deststr, argv[2], sizeof(STR_MAXLEN));
strncat(deststr, " ", sizeof(STR_MAXLEN));
}
//Print deststr and free memory
printf("%s\n", deststr);
free(deststr);
return 0;
}
//If second argument is silent option, remove length of string output
if(strncmp(argv[1], SILENT_ARG, sizeof(SILENT_ARG)) == 0)
{
//Change second argument to integer
loop = atoi(argv[3]);
//If loop is equal or under zero, terminate
if(loop <= 0)
{
printf("%s\n", USAGE_INFO);
return 1;
}
//If user requests to repeat string more than MAX_LOOP, terminate
if(loop > MAX_LOOP)
{
printf("Asked to repeat too many times, aborted.\n");
printf("Hardcoded maximum: %d\n", MAX_LOOP);
return 1;
}
//Allocate memory
deststr = malloc(strlen(argv[2]) * loop + 1);
//If memory allocation failed, terminate
if(deststr == NULL)
{
free(deststr);
printf("Error allocating memory!\n");
return 1;
}
//Append string in argument 2 to deststr for amount of times loop is set
for(i = 0; i < loop; i++)
{
strncat(deststr, argv[2], sizeof(STR_MAXLEN));
}
//Print deststr and free memory
printf("%s\n", deststr);
free(deststr);
return 0;
}
//Change second argument to integer
loop = atoi(argv[2]);
//If loop is equal or under 0, terminate
if(loop <= 0)
{
printf("%s\n", USAGE_INFO);
return 1;
}
//If user requests to repeat string more than MAX_LOOP, terminate
if(loop > MAX_LOOP)
{
printf("Asked to repeat too many times, aborted.\n");
printf("Hardcoded maximum: %d\n", MAX_LOOP);
return 1;
}
//Allocate memory
deststr = malloc(strlen(argv[1]) * loop + 1);
//If memory allocation failed, terminate
if(deststr == NULL)
{
free(deststr);
printf("Error allocating memory!\n");
return 1;
}
//Append string in argument 2 to deststr for amount of times loop is set
for(i = 0; i < loop; i++)
{
strncat(deststr, argv[1], sizeof(STR_MAXLEN));
}
int destStrLen = strlen(deststr);
//Print repeated string
printf("%s\n", deststr);
printf("\nLength of string: %d\n", destStrLen);
//Free allocated memory
free(deststr);
return 0;
}
else
{
printf("%s\n", USAGE_INFO);
return 1;
}
return 0;
}
I realize that I should probably move a lot of the code to seperate functions to uncomplicate things, and that I'm still using strncat instead of strncpy for the loops even though it was suggested that I change that last time, and that you can only use one argument at a time.
What I really want to know is if I've handled everything correctly, if I could make any improvements anywhere, and if the program is secure.
Review would be very appreciated.
deststr = malloc(strlen(argv[2]) * loop + 1); ... strncat(deststr, argv[2], sizeof(STR_MAXLEN));
is obviously UB. \$\endgroup\$