This repository has been archived on 2021-08-17. You can view files and clone it, but cannot push or open issues or pull requests.
unix/mygrep/mygrep.c

149 lines
4.5 KiB
C

#define _GNU_SOURCE // in order for strcasestr to work
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
static void print_usage(void);
static void check_opts_number(int argc);
static void check_for_string(char *to_check, char *to_find, int iflag, char *ofile);
int main(int argc, char *argv[]) {
check_opts_number(argc);
int iflag = 0;
char *ofile = NULL;
char *keyword = NULL;
char *filename = NULL;
int c;
// Get the options
while((c = getopt(argc, argv, "io:h")) != -1) {
switch(c) {
case 'i':
iflag = 1;
break;
case 'o':
ofile = optarg;
break;
case 'h':
printf("Command usage:\n");
print_usage();
exit(EXIT_SUCCESS);
break;
case '?':
print_usage();
exit(EXIT_FAILURE);
default:
abort();
}
}
// Check if the required argument is there
if(argv[optind] == NULL) {
fprintf(stderr, "Mandatory argument 'keyword' missing.\n");
print_usage();
exit(EXIT_FAILURE);
} else {
keyword = argv[optind];
filename = argv[optind + 1];
}
// Get user input if there is no input file defined
while(filename == NULL) {
size_t len; // Define an unsigned string length value
if(getline(&filename, &len, stdin)) { // Read until new line
check_for_string(filename, keyword, iflag, ofile);
filename = NULL; // Reset the input
}
}
// Get data from input file
if(filename != NULL) {
FILE *in;
if((in = fopen(filename, "r")) == NULL) {
fprintf(stderr, "Error opening the file %s\n", filename);
exit(EXIT_FAILURE);
}
size_t len;
char *line = NULL; // Define a pointer to hold our value
// Read the file line by line and execute check_for_string for each line
while(getline(&line, &len, in) != -1) {
check_for_string(line, keyword, iflag, ofile);
}
}
return EXIT_SUCCESS;
}
static void print_usage(void) {
printf("mygrep [-i] [-o outfile] keyword [file...]\n");
}
/**
* @brief Function to check the number of arguments
* @details Checks the number of arguments supplied to the command line.
* If the arguments are less than the required or more than possible, it exits
* @param argc Number of arguments obtained from the command line
* @return none
*
**/
static void check_opts_number(int argc) {
if(argc <= 1) {
fprintf(stderr, "At least one argument expected.\n");
print_usage();
exit(EXIT_FAILURE);
} else if(argc > 6) {
fprintf(stderr, "Too many arguments supplied.\n");
print_usage();
exit(EXIT_FAILURE);
}
}
/**
* @brief Function to check whether or not a string is contained in another string
* @details Checks whether or not a substring is contained in a line.
* If it is there and no output file is passed, it will print the line to stdout
* If it is there and an output file is passed, it will append the line to the end of the output file
*
* @param
* to_check: String to be checked against
* to_find: String to search for
* iflag: Whether or not to ignore the casing of the letters
* ofile: The file to append the output to
* @return none
*
**/
static void check_for_string(char *to_check, char *to_find, int iflag, char *ofile) {
if(ofile == NULL) {
/**
* Find the first occurance of needle in haystack and return it as a pointer.
* If found, print haystack
**/
if(iflag == 0 && strstr(to_check, to_find) != NULL) printf("%s", to_check);
else if(iflag == 1 && strcasestr(to_check, to_find)) printf("%s", to_check);
} else {
/**
* Open the specified file for appending
* Find the first occurance of needle in haystack and return it as a pointer.
* If found, append haystack to the end of the file
* Close the file
**/
FILE *out;
// Check if the file was opened successfully
if((out = fopen(ofile, "a")) == NULL) {
fprintf(stderr, "Error opening the file %s\n", ofile);
exit(EXIT_FAILURE);
}
if(iflag == 0 && strstr(to_check, to_find)) fprintf(out, "%s", to_check);
else if(iflag == 1 && strcasestr(to_check, to_find)) fprintf(out, "%s", to_check);
fclose(out);
}
}