diff --git a/examples/smpfd.c b/examples/smpfd.c index 7e08162..1aa6ee0 100644 --- a/examples/smpfd.c +++ b/examples/smpfd.c @@ -4,15 +4,15 @@ * (c) Alexander Vdolainen 2013-2015 * (c) Alexander Vdolainen 2016 * - * libsxmp is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published + * libsxmp examples is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libsxmp is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. + * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see ."; @@ -27,8 +27,9 @@ * This implements a simple client-server topology, to see * more advanced technics check out other examples. * - * NOTE(win32): don't have a time to test it or fix it to - * make it works on windows, if you can - u're welcome. + * NOTE(win32): win32 is not a platform for any serious, + * except the games maybe... well, this code contains linux + * stuff (not sure about other *nixes) */ #include @@ -37,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -44,21 +46,22 @@ #include #include #include -#include +#include +#include #include #include +#include +#include +#include +#include +#include #include #include #include #include #include -#include -#include -#include -#include - #include "smpf.h" #include "smpfd_defs.h" #include "../config.h" @@ -73,6 +76,102 @@ static struct smpfd_ctx daemon_ctx; */ static usrtc_t *fulist; +/* misc functions */ +static char *__humansize(struct stat *buf) +{ + char *hsize = malloc(64); + int d = 0; + + if(!hsize) return NULL; + if(buf->st_size < 10*1024) snprintf(hsize, 64, "%ld", buf->st_size); + else if(buf->st_size >= 10*1024 && buf->st_size < 1024*1024) { /* KiB */ + d = buf->st_size % 1024; + if(!d) snprintf(hsize, 64, "%ldKiB", buf->st_size/1024); + else snprintf(hsize, 64, "%ld.%dKiB", buf->st_size/1024, d /= 102); + } else if(buf->st_size >= 1024*1024 && buf->st_size < 1024*1024*1024) { /* MiB */ + d = buf->st_size % (1024*1024); + if(!d) snprintf(hsize, 64, "%ldMiB", buf->st_size/(1024*1024)); + else snprintf(hsize, 64, "%ld.%dMiB", buf->st_size/(1024*1024), d /= 102); + } else { /* GiB */ + d = buf->st_size % (1024*1024*1024); + if(!d) snprintf(hsize, 64, "%ldGiB", buf->st_size/(1024*1024*1024)); + else snprintf(hsize, 64, "%ld.%dGiB", buf->st_size/(1024*1024*1024), d /= 102); + } + return hsize; +} + +static char *__humanmode(struct stat *buf) +{ + char *hmode = malloc(12); + char s = 0; + int i; + + if(!hmode) return NULL; + memset(hmode, 0, 12); + + for(i = 0; i < 10; i++) { + switch(i) { + case 0: + if(S_ISDIR(buf->st_mode)) s = 'd'; + else if(S_ISCHR(buf->st_mode)) s = 'c'; + else if(S_ISBLK(buf->st_mode)) s = 'b'; + else if(S_ISFIFO(buf->st_mode)) s = 'f'; + else if(S_ISLNK(buf->st_mode)) s = 'l'; + else if(S_ISSOCK(buf->st_mode)) s = 's'; + else s = '-'; + break; + } + hmode[i] = s; + } + + return hmode; +} + +static char *__humanuser(struct stat *buf) +{ + struct passwd pwd; + struct passwd *res; + char *pwdbuf, *huser; + size_t pwdlen; + + if((pwdlen = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) pwdlen = 16384; + + if(!(pwdbuf = malloc(pwdlen))) return NULL; + + getpwuid_r(buf->st_uid, &pwd, pwdbuf, pwdlen, &res); + if(!res) { + if(!(huser = malloc(12))) goto __fini; + snprintf(huser, 12, "%d", buf->st_uid); + } else huser = strdup(pwd.pw_name); + + __fini: + free(pwdbuf); + return huser; +} + +static char *__humangroup(struct stat *buf) +{ + struct group grp; + struct group *res; + char *pwdbuf, *hgroup; + size_t pwdlen; + + if((pwdlen = sysconf(_SC_GETGR_R_SIZE_MAX)) == -1) pwdlen = 16384; + + if(!(pwdbuf = malloc(pwdlen))) return NULL; + + getgrgid_r(buf->st_gid, &grp, pwdbuf, pwdlen, &res); + if(!res) { + if(!(hgroup = malloc(12))) goto __fini; + snprintf(hgroup, 12, "%d", buf->st_gid); + } else hgroup = strdup(grp.gr_name); + + __fini: + free(pwdbuf); + return hgroup; +} + + /* ok, here we will define out sxmp specific functions */ /* @@ -211,6 +310,74 @@ static int __getcwd(void *m, sexp_t *sx) return sxmsg_rreply(msg, rbuf_len); } +static int __stat(void *m, sexp_t *sx) +{ + sxmsg_t *msg = (sxmsg_t*)m; + sxlink_t *link = sxmsg_link(msg); + char *rbuf = sxmsg_rapidbuf(msg), *dirname = NULL, *odir = NULL; + char *hsize, *hmode, *huser, *hgroup; + sexp_t *isx; + size_t rbuf_len = 0; + int r = SXE_SUCCESS, idx, olen = 0, rc; + struct mp_session *session = (struct mp_session *)sxlink_getpriv(link); + struct stat statbuf; + + SEXP_ITERATE_LIST(sx, isx, idx) { + if(isx->ty == SEXP_LIST) r = SXE_BADPROTO; + if(idx > 1) r = SXE_BADPROTO; + + if(idx) dirname = isx->val; + } + if(r != SXE_SUCCESS || !dirname) goto __fail; + if(!strcmp(dirname, "./")) goto __fail; + if(!strlen(dirname) || !strcmp(dirname, ".")) goto __fail; + + + if(*dirname == '/') odir = strdup(dirname); + else { + olen = strlen(session->cwd) + strlen(dirname) + 2*sizeof(char); + odir = malloc(olen); + } + + if(!odir) { + r = SXE_ENOMEM; + goto __fail; + } + + if(olen) snprintf(odir, olen, "%s/%s", session->cwd, dirname); + + if(normalize_path(odir)) r = SXE_FAILED; + else { /* take stat of the file */ + rc = stat(odir, &statbuf); + if(rc) { + r = SXE_FAILED; + goto __fail; + } + /* make this human readable to reply for client */ + hsize = __humansize(&statbuf); + hmode = __humanmode(&statbuf); + huser = __humanuser(&statbuf); + hgroup = __humangroup(&statbuf); + /* create a reply */ + rbuf_len = snprintf(rbuf, MAX_RBBUF_LEN, "((:user %s)(:group %s)(:size %s)(:mode %s))", + huser, hgroup, hsize, hmode); + + /* free */ + if(odir) free(odir); + if(hsize) free(hsize); + if(hmode) free(hmode); + if(huser) free(huser); + if(hgroup) free(hgroup); + + /* reply rapidly */ + return sxmsg_rreply(msg, rbuf_len); + } + + __fail: + if(odir) free(odir); + return sxmsg_return(msg, r); +} + /* stream, simple entry nonamed streams */ /* dir listing stream */ typedef struct __dirlist_type { @@ -474,7 +641,7 @@ int main(int argc, char **argv) if(opt) goto __failaddrpc; opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, GETCWD_CMD, __getcwd); if(opt) goto __failaddrpc; - opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, STAT_CMD, __ping); + opt = sxmp_rpclist_add_function(fulist, READONLY_CHANNEL, STAT_CMD, __stat); if(opt) goto __failaddrpc; /* streams */ diff --git a/man/Makefile.am b/man/Makefile.am index 9329bce..e3d63d1 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -4,4 +4,4 @@ man_MANS = sxmsg_rreply.3 sxhub_create.3 sxhub_init.3 sxhub_destroy.3 sxhub_free sxhub_set_authcheck.3 sxhub_set_rpcvalidator.3 sxhub_set_channelcall.3 \ sxlink_master_accept.3 sxlink_connect.3 sxlink_close.3 sxchannel_open.3 \ sxchannel_close.3 sxmsg_send.3 sxmsg_send_pp.3 sxmsg_clean.3 sxmp_finalize.3 sxmsg_pulse.3 \ - sxmsg_reply.3 sxmsg_reply_pp.3 sxmsg_return.3 sxmsg_return_pp.3 + sxmsg_reply.3 sxmsg_reply_pp.3 sxmsg_return.3 sxmsg_return_pp.3 sxlink_connect_at.3 diff --git a/man/sxlink_connect_at.3 b/man/sxlink_connect_at.3 new file mode 120000 index 0000000..fbb96ce --- /dev/null +++ b/man/sxlink_connect_at.3 @@ -0,0 +1 @@ +sxlink_master_accept.3 \ No newline at end of file diff --git a/man/sxlink_master_accept.3 b/man/sxlink_master_accept.3 index 52b4f63..f517a5d 100644 --- a/man/sxlink_master_accept.3 +++ b/man/sxlink_master_accept.3 @@ -1,9 +1,11 @@ -.TH SXLINK_MASTER_ACCEPT 3 "20 July 2015" "SXMP" "SXMP Library Manual" +.TH SXLINK_MASTER_ACCEPT 3 "15 March 2016" "SXMP" "SXMP Library Manual" .SH NAME sxlink_master_accept \- Create a new link on already accept TCP connection on the master side. .br sxlink_connect \- Create link to the master. .br +sxlink_connect_at \- Create link to the master and assign private data. +.br sxlink_close \- Close link. .SH SYNOPSIS .B #include @@ -14,6 +16,10 @@ sxlink_t *sxlink_connect(sxhub_t *hub, const char *host, int port, const char *SSL_cert, const char *login, const char *passwd); +sxlink_t *sxlink_connect_at(sxhub_t *hub, const char *host, + int port, const char *SSL_cert, const char *login, + const char *passwd, const void *priv); + int sxlink_close(sxlink_t *co); .br @@ -44,6 +50,13 @@ trying to authorizated with username pointed by and password pointed by .B passwd .br +.B sxlink_connect_at +will do the same as +.B sxlink_connect +but also will assign a private data pointed by +.B priv +to be used by application implementation. +.br .B sxlink_close will close link pointed by .B co @@ -96,6 +109,6 @@ Using connection_link on master side with initialized connections set for master .SH COPYRIGHT This software licensed under GNU LGPL v3. See COPYING for further details. .br -(c) Askele Group 2013-2015 +(c) Askele Group 2013-2015 , (c) libsxmp dev team 2016 .SH AUTHOR -Alexander Vdolainen (vdo@askele.com) +Alexander Vdolainen (avdolainen@zoho.com)