hello_mother
hello_mother

Reputation: 1

creating custom options in unix

I want to created new options in cat using c file

I am new to Unix so I don`t know what to use.

I want to compile

./mycat -s 16 foo 

16 is size of buffer and foo is file name

using mycat.c file and code is below

#include <stdio.h> /* fprintf */
#include <unistd.h> /* getopt */
#include <stdlib.h> /* exit */

/* debug mode (-d option) */
int is_debug = 0;

/* prints log message to stderr only when -d is available */
#define LOG(fmt, ...) do { if (is_debug) fprintf(stderr, fmt "\n", __VA_ARGS__); } while (0)


/* Non-portable functions for checking stdio's buffer size, etc. */

/* checks if the given stream is line-buffered */
int is_stdio_linebuffered(FILE *stream) {
    return (stream->_flags & __SLBF) > 0;
}

/* checks if the given stream is NOT buffered */
int is_stdio_unbuffered(FILE *stream) {
    return (stream->_flags & __SNBF) > 0;
}

/* obtains the buffer size of the given stream */
int stdio_buffer_size(FILE *stream) {
return stream->_bf._size;
}

int main(int argc, char **argv) {
    int opt, i;
    while ((opt = getopt(argc, argv, "dm:")) != -1) {
    switch (opt) {
    case 'd':
        is_debug = 1;
        break;
    case 'm':
        fprintf(stderr, "%s: message is '%s'\n", argv[0], optarg);
        break;
    case 'i': ???????????????????????????????????
    default:
        fprintf(stderr, "Usage: %s [-d] [-m message] args...\n", argv[0]);
        exit(EXIT_FAILURE);
    }
}

  for (i = optind; i < argc; i++) {
      LOG("[%d] %s", i, argv[i]);
  }
  return 0;
}

so c file need to add some code

but I don`t know what function to use

how to make -i option which gets buffer size and file name?

Upvotes: 0

Views: 85

Answers (1)

J...S
J...S

Reputation: 5207

The signature of getopt() is

int getopt(int argc, char * const argv[], const char *optstring);

In optstring, the option characters must be specified. An option character is followed by a single : only if it always needs an argument. Two semicolons are used for optional argument and no semicolon for those always without arguments.

You need an option -s which takes an integer argument.

In your usage of getopt(), there are two other options d and m which don't take argument (I assumed that m doesn't take an argument as you wanted ./mycat -s 16 foo to compile. Change it to take optional argument if you like).

So getopt() should be

while ((opt = getopt(argc, argv, "dms:")) != -1) {
    ....
    ....
} 

And in case 's': of the switch statement

case 's': 
iopt = strtol(optarg, &dp, 10); 
if(iopt==0 && errno == ERANGE)
{
    errno = 0;
    perror("Number out of range");
}
else if(*dp != 0)
{
    printf("\nNot a numeric value. Non number part found");
}
break;

optarg would point to the beginning of a string which is the argument of the s option.

Since we need it as a number, you need to convert the string to number.

strtol() is used for this. It returns the number of type long if successful.
If the number is too big to contained in long, it returns 0 and sets errno to ERANGE. To check these error codes, you must include errno.h.

You could use other functions in the same family as strtol() to get values of other types. eg: strtoll() for long long.

Upvotes: 1

Related Questions