From 001d2878c3715da32da0da6bbecdf1ac810cde01 Mon Sep 17 00:00:00 2001 From: SANO Masatoshi Date: Wed, 30 Jul 2014 03:09:01 +0900 Subject: [PATCH] first commit --- AUTHORS | 0 ChangeLog | 0 Makefile.am | 2 + NEWS | 0 README | 0 configure.ac | 30 +++++ src/Makefile.am | 3 + src/archive.c | 176 ++++++++++++++++++++++++ src/cmd_install.c | 300 +++++++++++++++++++++++++++++++++++++++++ src/cmd_run.c | 71 ++++++++++ src/cmd_version.c | 10 ++ src/download.c | 51 +++++++ src/lsp.c | 92 +++++++++++++ src/opt.c | 210 +++++++++++++++++++++++++++++ src/opt.h | 29 ++++ src/util.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++ src/util.h | 24 ++++ 17 files changed, 1335 insertions(+) create mode 100644 AUTHORS create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 configure.ac create mode 100644 src/Makefile.am create mode 100644 src/archive.c create mode 100644 src/cmd_install.c create mode 100644 src/cmd_run.c create mode 100644 src/cmd_version.c create mode 100644 src/download.c create mode 100644 src/lsp.c create mode 100644 src/opt.c create mode 100644 src/opt.h create mode 100644 src/util.c create mode 100644 src/util.h diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e69de29 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..f268924 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = src + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..75e6097 --- /dev/null +++ b/configure.ac @@ -0,0 +1,30 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.69]) +AC_INIT([lsp],[0.0.0],snmsts@gmail.com) + +AM_CONFIG_HEADER(config.h) +AC_CONFIG_FILES([Makefile src/Makefile]) +AC_CONFIG_SRCDIR([src/lsp.c]) +AM_INIT_AUTOMAKE + +# Checks for programs. +AC_PROG_CC +#AC_PROG_INSTALL + +# Checks for libraries. + +AC_CHECK_LIB([curl], [curl_global_init],[],[AC_MSG_ERROR([libcurl development files required])]) + +AC_CHECK_LIB([archive], [archive_read_open_filename],[],[AC_MSG_ERROR([libarchive is needed to compile lsp])]) + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS(stdlib.h stdio.h sys/stat.h archive.h) + +# Checks for typedefs, structures, and compiler characteristics. + +# Checks for library functions. + +AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..c93121d --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,3 @@ +bin_PROGRAMS = lsp +lsp_SOURCES = lsp.c opt.c download.c util.c archive.c cmd_version.c cmd_install.c cmd_run.c +include_HEADERS = opt.h util.h diff --git a/src/archive.c b/src/archive.c new file mode 100644 index 0000000..aa59ce0 --- /dev/null +++ b/src/archive.c @@ -0,0 +1,176 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" + +static void errmsg(const char *); +static int extract(const char *filename, int do_extract, int flags,const char* outputpath); +static int copy_data(struct archive *, struct archive *); +static void msg(const char *); + +static int verbose = 0; + +int cmd_tar(int argc, const char **argv) +{ + const char *filename = NULL; + const char *outputpath = NULL; + int compress, flags, mode, opt; + + (void)argc; + mode = 'x'; + verbose = 0; + compress = '\0'; + flags = ARCHIVE_EXTRACT_TIME; + /* Among other sins, getopt(3) pulls in printf(3). */ + argv--; + while (*++argv != NULL && **argv == '-') { + const char *p = *argv + 1; + while ((opt = *p++) != '\0') { + switch (opt) { + case 'f': + if (*p != '\0') + filename = p; + else + filename = *++argv; + p += strlen(p); + break; + case 'C': + if (*p != '\0') + outputpath = p; + else + outputpath = *++argv; + p += strlen(p); + break; + case 'p': + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + break; + case 't': + mode = opt; + break; + case 'v': + verbose++; + break; + case 'x': + mode = opt; + break; + } + } + } + switch (mode) { + case 't': + extract(filename, 0, flags,outputpath); + break; + case 'x': + extract(filename, 1, flags,outputpath); + break; + } + + return (0); +} + +static int +extract(const char *filename, int do_extract, int flags,const char* outputpath) +{ + struct archive *a; + struct archive *ext; + struct archive_entry *entry; + int r; + + a = archive_read_new(); + ext = archive_write_disk_new(); + archive_write_disk_set_options(ext, flags); + archive_read_support_filter_bzip2(a); + archive_read_support_filter_gzip(a); + archive_read_support_format_tar(a); +#ifndef NO_LOOKUP + archive_write_disk_set_standard_lookup(ext); +#endif + if (filename != NULL && strcmp(filename, "-") == 0) + filename = NULL; + if ((r = archive_read_open_filename(a, filename, 10240))) { + errmsg(archive_error_string(a)); + errmsg("\n"); + exit(r); + } + for (;;) { + r = archive_read_next_header(a, &entry); + if (r == ARCHIVE_EOF) + break; + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(a)); + errmsg("\n"); + exit(EXIT_FAILURE); + } + if (verbose && do_extract) + msg("x "); + if (verbose || !do_extract) + msg(archive_entry_pathname(entry)); + if(outputpath) { + char* p=s_cat2(q(outputpath),q(archive_entry_pathname(entry))); + archive_entry_copy_pathname(entry,p); + s(p); + } + + if (do_extract) { + r = archive_write_header(ext, entry); + if (r != ARCHIVE_OK) + errmsg(archive_error_string(a)); + else + copy_data(a, ext); + } + + if (verbose || !do_extract) + msg("\n"); + } + archive_read_close(a); + archive_read_free(a); +} + +static int +copy_data(struct archive *ar, struct archive *aw) +{ + int r; + const void *buff; + size_t size; + int64_t offset; + + for (;;) { + r = archive_read_data_block(ar, &buff, &size, &offset); + if (r == ARCHIVE_EOF) { + errmsg(archive_error_string(ar)); + return (ARCHIVE_OK); + } + if (r != ARCHIVE_OK) + return (r); + r = archive_write_data_block(aw, buff, size, offset); + if (r != ARCHIVE_OK) { + errmsg(archive_error_string(ar)); + return (r); + } + } +} + +static void +msg(const char *m) +{ + int ret=write(1, m, strlen(m)); +} + +static void +errmsg(const char *m) +{ + int ret; + if (m != NULL) { + ret=write(2, m, strlen(m)); + } +} diff --git a/src/cmd_install.c b/src/cmd_install.c new file mode 100644 index 0000000..348eb4e --- /dev/null +++ b/src/cmd_install.c @@ -0,0 +1,300 @@ +#include +#include +#include "util.h" + +static int in_resume=0; +static char *flags =NULL; +typedef int (*install_cmds)(char* impl,char* version); +install_cmds *cmds=NULL; + +int installed_p(char* impl,char* version) +{ + int ret; + char* i; + if(strcmp(impl,"sbcl-bin")==0){ + impl="sbcl"; + i=s_cat(homedir(),q("impls/"),q(impl),q("-"),q(version),q("/"),NULL); + } + ret=directory_exist_p(i); + s(i); + return ret; +} + +int install_running_p(char* impl,char* version) +{ + /* TBD */ + return 0; +} + +int start(char* impl,char* version) +{ + char* home= homedir(); + char* p; + ensure_directories_exist(home); + if(installed_p(impl,version)) { + printf("%s-%s are already installed.if you intend to reinstall by (TBD).\n",impl,version); + return 0; + } + + if(install_running_p(impl,version)) { + printf("It seems running installation process for $1-$2.\n"); + return 0; + } + if(strcmp(impl,"sbcl")==0 && NULL==get_opt("sbcl-compiler")) { + printf("compiler variable 'sbcl-compiler' should be specified"); + return 0; + } + /*trap "exit 1" HUP INT PIPE QUIT TERM*/ + /*trap "rm -f $CIM_HOME/tmp/$1-$2.lock" EXIT*/ + p=cat(home,"tmp/",impl,"-",version,"/",NULL); + ensure_directories_exist(p); + s(p); + + p=cat(home,"tmp/",impl,"-",version,".lock",NULL); + touch(p); + s(p); + s(home); + return 1; +} + +char* bz2distp(char* impl) +{ + /* TBD rename function */ + if(strcmp(impl,"sbcl")==0|| + strcmp(impl,"sbcl-bin")==0|| + strcmp(impl,"alisp")==0) { + return "bz2"; + } + return "gz"; +} + +char* get_default_version(char* impl) +{ + /* TBD */ + if(strcmp(impl,"sbcl")==0) { + return q("1.2.1"); + }else if(strcmp(impl,"sbcl-bin")==0) { + return s_cat(get_default_version("sbcl"),q("-"),uname_m(),q("-"),uname(),NULL); + } +} + +char* get_download_path(char** impl,char** version) +{ + if(strcmp(*impl,"sbcl")==0 && *version) { + return cat("http://sourceforge.net/projects/sbcl/files/sbcl/",*version, + "/sbcl-",*version,"-source.tar.bz2",NULL); + }else if(strcmp(*impl,"sbcl-bin")==0) { + return q("http://prdownloads.sourceforge.net/sbcl/sbcl-1.2.1-x86-64-linux-binary.tar.bz2"); + } + return NULL; +} + +int download(char* impl,char* version) +{ + char* home= homedir(); + char* url; + char* impl_archive; + printf("Donwloading archive.\n"); + url=get_download_path(&impl,&version); + if(url) { + impl_archive=cat(home,"archives/",impl,"-",version,".tar.",bz2distp(impl),NULL); + ensure_directories_exist(impl_archive); + + /* pipe connect for logging cim_with_output_control */ + if(download_simple(url,impl_archive,0)) { + printf("Failed to Download.\n"); + return 0; + /* fail */ + }else{ + printf("download done:%s\n",url); + } + } + s(impl_archive); + s(url); + s(home); + return 1; +} + +int expand(char* impl,char* version) +{ + char* home= homedir(); + char* argv[5]={"-xf",NULL,"-C",NULL,NULL}; + int argc=4; + char* archive; + char* dist_path; + + archive=cat(impl,"-",version,".tar.",bz2distp(impl),NULL); + if(strcmp(impl,"sbcl-bin")==0) { + impl="sbcl"; + }else { + } + version=q(version); + dist_path=cat(home,"src/",impl,"-",version,"/",NULL); + + printf("Extracting archive. %s to %s\n",archive,dist_path); + + delete_directory(dist_path,1); + ensure_directories_exist(dist_path); + + /* pipe connect for logging cim_with_output_control */ + argv[1]=cat(home,"archives/",archive,NULL); + argv[3]=cat(home,"src/",NULL); + cmd_tar(argc,argv); + + s(argv[1]); + s(argv[3]); + s(dist_path); + s(archive); + s(home); + s(version); + return 1; +} + +int configure(char* impl,char* version) +{ + char* home= homedir(); + char* confgcache= cat(home,"/src/",impl,"-",version,"/src/confg.cache",NULL); + char* cd; + char* configure; + int ret; + if(in_resume) { + delete_file(confgcache); + } + if(flags==NULL) { + flags=q(""); + } + if(strcmp("gcl",impl)==0) { + flags=s_cat(flags,q(" --enable-ansi")); + } + if(strcmp("ecl",impl)==0 ||strcmp("ecl",impl)==0 || strcmp("clisp",impl)==0) { + flags=s_cat(flags,q(" --mandir="),q(home),q("/share/man")); + } + printf("Configuring %s-%s\n",impl,version); + cd=cat(home,"src/",impl,"-",version,NULL); + printf ("cd:%s\n",cd); + change_directory(cd); + /* pipe connect for logging cim_with_output_control */ + configure=cat("./configure ",flags," --prefix=",home,"/impls/",impl,"-",version,NULL); + ret=system(configure); + s(configure); + s(cd); + s(confgcache); + s(home); +} + +/*int sbcl_ensure_impl(char* impl,char* version) { + int ret=1; + char* bin_version; + printf((bin_version=q("Finding Lisp impl to build sbcl.\n"))); + char* sbcl_bin_url=get_download_path("sbcl-bin",bin_version); + if(sbcl_bin_url){ + if(!directory_exist_p()) { + + } + s(sbcl_bin_url); + }else { + printf("can't download sbcl\n"); + ret=0; + } + s(bin_version); + return ret; +} +*/ + +int sbcl_make(char* impl,char* version) { + char* home=homedir(); + char* src=cat(home,"src/",impl,"-",version,NULL); + char* cmd=cat("sh make.sh \"","sbcl","\" ","--prefix=\"",home,"impls/",impl,"-",version,"\"",NULL); + printf("Building %s-%s\n",impl,version); + change_directory(src); + printf("cmd:%s\n",cmd); + system(cmd); + /* pipe connect for logging cim_with_output_control */ + s(home),s(src),s(cmd); +} + +int sbcl_install(char* impl,char* version) { +#ifndef _WIN32 + int ret=1; + char* home= homedir(); + if(strcmp(impl,"sbcl-bin")==0) { + impl="sbcl"; + } + char* impl_path= cat(home,"impls/",impl,"-",version,NULL); + char* src=cat(home,"src/",impl,"-",version,NULL); + char* sbcl_home=cat(impl_path,"/lib/sbcl",NULL); + char* install_root=q(impl_path); + impl="sbcl"; + printf("installing %s-%s\n",impl,version); + ensure_directories_exist(impl_path); + printf("cd:%s\n",src); + change_directory(src); + setenv("SBCL_HOME",sbcl_home,1); + setenv("INSTALL_ROOT",install_root,1); + if(system("sh install.sh")==-1) { + ret=0; + } + s(home); + s(impl_path); + s(src); + s(sbcl_home); + s(install_root); + return ret; +#else +#error not implemented. +#endif +} + +install_cmds install_full[]={ + start, + download, + expand, + configure, + NULL +}; +install_cmds install_sbcl_full[]={ + start, + download, + expand, + sbcl_make, + sbcl_install, + NULL +}; + +install_cmds install_sbcl_bin_full[]={ + start, + download, + expand, + sbcl_install, + NULL +}; + +int cmd_install(int argc,char **argv) +{ + int ret=1; + if(argc!=0) { + char* impl=q(argv[0]); + char* version=NULL; + if(strcmp(impl,"sbcl-bin")==0) { + cmds=install_sbcl_bin_full; + }else if(strcmp(impl,"sbcl")==0) { + cmds=install_sbcl_full; + }else { + printf("%s is not implemented for install.\n",impl); + exit(EXIT_FAILURE); + } + if(argc==1) { + version=get_default_version(impl); + }else { + version=q(argv[1]); + } + for(;*cmds&&ret;++cmds) { + ret=(*cmds)(impl,version); + } + s(version); + }else { + printf("what would you like to install?\n"); + exit(EXIT_FAILURE); + } + return ret; +} diff --git a/src/cmd_run.c b/src/cmd_run.c new file mode 100644 index 0000000..dfab100 --- /dev/null +++ b/src/cmd_run.c @@ -0,0 +1,71 @@ +#include +#include +#include "util.h" +#include "opt.h" + +int cmd_run(int argc,char **argv) +{ + int ret=1; + char* impl; + char* version; + char* home=homedir(); + int pos; + impl=get_opt("impl"); + if(impl && (pos=position_char("/",impl))!=-1) { + version=subseq(impl,pos+1,0); + impl=subseq(impl,0,pos); + }else { + version=get_opt("version"); + } + if(impl) { + char** arg=NULL; + char* bin=NULL; + int offset=0; + int i; + if(strcmp(impl,"sbcl-bin")==0) { + impl="sbcl"; + if(version) { + version=cat(q(version),q("-"),uname_m(),q("-"),uname(),NULL); + } + } + if(strcmp(impl,"sbcl")==0) { + char* impl_path= cat(home,"impls/",impl,"-",version,NULL); + int core_p=1; + + bin= cat(impl_path,"/bin/sbcl",NULL); + for(i=0;i + +int cmd_version(int argc,char **argv) +{ + printf("%s\n",PACKAGE_STRING); + return 0; +} diff --git a/src/download.c b/src/download.c new file mode 100644 index 0000000..d7d3bb5 --- /dev/null +++ b/src/download.c @@ -0,0 +1,51 @@ +#include +#include +#include + +static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) +{ + int written = fwrite(ptr, size, nmemb, (FILE *)stream); + return written; +} +extern char* homedir(void); +extern int ensure_directories_exist (char* path); + +int download_simple (char* uri,char* path,int verbose) +{ + CURL *curl; + CURLcode res; + FILE *bodyfile; + + curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, uri); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + + bodyfile = fopen(path,"wb"); + if (bodyfile == NULL) { + curl_easy_cleanup(curl); + return -1; + } + curl_easy_setopt(curl,CURLOPT_WRITEDATA,bodyfile); + res = curl_easy_perform(curl); + if(res != CURLE_OK && verbose) { + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(res)); + } + curl_easy_cleanup(curl); + } + fclose(bodyfile); + if(res != CURLE_OK) { + return -2; + }else { + return 0; + } +} + +int cmd_download (int argc,char **argv) { + if(argc>=2) { + return download_simple(argv[0],argv[1],1); + } + return 0; +} diff --git a/src/lsp.c b/src/lsp.c new file mode 100644 index 0000000..c5f0799 --- /dev/null +++ b/src/lsp.c @@ -0,0 +1,92 @@ +#include +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "opt.h" +#include "util.h" +char** argv_orig; +int argc_orig; +struct opts* global_opt; +struct opts* local_opt=NULL; + +extern int cmd_install(int argc,char **argv); +extern int cmd_download(int argc,char **argv); +extern int cmd_tar(int argc,char **argv); +extern int cmd_version(int argc,char **argv); +extern int cmd_opt(int argc,char **argv); +extern int cmd_run(int argc,char **argv); + +int cmd_notyet(int argc,char **argv) +{ + printf("notyet\n"); +} + +static struct sub_command commands[] = { + { "help", cmd_notyet}, + { "version", cmd_version}, + { "install", cmd_install}, + { "run",cmd_run}, + { "opt", cmd_opt}, + { "set", cmd_notyet}, + { "tar",cmd_tar}, + { "download",cmd_download}, +}; + +int main (int argc,char **argv) { + char **subargv=NULL; + char *subcmd=NULL; + int i; + int found=0; + struct sub_command* j; + argv_orig=argv; + argc_orig=argc; + char* path=s_cat(homedir(),q("config"),NULL); + global_opt=load_opts(path); + s(path); + if(argc==1) { + subcmd="help"; + subargv=NULL; + argc=0; + } else { + argc--; + argv++; + + while(argc>0 && argv[0][0]=='-') { + struct opts* opt=local_opt; + struct opts** opts=&opt; + if(argv[0][1]!='-' && argv[0][1]!='\0' && argc>1 && argv[1][0]!='-') { + set_opt(opts, &argv[0][1],(char*)argv[1],0); + argc--; + argv++; + }else{ + int index=1; + if(argv[0][1]=='-') ++index; + set_opt(opts, &argv[0][index],(char*)"1",0); + } + local_opt=*opts; + argc--; + argv++; + } + } + if(argc>0) { + subcmd=argv[0]; + subargv=&argv[1]; + argc--; + for(i=0;iname)==0) { + found=1; + j->call(argc,subargv); + break; + } + } + if(!found) { + printf("action %s not found\n",subcmd); + } + } + free_opts(global_opt); +} + +/* ./lsp tar -xvf ~/.lsp/archives/sbcl-1.2.1.tar.bz2 */ diff --git a/src/opt.c b/src/opt.c new file mode 100644 index 0000000..471e5f5 --- /dev/null +++ b/src/opt.c @@ -0,0 +1,210 @@ +#include +#include +#include "opt.h" +#include "util.h" + +void free_opts(struct opts* opt) +{ + void* tmp; + while(opt) { + if(opt->value) { + free((void*)opt->value); + opt->value=NULL; + } + if(opt->name) { + free((void*)opt->name); + opt->name=NULL; + } + tmp=opt->next; + opt->next=NULL; + tmp=opt; + opt=opt->next; + free(tmp); + } +} + +void print_opts(struct opts* opt) +{ + void* tmp; + char* typestr; + while(opt) { + switch(opt->type) { + case OPT_INT: + typestr="int"; + break; + case OPT_STRING: + typestr="string"; + break; + case OPT_BOOL: + typestr="bool"; + break; + default: + typestr="unknown"; + } + printf("%s=%s[%s]\n",opt->name,opt->value,typestr); + opt=opt->next; + } +} + +struct opts* load_opts(const char* path) { + FILE* fp; + char buf[1024]; + struct opts opt; + struct opts *cur=&opt; + + if((fp=fopen(path,"r"))==NULL) { + return NULL; + } + + while(fgets(buf,1024,fp) !=NULL) { + int i,mode,last; + char* str; + cur->next=(struct opts*)malloc(sizeof(struct opts)); + cur=cur->next; + cur->type=OPT_VOID; + cur->value=NULL; + cur->name=NULL; + cur->next=NULL; + for(i=0,mode=0,last=0;i<1024&&buf[i]!='\0';++i) { + if(buf[i]=='\t'||buf[i]=='\n') { + switch (mode++) { + case 0: + cur->name=subseq(buf,last,i); + break; + case 1: + cur->type=buf[i-1]-'0'; + break; + case 2: + cur->value=subseq(buf,last,i); + break; + } + last=i+1; + } + } + } + fclose (fp); + return opt.next; +} + +int save_opts(const char* path,struct opts* opt) { + FILE* fp; + void* tmp; + + if((fp=fopen(path,"w"))==NULL) { + return 0; + } + + while(opt) { + fprintf(fp,"%s\t%d\t%s\n",opt->name,opt->type,opt->value); + opt=opt->next; + } + fclose(fp); + return 1; +} + +int set_opt(struct opts** opts,const char* name,char* value,int type) +{ + int found=0; + struct opts* opt=*opts; + + while(opt) { + if(strcmp(opt->name,name)==0) { + found=1; + s((char*)opt->value); + opt->value=remove_char("\n\t",value); + if(type!=0) { + opt->type=type; + } + } + opt=opt->next; + } + if(!found) { + opt=(struct opts*)malloc(sizeof(struct opts)); + opt->next=*opts; + opt->type=type; + opt->name=(const char*)remove_char("\n\t",(char*)name); + opt->value=remove_char("\n\t",value); + *opts=opt; + } + return 1; +} + +int get_opt_type(struct opts* opt,const char* name) +{ + while(opt) { + if(strcmp(opt->name,name)==0) { + return opt->type; + } + opt=opt->next; + } + return 0; +} +char* _get_opt(struct opts* opt,const char* name) +{ + while(opt) { + if(strcmp(opt->name,name)==0) { + return (char*)opt->value; + } + opt=opt->next; + } + return NULL; +} + +char* get_opt(const char* name) +{ + char* ret=NULL; + ret=_get_opt(local_opt,name); + if(!ret) { + ret=_get_opt(global_opt,name); + } + return ret; +} + +int unset_opt(struct opts** opts,const char* name) +{ + struct opts *opt=*opts; + struct opts dummy; + struct opts *before=&dummy; + before->next=opt; + while(opt) { + if(strcmp(opt->name,name)==0) { + before->next=opt->next; + opt->next=NULL; + free_opts(opt); + opt=before; + } + before=opt; + opt=opt->next; + } + *opts=dummy.next; + return 1; +} + +int set_opts_int(struct opts* opts,const char* name,int value) { +} + +int cmd_opt(int argc, const char **argv) +{ + char* home=homedir(); + char* path=cat(home,"config",NULL); + struct opts* opt=global_opt; + struct opts** opts=&opt; + if(argc==0) { + printf("local:\n"); + print_opts(local_opt); + printf("global:\n"); + print_opts(opt); + }else if(strcmp(argv[0],"set")==0) { + if(argc>=3) { + set_opt(opts, argv[1],(char*)argv[2],0); + save_opts(path,opt); + } + }else if(strcmp(argv[0],"unset")==0) { + if(argc>=2) { + unset_opt(opts, argv[1]); + save_opts(path,opt); + } + } + s(home); + s(path); +} diff --git a/src/opt.h b/src/opt.h new file mode 100644 index 0000000..eab732c --- /dev/null +++ b/src/opt.h @@ -0,0 +1,29 @@ +#ifndef __OPT_H__ +#define __OPT_H__ + +typedef int (*sub_command_fnc)(int argc,char **argv); + +struct opts +{ + const char* name; + int type; + const char* value; + struct opts* next; +}; + +enum opt_type { + OPT_VOID, + OPT_INT, + OPT_STRING, + OPT_BOOL +}; +struct sub_command +{ + const char* name; + sub_command_fnc call; +}; +extern struct opts* global_opt; +extern struct opts* local_opt; +struct opts* load_opts(const char* path); +char* get_opt(const char* name); +#endif diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..df3b2d8 --- /dev/null +++ b/src/util.c @@ -0,0 +1,337 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#ifndef _WIN32 +#include +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#include + +char* q(const char* orig) { + char* ret= (char*)malloc(strlen(orig)+1); + strcpy(ret,orig); + return ret; +} + +void s(char* f) { + free(f); +} + +char* s_cat2(char* a,char* b) { + char* ret= (char*)malloc(strlen(a)+strlen(b)+1); + strcpy(ret,a); + strcat(ret,b); + s(a); + s(b); + return ret; +} + +char* s_cat(char* first,...) +{ + char* ret=first; + char* i; + va_list list; + va_start(list,first); + + for(i=va_arg( list , char*);i!=NULL;i=va_arg( list , char*)) { + ret=s_cat2(ret,i); + } + va_end(list); + + return ret; + +} + +char* cat(char* first,...) +{ + char* ret=q(first); + char* i; + va_list list; + va_start(list,first); + + for(i=va_arg( list , char*);i!=NULL;i=va_arg( list , char*)) { + ret=s_cat2(ret,q(i)); + } + va_end(list); + + return ret; +} +char* subseq(char* base,int beg,int end) +{ + int len=-1; + int i; + char* ret; + if(0>beg) { + if(0>len) { + len=strlen(base); + } + beg=len+beg; + } + if(0>=end) { + if(0>len) { + len=strlen(base); + } + end=len+end; + } + if(end<=beg) + return NULL; + ret=malloc(end-beg+1); + for(i=0;ipw_dir); + }else { + /* error? */ + return NULL; + } + + c=append_trail_slash(c); + return s_cat(c,q("."),q(PACKAGE),q("/"),NULL); +#endif +} + +char* pathname_directory(char* path) { + int i; + char* ret; + for(i=strlen(path)-1;i>=0&&path[i]!='/';--i); + ret=append_trail_slash(subseq(path,0,i)); + s(path); + return ret; +} + +char* ensure_directories_exist (char* path) { + int len = strlen(path); + if(len) { + for(--len;(path[len]!='/'||len==-1);--len); + path=subseq(path,0,len+1); + } + #ifndef _WIN32 + char* cmd=s_cat2(q("mkdir -p "),path); + #else + char* cmd=q(""); + #endif + if(system(cmd)==-1) { + printf("failed:%s\n",cmd); + return NULL; + }; + s(cmd); + return path; +} + +int directory_exist_p (char* path) { +#ifdef HAVE_SYS_STAT_H + struct stat sb; + int ret=0; + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { + ret=1; + } + return ret; +#else +# error not imprement directory_exist_p +#endif +} + +int change_directory(const char* path) { +#ifndef _WIN32 + return chdir(path); +#else + return _chdir(path); +#endif +} + +int delete_directory(char* pathspec,int recursive) { +#ifndef _WIN32 + char* cmd; + int ret; + if(recursive) { + cmd=s_cat2(q("rm -rf "),q(pathspec)); + }else { + cmd=s_cat2(q("rmdir "),q(pathspec)); + } + ret=system(cmd); + s(cmd); + if(ret==-1) { + return 0; + }else { + return 1; + } +#else + #error not implemented delete_directory +#endif +} + +int delete_file(char* pathspec) { +#ifndef _WIN32 + char* cmd; + int ret; + cmd=s_cat2(q("rm -f "),q(pathspec)); + ret=system(cmd); + s(cmd); + if(ret==-1) { + return 0; + }else { + return 1; + } +#else + #error not implemented delete_file +#endif +} + +void touch(char* path) { +#ifndef _WIN32 + char* cmd=s_cat2(q("touch "),q(path)); +#else + char* cmd=q(""); +#endif + if(system(cmd)==-1){ + }; + s(cmd); +} + +char* system_(char* cmd) { +#ifndef _WIN32 + FILE *fp; + char buf[256]; + char* s=q(""); + if((fp=popen(cmd,"r")) ==NULL) { + printf("Error:%s\n",cmd); + exit(EXIT_FAILURE); + } + while(fgets(buf,256,fp) !=NULL) { + s=s_cat2(s,q(buf)); + } + (void)pclose(fp); + return s; +#else +#endif +} + +char* uname(void) { + char *p=system_("uname"); + char *p2; + p2=remove_char("\r\n",p); + s(p); + return downcase(p2); +} + +char* uname_m(void) { + char *p=system_("uname -m"); + char *p2; + p2=remove_char("\r\n",p); + s(p); + return substitute_char('-','_',p2); +} +char* which(char* cmd) { + char* which_cmd=cat("command -v \"",cmd,"\"",NULL); + char* p=system_(which_cmd); + char* p2=remove_char("\r\n",p); + s(p),s(which_cmd); + return p2; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..e2cabf0 --- /dev/null +++ b/src/util.h @@ -0,0 +1,24 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ +char* q(const char* orig); +void s(char* f); +char* s_cat2(char* a,char* b); +char* s_cat(char* first,...); +char* cat(char* first,...); +char* subseq(char* base,int beg,int end); +char* remove_char(char* items,char* orig); +int position_char(char* items,char* seq); +char* upcase(char* orig); +char* homedir(void); +char* pathname_directory (char* path); +char* ensure_directories_exist (char* path); +int directory_exist_p (char* path); +int change_directory(const char* path); +int delete_directory(char* pathspec,int recursive); +int delete_file(char* pathspec); +void touch(char* path); +char* system_(char* cmd); +char* uname(void); +char* uname_m(void); +char* which(char* cmd); +#endif