How to use nested Switch with commandline arguments? - c

I have my switch case and statements inside my main function as follows:
int main(int argc, char *argv[])
{
int c;
while((c = getopt(argc,argv,"ABS"))!=-1)
{
switch(c)
{
case 'A':
flag = 0;
printf("open the port\n");
struct can_frame frame_rd;
open_port("vcan0");
printf("vcan0 port is opened");
fflush(stdout);
create_file();
while(1)
{
read_port(&frame_rd);
}
break;
case 'B':
flag = 1;
printf("open the port\n");
open_port("vcan0");
printf("vcan0 port is opened");
fflush(stdout);
create_binfile();
while(1)
{
read_port(&frame_rd);
}
break;
}
}
Now I want to make use of nested switch when user passes an argument -S inside the case A can i do it as follows? Is the following procedure correct?
int main(int argc, char *argv[])
{
int c;
while((c = getopt(argc,argv,"ABS"))!=-1)
{
switch(c)
{
case 'A':
switch(c)
{
case 'S':
size = 100;
break;
}
flag = 0;
printf("open the port\n");
struct can_frame frame_rd;
open_port("vcan0");
printf("vcan0 port is opened");
fflush(stdout);
create_file();
while(1)
{
read_port(&frame_rd);
}
break;
case 'B':
flag = 1;
printf("open the port\n");
open_port("vcan0");
printf("vcan0 port is opened");
fflush(stdout);
create_binfile();
while(1)
{
read_port(&frame_rd);
}
break;
}
}
In the above code can I use same switch(c) for the nested case also , is the usage of nested switch correct?Thanks in advance.

No, within the outer swich case 'A', variable c can be thought of as constant, therefore your nested switch will not find a case to match and does not have a default case.
If you know your arguments are in a particular order, you can address them directly e.g. argv[1] and argv[2] for the first and second arguments.

Related

How to create a shared buffer of a value from the command line in C (producer/consumer multi-threading problem)?

I get the size of a buffer to be created from the command line with this code:
while ((c = getopt(argc, argv, "d:p:t:b:")) != -1)
switch (c) {
case 'd':
root_dir = optarg;
break;
case 'p':
port = atoi(optarg);
break;
case 't':
// NUMBER OF CONSUMER THREADS
n_threads = atoi(optarg);
break;
case 'b':
// BUFFER SIZE
THREAD_BUFFER_SIZE = atoi(optarg);
default:
fprintf(stderr, "usage: wserver [-d basedir] [-p port] [-t threads] [-b buffer] \n");
exit(1);
}
Which is contained in my main() function.
Lets say I execute ./wserver -d . -p 8004 -t 8 -b 10.
I expect to get a buffer of size 10.
This buffer is being shared between producer and consumer threads, whose function implementations lie outside of the main() function. With that, I receive an error stating 'buffer is undeclared.'
I then created a buffer of default size, lets say 4 (int buffer[4];), outside of the main function so that it would be declared. Then inside of the main() function, I add buffer = buffer[THREAD_BUFFER_SIZE], which gets the size requested from the getopt case statement above. Which is obviously wrong, but I do not understand how to replace this code to allow the shared buffer of a size requested to be created.
Any tips?
Default initialized buffer on line 3 and shared buffer commented:
char default_root[] = ".";
int count = 0;
int buffer[10];
void *producer(void *THREAD_BUFFER_SIZE) {
[uses buffer]
}
void *consumer(void *arg) {
[uses buffer]
}
int main(int argc, char *argv[])
{
int c;
char *root_dir = default_root;
int port = 10000;
// I created these
int n_threads;
int THREAD_BUFFER_SIZE;
pthread_t* mythreads; // consumer threads
pthread_t p_id; // producer thread
while ((c = getopt(argc, argv, "d:p:t:b:")) != -1)
switch (c) {
case 'd':
root_dir = optarg;
break;
case 'p':
port = atoi(optarg);
break;
case 't':
// NUMBER OF CONSUMER THREADS
n_threads = atoi(optarg);
break;
case 'b':
// BUFFER SIZE
THREAD_BUFFER_SIZE = atoi(optarg);
default:
fprintf(stderr, "usage: wserver [-d basedir] [-p port]\n");
exit(1);
}
// SHARED BUFFER
buffer = buffer[THREAD_BUFFER_SIZE];
// Create producer thread
if (pthread_create(&p_id, NULL, producer, (void*) THREAD_BUFFER_SIZE) != 0) {
fprintf(stderr, "unable to create producer thread\n");
exit(1);
}
// Create n_threads consumer threads
mythreads = (pthread_t*) malloc(sizeof(pthread_t)*n_threads);
for(int i = 0; i < n_threads; i++) {
if(pthread_create(&mythreads[i], NULL, consumer, NULL) != 0) {
fprintf(stderr, "unable to create consumer thread\n");
exit(1);
}
}
// run out of this directory
chdir_or_die(root_dir);
// now, get to work
int listen_fd = open_listen_fd_or_die(port);
while (1) {
struct sockaddr_in client_addr;
int client_len = sizeof(client_addr);
int conn_fd = accept_or_die(listen_fd, (sockaddr_t *) &client_addr,
(socklen_t *) &client_len);
request_handle(conn_fd);
close_or_die(conn_fd);
}
// Added at end to close and clean
pthread_join(p_id, NULL);
free(mythreads);
pthread_mutex_destroy(&mut);
return 0;
}

C program help to open a file in Unix/Linux using getopt and command line argument

I am trying to work on my college assignment that required programming in C in Unix. I have to take command line arguments and open a file with the name passed as an argument. I've been trying to find help, but couldn't find any resources to help me understand how to parse the argument as a string and open the required file. I'm seeking examples or links that point me in the right direction.
I'm including the short piece of code where I'm trying to parse the options using getopt(). What am I doing wrong?
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc[], char *argv[])
{
int option;
while(option = getopt(argc, argv, "hi:o:") != -1)
{
switch (option){
case 'h':
printf("Usage : -i [input file name]\n-o [output file name]");
break;
case 'i':
printf("\n Input file is: %s",argv[1]);
break;
case 'o':
printf("\n Output file is: %s",argv[2]);
break;
}
}
return 0;
}
I keep getting "Unrecognized command line option error". Also, when I try to include a text file, I believe that the error says that the option is being parsed as an int, but the argument is a string.
P.S: I'm not really looking get any direct answers here. I want the community to help me learn in the best possible way.
As mentioned in the comments, you should be using optarg. Here is an example that is pretty comprehensive:
/*
example of command line parsing via getopt
usage: getopt [-dmp] -f fname [-s sname] name [name ...]
Paul Krzyzanowski
*/
#include <stdio.h>
#include <stdlib.h>
int debug = 0;
int
main(int argc, char **argv)
{
extern char *optarg;
extern int optind;
int c, err = 0;
int mflag=0, pflag=0, fflag=0;
char *sname = "default_sname", *fname;
static char usage[] = "usage: %s [-dmp] -f fname [-s sname] name [name ...]\n";
while ((c = getopt(argc, argv, "df:mps:")) != -1)
switch (c) {
case 'd':
debug = 1;
break;
case 'm':
mflag = 1;
break;
case 'p':
pflag = 1;
break;
case 'f':
fflag = 1;
fname = optarg;
break;
case 's':
sname = optarg;
break;
case '?':
err = 1;
break;
}
if (fflag == 0) { /* -f was mandatory */
fprintf(stderr, "%s: missing -f option\n", argv[0]);
fprintf(stderr, usage, argv[0]);
exit(1);
} else if ((optind+1) > argc) {
/* need at least one argument (change +1 to +2 for two, etc. as needeed) */
printf("optind = %d, argc=%d\n", optind, argc);
fprintf(stderr, "%s: missing name\n", argv[0]);
fprintf(stderr, usage, argv[0]);
exit(1);
} else if (err) {
fprintf(stderr, usage, argv[0]);
exit(1);
}
/* see what we have */
printf("debug = %d\n", debug);
printf("pflag = %d\n", pflag);
printf("mflag = %d\n", mflag);
printf("fname = \"%s\"\n", fname);
printf("sname = \"%s\"\n", sname);
if (optind < argc) /* these are the arguments after the command-line options */
for (; optind < argc; optind++)
printf("argument: \"%s\"\n", argv[optind]);
else {
printf("no arguments left to process\n");
}
exit(0);
}
This example and more information is found here.

Parsing options having a common flag in C

I have a C program where I accept multiple arguments. Here, I have a common flag d for both data-store and disk. Is there a way that I can check for the flags in-order and get the value of store before I check with case d. I've tried various ways like adding a while loop before this to check for s and then enter this loop etc.
static void
ParseOptions(int argc, char* argv[])
{
int c, option_index;
int ind = 0;
while((c = getopt_long(argc, argv, "s:d:",
long_options, &option_index))!= -1) {
ind = optind;
switch(c) {
case 's':
optionStore = true;
store = strdup(optarg);
break;
case 'd':
if(strcmp(store,"datastore") == 0){
printf("In datastore\n");
datastore = strdup(optarg);
}
else if(strcmp(store,"disk") == 0){
printf("In disk\n");
disk = strdup(optarg);
}
break;
default:
exit(-1);
}
}
}
Not sure how to go about this.
You need to store optarg returned for flag d in a temporary variable, and use it after the loop exits to set either disk or datastore:
char *temp_disk_or_datastore;
while((c = getopt_long(argc, argv, "s:d:",
long_options, &option_index))!= -1) {
ind = optind;
switch(c) {
case 's':
optionStore = true;
store = strdup(optarg);
break;
case 'd':
temp_disk_or_datastore = strdup(optarg);
break;
default:
exit(-1);
}
}
if (store == NULL) {
printf("Missing storage option");
exit(-1);
}
if(strcmp(store,"datastore") == 0){
printf("In datastore\n");
datastore = temp_disk_or_datastore;
}
else if(strcmp(store,"disk") == 0){
printf("In disk\n");
disk = temp_disk_or_datastore;
}

getopt is not working for one of my parameters

I have to programm a TCP/UDP Server/Client software.
Possible arguments: -u: UDP -t: TCP -l Server -p: [Port] -h [IP]
I wrote a function printflags, to see if everything works fine.
The u-, t-, l- and p-Options work fine. But my IP is everytime NULL.
Where is the problem?
#include <ctype.h>
#include <stdio.h>
#include <getopt.h>
#include <stdlib.h>
#include <unistd.h>
int printflags(int, int, int, char *,char *);
int main(int argc, char *argv[]){
int uflag=0;
int tflag=0;
int lflag=0;
char *pvalue = NULL;
char *hvalue = NULL;
int c;
opterr = 0;
while((c = getopt (argc, argv, "utlhp:")) != -1)
{
switch(c)
{
case 'u':
uflag = 1;
break;
case 't':
tflag = 1;
break;
case 'l':
lflag = 1;
break;
case 'p':
pvalue = optarg;
break;
case 'h':
hvalue = optarg;
break;
case ':':
fprintf(stderr, "case :");
case '?':
if(optopt == 'p' || optopt == 'h')
fprintf(stderr, "Option '-%c' requires an argument.\n", optopt);
else if (isprint(optopt))
fprintf(stderr, "Unknown option character '-%c'.\n", optopt);
else
fprintf(stderr, "Unknown option character '%x'.\n", optopt);
return 1;
default:
abort();
}
}
printflags(uflag, tflag, lflag, pvalue, hvalue);
return 0;
}
int printflags(int uflag, int tflag, int lflag, char* pv, char *hv){
printf("-u UDP: %d\n", uflag);
printf("-t TCP: %d\n", tflag);
printf("-l Listen Socket - Server: %d\n", lflag);
printf("-p Port: %s\n", pv);
printf("-h IP: %s\n", hv);
return 0;
}
Your option string should be "utlh:p:". You need a colon after each letter that takes an optarg.
Your parameter to getopt() needs a colon after the h to signify that -h needs an argument.
while((c = getopt (argc, argv, "utlh:p:")) != -1)
// ^ --- here

C: No such file or directory

when I hard code chemin in open(chemin, O_RDONLY) to a file name, the program works, but when I leave if to open(chemin, O_RDONLY) I get No such file or directory.
Why isn't chemin in type_fichier used?
When i use printf("%s", chemin) in type_fichier I get '
int type_fichier(char * chemin) {
int fp;
if ((fp = open(chemin, O_RDONLY)) == -1) { perror(""); exit(0); }
struct stat fileStat;
if(fstat(fp, &fileStat) < 0)
return 1;
switch(fileStat.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
}
int main(int argc, char *argv[]) {
char fn = "file";
type_fichier(&fn);
}
Your mistake is here, you are allocating only 1 character for fn:
char fn = "file";
type_fichier(&fn);
You probably want:
const char *fn = "file";
type_fichier(fn);
You are using char variable for storing string literal instead of char array or an equivalent one.
int main(int argc, char *argv[]) {
char fn[] = "file";
type_fichier(fn);
}
there you go....

Resources