Annotation of loncom/debugging_tools/move_construction_spaces.pl, revision 1.8
1.1 raeburn 1: #!/usr/bin/perl
2: #
1.3 raeburn 3: # The LearningOnline Network
4: #
1.1 raeburn 5: # Move Construction Spaces from /home/$user/public_html
6: # to /home/httpd/html/priv/$domain/$user and vice versa
1.3 raeburn 7: #
1.8 ! raeburn 8: # $Id: move_construction_spaces.pl,v 1.7 2011/12/09 03:01:44 raeburn Exp $
1.3 raeburn 9: #
10: # Copyright Michigan State University Board of Trustees
11: #
12: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
13: #
14: # LON-CAPA is free software; you can redistribute it and/or modify
15: # it under the terms of the GNU General Public License as published by
16: # the Free Software Foundation; either version 2 of the License, or
17: # (at your option) any later version.
18: #
19: # LON-CAPA is distributed in the hope that it will be useful,
20: # but WITHOUT ANY WARRANTY; without even the implied warranty of
21: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22: # GNU General Public License for more details.
23: #
24: # You should have received a copy of the GNU General Public License
25: # along with LON-CAPA; if not, write to the Free Software
26: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27: #
28: # /home/httpd/html/adm/gpl.txt
29: #
30: # http://www.lon-capa.org/
31: #
32: #################################################
1.1 raeburn 33:
34: use strict;
35: use lib '/home/httpd/lib/perl/';
36: use LONCAPA::Configuration;
37: use LONCAPA qw(:DEFAULT :match);
38: use Apache::lonlocal;
39: use File::Copy;
40: use GDBM_File;
1.6 raeburn 41: use DBI;
1.1 raeburn 42:
1.6 raeburn 43: my ($lonusersdir,$londocroot,$londaemons,$lonsqlaccess);
1.5 raeburn 44:
45: BEGIN {
46: my $perlvar=&LONCAPA::Configuration::read_conf();
47: if (ref($perlvar) eq 'HASH') {
48: $lonusersdir = $perlvar->{'lonUsersDir'};
49: $londocroot = $perlvar->{'lonDocRoot'};
50: $londaemons = $perlvar->{'lonDaemons'};
1.6 raeburn 51: $lonsqlaccess = $perlvar->{'lonSqlAccess'};
1.5 raeburn 52: }
53: undef($perlvar);
54: }
55:
1.1 raeburn 56: my $lang = &Apache::lonlocal::choose_language();
57: &Apache::lonlocal::get_language_handle(undef,$lang);
1.2 raeburn 58:
59: if ($< != 0) {
1.3 raeburn 60: print &mt('You must be root in order to move Construction Spaces.')."\n".
61: &mt('Stopping')."\n";
1.2 raeburn 62: exit;
63: }
64:
1.5 raeburn 65: if ($lonusersdir eq '') {
1.4 raeburn 66: print &mt('Could not determine location of [_1] directory.',"'lonUsersDir'")."\n".
67: &mt('Stopping')."\n";
68: exit;
69: }
70:
71: if ($londocroot eq '') {
72: print &mt('Could not determine location of [_1] directory.',"'lonDocRoot'")."\n".
73: &mt('Stopping')."\n";
74: exit;
75: }
76:
1.3 raeburn 77: my $distro;
1.4 raeburn 78: if ($londaemons eq '') {
79: print &mt('Could not determine location of [_1] directory.',"'lonDaemons'")."\n".
80: &mt('Stopping')."\n";
81: exit;
82: } else {
1.3 raeburn 83: if (-e "$londaemons/distprobe") {
84: if (open(PIPE,"perl $londaemons/distprobe|")) {
85: $distro = <PIPE>;
86: close(PIPE);
87: }
88: }
89: }
90:
91: if ($distro eq '') {
92: print &mt('Could not determine Linux distro.')."\n".
93: &mt('Stopping')."\n";
94: exit;
95: } else {
96: my $stopapachecmd = '/etc/init.d/httpd stop';
97: my $apacheprocess = '/usr/sbin/httpd';
98: my $stopapachecmd = '/etc/init.d/httpd stop';
99: my $proc_owner = 'root';
100: if ($distro =~ /^(suse|sles)/) {
101: if ($distro =~ /^(suse|sles)9/) {
102: $stopapachecmd = '/etc/init.d/apache stop';
103: } else {
104: $apacheprocess = '/usr/sbin/httpd2';
105: $stopapachecmd = '/etc/init.d/apache2 stop';
106: }
107: } elsif ($distro =~ /^(?:debian|ubuntu)(\d+)/) {
108: $apacheprocess = '/usr/sbin/apache2';
109: $stopapachecmd = '/etc/init.d/apache2 stop';
110: } elsif ($distro =~ /^(?:fedora)(\d+)/) {
111: my $version = $1;
112: if ($version >= 16) {
113: $stopapachecmd = '/bin/systemctl stop httpd.service';
114: }
115: }
116: if (open(PIPE,"ps -ef |grep '$apacheprocess' |grep -v grep 2>&1 |")) {
117: my $status = <PIPE>;
118: close(PIPE);
119: chomp($status);
120: if ($status =~ /^\Q$proc_owner\E\s+\d+\s+/) {
121: print "\n".
122: &mt('You need to stop the Apache daemon before moving Construction Spaces.')."\n".
123: &mt('To do so use the following command: [_1]',"\n\n$stopapachecmd")."\n\n".
124: &mt('Now stopping the move_construction_spaces.pl script.')."\n";
125: exit;
126: }
127: } else {
128: print &mt('Could not determine if Apache daemon is running.')."\n";
129: }
130: }
131:
132: my $stoploncontrol = '/etc/init.d/loncontrol stop';
133: if (open(PIPE,"ps -ef |grep lond |grep -v grep 2>&1 |")) {
134: my $status = <PIPE>;
135: close(PIPE);
136: chomp($status);
137: if ($status =~ /^www\s+\d+\s+/) {
138: print "\n".
139: &mt('You need to stop the LON-CAPA daemons before moving Construction Spaces.')."\n".
140: &mt('To do so use the following command: [_1]',"\n\n$stoploncontrol")."\n\n".
141: &mt('Now stopping the move_construction_spaces.pl script.')."\n";
142: exit;
143: }
144: }
145:
1.1 raeburn 146: # Abort if more than one argument.
1.2 raeburn 147:
148: my $parameter=$ARGV[0];
149: $parameter =~ s/^\s+//;
150: $parameter =~ s/\s+$//;
151:
152: if ((@ARGV > 1) || (($parameter ne '') && ($parameter !~ /^(move|undo)$/))) {
1.1 raeburn 153: print &mt('usage: [_1]','move_construction_spaces.pl [move|undo]')."\n\n".
154: &mt('You should enter either no arguments, or just one argument -- either move or undo.')."\n".
1.2 raeburn 155: &mt("move - to move authors' Construction Spaces from: [_1] to [_2].",
156: "'/home'","'$londocroot/priv/'")."\n".
157: &mt('undo - to reverse those changes and move Construction Spaces back from: [_1] to [_2].',
158: "'$londocroot/priv/'","'/home'")."\n".
1.1 raeburn 159: &mt('no argument to do a dry run of the move option, without actually moving anything.')."\n";
160: exit;
161: }
162:
1.2 raeburn 163: print "\n".&mt("Moving authors' Construction Spaces.")."\n".
1.1 raeburn 164: "-----------------------------\n\n".
1.2 raeburn 165: &mt('If run without an argument, the script will report what it would do when moving Construction Spaces from [_1] to [_2].',
166: "'/home'","'$londocroot/priv/'")."\n\n".
167: &mt('If there are ambiguities (i.e., the same username belongs to two domains), this will be flagged, and you will be able to decide how to proceed.')."\n";
1.1 raeburn 168:
169: my (undef,undef,$uid,$gid) = getpwnam('www');
170: my ($action) = ($parameter=~/^(move|undo)$/);
171: if ($action eq '') {
172: $action = 'dryrun';
173: }
174:
175: if ($action eq 'dryrun') {
1.5 raeburn 176: print "\n\n".
1.3 raeburn 177: &mt('Running in exploratory mode ...')."\n\n".
1.2 raeburn 178: &mt('Run with argument [_1] to actually move Construction Spaces to [_2], i.e., [_3]',
1.3 raeburn 179: "'move'","'$londocroot/priv'","\n\nperl move_construction_spaces.pl move")."\n\n\n".
1.2 raeburn 180: &mt('Run with argument [_1] to move Construction spaces back to [_2], i.e., [_3]',
1.3 raeburn 181: "'undo'","'/home'","\n\nperl move_construction_spaces.pl undo")."\n\n\n".
1.2 raeburn 182: &mt('Continue? ~[y/N~] ');
183: if (!&get_user_selection()) {
184: exit;
1.3 raeburn 185: } else {
186: print "\n";
1.2 raeburn 187: }
1.1 raeburn 188: } else {
1.3 raeburn 189: print "\n *** ".&mt('Running in a mode where changes will be made.')." ***\n";
1.1 raeburn 190: if ($action eq 'move') {
1.2 raeburn 191: print "\n".
192: &mt('Mode is [_1] -- directories will be moved to [_2].',
193: "'$action'","'$londocroot/priv'")."\n";
1.1 raeburn 194: } else {
1.2 raeburn 195: print "\n".
196: &mt('Mode is [_1] -- directories will be moved back to [_2].',
197: "'$action'","'/home'")."\n";
1.1 raeburn 198: }
199: print &mt('Continue? ~[y/N~] ');
200: if (!&get_user_selection()) {
201: exit;
1.3 raeburn 202: } else {
203: print "\n";
204: }
205: }
206:
207: my $logfh;
208: if ($action ne 'dryrun') {
209: if (!open($logfh,">>$londaemons/logs/move_construction_spaces.log")) {
210: print &mt('Could not open log file: [_1] for writing.',
211: "'$londaemons/logs/move_construction_spaces.log'")."\n".
212: &mt('Stopping.')."\n";
213: } else {
214: &start_logging($logfh,$action);
1.1 raeburn 215: }
216: }
217:
218: # Authors hosted on this server
219: my %allauthors;
220: my %pubusers;
221:
222: if ($action eq 'move') {
1.3 raeburn 223: my $output;
1.1 raeburn 224: if (-d "$londocroot/priv") {
1.3 raeburn 225: $output = &mt('New Construction Spaces directory: [_1] already exists.',
226: "'$londocroot/priv'")."\n";
227: print $output;
228: print $logfh $output;
1.1 raeburn 229: } else {
1.3 raeburn 230: $output = &mt('Creating new directory: [_1] for Construction Spaces.',
231: "'$londocroot/priv'")."\n";
232: if (mkdir("$londocroot/priv",0750)) {
1.1 raeburn 233: if (chown($uid,$gid,"$londocroot/priv")) {
1.3 raeburn 234: $output .= &mt('Creation Successful')."\n";
235: print $output;
236: print $logfh $output;
1.1 raeburn 237: } else {
1.3 raeburn 238: $output .= &mt('Failed to change ownership to [_1].',"'$uid:$gid'")."\n";
239: print $output;
240: &stop_logging($logfh,$output);
241: print &mt('Stopping')."\n";
1.1 raeburn 242: exit;
243: }
244: } else {
1.3 raeburn 245: $output .= &mt('Failed to create directory [_1].',"'$londocroot/priv'")."\n";
246: print $output;
247: &stop_logging($logfh,$output);
248: print &mt('Stopping')."\n";
1.2 raeburn 249: exit;
1.1 raeburn 250: }
251: }
252: }
253:
254: my @machinedoms;
1.5 raeburn 255: if ($lonusersdir) {
1.3 raeburn 256: my ($dir,$output);
1.5 raeburn 257: if (opendir($dir,$lonusersdir)) {
1.1 raeburn 258: my @contents = (grep(!/^\.{1,2}$/,readdir($dir)));
1.7 raeburn 259: closedir($dir);
1.1 raeburn 260: foreach my $item (@contents) {
1.5 raeburn 261: if (-d "$lonusersdir/$item") {
1.1 raeburn 262: if ($item =~ /^$match_domain$/) {
263: my $domain = $item;
264: unless (grep(/^\Q$domain\E$/,@machinedoms)) {
265: push(@machinedoms,$domain);
266: }
1.4 raeburn 267: my $dom_target="$londocroot/priv/$domain";
1.1 raeburn 268: if ($action eq 'move') {
269: if (!-e $dom_target) {
270: if (mkdir($dom_target,0755)) {
271: chown($uid,$gid,$dom_target);
1.3 raeburn 272: $output = &mt('Made [_1].',"'$dom_target'")."\n";
273: print $output;
274: print $logfh $output;
1.1 raeburn 275: } else {
1.3 raeburn 276: $output = &mt('Failed to make [_1].',"'$dom_target'")."\n";
277: print $output;
278: print $logfh $output;
279: &stop_logging($logfh,$output);
280: print &mt('Stopping')."\n";
1.1 raeburn 281: exit;
282: }
283: } elsif ($action eq 'dryrun') {
1.2 raeburn 284: print &mt('Would make [_1].',"'$dom_target'")."\n";
1.1 raeburn 285: }
286: }
287: my %authors=();
1.5 raeburn 288: my $fname = "$lonusersdir/$domain/nohist_domainroles.db";
1.1 raeburn 289: my $dbref;
290: if (-e $fname) {
291: $dbref=&LONCAPA::locking_hash_tie($fname,&GDBM_READER());
292: }
293: if (!$dbref) {
1.2 raeburn 294: print &mt('Unable to tie to [_1].',"'$fname'")."\n";
1.1 raeburn 295: } elsif (ref($dbref) eq 'HASH') {
296: foreach my $key (keys(%{$dbref})) {
297: $key = &unescape($key);
298: if ($key =~ /^au\:($match_username)\Q:$domain\E/) {
299: push(@{$allauthors{$1}},$domain);
300: }
301: }
302: &LONCAPA::locking_hash_untie($dbref);
303: }
304: }
305: }
306: }
307: } else {
1.5 raeburn 308: $output = &mt('Could not open [_1].',"'$lonusersdir'")."\n";
1.3 raeburn 309: print $output;
310: &stop_logging($logfh,$output);
311: print &mt('Stopping')."\n";
1.1 raeburn 312: exit;
313: }
314: }
315:
316: if ($londocroot ne '') {
317: if (-d "$londocroot/res") {
318: my ($dir,$domdir);
319: if (opendir($dir,"$londocroot/res")) {
320: my @contents = (grep(!/^\.{1,2}$/,readdir($dir)));
1.7 raeburn 321: closedir($dir);
1.1 raeburn 322: foreach my $dom (@contents) {
323: if ((grep(/^\Q$dom\E/,@machinedoms)) && (-d "$londocroot/res/$dom")) {
324: if (opendir($domdir,"$londocroot/res/$dom")) {
325: my @unames = (grep(!/^\.{1,2}$/,readdir($domdir)));
1.7 raeburn 326: closedir($domdir);
1.1 raeburn 327: foreach my $uname (@unames) {
328: if ($uname =~ /^$match_username$/) {
329: push(@{$pubusers{$uname}},$dom);
330: }
331: }
332: }
333: }
334: }
335: }
336: }
337: }
338:
339: if ($action eq 'undo') {
340: my %privspaces;
341: if ($londocroot ne '') {
342: if (-d "$londocroot/priv") {
343: my ($dir,$domdir);
344: if (opendir($dir,"$londocroot/priv")) {
345: my @contents = (grep(!/^\.{1,2}/,readdir($dir)));
1.7 raeburn 346: closedir($dir);
1.1 raeburn 347: foreach my $dom (@contents) {
348: next if (!-d "$londocroot/priv/$dom");
349: if (opendir($domdir,"$londocroot/priv/$dom")) {
350: my @unames = (grep(!/^\.{1,2}$/,readdir($domdir)));
1.7 raeburn 351: closedir($domdir);
1.1 raeburn 352: foreach my $uname (@unames) {
353: if ($uname =~ /^$match_username$/) {
354: push(@{$privspaces{$uname}},$dom);
355: }
356: }
357: }
358: }
359: }
360: }
361: }
362: foreach my $uname (keys(%privspaces)) {
363: if (ref($privspaces{$uname}) eq 'ARRAY') {
1.7 raeburn 364: my $output;
1.1 raeburn 365: if (@{$privspaces{$uname}} > 1) {
1.2 raeburn 366: my $displaydoms = join(', ',@{$privspaces{$uname}});
367: print &mt('Same username used for authors in multiple domains.')."\n".
368: &mt('This configuration is not supported where Construction Spaces are located in [_1].','/home').".\n".
369: &mt('You will be able to move files for just one of the domains, choose which one.')."\n".
370: &mt('The domains to choose from are: [_1].',"'$displaydoms'")."\n".
371: &mt('Enter choice: ');
1.1 raeburn 372: my $choice=<STDIN>;
373: chomp($choice);
374: if (grep(/^\Q$choice\E$/,@{$privspaces{$uname}})) {
1.7 raeburn 375: $output = &move_priv_to_home($londocroot,$uid,$gid,$uname,$choice);
1.1 raeburn 376: } else {
1.3 raeburn 377: print &mt('Invalid choice of domain:')." $choice\n";
1.7 raeburn 378: $output = &mt('Skipping this user: [_1].',"'$uname'")."\n";
1.3 raeburn 379: print $output;
380: print $logfh $output;
1.1 raeburn 381: next;
382: }
383: } elsif (@{$privspaces{$uname}} == 1) {
1.7 raeburn 384: $output = &move_priv_to_home($londocroot,$uid,$gid,$uname,$privspaces{$uname}[0]);
1.1 raeburn 385: } else {
1.2 raeburn 386: print &mt('Username [_1] found in [_2] was not within a domain',
387: "'$uname'","'$londocroot/priv'")."\n";
1.7 raeburn 388: $output = &mt('Skipping this user: [_1].',"'$uname'")."\n";
389: }
390: print $output;
391: print $logfh $output;
392: }
393: }
394: if (-d "$londocroot/priv") {
395: my $output;
396: if (opendir(my $dir,"$londocroot/priv")) {
397: my @doms = grep(!/^\.{1,2}/,readdir($dir));
398: closedir($dir);
399: foreach my $dom (@doms) {
400: if (opendir(my $domdir,"$londocroot/priv/$dom")) {
401: my @contents = grep(!/^\.{1,2}/,readdir($domdir));
402: closedir($domdir);
403: if (@contents == 0) {
404: if (rmdir("$londocroot/priv/$dom")) {
405: $output = &mt('Removed empty directory: [_1]',
406: "'$londocroot/priv/$dom'")."\n";
407: } else {
408: $output = &mt('Failed to remove directory: [_1]',
409: "'$londocroot/priv/$dom'")."\n";
410: }
411: }
412: }
413: }
414: }
415: my $warning = &mt('WARNING: Access to Construction Spaces in their old locations (i.e., in [_1]) via LON-CAPA with URLs of the form [_2] will not work until the directory at [_3] is moved or deleted.',"'/home/<user>/'","'/priv/<user>/'","'$londocroot/priv/'")."\n";
416: if (opendir(my $dir,"$londocroot/priv")) {
417: my @contents = (grep(!/^\.{1,2}/,readdir($dir)));
418: closedir($dir);
419: if (@contents == 0) {
420: if (rmdir("$londocroot/priv")) {
421: $output .= &mt('Removed empty directory: [_1]',
422: "'$londocroot/priv'")."\n";
423: } else {
424: $output .= &mt('Failed to remove directory: [_1]',
425: "'$londocroot/priv'")."\n".
426: $warning."\n";
427: }
428: } else {
429: $output .= $warning."\n".
430: &mt('The attempt to remove the directory failed, because it is not empty.')."\n";
1.1 raeburn 431: }
1.7 raeburn 432: } else {
433: $output .= $warning."\n".
434: &mt('The attempt to open the directory to see its contents failed, hence no attempt was made to remove it.')."\n";
1.1 raeburn 435: }
1.7 raeburn 436: print $output;
437: print $logfh $output;
1.1 raeburn 438: }
1.3 raeburn 439: &stop_logging($logfh);
440: print "\n".&mt('Done')."\n";
1.1 raeburn 441: exit;
442: }
443:
1.5 raeburn 444: my @allskipped;
445: my %allmoved;
1.6 raeburn 446: my ($dbh,$dbflag);
1.5 raeburn 447:
1.1 raeburn 448: # Iterate over directories in /home
449: if (opendir(my $dir,"/home")) {
1.7 raeburn 450: my @possibles = grep(!/^\.{1,2}$/,readdir($dir));
451: closedir($dir);
1.5 raeburn 452: foreach my $item (sort(@possibles)) {
1.1 raeburn 453: next if ($item eq 'www');
1.3 raeburn 454: if ((-d "/home/$item") && ($item ne '')) {
1.1 raeburn 455: # Is there a public_html-directory?
456: if (-d "/home/$item/public_html") {
457: my $author = $item;
1.6 raeburn 458: my ($domain,$skipped,$output,$stopnow);
1.5 raeburn 459: if (ref($allauthors{$author}) eq 'ARRAY') {
1.6 raeburn 460: ($domain,$skipped,$stopnow) =
461: &choose_domain($action,$author,$allauthors{$author});
462: if ($stopnow) {
463: if ($action ne 'dryrun') {
464: my $output = &mt('Stopped by user at author: [_1].',
465: "'$author'")/"\n";
466: &stop_logging($logfh,$output);
467: }
468: if ($dbflag == 1) {
469: &disconnect_mysql($dbh);
470: }
471: print &mt('Stopped.')."\n";
472: exit;
473: }
1.1 raeburn 474: }
475: if (($domain eq '') && (!$skipped)) {
1.5 raeburn 476: if (ref($pubusers{$author}) eq 'ARRAY') {
1.6 raeburn 477: ($domain,$skipped,$stopnow) =
478: &choose_domain($action,$author,$pubusers{$author});
479: }
480: if ($stopnow) {
481: if ($action ne 'dryrun') {
482: my $output = &mt('Stopped by user at author: [_1].',
483: "'$author'")/"\n";
484: &stop_logging($logfh,$output);
485: }
486: if ($dbflag == 1) {
487: &disconnect_mysql($dbh);
488: }
489: print &mt('Stopped.')."\n";
490: exit;
1.5 raeburn 491: }
492: }
493: if (($domain eq '') && (!$skipped)) {
494: my @foundauthor = ();
495: foreach my $dom (@machinedoms) {
496: my $posspath = &LONCAPA::propath($dom,$author);
497: if (-e $posspath) {
498: my $rolesdbref;
499: my $fname = "$posspath/roles.db";
500: if (-e "$fname") {
501: $rolesdbref=&LONCAPA::locking_hash_tie($fname,&GDBM_READER());
502: if (!$rolesdbref) {
503: print &mt('Unable to tie to [_1].',"'$fname'")."\n";
504: } elsif (ref($rolesdbref) eq 'HASH') {
505: foreach my $key (keys(%{$rolesdbref})) {
506: if ($key eq "/$dom/_au") {
507: unless(grep(/^\Q$dom\E$/,@foundauthor)) {
508: push(@foundauthor,$dom);
509: }
510: }
511: }
512: &LONCAPA::locking_hash_untie($rolesdbref);
513: }
514: }
515: }
516: }
517: if (@foundauthor > 0) {
1.6 raeburn 518: ($domain,$skipped,$stopnow) =
519: &choose_domain($action,$author,\@foundauthor);
520: if ($stopnow) {
521: if ($action ne 'dryrun') {
522: my $output = &mt('Stopped by user at author: [_1].',
523: "'$author'")/"\n";
524: &stop_logging($logfh,$output);
525: }
526: if ($dbflag == 1) {
527: &disconnect_mysql($dbh);
528: }
529: print &mt('Stopped.')."\n";
530: exit;
531: }
532: }
533: }
534: if (($domain eq '') && (!$skipped)) {
535: if (!$dbflag) {
536: ($dbh,$dbflag) = &connect_mysql($lonsqlaccess);
537: }
538: if (defined($dbh)) {
539: my $foundusers = &search_allusers($dbh,$author);
540: if (ref($foundusers) eq 'HASH') {
541: ($domain,$skipped,$stopnow) =
542: &choose_domain($action,$author,$foundusers);
543: }
544: if ($stopnow) {
545: if ($action ne 'dryrun') {
546: my $output = &mt('Stopped by user at author: [_1].',
547: "'$author'")/"\n";
548: &stop_logging($logfh,$output);
549: }
550: if ($dbflag == 1) {
551: &disconnect_mysql($dbh);
552: }
553: print &mt('Stopped.')."\n";
554: exit;
555: }
1.1 raeburn 556: }
557: }
1.3 raeburn 558: my $source_path="/home/$author/public_html";
1.5 raeburn 559: if ($domain) {
1.1 raeburn 560: my $target_path="$londocroot/priv/$domain/$author";
561: if ($action eq 'move') {
1.3 raeburn 562: if (move($source_path,$target_path)) {
1.5 raeburn 563: my (undef,undef,$userid,$groupid) = getpwnam($author);
564: if ($userid eq '' && $groupid eq '' && $author ne '') {
565: chown($uid,$gid,$target_path);
566: }
1.3 raeburn 567: $output = &mt('Moved [_1] to [_2].',
568: "'$source_path'","'$target_path'")."\n";
1.5 raeburn 569: push(@{$allmoved{$domain}},$author);
1.3 raeburn 570: my (undef,undef,$userid,$groupid) = getpwnam($author);
571: if ($userid eq '' && $groupid eq '' && $author ne '') {
572: &check_for_restore_files($londaemons,$author,$domain);
573: if (opendir(my $homedir,"/home/$author")) {
574: my @contents =
575: grep(!/^\.{1,2}$/,readdir($homedir));
1.7 raeburn 576: closedir($homedir);
1.3 raeburn 577: if (@contents == 0) {
578: if (rmdir("/home/$author/")) {
579: $output .= &mt('Removed empty directory: [_1]',
580: "'/home/$author/'")."\n";
581: } else {
582: $output .= &mt('Failed to remove directory: [_1]',
583: "'/home/$author/'")."\n";
584: }
585: } else {
586: $output .= &mt('Not removing directory [_1] as it still contains: [_2]',
587: "'/home/$author/'",
588: "\n".join("\n",@contents)."\n");
589: }
590: }
591: } else {
592: $output .= &mt('Not removing directory [_1] for UNIX user account',
593: "'/home/$author/'")."\n";
594: }
595: } else {
596: $output = &mt('Failed to move [_1] to [_2].',
597: "'$source_path'","'$target_path'")."\n";
598: }
599: print $output;
600: print $logfh $output;
1.1 raeburn 601: } elsif ($action eq 'dryrun') {
1.5 raeburn 602: push(@{$allmoved{$domain}},$author);
1.2 raeburn 603: print &mt('Would move [_1] to [_2].',"'$source_path'","'$target_path'")."\n";
1.1 raeburn 604: }
1.3 raeburn 605: } elsif ($skipped) {
1.5 raeburn 606: push(@allskipped,$author);
1.3 raeburn 607: if ($action ne 'dryrun') {
1.5 raeburn 608: my $output = &mt('Skipping this user: [_1].',"'$author'")."\n";
609: print $logfh $output;
1.3 raeburn 610: }
611: } else {
1.2 raeburn 612: print '*** '.&mt('WARNING: [_1] has no domain.',"'$author'")."\n".
1.6 raeburn 613: &mt('Enter [_1]: skip this user.','1')."\n".
1.5 raeburn 614: &mt('Enter [_1]: stop.','2')."\n".
1.2 raeburn 615: &mt('or enter domain for user to be placed into')."\n".
616: &mt('Your input: ');
1.1 raeburn 617: my $choice=<STDIN>;
618: chomp($choice);
1.5 raeburn 619: $choice =~ s/^\s+//;
620: $choice =~ s/\s+$//;
621: if ($choice == 1) {
622: my $output = &mt('Skipping -- no domain for user: [_1].',"'$author'")."\n";
623: print $output;
624: if ($action ne 'dryrun') {
625: print $logfh $output;
626: }
627: push(@allskipped,$author);
628: next;
1.3 raeburn 629: }
1.2 raeburn 630: if ($choice == 2) {
631: print &mt('Stopped.')."\n";
1.3 raeburn 632: if ($action ne 'dryrun') {
633: my $output = &mt('Stopped by user because of author without domain: [_1].',
634: "'$author'")/"\n";
635: &stop_logging($logfh,$output);
636: }
1.6 raeburn 637: if ($dbflag == 1) {
638: &disconnect_mysql($dbh);
639: }
1.2 raeburn 640: exit;
1.5 raeburn 641: } elsif ($choice =~ /^$match_domain$/) {
642: print &mt('You entered:')." $choice\n".
643: &mt('Is this ok? ~[Y/n~] ');
644: if (!&get_user_selection(1)) {
645: print &mt('Try again ...')."\n".
1.6 raeburn 646: &mt('Enter [_1]: skip this user.','1')."\n".
1.5 raeburn 647: &mt('Enter [_1]: stop.','2')."\n".
648: &mt('or enter domain for user to be placed into')."\n".
649: &mt('Your input: ');
650: $choice=<STDIN>;
651: chomp($choice);
652: $choice =~ s/^\s+//;
653: $choice =~ s/\s+$//;
654: if ($choice == 1) {
655: my $output = &mt('Skipping -- no domain for user: [_1].',"'$author'")."\n";
656: print $output;
657: if ($action ne 'dryrun') {
658: print $logfh $output;
659: }
660: push(@allskipped,$author);
661: next;
662: }
663: if ($choice == 2) {
664: print &mt('Stopped.')."\n";
665: if ($action ne 'dryrun') {
666: my $output = &mt('Stopped by user because of author without domain: [_1].',
667: "'$author'")/"\n";
668: &stop_logging($logfh,$output);
669: }
1.6 raeburn 670: if ($dbflag == 1) {
671: &disconnect_mysql($dbh);
672: }
1.5 raeburn 673: exit;
674: } elsif ($choice !~ /^$match_domain$/) {
675: print &mt('Invalid domain entered:')." $choice\n";
676: my $output = &mt('Skipping -- no domain for user: [_1].',"'$author'")."\n";
677: print $output;
678: if ($action ne 'dryrun') {
679: print $logfh $output;
680: }
681: push(@allskipped,$author);
682: next;
683: }
684: }
1.1 raeburn 685: my $dompath="$londocroot/priv/$choice";
686: my $newpath="$londocroot/priv/$choice/$author";
687: unless (-e $dompath) {
1.5 raeburn 688: if ($action eq 'move') {
689: print '*** '.&mt('WARNING: [_1] does not yet exist.',"'$dompath'")."\n";
690: }
1.1 raeburn 691: }
692: if ($action eq 'move') {
693: unless (-e $dompath) {
1.3 raeburn 694: $output .= &mt('Making [_1].',"'$dompath'")."\n";
695: if (mkdir($dompath,0755)) {
696: chown($uid,$gid,$dompath);
697: }
698: }
699: if (-e $dompath) {
700: if (move($source_path,$newpath)) {
701: chown($uid,$gid,$newpath);
1.7 raeburn 702: chmod(0750,$newpath);
1.3 raeburn 703: $output = &mt('Moved [_1] to [_2].',
704: "'$source_path'","'$newpath'")."\n";
705: } else {
706: $output = &mt('Failed to move [_1] to [_2].',
707: "'$source_path'","'$newpath'")."\n";
708: }
709: print $output;
710: print $logfh $output;
711: } else {
712: $output = &mt('Failed to move [_1] to [_2] -- missing [_3].',
713: "'$source_path'","'$newpath'","'$dompath'")."\n";
1.1 raeburn 714: }
715: } elsif ($action eq 'dryrun') {
1.2 raeburn 716: print &mt('Would make author [_1] in domain [_2].',"'$author'","'$choice'")."\n";
1.1 raeburn 717: unless (-e $dompath) {
1.2 raeburn 718: print &mt('Would make [_1].',"'$dompath'")."\n";
1.1 raeburn 719: }
1.2 raeburn 720: print &mt('Would make [_1].',"'$newpath'")."\n";
1.1 raeburn 721: }
1.5 raeburn 722: } else {
723: print &mt('Invalid domain:')." $choice\n";
724: if ($action eq 'move') {
725: print $logfh &mt('Skipping -- no domain for user: [_1].',"'$author'")."\n";
726: }
727: push(@allskipped,$author);
728: next;
1.1 raeburn 729: }
730: }
731: }
732: }
733: }
734: }
1.5 raeburn 735:
736: my ($moveinfo,$skipcount);
737: if (keys(%allmoved) == 0) {
738: $moveinfo = &mt('None')."\n";
739: } else {
740: foreach my $dom (sort(keys(%allmoved))) {
741: if (ref($allmoved{$dom}) eq 'ARRAY') {
742: $moveinfo .= "\n ".&mt('Domain: [_1], number of authors: [_2]',
743: "'$dom'",scalar(@{$allmoved{$dom}}));
744: }
745: }
746: }
747:
748: $skipcount = scalar(@allskipped);
749:
750: print "\n";
1.3 raeburn 751: if ($action ne 'dryrun') {
1.5 raeburn 752: my $output = &mt('You skipped: [_1].',$skipcount)."\n".
1.6 raeburn 753: join("\n",sort(@allskipped))."\n\n".
1.5 raeburn 754: &mt('Moved ... [_1]',$moveinfo);
755: print $output;
756: print $logfh $output;
1.3 raeburn 757: &stop_logging($logfh);
1.5 raeburn 758: } else {
759: print &mt('You would have skipped: [_1].',$skipcount)."\n".
1.6 raeburn 760: join("\n",sort(@allskipped))."\n\n".
1.5 raeburn 761: &mt('You would have moved ... [_1]',$moveinfo);
1.3 raeburn 762: }
1.5 raeburn 763: print "\n\n".&mt('Done.')."\n";
1.1 raeburn 764:
1.6 raeburn 765: sub choose_domain {
766: my ($action,$author,$domref) = @_;
767: my ($domain,$skipped,$stopnow,@domains);
768: if (ref($domref) eq 'ARRAY') {
769: @domains = @{$domref};
770: } elsif (ref($domref) eq 'HASH') {
771: @domains = sort(keys(%{$domref}));
772: }
773: if (@domains > 1) {
774: print '*** '.&mt('ERROR: [_1] found in multiple domains.',"'$author'")."\n".
775: &mt('Enter a number to choose what action to take.')."\n";
776: my $num = 1;
777: print &mt('Enter [_1]: skip this user.',$num)."\n";
778: for (my $i=0; $i<@domains; $i++) {
779: my $shown = $domains[$i];
780: if (ref($domref) eq 'HASH') {
781: if ($domref->{$shown} ne '') {
782: $shown .= ' ('.$domref->{$shown}.') ';
783: }
784: }
785: $num ++;
786: print &mt('Enter [_1]: use domain - [_2].',$num,$shown)."\n";
787: }
788: $num ++;
789: print &mt('Enter [_1]: stop.',$num)."\n";
790: print &mt('Your choice:').' ';
791: my $choice=<STDIN>;
792: chomp($choice);
793: if ($choice =~ /^\d+$/) {
794: if ($choice == 1) {
795: $skipped = 1;
796: } elsif (($choice < $num) && ($choice > 1)) {
797: $domain = $domains[$choice-2];
798: } elsif ($choice == $num) {
799: $stopnow = 1;
800: } else {
801: print &mt('Invalid choice:')." $choice\n".
802: &mt('Skipping this user.')."\n";
803: $skipped = 1;
804: }
805: } else {
806: print &mt('Invalid choice:')." $choice\n".
807: &mt('Skipping this user.')."\n";
808: $skipped = 1;
809: }
810: } elsif (@domains == 1) {
811: $domain = $domains[0];
1.1 raeburn 812: }
1.6 raeburn 813: return ($domain,$skipped,$stopnow);
1.1 raeburn 814: }
815:
816: sub move_priv_to_home {
1.3 raeburn 817: my ($londocroot,$uid,$gid,$uname,$domain) = @_;
818: my $output;
1.1 raeburn 819: if ($uname =~ /^$match_username$/ && $domain =~ /^$match_domain$/) {
820: my $source_path="$londocroot/priv/$domain/$uname";
821: my $target_path="/home/$uname/public_html";
822: if (!-e "/home/$uname") {
1.3 raeburn 823: my (undef,undef,$userid,$groupid) = getpwnam($uname);
1.8 ! raeburn 824: if (mkdir("/home/$uname",0711)) {
1.3 raeburn 825: if ($userid ne '' && $groupid ne '') {
826: chown($userid,$groupid,"/home/$uname");
827: }
1.1 raeburn 828: } else {
1.3 raeburn 829: $output = &mt('Failed to create directory [_1] -- not moving [_2].',
1.2 raeburn 830: "'/home/$uname'","'$source_path'")."\n";
1.3 raeburn 831: return $output;
1.1 raeburn 832: }
833: }
1.3 raeburn 834: if (-e "/home/$uname") {
835: if (!-e $target_path) {
836: move($source_path,$target_path);
837: chown($uid,$gid,$target_path);
1.8 ! raeburn 838: chmod(02770,$target_path);
1.7 raeburn 839: if (-e $target_path && !-e $source_path) {
840: $output = &mt('Moved [_1] to [_2].',"'$source_path'","'$target_path'")."\n";
841: } else {
842: $output = &mt('Failed to move [_1] to [_2].',"'$source_path'","'$target_path'")."\n";
843: }
1.3 raeburn 844: } else {
845: $output = &mt('Directory [_1] already exists -- not moving [_2].',
846: "'$target_path'","'$source_path'")."\n";
847: }
1.1 raeburn 848: }
849: }
1.3 raeburn 850: return $output;
1.1 raeburn 851: }
852:
853: sub get_user_selection {
854: my ($defaultrun) = @_;
855: my $do_action = 0;
856: my $choice = <STDIN>;
857: chomp($choice);
858: $choice =~ s/(^\s+|\s+$)//g;
859: my $yes = &mt('y');
860: if ($defaultrun) {
861: if (($choice eq '') || ($choice =~ /^\Q$yes\E/i)) {
862: $do_action = 1;
863: }
864: } else {
865: if ($choice =~ /^\Q$yes\E/i) {
866: $do_action = 1;
867: }
868: }
869: return $do_action;
870: }
871:
1.3 raeburn 872: sub start_logging {
873: my ($fh,$action) = @_;
874: my $start = localtime(time);
875: print $fh "*****************************************************\n".
876: &mt('[_1] - mode is [_2].',
877: 'move_construction_spaces.pl',"'$action'")."\n".
878: &mt('Started -- time: [_1]',$start)."\n".
879: "*****************************************************\n\n";
880: return;
881: }
882:
883: sub stop_logging {
884: my ($fh) = @_;
885: my $end = localtime(time);
886: print $fh "*****************************************************\n".
887: &mt('Ended -- time: [_1]',$end)."\n".
888: "*****************************************************\n\n\n";
889: close($fh);
890: return;
891: }
892:
893: sub check_for_restore_files {
894: my ($londaemons,$author,$domain) = @_;
895: if (opendir(my $homedir,"/home/$author")) {
896: my @contents = grep(!/^\.{1,2}$/,readdir($homedir));
1.7 raeburn 897: closedir($homedir);
1.3 raeburn 898: if (@contents > 0) {
899: if (grep(/^restore_\d+\.sh$/,@contents)) {
900: if (!-e "$londaemons/logs/moved_construction_spaces") {
901: mkdir("$londaemons/logs/moved_construction_spaces",0755);
902: }
903: if (!-e "$londaemons/logs/moved_construction_spaces/$domain") {
904: mkdir("$londaemons/logs/moved_construction_spaces/$domain",0755);
905: }
906: if (-e "$londaemons/logs/moved_construction_spaces/$domain") {
907: if (open(my $restorefh,">>$londaemons/logs/moved_construction_spaces/$domain/$author")) {
908: foreach my $item (@contents) {
909: if ($item =~ /^restore_\d+\.sh$/) {
910: my @stats = stat("/home/$author/$item");
911: my $lastmod = $stats[9];
912: if (open(my $fh,"</home/$author/$item")) {
913: print $restorefh
914: "*******************************\n".
915: "$item -- ".localtime(time)."\n".
916: "*******************************\n";
917: while (<$fh>) {
918: print $restorefh $_;
919: }
920: print $restorefh
921: "*******************************\n\n";
922: close($fh);
923: unlink("/home/$author/$item");
924: }
925: }
926: }
927: close($restorefh);
928: }
929: }
930: }
931: }
932: }
933: return;
934: }
935:
1.6 raeburn 936: sub connect_mysql {
937: my ($lonsqlaccess) = @_;
938: my ($dbh,$dbflag);
939: eval { $dbh = DBI->connect("DBI:mysql:loncapa","www",
940: $lonsqlaccess,
941: {RaiseError =>0,PrintError=>0});
942: };
943: if ($@) {
944: $dbflag = -1;
945: } else {
946: if (defined($dbh)) {
947: $dbflag = 1;
948: }
949: }
950: return ($dbh,$dbflag);
951: }
952:
953: sub disconnect_mysql {
954: my ($dbh) = @_;
955: if (ref($dbh)) {
956: $dbh->disconnect;
957: }
958: return;
959: }
960:
961: sub search_allusers {
962: my ($dbh,$author) = @_;
963: my %fullnames;
964: if ((ref($dbh)) && ($author ne '')) {
965: eval {
966: my $statement = "SELECT domain, lastname, firstname FROM allusers WHERE username='$author'";
967: my $sth = $dbh->prepare($statement);
968: $sth->execute();
969: while ( my ($dom,$last,$first) = $sth->fetchrow_array()) {
970: if ($dom ne '') {
971: $fullnames{$dom} = "$first $last";
972: }
973: }
974: $sth->finish;
975: };
976: }
977: return \%fullnames;
978: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>