#include #include #include #include #include #include #include #include #include "ninac.h" using namespace std; static SSTRING secret; static const char *id = "std"; /* Like fgets, but will read a complete line whatever its length but will discard the extra bytes. toolong will be set to true if this happen */ static char *ninac_fgets(char *buf, unsigned size, FILE *fin, bool &toolong) { toolong = false; unsigned len = 0; size--; // Keep room for \0 while (1){ int car = fgetc(fin); if (car == EOF) break; if (len < size) buf[len] = car; len++; if (car == '\n') break; } if (len < size){ buf[len] = '\0'; }else{ buf[size] = '\0'; toolong = true; } return len > 0 ? buf : NULL; } static void ninaccmd_readone(_F_tcpconnect *c, FILE *fin, bool &end, bool &some_errors) { char buf[10000]; while (1){ bool toolong = false; if (ninac_fgets(buf,sizeof(buf),fin,toolong)==NULL){ end = true; break; }else if (toolong){ tlmp_error ("Line too long, ignored: %-100.100s...",buf); some_errors = true; // Loop to get another line }else{ // Send that line and wait for an answer strip_end (buf); //fprintf (stderr,"%lu %s\n",strlen(buf),buf); c->send (buf); c->send ("\n"); break; } } } static int execcmd ( const SSTRING &host, const SSTRING &port, const char *cmd, // Command to transmit FILE *fin) // Or stream of command to transmit { glocal int ret = -1; glocal const char *cmd = cmd; glocal FILE *fin = fin; glocal bool auth = false; glocal bool some_errors = false; (host.get(),port.get(),30); glocal.ret = 0; if (!glocal.auth){ SSTRING ver; line = str_copyword (ver,line); line = str_skip(line); if (ver != PROTO_VERSION){ tlmp_error ("Invalid server protocol: Received %s, expected %s" ,ver.c_str(),PROTO_VERSION); end = true; }else{ SSTRING answer; answer.setfrom (line); answer.strip_end(); answer.append (secret); misc_sha (answer.get(),answer); sendf ("%s %s\n",id,answer.get()); glocal.auth = true; if (glocal.cmd != NULL){ sendf ("%s\n",glocal.cmd); }else if (glocal.fin != NULL){ ninaccmd_readone(this,glocal.fin,end,glocal.some_errors); } } }else if (strncmp(line,"## ",3)==0){ glocal.ret = atoi(line+3); if (glocal.cmd != NULL){ end = true; }else{ ninaccmd_readone(this,glocal.fin,end,glocal.some_errors); } }else{ printf ("%s\n",line); } return glocal.some_errors ? -1 : glocal.ret; } static int execcmd ( const SSTRING &host, const SSTRING &port, const char *cmd) // Command to transmit { return execcmd (host,port,cmd,NULL); } int main (int argc, char *argv[]) { glocal int ret = -1; glocal SSTRING host = "unix:"; glocal SSTRING port = "/var/run/ninac.sock"; glocal SSTRING config = "/etc/ninac/ninaccmd.conf"; glocal const char *file = NULL; glocal.ret = (argc,argv); setproginfo ("ninaccmd",VERSION ,"Envoie des commandes au serveur ninac\n" "\n" "\tcheckpoint\n" "\tcleanvars\n" "\tcleartasks\n" "\tdumpstate\n" "\tdumpvars\n" "\tgetvar variable\n" "\tgetvar_ex variable(regexp)\n" "\tlistfunc\n" "\tliststate\n" "\tlisttarget\n" "\tlisttask\n" "\tquit\n" "\trun\n" "\tstop\n" "\tsettask task target state/:func ...\n" "\tunsettask task target\n" "\truntask task target\n" "\tsetpriority task target priority\n" "\tsetvar var valeur [timestamp]\n" "\tunsetvar var\n" "\tdone task target\n" "\tsetstate state\n" "\tunsetstate state\n" "\tsolver\n" "\twait_ex variable(regex) timestamp\n" "\tlock\n" "\tunlock\n"); setarg ('c',"config","Configuration file",glocal.config,false); setarg ('f',"fromfile","Read command to send from file (- = stdin)",glocal.file,false); setarg ('h',"host","TCP host or unix:",glocal.host,false); setarg ('p',"port","TCP port or unix socket" ,glocal.port,false); setarg ('i',"id","Identification of the process",id,false); fprintf (stderr,"%s\n",msg); syslog (LOG_ERR,"%s",msg); glocal int ret = 0; if (argc < 1 && glocal.file == NULL){ usage(); glocal.ret = -1; }else{ (glocal.config.c_str(),true); if (line[0] != '\0' && line[0] != '#'){ SSTRINGS words; int nb = str_splitline (line,'=',words); if (nb != 2){ tlmp_error ("%s: Invalid configuration on line %d: %s" ,glocal.config.c_str(),noline,line); glocal.ret = -1; }else{ const char *w1 = words.getitem(0)->get(); const char *w2 = words.getitem(1)->get(); if (strcmp(w1,"secret")==0){ secret = w2; }else if (strcmp(w1,"host")==0){ if (!glocal.tlmpprogram.opt_was_set("host")){ glocal.host = w2; } }else if (strcmp(w1,"port")==0){ if (!glocal.tlmpprogram.opt_was_set("port")){ glocal.port = w2; } }else{ tlmp_error ("%s: Invalid configuration on line %d: %s" ,glocal.config.c_str(),noline,line); glocal.ret = -1; } } } return 0; if (glocal.ret == -1){ tlmp_error ("Aborting"); glocal.ret = -1; }else if (secret.is_empty()){ tlmp_error ("No secret found in configuration file"); glocal.ret = -1; }else if (argc == 0 && glocal.file != NULL){ FILE *fin = strcmp(glocal.file,"-")==0 ? stdin : fopen (glocal.file,"r"); if (fin == NULL){ tlmp_error ("Can't open file %s (%s)",glocal.file ,strerror(errno)); }else{ glocal.ret = execcmd (glocal.host,glocal.port,NULL,fin); if (fin != stdin) fclose (fin); } }else if (argc == 1 && (strcmp(argv[0],"dumpvars")==0 || strcmp(argv[0],"dumpstate")==0 || strcmp(argv[0],"checkpoint")==0 || strcmp(argv[0],"clearvars")==0 || strcmp(argv[0],"cleartasks")==0 || strcmp(argv[0],"liststate")==0 || strcmp(argv[0],"listtask")==0 || strcmp(argv[0],"listfunc")==0 || strcmp(argv[0],"listtarget")==0 || strcmp(argv[0],"quit")==0 || strcmp(argv[0],"run")==0 || strcmp(argv[0],"solver")==0 || strcmp(argv[0],"stop")==0)){ glocal.ret = execcmd (glocal.host,glocal.port,argv[0]); }else if (argc == 1 && (strcmp(argv[0],"lock")==0 || strcmp(argv[0],"unlock")==0)){ tlmp_error ("Command lock or unlock are meaningless on the command line\n" "Their effect ends with the connection\n"); glocal.ret = -1; }else if (strcmp(argv[0],"getvar")==0 && argc==2){ string tmp = string("getvar") + " " + argv[1]; glocal.ret = execcmd (glocal.host,glocal.port ,tmp.c_str()); }else if (strcmp(argv[0],"getvar_ex")==0 && argc==2){ string tmp = string("getvar_ex") + " " + argv[1]; glocal.ret = execcmd (glocal.host,glocal.port ,tmp.c_str()); }else if (strcmp(argv[0],"setvar")==0 && argc==3){ string tmp = string("setvar") + " " + argv[1] + " \"" + argv[2] + "\""; glocal.ret = execcmd (glocal.host,glocal.port,tmp.c_str()); }else if (strcmp(argv[0],"setvar")==0 && argc==4){ string tmp = string("setvar") + " " + argv[1] + " \"" + argv[2] + "\" " + argv[3]; glocal.ret = execcmd (glocal.host,glocal.port,tmp.c_str()); }else if (strcmp(argv[0],"unsetvar")==0 && argc==2){ string tmp = string("unsetvar") + " " + argv[1]; glocal.ret = execcmd (glocal.host,glocal.port,tmp.c_str()); }else if (strcmp(argv[0],"done")==0 && argc == 4){ string tmp = string("done") + " " + argv[1] + " " + argv[2] + " " + argv[3]; glocal.ret = execcmd (glocal.host,glocal.port,tmp.c_str()); }else if (strcmp(argv[0],"setstate")==0 && argc == 2){ string tmp = string("setstate") + " " + argv[1]; glocal.ret = execcmd (glocal.host,glocal.port,tmp.c_str()); }else if (strcmp(argv[0],"unsetstate")==0 && argc == 2){ string tmp = string("unsetstate") + " " + argv[1]; glocal.ret = execcmd (glocal.host,glocal.port,tmp.c_str()); }else if (strcmp(argv[0],"settask")==0 && argc > 3){ string tmp = string("settask"); for (int i=1; i int ret = -1; if (glocal.file != NULL){ return main(0,NULL); }else{ usage(); } return ret; return glocal.ret; }