Is it possible to make command like arguments like below?
./exe FROM_FILE=true
Here in this case, how I expect in the program is, when FROM_FILE value is true, I wil take data from file and if false, I can take standard values. The other alternatives I find for the purpose is to use
-options
Simply pass arguments. But in this case I have to worry about the order of arguments.
This one just came to mind when doing a makefile.
$>cat makefile
exe :
echo ${FROM_FILE}
$>make FROM_FILE=true
echo true
true
$>
You can do
FROM_FILE=true ./exe
and then read the FROM_FILE environment variable from inside the app with the environ pointer or getenv(). See http://linux.die.net/man/7/environ
Of course it is possible! Something like this (untested):
int main(int argc, char **argv)
{
int FROM_FILE = 0;
const char *FROM_FILE_key = "FROM_FILE";
int i;
/* Iterate through all the arguments. */
for (i = 1; i < argc; ++i)
{
/* Look for the '='. If not there, skip this argument. */
char *eq = strchr(argv[i], '=');
if (!eq)
continue;
/* Compare the key. If not what we want, skip it. */
if (strncmp(argv[i], FROM_FILE_key, strlen(FROM_FILE_key)) != 0)
continue;
/* Parse the value. You probably want to make this more flexible
(true, 1, yes, y...)*/
if (strcmp(eq+1, "true") == 0)
FROM_FILE = 1;
}
printf("FROM_FILE=%s", FROM_FILE? "true" : "false");
}
Possible? Well, since make apparently does it (I haven't tried it myself), it's obviously possible. It might trip up some people because it's certainly an unusual syntax, though.
What you'd want to do then is probably to iterate over argv[], find any parameters on the form something=something, and do your magic. Maybe even zero them out after you are done with them, and then do something more normal like handing over the grunt work to getopt or a similar library.
One thing to consider, especially if you want this to be generic, is what to do when someone passes a file name to your application that contains a =, expecting that file name to be opened, processed or whatever it is your application does for a living.
EDIT: The more I think about it, the less a good idea it seems to break with common command line interface conventions. maybe you should read this: http://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html
have you tried environment variables?
you can do
FROM_FILE=true ./exe
and in exe.c:
[...]
char *file = getenv("FROM_FILE");
if (file == NULL)
*file = DEFAULT;
[...]
alternatively, for a more GNU-ish approach to command line interfaces, have a look at getopt, or argp. (http://www.gnu.org/software/libc/manual/html_node/Parsing-Program-Arguments.html#Parsing-Program-Arguments)
Related
While there is an easy way of using both file redirection and piping, as well as interactive user input reading , with main(), as shown in this C code snippet...
#define SIZ 1024
#include <stdio.h>
extern void do_something_with_the_array(float *a[], int *n);
int main(int argc, const char * argv[])
{
float f[SIZ];
int k = 0;
while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) {
k++;
}
do_something_with_the_array(f, k);
return 0;
}
… I'm not sure if there is a modern UNIX source compatible and easy way of programmatically achieving any of the three possibilities in a main() in C, depending on the context ?
interactive reading of a string of numbers as user input
reading of the same string of numbers as command line arguments
file redirection and piping
I understand piping and redirection "belong" to the shell which intercepts the program before it even starts executing, while command line arguments and interactive reading "belong" to the main() itself and therefore there may not be an easy way of doing this.
I see using stdin or file input or pipe input pretty self-explanatory. However, reading command line arguments is a different story. Here's a demo how I usually code it, but it looks kind of heavy-handed and hacked to me. Also, in more complicated scenarios with options, this could become a pretty messy piece of code. I'm also not sure how fail-safe or fool proof this is...
#define SIZ 1024
#include <stdio.h>
#include <stdlib.h>
extern void do_something_with_the_array(float *, int);
int main(int argc, const char * argv[])
{
float f[SIZ];
int k = 0;
if(argc > 2){
for(k = 0; k < argc - 1; k++)
f[k] = (float)atof(argv[k+1]);
}
else while ((scanf("%f", &f[k]) == 1)&&(k < SIZ))
k++;
do_something_with_the_array(f, k);
return 0;
}
Thanks in advance!
I do not know off-hand of a C library that will make the three specific cases you mentioned look the same (although someone who does, please answer because I'd like to know, too!). I think you're looking for something not unlike the diamond <> operator in Perl, but for individual arguments rather than files containing arguments.
I think #David Hoelzer has the right idea: handle the three cases separately. For example, when processing command-line or file arguments, don't generate "Enter a value" prompts that you might print for interactive input. For command-line processing, getopt is a good place to start.
Now, a challenge to you: Wrap those three operations in a library and make it open-source so the rest of us can benefit! :)
Quite a few programs do care if they're invoked with keyboard input vs. file input, including the shell itself.
Let us take /bin/sh as our first example. If you call it directly, it starts an interactive shell, but if you pipe something into it, it starts as a non-interactive reading shell. The main difference between the two is if it is not interactive, it doesn't display the $ prompt. However just in case it really is interactive, it can be started with the -i option to make it assume its interactive when it would normally decide otherwise.
The magic involved here is isatty(); see man 3 isatty.
In addition, some programs like to receive keyboard input while processing redirected standard input. There are two generally favored ways of doing this; either opening and reading from /dev/tty or reading standard error, depending on context. Most stuff in an interactively started pipeline doesn't have standard error redirected, so this tends to work well (reading a redirected standard error yields an error immediately as the handle isn't open for read). If you want to make it potentially fully automatable, you read standard error, otherwise you read /dev/tty.
I am building a Linux Shell, and my current headache is passing command line arguments to forked/exec'ed programs and system functions.
Currently all input is tokenized on spaces and new lines, in a global variable char * parsed_arguments. For example, the input dir /usa/folderb would be tokenized as:
parsed_arguments[0] = dir
parsed_arguments[1] = /usa/folderb
parsed_arguments tokenizes everything perfectly; My issue now is that i wish to only take a subset of parsed_arguments, which excludes the command/ first argument/path to executable to run in the shell, and store them in a new array, called passed_arguments.
so in the previous example dir /usa/folderb
parsed_arguments[0] = dir
parsed_arguments[1] = /usa/folderb
passed_arguments[0] = /usa/folderb
passed_arguments[1] = etc....
Currently I am not having any luck with this so I'm hoping someone could help me with this. Here is some code of what I have working so far:
How I'm trying to copy arguments:
void command_Line()
{
int i = 1;
for(i;parsed_arguments[i]!=NULL;i++)
printf("%s",parsed_arguments[i]);
}
Function to read commands:
void readCommand(char newcommand[]){
printf("readCommand: %s\n", newcommand);
//parsed_arguments = (char* malloc(MAX_ARGS));
// strcpy(newcommand,inputstring);
parsed = parsed_arguments;
*parsed++ = strtok(newcommand,SEPARATORS); // tokenize input
while ((*parsed++ = strtok(NULL,SEPARATORS)))
//printf("test1\n"); // last entry will be NULL
//passed_arguments=parsed_arguments[1];
if(parsed[0]){
char *initial_command =parsed[0];
parsed= parsed_arguments;
while (*parsed) fprintf(stdout,"%s\n ",*parsed++);
// free (parsed);
// free(parsed_arguments);
}//end of if
command_Line();
}//end of ReadCommand
Forking function:
else if(strstr(parsed_arguments[0],"./")!=NULL)
{
int pid;
switch(pid=fork()){
case -1:
printf("Fork error, aborting\n");
abort();
case 0:
execv(parsed_arguments[0],passed_arguments);
}
}
This is what my shell currently outputs. The first time I run it, it outputs something close to what I want, but every subsequent call breaks the program. In addition, each additional call appends the parsed arguments to the output.
This is what the original shell produces. Again it's close to what I want, but not quite. I want to omit the command (i.e. "./testline").
Your testline program is a sensible one to have in your toolbox; I have a similar program that I call al (for Argument List) that prints its arguments, one per line. It doesn't print argv[0] though (I know it is called al). You can easily arrange for your testline to skip argv[0] too. Note that Unix convention is that argv[0] is the name of the program; you should not try to change that (you'll be fighting against the entire system).
#include <stdio.h>
int main(int argc, char **argv)
{
while (*++argv != 0)
puts(*argv);
return 0;
}
Your function command_line() is also reasonable except that it relies unnecessarily on global variables. Think of global variables as a nasty smell (H2S, for example); avoid them when you can. It should be more like:
void command_Line(char *argv[])
{
for (int i = 1; argv[i] != NULL; i++)
printf("<<%s>>\n", argv[i]);
}
If you're stuck with C89, you'll need to declare int i; outside the loop and use just for (i = 1; ...) in the loop control. Note that the printing here separates each argument on a line on its own, and encloses it in marker characters (<< and >> — change to suit your whims and prejudices). It would be fine to skip the newline in the loop (maybe use a space instead), and then add a newline after the loop (putchar('\n');). This makes a better, more nearly general purpose debug routine. (When I write a 'dump' function, I usually use void dump_argv(FILE *fp, const char *tag, char *argv[]) so that I can print to standard error or standard output, and include a tag string to identify where the dump is written.)
Unfortunately, given the fragmentary nature of your readCommand() function, it is not possible to coherently critique it. The commented out lines are enough to elicit concern, but without the actual code you're running, we can't guess what problems or mistakes you're making. As shown, it is equivalent to:
void readCommand(char newcommand[])
{
printf("readCommand: %s\n", newcommand);
parsed = parsed_arguments;
*parsed++ = strtok(newcommand, SEPARATORS);
while ((*parsed++ = strtok(NULL, SEPARATORS)) != 0)
{
if (parsed[0])
{
char *initial_command = parsed[0];
parsed = parsed_arguments;
while (*parsed)
fprintf(stdout, "%s\n ", *parsed++);
}
}
command_Line();
}
The variables parsed and parsed_arguments are both globals and the variable initial_command is set but not used (aka 'pointless'). The if (parsed[0]) test is not safe; you incremented the pointer in the previous line, so it is pointing at indeterminate memory.
Superficially, judging from the screen shots, you are not resetting the parsed_arguments[] and/or passed_arguments[] arrays correctly on the second use; it might be an index that is not being set to zero. Without knowing how the data is allocated, it is hard to know what you might be doing wrong.
I recommend closing this question, going back to your system and producing a minimal SSCCE. It should be under about 100 lines; it need not do the execv() (or fork()), but should print the commands to be executed using a variant of the command_Line() function above. If this answer prevents you deleting (closing) this question, then edit it with your SSCCE code, and notify me with a comment to this answer so I get to see you've done that.
I am currently trying to get my program to work the way I want. I am currently at the point where I can open up any text file from the command line (an unlimited amount) and display them. I'd like to expand on this and have users enter phrases that format the displayed text. I have previously posted a similar question and I've gotten some great answers, but I cannot use getopt(). How else would it be possible to scan the command line for a "-w" and a number, so "-w5" and a "-s" with no number. Those are the only two things I'd like to be able to detect. I don't mind if statements, I was hoping for the shortest program in my friends, but at this point, I'd just like to get it done. Any ideas? Multiple if-statements was my friend's idea, I personally think this is unneeded, but if that's what I have to do... If anyone else has any ideas, that would be really useful. I just want my program to detect those two characters from the command line. I'm fairly new to C (I've only made a few programs), but I'm edger to learn and I have tried googling and trying this on my own, but being new to C, trying to find what I need through all the other text and jargon is difficult.
Anything will be useful, thanks.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int l = 1;
while(l != argc)
{
FILE *fp;
fp = fopen(argv[l], "rb");
l++;
if (fp != NULL)
{
int i = 1;
do
{
i = fgetc(fp);
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
}
void scanningForWS(int argc, char **argv)
{
}
You should look at plan9's ARGBEGIN and ARGEND macros in their libc.h file (at the very end of the file), to see how it's done (for an example of its usage, see arg(3)).
Alernatively, you can check the suckless implementation of this mechanism, which is very nice (I have re-implemented a version of it which parses arguments even after incorrect flags have been found, but it's not published anywhere. I can publish it if you need that).
The command line arguments are in argv, and since argv is an array, the only way to find a specific element inside of it is to iterate through, checking each element until you get the one you want. If you don't want to write all that yourself, it looks like C has a method called 'lfind' in search.h that does this. Here is an example of how to use it. Hope that helps :3.
Also, the GNU documentation for it
I have to write a shell program in c that doesn't use the system() function. One of the features is that we have to be able to use wild cards. I can't seem to find a good example of how to use glob or this fnmatch functions that I have been running into so I have been messing around and so far I have a some what working blog feature (depending on how I have arranged my code).
If I have a glob variable declared as a global then the function partially works. However any command afterwards produces in error. example:
ls *.c
produce correct results
ls -l //no glob required
null passed through
so I tried making it a local variable. This is my code right now:
int runCommand(commandStruct * command1) {
if(!globbing)
execvp(command1->cmd_path, command1->argv);
else{
glob_t globbuf;
printf("globChar: %s\n", globChar);
glob(globChar, GLOB_DOOFFS, NULL, &globbuf);
//printf("globbuf.gl_pathv[0]: %s\n", &globbuf.gl_pathv[0]);
execvp(command1->cmd_path, &globbuf.gl_pathv[0]);
//globfree(&globbuf);
globbing = 0;
}
return 1;
}
When doing this with the globbuf as a local, it produces a null for globbuf.gl_path[0]. Can't seem to figure out why. Anyone with a knowledge of how glob works know what might be the cause? Can post more code if necessary but this is where the problem lies.
this works for me:
...
glob_t glob_buffer;
const char * pattern = "/tmp/*";
int i;
int match_count;
glob( pattern , 0 , NULL , &glob_buffer );
match_count = glob_buffer.gl_pathc;
printf("Number of mathces: %d \n", match_count);
for (i=0; i < match_count; i++)
printf("match[%d] = %s \n",i,glob_buffer.gl_pathv[i]);
globfree( &glob_buffer );
...
Observe that the execvp function expects the argument list to end with a NULL pointer, i.e. I think it will be the easiest to create your own char ** argv copy with all the elements from the glob_buffer.gl_pathv[] and a NULL pointer at the end.
You are asking for GLOB_DOOFFS but you did not specify any number in globbuf.gl_offs saying how many slots to reserve.
Presumably as a global variable it gets initialized to 0.
Also this: &globbuf.gl_pathv[0] can simply be globbuf.gl_pathv.
And don't forget to run globfree(globbuf).
I suggest running your program under valgrind because it probably has a number of memory leaks, and/or access to uninitialized memory.
If you don't have to use * style wildcards I've always found it simpler to use opendir(), readdir() and strcasestr(). opendir() opens a directory (can be ".") like a file, readdir() reads an entry from it, returns NULL at the end. So use it like
struct dirent *de = NULL;
DIR *dirp = opendir(".");
while ((de = readdir(dirp)) != NULL) {
if ((strcasestr(de->d_name,".jpg") != NULL) {
// do something with your JPEG
}
}
Just remember to closedir() what you opendir(). A struct dirent has the d_type field if you want to use it, most files are type DT_REG (not dirs, pipes, symlinks, sockets, etc.).
It doesn't make a list like glob does, the directory is the list, you just use criteria to control what you select from it.
If I wanted to run a shell command in linux with a c program, I would use
system("ls");
Is there a way I can accomplish this in Wind River vxworks?
I found the below example but I'm wondering do I need to include vxworks header files for this to work? I assume I do, but how do I figure out which one?
Example:
// This function runs a shell command and captures the output to the
// specified file
//
extern int consoleFd;
typedef unsigned int (*UINTFUNCPTR) ();
extern "C" int shellToFile(char * shellCmd, char * outputFile)
{
int rtn;
int STDFd;
int outFileFd;
outFileFd = creat( outputFile, O_RDWR);
printf("creat returned %x as a file desc\n",outFileFd);
if (outFileFd != -1)
{
STDFd=ioGlobalStdGet(STD_OUT);
ioGlobalStdSet(STD_OUT,outFileFd);
rtn=execute(shellCmd);
if (rtn !=0)
printf("execute returned %d \n",outFileFd);
ioGlobalStdSet(STD_OUT,STDFd);
}
close(outFileFd);
return (rtn);
}
I found the code segment below worked for me. For some reason changing the globalStdOut didn't work. Also the execute function did not work for me. But my setting the specific task out to my file, I was able to obtain the data I needed.
/* This function directs the output from the devs command into a new file*/
int devsToFile(const char * outputFile)
{
int stdTaskFd;
int outputFileFd;
outputFileFd = creat( outputFile, O_RDWR);
if (outputFileFd != ERROR)
{
stdTaskFd = ioTaskStdGet(0,1);
ioTaskStdSet(0,1,outputFileFd);
devs();
ioTaskStdSet(0,1,stdTaskFd);
close(outputFileFd);
return (OK);
}
else
return (ERROR);
}
If this is a target/kernel shell (i.e. running on the target itself), then remember that all the shell commands are simply translated to function calls.
Thus "ls" really is a call to ls(), which I believe is declared in dirLib.h
I think that the ExecCmd function is what you are looking for.
http://www.dholloway.com/vxworks/6.5/man/cat2/ExecCmd.shtml
As ever, read the documentation. ioLib.h is required for most of the functions used in that example, and stdio.h of course for printf().
As to the general question of whether you need to include any particular headers for any code to compile, you do need to declare all symbols used, and generally that means including appropriate headers. The compiler will soon tell you about any undefined symbols, either by warning or error (in C89/90 undefined functions are not an error, just a bad idea).