summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am8
-rw-r--r--src/include/cache.h10
-rw-r--r--src/include/draw.h18
-rw-r--r--src/include/entry.h28
-rw-r--r--src/include/group.h40
-rw-r--r--src/include/read_cfg.h23
-rw-r--r--src/unix/cache.c35
-rw-r--r--src/unix/draw.c14
-rw-r--r--src/unix/read_cfg.c234
-rw-r--r--src/windows/cache.c30
-rw-r--r--src/windows/draw.c44
-rw-r--r--src/windows/read_cfg.c232
12 files changed, 716 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..561c767
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,8 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+LIBS = -lncurses
+
+bin_PROGRAMS = terminal_media_launcher
+
+terminal_media_launcher_SOURCES = cache.c draw.c read_cfg.c group.c entry.c unix/cache.c unix/draw.c unix/read_cfg.c
+terminal_media_launcher_LDADD = $(LIBS)
diff --git a/src/include/cache.h b/src/include/cache.h
new file mode 100644
index 0000000..0f5a6c4
--- /dev/null
+++ b/src/include/cache.h
@@ -0,0 +1,10 @@
+#ifndef CACHE_H
+#define CACHE_H
+
+void save_to_cache(int g_hover, int e_hover, int true_hover, char *cfg_name);
+
+void load_cache(int *g_hover, int *e_hover, int *true_hover, char *new_cfg_name);
+
+char *get_cache_path(bool create);
+
+#endif
diff --git a/src/include/draw.h b/src/include/draw.h
new file mode 100644
index 0000000..0a6baba
--- /dev/null
+++ b/src/include/draw.h
@@ -0,0 +1,18 @@
+#ifndef DRAW_H
+#define DRAW_H
+
+//These functions are needed by either unix/draw.c or windows/draw.c and must be supplied via a header file
+
+#define BUF_LEN 1024
+
+extern int g_hover;
+extern int e_hover;
+extern struct group **g;
+extern struct entry **e;
+
+char *get_launch();
+
+//functions that differ between os
+void launch();
+
+#endif
diff --git a/src/include/entry.h b/src/include/entry.h
new file mode 100644
index 0000000..51e43ca
--- /dev/null
+++ b/src/include/entry.h
@@ -0,0 +1,28 @@
+#ifndef ENTRY_H
+#define ENTRY_H
+
+typedef struct entry ENTRY;
+
+ENTRY *create_entry(char *new_name, char *new_path, bool force);
+
+void entry_rm(ENTRY *e, ENTRY *prev);
+
+void clear_entries(ENTRY *head);
+
+int entry_add(ENTRY *head, ENTRY *tail, ENTRY *add);
+
+ENTRY **get_entries(ENTRY *head, int count);
+
+char *get_ename(ENTRY *e);
+
+char *get_epath(ENTRY *e);
+
+bool get_eforce(ENTRY *e);
+
+void set_hide(ENTRY *e, bool status);
+
+bool get_hide(ENTRY *e);
+
+void entry_debug(ENTRY *trav);
+
+#endif
diff --git a/src/include/group.h b/src/include/group.h
new file mode 100644
index 0000000..ab6f409
--- /dev/null
+++ b/src/include/group.h
@@ -0,0 +1,40 @@
+#ifndef GROUP_H
+#define GROUP_H
+
+typedef struct group GROUP;
+
+GROUP *create_group(char *new_name);
+
+void group_add(char *gname, ENTRY *addme);
+
+void group_rm(GROUP *g);
+
+void clean_groups(); //remove empty groups from linked list
+
+GROUP **get_groups();
+
+char *get_gname(GROUP *g);
+
+char *get_gprog(GROUP *g);
+
+void set_gprog(GROUP *g, char *p);
+
+char *get_gflags(GROUP *g);
+
+void set_gflags(GROUP *g, char *p);
+
+ENTRY *get_ghead(GROUP *g);
+
+int get_ecount(GROUP *g);
+
+void set_ecount(GROUP *g, int new_count); //for use in hiding entries
+
+void set_gquotes(GROUP *g, bool b);
+
+bool get_gquotes(GROUP *g);
+
+int get_gcount();
+
+void group_debug(); //debug function to output all groups
+
+#endif
diff --git a/src/include/read_cfg.h b/src/include/read_cfg.h
new file mode 100644
index 0000000..b6b996f
--- /dev/null
+++ b/src/include/read_cfg.h
@@ -0,0 +1,23 @@
+#ifndef READ_CFG_H
+#define READ_CFG_H
+
+#define BUF_LEN 1024
+
+bool cfg_interp(char *path);
+bool get_sort();
+bool get_case_sensitivity();
+void refer_to_doc();
+void addme(char *path, char *group, bool force, char *name);
+int search_ch(char *str, char c);
+int search_last_ch(char *str, char c);
+int wild_cmp(char *wild, char *literal);
+char *strip_quotes(char *str);
+void error_mes(int ln, char *message);
+
+//functions that differ by os
+extern char sep;
+char *find_config();
+void mkconfig_wizard();
+void handle_fname(char *path, char *group, bool recurs, bool force, char *name, int ln);
+
+#endif
diff --git a/src/unix/cache.c b/src/unix/cache.c
new file mode 100644
index 0000000..e618602
--- /dev/null
+++ b/src/unix/cache.c
@@ -0,0 +1,35 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "../include/cache.h"
+#include "../include/read_cfg.h"
+
+char *get_cache_path(bool create){
+ char *path = malloc(sizeof(char) * BUF_LEN);
+ char *home = getenv("HOME");
+
+ assert(path != NULL);
+
+ if(home == NULL){
+ printf("Failed to save cache data: HOME is not set\n");
+ free(path);
+ return NULL;
+ }
+
+ //if create is asserted, build the path to the file
+ if(create){
+ sprintf(path, "%s%c.cache%c", home, sep, sep);
+ mkdir(path, 0755);
+
+ sprintf(path, "%s%c.cache%cterminal-media-launcher%c", home, sep, sep, sep);
+ mkdir(path, 0755);
+ }
+
+ sprintf(path, "%s%c.cache%cterminal-media-launcher%cdata.bin", home, sep, sep, sep);
+
+ return path;
+}
diff --git a/src/unix/draw.c b/src/unix/draw.c
new file mode 100644
index 0000000..ae7f758
--- /dev/null
+++ b/src/unix/draw.c
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "../include/draw.h"
+
+void launch(){
+ char full_command[BUF_LEN];
+
+ strcpy(full_command, get_launch());
+ strcat(full_command, " > /dev/null 2>&1 &");
+ system(full_command);
+
+ return;
+}
diff --git a/src/unix/read_cfg.c b/src/unix/read_cfg.c
new file mode 100644
index 0000000..4d98c82
--- /dev/null
+++ b/src/unix/read_cfg.c
@@ -0,0 +1,234 @@
+#include <assert.h>
+#include <dirent.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "../include/read_cfg.h"
+#include "../include/entry.h"
+
+char sep = '/';
+
+char *find_config(){
+ char *home = getenv("HOME");
+ char *path = malloc(sizeof(char) * BUF_LEN);
+ char choices[2][BUF_LEN];
+ int check_count = 2;
+ int i;
+
+ sprintf(choices[0], "%s%c.config%cterminal-media-launcher%cconfig", home, sep, sep, sep);
+ sprintf(choices[1], "%s%c.terminal-media-launcher%cconfig", home, sep, sep);
+
+ for(i = 0; i < check_count; i++){
+ path = choices[i];
+ printf("Checking for config at %s: ", choices[i]);
+ if(access(path, R_OK) == 0){
+ printf("Using config \"%s\"\n\n", path);
+ return path;
+ }
+ else printf("File does not exist\n");
+ }
+
+ //TODO no config exists, ask user if they want to autogenerate one
+ mkconfig_wizard(choices[0]);
+ path = choices[0];
+ return path;
+}
+
+void mkconfig_wizard(char *path){
+ char input;
+ FILE *fp;
+
+ char *home = getenv("HOME");
+
+ printf("\nNo configuration file found. Auto-generate one now at \"%s\"? [Y/n] ", path);
+ fflush(stdout);
+ scanf(" %c", &input);
+
+ if(input == 'n'){
+ printf("Configuration will not be auto-generated\n");
+ refer_to_doc();
+ exit(0);
+
+ }
+
+ printf("Generating configuration file at \"%s\"...\n", path);
+
+ //ensure directories have been created
+ if(home == NULL){
+ printf("Failed: HOME is NULL\n");
+ exit(1);
+ }
+
+ sprintf(path, "%s%c.config%c", home, sep, sep);
+ mkdir(path, 0755);
+
+ sprintf(path, "%s%c.config%cterminal-media-launcher%c", home, sep, sep, sep);
+ mkdir(path, 0755);
+
+ sprintf(path, "%s%c.config%cterminal-media-launcher%cconfig", home, sep, sep, sep);
+
+ //open file for writing, make sure non-NULL
+ fp = fopen(path, "w");
+ if(fp == NULL){
+ printf("Failed: \"%s\" could not be open for writing\n", path);
+ exit(1);
+ }
+
+ //write to file
+ fprintf(fp, "# This file was auto-generated by terminal-media-launcher. See docs/terminal-media-launcher-config.md or terminal-media-launcher-config(5) for documentation\n"
+ "# The default launcher is set to \"xdg-open\" which will open files based on the relevant default application set through xdg\n\n"
+ "# Recursively add files from %s%cMusic%c to Music group\n"
+ "addGroup Music\n"
+ "setLauncher Music xdg-open\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.aac Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.aiff Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.alac Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.au Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.flac Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.m4a Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.mp3 Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.ogg Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.pcm Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.wav Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.wma Music\n\n", home, sep, sep);
+ fprintf(fp, "# Recursively add files from %s%cPictures%c to Pictures group\n"
+ "addGroup Pictures\n"
+ "setLauncher Pictures xdg-open\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.epi Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.eps Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.eps2 Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.eps3 Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.epsf Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.epsi Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.ept Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.gif Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.gfa Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.giff Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.jpeg Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.jpg Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.png Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.svg Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.svgz Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.tif Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.tiff Pictures\n\n", home, sep, sep);
+ fprintf(fp, "# Recursively add files from %s%cVideos%c to Videos group\n"
+ "addGroup Videos\n"
+ "setLauncher Videos xdg-open\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.asf Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.avi Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.flv Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mk3d Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mkv Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mov Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mp4 Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.qt Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.webm Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.wmv Videos\n", home, sep, sep);
+
+ fclose(fp);
+ printf("done\nIt is highly recommended to further tweak the configuration file! [press any key to continue]");
+ fflush(stdout);
+ getchar();
+ getchar();
+
+ return;
+}
+
+//TODO augment to involve recurs
+//TODO could use some cleanup...
+void handle_fname(char *path, char *group, bool recurs, bool force, char *name, int ln){
+ ENTRY *new;
+ char *search; //pointer for traversing path
+ char full_path_cpy[BUF_LEN];
+ char relative_path_cpy[BUF_LEN];
+ char arg_cpy[BUF_LEN];
+ char auto_name[BUF_LEN];
+ int plen = strlen(path);
+ char *dirname;
+ char *local_arg; //for use in addR
+ DIR *dp;
+ struct dirent *fname;
+ int i;
+ char *error_p; //helper for complex error messages
+
+ assert(path != NULL && group != NULL);
+
+ if(path[0] == '\0' || group[0] == '\0'){
+ error_mes(ln, "Too few arguments for \"add\"");
+ return;
+ }
+
+ //address potential quotes
+ strcpy(full_path_cpy, strip_quotes(path));
+
+ //don't check that the path arg is valid when forced
+ if(force) addme(full_path_cpy, group, force, name);
+
+ //file is not recognized, perhaps it has a wildcard?
+ //TODO finish rewriting a more robust wildcard thingy
+ else if(access(full_path_cpy, F_OK) == -1){
+ i = search_ch(full_path_cpy, '*');
+ if(i > -1){
+ //look for a directory
+ while(full_path_cpy[i] != sep && (i >= 0)){
+ i--;
+ }
+ dirname = full_path_cpy;
+ strcpy(arg_cpy, full_path_cpy);
+ dirname[i+1] = '\0';
+ dp = opendir(dirname);
+
+ //the directory is real
+ if(dp != NULL){
+ while(fname = readdir(dp)){
+ relative_path_cpy[0] = '\0';
+ strcat(relative_path_cpy, dirname);
+ strcat(relative_path_cpy, fname->d_name);
+
+ //check if path is a file (and not a directory/symlink/etc.) and regex matches
+ if(fname->d_type == DT_REG && !(wild_cmp(&arg_cpy[i+1], fname->d_name))) addme(relative_path_cpy, group, force, name);
+
+ //if the recursive option was specified and the path is a directory, run handle_fname on this directory, but for security reasons, do not consider directories that start with a '.'
+ else if(recurs && fname->d_type == DT_DIR && fname->d_name[0] != '.'){
+ i = search_last_ch(arg_cpy, sep);
+ local_arg = &arg_cpy[i+1];
+ strcat(relative_path_cpy, &sep);
+ strcat(relative_path_cpy, local_arg);
+ handle_fname(relative_path_cpy, group, 1, 0, NULL, ln);
+ }
+
+ }
+
+ closedir(dp);
+ }
+
+ //directory is not real, report error to the user
+ else{
+ error_p = malloc(sizeof(char) * 1024);
+ sprintf(error_p, "\"%s\" bad path", dirname);
+ error_mes(ln, error_p);
+ free(error_p);
+ //printf("Error: \"%s\" bad path\n", dirname);
+ }
+ }
+
+ //path is not real, report error to the user
+ else{
+ error_p = malloc(sizeof(char) * 1024);
+ sprintf(error_p, "\"%s\" bad path", full_path_cpy);
+ error_mes(ln, error_p);
+ free(error_p);
+ }
+ }
+
+ //file name is okay
+ //FIXME does not take into account whether the argument is a file (could be a directory, symlink, etc.)
+ else addme(full_path_cpy, group, force, name);
+
+ return;
+}
diff --git a/src/windows/cache.c b/src/windows/cache.c
new file mode 100644
index 0000000..01db0ef
--- /dev/null
+++ b/src/windows/cache.c
@@ -0,0 +1,30 @@
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "../include/cache.h"
+#include "../include/read_cfg.h"
+
+char *get_cache_path(bool create){
+ char *path = malloc(sizeof(char) * BUF_LEN);
+ char *appdata = getenv("APPDATA");
+
+ if(appdata == NULL){
+ printf("Failed to save cache data: APPDATA is not set\n");
+ free(path);
+ return NULL;
+ }
+
+ //if create is asserted, build the path to the file
+ if(create){
+ sprintf(path, "%s%cterminal-media-launcher%c", appdata, sep, sep);
+ mkdir(path);
+ }
+
+ sprintf(path, "%s%cterminal-media-launcher%ccache.bin", appdata, sep, sep);
+
+ return path;
+}
diff --git a/src/windows/draw.c b/src/windows/draw.c
new file mode 100644
index 0000000..28bef68
--- /dev/null
+++ b/src/windows/draw.c
@@ -0,0 +1,44 @@
+#include <stdbool.h>
+#include <windows.h>
+
+#include "../include/draw.h"
+#include "../include/entry.h"
+#include "../include/group.h"
+
+void launch(){
+ char *program = get_gprog(g[g_hover]);
+ char *flags = get_gflags(g[g_hover]);
+ char *path = get_epath(e[e_hover]);
+ bool quotes = get_gquotes(g[g_hover]);
+ char file[BUF_LEN];
+ char params[BUF_LEN];
+
+ file[0] = '\0';
+
+ if(!(strcmp(program, "./"))){
+ strcat(file, "/C ");
+ strcat(file, "\"");
+ strcat(file, path);
+ strcat(file, "\"");
+ ShellExecute(NULL, NULL, "cmd.exe", file, NULL, SW_HIDE);
+ }
+
+ else{
+ if(quotes) strcat(file, "\"");
+ strcat(file, program);
+ if(quotes) strcat(file, "\"");
+
+ params[0] = '\0';
+ if(flags[0] != '\0'){
+ strcat(params, flags);
+ strcat(params, " ");
+ }
+ strcat(params, "\"");
+ strcat(params, path);
+ strcat(params, "\"");
+
+ ShellExecute(NULL, NULL, file, params, NULL, SW_SHOW);
+ }
+
+ return;
+}
diff --git a/src/windows/read_cfg.c b/src/windows/read_cfg.c
new file mode 100644
index 0000000..2a56ef8
--- /dev/null
+++ b/src/windows/read_cfg.c
@@ -0,0 +1,232 @@
+#include <assert.h>
+#include <dirent.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "../include/entry.h"
+#include "../include/read_cfg.h"
+
+char sep = '\\';
+
+char *find_config(){
+ char *appdata = getenv("APPDATA");
+ char *path = malloc(sizeof(char) * BUF_LEN);
+ int check_count = 1;
+ char choices[check_count][BUF_LEN];
+ int i;
+
+ sprintf(choices[0], "%s%cterminal-media-launcher%cconfig", appdata, sep, sep);
+
+ for(i = 0; i < check_count; i++){
+ path = choices[i];
+ printf("Checking for config at %s: ", choices[i]);
+ if(access(path, R_OK) == 0){
+ printf("Using config \"%s\"\n\n", path);
+ return path;
+ }
+ else printf("File does not exist\n");
+ }
+
+ //TODO no config exists, ask user if they want to autogenerate one
+ mkconfig_wizard(choices[0]);
+ path = choices[0];
+ return path;
+}
+
+void mkconfig_wizard(char *path){
+ char input;
+ FILE *fp;
+
+ char *home = getenv("USERPROFILE");
+ char *appdata = getenv("APPDATA");
+
+ printf("\nNo configuration file found. Auto-generate one now at \"%s\"? [Y/n] ", path);
+ fflush(stdout);
+ scanf(" %c", &input);
+
+ if(input == 'n'){
+ printf("Configuration will not be auto-generated\n");
+ refer_to_doc();
+ exit(0);
+
+ }
+
+ printf("Generating configuration file at \"%s\"...\n", path);
+
+ //ensure directories have been created
+ if(appdata == NULL){
+ printf("Failed: \%APPDATA\% is NULL\n");
+ exit(1);
+ }
+
+ if(home == NULL){
+ printf("Failed: \%USERPROFILE\% is NULL\n");
+ exit(1);
+ }
+
+ sprintf(path, "%s%cterminal-media-launcher%c", appdata, sep, sep);
+ mkdir(path);
+
+ sprintf(path, "%s%cterminal-media-launcher%cconfig", appdata, sep, sep);
+
+ //open file for writing, make sure non-NULL
+ fp = fopen(path, "w");
+ if(fp == NULL){
+ printf("Failed: \"%s\" could not be open for writing\n", path);
+ exit(1);
+ }
+
+ fprintf(fp, "# This file was auto-generated by terminal-media-launcher. See docs\\terminal-media-launcher-config.md or terminal-media-launcher-config(5) for documentation\n"
+ "# By default, no launcher is specified for any group. When no launcher is specified on the Windows build of terminal-media-launcher, media files will be opened with their default application.\n"
+ "# It is generally recommended to specify a launcher for groups containing media files using the \"setLauncher\" command\n\n"
+ "# Recursively add files from %s%cMusic%c to Music group\n"
+ "addGroup Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.aac Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.aiff Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.alac Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.au Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.flac Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.m4a Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.mp3 Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.ogg Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.pcm Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.wav Music\n", home, sep, sep);
+ fprintf(fp, "addR %s%cMusic%c*.wma Music\n\n", home, sep, sep);
+ fprintf(fp, "# Recursively add files from %s%cPictures%c to Pictures group\n"
+ "addGroup Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.epi Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.eps Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.eps2 Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.eps3 Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.epsf Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.epsi Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.ept Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.gif Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.gfa Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.giff Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.jpeg Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.jpg Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.png Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.svg Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.svgz Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.tif Pictures\n", home, sep, sep);
+ fprintf(fp, "addR %s%cPictures%c*.tiff Pictures\n\n", home, sep, sep);
+ fprintf(fp, "# Recursively add files from %s%cVideos%c to Videos group\n"
+ "addGroup Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.asf Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.avi Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.flv Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mk3d Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mkv Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mov Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.mp4 Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.qt Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.webm Videos\n", home, sep, sep);
+ fprintf(fp, "addR %s%cVideos%c*.wmv Videos\n", home, sep, sep);
+
+ fclose(fp);
+ printf("done\nIt is highly recommended to further tweak the configuration file! [press any key to continue]");
+ fflush(stdout);
+ getchar();
+ getchar();
+
+ return;
+}
+
+//TODO augment to involve recurs
+//TODO could use some cleanup...
+void handle_fname(char *path, char *group, bool recurs, bool force, char *name, int ln){
+ ENTRY *new;
+ char *search; //pointer for traversing path
+ char full_path_cpy[BUF_LEN];
+ char relative_path_cpy[BUF_LEN];
+ char arg_cpy[BUF_LEN];
+ char auto_name[BUF_LEN];
+ int plen = strlen(path);
+ char *dirname;
+ char *local_arg; //for use in addR
+ DIR *dp;
+ struct dirent *fname;
+ int i;
+ char *error_p; //helper for complex error messages
+
+ assert(path != NULL && group != NULL);
+
+ if(path[0] == '\0' || group[0] == '\0'){
+ error_mes(ln, "Too few arguments for \"add\"");
+ return;
+ }
+
+ //address potential quotes
+ strcpy(full_path_cpy, strip_quotes(path));
+
+ //don't check that the path arg is valid when forced
+ if(force) addme(full_path_cpy, group, force, name);
+
+ //file is not recognized, perhaps it has a wildcard?
+ //TODO finish rewriting a more robust wildcard thingy
+ else if(access(full_path_cpy, F_OK) == -1){
+ i = search_ch(full_path_cpy, '*');
+ if(i > -1){
+ //look for a directory
+ while(full_path_cpy[i] != sep && (i >= 0)){
+ i--;
+ }
+ dirname = full_path_cpy;
+ strcpy(arg_cpy, full_path_cpy);
+ dirname[i+1] = '\0';
+ dp = opendir(dirname);
+
+ //the directory is real
+ if(dp != NULL){
+ while(fname = readdir(dp)){
+ relative_path_cpy[0] = '\0';
+ strcat(relative_path_cpy, dirname);
+ strcat(relative_path_cpy, fname->d_name);
+
+ //Windows cannot tell file types (TODO), so just add relatively indiscriminantly
+ if(!(wild_cmp(&arg_cpy[i+1], fname->d_name))) addme(relative_path_cpy, group, force, name);
+
+ //if the recursive option was specified, run handle_fname on this directory, but for security reasons, do not consider directories that start with a '.'
+ else if(recurs && fname->d_name[0] != '.'){
+ i = search_last_ch(arg_cpy, sep);
+ local_arg = &arg_cpy[i+1];
+ strcat(relative_path_cpy, &sep);
+ strcat(relative_path_cpy, local_arg);
+ handle_fname(relative_path_cpy, group, 1, 0, NULL, ln);
+ }
+ }
+
+ closedir(dp);
+ }
+
+ //directory is not real, report error to the user
+ else if(!recurs){
+ error_p = malloc(sizeof(char) * 1024);
+ sprintf(error_p, "\"%s\" bad path", dirname);
+ error_mes(ln, error_p);
+ free(error_p);
+ //printf("Error: \"%s\" bad path\n", dirname);
+ }
+ }
+
+ //path is not real, report error to the user
+ else{
+ error_p = malloc(sizeof(char) * 1024);
+ sprintf(error_p, "\"%s\" bad path", full_path_cpy);
+ error_mes(ln, error_p);
+ free(error_p);
+ }
+ }
+
+ //file name is okay
+ //FIXME does not take into account whether the argument is a file (could be a directory, symlink, etc.)
+ else addme(full_path_cpy, group, force, name);
+
+ return;
+}