# New CVS setup accessible by local users locally or via ssh: su # Create cvs user and group, to own the repositories: mkdir /var/cvs-repos useradd -c "CVS User" -d /var/cvs-repos -M cvs -s /sbin/nologin gpasswd -a wpollock cvs gpasswd -a rabaut cvs pwck grpck chage -l cvs chage -E -1 cvs # Setup email aliases for cvs and cvs-admin-: vi /etc/aliases # forward to wpollock, on localhost newaliases # or: postalias /etc/aliases # Set up a group quota for /var, for group "cvs": cd /var touch aquota.group chmod a+r aquota.group # Note! Once students start checking in stuff, the owner # of some of the files will be root. If there is a quota # for root (or a group quota) on /var then updates may not work! vi /etc/fstab # Changed the "/var" line: # /dev/sda6 /var ext4 defaults,usrquota,grpquota,nodev,acl 1 2 mount /var -o remount quotacheck -vgcMF vfsv0 /var setquota -g cvs 100000 150000 300 500 /var # Set correct owner, group for ~cvs, and set default permissions: cd ~cvs # /var/cvs-repos mkdir .ssh chown -R cvs.cvs . chmod g+ws . setfacl -m d:g:cvs:rwX . # Create a repository for the COP-2805 class: mkdir cop2805 export CVSROOT=/var/cvs-repos/cop2805 cvs init # Create module "cvsproj" in the "cop2805" repository: cd mkdir cvsproj cd cvsproj # The following tells CVS to ignore the Eclipse and NetBeans project files # and folders, so if a student forgets to exclude those from a commit, # it will not corrupt the project files of other students: cat <<\EOF > .cvsignore .?* nbproject build.xml manifest.mf EOF mkdir -p src/mypkg cat <<\EOF > src/mypkg/SayHello.java # copy from ~/private/SayHello.java // CVS collaborative COP-2805 (Java II) project. // $Id$ package mypkg; public class SayHello { public static void main ( String [] args ) { int counter = 0; // (1) Add your own output below that includes your name. // (2) Place "counter++;" command after your contribution, to keep count. // (3) Keep the last println statement at the very end. System.out.println( "Howdy! My name is Wayne Pollock." ); counter++; System.out.println( "Number of students who edited this file: " + counter ); } } EOF cvs import -m 'Create initial project' cvsproj vendor start cd rmdir cvsproj $ cat <<\EOF >> .bash_profile if echo "X$HOSTNAME" | grep -qi '^XYborStudent' then CVSROOT='/var/cvs-repos/cop2805' else CVSROOT=':ext:wpollock@YborStudent.hccfl.edu:/var/cvs-repos/cop2805' fi CVS_RSH=ssh export CVSROOT CVS_RSH EOF # Configure repository: cvs checkout CVSROOT cd CVSROOT vi notify tail notify ALL mail -s "YborStudent CVS notification - cop2805" cvs vi users # Lists email address to use, rather than local mail cat users wpollock:pollock@acm.org cvs add users # Not needed for class setup, but allows anonymous checkout: echo anonymous > readers cvs add readers cvs commit -m 'Allow use of cvs watch command' notify users readers # Prevent line-ending conversions and keyword expansions in media files: vi cvswrappers tail -n 3 cvswrappers *.gif -k 'b' -m 'COPY' *.jpg -k 'b' -m 'COPY' *.png -k 'b' -m 'COPY' cvs commit -m 'Prevent media (binary) file corruption' cvswrappers vi modules cop2805 cop2805 cvs commit -m 'Initialize repo module list' modules vi loginfo tail loginfo # Notify cvs administrator of all commits: ALL mail -s 'YborStudent CVS Repository commit by $USER: %{psv}' cvs cvs commit -m 'Automatically maintain current copy in my private website, and send email notice to cvs-admin-cop2805 (pollock@acm.org) after each commit' loginfo cd .. cvs release -d CVSROOT # Setup procmail to process the cvs (forward to wpollock) email # commit notices: cat <<\EOF >~/.procmailrc # Redirect CVS commit notices for cop2805 repo, and update website: :0 c *^Subject: YborStudent CVS Repository commit by .* ! pollock@acm.org # Forward the mail that matched the last rule's condition (A flag): # The sed command transforms the Subject line from something like: # Subject: YborStudent CVS Repository commit by wpollock: "cvsproj/src ,Foo.java,1.2" # to just the module name ("cvsproj" in this example). The module name is then passed # as a command line argument to the update script. The initial sed N command joins # two lines, as the subject is often split over two lines: :0 A | (MODULE=$(sed -n '/^Subject:/{N; s,[^"]*"\([^/ ]*\)[/ ].*$,\1,p}') && \ /home/wpollock/bin/update-cvs-website "$MODULE") EOF cat <<\EOF >~/bin/update-cvs-website #!/bin/bash # This script is intended to be invoked by procmail, whenever # wpollock receives a CVS update email. Procmail will parse the # email subject line to extract the name of the module that was # updated, and pass it as the only command line argument. # If run interactively with no module name, the default module # of "cvsproj" is used. # # $Id: update-cvs-website,v 1.5 2013/03/20 03:29:33 wpollock Exp $ LC_ALL=POSIX export CVSROOT=/var/cvs-repos/cop2805 MODULE=${1:-cvsproj} # Adds a system log (/var/log/messages) entry, useful for debugging: #logger -t updatecvswebsite "Updating CVS module: $MODULE" OUTPUT=$( ssh wpollock@wpollock.com \ 'cd /home/wpollock.com/secure-html/cvs-repos; umask 022; \ test -d "'"$MODULE"'" || mkdir "'"$MODULE"'"; \ CVS_RSH=ssh \ cvs -q -d :ext:wpollock@yborstudent.hccfl.edu/var/cvs-repos/cop2805 \ update -d '"$MODULE" 2>&1) LOG=$(cvs rlog -r. $MODULE 2>&1) DIFF=$(cvs rdiff -t $MODULE 2>&1) echo "Check https://wpollock.com/cvs-repos/ Update output: $OUTPUT ------------------------------------------------------------ Log message: $LOG ------------------------------------------------------------ Diff output of this and previous version: $DIFF " |expand |tr -cd '[:graph:][:space:]' | mail -s \ "Updated cop2805 CVS repo website mirror, exit status: $?" \ pollock@acm.org EOF chmod +x bin/update-cvs-website # Add accounts for students, using official HCC user ID: vi ~wpollock/private/students-cop2805 # paste names from gradebook for User in $(cat students-cop2805) do useradd -c "(COP-2805 CVS)" -m $User gpasswd -a $User cvs setquota -u $User 6000 12000 2000 3000 /home setquota -u "$User" 1000 1500 100 200 /tmp setquota -u "$User" 2000 3000 100 200 /var # This is larger than usual done pwgen # repeat for all COP-2805 students: chfn -f 'Anne Student (COP-2805 CVS)' astudent passwd astudent ... #################################################################### # Setup website to hold snap-shot of module: # (accessed with: https://wpollock.com, requires login) ssh wpollock.com cat <<\EOF >> .bash_profile CVSROOT=:ext:wpollock@YborStudent.hccfl.edu:/var/cvs-repos/cop2805 CVS_RSH=ssh export CVSROOT CVS_RSH EOF su - -c 'useradd -c "CVS User" -d /var/cvs-repos -M cvs -s /sbin/nologin' cd ~wpollock/../secure-html mkdir cvs-repos chgrp cvs cvs-repos chmod g+s,a+rx cvs-repos setfacl -m d:o::rX cvs-repos cat <<\EOF >cvs-repos/index.php # auto-lists files in all modules Current Snap-shots of CVS Repositories

