From be2491b093b1f0ca430bede679ecbb670041e483 Mon Sep 17 00:00:00 2001 From: cassio Date: Tue, 2 Jul 2013 09:46:45 +0400 Subject: restructuring of boca's git --- tools/.htaccess | 1 + tools/READMEubuntu.txt | 33 + tools/READMEvm.txt | 163 ++++ tools/autojudge.sh | 26 + tools/etc/apache2/conf.d/boca | 15 + tools/etc/cron.hourly/.placeholder | 2 + tools/etc/cron.hourly/ntp | 2 + tools/etc/icpc/becomeserver.sh | 213 +++++ tools/etc/icpc/bocaserver.sh | 1 + tools/etc/icpc/cleandisk.sh | 4 + tools/etc/icpc/createbocajail.sh | 122 +++ tools/etc/icpc/doclean.sh | 29 + tools/etc/icpc/installboca.sh | 190 +++++ tools/etc/icpc/restart.sh | 31 + tools/etc/icpc/setup.sh | 91 +++ tools/etc/icpc/update.sh | 14 + tools/etc/icpc/update.sh.tmp | 40 + tools/etc/icpc/updatedbpass.sh | 84 ++ tools/etc/network/if-pre-up.d/boca | 25 + tools/etc/network/if-up.d/boca | 17 + tools/etc/rc.local | 34 + tools/etc/sysctl.d/10-shmmax.conf | 2 + tools/etc/sysctl.d/10-vm-swappiness.conf | 1 + tools/fcontest.php | 1278 ++++++++++++++++++++++++++++++ tools/genpackage.sh | 51 ++ tools/icpc.etc.tgz | Bin 0 -> 9525 bytes tools/installv2.sh | 354 +++++++++ tools/makebkp.sh | 32 + tools/postgresql.conf.diffs | 5 + tools/safeexec.c | 523 ++++++++++++ tools/sendscore.sh | 69 ++ tools/singlefilebkp.sh | 46 ++ tools/updatescore.sh | 141 ++++ 33 files changed, 3639 insertions(+) create mode 100644 tools/.htaccess create mode 100644 tools/READMEubuntu.txt create mode 100644 tools/READMEvm.txt create mode 100755 tools/autojudge.sh create mode 100644 tools/etc/apache2/conf.d/boca create mode 100644 tools/etc/cron.hourly/.placeholder create mode 100755 tools/etc/cron.hourly/ntp create mode 100755 tools/etc/icpc/becomeserver.sh create mode 100755 tools/etc/icpc/bocaserver.sh create mode 100755 tools/etc/icpc/cleandisk.sh create mode 100755 tools/etc/icpc/createbocajail.sh create mode 100755 tools/etc/icpc/doclean.sh create mode 100755 tools/etc/icpc/installboca.sh create mode 100755 tools/etc/icpc/restart.sh create mode 100755 tools/etc/icpc/setup.sh create mode 100644 tools/etc/icpc/update.sh create mode 100644 tools/etc/icpc/update.sh.tmp create mode 100755 tools/etc/icpc/updatedbpass.sh create mode 100644 tools/etc/network/if-pre-up.d/boca create mode 100644 tools/etc/network/if-up.d/boca create mode 100755 tools/etc/rc.local create mode 100644 tools/etc/sysctl.d/10-shmmax.conf create mode 100644 tools/etc/sysctl.d/10-vm-swappiness.conf create mode 100644 tools/fcontest.php create mode 100755 tools/genpackage.sh create mode 100644 tools/icpc.etc.tgz create mode 100755 tools/installv2.sh create mode 100755 tools/makebkp.sh create mode 100644 tools/postgresql.conf.diffs create mode 100644 tools/safeexec.c create mode 100755 tools/sendscore.sh create mode 100755 tools/singlefilebkp.sh create mode 100755 tools/updatescore.sh (limited to 'tools') diff --git a/tools/.htaccess b/tools/.htaccess new file mode 100644 index 0000000..3a42882 --- /dev/null +++ b/tools/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/tools/READMEubuntu.txt b/tools/READMEubuntu.txt new file mode 100644 index 0000000..09994a8 --- /dev/null +++ b/tools/READMEubuntu.txt @@ -0,0 +1,33 @@ +ICPC Linux installation script +---------------------------------- +Copyright (c) 2009 C. P. de Campos. +Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +--------------------------------- +File last modified: 11/oct/2011 + +==> The installv2.sh script is not necessary if you are using the virtual machine version. This is intended to those that +want to install the system as the host of a computer, or desire to create again the virtual machine version from the beginning. + +The script installv2.sh available here was used to create the "ICPC Linux" image after a standard installation +of the ubuntu (or xubuntu) distribution. This is well-suitable in case you do not want to +use the virtualized version, for example, in the server of the contest. After using the installv2.sh script over a fresh +install of the ubuntu, you reach the exactly same content of the virtual machine version that is available. +Take care with the following points during the installation of the ubuntu: +1) Use the name "icpcadmin" and password "icpcadmin" (no quotes obviously) as the standard user during the installation. +2) Call the machine "icpc" (in the same screen where you set up the username above). +3) Use the simplest partitioning option (that is, everything in a single partition) and choose at least 10GB for it. + +After installing ubuntu, the system reboots. Download the script installv2.sh to the home directory of icpcadmin, +make it executable by chmod 755 installv2.sh, and run it as root: sudo ./installv2.sh +and reboot the system to finish the configuration (such as setting passwords, IPs, etc). +Note this is going to give you a system just like you would get from the box (the virtual machine version). If you +want it to become a server, you must follow the same procedure that is indicated in the READMEvm.txt. This +mainly means that you need to run the script /etc/icpc/becomeserver.sh + +The most recent installv2.sh script is available at http://www.ime.usp.br/~cassio/boca/ link named installv2.sh +In case of any questions, do not hesitate to contact me: bocasystem@gmail.com. Have fun! diff --git a/tools/READMEvm.txt b/tools/READMEvm.txt new file mode 100644 index 0000000..e78fca8 --- /dev/null +++ b/tools/READMEvm.txt @@ -0,0 +1,163 @@ +READMEvm.txt file of the ICPC Linux VM (release 2011) +================================= +Copyright (c) 2009-2011 C. P. de Campos. +Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +================================= +Last modified: 10/Oct/2011 + +This file concerns the ICPC Linux image available in this directory. It is a vmware-type +hard-disk image with a system built up over a ubuntu (or xubuntu) distribution. This is +also relevant if you have used the installv2.sh script to build the server natively, as the +system will have the exactly same characteristics of the VM version mentioned here. + +- You need the vmplayer from www.vmware.com to use this image. As far as I know, vmplayer is +free-of-charge for linux and windows hosts. Check it. There is another version based on virtualbox, +which is just a translation from the image here. virtualbox is free and works pretty well too. + +- Internet access is restricted inside the box. By default, users can only access +bombonera.ime.usp.br, the home of BOCA. During the first boot time, you are able to choose a +different IP address of your server instead of bombonera. If you are going to run a contest, +you must do that! The system inside the virtual machine (or just VM) will +only be able to access such server and nothing else. An alias with the name boca is created +for such IP, so it is possible to connect to it using the name boca instead of typing the +IP address. So, during the first initialization of each VM you should configure the IP address +of your BOCA server. The image provided here can be used as a BOCA server too. See next bullets +on how to do that. In the team machines, check if the internet is really blocked. If not, the +initialization scripts might be malfunctioning, or the computer might be mistakenly set to be +a server (this can be easily checked by verifying whether the file /etc/icpc/.isserver exists or not). + +- There are two linux users in the box: icpcadmin, which has right to become root using +sudo, and the user icpc. The latter has password icpc, and more restricted access. The user +icpc is intended to be used by the teams, judges, staff, or anyone else. The icpcadmin is +an administrative account and the password must be known only by the sysadmin, director of the +contest, and so on. During the first boot time, you are able to change the password of the icpcadmin +account. DO IT and keep it safe! The default password is icpcadmin. Note that such +users (icpcadmin and icpc) have nothing to do with users of the BOCA web system. Each +team must have a distinct user to login on BOCA, which are configured through the BOCA web interface. +Still, each team will logon into the linux box using the same user: icpc. As mentioned, this is +not a security problem because the user icpc is just a local account in the linux system without +any privileges. + +- To run a contest using a virtual machine, you probably need at least 384MB of RAM inside a +"good" computer (then you can configure the VM to run with 256MB). I have tested the vm image +configured to use 512MB. If your host has for example 1GB, you may change the vmplayer +to use 768MB, although 512 should be fine too. Just keep some room for the underlying operating +system. Using more memory inside the vm is better for the teams, so they can run heavier tools. + +- Unzipped, the image takes around 12 GB of your hard disk. You need this space in the hard +disk of each computer. If this is a problem for you, it is possible to rebuild the vm system +with less space (8GB for clients is enough, the server has to have more). + +- It is possible to maximize the VM window so as it uses the whole screen area. The current +image is set to 800x600 or 1024x768 pixels, but that can probably be increased depending on your +video card and monitor settings. The keyboard config can also be changed +inside the x-window system configurations. + +- During the first startup, an script will ask you for the BOCA database password (after +asking the BOCA server IP address and password of the icpcadmin). YOU MUST ONLY FILL +SUCH PASSWORD IN THERE IF the machine being configured is NOT going to be used by a team. With +this password, it will be possible to access the database directly (instead of by web). Teams +shall access the system only by using the web interface. This password is intended to be used +in the machine that will have the autojudging system, as the autojudging script needs to +connect to the database directly (see next item about the autojudge). In fact only the +autojudging machine (or machines, if you have more than one) need this password to be set. + +- An autojugding machine is used to automatically compile and execute the codes submitted +by the teams. DO NOT run it on the same computer as the BOCA server (the web server and the database +server). Because teams may submit malicious code, it is safe to run it on a separate computer. +The worst scenario (in case a team's code hangs the computer) will require to reboot such +computer. About the configuration, the only difference between the autojudge computer and +team's computers is the setup of the database password, as mentioned before. You must set up +the database password during the initialization of the autojudging computer. Then, to run the +autojudging system, you need to login as icpcadmin (privileged user), open a command-line +terminal (it is inside accessories), and run "sudo /var/www/boca/tools/autojudge.sh" (without quotes). +If everything is fine, some dots will appear on the screen while the script runs an infinite +loop waiting for submissions. Ctrl-C stops the autojudge. The autojudging shall be started +after configuring the server to run the contest, otherwise it will eventually output an error or +freeze. If you see the dots happening every few seconds, you are in the correct track. + +- With old versions of ICPC Linux, all the team files were kept in the server. Now this is +NOT true anymore. Everything is stored locally. So, after a warmup and before the real +contest, it is necessary to go to each team computer, open a command-line shell (you do not +need to change to the privileged user, the unprivilegied icpc user is enough) and run +the command +/etc/icpc/cleandisk.sh +After that, reboot the system inside the virtual machine (not the host computer itself!) and you +are done. All files belonging to the icpc user have been erased. + +- Because the files are stored in the local team computers, now BOCA (by web) has an option +to make file backups, where teams can save their files on the server. Currently this must be done +manually by the teams (using the web interface of BOCA). There is a script available inside the +ICPC linux (and inside the BOCA package) that teams may use to backup their files. To +do that, they can just run "makebkp.sh". If they want to save other files, it is possible to use +the web interface of the teams. Note that teams should submit backup files with small size only, but +that is not a problem because source codes are really small. The script makebkp.sh is available +(but not very tested) which sends files .c, .cpp, .java and .in (it looks for these files in the +current directory) to the server. IT IS IMPORTANT TO LET THE TEAMS KNOW ABOUT THIS SITUATION AND +THE POSSIBILITY OF SAVING FILES TO THE SERVER, EITHER BY USING THE makebkp.sh IN THE COMMAND-LINE, +OR BY DIRECTLY UPLOADING THE FILES IN THE WEB INTERFACE. + +- The most complicated thing to run the contest using a VM is that you need to restrict the +use of the host operating system. For example, it would be possible for a team to switch +the window (from the VM to another program), and then use the internet (in case you have +internet available in the host, which is usually true). I believe that the simplest approach +to restrict the system is to impose a set of packet filtering rules in the host system, using +a firewall solution. That would make the host system useless for the team. The only permission +that the host must have is to allow connections to the BOCA server and (possibly) to the +authentication server of your network (in case it is needed to keep the host running. Better +if that can be avoided too). If your host is linux, then it is easy: you just need to include some +rules in the iptables (certainly a sysadmin knows how to do it). +For windows (which is probably more usual and easy to deal with), there are many free-of-charge +solutions. I do not know them well, but let me cite some: www.r-firewall.com, +www.personalfirewall.comodo.com, tiny personal firewall (it is possible to find it online), +perhaps the windows firewall can be enough (in some windows versions). NOW THE MOST COMMON / +PRACTICAL WAY TO SOLVE THE PROBLEM: keep an eye on the teams all the time. Have some volunteers +looking the teams work on the computers during the whole contest. No one is allowed to leave the +VM and use the underlying system. If they do that, then simply expel them from the contest! +Give a warn of the possible penalty to everyone before starting and that is it. Quick and clean :D + +- Any vm can become a server for the contest, which in this case will be a BOCA server running +inside a virtual machine system. To do that, you just need to login as user +icpcadmin, become root using the command "sudo /bin/bash" +and execute the script /etc/icpc/becomeserver.sh +READ THE FULL TEXT BEFORE RUNNING THIS SCRIPT. THE VM MUST BE IN BRIDGE MODE (see explanation +below). At this moment, you will be prompted to define the DB password or use a random one. After +that, the IP address of this computer must be used to configure all other VMs (during those +startup questions). +Some considerations about a server: more memory must be used for the server. Have a computer +with enough memory and increase the memory of the VM. Also take care with the +disk space. The current image has only around 1.6GB free (still, that must be more than enough). +Finally, note that to run the VM as the server, it must be configured to run in BRIDGE mode +with respect to the network interface, otherwise it will not be possible for other computers +to reach it. BRIDGE mode means that you must look in your vmplayer (whatever player you are using) +to configure the network as in BRIDGE mode). You may need to reboot the VM. If after rebooting it +and running the command-line program "ifconfig" you can see that the IP address of your computer +is the same inside the VM and outside, you are done. Besides that, the underlying operating +system must have NO apache or postgresql running, nor +any other TCP server in the ports 80 (http), 443 (https) and 5432 (postgres). +Yet I point out that running the BOCA system in a server computer (without the VM) +is the mostly tested solution, but the VM version was used in many sites already. If you want to +run it natively, stop here and go to the xubuntu directory of bombonera.ime.usp.br to see the +instructions. You will need a computer that you can format and reinstall. +That is the simplest way of having a full ICPC linux server +running apart from using the VM version itself, as explained here. + +- After having the server and clients running up, it is necessary to configure the BOCA +web system. For that purpose, please follow the steps of the ADMIN.txt file in the doc/ +folder of the boca system. It is available in the BOCA package or inside the ICPC +linux at /var/www/boca/doc/. There are some examples inside the bits/ subfolder. + +- Try to use the vm without fear. In the worst case, download it again and start again +(or even better, keep a copy of the image without changes). Any questions, please +do not hesitate to contact me: bocasystem@gmail.com. + +- If you need to update the BOCA system that is running in your server (with the risk of losing +data in the database of BOCA!), then you may run the script /etc/icpc/installboca.sh +If you need to update general scripts that are used in the system and were installed by the +installv2.sh procedure, you may run the script /etc/icpc/installscripts.sh +These are easy ways to update the system in case bugs are found and fixed. diff --git a/tools/autojudge.sh b/tools/autojudge.sh new file mode 100755 index 0000000..6123eed --- /dev/null +++ b/tools/autojudge.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program 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. +# // +# // This program 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 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 . +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 06/aug/2012 by cassio@ime.usp.br +if [ "`id -u`" != "0" ]; then + echo "Must be run as root" + exit 1 +fi +bocadir=/var/www/boca +[ -r /etc/boca.conf ] && . /etc/boca.conf +cd $bocadir/src +php private/autojudging.php diff --git a/tools/etc/apache2/conf.d/boca b/tools/etc/apache2/conf.d/boca new file mode 100644 index 0000000..66c62fe --- /dev/null +++ b/tools/etc/apache2/conf.d/boca @@ -0,0 +1,15 @@ + + AllowOverride Options AuthConfig Limit + Order Allow,Deny + Allow from all + AddDefaultCharset utf-8 + + + AllowOverride Options AuthConfig Limit + Deny from all + + + AllowOverride Options AuthConfig Limit + Deny from all + +Alias /boca /var/www/boca/src diff --git a/tools/etc/cron.hourly/.placeholder b/tools/etc/cron.hourly/.placeholder new file mode 100644 index 0000000..76cb8d0 --- /dev/null +++ b/tools/etc/cron.hourly/.placeholder @@ -0,0 +1,2 @@ +# DO NOT EDIT OR REMOVE +# This file is a simple placeholder to keep dpkg from removing this directory diff --git a/tools/etc/cron.hourly/ntp b/tools/etc/cron.hourly/ntp new file mode 100755 index 0000000..40ea135 --- /dev/null +++ b/tools/etc/cron.hourly/ntp @@ -0,0 +1,2 @@ +#!/bin/bash +ntpdate -u 143.107.255.15 diff --git a/tools/etc/icpc/becomeserver.sh b/tools/etc/icpc/becomeserver.sh new file mode 100755 index 0000000..4de2084 --- /dev/null +++ b/tools/etc/icpc/becomeserver.sh @@ -0,0 +1,213 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program 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. +# // +# // This program 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 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 . +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 06/aug/2012 by cassio@ime.usp.br +for i in id chown chmod cut awk grep cat sed makepasswd ifconfig iptables php touch mkdir update-rc.d su rm mv; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done + +if [ "`id -u`" != "0" ]; then + echo "Must be run as root" + exit 1 +fi +bocadir=/var/www/boca +[ -r /etc/boca.conf ] && . /etc/boca.conf + +privatedir=$bocadir/src/private +if [ ! -d $privatedir ]; then + echo "Could not find directory $privatedir" + exit 1 +fi + +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser >/dev/null 2>/dev/null +if [ $? != 0 ]; then + echo "User $apacheuser not found -- error to set permissions with chown/chmod" + apacheuser=root +fi + +postgresuser=postgres +id -u $postgresuser >/dev/null 2>/dev/null +if [ $? != 0 ]; then + echo "User $postgresuser not found -- maybe you use another name (then update this script) or postgres is not installed" + exit 1 +fi + +grep -iq "iface.*eth0.*inet.*static" /etc/network/interfaces +if [ $? != 0 ]; then + echo "*****************************************" + echo "IMPORTANT NOTICE ************************" + echo "Network interface eth0 has to be set with" + echo "a static IP address for this computer to " + echo "be a proper server -- DO IT ASAP ********" + echo "*****************************************" + sleep 2 +fi + +BOCASERVER=localhost +if [ -f /etc/icpc/postgresql.version ]; then + . /etc/icpc/postgresql.version +else +POSTGRESV="" +if [ ! -f /etc/init.d/postgresql ]; then + POSTGRESV="-8.4" +fi +fi +if [ ! -f /etc/init.d/postgresql$POSTGRESV ]; then + echo "I did not find the correct version of postgres -- please check it and update this script" + exit 1 +fi + +for i in `ls /etc/postgresql/*/main/pg_hba.conf`; do + grep -q "host.*bocadb.*bocauser" $i + if [ $? != 0 ]; then + echo "############" + echo "I AM GIVING ACCESS TO THE DATABASE FROM ANY IP (AS LONG AS THE PASSWORD IS OK)" + echo "In order to improve security, it is possible to alter the file $i" + echo "and perform a finer tune. Nevertheless, if the password of the DB is safe, there is no big threat" + echo "For doing that, I am using the line:" + echo "" + echo -e "echo \"host bocadb bocauser 0/0 md5\" >> $i" + echo "" + echo "==> IDEALLY FOR IMPROVED SECURITY, REPLACE THE 0/0 ABOVE (IN THAT FILE) WITH THE IP ADDRESS OF THE AUTOJUDGE MACHINE <==" + echo "==> IF YOU HAVE MULTIPLE AUTOJUDGE MACHINES, WRITE ONE LINE FOR EACH IP ADDRESS THERE IN THE FILE <==" + echo "############" + echo "host bocadb bocauser 0/0 md5" >> $i + else + echo "############" + echo "IT SEEMS YOU ALREADY HAVE MODIFIED THE FILE $i WITH BOCA'S INFORMATION" + echo "I WOULD USE THE LINE:" + echo "" + echo -e "echo \"host bocadb bocauser 0/0 md5\" >> $i" + echo "" + echo "to give access to the database to other computers, but" + echo ">>> I'M NOT DOING IT -- PLEASE CHECK IT <<<" + echo "############" + fi +done + +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*listen_addresses" $i +if [ $? != 0 ]; then + echo "listen_addresses = '*'" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*max_connections" $i +if [ $? != 0 ]; then + echo "max_connections = 100" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*maintenance_work_mem" $i +if [ $? != 0 ]; then + echo "maintenance_work_mem = 64MB" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*shared_buffers" $i +if [ $? != 0 ]; then + echo "shared_buffers = 128MB" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*work_mem" $i +if [ $? != 0 ]; then + echo "work_mem = 4MB" >> $i +fi +done + +echo "You need to define a password to be used in the database." +echo -n "It is possible generate a random one. Want a random password " +read -p "[Y/n]? " OK +if [ "$OK" = "n" ]; then + read -p "Enter DB password: " -s PASS +else + PASS=`makepasswd --char 8` + echo "The DB password is $PASS" +fi +echo "Keep the DB password safe!" +echo "The IP address that is computer is using is" +echo "(check using the command ifconfig, if desired. Use this address to configure other computers)" +ifconfig eth0 | grep -i "inet addr" + +PASSK=`makepasswd --chars 20` +awk -v boca="$BOCASERVER" -v pass="$PASS" -v passk="$PASSK" '{ if(index($0,"[\"dbpass\"]")>0) \ + print "$conf[\"dbpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"dbhost\"]")>0) print "$conf[\"dbhost\"]=\"" boca "\";"; \ + else if(index($0,"[\"dbsuperpass\"]")>0) print "$conf[\"dbsuperpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"key\"]")>0) print "$conf[\"key\"]=\"" passk "\";"; else print $0; }' \ + < $privatedir/conf.php > $privatedir/conf.php1 +mv -f $privatedir/conf.php1 $privatedir/conf.php +echo "Deny from all" > $privatedir/.htaccess +chown -R $apacheuser.root $privatedir +chmod -R u+rw,g+rw,o-rw $privatedir +iptables -F +echo "BOCASERVER=0/0" > /etc/icpc/bocaserver.sh + + +grep -iq "^[^\#]*ServerName" /etc/apache2/apache2.conf +if [ $? != 0 ]; then + echo "ServerName boca" >> /etc/apache2/apache2.conf +fi + +/etc/init.d/apache2 restart +mkdir -p /var/run/postgresql +chown $postgresuser.$postgresuser /var/run/postgresql +/etc/init.d/postgresql$POSTGRESV restart +update-rc.d apache2 defaults +update-rc.d postgresql$POSTGRESV defaults + +rm -f /tmp/.boca.tmp +su - $postgresuser -c "echo select contestnumber from contesttable | psql -d bocadb | grep contestnumber >/tmp/.boca.tmp 2>/tmp/.boca.tmp" +su - $postgresuser -c "echo drop user bocauser | psql -d template1 >/dev/null 2>/dev/null" +su - $postgresuser -c "echo create user bocauser createdb password \'$PASS\' | psql -d template1" +su - $postgresuser -c "echo alter user bocauser createdb password \'$PASS\' | psql -d template1" + +OK=y +grep -qi contestnumber /tmp/.boca.tmp +if [ $? == 0 ]; then + OK=x + while [ "$OK" != "y" -a "$OK" != "n" ]; do + echo "====== An old database seems to exist. I can keep it, but it might not work with the version" + echo -n "of BOCA being installed. May I erase all the content of the bocadb database [y/n]" + OK=x + read -p "?" OK + done +fi +if [ "$OK" == "y" ]; then +cd $bocadir/src +php private/createdb.php +cd - >/dev/null 2>/dev/null + echo "database renewed. Data on bocadb has been lost" +else + echo "*** database not erased. Check if BOCA is compatible. You can always erase the database and" + echo "*** fix the problem by running (as root) cd $bocadir/src; php private/createdb.php" + echo "*** still, all data regarding BOCA in the database will be lost" +fi +touch /etc/icpc/.isserver + +echo "configuration finished. Boca should be available at http://localhost/boca/" +echo "reboot might not be required, but is advised." diff --git a/tools/etc/icpc/bocaserver.sh b/tools/etc/icpc/bocaserver.sh new file mode 100755 index 0000000..8bb6c2c --- /dev/null +++ b/tools/etc/icpc/bocaserver.sh @@ -0,0 +1 @@ +BOCASERVER=127.0.0.1 diff --git a/tools/etc/icpc/cleandisk.sh b/tools/etc/icpc/cleandisk.sh new file mode 100755 index 0000000..0d177de --- /dev/null +++ b/tools/etc/icpc/cleandisk.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +mkdir -p /home/icpc +/usr/bin/touch /home/icpc/.cleandisk.sh diff --git a/tools/etc/icpc/createbocajail.sh b/tools/etc/icpc/createbocajail.sh new file mode 100755 index 0000000..bd8bd5d --- /dev/null +++ b/tools/etc/icpc/createbocajail.sh @@ -0,0 +1,122 @@ +#!/bin/bash +homejail=/home/bocajail +[ "$1" != "" ] && homejail=$1 +echo "=================================================================================" +echo "============= CREATING $homejail (this might take some time) ===============" +echo "=================================================================================" +for i in setquota ln id chown chmod dirname useradd mkdir cp rm mv apt-get dpkg uname debootstrap schroot; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +if [ "`id -u`" != "0" ]; then + echo "Must be run as root" + exit 1 +fi +if [ ! -r /etc/lsb-release ]; then + echo "File /etc/lsb-release not found. Is this a ubuntu or debian-like distro?" + echo "If so, execute the command" + echo "" + echo "DISTRIB_CODENAME=WXYZ > /etc/lsb-release" + echo "" + echo "to save the release name to that file (replace WXYZ with your distro codename)" + exit 1 +fi +. /etc/lsb-release +if [ -d /bocajail/ ]; then + echo "You seem to have already a /bocajail installed" + echo "If you want to reinstall, remove it first (e.g. rm /bocajail) and then run /etc/icpc/createbocajail.sh" + exit 1 +fi + +if [ -f $homejail/proc/cpuinfo ]; then + echo "You seem to have already installed /bocajail and the /bocajail/proc seems to be mounted" + chroot $homejail umount /sys >/dev/nul 2>/dev/null + chroot $homejail umount /proc >/dev/nul 2>/dev/null + echo "Please reboot the system to remove such mounted point" + exit 1 +fi + +id -u bocajail >/dev/null 2>/dev/null +if [ $? != 0 ]; then + useradd -m -s /bin/bash -d $homejail -g users bocajail + if [ -d /etc/gdm ]; then + echo -e "[greeter]\nExclude=bocajail,nobody\n" >> /etc/gdm/custom.conf + fi + sleep 1 +else + echo "user bocajail already exists" + echo "if you want to proceed, first remove it (e.g. userdel bocajail) and then run /etc/icpc/createbocajail.sh" + exit 1 +fi +setquota -u bocajail 0 500000 0 10000 -a + +rm -rf /bocajail +mkdir -p $homejail/tmp +chmod 1777 $homejail/tmp +ln -s $homejail /bocajail +[ -x /usr/bin/safeexec ] && cp -a /usr/bin/safeexec /bocajail/usr/bin/ +#for i in usr lib var bin sbin etc dev; do +# [ -d $homejail/$i ] && rm -rf $homejail/$i +# cp -ar /$i $homejail +#done +#rm -rf $homejail/var/lib/postgres* +#rm -rf $homejail/var/www/* +#mkdir -p $homejail/proc +#mkdir -p $homejail/sys +uname -m | grep -q 64 +if [ $? == 0 ]; then + archt=amd64 +else + archt=i386 +fi + +cat < /etc/schroot/chroot.d/bocajail.conf +[bocajail] +description=Jail +location=$homejail +directory=$homejail +root-users=root +type=directory +users=bocajail,nobody,root +FIM + +#debootstrap --arch $archt $DISTRIB_CODENAME $homejail +debootstrap $DISTRIB_CODENAME $homejail +if [ $? != 0 ]; then + echo "bocajail failed to debootstrap" + exit 1 +else +schroot -l | grep -q bocajail +if [ $? == 0 ]; then + echo "bocajail successfully installed at $homejail" +else + echo "*** some error has caused bocajail not to install properly -- I will try it again with different parameters" + grep -v "^location" /etc/schroot/chroot.d/bocajail.conf > /tmp/.boca.tmp + mv /tmp/.boca.tmp /etc/schroot/chroot.d/bocajail.conf + debootstrap $DISTRIB_CODENAME $homejail + schroot -l | grep -q bocajail + if [ $? == 0 ]; then + echo "*** bocajail successfully installed at $homejail" + else + echo "*** bocajail failed to install" + exit 1 + fi +fi +fi + +echo "*** Populating $homejail" +cat < /home/bocajail/tmp/populate.sh +#!/bin/bash +mount -t proc proc /proc +apt-get -y update +apt-get -y install g++ gcc libstdc++6 sharutils default-jdk default-jre +umount /proc +EOF +cp -f /etc/apt/sources.list $homejail/etc/apt/ +chmod 755 /home/bocajail/tmp/populate.sh +cd / ; chroot $homejail /tmp/populate.sh diff --git a/tools/etc/icpc/doclean.sh b/tools/etc/icpc/doclean.sh new file mode 100755 index 0000000..40b49c1 --- /dev/null +++ b/tools/etc/icpc/doclean.sh @@ -0,0 +1,29 @@ +#!/bin/bash +cd /home +if [ -f /home/icpc/.cleandisk.sh ]; then +rm -rf /home/icpc +find /home -user icpc -delete +if [ -x /usr/bin/makepasswd ]; then + pass=`echo -n icpc | /usr/bin/makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` + pass=\$`echo $pass` + id -u icpc >/dev/null 2>/dev/null + if [ $? != 0 ]; then + useradd -d /home/icpc -k /etc/skel -m -p "$pass" -s /bin/bash -g users icpc + else + usermod -d /home/icpc -p "$pass" -s /bin/bash -g users icpc + fi +fi +for i in media mnt var opt tmp usr; do + find /$i -user icpc -delete +done +if [ ! -d /home/icpc ]; then + rm -rf /home/icpc + rm -rf /home/skel + cp -ar /etc/skel/ /home + mv /home/skel /home/icpc +fi +chown -R icpc.users /home/icpc +chmod -R u+rwx /home/icpc +fi +cd - >/dev/null +exit 0 diff --git a/tools/etc/icpc/installboca.sh b/tools/etc/icpc/installboca.sh new file mode 100755 index 0000000..55d8d18 --- /dev/null +++ b/tools/etc/icpc/installboca.sh @@ -0,0 +1,190 @@ +#!/bin/bash +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi + +di=`date +%s` +echo "===================================================" +echo "=================== obtaining BOCA ===============" +echo "===================================================" + +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/boca.date.txt" +echo ">>>>>>>>>>" +echo ">>>>>>>>>> Downloading boca release `cat /tmp/.boca.tmp`" +echo ">>>>>>>>>>" + +if [ "$1" == "" ]; then +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/bocaver.txt" +bocaver=`cat /tmp/.boca.tmp` +else +bocaver=$1 +fi + +if [ "$2" == "" ]; then +basedir=/var/www +else +if [ -d "$2" ]; then +basedir=$2 +else +echo "Directory $2 does not exist" +exit 1 +fi +fi + +OK=y +read -p "I will install boca at $basedir is it correct (otherwise, run this script as: $0 $bocaver to choose the place) [Y/n]? " OK +if [ "$OK" == "y" -o "$OK" == "Y" ]; then +echo "Install directory is $basedir" +else +echo "Aborted" +exit 1 +fi + +echo "Looking for BOCA version $bocaver from http://www.ime.usp.br/~cassio/boca/" +cd $basedir +rm -f boca-$bocaver.tgz +wget -O boca-$bocaver.tgz "http://www.ime.usp.br/~cassio/boca/download.php?filename=boca-$bocaver.tgz" +if [ "$?" != "0" -o ! -f boca-$bocaver.tgz ]; then + echo "ERROR downloading BOCA package version $bocaver. Aborting *****************" + exit 1 +fi +grep -qi "bad parameters" boca-$bocaver.tgz +if [ "$?" == "0" ]; then + echo "ERROR downloading BOCA package version $bocaver. Aborting *****************" + exit 1 +fi +echo "===========================================================" +echo "====================== BACKUPING OLD BOCA ===============" +echo "===========================================================" +if [ -d boca-$bocaver ]; then + mv boca-$bocaver boca-$bocaver.$di + echo "OLD BOCA FOLDER for version $bocaver saved as boca-$bocaver.$di" +fi + +echo "bocadir=$basedir/boca" > /etc/boca.conf +chmod 644 /etc/boca.conf + +echo "=====================================================" +echo "=================== EXTRACTING BOCA ===============" +echo "=====================================================" + +OK=x +conffile=boca/src/private/conf.php +if [ ! -f $conffile ]; then +conffile=boca-$bocaver.$di/src/private/conf.php +fi +if [ -f $conffile ]; then + echo "OLD CONFIG FILE EXISTS" + OK=x + while [ "$OK" != "y" -a "$OK" != "n" ]; do + OK=x + read -p "Do you want to keep the old private/conf.php file [y/n] (note that the old file might be incompatible with this version)? " OK + done + if [ "$OK" == "n" ]; then + echo "You probably need to update the new file boca-$bocaver/src/private/conf.php with the correct passwords - PLEASE CHECK IT - NOT DONE AUTOMATICALLY" + fi +else + echo "OLD Config file not found -- you must set up the new private/conf.php file properly" +fi + +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser >/dev/null 2>/dev/null +if [ $? != 0 ]; then + echo "User $apacheuser not found -- error to set permissions with chown/chmod" + apacheuser=root +fi + +tar xzf boca-$bocaver.tgz +chown -R root.$apacheuser boca-$bocaver/ +chmod -R g+rx,u+rwx boca-$bocaver/ + +chmod 600 boca-$bocaver/src/private/*.php +[ -f boca-$bocaver.$di/src/private/remotescores/otherservers ] && cp -f boca-$bocaver.$di/src/private/remotescores/otherservers boca-$bocaver/src/private/remotescores/otherservers +if [ "$OK" == "y" ]; then + cp -f $conffile boca-$bocaver/src/private/conf.php +fi +chmod 700 boca-$bocaver/tools/*.sh + +cat > boca-$bocaver/src/.htaccess < boca-$bocaver/tools/.htaccess < /etc/apache2/conf.d/boca < + AllowOverride Options AuthConfig Limit + Order Allow,Deny + Allow from all + AddDefaultCharset utf-8 + + + AllowOverride Options AuthConfig Limit + Deny from all + + + AllowOverride Options AuthConfig Limit + Deny from all + +Alias /boca $basedir/boca/src +EOF diff --git a/tools/etc/icpc/restart.sh b/tools/etc/icpc/restart.sh new file mode 100755 index 0000000..8c6c98c --- /dev/null +++ b/tools/etc/icpc/restart.sh @@ -0,0 +1,31 @@ +#!/bin/bash +uid=`id -u` +if [ "$uid" != "0" ]; then + echo "Must be root to run this script. Use sudo /bin/bash first" + exit 1 +fi + +apt-get clean +if [ -f /etc/icpc/postgresql.version ]; then + . /etc/icpc/postgresql.version +else +POSTGRESV="" +if [ ! -f /etc/init.d/postgresql ]; then + POSTGRESV="-8.4" +fi +fi + +pass=\$`echo -n icpc | makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` +usermod -p "$pass" icpc + +rm -f /etc/icpc/.isserver +rm -f /etc/icpc/.firsttimedone +rm -f /etc/icpc/bocaserver.sh +/etc/icpc/cleandisk.sh +/etc/init.d/apache2 stop +/etc/init.d/postgresql$POSTGRESV stop +rm -f /var/log/apache2/* +rm -f /var/log/postgresql/* +update-rc.d -f apache2 remove +update-rc.d -f postgresql$POSTGRESV remove + diff --git a/tools/etc/icpc/setup.sh b/tools/etc/icpc/setup.sh new file mode 100755 index 0000000..a854581 --- /dev/null +++ b/tools/etc/icpc/setup.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +if [ ! -x /etc/icpc/bocaserver.sh ]; then + OK=1 + while [ "$OK" != "0" ]; do + IP=`zenity --title="Setting up the BOCA server IP number" --text="Enter the IP address of the server (format x.y.w.z)\n\ +If this is supposed to be the server, then leave it empty" --width=500 --height=100 --entry` + [ "$IP" == "" ] && IP=LOCAL + zenity --title="IP confirmation" --text="The chosen IP is $IP\nDo you confirm?" --question + OK=$? + done + if [ "$IP" = "local" -o "$IP" = "LOCAL" ]; then + IP=127.0.0.1 + BOCASERVER=0/0 + fi + echo "BOCASERVER=$IP" > /etc/icpc/bocaserver.sh + echo "$IP boca boca" >> /etc/hosts + chmod 755 /etc/icpc/bocaserver.sh +fi +. /etc/icpc/bocaserver.sh + +if [ ! -f /etc/icpc/.firsttimedone ]; then + + zenity --title="PAY ATTENTION TO THE FOLLOWING:" \ + --text="It is HIGHLY recommended that you set up a super-user password NOW. Set up the super-user password now?" --question + OK=$? + if [ "$OK" == "0" ]; then + id -u icpcadmin 2>\dev\null >\dev\null + if [ "$?" == "0" ]; then + OK=1 + while [ $OK != 0 ]; do + pass=`zenity --title="Setting up a icpcadmin password" --text="Take care \ + to keep it safe. icpcadmin is the user that \n\ + can become root using the command sudo, e.g. \n\ + sudo /bin/bash \n\ + TEAMS WILL USE THE ACCOUNT icpc, WITH PASSWORD\n\ + icpc. THEY MUST NOT KNOW THE PASSWORD YOU\n\ + ARE SETTING UP HERE, WHICH IS A PRIVILEGIED USER.\n\ + If you need to change the password later, you \n\ + must know the current password and use the \n\ + command-line passwd to change it. Do not forget it" --entry --hide-text` + pass2=`zenity --title="Setting up a icpcadmin password" --text="Re-type it" --entry --hide-text` + if [ "$pass" == "$pass2" -a "$pass" != "" ]; then + OK=0 + else + zenity --info --title="Error" --text="Passwords do not match" + fi + done + pass=\$`/bin/echo -n "$pass2" | /usr/bin/makepasswd --clearfrom - --crypt-md5 | /usr/bin/cut -d'$' -f2-` + pass2="" + /usr/sbin/usermod -p "$pass" icpcadmin + pass=`echo -n icpc | makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` + pass=\$`echo $pass` + /usr/sbin/usermod -p "$pass" icpc + zenity --info --title="Updated" --text="Password of icpcadmin should be updated\nIf not, login in and change it to something safe" + else + zenity --info --title="Update error" --text="User icpcadmin not found -- update your password by yourself." + fi + fi + + if [ "$BOCASERVER" != "0/0" ]; then + OK=1 + while [ $OK != 0 ]; do + pass=`zenity --title="Setting up password of BOCA database" --text="Enter the password of the BOCA database IF AND ONLY IF \n\ +this is NOT a team machine. The password must be entered \n\ +in case this machine will be used for autojudging. \n\ +If you do not enter a password now, it is possible to do \n\ +it later using the command-line /etc/icpc/updatedbpass.sh \n\ +IF THIS IS GOING TO BE USED BY A TEAM, THEN JUST \n\ +PRESS ENTER WITHOUT TYPING ANY PASSWORD\n\ +If this is a server, you may also leave this field empty" --entry --hide-text` + if [ "$pass" == "" ]; then + break + fi + pass2=`zenity --title="Setting up password of BOCA database" --text="Re-type it" --entry --hide-text` + if [ "$pass" == "$pass2" -a "$pass" != "" ]; then + OK=0 + /etc/icpc/updatedbpass.sh "$pass" + else + zenity --info --title="Error" --text="Passwords do not match" + fi + done + fi + touch /etc/icpc/.firsttimedone + zenity --info --title="Setup completed" --text="The setup is completed. If you want to do it again, you might \n\ +run the command-line /etc/icpc/restart.sh\nbut some files in this computer (e.g. from the icpc user) might be lost." +fi + +if [ -x /etc/network/if-pre-up.d/boca ]; then + . /etc/network/if-pre-up.d/boca +fi diff --git a/tools/etc/icpc/update.sh b/tools/etc/icpc/update.sh new file mode 100644 index 0000000..f6b4bb6 --- /dev/null +++ b/tools/etc/icpc/update.sh @@ -0,0 +1,14 @@ +#!/bin/bash +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi +wget -O /tmp/update.sh "http://www.ime.usp.br/~cassio/boca/update.sh" +if [ $? != 0 ]; then + echo "ERROR DOWNLOADING UPDATE" + exit 1 +fi +echo ">>>>>>>>>>" +echo ">>>>>>>>>> Running update script" +echo ">>>>>>>>>>" +/tmp/update.sh +exit $? diff --git a/tools/etc/icpc/update.sh.tmp b/tools/etc/icpc/update.sh.tmp new file mode 100644 index 0000000..63a3858 --- /dev/null +++ b/tools/etc/icpc/update.sh.tmp @@ -0,0 +1,40 @@ +#!/bin/bash +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi + +echo "===================================================" +echo "=================== checking for updates ==========" +echo "===================================================" + +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/update.date.txt" +if [ $? != 0 ]; then + echo "ERROR DOWNLOADING UPDATE" + exit 1 +fi +di=`cat /tmp/.boca.tmp` +lastu=0 +if [ -r /etc/icpc/.lastupdate ]; then + lastu=`cat /etc/icpc/.lastupdate` +fi +if [ "$di" == "$lastu" ]; then + echo "NO UPDATES AVAILABLE" + exit 0 +fi + +echo ">>>>>>>>>>" +echo ">>>>>>>>>> Downloading update release `cat /tmp/.boca.tmp`" +echo ">>>>>>>>>>" + +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/update.sh" +if [ $? != 0 ]; then + echo "ERROR DOWNLOADING UPDATE" + exit 1 +fi + +echo ">>>>>>>>>>" +echo ">>>>>>>>>> Running update script" +echo ">>>>>>>>>>" +chmod 755 /tmp/.boca.tmp +/tmp/.boca.tmp +exit $? diff --git a/tools/etc/icpc/updatedbpass.sh b/tools/etc/icpc/updatedbpass.sh new file mode 100755 index 0000000..b100af5 --- /dev/null +++ b/tools/etc/icpc/updatedbpass.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program 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. +# // +# // This program 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 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 . +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 05/aug/2012 by cassio@ime.usp.br +privatedir=/var/www/boca/src/private + +if [ ! -d $privatedir ]; then + echo "Could not find directory $privatedir" + exit 1 +fi +for i in id chown chmod awk grep cat sed mv; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi + +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser >/dev/null 2>/dev/null +[ $? != 0 ] && echo "User $apacheuser not found -- error to set permissions with chown/chmod" + +BOCASERVER=localhost +[ -x /etc/icpc/bocaserver.sh ] && . /etc/icpc/bocaserver.sh +if [ "$BOCASERVER" = "0/0" -o "$BOCASERVER" = "" ]; then + BOCASERVER=localhost +fi +echo "BOCA server is configured to be $BOCASERVER" +if [ "$1" == "" ]; then + read -p "DB password: " -s PASS +else + zenity --info --title="Server info" --text="BOCA server is configured to be $BOCASERVER" + PASS=$1 +fi +PASSK=`makepasswd --chars 20` +awk -v boca="$BOCASERVER" -v pass="$PASS" -v passk="$PASSK" '{ if(index($0,"[\"dbpass\"]")>0) \ + print "$conf[\"dbpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"dbhost\"]")>0) print "$conf[\"dbhost\"]=\"" boca "\";"; \ + else if(index($0,"[\"dbsuperpass\"]")>0) print "$conf[\"dbsuperpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"key\"]")>0) print "$conf[\"key\"]=\"" passk "\";"; else print $0; }' \ + < $privatedir/conf.php > $privatedir/conf.php1 +mv -f $privatedir/conf.php1 $privatedir/conf.php +echo "Deny from all" > $privatedir/.htaccess +chown -R $apacheuser.root $privatedir +chmod -R u+rw,g+rw,o-rw $privatedir +echo "passwords updated in $privatedir/conf.php" + +postgresuser=postgres +id -u $postgresuser >/dev/null 2>/dev/null +if [ $? == 0 -a "$BOCASERVER" == "localhost" ]; then + echo "trying to update password for user bocauser in the database"; + rm -f /tmp/.boca.tmp + su - $postgresuser -c "echo select contestnumber from contesttable | psql -d bocadb | grep contestnumber >/tmp/.boca.tmp 2>/tmp/.boca.tmp" + su - $postgresuser -c "echo drop user bocauser | psql -d template1 >/dev/null 2>/dev/null" + su - $postgresuser -c "echo create user bocauser createdb password \'$PASS\' | psql -d template1 2>/dev/null" + su - $postgresuser -c "echo alter user bocauser createdb password \'$PASS\' | psql -d template1" + rm -f /tmp/.boca.tmp +fi + + +if [ "$1" != "" ]; then + zenity --info --title="Updated" --text="Password updated in $privatedir/conf.php file" +fi diff --git a/tools/etc/network/if-pre-up.d/boca b/tools/etc/network/if-pre-up.d/boca new file mode 100644 index 0000000..f65a27f --- /dev/null +++ b/tools/etc/network/if-pre-up.d/boca @@ -0,0 +1,25 @@ +#!/bin/bash +if [ ! -f /etc/icpc/.isserver ]; then +if [ -x /etc/icpc/bocaserver.sh ]; then + . /etc/icpc/bocaserver.sh +fi +/sbin/iptables -F INPUT +/sbin/iptables -A INPUT -i lo -j ACCEPT +/sbin/iptables -A INPUT -s 143.107.255.15 -j ACCEPT + +# just to make things easier, let's allow communication to/from BOCA servers +/sbin/iptables -A INPUT -s 143.107.45.122 -j ACCEPT +/sbin/iptables -A INPUT -s 50.116.19.221 -j ACCEPT + +if [ "$BOCASERVER" != "" ]; then + /sbin/iptables -A INPUT -s $BOCASERVER -j ACCEPT +fi +/sbin/iptables -A INPUT -m udp -p udp -s 0/0 --sport 67:68 --dport 67:68 -j ACCEPT +/sbin/iptables -A INPUT -m udp -p udp -s 0/0 --sport 53 --dport 53 -j ACCEPT +/sbin/iptables -A INPUT -m tcp -p tcp -s 0/0 --sport 53 --dport 53 -j ACCEPT +/sbin/iptables -A INPUT -j REJECT +else + if [ -x /etc/icpc/bocaserver.iptables ]; then + . /etc/icpc/bocaserver.iptables + fi +fi diff --git a/tools/etc/network/if-up.d/boca b/tools/etc/network/if-up.d/boca new file mode 100644 index 0000000..0f31ee0 --- /dev/null +++ b/tools/etc/network/if-up.d/boca @@ -0,0 +1,17 @@ +#!/bin/bash +if [ ! -f /etc/icpc/.isserver ]; then +if [ -x /etc/icpc/bocaserver.sh ]; then + . /etc/icpc/bocaserver.sh +fi +/sbin/iptables -F INPUT +/sbin/iptables -A INPUT -i lo -j ACCEPT +/sbin/iptables -A INPUT -s 143.107.255.15 -j ACCEPT +if [ "$BOCASERVER" != "" ]; then + /sbin/iptables -A INPUT -s $BOCASERVER -j ACCEPT +fi +/sbin/iptables -A INPUT -j REJECT +else + if [ -x /etc/icpc/bocaserver.iptables ]; then + . /etc/icpc/bocaserver.iptables + fi +fi diff --git a/tools/etc/rc.local b/tools/etc/rc.local new file mode 100755 index 0000000..2b0fff8 --- /dev/null +++ b/tools/etc/rc.local @@ -0,0 +1,34 @@ +#!/bin/bash +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +if [ -x /etc/icpc/doclean.sh ]; then + /etc/icpc/doclean.sh +fi + +grep -iq "iface.*eth0" /etc/network/interfaces +if [ $? != 0 ]; then + echo "auto eth0" >> /etc/network/interfaces + echo "iface eth0 inet dhcp" >> /etc/network/interfaces +fi + +grep -q "143.107.255.15.*ntp.usp.br.*ntp.usp.br" /etc/hosts +if [ $? != 0 ]; then + echo "143.107.255.15 ntp.usp.br ntp.usp.br" >> /etc/hosts +fi +grep -q "143.107.45.22.*www.ime.usp.br.*www.ime.usp.br" /etc/hosts +if [ $? != 0 ]; then + echo "143.107.45.22 www.ime.usp.br www.ime.usp.br" >> /etc/hosts +fi +ntpdate -u ntp.usp.br +ntpdate -u ntp.usp.br +exit 0 diff --git a/tools/etc/sysctl.d/10-shmmax.conf b/tools/etc/sysctl.d/10-shmmax.conf new file mode 100644 index 0000000..b645ff6 --- /dev/null +++ b/tools/etc/sysctl.d/10-shmmax.conf @@ -0,0 +1,2 @@ +kernel.shmmax = 805416960 +kernel.shmall = 196635 diff --git a/tools/etc/sysctl.d/10-vm-swappiness.conf b/tools/etc/sysctl.d/10-vm-swappiness.conf new file mode 100644 index 0000000..c062945 --- /dev/null +++ b/tools/etc/sysctl.d/10-vm-swappiness.conf @@ -0,0 +1 @@ +vm.swappiness=20 diff --git a/tools/fcontest.php b/tools/fcontest.php new file mode 100644 index 0000000..b8f59ca --- /dev/null +++ b/tools/fcontest.php @@ -0,0 +1,1278 @@ +. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 10/jul/2012 by cassio@ime.usp.br + +function DBDropContestTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"contesttable\"", "DBDropContestTable(drop table)"); +} +function DBCreateContestTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"contesttable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"contestname\" varchar(100) NOT NULL, -- (nome do concurso) + \"conteststartdate\" int4 NOT NULL, -- (dia/horario de inicio) + \"contestduration\" int4 NOT NULL, -- (duracao em segundos do contest) + \"contestlastmileanswer\" int4, -- (qtd segundos a partir do inicio para nao responder aos times) + \"contestlastmilescore\" int4, -- (qtd segundos a partir do inicio para nao atualizar placar) + \"contestlocalsite\" int4 NOT NULL, -- (id do site local com relacao a este servidor) + \"contestpenalty\" int4 NOT NULL, -- (qtd de segundos perdidos para cada run errada) + \"contestmaxfilesize\" int4 NOT NULL, -- (tamanho max em bytes dos codigos que podem ser submetidos) + \"contestactive\" bool NOT NULL, -- (indica se o contest esta ativo) + \"contestmainsite\" int4 NOT NULL, -- (id do site principal com relacao ao contest) + \"contestkeys\" text NOT NULL, -- (list of keys relevant to the contest) + \"contestunlockkey\" varchar(100) NOT NULL, -- (key to decrypt problem files) + \"contestmainsiteurl\" varchar(200) NOT NULL, -- (id do site principal com relacao ao contest) + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (esta tabela eh igual em todos os sites, com excecao do campo contestlocalsite, +-- que guarda qual o site local. Na verdade a ideia eh que todas as tabelas sejam +-- iguais em todos os sites.) + CONSTRAINT \"contest_pkey\" PRIMARY KEY (\"contestnumber\") +)", "DBCreateContestTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"contesttable\" FROM PUBLIC", "DBCreateContestTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"contesttable\" TO \"".$conf["dbuser"]."\"", "DBCreateContestTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"contestnumber_index\" ON \"contesttable\" USING btree ". + "(\"contestnumber\" int4_ops)", "DBCreateContestTable(create index)"); +} +function DBDropSiteTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"sitetable\"", "DBDropSiteTable(drop table)"); +} +function DBCreateSiteTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"sitetable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"sitenumber\" int4 NOT NULL, -- (id do local) + \"siteip\" varchar(200) NOT NULL, -- (ip publico do servidor do site) + \"sitename\" varchar(50) NOT NULL, -- (nome do local) + \"siteactive\" bool NOT NULL, -- (site ativo?) + \"sitepermitlogins\" bool NOT NULL, -- (logins estao aceitos?) + \"sitelastmileanswer\" int4, -- (hora (em seg do inicio) que este site para de responder aos times) + \"sitelastmilescore\" int4, -- (hora (em seg do inicio) que o placar eh congelado neste site) + \"siteduration\" int4, -- (tamanho da competicao em segundos) + \"siteautoend\" bool, -- (?) + \"sitejudging\" text, -- (indica quais sites sao julgados neste site) + \"sitetasking\" text, -- (indica quais sites sao processadas as tasks neste site) + \"siteglobalscore\" varchar(50) DEFAULT '' NOT NULL, -- (indica se este site deve mostrar placar global) + \"sitescorelevel\" int4 DEFAULT 0 NOT NULL, -- (indica o nivel de detalhes do placar exibido aos times) + \"sitenextuser\" int4 DEFAULT 0 NOT NULL, + \"sitenextclar\" int4 DEFAULT 0 NOT NULL, + \"sitenextrun\" int4 DEFAULT 0 NOT NULL, + \"sitenexttask\" int4 DEFAULT 0 NOT NULL, + \"sitemaxtask\" int4 DEFAULT 8 NOT NULL, + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) + \"sitechiefname\" varchar(20) DEFAULT '' NOT NULL, -- (username do juiz chefe, se existir) +-- (esta tabela contem uma linha para cada site do contest) + \"siteautojudge\" bool DEFAULT 'f', + \"sitemaxruntime\" int4 DEFAULT 600 NOT NULL, + \"sitemaxjudgewaittime\" int4 DEFAULT 900 NOT NULL, + CONSTRAINT \"site_pkey\" PRIMARY KEY (\"contestnumber\", \"sitenumber\"), + CONSTRAINT \"contest_fk\" FOREIGN KEY (\"contestnumber\") REFERENCES \"contesttable\" (\"contestnumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateSiteTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"sitetable\" FROM PUBLIC", "DBCreateSiteTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"sitetable\" TO \"".$conf["dbuser"]."\"", "DBCreateSiteTable(grant bocauser)"); + $r = DBexec($c, "CREATE UNIQUE INDEX \"site_index\" ON \"sitetable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops)", "DBCreateSiteTable(create index)"); +} +function DBDropSiteTimeTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"sitetimetable\"", "DBDropSiteTimeTable(drop table)"); +} +function DBCreateSiteTimeTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"sitetimetable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"sitenumber\" int4 NOT NULL, -- (id do local) + \"sitestartdate\" int4 NOT NULL, -- (hora que o local comecou) + \"siteenddate\" int4 NOT NULL, -- (hora que o local deve terminar, zero nao terminado) + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (esta tabela contem uma linha para cada reinicio de um site do contest) + CONSTRAINT \"sitetime_pkey\" PRIMARY KEY (\"contestnumber\", \"sitenumber\", \"sitestartdate\"), + CONSTRAINT \"site_fk\" FOREIGN KEY (\"contestnumber\", \"sitenumber\") + REFERENCES \"sitetable\" (\"contestnumber\", \"sitenumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateSiteTimeTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"sitetimetable\" FROM PUBLIC", "DBCreateSiteTimeTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"sitetimetable\" TO \"".$conf["dbuser"]."\"", "DBCreateSiteTimeTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"sitetime_index\" ON \"sitetimetable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops, \"sitestartdate\" int4_ops)", + "DBCreateSiteTimeTable(create index)"); + $r = DBexec($c, "CREATE INDEX \"sitetimesite_index\" ON \"sitetimetable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops)", "DBCreateSiteTimeTable(create site_index)"); +} +function DBDropUserTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"usertable\"", "DBDropUserTable(drop table)"); +} +function DBCreateUserTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"usertable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"usersitenumber\" int4 NOT NULL, -- (id do local do time) + \"usernumber\" int4 NOT NULL, -- (id do usuario) + \"username\" varchar(20) NOT NULL, -- (nome do usuario) + \"userfullname\" varchar(200) NOT NULL, -- (nome completo do usuario) + \"userdesc\" varchar(300), -- (descricao: escola ou integrantes ou etc) + \"usertype\" varchar(20) NOT NULL, -- (judge, team, admin, system) + \"userenabled\" bool DEFAULT 't' NOT NULL, -- (usuario ativo) + \"usermultilogin\" bool DEFAULT 'f' NOT NULL, -- (usuario pode se logar multiplas vezes) + \"userpassword\" varchar(200) DEFAULT '', -- (senha) + \"userip\" varchar(300), -- (ip do ult acesso) + \"userlastlogin\" int4, -- (data em seg desde epoch do ult login) + \"usersession\" varchar(50) DEFAULT '', -- (sessao do usuario) + \"usersessionextra\" varchar(50) DEFAULT '', -- (sessao do usuario) + \"userlastlogout\" int4, -- (data em seg desde epoch do ult logout) + \"userpermitip\" varchar(300), -- (ip permitido para acesso) + \"userinfo\" varchar(300) DEFAULT '', + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (esta tabela contem uma linha para cada usuario, seja ele administrador, juiz ou time. ) + \"usericpcid\" varchar(50) DEFAULT '', -- (compatibilidade com dados do ICPC) + CONSTRAINT \"user_pkey\" PRIMARY KEY (\"contestnumber\", \"usersitenumber\", \"usernumber\"), + CONSTRAINT \"site_fk\" FOREIGN KEY (\"contestnumber\", \"usersitenumber\") + REFERENCES \"sitetable\" (\"contestnumber\", \"sitenumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateUserTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"usertable\" FROM PUBLIC", "DBCreateUserTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"usertable\" TO \"".$conf["dbuser"]."\"", "DBCreateUserTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"user_index\" ON \"usertable\" USING btree ". + "(\"contestnumber\" int4_ops, \"usersitenumber\" int4_ops, \"usernumber\" int4_ops)", + "DBCreateUserTable(create user_index)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"user_index2\" ON \"usertable\" USING btree ". + "(\"contestnumber\" int4_ops, \"usersitenumber\" int4_ops, \"username\" varchar_ops)", + "DBCreateUserTable(create user_index2)"); +} + +//////////////////////////////funcoes de usuarios/sites/contests/////////////////////////////////////// +function DBFakeContest() { + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "insert into contesttable (contestnumber, contestname, conteststartdate, contestduration, ". + "contestlastmileanswer, contestlastmilescore, contestlocalsite, contestpenalty, contestmaxfilesize, ". + "contestactive, contestmainsite, contestmainsiteurl,contestkeys,contestunlockkey) " . + "values (0, 'Fake contest (just for initial purposes)', ". + "EXTRACT(EPOCH FROM now()), ". + "0, 0, 0, 1, 20*60, 100000, 't', 1, '', '', '')", "DBFakeContest(insert contest)"); + + DBExec($c, "insert into sitetable (contestnumber, sitenumber, siteip, sitename, siteactive, sitepermitlogins, ". + "sitelastmileanswer, sitelastmilescore, siteduration, siteautoend, sitejudging, sitetasking, ". + "siteglobalscore, sitescorelevel) ". + "values (0, 1, '', 'Fake Site (just for initial purposes)', ". + "'t', 't', 0, 0, 1, 't', '1', ". + "'1', '0', 4)", "DBFakeContest(insert site)"); + + $param['contest']=0; + $param['site']=1; + $param['start']=1; + DBRenewSiteTime($param, $c); + $cf = globalconf(); + $pass = myhash($cf["basepass"]); + DBExec($c, "insert into usertable (contestnumber, usersitenumber, usernumber, username, userfullname, ". + "userdesc, usertype, userenabled, usermultilogin, userpassword, userip, userlastlogin, usersession, ". + "userlastlogout, userpermitip) ". + "values (0, 1, 1, 'system', 'Systems', NULL, 'system', 't', ". + "'t', '$pass', NULL, NULL, '', NULL, NULL)", "DBFakeContest(insert system user)"); + DBExec($c, "commit work"); +} +function DBAllUserInfo($contest,$site=-1) { + $sql = "select * from usertable where contestnumber=$contest "; + if($site > 0) $sql .= "and usersitenumber=$site "; + $sql .= "order by usersitenumber, usernumber"; + $c = DBConnect(); + $r = DBExec ($c, $sql, "DBAllUserInfo(get users)"); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find users in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find users in the database!"); + } + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + $a[$i]['userpassword'] = myhash($a[$i]['userpassword'] . $a[$i]['usersessionextra']); + } + return $a; +} +function DBAllSiteTime($contest, $site) { + $sql = "select * from sitetimetable where contestnumber=$contest and sitenumber=$site order by sitestartdate"; + $c = DBConnect(); + $r = DBExec ($c, $sql, "DBAllSiteTime(get times)"); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find Site times in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find site times in the database!"); + } + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + + return $a; +} +function DBUserInfo($contest, $site, $user, $c=null,$hashpass=true) { + $sql = "select * from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + $a = DBGetRow ($sql, 0, $c); + if ($a == null) { + LOGError("Unable to find the user in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find the user in the database. Contact an admin now!"); + } + $a['changepassword']=true; + if(substr($a['userpassword'],0,1)=='!') { + $a['userpassword'] = substr($a['userpassword'],1); + $a['changepassword']=false; + } + if($hashpass) + $a['userpassword'] = myhash($a['userpassword'] . $a['usersessionextra']); + $inst = explode(']',$a['userfullname']); + if(isset($inst[1])) { + $a['userfullname'] = trim($inst[1]); + $inst = explode('[',$inst[0]); + if(isset($inst[1])) + $a['usershortname'] = trim($inst[1]); + } + $inst = explode(']',$a['userdesc']); + if(isset($inst[1])) { + $inst2 = explode('[',$inst[0]); + if(isset($inst2[1])) + $a['usershortinstitution'] = trim($inst2[0]); + if(isset($inst[2])) { + $a['userdesc']=trim($inst[2]); + $inst = explode('[',$inst[1]); + if(isset($inst[1])) { + $a['userinstitution'] = trim($inst[1]); + } + } else { + $a['userdesc']=trim($inst[1]); + } + } + return $a; +} +function DBDeleteUser($contest, $site, $user) { + if ($contest==$_SESSION["usertable"]["contestnumber"] && + $site==$_SESSION["usertable"]["usersitenumber"] && + $user==$_SESSION["usertable"]["usernumber"]) return false; + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table usertable"); + $sql = "select * from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + $a = DBGetRow ($sql, 0); + if ($a != null) { + $sql = "delete from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + DBExec ($c, $sql); + DBExec($c, "commit work"); + LOGLevel("User $user (site=$site,contest=$contest) removed.", 1); + return true; + } else { + DBExec($c, "rollback work"); + LOGLevel("User $user (site=$site,contest=$contest) could not be removed.", 1); + return false; + } +} +function DBSiteInfo($contest, $site, $c=null, $msg=true) { + $sql = "select * from sitetable where sitenumber=$site and contestnumber=$contest"; + if($c == null) $c = DBConnect(); + $r = DBExec($c, $sql); + if(DBnLines($r) < 1) { + if($msg) { + LOGError("Unable to find the site in the database (site=$site, contest=$contest). SQL=(" . $sql . ")"); + MSGError("Unable to find the site in the database. Contact an admin now!"); + } else return null; + } + $a = DBRow($r, 0); + + $sql = "select sitestartdate as s, siteenddate as e from sitetimetable ". + "where sitenumber=$site and contestnumber=$contest order by sitestartdate"; + $r = DBExec($c, $sql); + $n = DBnLines($r); + $a["currenttime"] = 0; + $a["siterunning"] = false; + $ti = time(); + for($i = 0; $i < $n; $i++) { + $b = DBRow($r, $i); + if($i == 0) $a["sitestartdate"] = $b["s"]; + if($b["e"] == 0) { + $a["siterunning"] = true; + $a["currenttime"] += $ti - $b["s"]; + } else + $a["currenttime"] += $b["e"] - $b["s"]; + $a["siteendeddate"] = $b["e"]; + } + if($a["siteendeddate"] == 0) $a["siteendeddate"] = $ti + $a["siteduration"] - $a["currenttime"]; + $a["siteautoended"] = false; + if($a["siteautoend"] == "t" && $a["currenttime"] >= $a["siteduration"]) { + $a["siterunning"] = false; + $a["siteautoended"] = true; + } + return $a; +} +function DBSiteLogoffAll($contest, $site) { + $c = DBConnect(); + DBExec($c, "begin work"); + $r = DBExec($c,"update usertable set usersessionextra='', usersession='', updatetime=".time()." where usertype!='admin' and " . + "contestnumber=$contest and usersitenumber=$site"); + $r = DBExec($c,"update usertable set userlastlogout=".time()." where usertype!='admin' and " . + "contestnumber=$contest and usersitenumber=$site and (userlastlogin>userlastlogout or " . + "(userlastlogout is null and userlastlogin is not null))"); + DBExec($c, "commit work"); + + LOGLevel("Logoff all (contest=$contest,site=$site).",2); +} + +function DBAllSiteInfo($contest) { + $sql = "select * from sitetable where contestnumber=$contest"; + $c = DBConnect(); + $r = DBExec ($c, $sql); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find sites in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find sites in the database!"); + } + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +function DBAllContestInfo() { + $sql = "select * from contesttable"; + $c = DBConnect(); + $r = DBExec ($c, $sql); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find contests in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find contests in the database!"); + } + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +function DBContestInfo($contest, $c=null) { + $sql = "select * from contesttable where contestnumber=$contest"; + $a = DBGetRow ($sql, 0, $c); + if ($a == null) { + LOGError("Unable to find the contest $contest in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find the contest $contest in the database. Contact an admin now!"); + return null; + } + return $a; +} +function DBGetActiveContest() { + $sql = "select * from contesttable where contestactive='t'"; + $a = DBGetRow ($sql, 0); + if ($a == null) { + LOGError("Unable to find active contests in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find active contests in the database."); + } + return $a; +} +function DBSiteStartNow ($contest, $site) { + $s = DBSiteInfo($contest, $site); + if($s["siterunning"]) return false; + $t = time(); + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table sitetimetable"); + DBExec($c, "update sitetimetable set siteenddate=".$s['siteendeddate']." where ". + "siteenddate=0 and sitenumber=$site and contestnumber=$contest"); + DBExec($c, "insert into sitetimetable (contestnumber, sitenumber, sitestartdate, siteenddate) ". + "values ($contest, $site, $t, 0)"); + DBExec($c, "commit work"); + LOGLevel("Site $site (contest=$contest) started at ".dateconv($t),2); + return true; +} +function DBSiteEndNow ($contest, $site, $w=0) { + $s = DBSiteInfo($contest, $site); + if(!$s["siterunning"]) return false; + if($w == 0) $t = time(); + else $t = $w; + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table runtable"); + $a = DBGetRow("select max(rundate) as t from runtable where contestnumber=$contest and ". + "runsitenumber=$site and not runstatus ~ 'deleted'", 0); + if($a["t"] >= $t) { + LOGLevel("Unable to stop a contest before an existing run",2); + MSGError("Impossible to stop a contest before an existing run"); + DBExec($c, "commit work"); + return false; + } + DBExec($c, "update sitetimetable set siteenddate=$t, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site and siteenddate=0"); + DBExec($c, "commit work"); + LOGLevel("Site $site (contest=$contest) stopped at ".dateconv(time()),2); + return true; +} +function DBSiteLogins ($contest, $site, $logins) { + $s = DBSiteInfo($contest, $site); + $param = $s; + $param['contestnumber']=$contest; + $param['sitenumber']=$site; + $param['sitepermitlogins']=$logins; + DBUpdateSite ($param); + LOGLevel("Site logins=$logins (contest=$contest)",2); +} +function DBSiteDeleteAllClars ($contest, $site, $user, $usersite, $c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table clartable"); + DBExec($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $r = DBExec($c, "select * from clartable as c where c.contestnumber=$contest and " . + "c.clarsitenumber=$site for update"); + DBExec($c, "delete from clartable where contestnumber=$contest and clarsitenumber=$site"); + DBExec($c, "update sitetable set sitenextclar=0, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Clarifications deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBSiteDeleteAllTasks ($contest, $site, $user, $usersite,$c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table tasktable"); + DBExec($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $r = DBExec($c, "select * from tasktable as t where t.contestnumber=$contest and " . + "t.sitenumber=$site for update"); + DBExec($c, "delete from tasktable where contestnumber=$contest and sitenumber=$site"); + DBExec($c, "update sitetable set sitenexttask=0, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Tasks deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBSiteDeleteAllBkps ($contest, $site, $user, $usersite,$c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table bkptable"); + $r = DBExec($c, "select bkpdata from bkptable where contestnumber=$contest and sitenumber=$site and bkpstatus='active'"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + DB_lo_unlink($c,$a["bkpdata"]); + } + DBExec($c, "delete from bkptable where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Bkps deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBSiteDeleteAllRuns ($contest, $site, $user, $usersite,$c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table runtable"); + DBExec($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $sql = "select * from runtable as r where r.contestnumber=$contest and " . + "r.runsitenumber=$site"; + $r = DBExec ($c, $sql . " for update"); + DBExec($c, "delete from runtable where contestnumber=$contest and runsitenumber=$site"); + DBExec($c, "update sitetable set sitenextrun=0, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Runs deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBUpdateSite ($param,$c=null) { + $ac=array('contestnumber','sitenumber','sitename','sitepermitlogins','sitescorelevel'); + $ac1=array('updatetime','siteautoend','siteglobalscore','siteip','siteactive','siteduration','sitelastmileanswer','sitelastmilescore', + 'siteautojudge','sitenextuser','sitenextclar','sitenextrun','sitenexttask','sitemaxtask','sitechiefname','sitejudging','sitetasking'); + + if(isset($param['number']) && !isset($param['sitenumber'])) $param['sitenumber']=$param['number']; + $type['contestnumber']=1; + $type['sitenumber']=1; + $type['updatetime']=1; + $type['siteduration']=1; + $type['sitelastmilescore']=1; + $type['sitelastmileanswer']=1; + $type['sitenextuser']=1; + $type['sitenextclar']=1; + $type['sitenextrun']=1; + $type['sitenexttask']=1; + $type['sitemaxtask']=1; + foreach($ac as $key) { + if(!isset($param[$key])) { + MSGError("DBUpdateSite param error: $key is not set"); + return false; + } + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateSite param error: $key is not numeric"); + return false; + } + } + $siteduration=-1; + $sitelastmileanswer=-1; + $sitelastmilescore=-1; + $sitenextuser = -1; + $sitenextclar = -1; + $sitenextrun = -1; + $sitenexttask = -1; + $sitemaxtask = -1; + $sitejudging = ''; + $sitetasking = ''; + $sitechiefname = ''; + $siteip=''; + $updatetime = -1; + $siteautojudge = 'f'; + $siteautoend='f'; + $siteglobalscore=''; + $siteactive='f'; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateSite param error: $key is not numeric"); + return false; + } + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + + if ($siteautoend != "t" && $siteautoend != "") $siteautoend = "f"; + if ($siteactive != "t" && $siteactive != "") $siteactive = "f"; + if ($siteautojudge != "t" && $siteautojudge != "") $siteautojudge = "f"; + if ($sitescorelevel == "" || !is_numeric($sitescorelevel)) $sitescorelevel = 0; + if ($sitescorelevel < -3) $sitescorelevel = -4; + if ($sitescorelevel > 3) $sitescorelevel = 4; + + $docommit=false; + if($c==null) { + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateSite(begin)"); + $docommit=true; + } + $a = DBGetRow ("select * from sitetable where contestnumber=$contestnumber and sitenumber=$sitenumber", 0, $c); + $ret=1; + if ($a == null) { + $ret=2; + $param['number']=$sitenumber; + DBNewSite($contestnumber,$c,$param); + $a = DBGetRow ("select * from sitetable where contestnumber=$contestnumber and sitenumber=$sitenumber", 0, $c); + if ($a == null) { + DBExec($c, "rollback work", "DBUpdateSite(rollback-errorsite)"); + MSGError("DBUpdateSite update error: impossible to create a site in the DB"); + LOGLevel("DBUpdateSite update error: impossible to create a site in the DB",0); + return false; + } + } + if($updatetime > $a['updatetime']) { + $ret=2; + if($sitenextrun==0) + DBSiteDeleteAllRuns($contestnumber,$sitenumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"],$c); + if($sitenextclar==0) + DBSiteDeleteAllClars($contestnumber,$sitenumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"],$c); + if($sitenexttask==0) + DBSiteDeleteAllTasks($contestnumber,$sitenumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"],$c); + + $sql = "update sitetable set sitename='$sitename', updatetime=".$updatetime.", "; + if ($sitepermitlogins!="") $sql .= "sitepermitlogins='$sitepermitlogins', "; + if ($siteduration > 0) + $sql .= "siteduration=$siteduration, "; + if($siteip != '') + $sql .= "siteip='$siteip',"; + if($siteautoend != "") + $sql .= "siteautoend='$siteautoend', "; + if($siteactive != "") + $sql .= "siteactive='$siteactive', "; + if($siteglobalscore != "") + $sql .= "siteglobalscore='$siteglobalscore', "; + if($sitenextuser >= 0) + $sql .= "sitenextuser=$sitenextuser, "; + if($sitenextclar >= 0) + $sql .= "sitenextclar=$sitenextclar, "; + if($sitenextrun >= 0) + $sql .= "sitenextrun=$sitenextrun, "; + if($sitenexttask >= 0) + $sql .= "sitenexttask=$sitenexttask, "; + if($sitemaxtask >= 0) + $sql .= "sitemaxtask=$sitemaxtask, "; + if($sitechiefname != '') + $sql .= "sitechiefname='$sitechiefname', "; + if($siteautojudge != '') + $sql .= "siteautojudge='$siteautojudge', "; + if($sitejudging != '') + $sql .= "sitejudging='$sitejudging', "; + if($sitetasking != '') + $sql .= "sitetasking='$sitetasking', "; + if($sitelastmileanswer > 0) + $sql .= " sitelastmileanswer=$sitelastmileanswer, "; + if($sitelastmilescore > 0) + $sql .= " sitelastmilescore=$sitelastmilescore, "; + $sql .= " sitescorelevel=$sitescorelevel where contestnumber=$contestnumber and sitenumber=$sitenumber " . + "and updatetime < $updatetime"; + DBExec($c,$sql, "DBUpdateSite(update site)"); + if($docommit) + DBExec($c, "commit work", "DBUpdateSite(commit-update)"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . + " changed the site $sitenumber (contest=$contestnumber) settings.",2); + } else { + if($docommit) + DBExec($c, "commit work", "DBUpdateSite(commit-noupdate)"); + } + return $ret; +} +function DBUpdateContest ($param, $c=null) { + if(isset($param['contestnumber']) && !isset($param['number'])) $param['number']=$param['contestnumber']; + + $ac=array('number'); + $ac1=array('updatetime','atualizasites','scorelevel','mainsite','localsite','mainsiteurl','keys','unlockkey', + 'active','lastmileanswer','lastmilescore','penalty','startdate', 'duration', 'maxfilesize'); + $type['number']=1; + $type['scorelevel']=1; + $type['startdate']=1; + $type['updatetime']=1; + $type['duration']=1; + $type['penalty']=1; + $type['maxfilesize']=1; + $type['active']=1; + $type['lastmilescore']=1; + $type['lastmileanswer']=1; + $type['mainsite']=1; + $type['localsite']=1; + foreach($ac as $key) { + if(!isset($param[$key])) { + MSGError("DBUpdateContest param error: $key is not set"); + return false; + } + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateContest param error: $key is not numeric"); + return false; + } + } + $name=''; + $atualizasites = false; + $mainsiteurl=''; + $keys=''; + $unlockkey=''; + $mainsite=-1; + $duration=-1; + $lastmilescore=-1; + $lastmileanswer=-1; + $penalty=-1; + $maxfilesize=-1; + $active=0; + $startdate=-1; + $localsite=-1; + $updatetime=-1; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateContest param error: $key is not numeric"); + return false; + } + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateContest(begin)"); + } + $a = DBGetRow("select * from contesttable where contestnumber=$number for update", 0, $c, "DBUpdateContest(get for update)"); + if($a == null) { + MSGError("Error updating contest $number -- not found"); + LOGError("DBUpdateContest contest $number not found"); + return false; + } + $ret=1; + if ($active == 1) { + $ret=2; + DBExec($c, "update contesttable set contestactive='f'", "DBUpdateContest(deactivate)"); + DBExec($c, "update contesttable set contestactive='t' where contestnumber=$number", + "DBUpdateContest(active)"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " activated contest $number.",2); + } + if($updatetime > $a['updatetime']) { + $ret=2; + $sql = "update contesttable set updatetime=".$updatetime; + if($name != '') $sql .= ", contestname='$name'"; + if($maxfilesize > 0) $sql .= ", contestmaxfilesize=$maxfilesize"; + if($penalty > 0) $sql .= ", contestpenalty=$penalty"; + if($lastmileanswer > 0) $sql .= ", contestlastmileanswer=$lastmileanswer"; + if($lastmilescore > 0) $sql .= ", contestlastmilescore=$lastmilescore"; + if($startdate > 0) $sql .= ", conteststartdate=$startdate"; + if($duration > 0) $sql .= ", contestduration=$duration"; + if ($mainsite > 0) $sql .= ", contestmainsite=$mainsite"; + if ($mainsiteurl != '') $sql .= ", contestmainsiteurl='$mainsiteurl'"; + if ($unlockkey != '') $sql .= ", contestunlockkey='$unlockkey'"; + if ($keys != '') $sql .= ", contestkeys='$keys'"; + if ($localsite > 0) $sql .= ", contestlocalsite=$localsite"; + $sql .= " where contestnumber=$number"; + DBExec($c, $sql, "DBUpdateContest(update contest)"); + + if($localsite > 0) { + $param['contestnumber']=$number; + $param['sitename']='Local site'; + if($duration > 0) + $param['siteduration']=$duration; + if(isset($param['scorelevel'])) + $param['sitescorelevel']=$scorelevel; + if($lastmileanswer > 0) + $param['sitelastmileanswer']=$lastmileanswer; + if($lastmilescore > 0) + $param['sitelastmilescore']=$lastmilescore; + $param['number']=$localsite; + DBNewSite ($number,$c,$param); + } + if($mainsite > 0) { + $param['contestnumber']=$number; + $param['sitename']='Main site'; + if($duration > 0) + $param['siteduration']=$duration; + if(isset($param['scorelevel'])) + $param['sitescorelevel']=$scorelevel; + if($lastmileanswer > 0) + $param['sitelastmileanswer']=$lastmileanswer; + if($lastmilescore > 0) + $param['sitelastmilescore']=$lastmilescore; + $param['number']=$mainsite; + DBNewSite ($number,$c,$param); + } + + if($atualizasites) { + $s = DBAllSiteInfo($number); + for($i=0; $i 0) + $param['siteduration']=$duration; + if(isset($param['scorelevel'])) + $param['sitescorelevel']=$scorelevel; + if($lastmileanswer > 0) + $param['sitelastmileanswer']=$lastmileanswer; + if($lastmilescore > 0) + $param['sitelastmilescore']=$lastmilescore; + + DBUpdateSite ($param,$c); + + if($startdate > 0) { + $p=array(); + $p['contest']=$number; + $p['site']=$s[$i]["sitenumber"]; + $p['start']=$startdate; + DBRenewSiteTime($p, $c); + } + } + } + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " changed the contest $number settings.",2); + } + if($cw) { + DBExec($c, "commit work", "DBUpdateContest(commit)"); + } + return $ret; +} +function DBRenewSiteTime($param, $c=null) { + if(!isset($param[0])) { + $tmp = $param; + $param = array(); + $param[0] = $tmp; + } + $ac=array('contest','site','start'); + $ac1=array('enddate','updatetime'); + $type['contest']=1; + $type['site']=1; + $type['start']=1; + $type['enddate']=1; + + $t = time(); + $maxtime = 0; + for($i=0; isset($param[$i]); $i++) { +// LOGLevel(implode(" ",array_keys($param[$i])),2); +// LOGLevel(implode(" ",$param[$i]),2); + if(isset($param[$i]['contestnumber']) && !isset($param[$i]['contest'])) $param[$i]['contest']=$param[$i]['contestnumber']; + if(isset($param[$i]['sitenumber']) && !isset($param[$i]['site'])) $param[$i]['site']=$param[$i]['sitenumber']; + foreach($ac as $key) { + if(!isset($param[$i][$key])) { + MSGError("DBRenewSiteTime param error: $key is not set"); + return false; + } + if(isset($type[$key]) && !is_numeric($param[$i][$key])) { + MSGError("DBRenewSiteTime param error: $key is not numeric"); + return false; + } + } + foreach($ac1 as $key) { + if(isset($param[$i][$key])) { + if(isset($type[$key]) && !is_numeric($param[$i][$key])) { + MSGError("DBRenewSiteTime param error: $key is not numeric"); + return false; + } + } + } + if(!isset($param[$i]['updatetime'])) $param[$i]['updatetime']=$t; + if($param[$i]['updatetime'] > $maxtime) $maxtime = $param[$i]['updatetime']; + if(!isset($param[$i]['enddate'])) $param[$i]['enddate']=0; + + if($param[$i]['contest'] != $param[0]['contest'] || $param[$i]['site'] != $param[0]['site']) { + MSGError("DBRenewSiteTime param error: contest and site have to match over all instances"); + return false; + } + } + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBRenewSiteTime(begin)"); + } + DBExec($c,"lock table sitetimetable","DBRenewSiteTime(lock)"); + + $a = DBGetRow ("select max(updatetime) as maxtime from sitetimetable where contestnumber=". $param[0]['contest']. + " and sitenumber=". $param[0]['site'], 0, $c); + $ret = 1; + if ($a == null || $a['maxtime'] < $maxtime) { + DBExec($c, "delete from sitetimetable where contestnumber=" . $param[0]['contest']. + " and sitenumber=". $param[0]['site'], "DBRenewSiteTime(delete)"); + for($i=0; isset($param[$i]); $i++) { + DBExec($c, "insert into sitetimetable (contestnumber, sitenumber, sitestartdate, siteenddate, updatetime) ". + "values (". $param[0]['contest'].", ". $param[0]['site'].", ".$param[$i]['start'].", ". + $param[$i]['enddate'].", ".$param[$i]['updatetime'].")", "DBRenewSiteTime(insert)"); + } + $ret = 2; + } + if($cw) DBExec($c, "commit work", "DBRenewSiteTime(commit)"); + return $ret; +} +function DBNewContest ($param=array(), $c=null) { + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewContest(begin)"); + } + $a = DBGetRow ("select max(contestnumber) as contest from contesttable", 0, $c, + "DBNewContest(max(contest))"); + if ($a == null) $n=1; + else $n = $a["contest"]+1; + + $ac=array('name','startdate','duration','lastmileanswer','lastmilescore','penalty','updatetime','localsite','mainsite','mainsiteurl','keys','unlockkey'); //'active' + $type['startdate']=1; + $type['duration']=1; + $type['lastmileanswer']=1; + $type['lastmilescore']=1; + $type['penalty']=1; + $type['updatetime']=1; + $type['mainsite']=1; + $type['localsite']=1; + $mainsiteurl=''; + $keys=''; + $unlockkey=''; + foreach($ac as $key) { + if(isset($param[$key]) && (!isset($type[$key]) || is_numeric($param[$key]))) + $$key = sanitizeText($param[$key]); + else + $$key = ""; + } + if($mainsite=="") $mainsite=1; + if($localsite=="") $localsite=1; + if($name=="") $name="Contest"; + if($startdate=="") $startdate="EXTRACT(EPOCH FROM now())+600"; + if($duration=="") $duration=300*60; + if($lastmileanswer=="") $lastmileanswer=285*60; + if($lastmilescore=="") $lastmilescore=240*60; + if($penalty=="") $penalty=20*60; + //if($active=="") + $active="f"; + if($updatetime=="") $updatetime=time(); + + DBExec($c, "insert into contesttable (contestnumber, contestname, conteststartdate, contestduration, ". + "contestlastmileanswer, contestlastmilescore, contestlocalsite, contestpenalty, ". + "contestmaxfilesize, contestactive, contestmainsite, contestmainsiteurl,contestkeys,contestunlockkey, updatetime) values ($n, '$name', ". + "$startdate, $duration, $lastmileanswer, " . + "$lastmilescore, $localsite, $penalty, 100000, '$active', $mainsite, '$mainsiteurl', '$keys','$unlockkey',$updatetime)", "DBNewContest(insert contest)"); + + DBNewSite($n, $c, $param); + + insertanswers($n,$c); + insertlanguages($n,$c); + DBinsertfakeproblem($n,$c); + + if($cw) { + DBExec($c, "commit work", "DBNewContest(commit)"); + } + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " created a new contest ($n).",2); + return $n; +} +function insertlanguages($n,$c=null) { + $ok=false; + $param=null; + $param['number']=1; + $param['name']='C'; + $param['extension']='c'; + DBNewLanguage($n, $param, $c); + $param['number']=2; + $param['name']='C++'; + $param['extension']='cpp'; + DBNewLanguage($n, $param, $c); + $param['number']=3; + $param['name']='Java'; + $param['extension']='java'; + DBNewLanguage($n, $param, $c); +} +function insertanswers($n,$c) { + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 0, 'Not answered yet', 'f', 't')", "DBNewContest(insert fake answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 1, 'YES', 't', 'f')", "DBNewContest(insert YES answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 2, 'NO - Compilation error', 'f', 'f')", "DBNewContest(insert CE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 3, 'NO - Runtime error', 'f', 'f')", "DBNewContest(insert RE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 4, 'NO - Time limit exceeded', 'f', 'f')", "DBNewContest(insert TLE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 5, 'NO - Presentation error', 'f', 'f')", "DBNewContest(insert PE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 6, 'NO - Wrong answer', 'f', 'f')", "DBNewContest(insert WA answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 7, 'NO - If possible, contact staff', 'f', 'f')", "DBNewContest(insert CS answer)"); +} +function DBNewSite ($contest, $c=null, $param=array()) { + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + $ct = DBContestInfo ($contest, $c); + if($ct==null) return false; + + if(isset($param['sitenumber']) && !isset($param['number'])) $param['number']=$param['sitenumber']; + $ac=array('number','siteip','sitename','sitescorelevel','updatetime','startdate','duration'); + $type=array(); + $type['startdate']=1; + $type['duration']=1; + $type['number']=1; + $type['sitescorelevel']=1; + $type['updatetime']=1; + foreach($ac as $key) { + if(isset($param[$key]) && (!isset($type[$key]) || is_numeric($param[$key]))) + $$key = sanitizeText($param[$key]); + else + $$key = ""; + } + + if($number=="") { + $a = DBGetRow ("select max(sitenumber) as site from sitetable where contestnumber=$contest", 0, $c); + if ($a == null) $n=1; + else $n = $a["site"]+1; + $number=$n; + } else { + $a = DBGetRow ("select * from sitetable where contestnumber=$contest and sitenumber=$number", 0, $c); + if($a != null) return 1; + } + if($duration=='') $duration = $ct["contestduration"]; + if($startdate=='') $startdate=$ct["conteststartdate"]; + if($siteip=="") $siteip="127.0.0.1/boca"; + if($sitename=="") $sitename="Site"; + if($sitescorelevel=="") $sitescorelevel=3; + $t=time(); + if($updatetime=="") $updatetime=$t; + DBExec($c, "insert into sitetable (contestnumber, sitenumber, siteip, sitename, siteactive, sitepermitlogins, ". + "sitelastmileanswer, sitelastmilescore, siteduration, siteautoend, sitejudging, sitetasking, ". + "siteglobalscore, sitescorelevel, ". + "sitenextuser, sitenextclar, sitenextrun, sitenexttask, sitemaxtask, updatetime) values ". + "($contest, $number, '$siteip', '$sitename', 't', 't', ". + $ct["contestlastmileanswer"].",".$ct["contestlastmilescore"]. + ", $duration, 't', '$number', '$number', '$number', $sitescorelevel, 0, 0, 0, 0, 10, $updatetime)"); + + $cf=globalconf(); + $admpass = myhash($cf["basepass"]); + + DBExec($c, "insert into usertable ". + "(contestnumber, usersitenumber, usernumber, username, userfullname, " . + "userdesc, usertype, userenabled, usermultilogin, userpassword, userip, userlastlogin, ". + "usersession, usersessionextra, userlastlogout, userpermitip, updatetime) values " . + "($contest, $number, 1000, 'admin', 'Administrator', NULL, 'admin', ". + "'t', 't', '$admpass', NULL, NULL, '', '', NULL, NULL, $updatetime)"); + $param=array(); + $param['contest']=$contest; + $param['site']=$number; + $param['start']=$startdate; + DBRenewSiteTime($param, $c); + if($cw) DBExec($c, "commit work"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . + " created site $number on contest $contest.",2); + return 2; +} + +function DBUserUpdate($contest, $site, $user, $username, $userfull, $userdesc, $passo, $passn) { + $a = DBUserInfo($contest, $site, $user, null, false); + $p = myhash($a["userpassword"] . session_id()); + if ($a["userpassword"] != "" && $p != $passo) { + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " (contest=$contest, site=$site) " . + "tried to change settings, but password was incorrect.",2); + MSGError ("Incorrect password."); + } + else { + if($a['userpassword'] + MSGError('Password change is DISABLED'); return; + + if ($a["userpassword"] == "") $temp = myhash(""); + else $temp = $a["userpassword"]; + $lentmp = strlen($temp); + $temp = bighexsub($passn, $temp); + $newpass = substr($temp, strlen($temp)-$lentmp); + + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table usertable"); + $r = DBExec($c, "select * from usertable where username='$username' and usernumber!=$user and ". + "usersitenumber=$site and contestnumber=$contest"); + $n = DBnlines ($r); + if ($n == 0) { + $sql = "update usertable set username='$username', userdesc='$userdesc', userfullname='$userfull', updatetime=".time(); + if ($newpass != myhash("")) $sql .= ", userpassword='$newpass'"; + $sql .= " where usernumber=$user and usersitenumber=$site and contestnumber=$contest"; + $r = DBExec ($c, $sql); + DBExec ($c, "commit work"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " changed his settings (newname=$username) ". + "(user=$user,site=$site,contest=$contest)",2); + MSGError("Data updated."); + ForceLoad("index.php"); + } else { + DBExec ($c, "rollback work"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " couldn't change his settings " . + "(user=$user,site=$site,contest=$contest)",2); + MSGError ("Update problem (maybe username already in use). No data was changed."); + } + } +} + +function DBNewUser($param, $c=null) { + if(isset($param['contestnumber']) && !isset($param['contest'])) $param['contest']=$param['contestnumber']; + if(isset($param['sitenumber']) && !isset($param['site'])) $param['site']=$param['sitenumber']; + if(isset($param['usernumber']) && !isset($param['user'])) $param['user']=$param['usernumber']; + if(isset($param['number']) && !isset($param['user'])) $param['user']=$param['number']; + + $ac=array('contest','site','user'); + $ac1=array('updatetime','username','usericpcid','userfull','userdesc','type','enabled','multilogin','pass','permitip', + 'userip','userlastlogin','userlastlogout','usersession','usersessionextra'); + + $typei['contest']=1; + $typei['updatetime']=1; + $typei['site']=1; + $typei['user']=1; + foreach($ac as $key) { + if(!isset($param[$key]) || $param[$key]=="") { + MSGError("DBNewUser param error: $key not found"); + return false; + } + if(isset($typei[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewUser param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $username= "team" . $user; + $updatetime=-1; + $pass = null; + $usericpcid=''; + $userfull=''; + $userdesc=''; + $type='team'; + $enabled='f'; + $multilogin='f'; + $permitip=''; + $usersession=null; + $usersessionextra=null; + $userip=null; + $userlastlogin=null; + $userlastlogout=null; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($typei[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewUser param error: $key is not numeric"); + return false; + } + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + + if ($type != "chief" && $type != "judge" && $type != "admin" && + $type != "score" && $type != "staff" && $type != "site") + $type = "team"; + if ($enabled != "f") $enabled = "t"; + if ($multilogin != "t") $multilogin = "f"; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewUser(begin)"); + } + DBExec($c, "lock table usertable", "DBNewUser(lock)"); + $r = DBExec($c, "select * from sitetable where sitenumber=$site and contestnumber=$contest", "DBNewUser(get site)"); + $n = DBnlines ($r); + if($n == 0) { + DBExec ($c, "rollback work","DBNewUser(no-site)"); + MSGError("DBNewUser param error: site $site does not exist"); + return false; + } + $r = DBExec($c, "select * from usertable where username='$username' and usernumber!=$user and ". + "usersitenumber=$site and contestnumber=$contest", "DBNewUser(get user)"); + $n = DBnlines ($r); + $ret=1; + if ($n == 0) { + $sql = "select * from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + $a = DBGetRow ($sql, 0, $c); + if ($a == null) { + $ret=2; + $sql = "select * from sitetable where sitenumber=$site and contestnumber=$contest"; + $aa = DBGetRow ($sql, 0); + if($aa==null) { + DBExec ($c, "rollback work"); + MSGError("Site $site does not exist"); + return false; + } + $sql = "insert into usertable (contestnumber, usersitenumber, usernumber, username, usericpcid, userfullname, " . + "userdesc, usertype, userenabled, usermultilogin, userpassword, userpermitip) values " . + "($contest, $site, $user, '$username', '$usericpcid', '$userfull', '$userdesc', '$type', '$enabled', " . + "'$multilogin', '$pass', '$permitip')"; + DBExec ($c, $sql, "DBNewUser(insert)"); + if($cw) { + DBExec ($c, "commit work"); + } + LOGLevel ("User $user (site=$site,contest=$contest) included.",2); + } else { + if($updatetime > $a['updatetime']) { + $ret=2; + $sql = "update usertable set username='$username', usericpcid='$usericpcid', userdesc='$userdesc', updatetime=$updatetime, " . + "userfullname='$userfull', usertype='$type', userpermitip='$permitip', "; + if($pass != null && $pass != myhash("")) $sql .= "userpassword='$pass', "; + if($usersession != null) $sql .= "usersession='$usersession', "; + if($usersessionextra != null) $sql .= "usersessionextra='$usersessionextra', "; + if($userip != null) $sql .= "userip='$userip', "; + if($userlastlogin != null) $sql .= "userlastlogin='$userlastlogin', "; + if($userlastlogout != null) $sql .= "userlastlogout='$userlastlogout', "; + $sql .= "userenabled='$enabled', usermultilogin='$multilogin'"; + $sql .= " where usernumber=$user and usersitenumber=$site and contestnumber=$contest"; + $r = DBExec ($c, $sql, "DBNewUser(update)"); + if($cw) { + DBExec ($c, "commit work"); + } + LOGLevel("User $user (username=$username,site=$site,contest=$contest) updated.",2); + } + } + } else { + DBExec ($c, "rollback work"); + LOGLevel ("Update problem for user $user (site=$site,contest=$contest) (maybe username already in use).",1); + MSGError ("Update problem for user $user, site $site (maybe username already in use)."); + return false; + } + return $ret; +} + +function siteclock() { + if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + + if ($s["siteactive"]!="t") + return array("site is not active",-1000000000); + if (!$s["siterunning"]) + return array("contest not running",-1000000000); + if ($s["currenttime"]<0) { + $t = - $s["currenttime"]; + if($t>3600) { + $t = ((int) ($t/360))/10; + return array("> ". $t . " hour(s) to start",$s["currenttime"]); + } + if ($t>60) { + $t = (int) ($t/60); + return array("> ". $t . " min(s) to start",$s["currenttime"]); + } else { + return array($t . " second(s) to start",$s["currenttime"]); + } + } + if ($s["currenttime"]>=0) { + $t = $s["siteduration"] - $s["currenttime"]; + $str = ''; + if($t >= 3600) { + $str .= ((int)($t/3600)) . 'h '; + $t = $t % 3600; + } + if ($t>60) { + $t = (int) ($t/60); + return array($str . $t . " min(s) left",$s["currenttime"]); + } else if($str=='') { + if ($t>0) { + return array($t . " second(s) left",$s["currenttime"]); + } else { + $t = (int) (- $t/60); + return array($t . "min. of extra time",$s["currenttime"]); + } + } else return array($str . " left",$s["currenttime"]); + } + else return array("not started",-1000000000); +} +// eof +?> diff --git a/tools/genpackage.sh b/tools/genpackage.sh new file mode 100755 index 0000000..18caac2 --- /dev/null +++ b/tools/genpackage.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program 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. +# // +# // This program 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 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 . +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 06/aug/2012 by cassio@ime.usp.br +cdir=`pwd` +basen=`basename $cdir` +if [ ! -f "$cdir/genpackage.sh" -o "$basen" != "tools" ]; then + echo "Please run this script from its own directory in tools/ of the BOCA directory" +else +ver=$(basename $(dirname $cdir) | cut -d'-' -f2-) +echo "*** Processing version $ver" +cd ../.. +if [ "$ver" != "" -a -d "boca-$ver" ]; then +echo "boca-$ver" > boca-$ver/src/version +echo -e "\n" > boca-$ver/src/versionnum.php +touch boca-$ver/src/private/runtmp/run0.php boca-$ver/src/private/scoretmp/0.php boca-$ver/src/private/remotescores/0.dat \ + boca-$ver/src/private/remotescores/0.tmp boca-$ver/src/private/problemtmp/problem0.tmp +rm -f boca-$ver/src/balloons/*.png +rm -f boca-$ver/src/private/runtmp/run*.php boca-$ver/src/private/scoretmp/*.php boca-$ver/src/private/remotescores/*.dat \ + boca-$ver/src/private/remotescores/*.tmp +rm -rf boca-$ver/src/private/problemtmp/problem* +touch boca-$ver/.temp +rm boca-$ver/.temp `find boca-$ver/ -name "*.orig"` +touch boca-$ver/.temp +rm boca-$ver/.temp `find boca-$ver/ -name "*~"` +touch boca-$ver/.temp +rm boca-$ver/.temp `find boca-$ver/ -name ".\#*"` +cd boca-$ver/tools/etc +tar cvzf ../icpc.etc.tgz * +cd ../../.. +tar czf boca-$ver.tgz boca-$ver/ +echo "*** file generated: `pwd`/boca-$ver.tgz" +else + echo "*** boca-$ver not found" +fi +fi +cd $cdir diff --git a/tools/icpc.etc.tgz b/tools/icpc.etc.tgz new file mode 100644 index 0000000..e58e2b1 Binary files /dev/null and b/tools/icpc.etc.tgz differ diff --git a/tools/installv2.sh b/tools/installv2.sh new file mode 100755 index 0000000..85886b6 --- /dev/null +++ b/tools/installv2.sh @@ -0,0 +1,354 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program 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. +# // +# // This program 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 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 . +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 06/aug/2012 by cassio@ime.usp.br +#/////////////////////////////////////////////////////////////////////////////////////////// +echo "#############################################################" +echo "### installv2.sh of 06/Aug/2012 (A) by cassio@ime.usp.br ###" +echo "#############################################################" + +for i in id chown chmod cut awk tail grep cat sed mkdir rm mv sleep apt-get add-apt-repository update-alternatives; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +sleep 2 + +echo "$0" | grep -q "install.*sh" +if [ $? != 0 ]; then + echo "Make the install script executable (using chmod) and run it directly, like ./installv2.sh" +else + +if [ "`id -u`" != "0" ]; then + echo "Must be run as root" + exit 1 +fi + +if [ "$1" != "alreadydone" ]; then + echo "It is recommended that you run the commands" + echo " apt-get update; apt-get upgrade" + echo "by your own before running this script. If you have already done it," + echo "please run the script as" + echo " ./install.sh alreadydone" + exit 1 +fi + +if [ ! -r /etc/lsb-release ]; then + echo "File /etc/lsb-release not found. Is this a ubuntu or debian-like distro?" + exit 1 +fi +. /etc/lsb-release + +echo "=============================================================" +echo "============== DISABLING AUTO-UPDATE POP-UPS ===============" +echo "=============================================================" +gconftool -s --type bool /apps/update-notifier/auto_launch false +gsettings set com.ubuntu.update-notifier no-show-notifications true +sed -i 's/X-GNOME-Autostart-Delay=60/X-GNOME-Autostart-enabled=false/' /etc/xdg/autostart/update-notifier.desktop + +echo "=============================================================" +echo "========= UNINSTALLING SOME UNNECESSARY PACKAGES ===========" +echo "=============================================================" +apt-get -y purge libreoffice-common libreoffice-base-core bluez thunderbird \ + ubuntuone-client python-ubuntuone-client \ + ubuntuone-installer python-ubuntuone-storageprotocol + +sysvutils=sysvutils +if [ "$DISTRIB_CODENAME" == "oneiric" -o "$DISTRIB_CODENAME" == "precise" ]; then + sysvutils=sysvinit-utils +fi + +echo "=====================================================================" +echo "============== CHECKING FOR canonical.com APT SERVER ===============" +echo "=====================================================================" + +cd +grep -q "^[^\#]*deb http://archive.canonical.com.* $DISTRIB_CODENAME .*partner" /etc/apt/sources.list +if [ $? != 0 ]; then + add-apt-repository "deb http://archive.canonical.com/ubuntu $DISTRIB_CODENAME partner" +fi +apt-get -y update +apt-get -y upgrade + +libCppdev=`apt-cache search libstdc++ | grep "libstdc++6-.*-dev " | sort | tail -n1 | cut -d' ' -f1` +if [ "$libCppdev" == "" ]; then + echo "libstdc++6-*-dev not found" + exit 1 +fi +libCppdbg=`apt-cache search libstdc++ | grep "libstdc++6-.*-dbg " | sort | tail -n1 | cut -d' ' -f1` +if [ "$libCppdbg" == "" ]; then + echo "libstdc++6-*-dbg not found" + exit 1 +fi +libCppdoc=`apt-cache search libstdc++ | grep "libstdc++6-.*-doc " | sort | tail -n1 | cut -d' ' -f1` +if [ "$libCppdoc" == "" ]; then + echo "libstdc++6-*-doc not found" + exit 1 +fi + +echo "=====================================================================" +echo "================= installing packages needed by BOCA ===============" +echo "=====================================================================" + +apt-get -y install zenity apache2 eclipse-pde eclipse-rcp eclipse-platform eclipse-jdt eclipse-cdt eclipse emacs \ + evince g++ gcc gedit scite libstdc++6 makepasswd manpages-dev mii-diag php5-cli php5-mcrypt openjdk-6-dbg \ + php5 php5-pgsql postgresql postgresql-client postgresql-contrib quota sharutils default-jdk openjdk-6-doc \ + vim-gnome geany geany-plugin-addons geany-plugin-gdb geany-plugins default-jre sysstat \ + $sysvutils vim xfce4 $libCppdev $libCppdoc $libCppdbg php5-gd stl-manual gcc-doc debootstrap schroot c++-annotations +if [ $? != 0 ]; then + echo "" + echo "ERROR running the apt-get -- must check if all needed packages are available" + exit 1 +fi + +for i in makepasswd useradd update-rc.d; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done + + +echo "==================================================================" +echo "============= creating user icpc with password icpc =============" +echo "==================================================================" + +mkdir -p /etc/skel/Desktop/ +cat < /etc/skel/Desktop/javadoc.desktop +[Desktop Entry] +Version=1.5.1 +Name=Java API +Comment=Java API +Exec=firefox /usr/share/doc/openjdk-6-jre-headless/api/index.html +Terminal=false +Type=Application +EOF +cat < /etc/skel/Desktop/stldoc.desktop +[Desktop Entry] +Version=1.5.1 +Name=C++ STL +Comment=C++ STL +Exec=firefox /usr/share/doc/stl-manual/html/index.html +Terminal=false +Type=Application +EOF +cat < /etc/skel/Desktop/cppannotations.desktop +[Desktop Entry] +Version=1.5.1 +Name=C++ Annotations +Comment=C++ Annotations +Exec=firefox /usr/share/doc/c++-annotations/html/index.html +Terminal=false +Type=Application +EOF +cp /usr/share/applications/eclipse.desktop /etc/skel/Desktop/ +cp /usr/share/applications/gedit.desktop /etc/skel/Desktop/ +cp /usr/share/applications/emacs23.desktop /etc/skel/Desktop/ +cp /usr/share/applications/gnome-terminal.desktop /etc/skel/Desktop/ +chmod 755 /etc/skel/Desktop/*.desktop + +pass=`echo -n icpc | makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` +pass=\$`echo $pass` +id -u icpc >/dev/null 2>/dev/null +if [ $? != 0 ]; then + useradd -d /home/icpc -k /etc/skel -m -p "$pass" -s /bin/bash -g users icpc +else + usermod -d /home/icpc -p "$pass" -s /bin/bash -g users icpc + echo "user icpc already exists" +fi + +if [ -f /etc/lightdm/lightdm.conf ]; then + echo "==============================================================" + echo "============ disabling guest account on lightdm.conf ========" + echo "==============================================================" + grep -q "^[^\#]*allow-guest" /etc/lightdm/lightdm.conf + if [ $? != 0 ]; then + echo "allow-guest=false" >> /etc/lightdm/lightdm.conf + fi + grep -q "^[^\#]*greeter-hide-users" /etc/lightdm/lightdm.conf + if [ $? != 0 ]; then + echo "greeter-hide-users=true" >> /etc/lightdm/lightdm.conf + fi +fi + +echo "=====================================================================================" +echo "============ updating grub boot loader to make it password protected ===============" +echo "=====================================================================================" + +grep -q "^[^\#]*password" /etc/grub.d/40_custom +if [ $? != 0 ]; then + echo "updated with new password (if needed, see the password at /etc/grub.d/40_custom)" + echo -e "set superusers=\"root\"" >> /etc/grub.d/40_custom + echo -e "password root `makepasswd`" >> /etc/grub.d/40_custom + chmod go-rw /etc/grub.d/40_custom + grub-mkconfig > /boot/grub/grub.cfg + chmod go-rw /boot/grub/grub.cfg +fi +echo "grub loader configured with password (if needed, see the password at /etc/grub.d/40_custom)" + +echo "==============================================================" +echo "============= INSTALLING SCRIPTS at /etc/icpc ===============" +echo "==============================================================" +mkdir -p /etc/icpc +chown root.root /etc/icpc +chmod 755 /etc/icpc +cat < /etc/icpc/installscripts.sh +#!/bin/bash +echo "================================================================================" +echo "========== downloading config files from www.ime.usp.br/~cassio/boca ==========" +echo "================================================================================" +iptables -F +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/icpc.etc.date.txt" +echo ">>>>>>>>>>" +echo ">>>>>>>>>> Downloading scripts release \`cat /tmp/.boca.tmp\`" +echo ">>>>>>>>>>" + +if [ "\$1" == "" ]; then +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/icpc.etc.ver.txt" +icpcver=\`cat /tmp/.boca.tmp\` +else +icpcver=\$1 +fi +echo "Looking for version \$icpcver from http://www.ime.usp.br/~cassio/boca/" + +rm -f /tmp/icpc.etc.tgz +wget -O /tmp/icpc.etc.tgz "http://www.ime.usp.br/~cassio/boca/download.php?filename=icpc-\$icpcver.etc.tgz" +if [ "\$?" != "0" -o ! -f /tmp/icpc.etc.tgz ]; then + echo "ERROR downloading file icpc-\$icpcver.etc.tgz. Aborting *****************" + exit 1 +fi +grep -qi "bad parameters" /tmp/icpc.etc.tgz +if [ "\$?" == "0" ]; then + echo "ERROR downloading file icpc-\$icpcver.etc.tgz. Aborting *****************" + exit 1 +fi + +cd /etc +di=\`date +%s\` + +echo "==============================================================" +echo "====================== BACKUPING CONFIG FILES ===============" + +for i in \`tar tvzf /tmp/icpc.etc.tgz | awk '{ print \$6; }'\`; do + if [ -f "\$i" ]; then + bn=\`basename \$i\` + dn=\`dirname \$i\` + mv \$i \$dn/.\$bn.bkp.\$di + chmod 600 \$dn/.\$bn.bkp.\$di + fi +done + +echo "==============================================================" +echo "====================== EXTRACTING CONFIG FILES ===============" +tar -xkvzf /tmp/icpc.etc.tgz +for i in \`tar tvzf /tmp/icpc.etc.tgz | awk '{ print \$6; }'\`; do + chown root.root \$i + chmod o-w,u+rx \$i +done +EOF +chmod 750 /etc/icpc/installscripts.sh +/etc/icpc/installscripts.sh $3 + +service procps start + +grep -q "quota" /etc/fstab +if [ $? != 0 ]; then + cp -f /etc/fstab /etc/fstab.bkp.$di + sed "s/relatime/quota,relatime/" < /etc/fstab.bkp.$di > /etc/fstab.bkp.$di.1 + sed "s/errors=remount-ro/quota,errors=remount-ro/" < /etc/fstab.bkp.$di.1 > /etc/fstab +fi + +echo "============================================================" +echo "===================== SETTING UP USER QUOTA ===============" +echo "============================================================" + +for i in `mount | grep gvfs | cut -d' ' -f3`; do + umount $i +done + +mount / -o remount +quotaoff -a 2>/dev/null +quotacheck -M -a +quotaon -a +setquota -u postgres 0 3000000 0 10000 -a +setquota -u icpc 0 500000 0 10000 -a +setquota -u nobody 0 500000 0 10000 -a +setquota -u www-data 0 1500000 0 10000 -a + +echo "==============================================================" +echo "================= UPDATING rc.local symlinks ===============" +echo "==============================================================" + +update-rc.d rc.local defaults +update-rc.d -f cups remove +apt-get -y clean + +#echo "==============================================================" +#echo "====================== SETTING UP IPs and PASSWORDs (server config follows) ===============" +# +/etc/icpc/restart.sh +#/etc/icpc/setup.sh + +startscript="NOTOK" +if [ -f /etc/lightdm/lightdm.conf ]; then + startscript="OK" + grep -q "^[^\#]*display-setup-script=/etc/icpc/setup.sh" /etc/lightdm/lightdm.conf + if [ $? != 0 ]; then + echo "display-setup-script=/etc/icpc/setup.sh" >> /etc/lightdm/lightdm.conf + fi +fi +if [ -d /etc/gdm/Init ]; then + startscript="OK" + echo "======================================================================================" + echo "========== UPDATING /etc/gdm/Init/Default TO PROVIDE CONFIG AT STARTUP ===============" + echo "======================================================================================" + echo -e "#!/bin/bash\n[ -x /etc/icpc/setup.sh ] && /etc/icpc/setup.sh\n\n" > /tmp/.boca.tmp + cat /etc/gdm/Init/Default >> /tmp/.boca.tmp + mv /tmp/.boca.tmp /etc/gdm/Init/Default + chmod 755 /etc/gdm/Init/Default +fi +if [ "$startscript" != "OK" ]; then + echo "************ STARTUP CALL OF SCRIPTS NOT CONFIGURED **************" + echo "****** neither /etc/gdm/Init nor /etc/lightdm/lightdm.conf were found ************" +fi + +if [ -f /etc/icpc/createbocajail.sh ]; then + chmod 750 /etc/icpc/createbocajail.sh + if [ "$2" != "notbuildjail" ]; then + /etc/icpc/createbocajail.sh + fi +else + echo "************** SCRIPT TO CREATE BOCAJAIL NOT FOUND -- SOMETHING LOOKS WRONG ***************" +fi + +# BOCA CONFIG +if [ -f /etc/icpc/installboca.sh ]; then + chmod 750 /etc/icpc/installboca.sh + /sbin/iptables -F + /etc/icpc/installboca.sh "$3" "$4" +else + echo "************* SCRIPT TO INSTALL BOCA NOT FOUND -- SOMETHING IS WRONG -- I CANT INSTALL BOCA **************" +fi + +fi diff --git a/tools/makebkp.sh b/tools/makebkp.sh new file mode 100755 index 0000000..5a99c8a --- /dev/null +++ b/tools/makebkp.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +for i in zip du find cut; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo "$i" not found + exit 1 + fi +done + +ex=`which singlefilebkp.sh` +if [ "$ex" = "" ]; then + ex=/var/www/boca/tools/singlefilebkp.sh +fi + +if [ -x "$ex" ]; then + zip /tmp/bkp.zip `find $cdir -name "*.c"` `find $cdir -name "*.java"` `find $cdir -name "*.cpp"` `find $cdir -name "*.in"` + if [ ! -f /tmp/bkp.zip ]; then + echo "Nothing to backup" + else + size=`du -s /tmp/bkp.zip | cut -f1` + if [ "$size" -gt 100000 ]; then + echo Bkp is already too large. BACKUP ABORTED + else + $ex /tmp/bkp.zip + fi + fi +else + echo Bkp script not found or is not executable +fi diff --git a/tools/postgresql.conf.diffs b/tools/postgresql.conf.diffs new file mode 100644 index 0000000..1f02936 --- /dev/null +++ b/tools/postgresql.conf.diffs @@ -0,0 +1,5 @@ +listen_addresses = '*' +max_connections = 300 # (change requires restart) +shared_buffers = 32MB # min 128kB +work_mem = 4MB +maintenance_work_mem = 64MB # min 1MB diff --git a/tools/safeexec.c b/tools/safeexec.c new file mode 100644 index 0000000..33f16b7 --- /dev/null +++ b/tools/safeexec.c @@ -0,0 +1,523 @@ +/* + safeexec + Executar um comando num ambiente protegido + pbv, 1999-2000 + alterado por cassio@ime.usp.br 2003-2011 + + THIS PROGRAM HAS TO BE INSTALLED WITH SETUID ROOT TO HAVE ALL FUNCTIONS WORKING + $ gcc -Wall -o safeexec safeexec.c + $ chown root.root safeexec + $ chmod 4555 safeexec +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* tempo de erro entre o sinal e o estouro no caso de time-limit */ +#define EPSILON 0.01 + +#define KBYTE 1024 +#define MBYTE (KBYTE*KBYTE) + +pid_t child_pid; /* pid of the child process */ + +double cpu_timeoutdouble = 5.0; +struct rlimit cpu_timeout = {5,5}; /* max cpu time (seconds) */ +struct rlimit max_nofile = {64,64}; /* max number of open files */ +struct rlimit max_fsize = {128*MBYTE,128*MBYTE}; /* max filesize */ + +struct rlimit max_data = {128*MBYTE, 128*MBYTE}; /* max data segment size */ +struct rlimit max_core = {0, 0}; /* max core file size */ +struct rlimit max_rss = {128*MBYTE, 128*MBYTE}; /* max resident set size */ + +struct rlimit max_processes = {64,64}; /* max number of processes */ + + +int real_timeout = 30; /* max real time (seconds) */ + +int dochroot = 0, st=1; +int nruns = 1; +int allproc; +int killallproc; +int bequiet; +int checknchild; +int user, group; +const char vers[] = "1.5.1"; + +#define BUFFSIZE 256 +char curdir[BUFFSIZE], rootdir[BUFFSIZE], saida[BUFFSIZE], entrada[BUFFSIZE], erro[BUFFSIZE]; + +struct Proc { + int uid, pid, ppid, gid, group; + unsigned long utime, stime; + long cutime, cstime; + unsigned long starttime; + unsigned long vsize; + long rss; + long resident, share, text, lib, data; +}; + +unsigned int getprocs(pid_t ppid, pid_t ppid2, int userid, int groupid, int *nchild, struct Proc **Pr); + +void exitandkill(int ret) { + if(killallproc) { + if(!bequiet) + fprintf(stderr,"safeexec: killing all recent processes from this user/group to avoid possible malicious code... use -K if you don't want this\n"); + struct Proc *P; + unsigned n; + int nchild, i; + if((n = getprocs(child_pid,getpid(),user,group,&nchild,&P)) > 0) { + for(i = 0; i < n; i++) { + if(!bequiet) + fprintf(stderr,"safeexec: killing processes pid=%d\n", P[i].pid); + kill(P[i].pid,9); /* kill children and all processes with userid/groupid that started after us if instructed to do so */ + } + } + } + switch(ret) { + case 8: fprintf(stderr,"safeexec: security threat because strange processes\n"); break; + case 7: fprintf(stderr,"safeexec: memory limit exceeded\n"); break; + case 5: fprintf(stderr,"safeexec: parameter problem\n"); break; + case 6: + case 4: fprintf(stderr,"safeexec: ERROR! internal error\n"); break; + case 3: fprintf(stderr,"safeexec: time limit exceeded\n"); break; + case 2: fprintf(stderr,"safeexec: runtime error\n"); break; + case 9: fprintf(stderr,"safeexec: runtime error\n"); break; + } + exit(ret); +} + +unsigned int getprocs(pid_t ppid, pid_t ppid2, int userid, int groupid, int *nchild, struct Proc **Pr) { + const int SIZE=10000; + char a[SIZE], b[SIZE]; + unsigned long pidtime=0; + glob_t globbuf; + unsigned int i, j, k, ki, oldi, n; + FILE *tn; + struct stat sstat; + struct Proc *P, Ptmp; + + glob("/proc/[0-9]*", GLOB_NOSORT, NULL, &globbuf); + + P = calloc(globbuf.gl_pathc, sizeof(struct Proc)); + if (P == NULL) { + if(!bequiet) fprintf(stderr,"safeexec: problem with malloc"); + exitandkill(4); + } + *Pr = P; + + for (i = j = 0; i < globbuf.gl_pathc; i++) { + snprintf(a, sizeof(a)-1, "%s%s", + globbuf.gl_pathv[globbuf.gl_pathc - i - 1], "/stat"); + snprintf(b, sizeof(b)-1, "%s%s", + globbuf.gl_pathv[globbuf.gl_pathc - i - 1], "/statm"); +#ifdef DEBUG + fprintf(stderr,"[opening %s and %s]\n", a,b); +#endif + tn = fopen(b, "r"); + if (tn == NULL) continue; /* process vanished since glob() */ + n = fread(b, 1, SIZE, tn); + fclose(tn); + tn = fopen(a, "r"); + if (tn == NULL) continue; /* process vanished since glob() */ + n = fread(a, 1, SIZE, tn); + fstat(fileno(tn), &sstat); + P[j].uid = sstat.st_uid; + P[j].gid = sstat.st_gid; + fclose(tn); + + sscanf(a, "%d %*s %*s %d %d %*s %*s %*s %*s %*s %*s %*s %*s %lu %lu %ld %ld %*s %*s %*s %*s %lu %lu %ld", + &P[j].pid,&P[j].ppid,&P[j].group,&P[j].utime,&P[j].stime,&P[j].cutime,&P[j].cstime,&P[j].starttime,&P[j].vsize,&P[j].rss); + sscanf(b, "%*s %ld %ld %ld %ld %ld", + &P[j].resident,&P[j].share,&P[j].text,&P[j].lib,&P[j].data); + if(P[j].pid == ppid2) pidtime = P[j].starttime; +#ifdef DEBUG + fprintf(stderr,"[check %d,%d,%d,%ld]", P[j].pid, P[j].ppid, P[j].gid, P[j].rss); +#endif + j++; + } + + i = 0; + oldi = 1; + *nchild = 0; + while(i != oldi) { + oldi = i; + for(k = i; k < j; ++k) { + if(P[k].pid != ppid) { + for(ki = 0; ki < i; ++ki) + if(P[k].ppid == P[ki].pid) { + break; + } + if(ki >= i) { + continue; + } + } + Ptmp = P[i]; + P[i] = P[k]; + P[k] = Ptmp; + ++i; + } + } + *nchild = i; + while(i < j) { + if(P[i].uid != userid || P[i].gid != groupid || P[i].starttime < pidtime || P[i].pid==ppid2) { + P[i] = P[--j]; + } else { + if(!bequiet) + fprintf(stderr,"safeexec: process %d has user %d, group %d, time %lu, which is suspicious\n",P[i].pid,userid,groupid,P[i].starttime); + i++; + } + } + globfree(&globbuf); + return i; +} + +int testsystem(pid_t p, pid_t pp, int userid, int groupid, double memlim, double rsslim) { + struct rusage uso; + getrusage(RUSAGE_CHILDREN, &uso); + double mem1=0., mem2=0.; + struct Proc *P; + unsigned n, i; + int ret = 1, nchild; + n = getprocs(p,pp,userid,groupid,&nchild,&P); + if(checknchild) { + if(nchild != n) { + if(!bequiet) { + fprintf(stderr,"\nsafeexec: %d children of this user/group, but list has %d processes (who are the others?).\n",nchild,n); + fprintf(stderr,"safeexec: detached children found! Aborting because of possible malicious code... use -a if you don't want this\n"); + } + exitandkill(8); + } + } + if(n > 0) { + for(i = 0; i < n; i++) { +#ifdef DEBUG + fprintf(stderr,"\ndata+stack:%ld, rss:%ld, exe:%ld\n", P[i].data,P[i].rss,P[i].lib+P[i].text+P[i].share); +#endif + mem2 += (P[i].lib+P[i].text+P[i].share+P[i].data)*getpagesize(); // in pages + mem1 += P[i].rss*getpagesize(); + } +#ifdef DEBUG + fprintf(stderr,"\nTOTAL rss:%lf, data+stack+exe:%lf\n", mem1, mem2); +#endif + if(mem2 > memlim || mem1 > rsslim) { + if(!bequiet) + fprintf(stderr,"\nsafeexec: memory limit exceeded\n"); + exitandkill(7); + } + if(nchild == 0) ret = 2; + } else { + mem1 = ((uso.ru_maxrss+uso.ru_ixrss+uso.ru_idrss+uso.ru_isrss)); +// fprintf(stderr,"WARNING: controlling only waited-for children! Security issues here if code is not trustful...\n"); + if(mem1 > memlim) { + if(!bequiet) + fprintf(stderr,"\nsafeexec: memory limit exceeded of %lfMB\n",memlim/1048576.); + exitandkill(7); + } + ret = 0; + } + free(P); + return ret; +} + +char timekill=0; + +/* alarm handler */ +void handle_alarm(int sig) { + static int iter=0; +#ifdef DEBUG + fprintf(stderr,"parent alarmed\n"); +#endif + testsystem(child_pid,getpid(),allproc?user:-1,allproc?group:-1,max_data.rlim_max,max_rss.rlim_max); + if(++iter >= real_timeout) { + if(!bequiet) + fprintf(stderr, "safeexec: timed-out (realtime) after %d seconds\n", real_timeout); + fflush(stderr); + timekill=1; + kill(child_pid,9); /* kill child */ + exitandkill(3); + } + alarm(1); /* set alarm and wait for child execution */ +} + + +void usage(int argc, char **argv) { + fprintf(stderr, "safeexec version %s\nusage: %s [ options ] cmd [ arg1 arg2 ... ]\n", vers, argv[0]); + fprintf(stderr, "available options are:\n"); + fprintf(stderr, "\t-c (default: %d)\n", + (int) max_core.rlim_max); + fprintf(stderr, "\t-f (default: %d kbytes)\n", + (int) (max_fsize.rlim_max/1024.)); + fprintf(stderr, "\t-F (default: %d)\n", + (int) max_nofile.rlim_max); + fprintf(stderr, "\t-d (default: %d kbytes)\n", + (int) (max_data.rlim_max/1024.)); + fprintf(stderr, "\t-m (default: %d kbytes)\n", + (int) (max_rss.rlim_max/1024.)); + fprintf(stderr, "\t-u (default: %d)\n", + (int) max_processes.rlim_max); + fprintf(stderr, "\t-t (default: %d secs)\n", + (int) cpu_timeout.rlim_max); + fprintf(stderr, "\t-T (default: %d secs)\n", + (int) real_timeout); + fprintf(stderr, "\t-C (default: cwd)\n"); + fprintf(stderr, "\t-R (default: none)\n"); + fprintf(stderr, "\t-n (default: %d)\n", dochroot); + fprintf(stderr, "\t-r (default: %d)\n", nruns); + fprintf(stderr, "\t-i (default: not defined)\n"); + fprintf(stderr, "\t-o (default: not defined)\n"); + fprintf(stderr, "\t-e (default: not defined)\n"); + fprintf(stderr, "\t-U (default: %d)\n", user); + fprintf(stderr, "\t-G (default: %d)\n", group); + fprintf(stderr, "\t-p (default: %d)\n", st); + fprintf(stderr, "\t-a disable checking all processes (look only to the non-detached children) (default %s)\n", allproc?"enabled":"disabled"); + fprintf(stderr, "\t-s disable checking existence of detached children (default %s)\n", checknchild?"enabled":"disabled"); + fprintf(stderr, "\t-K disable killing all processes with user/group id after us (default %s)\n", killallproc?"enabled":"disabled"); + fprintf(stderr, "\t-q be quiet (default %s)\n", bequiet?"enabled":"disabled"); +/******* +Note that currently Linux does not support strong memory usage limits, so we have +to enforce it by checking the amount of memory periodically +********/ +} + +int main(int argc, char **argv) { + int status, opt, ret=0; + time_t ini; + int currun = 0; + struct stat sstat; + double dt; + setvbuf(stderr, NULL, _IONBF, 0); + entrada[0] = saida[0] = erro[0] = rootdir[0] = curdir[0] = 0; + user = group = -1; + allproc = 1; + checknchild=1; + killallproc=1; + bequiet=0; + + if(argc>1 && !strcmp("--help", argv[1])) { + usage(argc,argv); + exit(5); + } + + /* parse command-line options */ + getcwd(curdir, BUFFSIZE); /* default: use cwd as rootdir */ + while( (opt=getopt(argc,argv,"qKar:c:d:m:f:F:t:T:u:n:i:o:e:C:R:G:U:p:s")) != -1 ) { + switch(opt) { + case 'q': bequiet=1; + break; + case 'a': allproc=0; + break; + case 'K': killallproc=0; + break; + case 's': + checknchild=0; + break; + case 'c': max_core.rlim_max = max_core.rlim_cur = atoi(optarg); + break; + case 'f': max_fsize.rlim_max = max_fsize.rlim_cur = KBYTE*atoi(optarg); + break; + case 'F': max_nofile.rlim_max = max_nofile.rlim_cur = atoi(optarg); + break; + case 'd': max_data.rlim_max = max_data.rlim_cur = KBYTE*atoi(optarg); + break; + case 'm': max_rss.rlim_max = max_rss.rlim_cur = KBYTE*atoi(optarg); + break; + case 't': cpu_timeout.rlim_max = cpu_timeout.rlim_cur = 1 + ((int) atof(optarg)); + cpu_timeoutdouble = atof(optarg); + break; + case 'T': real_timeout = atoi(optarg); + break; + case 'u': max_processes.rlim_max = max_processes.rlim_cur = atoi(optarg); + break; + case 'U': user = atoi(optarg); + break; + case 'r': nruns = atoi(optarg); + break; + case 'G': group = atoi(optarg); + break; + case 'R': strncpy(rootdir, optarg, 255); /* root directory */ + rootdir[255]=0; + break; + case 'C': strncpy(curdir, optarg, 255); /* root directory */ + curdir[255]=0; + break; + case 'i': strncpy(entrada, optarg, 255); + entrada[255]=0; + break; + case 'o': strncpy(saida, optarg, 255); + saida[255]=0; + break; + case 'e': strncpy(erro, optarg, 255); + erro[255]=0; + break; + case 'n': dochroot = atoi(optarg); + break; + case 'p': st = atoi(optarg); + break; + case '?': usage(argc,argv); + exit(5); + } + } + + if(optind >= argc) { /* no more arguments */ + usage(argc,argv); + exit(5); + } + + if(dochroot && chroot(rootdir)) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr,"%s: unable to chroot to directory %s\n", + argv[0], rootdir); + exit(4); + } + /* change the root directory (ZP: and working dir, in not root)*/ + if(curdir[0] && chdir(curdir)) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr,"%s: unable to change directory to %s\n", + argv[0], curdir); + exit(4); + } + + stat(".", &sstat); + if(user == -1) { + user = (int) sstat.st_uid; + if(!bequiet) { + fprintf(stderr, "Security note: if the sub-code is not trustful, it shall be run with a different user from the one running safeexec.\ +Use -U and -G for that, but you might need to have root privilegies.\n"); + } + } + if(group == -1) + group = (int) sstat.st_gid; + if(user == 0 || group == 0) { + fprintf(stderr, "ERROR: safeexec shall not be instructed to run the sub-code as root\n"); + exit(4); + } + + time(&ini); + dt = 0.; +// int iter=0; + doagain: + if((child_pid=fork())) { + struct rusage uso; + /* ------------------- parent process ----------------------------- */ + if(currun == 0) { + setrlimit(RLIMIT_CORE, &max_core); + } + currun++; + if(!bequiet) + fprintf(stderr,"safeexec: starting the job. Parent controller has pid %d, child is %d...\n",getpid(),child_pid); + alarm(1); /* set alarm and wait for child execution */ + signal(SIGALRM, handle_alarm); + while(waitpid(child_pid, &status, 0) != child_pid) ; + if(timekill) exitandkill(3); + + testsystem(child_pid,getpid(),allproc?user:-1,allproc?group:-1,max_data.rlim_max,max_rss.rlim_max); + + getrusage(RUSAGE_CHILDREN, &uso); + dt = uso.ru_utime.tv_sec+(double)uso.ru_utime.tv_usec/1000000.0+ + uso.ru_stime.tv_sec+(double)uso.ru_stime.tv_usec/1000000.0; +// printf("user runnning time: %.4lf\n",uso.ru_utime.tv_sec+(double)uso.ru_utime.tv_usec/1000000.0); +// printf("system runnning time: %.4lf\n",uso.ru_stime.tv_sec+(double)uso.ru_stime.tv_usec/1000000.0); +// printf("total runnning time: %.4lf\n",dt); + + if (dt >= cpu_timeoutdouble) { +// printf ("utsec=%d utusec=%d stsec=%d stusec=%d\n", uso.ru_utime.tv_sec, uso.ru_utime.tv_usec, uso.ru_stime.tv_sec, uso.ru_stime.tv_usec); + if(!bequiet) + fprintf(stderr, "safeexec: timed-out (cputime) after %.2lf seconds\n", cpu_timeoutdouble); + fflush(stderr); +// fprintf(stdout, "timed-out (cputime) after %d seconds\n", cpu_timeoutint); +// fflush(stdout); + exitandkill(3); + } + + // check if child got an uncaught signal error & reproduce it in parent + if(WIFSIGNALED(status)) { + fprintf (stderr, "safeexec: RUN-TIME SIGNAL REPORTED BY THE PROGRAM %s: %d\n", argv[optind], WTERMSIG(status)); + fflush(stderr); +// raise(WTERMSIG(status)); + exitandkill(2); + } + + if(WIFEXITED(status)) { + if(WEXITSTATUS(status)) { + ret = WEXITSTATUS(status)+10; + if(!bequiet) + fprintf (stderr, "safeexec: PROGRAM EXITED WITH NONZERO CODE %s: %d\n", + argv[optind], ret-10); + } else ret = 0; + } else { + fprintf (stderr, "safeexec: PROGRAM TERMINATED ABNORMALLY %s\n", + argv[optind]); + exitandkill(9); + } + + if(currun < nruns) goto doagain; + + // otherwise just report the exit code: + if (st) fprintf (stderr, "safeexec: TOTAL TIME RUNNING %s: %u sec (%lf sec)\n", argv[optind], (unsigned int) (time(NULL)-ini), dt); + exitandkill(ret); + } else { + /* ------------------- child process ------------------------------ */ +#ifdef DEBUG + fprintf(stderr,"child started\n"); +#endif + /* change the group id to 'nobody' */ + if(setgid(group)<0) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: unable to change gid to %d\n", argv[0], group); + exit(4); + } + /* change the user id to 'nobody' */ + if(setuid(user)<0) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: unable to change uid to %d\n", argv[0], user); + exit(4); + } + + if(currun==nruns-1) { + if (saida[0]) freopen(saida, "w", stdout); + if (erro[0]) freopen(erro, "w", stderr); + } else { + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); + } + if (entrada[0]) freopen(entrada, "r", stdin); + + /* attempt to change the hard limits */ + /*******Note that currently Linux does not support memory usage limits********/ + + cpu_timeout.rlim_max+=1; cpu_timeout.rlim_cur+=1; + + if( setrlimit(RLIMIT_CPU, &cpu_timeout) || + setrlimit(RLIMIT_DATA, &max_data) || + setrlimit(RLIMIT_STACK, &max_data) || + setrlimit(RLIMIT_CORE, &max_core) || + setrlimit(RLIMIT_RSS, &max_rss) || + setrlimit(RLIMIT_FSIZE, &max_fsize) || + setrlimit(RLIMIT_NOFILE, &max_nofile) || + setrlimit(RLIMIT_NPROC, &max_processes) ) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: can't set hard limits\n", argv[0]); + exit(6); + } + + /* attempt to exec the child process */ + if(execv(argv[optind],&argv[optind]) < 0) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: unable to exec %s\n", argv[0], argv[optind]); + exit(6); + } + } + return 0; +} diff --git a/tools/sendscore.sh b/tools/sendscore.sh new file mode 100755 index 0000000..72393c3 --- /dev/null +++ b/tools/sendscore.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program 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. +# // +# // This program 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 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 . +# //////////////////////////////////////////////////////////////////////////////// +# last modified 22/oct/2012 by cassio@ime.usp.br + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" -o "$4" == "" ]; then + echo "Usage $0 []" + echo "e.g. $0 score.dat http://bombonera.ime.usp.br/boca site1 hardpass" + echo " $0 summary.html http://bombonera.ime.usp.br/boca site1 hardpass 1" + echo "the last number in the previous line indicates the number of the site, which should be unique among sites" + exit 1 +fi +BOCASERVER=$2 +user=$3 +pass=$4 +pc2=0 +if [ "$5" != "" ]; then +pc2=$5 +fi + +for i in wget tr perl shasum cut; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done + +if [ -r "$1" ]; then +md=`wget -S -T3 -t3 $BOCASERVER/index.php -O /dev/null --save-cookies /tmp/.cookie.txt --keep-session-cookies 2>&1 | grep PHPSESS | tail -n1 | cut -f2 -d'=' | cut -f1 -d';'` +res=`echo -n $pass | shasum -a 256 - | cut -f1 -d' '` +res=`echo -n "${res}${md}" | shasum -a 256 - | cut -f1 -d' '` +wget -T3 -t3 "$BOCASERVER/index.php?name=${user}&password=${res}&action=scoretransfer" --load-cookies /tmp/.cookie.txt --keep-session-cookies --save-cookies /tmp/.cookie.txt -O /tmp/.temp.txt 2>/dev/null >/dev/null +grep -qi incorrect /tmp/.temp.txt +if [ $? == 0 ]; then + echo User or password incorrect +else +nom=`echo -n $1 | perl -MURI::Escape -lne 'print uri_escape($_)'` +echo -n "PC2=${pc2}&name=${nom}&data=" > /tmp/.temp.txt +if [ "$pc2" != "0" ]; then + uuencode -m zzzzzzzzzz < "$1" | grep -v "begin-base64.*zzzzzzzzzz" | perl -MURI::Escape -lne 'print uri_escape($_)' >> /tmp/.temp.txt +else + cat "$1" | perl -MURI::Escape -lne 'print uri_escape($_)' >> /tmp/.temp.txt +fi +wget -t3 -T3 "$BOCASERVER/site/putfile.php" --load-cookies /tmp/.cookie.txt --keep-session-cookies -O /tmp/.temp2.txt --post-file=/tmp/.temp.txt >/dev/null 2>/dev/null +[ -r /tmp/.temp2.txt ] && cat /tmp/.temp2.txt +rm -f /tmp/.temp2.txt +fi +rm -f /tmp/.temp.txt +rm -f /tmp/.cookie.txt +else + echo file $1 not found +fi diff --git a/tools/singlefilebkp.sh b/tools/singlefilebkp.sh new file mode 100755 index 0000000..8f68c41 --- /dev/null +++ b/tools/singlefilebkp.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +[ -x /etc/icpc/bocaserver.sh ] && . /etc/icpc/bocaserver.sh +if [ "$BOCASERVER" == "" ]; then + echo "This computer has no configured BOCA server. Ask an admin to update /etc/icpc/bocaserver.sh (usually resetting everything is an easy way)" + exit 1 +fi + +for i in uuencode wget tr perl md5sum cut; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo "$i" not found + exit 1 + fi +done + +if [ "$1" == "" ]; then + echo "Usage: $0 " + exit 1 +fi + +if [ -r "$1" ]; then +md=`wget -S http://$BOCASERVER/boca/index.php -O /dev/null --save-cookies /tmp/.cookie.txt --keep-session-cookies 2>&1 | grep PHPSESS | tail -n1 | cut -f2 -d'=' | cut -f1 -d';'` +echo -n "User: " +read user +echo -n "Password: " +read pass +res=`echo -n $pass | md5sum - | cut -f1 -d' '` +res=`echo -n "${res}${md}" | md5sum - | cut -f1 -d' '` +wget "http://$BOCASERVER/boca/index.php?name=${user}&password=${res}" --load-cookies /tmp/.cookie.txt --keep-session-cookies --save-cookies /tmp/.cookie.txt -O /tmp/.temp.txt 2>/dev/null >/dev/null +grep -qi incorrect /tmp/.temp.txt +if [ $? == 0 ]; then + echo User or password incorrect +else +nom=`echo -n $1 | perl -MURI::Escape -lne 'print uri_escape($_)'` +echo -n "name=${nom}&data=" > /tmp/.temp.txt +uuencode -m zzzzzzzzzz < $1 | grep -v "begin-base64.*zzzzzzzzzz" | perl -MURI::Escape -lne 'print uri_escape($_)' >> /tmp/.temp.txt +wget "http://$BOCASERVER/boca/team/getfile.php" --load-cookies /tmp/.cookie.txt --keep-session-cookies -O /dev/null --post-file=/tmp/.temp.txt >/dev/null 2>/dev/null +fi +rm -f /tmp/.temp.txt +rm -f /tmp/.cookie.txt +else + echo file $1 not found +fi diff --git a/tools/updatescore.sh b/tools/updatescore.sh new file mode 100755 index 0000000..546e17f --- /dev/null +++ b/tools/updatescore.sh @@ -0,0 +1,141 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program 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. +# // +# // This program 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 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 . +# //////////////////////////////////////////////////////////////////////////////// +# last updated 01/nov/2012 by cassio@ime.usp.br +if [ "`id -u`" != "0" ]; then + echo "Must be run as root" + exit 1 +fi +bocadir=/var/www/boca +[ -r /etc/boca.conf ] && . /etc/boca.conf + +privatedir=$bocadir/src/private/remotescores +others=$privatedir/otherservers +if [ "$1" == "" -o "$2" == "" ]; then + echo "Usage $0 " + echo "e.g. $0 $privatedir $others" + echo "*** When arguments are not given, default values as of the previous line is used" +fi +if [ "$1" != "" ]; then + privatedir=$1 +fi +if [ "$2" != "" ]; then + others=$2 +else + others=$privatedir/otherservers +fi + +for i in id chown chmod md5sum shasum wget tr cut awk tail head grep cat sed sleep; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi + +if [ ! -d $privatedir ]; then + echo "Could not find directory $privatedir" + exit 1 +fi +tempdir=$privatedir/tmp +mkdir -p $tempdir >/dev/null 2>/dev/null +if [ ! -d $tempdir ]; then + echo "Could not create directory $tempdir" + exit 1 +fi +httpbocadir=boca +secs=120 +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser > /dev/null 2>/dev/null +[ $? != 0 ] && echo "User $apacheuser not found -- error to set permissions with chown/chmod" + +hash="shasum -a 256 -" +#hash="md5sum -" + +#rm -f $privatedir/score_*.dat +chown $apacheuser.root $privatedir/score_*.dat + +if [ ! -r $others ]; then + echo "External server list in $others not found" + exit 1 +fi +echo "Starting loop to get scores from servers defined in $others" +while /bin/true; do + echo "Getting scores..." + qtd=1 + for BOCASERVER in `grep -v "^[ \t]*\#" $others | awk '{ print $1; }'`; do + if [ "$BOCASERVER" == "" ]; then + continue + fi + echo $BOCASERVER | grep -q "http" + [ $? == 0 ] || BOCASERVER=http://$BOCASERVER/boca + + user=`grep -v "^[ \t]*\#" $others | head -n$qtd | tail -n1 | awk '{ print $2; }'` + [ "$user" == "" ] && user=score + pass=`grep -v "^[ \t]*\#" $others | head -n$qtd | tail -n1 | awk '{ print $2; }'` + [ "$pass" == "" ] && pass=score + let "qtd = $qtd + 1" + + echo -n "Asking server $BOCASERVER. Authenticating with user '$user'..." + md=`wget -t3 -T3 -S $BOCASERVER/index.php -O /dev/null --save-cookies $tempdir/.cookie.txt --keep-session-cookies 2>&1 | grep PHPSESS | tail -n1 | cut -f2 -d'=' | cut -f1 -d';'` + res=`echo -n $pass | $hash | cut -f1 -d' '` + res=`echo -n "${res}${md}" | $hash | cut -f1 -d' '` + echo -n "sending password..." + wget -t3 -T3 "$BOCASERVER/index.php?name=${user}&password=${res}" --load-cookies $tempdir/.cookie.txt --keep-session-cookies --save-cookies $tempdir/.cookie.txt -O $tempdir/.temp.txt 2>/dev/null >/dev/null + grep -qi incorrect $tempdir/.temp.txt + if [ "$?" != "0" ]; then + rm -f $tempdir/* + echo "downloading scoretable..." + wget -t3 -T3 "$BOCASERVER/scoretable.php?remote=-42" --load-cookies $tempdir/.cookie.txt --keep-session-cookies --save-cookies $tempdir/.cookie.txt -O $tempdir/score.zip 2>$tempdir/.bocascore.tmp >$tempdir/.bocascore.tmp + if [ "$?" == "0" ]; then + unzip -qq $tempdir/score.zip -d $tempdir + if [ "$?" == "0" ]; then + for fscore in `ls -d $tempdir/*.dat`; do + chown $apacheuser.root "$fscore" + chmod 660 "$fscore" + bfscore=`basename $fscore` + hasscore=`echo $bfscore | cut -d'_' -f1` + if [ "$hasscore" != "score" ]; then + bfscore=score_$bfscore + fi + mv "$fscore" "$privatedir/$bfscore" + echo "Score downloaded successfully into $privatedir/$bfscore" + done + else + echo "Error: score file from $BOCASERVER is not a valid package" + fi + else + echo "Error getting score file from $BOCASERVER: `cat $tempdir/.bocascore.tmp`" + fi + else + echo "Error authenticating to server $BOCASERVER" + fi + rm -f $tempdir/.temp.txt + rm -f $tempdir/.cookie.txt + done + + echo -n "Waiting $secs secs..." + sleep $secs + echo "" +done -- cgit v1.2.3