diff options
Diffstat (limited to '')
-rw-r--r-- | src/.sledjChisl.conf.lua | 1 | ||||
-rw-r--r-- | src/sledjchisl/sledjchisl.c | 898 |
2 files changed, 694 insertions, 205 deletions
diff --git a/src/.sledjChisl.conf.lua b/src/.sledjChisl.conf.lua index 6b8f29b..a817995 100644 --- a/src/.sledjChisl.conf.lua +++ b/src/.sledjChisl.conf.lua | |||
@@ -18,6 +18,7 @@ config = | |||
18 | ["Ttab"] = "SC"; | 18 | ["Ttab"] = "SC"; |
19 | ["loadAverageInc"] = 0.7; | 19 | ["loadAverageInc"] = 0.7; |
20 | ["simTimeOut"] = 45; -- seconds | 20 | ["simTimeOut"] = 45; -- seconds |
21 | ["bulkSims"] = 0; -- 0 means figure it out from number of CPUs. | ||
21 | ["webRoot"] = "/var/www/html"; | 22 | ["webRoot"] = "/var/www/html"; |
22 | ["webHost"] = "localhost"; | 23 | ["webHost"] = "localhost"; |
23 | ["URL"] = "sledjchisl.fcgi"; | 24 | ["URL"] = "sledjchisl.fcgi"; |
diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c index 42ed205..576f58f 100644 --- a/src/sledjchisl/sledjchisl.c +++ b/src/sledjchisl/sledjchisl.c | |||
@@ -2,18 +2,59 @@ | |||
2 | * | 2 | * |
3 | * Copyright 2020 David Seikel <sledjchisl@sledjhamr.org> | 3 | * Copyright 2020 David Seikel <sledjchisl@sledjhamr.org> |
4 | * Not in SUSv4. An entirely new invention, thus no web site either. | 4 | * Not in SUSv4. An entirely new invention, thus no web site either. |
5 | * | ||
6 | * Not using the usual taybox args system, coz it's not working as advertised. | ||
5 | 7 | ||
6 | USE_SLEDJCHISL(NEWTOY(sledjchisl, "m(mode):", TOYFLAG_USR|TOYFLAG_BIN)) | 8 | USE_SLEDJCHISL(NEWTOY(sledjchisl, "", TOYFLAG_USR|TOYFLAG_BIN)) |
7 | 9 | ||
8 | config SLEDJCHISL | 10 | config SLEDJCHISL |
9 | bool "sledjchisl" | 11 | bool "sledjchisl" |
10 | default y | 12 | default y |
11 | help | 13 | help |
12 | usage: sledjchisl [-m|--mode mode] | 14 | usage: sledjchisl [mode [arguments]] |
13 | 15 | ||
14 | opensim-SC management system. | 16 | opensim-SC management system. |
17 | |||
18 | Mode selects what sledjchisl will do - | ||
19 | create "Sim Name" x,y size | ||
20 | will create a sim. | ||
21 | start | ||
22 | start sim01 | ||
23 | start "Welcome sim" | ||
24 | will start a sim or everything. | ||
25 | backup | ||
26 | backup "Joan Smith" | ||
27 | backup sim01 | ||
28 | backup "Welcome sim" | ||
29 | will backup sim or everything. | ||
30 | gitar i "Joan Smith" | ||
31 | gitar o sim01 | ||
32 | gitar o "Welcome sim" | ||
33 | restart | ||
34 | restart sim01 | ||
35 | restart "Welcome sim" | ||
36 | will stop then start a sim, or everything. | ||
37 | status | ||
38 | status sim01 | ||
39 | status "Welcome sim" | ||
40 | will show status of a sim, or everything. | ||
41 | stop | ||
42 | stop sim01 | ||
43 | stop "Welcome sim" | ||
44 | will stop a sim, or everything. | ||
15 | */ | 45 | */ |
16 | 46 | ||
47 | /* | ||
48 | configs/sim01 - | ||
49 | backup-sim | ||
50 | start-sim | ||
51 | stop-sim | ||
52 | |||
53 | Currently they are all links to ../../current/scripts/start-sim, | ||
54 | they should be links to ../../current/bin/sledjchisl, | ||
55 | which itself is a link to ../src/build/toybox/generated/unstripped/toybox or ../src/build/toybox/toybox | ||
56 | |||
57 | */ | ||
17 | 58 | ||
18 | // TODO - figure out how to automate testing of this. | 59 | // TODO - figure out how to automate testing of this. |
19 | // Being all interactive and involving external web servers / viewers makes it hard. | 60 | // Being all interactive and involving external web servers / viewers makes it hard. |
@@ -54,7 +95,7 @@ extern char **environ; | |||
54 | // https://mariadb.com/kb/en/about-mariadb-connector-c/ Official docs. | 95 | // https://mariadb.com/kb/en/about-mariadb-connector-c/ Official docs. |
55 | // http://dev.mysql.com/doc/refman/5.5/en/c-api-function-overview.html MySQL docs. | 96 | // http://dev.mysql.com/doc/refman/5.5/en/c-api-function-overview.html MySQL docs. |
56 | // http://zetcode.com/db/mysqlc/ MySQL tutorial. | 97 | // http://zetcode.com/db/mysqlc/ MySQL tutorial. |
57 | #include <my_global.h> | 98 | //#include <my_global.h> |
58 | #include <mysql.h> | 99 | #include <mysql.h> |
59 | 100 | ||
60 | #include <qlibc.h> | 101 | #include <qlibc.h> |
@@ -71,16 +112,18 @@ extern char **environ; | |||
71 | // I deal with that by using a sed invokation when building toybox. | 112 | // I deal with that by using a sed invokation when building toybox. |
72 | #include "toys.h" | 113 | #include "toys.h" |
73 | 114 | ||
115 | typedef enum | ||
116 | { | ||
117 | CREATE = 0, | ||
118 | START = 1, | ||
119 | BACKUP = 2, | ||
120 | GITAR = 3, | ||
121 | RESTART = 4, | ||
122 | STATUS = 5, | ||
123 | STOP = 9 | ||
124 | } modes; | ||
74 | 125 | ||
75 | GLOBALS( | 126 | modes currentMode = START; |
76 | char *mode; | ||
77 | ) | ||
78 | |||
79 | #define TT this.sledjchisl | ||
80 | |||
81 | #define FLAG_m 2 | ||
82 | |||
83 | |||
84 | 127 | ||
85 | // Duplicate some small amount of code from qLibc, coz /, + and, = are not good choices, and the standard says we can pick those. | 128 | // Duplicate some small amount of code from qLibc, coz /, + and, = are not good choices, and the standard says we can pick those. |
86 | /** | 129 | /** |
@@ -282,10 +325,10 @@ typedef enum | |||
282 | // Silly "man getrandom" is bullshitting. | 325 | // Silly "man getrandom" is bullshitting. |
283 | // Note - this is Linux specific, it's calling a Linux kernel function. | 326 | // Note - this is Linux specific, it's calling a Linux kernel function. |
284 | // Remove this when we have a real getrandom(), and replace it with - | 327 | // Remove this when we have a real getrandom(), and replace it with - |
285 | // #include <sys/random.h> | 328 | //#include <sys/random.h> |
286 | #include <sys/syscall.h> | 329 | #include <sys/syscall.h> |
287 | #include <linux/random.h> | 330 | #include <linux/random.h> |
288 | int getrandom(void *b, size_t l, unsigned int f) | 331 | ssize_t getrandom(void *b, size_t l, unsigned int f) |
289 | { | 332 | { |
290 | return (int) syscall(SYS_getrandom, b, l, f); | 333 | return (int) syscall(SYS_getrandom, b, l, f); |
291 | } | 334 | } |
@@ -427,6 +470,7 @@ char *scBackup = ""; | |||
427 | char *scCache = ""; | 470 | char *scCache = ""; |
428 | char *scData = ""; | 471 | char *scData = ""; |
429 | char *scLog = ""; | 472 | char *scLog = ""; |
473 | char *scTemp = ""; | ||
430 | char *Tconsole = "SledjChisl"; | 474 | char *Tconsole = "SledjChisl"; |
431 | char *Tsocket = "opensim-tmux.socket"; | 475 | char *Tsocket = "opensim-tmux.socket"; |
432 | char *Ttab = "SC"; | 476 | char *Ttab = "SC"; |
@@ -439,8 +483,9 @@ int seshRenew = 10 * 60; | |||
439 | int idleTimeOut = 30 * 60; | 483 | int idleTimeOut = 30 * 60; |
440 | int seshTimeOut = 24 * 60 * 60; | 484 | int seshTimeOut = 24 * 60 * 60; |
441 | int newbieTimeOut = 30; | 485 | int newbieTimeOut = 30; |
442 | float loadAverageInc = 0.5; | 486 | float loadAverageInc = 0.7; |
443 | int simTimeOut = 45; | 487 | int simTimeOut = 45; |
488 | int bulkSims = 0; | ||
444 | boolean DEBUG = TRUE; | 489 | boolean DEBUG = TRUE; |
445 | qhashtbl_t *mimeTypes; | 490 | qhashtbl_t *mimeTypes; |
446 | qlist_t *dbRequests; | 491 | qlist_t *dbRequests; |
@@ -463,7 +508,7 @@ char *logTypes[] = | |||
463 | "36", "TIMEOUT", // cyan | 508 | "36", "TIMEOUT", // cyan |
464 | "97;40", "INFO", // white | 509 | "97;40", "INFO", // white |
465 | "90", "DEBUG", // grey | 510 | "90", "DEBUG", // grey |
466 | // VERBOSE? UNKNOWN? FATAL? SILENT? All from Android aparently. | 511 | // VERBOSE? UNKNOWN? FATAL? SILENT? All from Android apparently. |
467 | "35", "debug", // magenta | 512 | "35", "debug", // magenta |
468 | "34", "timeout", // blue | 513 | "34", "timeout", // blue |
469 | }; | 514 | }; |
@@ -647,12 +692,38 @@ float waitLoadAverage(float la, float extra, int timeout) | |||
647 | // Rob forget to do this, but at least he didn't declare it static. | 692 | // Rob forget to do this, but at least he didn't declare it static. |
648 | struct dirtree *dirtree_handle_callback(struct dirtree *new, int (*callback)(struct dirtree *node)); | 693 | struct dirtree *dirtree_handle_callback(struct dirtree *new, int (*callback)(struct dirtree *node)); |
649 | 694 | ||
695 | |||
696 | // A sim structure for holding all the stuff from the sim.ini file. | ||
697 | typedef struct _simData simData; | ||
698 | struct _simData | ||
699 | { | ||
700 | // portH is the HTTP port for the sim, portI is the UDP port for the sim. | ||
701 | int num, locX, locY, sizeX, sizeY, sizeZ, portH, portI, maxPrims; | ||
702 | char *name, *tab, *UUID, *regionType, *estate, *owner; | ||
703 | // char *nmbr; | ||
704 | }; | ||
705 | |||
650 | typedef struct _simList simList; | 706 | typedef struct _simList simList; |
651 | struct _simList | 707 | struct _simList |
652 | { | 708 | { |
653 | int len, num; | 709 | int len, num; |
654 | char **sims; | 710 | char **sims; |
711 | qtreetbl_t *tbl, *byTab; | ||
655 | }; | 712 | }; |
713 | simList *ourSims = NULL; | ||
714 | |||
715 | static int getIntFromIni(qlisttbl_t *ini, char *name) | ||
716 | { | ||
717 | int ret; | ||
718 | char *t = "0"; | ||
719 | |||
720 | t = ini->getstr(ini, name, false); | ||
721 | if (NULL == t) | ||
722 | t = "0"; | ||
723 | else if ('"' == t[0]) | ||
724 | t = qstrunchar(t, '"', '"'); | ||
725 | return strtol(t, NULL, 10); | ||
726 | } | ||
656 | 727 | ||
657 | static int filterSims(struct dirtree *node) | 728 | static int filterSims(struct dirtree *node) |
658 | { | 729 | { |
@@ -672,6 +743,7 @@ static int filterSims(struct dirtree *node) | |||
672 | return 0; | 743 | return 0; |
673 | } | 744 | } |
674 | 745 | ||
746 | /* | ||
675 | // We particularly don't want \ " ` | 747 | // We particularly don't want \ " ` |
676 | char *cleanSimName(char *name) | 748 | char *cleanSimName(char *name) |
677 | { | 749 | { |
@@ -690,19 +762,163 @@ char *cleanSimName(char *name) | |||
690 | 762 | ||
691 | return ret; | 763 | return ret; |
692 | } | 764 | } |
765 | */ | ||
766 | |||
767 | static int filterInis(struct dirtree *node) | ||
768 | { | ||
769 | if (!node->parent) return DIRTREE_RECURSE | DIRTREE_SHUTUP; | ||
770 | int l = strlen(node->name); | ||
771 | if (strncmp(&(node->name[l - 4]), ".ini", 4) == 0) | ||
772 | { | ||
773 | strncpy((char *) node->parent->extra, node->name, l - 4); | ||
774 | return DIRTREE_ABORT; | ||
775 | } | ||
776 | return 0; | ||
777 | } | ||
693 | 778 | ||
694 | simList *getSims() | 779 | simList *getSims() |
695 | { | 780 | { |
696 | simList *sims = xmalloc(sizeof(simList)); | 781 | if (NULL != ourSims) return ourSims; |
697 | memset(sims, 0, sizeof(simList)); | 782 | |
698 | char *path = xmprintf("%s/config", scRoot); | 783 | char *path = xmprintf("%s/config", scRoot), *newPath; |
699 | struct dirtree *new = dirtree_add_node(0, path, 0); | 784 | struct dirtree *new = dirtree_add_node(0, path, 0); |
700 | new->extra = (long) sims; | 785 | int i, j; |
786 | |||
787 | ourSims = xmalloc(sizeof(simList)); | ||
788 | memset(ourSims, 0, sizeof(simList)); | ||
789 | |||
790 | ourSims->tbl = qtreetbl(0); | ||
791 | ourSims->byTab = qtreetbl(0); | ||
792 | new->extra = (long) ourSims; | ||
701 | dirtree_handle_callback(new, filterSims); | 793 | dirtree_handle_callback(new, filterSims); |
702 | 794 | ||
703 | qsort(sims->sims, sims->num, sizeof(char *), qstrcmp); | 795 | qsort(ourSims->sims, ourSims->num, sizeof(char *), qstrcmp); |
704 | free(path); | 796 | free(path); |
705 | return sims; | 797 | |
798 | |||
799 | char *file = xmprintf("%s/sims.lua", scEtc); | ||
800 | char *tnm = "sims = -- Note these are .shini / tmux tab short names.\n{\n {['type'] = 'unsorted';\n"; | ||
801 | struct stat st; | ||
802 | int s = stat(file, &st); | ||
803 | int fd = -1; | ||
804 | size_t l = strlen(tnm); | ||
805 | |||
806 | if (s) | ||
807 | { | ||
808 | I("Creating sims %s.", file); | ||
809 | fd = notstdio(xcreate_stdio(file, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR)); | ||
810 | } | ||
811 | |||
812 | if (-1 != fd) | ||
813 | { | ||
814 | if (l != writeall(fd, tnm, l)) | ||
815 | perror_msg("Writing %s", file); | ||
816 | } | ||
817 | |||
818 | |||
819 | for (i = 0; i < ourSims->num; i++) | ||
820 | { | ||
821 | char *sim = ourSims->sims[i], *name = xmprintf("%s/config/%s", scRoot, sim); | ||
822 | qlisttbl_t *ini; | ||
823 | simData *simd = xmalloc(sizeof(simData)); | ||
824 | |||
825 | struct dirtree *new = dirtree_add_node(0, name, 0); | ||
826 | |||
827 | free(name); | ||
828 | name = xzalloc(1024); | ||
829 | new->extra = (long) name; | ||
830 | dirtree_handle_callback(new, filterInis); | ||
831 | if ('\0' != name[0]) | ||
832 | { | ||
833 | path = xmprintf("%s/config/%s/%s.ini", scRoot, sim, name); | ||
834 | newPath = xmprintf("%s/%s.shini", scEtc, name); | ||
835 | I("Reading .ini file %s", path); | ||
836 | ini = qconfig_parse_file(NULL, path, '='); | ||
837 | |||
838 | ini->putstr(ini, "INI FILE", name); | ||
839 | /* | ||
840 | [Region] | ||
841 | Location = "1,1" | ||
842 | InternalPort = "9008" | ||
843 | MaxPrims = 45000 | ||
844 | |||
845 | [Network] | ||
846 | http_listener_port = 9007 | ||
847 | */ | ||
848 | simd->num = getIntFromIni(ini, "Const.mysim"); | ||
849 | simd->name = qstrunchar(ini->getstr(ini, "Region.RegionName", false), '"', '"'); | ||
850 | simd->UUID = qstrunchar(ini->getstr(ini, "Region.RegionUUID", false), '"', '"'); | ||
851 | simd->regionType = qstrunchar(ini->getstr(ini, "Region.RegionType", false), '"', '"'); | ||
852 | simd->sizeX = getIntFromIni(ini, "Region.SizeX"); | ||
853 | simd->sizeY = getIntFromIni(ini, "Region.SizeY"); | ||
854 | simd->sizeZ = getIntFromIni(ini, "Region.SizeZ"); | ||
855 | simd->tab = name; | ||
856 | // simd->nmbr = sim; | ||
857 | ini->put(ini, "SIM DATA", simd, sizeof(simData)); | ||
858 | ourSims->tbl->put(ourSims->tbl, sim, ini, sizeof(qlisttbl_t)); | ||
859 | ourSims->byTab->put(ourSims->byTab, name, ini, sizeof(qlisttbl_t)); | ||
860 | |||
861 | if ((!qfile_exist(newPath))) | ||
862 | { | ||
863 | char *cmd = xmprintf("sed -E" | ||
864 | " -e 's#\\[Const]#\\[Const] ; fakeVariableCozOpenSim='' ; pushd ../current/bin; ./sledjchisl $1 `basename $0`; popd ; exit 0#'" | ||
865 | " -e 's/mysim=\"[[:digit:]]*\"/mysim=\"%s\"/'" | ||
866 | " -e 's/sim\\$\\{Const\\|mysim\\}/\\$\\{Const\\|mysim\\}/g'" | ||
867 | " %s >%s", simd->tab, path, newPath); | ||
868 | |||
869 | I("Writing .shini file %s", newPath); | ||
870 | D(cmd); | ||
871 | j = system(cmd); | ||
872 | if (!WIFEXITED(j)) | ||
873 | E("sed command failed!"); | ||
874 | else | ||
875 | { | ||
876 | free(cmd); | ||
877 | cmd = xmprintf("chmod ugo+x %s", newPath); | ||
878 | j = system(cmd); | ||
879 | if (!WIFEXITED(j)) | ||
880 | E("chmod command failed!"); | ||
881 | |||
882 | |||
883 | char *link = xmprintf("%s/%s.shini", scBin, simd->tab); | ||
884 | I("Symlinking %s to %s", newPath, link); | ||
885 | if (0 != symlink(newPath, link)) | ||
886 | perror_msg("Symlinking %s to %s", newPath, link); | ||
887 | free(link); | ||
888 | |||
889 | |||
890 | } | ||
891 | free(cmd); | ||
892 | } | ||
893 | } | ||
894 | free(newPath); | ||
895 | free(path); | ||
896 | |||
897 | |||
898 | if (-1 != fd) | ||
899 | { | ||
900 | tnm = xmprintf(" '%s', \n", simd->tab); | ||
901 | l = strlen(tnm); | ||
902 | if (l != writeall(fd, tnm, l)) | ||
903 | perror_msg("Writing %s", file); | ||
904 | free(tnm); | ||
905 | } | ||
906 | |||
907 | } | ||
908 | |||
909 | if (-1 != fd) | ||
910 | { | ||
911 | tnm = " },\n}\nreturn sims\n"; | ||
912 | l = strlen(tnm); | ||
913 | if (l != writeall(fd, tnm, l)) | ||
914 | perror_msg("Writing %s", file); | ||
915 | |||
916 | xclose(fd); | ||
917 | } | ||
918 | free(file); | ||
919 | |||
920 | |||
921 | return ourSims; | ||
706 | } | 922 | } |
707 | 923 | ||
708 | void freeSimList(simList *sims) | 924 | void freeSimList(simList *sims) |
@@ -712,69 +928,44 @@ void freeSimList(simList *sims) | |||
712 | for (i = 0; i < sims->num; i++) | 928 | for (i = 0; i < sims->num; i++) |
713 | free(sims->sims[i]); | 929 | free(sims->sims[i]); |
714 | free(sims->sims); | 930 | free(sims->sims); |
715 | free(sims); | ||
716 | } | ||
717 | 931 | ||
718 | static int filterInis(struct dirtree *node) | 932 | qtreetbl_obj_t obj; |
719 | { | 933 | memset((void*) &obj, 0, sizeof(obj)); // start from the minimum. |
720 | if (!node->parent) return DIRTREE_RECURSE | DIRTREE_SHUTUP; | 934 | sims->tbl->lock(sims->tbl); |
721 | int l = strlen(node->name); | 935 | while (sims->tbl->getnext(sims->tbl, &obj, false) == true) |
722 | if (strncmp(&(node->name[l - 4]), ".ini", 4) == 0) | 936 | { |
937 | char *name = qmemdup(obj.name, obj.namesize); // keep the name | ||
938 | size_t namesize = obj.namesize; // for removal argument | ||
939 | qlisttbl_t *ini = (qlisttbl_t *) obj.data; | ||
940 | if (NULL != ini) | ||
723 | { | 941 | { |
724 | strcpy((char *) node->parent->extra, node->name); | 942 | simData *simd = ini->get(ini, "SIM DATA", NULL, false); |
725 | return DIRTREE_ABORT; | ||
726 | } | ||
727 | return 0; | ||
728 | } | ||
729 | 943 | ||
730 | char *getSimName(char *sim) | 944 | if (NULL != simd) |
731 | { | ||
732 | char *ret = NULL; | ||
733 | char *c = xmprintf("%s/config/%s", scRoot, sim); | ||
734 | struct dirtree *new = dirtree_add_node(0, c, 0); | ||
735 | |||
736 | free(c); | ||
737 | c = xzalloc(1024); | ||
738 | new->extra = (long) c; | ||
739 | dirtree_handle_callback(new, filterInis); | ||
740 | if ('\0' != c[0]) | ||
741 | { | ||
742 | char *temp = NULL; | ||
743 | regex_t pat; | ||
744 | regmatch_t m[2]; | ||
745 | long len; | ||
746 | int fd; | ||
747 | |||
748 | temp = xmprintf("%s/config/%s/%s", scRoot, sim, c); | ||
749 | fd = xopenro(temp); | ||
750 | xregcomp(&pat, "RegionName = \"(.+)\"", REG_EXTENDED); | ||
751 | do | ||
752 | { | ||
753 | // TODO - get_line() is slow, and wont help much with DOS and Mac line endings. | ||
754 | // gio_gets() isn't any faster really, but deals with DOS line endings at least. | ||
755 | free(temp); | ||
756 | temp = get_line(fd); | ||
757 | if (temp) | ||
758 | { | 945 | { |
759 | if (!regexec(&pat, temp, 2, m, 0)) | 946 | free(simd->name); |
760 | { | 947 | free(simd->UUID); |
761 | // Return first parenthesized subexpression as string. | 948 | free(simd->regionType); |
762 | if (pat.re_nsub > 0) | 949 | // free(simd->estate); |
763 | { | 950 | // free(simd->owner); |
764 | ret = xmprintf("%.*s", (int) (m[1].rm_eo - m[1].rm_so), temp + m[1].rm_so); | 951 | free(simd); |
765 | free(temp); | ||
766 | break; | ||
767 | } | ||
768 | } | ||
769 | } | 952 | } |
770 | } while (temp); | 953 | // TODO - this leaks memory, but it's a bug in qLibc. Send the bug fix upstream. |
771 | regfree(&pat); | 954 | // It either leaks, or frees twice. Pffft |
772 | xclose(fd); | 955 | // ini->clear(ini); |
956 | // ini->free(ini); | ||
957 | ; | ||
958 | } | ||
959 | |||
960 | sims->tbl->remove_by_obj(sims->tbl, obj.name, obj.namesize); // remove | ||
961 | obj = sims->tbl->find_nearest(sims->tbl, name, namesize, false); // rewind one step back | ||
962 | free(name); // clean up | ||
773 | } | 963 | } |
774 | free(c); | 964 | sims->tbl->unlock(sims->tbl); |
775 | return ret; | 965 | sims->tbl->free(sims->tbl); |
776 | } | ||
777 | 966 | ||
967 | free(sims); | ||
968 | } | ||
778 | 969 | ||
779 | // Expects either "simXX" or "ROBUST". | 970 | // Expects either "simXX" or "ROBUST". |
780 | int checkSimIsRunning(char *sim) | 971 | int checkSimIsRunning(char *sim) |
@@ -3421,6 +3612,7 @@ char *checkLinky(reqData *Rd) | |||
3421 | ret = xmprintf("<p><font color='red'><b>You have an email waiting with a validation link in it, please check your email. " | 3612 | ret = xmprintf("<p><font color='red'><b>You have an email waiting with a validation link in it, please check your email. " |
3422 | "It will be from %s@%s, and it might be in your spam folder, coz these sorts of emails sometimes end up there. " | 3613 | "It will be from %s@%s, and it might be in your spam folder, coz these sorts of emails sometimes end up there. " |
3423 | "You should add that email address to your contacts, or otherwise let it through your spam filter. " | 3614 | "You should add that email address to your contacts, or otherwise let it through your spam filter. " |
3615 | "If your email client wont let you click the validation link, just copy and paste it into your web browser. " | ||
3424 | // "<a href='https://%s%s?hashish=%s'>%s</a>" | 3616 | // "<a href='https://%s%s?hashish=%s'>%s</a>" |
3425 | "</b></font></p>\n", | 3617 | "</b></font></p>\n", |
3426 | "grid_no_reply", Rd->Host, | 3618 | "grid_no_reply", Rd->Host, |
@@ -3646,15 +3838,22 @@ t("Write shs %s", tnm4); | |||
3646 | "\n" | 3838 | "\n" |
3647 | "Please go to this web link to validate your new account -\n" | 3839 | "Please go to this web link to validate your new account -\n" |
3648 | "https://%s%s?hashish=%s\n" | 3840 | "https://%s%s?hashish=%s\n" |
3841 | "If your email client wont let you click the validation\n" | ||
3842 | "link, just copy and paste it into your web browser.\n" | ||
3843 | "\n" | ||
3649 | "\n" | 3844 | "\n" |
3650 | "Do not reply to this email.\n" | 3845 | "Do not reply to this email.\n" |
3651 | "\n", | 3846 | "\n" |
3847 | "\n" | ||
3848 | "A copy of the grids Terms of Service that you agreed to\n" | ||
3849 | "when you created your account is included below.\n" | ||
3850 | "%s", | ||
3652 | Rd->Host, Rd->Host, Rd->Host, | 3851 | Rd->Host, Rd->Host, Rd->Host, |
3653 | getStrH(Rd->stuff, "email"), | 3852 | getStrH(Rd->stuff, "email"), |
3654 | Rd->Host, Rd->Host, | 3853 | Rd->Host, Rd->Host, |
3655 | first, last, | 3854 | first, last, |
3656 | first, last, Rd->Host, Rd->RUri, | 3855 | first, last, Rd->Host, Rd->RUri, |
3657 | Rd->Host, Rd->RUri, t1 | 3856 | Rd->Host, Rd->RUri, t1, ToS |
3658 | ); | 3857 | ); |
3659 | l = strlen(content); | 3858 | l = strlen(content); |
3660 | file = xmprintf("%s/sessions/%s.email", scCache, shs->leaf); | 3859 | file = xmprintf("%s/sessions/%s.email", scCache, shs->leaf); |
@@ -3894,6 +4093,7 @@ static void accountWrite(reqData *Rd) | |||
3894 | if (!writeLuaString (Rd, fd, file, "aboutMe", NULL)) goto notWritten; | 4093 | if (!writeLuaString (Rd, fd, file, "aboutMe", NULL)) goto notWritten; |
3895 | if (!writeLuaString (Rd, fd, file, "vouched", "off")) goto notWritten; | 4094 | if (!writeLuaString (Rd, fd, file, "vouched", "off")) goto notWritten; |
3896 | if (!writeLuaString (Rd, fd, file, "voucher", NULL)) goto notWritten; | 4095 | if (!writeLuaString (Rd, fd, file, "voucher", NULL)) goto notWritten; |
4096 | if (!writeLuaString (Rd, fd, file, "approver", NULL)) goto notWritten; | ||
3897 | if (!writeLuaString (Rd, fd, file, "link", link)) goto notWritten; | 4097 | if (!writeLuaString (Rd, fd, file, "link", link)) goto notWritten; |
3898 | l = strlen(end); | 4098 | l = strlen(end); |
3899 | if (l != writeall(fd, end, l)) | 4099 | if (l != writeall(fd, end, l)) |
@@ -3939,7 +4139,7 @@ notWritten: | |||
3939 | "UserLevel", | 4139 | "UserLevel", |
3940 | "UserFlags", | 4140 | "UserFlags", |
3941 | "UserTitle", | 4141 | "UserTitle", |
3942 | // "ServiceURLs", // No worky "text", filled with crap. | 4142 | // "ServiceURLs", // No worky "text", filled with crap. Leaving it blank works fine. |
3943 | "active", | 4143 | "active", |
3944 | NULL | 4144 | NULL |
3945 | }; | 4145 | }; |
@@ -4090,16 +4290,26 @@ notWritten: | |||
4090 | } | 4290 | } |
4091 | 4291 | ||
4092 | // load iar -m first last / password /opt/opensim_SC/backups/DefaultMember.IAR | 4292 | // load iar -m first last / password /opt/opensim_SC/backups/DefaultMember.IAR |
4093 | simList *sims = getSims(); | ||
4094 | struct sysinfo info; | 4293 | struct sysinfo info; |
4095 | float la; | 4294 | float la; |
4096 | 4295 | ||
4097 | sysinfo(&info); | 4296 | sysinfo(&info); |
4098 | la = info.loads[0]/65536.0; | 4297 | la = info.loads[0]/65536.0; |
4099 | 4298 | ||
4100 | for (i = 0; i < sims->num; i++) | 4299 | for (i = 0; i < ourSims->num; i++) |
4101 | { | 4300 | { |
4102 | char *sim = sims->sims[i], *name = getSimName(sims->sims[i]); | 4301 | char *sim = ourSims->sims[i], *name;// = getSimName(ourSims->sims[i], &nm, &num); |
4302 | |||
4303 | qlisttbl_t *ini = ourSims->tbl->get(ourSims->tbl, sim, NULL, false); | ||
4304 | if (NULL == ini) | ||
4305 | { | ||
4306 | E("Sim %s not found in ini list!", sim); | ||
4307 | // name = getSimName(ourSims->sims[i], &nm, &num); | ||
4308 | } | ||
4309 | else | ||
4310 | name = qstrunchar(ini->getstr(ini, "Region.RegionName", false), '"', '"'); | ||
4311 | |||
4312 | |||
4103 | 4313 | ||
4104 | if (checkSimIsRunning(sim)) | 4314 | if (checkSimIsRunning(sim)) |
4105 | { | 4315 | { |
@@ -4124,7 +4334,6 @@ T(c); | |||
4124 | } | 4334 | } |
4125 | free(name); | 4335 | free(name); |
4126 | } | 4336 | } |
4127 | freeSimList(sims); | ||
4128 | } | 4337 | } |
4129 | free(first); | 4338 | free(first); |
4130 | } | 4339 | } |
@@ -4796,8 +5005,8 @@ static int DoBValidate(reqData *Rd, inputForm *iF, inputValue *iV) | |||
4796 | else | 5005 | else |
4797 | { | 5006 | { |
4798 | i = atoi(t0); | 5007 | i = atoi(t0); |
4799 | // TODO - get this to use current year instead of 2020. | 5008 | // TODO - get this to use current year instead of 2021. |
4800 | if ((1900 > i) || (i > 2020)) | 5009 | if ((1900 > i) || (i > 2021)) |
4801 | { | 5010 | { |
4802 | bitch(Rd, "Please supply a year of birth.", "Out of range."); | 5011 | bitch(Rd, "Please supply a year of birth.", "Out of range."); |
4803 | ret++; | 5012 | ret++; |
@@ -4807,7 +5016,7 @@ static int DoBValidate(reqData *Rd, inputForm *iF, inputValue *iV) | |||
4807 | bitch(Rd, "Please supply a proper year of birth.", "Out of range, too old."); | 5016 | bitch(Rd, "Please supply a proper year of birth.", "Out of range, too old."); |
4808 | ret++; | 5017 | ret++; |
4809 | } | 5018 | } |
4810 | else if (i >2004) | 5019 | else if (i >2005) |
4811 | { | 5020 | { |
4812 | bitch(Rd, "This grid is Adult rated, you are too young.", "Out of range, too young."); | 5021 | bitch(Rd, "This grid is Adult rated, you are too young.", "Out of range, too young."); |
4813 | ret++; | 5022 | ret++; |
@@ -5074,6 +5283,7 @@ static void accountViewWeb(reqData *Rd, inputForm *oF, inputValue *oV) | |||
5074 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), | 5283 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), |
5075 | *email = getStrH(Rd->database, "UserAccounts.Email"), | 5284 | *email = getStrH(Rd->database, "UserAccounts.Email"), |
5076 | *voucher = getStrH(Rd->database, "Lua.voucher"), | 5285 | *voucher = getStrH(Rd->database, "Lua.voucher"), |
5286 | *approver = getStrH(Rd->database, "Lua.approver"), | ||
5077 | *about = getStrH(Rd->database, "Lua.aboutMe"); | 5287 | *about = getStrH(Rd->database, "Lua.aboutMe"); |
5078 | time_t crtd = atol(getStrH(Rd->database, "UserAccounts.Created")); | 5288 | time_t crtd = atol(getStrH(Rd->database, "UserAccounts.Created")); |
5079 | 5289 | ||
@@ -5086,6 +5296,7 @@ static void accountViewWeb(reqData *Rd, inputForm *oF, inputValue *oV) | |||
5086 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Email :</b></span></font> %s</p>", email); | 5296 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Email :</b></span></font> %s</p>", email); |
5087 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>UUID :</b></span></font> %s</p>", getStrH(Rd->database, "UserAccounts.PrincipalID")); | 5297 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>UUID :</b></span></font> %s</p>", getStrH(Rd->database, "UserAccounts.PrincipalID")); |
5088 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Voucher :</b></span></font> %s</p>", voucher); | 5298 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Voucher :</b></span></font> %s</p>", voucher); |
5299 | Rd->reply->addstrf(Rd->reply, "<p><font size='5'><span style='font-size: x-large'><b>Approver :</b></span></font> %s</p>", approver); | ||
5089 | HTMLtextArea(Rd->reply, "aboutMe", "About", 7, 50, 4, 16384, "", "off", "true", "soft", about, FALSE, TRUE); | 5300 | HTMLtextArea(Rd->reply, "aboutMe", "About", 7, 50, 4, 16384, "", "off", "true", "soft", about, FALSE, TRUE); |
5090 | accountWebSubs(Rd, oF); | 5301 | accountWebSubs(Rd, oF); |
5091 | accountWebFooter(Rd, oF); | 5302 | accountWebFooter(Rd, oF); |
@@ -5097,6 +5308,7 @@ static void accountEditWeb(reqData *Rd, inputForm *oF, inputValue *oV) | |||
5097 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), | 5308 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"), |
5098 | *email = getStrH(Rd->database, "UserAccounts.Email"), | 5309 | *email = getStrH(Rd->database, "UserAccounts.Email"), |
5099 | *voucher = getStrH(Rd->database, "Lua.voucher"), | 5310 | *voucher = getStrH(Rd->database, "Lua.voucher"), |
5311 | *approver = getStrH(Rd->database, "Lua.approver"), | ||
5100 | *about = getStrH(Rd->database, "Lua.aboutMe"), | 5312 | *about = getStrH(Rd->database, "Lua.aboutMe"), |
5101 | *lvl = getLevel(atoi(level)); | 5313 | *lvl = getLevel(atoi(level)); |
5102 | short lv = atoi(level); | 5314 | short lv = atoi(level); |
@@ -5117,6 +5329,7 @@ static void accountEditWeb(reqData *Rd, inputForm *oF, inputValue *oV) | |||
5117 | { | 5329 | { |
5118 | qlisttbl_obj_t obj; | 5330 | qlisttbl_obj_t obj; |
5119 | 5331 | ||
5332 | HTMLhidden(Rd->reply, "approver", approver); | ||
5120 | HTMLselect(Rd->reply, "level", "level"); | 5333 | HTMLselect(Rd->reply, "level", "level"); |
5121 | memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call | 5334 | memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call |
5122 | accountLevels->lock(accountLevels); | 5335 | accountLevels->lock(accountLevels); |
@@ -5288,6 +5501,7 @@ T("Found Lua record."); | |||
5288 | Rd->database->putstr(Rd->database, "Lua.aboutMe", getStrH(tnm, "aboutMe")); | 5501 | Rd->database->putstr(Rd->database, "Lua.aboutMe", getStrH(tnm, "aboutMe")); |
5289 | Rd->database->putstr(Rd->database, "Lua.vouched", getStrH(tnm, "vouched")); | 5502 | Rd->database->putstr(Rd->database, "Lua.vouched", getStrH(tnm, "vouched")); |
5290 | Rd->database->putstr(Rd->database, "Lua.voucher", getStrH(tnm, "voucher")); | 5503 | Rd->database->putstr(Rd->database, "Lua.voucher", getStrH(tnm, "voucher")); |
5504 | Rd->database->putstr(Rd->database, "Lua.approver", getStrH(tnm, "approver")); | ||
5291 | } | 5505 | } |
5292 | // else if (rows) | 5506 | // else if (rows) |
5293 | if (rows) | 5507 | if (rows) |
@@ -5369,9 +5583,9 @@ static int accountDelSub(reqData *Rd, inputForm *iF, inputValue *iV) | |||
5369 | } | 5583 | } |
5370 | else | 5584 | else |
5371 | { | 5585 | { |
5372 | // check if logged in user is allowed to delete this account | 5586 | // TODO - check if logged in user is allowed to delete this account |
5373 | // delete user record | 5587 | // TODO - delete user record |
5374 | // log the user out if they are logged in | 5588 | // TODO - log the user out if they are logged in |
5375 | } | 5589 | } |
5376 | return ret; | 5590 | return ret; |
5377 | } | 5591 | } |
@@ -5464,7 +5678,8 @@ static int accountSaveSub(reqData *Rd, inputForm *iF, inputValue *iV) | |||
5464 | { | 5678 | { |
5465 | int ret = 0; | 5679 | int ret = 0; |
5466 | // Using body[user] here, coz we got to this page via a URL query. | 5680 | // Using body[user] here, coz we got to this page via a URL query. |
5467 | char *uuid = Rd->shs.UUID, *first = getStrH(Rd->body, "user"), *last = NULL; | 5681 | char *uuid = Rd->shs.UUID, *first = getStrH(Rd->body, "user"), *last = NULL, |
5682 | *level = getStrH(Rd->database, "UserAccounts.UserLevel"); | ||
5468 | int c = accountRead(Rd, NULL, first, last); | 5683 | int c = accountRead(Rd, NULL, first, last); |
5469 | 5684 | ||
5470 | if (1 != c) | 5685 | if (1 != c) |
@@ -5474,6 +5689,24 @@ static int accountSaveSub(reqData *Rd, inputForm *iF, inputValue *iV) | |||
5474 | } | 5689 | } |
5475 | else if ((0 == ret) && (strcmp("POST", Rd->Method) == 0)) | 5690 | else if ((0 == ret) && (strcmp("POST", Rd->Method) == 0)) |
5476 | { | 5691 | { |
5692 | char *lvl = getStrH(Rd->body, "level"); | ||
5693 | qlisttbl_obj_t obj; | ||
5694 | |||
5695 | if (strcmp(level, lvl) != 0) | ||
5696 | { | ||
5697 | if (200 <= Rd->shs.level) | ||
5698 | { | ||
5699 | I("%s %s approved by %s.", getStrH(Rd->database, "UserAccounts.FirstName"), getStrH(Rd->database, "UserAccounts.LastName"), Rd->shs.name); | ||
5700 | Rd->stuff->putstr(Rd->stuff, "approver", Rd->shs.name); | ||
5701 | } | ||
5702 | else | ||
5703 | { | ||
5704 | bitch(Rd, "Cannot change level.", "User level not high enough."); | ||
5705 | lvl = level; | ||
5706 | Rd->stuff->putstr(Rd->stuff, "approver", getStrH(Rd->database, "Lua.approver")); | ||
5707 | } | ||
5708 | } | ||
5709 | |||
5477 | Rd->stuff->putstr(Rd->stuff, "email", getStrH(Rd->database, "UserAccounts.Email")); | 5710 | Rd->stuff->putstr(Rd->stuff, "email", getStrH(Rd->database, "UserAccounts.Email")); |
5478 | Rd->stuff->putstr(Rd->stuff, "created", getStrH(Rd->database, "UserAccounts.Created")); | 5711 | Rd->stuff->putstr(Rd->stuff, "created", getStrH(Rd->database, "UserAccounts.Created")); |
5479 | Rd->stuff->putstr(Rd->stuff, "flags", getStrH(Rd->database, "UserAccounts.UserFlags")); | 5712 | Rd->stuff->putstr(Rd->stuff, "flags", getStrH(Rd->database, "UserAccounts.UserFlags")); |
@@ -5488,15 +5721,14 @@ static int accountSaveSub(reqData *Rd, inputForm *iF, inputValue *iV) | |||
5488 | Rd->stuff->putstr(Rd->stuff, "vouched", getStrH(Rd->database, "Lua.vouched")); | 5721 | Rd->stuff->putstr(Rd->stuff, "vouched", getStrH(Rd->database, "Lua.vouched")); |
5489 | Rd->stuff->putstr(Rd->stuff, "voucher", getStrH(Rd->database, "Lua.voucher")); | 5722 | Rd->stuff->putstr(Rd->stuff, "voucher", getStrH(Rd->database, "Lua.voucher")); |
5490 | 5723 | ||
5491 | char *lvl = getStrH(Rd->body, "level"); | ||
5492 | qlisttbl_obj_t obj; | ||
5493 | |||
5494 | memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call | 5724 | memset((void*)&obj, 0, sizeof(obj)); // must be cleared before call |
5495 | accountLevels->lock(accountLevels); | 5725 | accountLevels->lock(accountLevels); |
5496 | while(accountLevels->getnext(accountLevels, &obj, NULL, false) == true) | 5726 | while(accountLevels->getnext(accountLevels, &obj, NULL, false) == true) |
5497 | { | 5727 | { |
5498 | if (strcmp(lvl, (char *) obj.data) == 0) | 5728 | if (strcmp(lvl, (char *) obj.data) == 0) |
5729 | { | ||
5499 | Rd->database->putstr(Rd->database, "UserAccounts.UserLevel", obj.name); | 5730 | Rd->database->putstr(Rd->database, "UserAccounts.UserLevel", obj.name); |
5731 | } | ||
5500 | } | 5732 | } |
5501 | accountLevels->unlock(accountLevels); | 5733 | accountLevels->unlock(accountLevels); |
5502 | accountWrite(Rd); | 5734 | accountWrite(Rd); |
@@ -5535,6 +5767,7 @@ static int accountValidateSub(reqData *Rd, inputForm *iF, inputValue *iV) | |||
5535 | Rd->stuff->putstr(Rd->stuff, "aboutMe", getStrH(Rd->database, "Lua.aboutMe")); | 5767 | Rd->stuff->putstr(Rd->stuff, "aboutMe", getStrH(Rd->database, "Lua.aboutMe")); |
5536 | Rd->stuff->putstr(Rd->stuff, "vouched", getStrH(Rd->database, "Lua.vouched")); | 5768 | Rd->stuff->putstr(Rd->stuff, "vouched", getStrH(Rd->database, "Lua.vouched")); |
5537 | Rd->stuff->putstr(Rd->stuff, "voucher", getStrH(Rd->database, "Lua.voucher")); | 5769 | Rd->stuff->putstr(Rd->stuff, "voucher", getStrH(Rd->database, "Lua.voucher")); |
5770 | Rd->stuff->putstr(Rd->stuff, "approver", getStrH(Rd->database, "Lua.approver")); | ||
5538 | Rd->shs.level = -100; | 5771 | Rd->shs.level = -100; |
5539 | Rd->database->putstr(Rd->database, "UserAccounts.UserLevel", "-100"); | 5772 | Rd->database->putstr(Rd->database, "UserAccounts.UserLevel", "-100"); |
5540 | accountWrite(Rd); | 5773 | accountWrite(Rd); |
@@ -5603,8 +5836,8 @@ d("Sub accountEditSub %s %s %s", uuid, first, last); | |||
5603 | } | 5836 | } |
5604 | else | 5837 | else |
5605 | { | 5838 | { |
5606 | // check if logged in user is allowed to make these changes | 5839 | // TODO - check if logged in user is allowed to make these changes |
5607 | // update user record | 5840 | // TODO - update user record |
5608 | } | 5841 | } |
5609 | return ret; | 5842 | return ret; |
5610 | } | 5843 | } |
@@ -6457,6 +6690,10 @@ void sledjchisl_main(void) | |||
6457 | I("qLibc version: qLibc only git tags for version numbers. Sooo, 2.4.4, unless I forgot to update this."); | 6690 | I("qLibc version: qLibc only git tags for version numbers. Sooo, 2.4.4, unless I forgot to update this."); |
6458 | I("toybox version: %s", TOYBOX_VERSION); | 6691 | I("toybox version: %s", TOYBOX_VERSION); |
6459 | 6692 | ||
6693 | T("SledjChisl arguments %d %d", (int)toys.optflags, (int)toys.optc); | ||
6694 | for (i = 0; i < toys.optc; i++) | ||
6695 | T(" argument %d %s", i, toys.optargs[i] ); | ||
6696 | |||
6460 | dbRequests = qlist(0); | 6697 | dbRequests = qlist(0); |
6461 | sigatexit(cleanup); | 6698 | sigatexit(cleanup); |
6462 | 6699 | ||
@@ -6517,6 +6754,7 @@ jit library is loaded or the JIT compiler will not be activated. | |||
6517 | luaL_openlibs(L); // Load Lua libraries. | 6754 | luaL_openlibs(L); // Load Lua libraries. |
6518 | 6755 | ||
6519 | // Load the config scripts. | 6756 | // Load the config scripts. |
6757 | // TODO - should add something like current working directory here. Gets complicated, may have to go up or down a bit. | ||
6520 | char *cPaths[] = | 6758 | char *cPaths[] = |
6521 | { | 6759 | { |
6522 | ".sledjChisl.conf.lua", | 6760 | ".sledjChisl.conf.lua", |
@@ -6528,7 +6766,6 @@ jit library is loaded or the JIT compiler will not be activated. | |||
6528 | }; | 6766 | }; |
6529 | struct stat st; | 6767 | struct stat st; |
6530 | 6768 | ||
6531 | |||
6532 | for (i = 0; cPaths[i]; i++) | 6769 | for (i = 0; cPaths[i]; i++) |
6533 | { | 6770 | { |
6534 | memset(toybuf, 0, sizeof(toybuf)); | 6771 | memset(toybuf, 0, sizeof(toybuf)); |
@@ -6583,6 +6820,7 @@ jit library is loaded or the JIT compiler will not be activated. | |||
6583 | D("Setting DEBUG = %d", DEBUG); | 6820 | D("Setting DEBUG = %d", DEBUG); |
6584 | if ((vd = configs->get (configs, "loadAverageInc", NULL, false)) != NULL) {loadAverageInc = *((float *) vd); D("Setting loadAverageInc = %f", loadAverageInc);} | 6821 | if ((vd = configs->get (configs, "loadAverageInc", NULL, false)) != NULL) {loadAverageInc = *((float *) vd); D("Setting loadAverageInc = %f", loadAverageInc);} |
6585 | if ((vd = configs->get (configs, "simTimeOut", NULL, false)) != NULL) {simTimeOut = (int) *((float *) vd); D("Setting simTimeOut = %d", simTimeOut);} | 6822 | if ((vd = configs->get (configs, "simTimeOut", NULL, false)) != NULL) {simTimeOut = (int) *((float *) vd); D("Setting simTimeOut = %d", simTimeOut);} |
6823 | if ((vd = configs->get (configs, "bulkSims", NULL, false)) != NULL) {bulkSims = (int) *((float *) vd); D("Setting bulkSims = %d", bulkSims);} | ||
6586 | if ((tmp = configs->getstr(configs, "scRoot", false)) != NULL) {scRoot = tmp; D("Setting scRoot = %s", scRoot);} | 6824 | if ((tmp = configs->getstr(configs, "scRoot", false)) != NULL) {scRoot = tmp; D("Setting scRoot = %s", scRoot);} |
6587 | if ((tmp = configs->getstr(configs, "scUser", false)) != NULL) {scUser = tmp; D("Setting scUser = %s", scUser);} | 6825 | if ((tmp = configs->getstr(configs, "scUser", false)) != NULL) {scUser = tmp; D("Setting scUser = %s", scUser);} |
6588 | if ((tmp = configs->getstr(configs, "Tconsole", false)) != NULL) {Tconsole = tmp; D("Setting Tconsole = %s", Tconsole);} | 6826 | if ((tmp = configs->getstr(configs, "Tconsole", false)) != NULL) {Tconsole = tmp; D("Setting Tconsole = %s", Tconsole);} |
@@ -6609,6 +6847,7 @@ jit library is loaded or the JIT compiler will not be activated. | |||
6609 | scCache = "/var/cache/opensim_SC"; | 6847 | scCache = "/var/cache/opensim_SC"; |
6610 | scData = "/var/lib/opensim_SC"; | 6848 | scData = "/var/lib/opensim_SC"; |
6611 | scLog = "/var/log/opensim_SC"; | 6849 | scLog = "/var/log/opensim_SC"; |
6850 | scTemp = "/tmp"; | ||
6612 | } | 6851 | } |
6613 | else if (strcmp("/usr/local", scRoot) == 0) | 6852 | else if (strcmp("/usr/local", scRoot) == 0) |
6614 | { | 6853 | { |
@@ -6620,6 +6859,7 @@ jit library is loaded or the JIT compiler will not be activated. | |||
6620 | scCache = "/var/local/cache/opensim_SC"; | 6859 | scCache = "/var/local/cache/opensim_SC"; |
6621 | scData = "/var/local/lib/opensim_SC"; | 6860 | scData = "/var/local/lib/opensim_SC"; |
6622 | scLog = "/var/local/log/opensim_SC"; | 6861 | scLog = "/var/local/log/opensim_SC"; |
6862 | scTemp = "/tmp"; | ||
6623 | } | 6863 | } |
6624 | else // A place for everything to live, like /opt/opensim_SC | 6864 | else // A place for everything to live, like /opt/opensim_SC |
6625 | { | 6865 | { |
@@ -6642,6 +6882,7 @@ jit library is loaded or the JIT compiler will not be activated. | |||
6642 | scCache = xmprintf("%s%s/var/cache", slsh, scRoot); | 6882 | scCache = xmprintf("%s%s/var/cache", slsh, scRoot); |
6643 | scData = xmprintf("%s%s/var/lib", slsh, scRoot); | 6883 | scData = xmprintf("%s%s/var/lib", slsh, scRoot); |
6644 | scLog = xmprintf("%s%s/var/log", slsh, scRoot); | 6884 | scLog = xmprintf("%s%s/var/log", slsh, scRoot); |
6885 | scTemp = xmprintf("%s%s/tmp", slsh, scRoot); | ||
6645 | } | 6886 | } |
6646 | 6887 | ||
6647 | 6888 | ||
@@ -6662,30 +6903,75 @@ jit library is loaded or the JIT compiler will not be activated. | |||
6662 | I("Not running inside the proper tmux server, starting it. %s == %s", eTMUX, toybuf); | 6903 | I("Not running inside the proper tmux server, starting it. %s == %s", eTMUX, toybuf); |
6663 | } | 6904 | } |
6664 | 6905 | ||
6665 | if (isTmux || isWeb) | 6906 | if (!isTmux) |
6666 | { | 6907 | { // Let's see if the proper tmux server is even running. |
6667 | char *d; | 6908 | memset(toybuf, 0, sizeof(toybuf)); |
6909 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s -q list-sessions 2>/dev/null | grep -q %s:", Tcmd, scRun, Tsocket, Tconsole); | ||
6910 | i = system(toybuf); | ||
6911 | if (WIFEXITED(i)) | ||
6912 | { | ||
6913 | if (0 != WEXITSTATUS(i)) // No such session, create it. | ||
6914 | { | ||
6915 | memset(toybuf, 0, sizeof(toybuf)); | ||
6916 | if (strcmp(pw->pw_name, scUser) == 0) | ||
6917 | { | ||
6918 | snprintf(toybuf, sizeof(toybuf), | ||
6919 | "%s %s/%s new-session -d -s %s -n '%s' \\; split-window -bhp 50 -t '%s:' bash -c '/usr/bin/valgrind --leak-check=full ./sledjchisl; cd %s; bash'", | ||
6920 | Tcmd, scRun, Tsocket, Tconsole, Ttab, Tconsole, scRoot); | ||
6921 | } | ||
6922 | else | ||
6923 | { | ||
6924 | // The sudo is only so that the session is owned by opensim, otherwise it's owned by whoever ran this script, which is a likely security hole. | ||
6925 | // After the session is created, we rely on the scRun directory to be group sticky, so that anyone in the opensim group can attach to the tmux socket. | ||
6926 | snprintf(toybuf, sizeof(toybuf), | ||
6927 | "sudo -Hu %s %s %s/%s new-session -d -s %s -n '%s' \\; split-window -bhp 50 -t '%s:' bash -c '/usr/bin/valgrind --leak-check=full ./sledjchisl; cd %s; bash'", | ||
6928 | scUser, Tcmd, scRun, Tsocket, Tconsole, Ttab, Tconsole, scRoot); | ||
6929 | } | ||
6930 | i = system(toybuf); | ||
6931 | if (!WIFEXITED(i)) | ||
6932 | E("tmux new-session command failed! %s", toybuf); | ||
6933 | } | ||
6934 | // Join the session. | ||
6935 | memset(toybuf, 0, sizeof(toybuf)); | ||
6936 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s select-window -t '%s' \\; attach-session -t '%s'", Tcmd, scRun, Tsocket, Tconsole, Tconsole); | ||
6937 | i = system(toybuf); | ||
6938 | if (!WIFEXITED(i)) | ||
6939 | E("tmux attach-session command failed! %s", toybuf); | ||
6940 | goto finished; | ||
6941 | } | ||
6942 | else | ||
6943 | E("tmux list-sessions command failed! %s", toybuf); | ||
6944 | } | ||
6668 | 6945 | ||
6669 | // Doing this here coz at this point we should be the correct user. | 6946 | |
6670 | if ((! qfile_exist(scBin)) && (! qfile_mkdir(scBin, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scBin); | 6947 | // Doing this here coz at this point we should be the correct user. |
6671 | if ((! qfile_exist(scEtc)) && (! qfile_mkdir(scEtc, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scEtc); | 6948 | I("Making directories in %s.", scRoot); |
6672 | if ((! qfile_exist(scLib)) && (! qfile_mkdir(scLib, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scLib); | 6949 | if ((! qfile_exist(scBin)) && (! qfile_mkdir(scBin, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scBin); |
6673 | if ((! qfile_exist(scRun)) && (! qfile_mkdir(scRun, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_ISGID, true))) C("Unable to create path %s", scRun); | 6950 | if ((! qfile_exist(scEtc)) && (! qfile_mkdir(scEtc, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scEtc); |
6674 | if ((! qfile_exist(scBackup)) && (! qfile_mkdir(scBackup, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scBackup); | 6951 | if ((! qfile_exist(scLib)) && (! qfile_mkdir(scLib, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scLib); |
6952 | if ((! qfile_exist(scRun)) && (! qfile_mkdir(scRun, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_ISGID, true))) C("Unable to create path %s", scRun); | ||
6953 | if ((! qfile_exist(scBackup)) && (! qfile_mkdir(scBackup, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scBackup); | ||
6675 | // TODO - the path to scCache/sledjchisl.socket needs to be readable by the www-data group. So the FCGI socket will work. | 6954 | // TODO - the path to scCache/sledjchisl.socket needs to be readable by the www-data group. So the FCGI socket will work. |
6676 | // AND it needs to be group sticky on opensimsc group. So the tmux socket will work. | 6955 | // AND it needs to be group sticky on opensimsc group. So the tmux socket will work. |
6677 | // So currently scCache is www-data readable, and scRun is group sticky. | 6956 | // So currently scCache is www-data readable, and scRun is group sticky. |
6678 | if ((! qfile_exist(scCache)) && (! qfile_mkdir(scCache, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scCache); | 6957 | if ((! qfile_exist(scCache)) && (! qfile_mkdir(scCache, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scCache); |
6679 | if ((! qfile_exist(scData)) && (! qfile_mkdir(scData, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scData); | 6958 | if ((! qfile_exist(scData)) && (! qfile_mkdir(scData, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scData); |
6680 | if ((! qfile_exist(scLog)) && (! qfile_mkdir(scLog, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scLog); | 6959 | if ((! qfile_exist(scLog)) && (! qfile_mkdir(scLog, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scLog); |
6681 | tmp = xmprintf("%s/sessions", scCache); | 6960 | if ((! qfile_exist(scTemp)) && (! qfile_mkdir(scTemp, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", scTemp); |
6682 | if ((! qfile_exist(tmp)) && (! qfile_mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", tmp); | 6961 | tmp = xmprintf("%s/sessions", scCache); |
6683 | free(tmp); | 6962 | if ((! qfile_exist(tmp)) && (! qfile_mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", tmp); |
6684 | tmp = xmprintf("%s/users", scData); | 6963 | free(tmp); |
6685 | if ((! qfile_exist(tmp)) && (! qfile_mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", tmp); | 6964 | tmp = xmprintf("%s/users", scData); |
6686 | free(tmp); | 6965 | if ((! qfile_exist(tmp)) && (! qfile_mkdir(tmp, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP, true))) C("Unable to create path %s", tmp); |
6966 | free(tmp); | ||
6967 | |||
6968 | getSims(); | ||
6687 | 6969 | ||
6688 | 6970 | ||
6971 | if (isTmux || isWeb) | ||
6972 | { | ||
6973 | char *d; | ||
6974 | |||
6689 | mimeTypes = qhashtbl(0, 0); | 6975 | mimeTypes = qhashtbl(0, 0); |
6690 | mimeTypes->putstr(mimeTypes, "gz", "application/gzip"); | 6976 | mimeTypes->putstr(mimeTypes, "gz", "application/gzip"); |
6691 | mimeTypes->putstr(mimeTypes, "js", "application/javascript"); | 6977 | mimeTypes->putstr(mimeTypes, "js", "application/javascript"); |
@@ -7159,111 +7445,312 @@ fcgiDone: | |||
7159 | } | 7445 | } |
7160 | 7446 | ||
7161 | 7447 | ||
7162 | if (!isTmux) | ||
7163 | { // Let's see if the proper tmux server is even running. | ||
7164 | memset(toybuf, 0, sizeof(toybuf)); | ||
7165 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s -q list-sessions 2>/dev/null | grep -q %s:", Tcmd, scRun, Tsocket, Tconsole); | ||
7166 | i = system(toybuf); | ||
7167 | if (WIFEXITED(i)) | ||
7168 | { | ||
7169 | if (0 != WEXITSTATUS(i)) // No such sesion, create it. | ||
7170 | { | ||
7171 | memset(toybuf, 0, sizeof(toybuf)); | ||
7172 | // The sudo is only so that the session is owned by opensim, otherwise it's owned by whoever ran this script, which is a likely security hole. | ||
7173 | // After the session is created, we rely on the scRun directory to be group sticky, so that anyone in the opensim group can attach to the tmux socket. | ||
7174 | snprintf(toybuf, sizeof(toybuf), | ||
7175 | "sudo -Hu %s %s %s/%s new-session -d -s %s -n '%s' \\; split-window -bhp 50 -t '%s:' bash -c '/usr/bin/valgrind --leak-check=full ./sledjchisl; cd %s; bash'", | ||
7176 | scUser, Tcmd, scRun, Tsocket, Tconsole, Ttab, Tconsole, scRoot); | ||
7177 | i = system(toybuf); | ||
7178 | if (!WIFEXITED(i)) | ||
7179 | E("tmux new-session command failed! %s", toybuf); | ||
7180 | } | ||
7181 | // Join the session. | ||
7182 | memset(toybuf, 0, sizeof(toybuf)); | ||
7183 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s select-window -t '%s' \\; attach-session -t '%s'", Tcmd, scRun, Tsocket, Tconsole, Tconsole); | ||
7184 | i = system(toybuf); | ||
7185 | if (!WIFEXITED(i)) | ||
7186 | E("tmux attach-session command failed! %s", toybuf); | ||
7187 | goto finished; | ||
7188 | } | ||
7189 | else | ||
7190 | E("tmux list-sessions command failed! %s", toybuf); | ||
7191 | } | ||
7192 | 7448 | ||
7449 | char *target = NULL; | ||
7450 | struct sysinfo info; | ||
7451 | float la; | ||
7452 | // TODO - See https://stackoverflow.com/questions/2693948/how-do-i-retrieve-the-number-of-processors-on-c-linux, there are more portable ways, this seems to be GNU specific. | ||
7453 | int cpus = (int) sysconf(_SC_NPROCESSORS_CONF), cpusOnline = (int) sysconf(_SC_NPROCESSORS_ONLN); | ||
7454 | int doWait = 1; | ||
7455 | |||
7456 | if (0 == bulkSims) | ||
7457 | bulkSims = (cpusOnline / 3) - 1; | ||
7458 | I("There are %i CPUs, %i of them are online. Doing %i sims at once.", cpus, cpusOnline, bulkSims); | ||
7459 | sysinfo(&info); | ||
7460 | la = info.loads[0]/65536.0; | ||
7461 | |||
7462 | if (0 == toys.optc) | ||
7463 | ; | ||
7464 | else if (strcmp(toys.optargs[0], "create") == 0) | ||
7465 | currentMode = CREATE; | ||
7466 | else if (strcmp(toys.optargs[0], "start") == 0) | ||
7467 | currentMode = START; | ||
7468 | else if (strcmp(toys.optargs[0], "backup") == 0) | ||
7469 | currentMode = BACKUP; | ||
7470 | else if (strcmp(toys.optargs[0], "gitar") == 0) | ||
7471 | currentMode = GITAR; | ||
7472 | else if (strcmp(toys.optargs[0], "status") == 0) | ||
7473 | currentMode = STATUS; | ||
7474 | else if (strcmp(toys.optargs[0], "stop") == 0) | ||
7475 | currentMode = STOP; | ||
7476 | else | ||
7477 | target = toys.optargs[0]; | ||
7478 | if (2 == toys.optc) | ||
7479 | target = toys.optargs[1]; | ||
7480 | |||
7481 | T("ARGS - %i |%s| |%s|", currentMode, toys.optargs[0], target); | ||
7193 | 7482 | ||
7194 | simList *sims = getSims(); | 7483 | if ((START == currentMode) && !checkSimIsRunning("ROBUST")) |
7195 | if (1) | ||
7196 | { | 7484 | { |
7197 | struct sysinfo info; | 7485 | char *d = xmprintf("%s.{right}", Ttab); |
7198 | float la; | 7486 | char *c = xmprintf("cd %s/current/bin", scRoot); |
7199 | 7487 | ||
7200 | sysinfo(&info); | 7488 | I("ROBUST is starting up."); |
7201 | la = info.loads[0]/65536.0; | 7489 | sendTmuxCmd(d, c); |
7490 | free(c); | ||
7491 | c = xmprintf("mono Robust.exe -inidirectory=%s/config/ROBUST", scRoot); | ||
7492 | sendTmuxCmd(d, c); | ||
7493 | free(c); | ||
7494 | waitTmuxText(d, "INITIALIZATION COMPLETE FOR ROBUST"); | ||
7495 | I("ROBUST is done starting up."); | ||
7496 | la = waitLoadAverage(la, loadAverageInc / 3.0, simTimeOut / 3); | ||
7497 | free(d); | ||
7498 | } | ||
7202 | 7499 | ||
7203 | if (!checkSimIsRunning("ROBUST")) | 7500 | /* |
7204 | { | 7501 | sims = -- Note these are .shini / tmux tab short names. |
7205 | char *d = xmprintf("%s.{right}", Ttab); | 7502 | { |
7206 | char *c = xmprintf("cd %s/current/bin", scRoot); | 7503 | {["type"] = "Important"; "Welcome", "Sandbox", "Shops"}, |
7207 | 7504 | {["type"] = "Rentals"; "Karen", "Bob"}, | |
7208 | I("ROBUST is starting up."); | 7505 | {["type"] = "Freebies"; "Gifts", "Free"}, |
7209 | sendTmuxCmd(d, c); | 7506 | {["type"] = "unsorted"; "New"}, -- NOTE - this is where new ones go to by default. |
7210 | free(c); | 7507 | {["type"] = "Water"; ["number"] = 90; "Water0", "Water1", "Water2", "Water3", "Water4"}, |
7211 | c = xmprintf("mono Robust.exe -inidirectory=%s/config/ROBUST", scRoot); | 7508 | {["type"] = "Heavies"; ["number"] = 70; "DP", "ARSE"}, |
7212 | sendTmuxCmd(d, c); | 7509 | } |
7213 | free(c); | 7510 | */ |
7214 | waitTmuxText(d, "INITIALIZATION COMPLETE FOR ROBUST"); | 7511 | memset(toybuf, 0, sizeof(toybuf)); |
7215 | I("ROBUST is done starting up."); | 7512 | snprintf(toybuf, sizeof(toybuf), "%s/sims.lua", scEtc); |
7216 | la = waitLoadAverage(la, loadAverageInc / 3.0, simTimeOut / 3); | 7513 | if (0 == lstat(toybuf, &st)) |
7217 | free(d); | 7514 | { |
7218 | } | 7515 | int number = 1, count = 1; |
7219 | 7516 | ||
7220 | for (i = 0; i < sims->num; i++) | 7517 | I("Loading configuration file - %s", toybuf); |
7518 | status = luaL_loadfile(L, toybuf); | ||
7519 | if (status) // If something went wrong, error message is at the top of the stack. | ||
7520 | E("Couldn't load file: %s", lua_tostring(L, -1)); | ||
7521 | else | ||
7221 | { | 7522 | { |
7222 | char *sim = sims->sims[i], *name = getSimName(sims->sims[i]); | 7523 | result = lua_pcall(L, 0, LUA_MULTRET, 0); |
7223 | 7524 | if (result) | |
7224 | if (!checkSimIsRunning(sim)) | 7525 | E("Failed to run script: %s", lua_tostring(L, -1)); |
7526 | else | ||
7225 | { | 7527 | { |
7226 | char *nm = cleanSimName(name); | 7528 | lua_getglobal(L, "sims"); |
7227 | 7529 | ||
7228 | I("%s is starting up.", name); | 7530 | lua_pushnil(L); // lua_next() needs the last key at the top, but we don't start with one. |
7229 | memset(toybuf, 0, sizeof(toybuf)); | 7531 | while(lua_next(L, -2) != 0) // pushes key then value. |
7230 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s new-window -dn '%s' -t '%s:%d' 'cd %s/current/bin; mono OpenSim.exe -inidirectory=%s/config/%s'", | 7532 | { // key -2 value -1 |
7231 | Tcmd, scRun, Tsocket, nm, Tconsole, i + 1, scRoot, scRoot, sim); | 7533 | if (lua_istable(L, -1)) |
7232 | int r = system(toybuf); | 7534 | { |
7233 | if (!WIFEXITED(r)) | 7535 | const char *type = "unsorted"; |
7234 | E("tmux new-window command failed!"); | 7536 | |
7235 | else | 7537 | lua_getfield(L, -1, "type"); |
7236 | { | 7538 | lua_getfield(L, -2, "number"); |
7237 | memset(toybuf, 0, sizeof(toybuf)); | 7539 | if (LUA_TNIL != lua_type(L, -2)) type = lua_tostring(L, -2); |
7238 | snprintf(toybuf, sizeof(toybuf), "INITIALIZATION COMPLETE FOR %s", name); | 7540 | if (LUA_TNIL != lua_type(L, -1)) number = lua_tonumber(L, -1); |
7239 | waitTmuxText(nm, toybuf); | 7541 | lua_pop(L, 2); |
7240 | I("%s is done starting up.", name); | 7542 | |
7241 | la = waitLoadAverage(la, loadAverageInc, simTimeOut); | 7543 | T("Doing sims of type %s starting at number %d", type, number); |
7544 | lua_pushnil(L); | ||
7545 | while(lua_next(L, -2) != 0) | ||
7546 | { | ||
7547 | char *sim = (char *) lua_tostring(L, -1); | ||
7548 | |||
7549 | if (LUA_TNUMBER == lua_type(L, -2)) | ||
7550 | { | ||
7551 | int num; | ||
7552 | char *nm = NULL; | ||
7553 | char *name;// = getSimName(ourSims->sims[i], &nm, &num); | ||
7554 | qlisttbl_t *ini = ourSims->byTab->get(ourSims->byTab, sim, NULL, false); | ||
7555 | simData *simd; | ||
7556 | |||
7557 | if (NULL == ini) | ||
7558 | { | ||
7559 | E("Sim %s not found in ini list!", sim); | ||
7560 | } | ||
7561 | else | ||
7562 | { | ||
7563 | simd = ini->get(ini, "SIM DATA", NULL, false); | ||
7564 | name = simd->name; | ||
7565 | nm = simd->tab; | ||
7566 | } | ||
7567 | |||
7568 | if (NULL != target) | ||
7569 | { | ||
7570 | int cont = TRUE; | ||
7571 | |||
7572 | memset(toybuf, 0, sizeof(toybuf)); | ||
7573 | snprintf(toybuf, sizeof(toybuf), "%s.shini", nm); | ||
7574 | if | ||
7575 | ( | ||
7576 | (strcmp(target, sim) == 0) || | ||
7577 | // (strcmp(target, simd->nmbr) == 0) || | ||
7578 | (strcmp(target, name) == 0) || | ||
7579 | (strcmp(target, nm) == 0) || | ||
7580 | (strcmp(target, toybuf) == 0) | ||
7581 | ) | ||
7582 | cont = FALSE; | ||
7583 | memset(toybuf, 0, sizeof(toybuf)); | ||
7584 | snprintf(toybuf, sizeof(toybuf), "%s.ini", nm); | ||
7585 | if (strcmp(target, toybuf) == 0) | ||
7586 | cont = FALSE; | ||
7587 | memset(toybuf, 0, sizeof(toybuf)); | ||
7588 | snprintf(toybuf, sizeof(toybuf), "sim%d.ini", number); | ||
7589 | if (strcmp(target, toybuf) == 0) | ||
7590 | cont = FALSE; | ||
7591 | if (cont) | ||
7592 | goto nextSim; | ||
7593 | } | ||
7594 | |||
7595 | doWait = (count % bulkSims); | ||
7596 | switch (currentMode) | ||
7597 | { | ||
7598 | case START : // "start sim01" "start 'Welcome sim'" "start Welcome.ini" "start Welcome" "start" start everything | ||
7599 | { // TODO - check if sim is down, but tmux window is still up, and close the tmux window first. | ||
7600 | if (!checkSimIsRunning(nm)) | ||
7601 | { | ||
7602 | char *path = xmprintf("%s/%s.shini", scEtc, nm); | ||
7603 | char *newPath = xmprintf("%s/sim%d/%s.ini", scTemp, number, nm); // Coz OpenSim. | ||
7604 | char *cmd = xmprintf("rm -fr %s/sim%d; mkdir -p %s/sim%d; sed -E" | ||
7605 | " -e 's/InternalPort[[:space:]]*=[[:space:]]*[[:digit:]]+/InternalPort = %d/'" | ||
7606 | " -e 's/InternalPort[[:space:]]*=[[:space:]]*\"[[:digit:]]+\"/InternalPort = %d/'" | ||
7607 | " -e 's/http_listener_port[[:space:]]*=[[:space:]]*[[:digit:]]+/http_listener_port = %d/'" | ||
7608 | " -e 's/http_listener_port[[:space:]]*=[[:space:]]*\"[[:digit:]]+\"/http_listener_port = %d/'" | ||
7609 | " %s >%s", | ||
7610 | scTemp, number, | ||
7611 | scTemp, number, | ||
7612 | 8004 + number * 2, | ||
7613 | 8004 + number * 2, | ||
7614 | 8005 + number * 2, | ||
7615 | 8005 + number * 2, | ||
7616 | path, newPath); | ||
7617 | int j; | ||
7618 | |||
7619 | D("Writing .ini file %s with ports %d %d", newPath, 8004 + number * 2, 8005 + number * 2); | ||
7620 | j = system(cmd); | ||
7621 | if (!WIFEXITED(j)) | ||
7622 | E("sed command failed!"); | ||
7623 | free(cmd); | ||
7624 | |||
7625 | I("%s is starting up in tab [%d:%s], from %s/sim%d. %i %i", name, number, nm, scTemp, number, doWait, count); | ||
7626 | memset(toybuf, 0, sizeof(toybuf)); | ||
7627 | snprintf(toybuf, sizeof(toybuf), "%s %s/%s new-window -dn '%s' -t '%s:%d' 'cd %s/current/bin; mono OpenSim.exe -inidirectory=%s/sim%d'", | ||
7628 | Tcmd, scRun, Tsocket, nm, Tconsole, number, scRoot, scTemp, number); | ||
7629 | int r = system(toybuf); | ||
7630 | if (!WIFEXITED(r)) | ||
7631 | E("tmux new-window command failed!"); | ||
7632 | else | ||
7633 | { | ||
7634 | if (0 == doWait) | ||
7635 | { | ||
7636 | memset(toybuf, 0, sizeof(toybuf)); | ||
7637 | snprintf(toybuf, sizeof(toybuf), "INITIALIZATION COMPLETE FOR %s", name); | ||
7638 | waitTmuxText(nm, toybuf); | ||
7639 | I("%s is done starting up.", name); | ||
7640 | la = waitLoadAverage(la, loadAverageInc, simTimeOut); | ||
7641 | } | ||
7642 | else | ||
7643 | I("Not waiting for %s to finish starting up.", name); | ||
7644 | count++; | ||
7645 | } | ||
7646 | } | ||
7647 | break; | ||
7648 | } | ||
7649 | |||
7650 | case BACKUP : // "backup 'onefang rejected'" "backup sim01" "backup 'Welcome Sim'" "backup" backup everything | ||
7651 | { // TODO - If it's not a sim code, and not a sim name, it's an account inventory. | ||
7652 | if (checkSimIsRunning(nm)) | ||
7653 | { | ||
7654 | struct timeval tv; | ||
7655 | time_t curtime; | ||
7656 | char date[DATE_TIME_LEN]; | ||
7657 | |||
7658 | |||
7659 | // TODO - should collect names of existing backups, both tmux / ini name and proper name. | ||
7660 | // Scan backups directory once before this for loop, add details to sims list. | ||
7661 | // strip off the last bit of file name (YYYY-mm-dd_HH:MM:SS.oar) to get the name | ||
7662 | // keep in mind some old files had munged names like "Tiffanie_s_Paradise-2021-06-23_05:11:38.oar" | ||
7663 | gettimeofday(&tv, NULL); | ||
7664 | curtime = tv.tv_sec; | ||
7665 | strftime(date, DATE_TIME_LEN, "%F_%T", localtime(&curtime)); | ||
7666 | I("%s is being backed up to %s/backups/%s-%s.oar.", name, scRoot, nm, date); | ||
7667 | memset(toybuf, 0, sizeof(toybuf)); | ||
7668 | snprintf(toybuf, sizeof(toybuf), "save oar --all %s/backups/%s-%s.oar", scRoot, nm, date); | ||
7669 | sendTmuxCmd(nm, toybuf); | ||
7670 | // if (0 == doWait) | ||
7671 | { | ||
7672 | memset(toybuf, 0, sizeof(toybuf)); | ||
7673 | snprintf(toybuf, sizeof(toybuf), "Finished writing out OAR for %s", name); | ||
7674 | waitTmuxText(nm, toybuf); | ||
7675 | I("%s is done backing up.", name); | ||
7676 | // TODO - should delete / gitAR the old ones now. | ||
7677 | // Have a config option for delete / gitAR. | ||
7678 | la = waitLoadAverage(la, loadAverageInc, simTimeOut); | ||
7679 | } | ||
7680 | } | ||
7681 | break; | ||
7682 | } | ||
7683 | |||
7684 | case CREATE : // "create name x,y size" | ||
7685 | { | ||
7686 | break; | ||
7687 | } | ||
7688 | |||
7689 | case GITAR : // "gitAR i name" "gitAR o name" | ||
7690 | { | ||
7691 | break; | ||
7692 | } | ||
7693 | |||
7694 | case STATUS : | ||
7695 | { | ||
7696 | break; | ||
7697 | } | ||
7698 | |||
7699 | case STOP : // "stop sim01" "stop 'Welcome Sim'" "stop" stop everything | ||
7700 | { | ||
7701 | if (checkSimIsRunning(nm)) | ||
7702 | { | ||
7703 | I("%s is stopping.", name); | ||
7704 | sendTmuxCmd(nm, "quit"); | ||
7705 | // There's three things that might happen - | ||
7706 | // Sim will quit, tmux tab will go away before we can see the shutdown message. | ||
7707 | // Sim will quit, tmux tab wont go away. Dunno yet if waitTmuxText() will still work. | ||
7708 | // Sim fails to quit, error message on the tab that we want to read, wont see the shutdown message. | ||
7709 | // Also sim might not have finished starting up, and may even not be accepting comands yet. | ||
7710 | // TODO - cater for and test them all. | ||
7711 | // Could also loop on checkSimIsRunning(sim) | ||
7712 | // memset(toybuf, 0, sizeof(toybuf)); | ||
7713 | // snprintf(toybuf, sizeof(toybuf), "[SHUTDOWN]: Shutdown processing on main thread complete. Exiting..."); | ||
7714 | // waitTmuxText(nm, toybuf); | ||
7715 | // I("%s is done stopping.", name); | ||
7716 | // la = waitLoadAverage(la, loadAverageInc, simTimeOut); | ||
7717 | } | ||
7718 | break; | ||
7719 | } | ||
7720 | |||
7721 | default : | ||
7722 | { | ||
7723 | E("Unknown command! %s", toys.optargs[0]); | ||
7724 | break; | ||
7725 | } | ||
7726 | } | ||
7727 | nextSim: | ||
7728 | number++; | ||
7729 | } | ||
7730 | lua_pop(L, 1); // removes 'value'; keeps 'key' for next iteration | ||
7731 | } | ||
7732 | } | ||
7733 | |||
7734 | lua_pop(L, 1); | ||
7242 | } | 7735 | } |
7243 | free(nm); | ||
7244 | } | 7736 | } |
7245 | free(name); | ||
7246 | } | 7737 | } |
7247 | |||
7248 | } | ||
7249 | else if (!strcmp(cmd, "create")) // "create name x,y size" | ||
7250 | { | ||
7251 | } | ||
7252 | else if (!strcmp(cmd, "start")) // "start sim01" "start Welcome" "start" start everything | ||
7253 | { | ||
7254 | // TODO - check if sim is down, but tmux window is still up, and close the tmux window first. | ||
7255 | } | ||
7256 | else if (!strcmp(cmd, "backup")) // "backup onefang rejected" "backup sim01" "backup Welcome" "backup" backup everything | ||
7257 | { // If it's not a sim code, and not a sim name, it's an account inventory. | ||
7258 | } | 7738 | } |
7259 | else if (!strcmp(cmd, "gitAR")) // "gitAR i name" | 7739 | |
7260 | { | 7740 | |
7261 | } | 7741 | if ((START == currentMode) && checkSimIsRunning("ROBUST")) |
7262 | else if (!strcmp(cmd, "stop")) // "stop sim01" "stop Welcome" "stop" stop everything | ||
7263 | { | 7742 | { |
7743 | // Start up the web stuff. TODO - remove this once we handle the fcgi stuff ourselves. | ||
7744 | char *d = xmprintf("%s.{left}", Ttab); | ||
7745 | char *c = xmprintf("cd %s/current/src;" | ||
7746 | " spawn-fcgi -n -u %s -s %s/sledjchisl.socket -M 0660 -G www-data -- " | ||
7747 | "/usr/bin/valgrind --leak-check=full build/toybox/generated/unstripped/toybox sledjchisl", | ||
7748 | scRoot, scUser, scCache); | ||
7749 | sendTmuxCmd(d, c); | ||
7750 | free(c); | ||
7751 | free(d); | ||
7264 | } | 7752 | } |
7265 | 7753 | ||
7266 | freeSimList(sims); | ||
7267 | 7754 | ||
7268 | /* | 7755 | /* |
7269 | double sum; | 7756 | double sum; |
@@ -7328,6 +7815,7 @@ fcgiDone: | |||
7328 | */ | 7815 | */ |
7329 | 7816 | ||
7330 | finished: | 7817 | finished: |
7818 | freeSimList(ourSims); | ||
7331 | 7819 | ||
7332 | // An example of calling a toy directly. | 7820 | // An example of calling a toy directly. |
7333 | // printf("\n\n"); | 7821 | // printf("\n\n"); |