Expanding on a *, using glob - c

I'm trying to expand *, so I've done some research and it seems that glob is the function to use. Just like linux when you type ls *.c, it will return you all the files that contains .c
I've got myself to start so I know that I need to malloc glob_t first, so here it is:
glob_t *globbuf = (glob_t*)malloc(sizeof(glob_t));
After this, I'm not sure how to work this out... going through internet has shown me some examples, but I don't get quite how it works. This is what I figured out:
if(glob("*.c",GLOB_DOOFFS,NULL,globbuf)) {
// what am i supposed to write in here?}
globbuf->gl_pathv[0] = "ls";

Here's a simple, straight-forward example that Works As Expected:
#include <glob.h>
#include <stdio.h>
int foo(char const * epath, int eerrno) { return 0; }
int main()
{
glob_t globbuf = {0};
glob("*.c", GLOB_DOOFFS, foo, &globbuf);
for (size_t i = 0; i != globbuf.gl_pathc; ++i)
{
printf("Found: %s\n", globbuf.gl_pathv[i]);
}
globfree(&globbuf);
}

Related

fuse parsing custom arguments in C

Using libfuse in my c-project, I 'm trying to add custom command-line arguments and handle them.
Here is an example on which I rely
https://github.com/libfuse/libfuse/wiki/Option-Parsing
First, I tried to do the argument for the mount point configuration -с <pathtoconfig>
I tried many ways to describe an option like -c --config conf= -o conf=, but ineffectually
Please, help me find the right path to solve the problem :(
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fuse.h>
#include "fuu_walk.h"
#include "jsmnload.h"
#define _JSMN_TOKEN_SIZE_ 256
#define _JSMN_BUFFER_SIZE_ 4096
#define MYFS_OPT(t, p, v) { t, offsetof(struct myfs_config, p), v }
struct myfs_config {
char *mystring;
} conf;
static struct fuse_opt myfs_opts[] = {
MYFS_OPT("-c %s", mystring, 1),
FUSE_OPT_END
};
jsmntok_t t[_JSMN_TOKEN_SIZE_];
char buf[_JSMN_BUFFER_SIZE_];
#if 0
= ""
"{\"root\": ["
"{\"path\":\"/\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ01\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ02\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE78\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE89\", \"mode\":\"drw-------\"}"
"]}";
#endif
static int myfs_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
struct myfs_config *ptr = (struct myfs_config *)data;
FILE *conf;
int rc = 0;
//I wanna check the argument on the each iteration of fuse_opt_parse. It's just the debug printf
printf("arg = %s\t string %s\t key = %i\n", arg, ptr->mystring, key);
switch (key) {
case 1:
conf = fopen(ptr->mystring, "r");
rc = read(fileno(conf), buf, _JSMN_BUFFER_SIZE_);
if ( jsmnload(buf, t, _JSMN_TOKEN_SIZE_, fuu_mkfstree) < 0 ) {
printf("Error load configuration\n");
exit(-1);
}
}
return 1;
}
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
memset(&conf, 0, sizeof(conf));
fuse_opt_parse(&args, &conf, myfs_opts, myfs_opt_proc);
return fuu_main(args.argc, args.argv);
}
Launch example
./appendix/fuu /mnt/cdrom/ -c /mnt/fs.json
As a result, printf in myfs_opt_proc function works only once and outputs
arg = /mnt/cdrom/ string (null) key = -2
Why myfs_opt_proc does not work for option -c?
I cannot comment so as an answer... looking at the reference you provided it seems to me that there is no option starting with -c. So result seems correct because fuse cannot parse this. Look at this snippet from your link:
fuse_opt_add_arg(&args, "-omodules=subdir,subdir=/foo");
You may try to announce options to fuse using -o.
Edit: Youre example differs from the linked one, try to add to following line to the defined struct:
FUSE_OPT_KEY("-c", "KEY_CONFIG");
and some line before
emum {
KEY_CONFIG
};
and parse it like this in youre myfs_opt_proc function
switch (key) {
case KEY_CONFIG:
/* ... */
. Summed up you missed declaring the -c key.

creating multiple recursive directories in c

I am completing cs50x (the edX (free) version of the Harvard cs50) course and am trying to be a bit tricky/lazy/test myself.
I am trying to use a C program to create all the directories I will need for my psets.
I have looked online and found that <sys/stat.h> includes the mkdir() function and therefore tried creating some nested loops to create all the necessary folders by doing something similar to mkdir {pset1,pset1/{standard,hacker},pset2,pset2{standard... to give me a directory structure like this:
pset1/Standard
pset1/Hacker
pset2/Standard
etc...
I came up with this:
#include <cs50.h>
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, string argv[])
{
for(int i = 1; i <=8; i++)
{
string dir = argv[1];
sprintf(dir,"%s%i", argv[1], i);
mkdir(dir, 0777);
for(int j = 0; j<2; j++)
{
string subDir[] = {"Standard","Hacker"};
sprintf(dir,"%s%i/%s", argv[1], i, subDir[j]);
mkdir(dir, 0777);
}
}
}
However, the program only creates pset1 and completes, there are no subfolders, no pset2 etc.
Yes, you're being lazy since you seem to have very little knowledge of C, yet try to program in it. :)
C is not Python, there is no string interpolation/formatting operator. You have to call a function, specificially snprintf(). Read that manual page.
Also, you can't create a bunch of nested directories with a single call to mkdir(). Read the manual page.
To create nested directories, you're either going to have to build each's absolute path (i.e. each successive time you call mkdir() the path will be longer than the previous time), or actually enter each directory as you create it, and go from there.
To create a full path you can call mkdir() recursivly like this:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkdirr(const char * path, const mode_t mode, const int fail_on_exist)
{
int result = 0;
char * dir = NULL;
do
{
if (NULL == path)
{
errno = EINVAL;
result = -1;
break;
}
if ((dir = strrchr(path, '/')))
{
*dir = '\0';
result = mkdirr(path, mode, fail_on_exist);
*dir = '/';
if (result)
{
break;
}
}
if (strlen(path))
{
if ((result = mkdir(path, mode)))
{
char s[PATH_MAX];
sprintf(s, "mkdir() failed for '%s'", path);
perror(s);
if ((EEXIST == result) && (0 == fail_on_exist))
{
result = 0;
}
else
{
break;
}
}
}
} while (0);
return result;
}
And then call mkdirr() like this;
int main(void)
{
char p[] = "test/1/2/3";
if (-1 == mkdirr(p, 0777, 0))
{
perror("mkdirr() failed()");
}
return 0;
}

User entered string run a particular function in c

Guys so I'm working on the web service assignment and I have the server dishing out random stuff and reading the uri but now i want to have the server run a different function depending on what it reads in the uri. I understand that we can do this with function pointers but i'm not exactly sure how to read char* and assign it to a function pointer and have it invoke that function.
Example of what I'm trying to do: http://pastebin.com/FadCVH0h
I could use a switch statement i believe but wondering if there's a better way.
For such a thing, you will need a table that maps char * strings to function pointers. The program segfaults when you assign a function pointer to string because technically, a function pointer is not a string.
Note: the following program is for demonstration purpose only. No bounds checking is involved, and it contains hard-coded values and magic numbers
Now:
void print1()
{
printf("here");
}
void print2()
{
printf("Hello world");
}
struct Table {
char ptr[100];
void (*funcptr)(void)
}table[100] = {
{"here", print1},
{"hw", helloWorld}
};
int main(int argc, char *argv[])
{
int i = 0;
for(i = 0; i < 2; i++){
if(!strcmp(argv[1],table[i].ptr) { table[i].funcptr(); return 0;}
}
return 0;
}
I'm gonna give you a quite simple example, that I think, is useful to understand how good can be functions pointers in C. (If for example you would like to make a shell)
For example if you had a struct like this:
typedef struct s_function_pointer
{
char* cmp_string;
int (*function)(char* line);
} t_function_pointer;
Then, you could set up a t_function_pointer array which you'll browse:
int ls_function(char* line)
{
// do whatever you want with your ls function to parse line
return 0;
}
int echo_function(char* line)
{
// do whatever you want with your echo function to parse line
return 0;
}
void treat_input(t_function_pointer* functions, char* line)
{
int counter;
int builtin_size;
builtin_size = 0;
counter = 0;
while (functions[counter].cmp_string != NULL)
{
builtin_size = strlen(functions[counter].cmp_string);
if (strncmp(functions[counter].cmp_string, line, builtin_size) == 0)
{
if (functions[counter].function(line + builtin_size) < 0)
printf("An error has occured\n");
}
counter = counter + 1;
}
}
int main(void)
{
t_function_pointer functions[] = {{"ls", &ls_function},
{"echo", &echo_function},
{NULL, NULL}};
// Of course i'm not gonna do the input treatment part, but just guess it was here, and you'd call treat_input with each line you receive.
treat_input(functions, "ls -laR");
treat_input(functions, "echo helloworld");
return 0;
}
Hope this helps !

Coredump in selfmade arrayList

i'm current working on a homework assesment where i'm programming a program ment to stitch textfiles with a piece of an ascii image to create a complete image of all the pieces. The way i intended to write the code is having a while loop looking through a directory finding the parts and adding them to an array. However in my AddFile method(or when i call it to be precise) i get a coredump.. I just started working with c so i dont know if it is very obvious to some of you why i get a coredump or more complicated. Also, i originaly wrote the addFile method to use and accept int's instead of the FILE type, at that point it worked perfectly without any coredumps so i suspect (but hey i might be wrong) that it went wrong when i tried to implement it with the FILE type.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int listSize;
int listCapacity;
FILE *fileStream;
}FileList;
void addFile(FileList* list, FILE file)
{
if((*list).listSize<(*list).listCapacity)
{
(*list).fileStream[(*list).listSize]=file;
(*list).listSize+=1;
}
else
{
FILE *tempArray = calloc((*list).listSize,sizeof(FILE));
for(int i=0; i<(*list).listSize; i++)
{
tempArray[i]=(*list).fileStream[i];
}
//Do something with array...
free((*list).fileStream);
(*list).listCapacity=((*list).listCapacity)*2;
(*list).fileStream=calloc((*list).listCapacity,sizeof(FILE));
for(int i=0; i<(*list).listSize; i++)
{
(*list).fileStream[i]=tempArray[i];
}
(*list).fileStream[(*list).listSize]=file;
(*list).listSize+=1;
free(tempArray);
}
}
int main()
{
FileList intList;
intList.listSize=0;
intList.listCapacity=1;
intList.fileStream=calloc(intList.listCapacity,sizeof(int));
int fileYcoord=0;
int fileXcoord=0;
while(1)
{
char fileName [100];
int fileNameLength=sprintf(fileName,"part_%02d-%02d",fileXcoord,fileYcoord);
FILE * pFile = fopen (fileName,"r");
if(pFile!=NULL)
{
printf("- ! found file: %s - name length : %d \n",fileName,fileNameLength);
addFile(&intList,*pFile);
fclose(pFile);
fileXcoord++;
}
else
{
if(fileXcoord!=0)
{
fileYcoord+=1;
fileXcoord=0;
}
else
{
break;
}
}
}
printf("size %d , %d",fileXcoord, fileYcoord);
free(intList.fileStream);
return 0;
}
The call to addFile() is dereferencing a FILE *, producing a value of type FILE. This is wrong, this is an opaque type and should always be handled by pointers.

How to change Keyboard Layout (a X11 API solution)

I want to change keyboard layout in Linux by programming,
What X11's API function does this?
I found one good solution.
It's a c++ class wrriten by Jay Bromley, that I can add to my app and using it.
source code
It's very easy to use:
#include "XKeyboard.h"
XKeyboard xkb;
std::string cGrpName=xkb.currentGroupName(); //return somethings like "USA"
std::string cGrpSymb=xkb.currentGroupSymbol(); //return somethings like "us"
xkb.setGroupByNum(0);//set keyboard layout to first layout in available ones
you can read source code and found some another useful functions.
for compiling standalone version you need to un-comments "int main" function present in "XKeyboard.cpp" (or write your own main.cpp) and use somethings like this:
g++ *.cpp -o getxkblayout -L/usr/lib -lX11
I'm not sure what the X11 library function is but setxkbmap is the bash command I use to achieve it. Maybe searching along these lines will find what you want (or at a pinch you could just execute the bash command).
Example
setxkbmap dvorak
setxkbmap us
EDIT:
After a strace of setxkbmap didn't turn up anything useful I suggest just calling:
system(“setxkbmap us”);
A pure X11 API solution should look something like this:
#include <stdio.h>
#include <X11/XKBlib.h>
int main() {
Display* _display;
char* displayName = "";
_display = XOpenDisplay(displayName);
XkbDescRec* _kbdDescPtr = XkbAllocKeyboard();
XkbGetNames(_display, XkbSymbolsNameMask, _kbdDescPtr);
Atom symName = _kbdDescPtr -> names -> symbols;
char* layoutString = XGetAtomName(_display, symName);
XCloseDisplay(_display);
printf("%s\n", layoutString);
}
Compile with -lX11 flag
This will print something like pc+us+inet(evdev) for English (USA) qwerty layout, pc+ru+us:2+inet(evdev) for Russian йцукен layout, pc+us(dvorak)+us:2+inet(evdev) for English dvorak layout.
Yesterday I was trying to make auto layuout switcher to EN for Google's xsecurelock. I tryed to find some existing solutions for X11 api, but...
So I decided to write my own with some help from S. Razi.
Here is the code: (run with gcc -lX11)
#include <stdio.h>
#include <stdlib.h>
#include <X11/XKBlib.h>
int main(){
Display* _display;
char* displayName = "";
_display = XOpenDisplay(displayName);
int _deviceId = XkbUseCoreKbd;
int i = 0;
int _groupCount = 0;
XkbDescRec* kbdDescPtr = XkbAllocKeyboard();
if (kbdDescPtr == NULL) {
printf("%s\n", "Failed to get keyboard description.");
return False;
}
kbdDescPtr->dpy = _display;
if (_deviceId != XkbUseCoreKbd) {
kbdDescPtr->device_spec = _deviceId;
}
XkbGetControls(_display, XkbAllControlsMask, kbdDescPtr);
XkbGetNames(_display, XkbSymbolsNameMask, kbdDescPtr);
XkbGetNames(_display, XkbGroupNamesMask, kbdDescPtr);
/* count groups */
Atom* groupSource = kbdDescPtr->names->groups;
if (kbdDescPtr->ctrls != NULL) {
_groupCount = kbdDescPtr->ctrls->num_groups;
} else {
_groupCount = 0;
while (_groupCount < XkbNumKbdGroups &&
groupSource[_groupCount] != 0) {
_groupCount++;
}
}
/* get group names */
Atom* tmpGroupSource = kbdDescPtr->names->groups;
Atom curGroupAtom;
char* groupName;
for (i = 0; i < _groupCount; i++) {
if ((curGroupAtom = tmpGroupSource[i]) != None) {
char* groupNameC = XGetAtomName(_display, curGroupAtom);
if (groupNameC == NULL) {
continue;
} else {
groupName = groupNameC;
char *temp = "English";
if (strncmp(temp, groupName, 7) == 0){
printf ("%s\n", groupName);
printf ("%d\n", i);
XkbLockGroup(_display, _deviceId, i);
XFree(groupNameC);
XCloseDisplay(_display);
}
return 0;
}
}
}
}
Here you can change char* temp = "English" to name of the group of your layout (exmp: "Russian"), and this simple code will switch your current layout :)

Resources