Current Snap-shots of CVS Repository Modules

(YborStudent.hccfl.edu/var/cvs-repos/cop2805)

\n" ); print( "

Module: " . basename($module) . "

\n" ); // List each file (recursively) in module: dir_list( $module ); } } // This function recursively lists the files in each module, ignoring // some entries: function dir_list ( $dir ) { $results = glob( $dir . '/*' ); // Return an array of all files in $dir. $results = array_filter( $results, "ignore"); // filter results if ( count($results) == 0 ) return false; // false indicates an empty directory echo "\n"; return true; // true means the directory wasn't empty. } // Shows non-HTML files escaped (raw) with line numbers; // shows HTML files normally: function show_link ( $pathname ) { global $cwd; $file = basename( $pathname ); $rel = str_replace( "$cwd/", '', "$pathname" ); // Relative pathname if ( preg_match( '/\.html?|\.jar|\.jpg$/', $file ) ) print( "
  • View $file
  • \n" ); else print( "
  • View " . "$file
  • \n" ); } // This function is used to filter the array of files in a directory: function ignore ( $file ) { $file = basename( $file ); $ignore_list = array( '.', '..', 'CVS' ); // entries not to show. if ( in_array( $file, $ignore_list ) ) return false; if ( preg_match( '/\,v?$/', $file ) ) return false; return true; } ?>
    EOF cat <<\EOF >cvs-repos/lister.php # Fancy text2HTML file lister PHP File Lister
    No filename provided!\n" . "

    You need to pass " . "file=name in the query string.\n" . "You can also add the linenums parameter " . "to display line numbers, the nodir " . "parameter to truncate the heading to only show the filename, " . "and the dl parameter to add a download link " . "(useful when showing line numbers).

    \n"; echo '
    '; exit; } if ( ! isset($dl) or $dl == "false" ) $dl = false; else $dl = true; if ( ! isset($linenums) or $linenums == "false" ) $linenums = false; else $linenums = true; // "nodir" means to only display the filename in the heading, // and not the pathname. if ( ! isset($nodir) or $nodir == "false" ) $nodir = false; else $nodir = true; // Output HTML document body (the file's contents): if ( $nodir ) echo "

    " . basename($file) . "

    \n"; else echo "

    $file

    \n"; if ( $dl ) echo "

    Download " . basename($file) . "

    \n"; echo "
    \n";
    
    //   echo htmlentities( file_get_contents($file) );
       $contents = file( $file, FILE_IGNORE_NEW_LINES );
       $linenumwidth = strlen( count($contents) );
       $format = "%" . $linenumwidth . "d: ";
    
       foreach ($contents as $line_num => $line) {
          if ( $linenums )
             printf( $format, ($line_num + 1) );
          echo htmlentities( rtrim($line) ) . "\n";
       }
    
       // Output HTML epilog:
       echo "
    \n"; ?>
    // ' ?>
    EOF chmod a+r cvs-repos/* # should not need this, with ACL set! # checkout initial version of project: cd cvs-repos cvs -q -d :ext:wpollock@yborstudent.hccfl.edu/var/cvs-repos/cop2805 \ checkout cvsproj # Adjust initial permissions: chmod -R a+rX . find -type d -exec chmod g+s '{}' + # if no ACLs, Add crontab job on wpollock.com to chmod a+rX ~/../secure-html/cvs-repos/ TODO: Configure security better, so only selected users (not all users listed in /etc/passwd!) have commit privileges to selected module(s). Also restrict access to CVSROOT module to admin users only. #################################################################### # To Create another project later, e.g., "Minigolf": Create new module as a new Eclipse project, "Minigolf". Right-click on project in Package Explorer, select Team-->Share Project... Select or enter CVS information Use project name as module name (avoid spaces in names!) ################################################################## # To add network access to cvs "pserver" service (Note: This is not # needed when students have system accounts, which is preferred): echo 'cvs: ALL' >> /etc/hosts.allow cat <<\EOF > /etc/xinetd.d/cvs # default: off # description: The CVS pserver allows pserver access to CVS \ # repositories from other systems. service cvspserver { disable = no socket_type = stream protocol = tcp wait = no user = root passenv = PATH server = /usr/bin/cvs server_args = -f --allow-root=/var/cvs-repos pserver } EOF chmod a+r /etc/xinetd.d/cvs /etc/init.d/xinetd reload #################################################################### # On client (your end), to use the CVS "pserver": export CVSROOT=:pserver:YborStudent.hccfl.edu/var/cvs-repos #export CVS_RSH=ssh # don't think this is needed for pserver use cvs login cvs co cop2805 cd cop2805 vi files cvs add files vi files cvs commit cd .. cvs release cop2805 rm -r cop2805 cvs logout