Import of revision 19971210+
[mspang/plceo1.git] / lib_sys.pl
1 #
2 # Date                  Name                            Modification
3 # ----          ----                ------------
4 # 94/09/12              Alex Brodsky            Split off from main ceo file
5 # 96/05/17              Nikita Borisov          Added ISBN checks
6 # 96/10/23              Nikita Borisov          Use dbmtie instead of fakedbm
7 # 96/10/24              Nikita Borisov          'use NDBM_File' to make dbmopen
8 #                                                                       use that format.  Should really
9 #                                                                       replace them with 'tie' sometime
10 #                                                                       soon.
11 # 96/10/24              Nikita Borisov          'soon' came sooner than expected
12 # 97/07/04              Dax Hutcheon            Fixed the Edit book list menu
13
14 require "/u/ceo/ceo/isbn.pl";
15 use NDBM_File;
16 use Fcntl;
17
18 sub librarymenu
19 {
20     local($menu) = <<EOM;
21
22 Choose an option:
23   Sign a book (I)n
24   Sign a book (O)ut
25   (V)iew outstanding books list
26   (E)dit book list
27   (M)ain menu
28
29 (I,O,V,M): 
30 EOM
31     @opts=('idobookin','odobookout','vdooutstanding','mmainmenu','edoeditdb' );
32     $choice = &domenu($menu,@opts);
33     return $choice;
34 }
35
36 sub dobookin
37 {
38     local ($bid);
39         local ($yes);
40
41         tie(%LIB, NDBM_File, $LIBDB, O_RDWR, 0600) || do
42     {
43         print "\n${beep}Error opening library database: $!\n";
44         return;
45     };
46
47     ## Get the book ID
48     while(1)
49     {
50         print "Enter the book ID: ";
51         chop($bid = <STDIN>);
52         $bid =~ s/[^\w-]//g;
53                 # let people type 0-07-054235-x
54                 $bid =~ tr/x/X/;
55         if ($bid =~ /^\s*$/)
56         {
57             print "\n${beep}No ID supplied - aborting.\n";
58                         untie(%LIB);
59             return;
60         }
61         unless (&validbookID($bid))
62         {
63             print "\n${beep}Invalid checksum - try again.\n\n";
64             next;
65         }
66                 unless (&ISBN_checksum($bid) ||
67                         defined $LIB{$bid}) {
68                         print "\n${beep}WARNING: Invalid ISBN: $bid.\n",
69                                   "Are you sure this is the right ID? ";
70                         $yes = <STDIN>;
71                         next unless $yes =~ /^y/i;
72                 }
73         last;
74     }
75
76     ## Make a library entry for this book, if none already
77     &Lib_Newbook($bid) unless defined $LIB{$bid};
78
79     ## Mark the book as being in the library
80     if (defined $LIB{$bid})
81     {
82         $LIB{$bid} =~ s/W\{([^\}]*)\}/W\{0\}/;
83         $whohad = $1;
84     }
85
86     ($btitle) = $LIB{$bid} =~ /N\{([^\}]*)\}/;
87
88     untie(%LIB);
89     &Backup("$LIBDB.db");
90     &Backup("$LIBDB.dir");
91     &Backup("$LIBDB.pag");
92
93     if ($whohad == 0)
94     {
95         print "\n${beep}No one had this book signed out - aborting.\n\n";
96         return;
97     }
98     
99     eval { dbmtie($MEMDB,\%MEM) } || do
100     {
101         print "\n${beep}Error opening members database: $!\n";
102         return;
103     };
104     $thename = (split(/;/,$MEM{$whohad}))[0];
105     dbmuntie(\%MEM);
106
107     ## Make an entry in the library log file
108     open (LIBLOG, ">>$LIBRARYLOG") || do
109     {
110         print "\n${beep}Error writing library log file: $!\n";
111         return;
112     };
113     chop($date = `date`);
114     print LIBLOG "$date;$whohad;$thename;IN;$bid;$btitle\n";
115     close(LIBLOG);
116
117     Backup($LIBRARYLOG);
118
119     print "\"$btitle\" has been received from $thename.\n";
120
121     &Gopher_Outstanding;
122 }
123
124 sub dobookout
125 {
126     local($memnum,$thename,$thepw,$bid,$flags,$btitle);
127     ## Who wants it?
128     print "Enter CSC member number: ";
129     chop($memnum=<STDIN>);
130     $memnum =~ s/\D//g;
131     if ($memnum =~ /^\s*$/)
132     {
133         print "\n${beep}No member number supplied - aborting.\n";
134         return;
135     }
136
137     ## Get the info on this member
138     eval { dbmtie($MEMDB,\%MEM) } || do
139     {
140         print "\n${beep}Unable to open member database: $!\n";
141         return;
142     };
143     unless (defined $MEM{$memnum})
144     {
145         print "\n${beep}No such member number is on record - aborting\n";
146         dbmuntie(\%MEM);
147         return;
148     }
149         $match = &MemThisTerm((split(/;/,$MEM{$memnum}))[7]);
150     unless ($match)
151     {
152         print "\n${beep}This member has not paid for the current term.\n";
153         dbmuntie(\%MEM);
154         return;
155     }
156     ($thename, $thepw) = (split(/;/,$MEM{$memnum}))[0,5];
157     dbmuntie(\%MEM);
158
159     if ($thepw ne "" && $ENV{'CALUM'} != 1)
160     {
161         print "Enter your CSC password: ";
162         if (crypt(&GetPass, $thepw) ne $thepw)
163         {
164             print "\n${beep}Incorrect password - aborting\n";
165             return;
166         }
167     }
168
169     print "\nName: $thename\n\n";
170
171     ## Read the library file
172     tie(%LIB, NDBM_File, $LIBDB, O_RDWR, 0600) || do
173     {
174         print "\n${beep}Error opening library database: $!\n";
175         return;
176     };
177
178     ## Get the book ID
179     while(1)
180     {
181         print "Enter the book ID: ";
182         chop($bid = <STDIN>);
183         $bid =~ s/[^\w-]//g;
184         if ($bid =~ /^\s*$/)
185         {
186             print "\n${beep}No ID supplied - aborting.\n";
187                         untie(%LIB);
188             return;
189         }
190         unless (&validbookID($bid))
191         {
192             print "\n${beep}Invalid checksum - try again.\n\n";
193             next;
194         }
195                 unless (&ISBN_checksum($bid) ||
196                         defined $LIB{$bid}) {
197                         print "\n${beep}WARNING: Invalid ISBN: $bid.\n",
198                                   "Are you sure this is the right ID? ";
199                         $yes = <STDIN>;
200                         next unless $yes =~ /^y/i;
201                 }
202         last;
203     }
204     
205
206     ## Make a library entry for this book, if none already
207     &Lib_Newbook($bid) unless defined $LIB{$bid};
208
209     if (defined $LIB{$bid})
210     {
211         ## Does someone have the book now?
212         $LIB{$bid} =~ /W\{([^\}]*)\}/;
213         $whohad = $1;
214         if ($whohad > 0)
215         {
216             ## Who has it?
217             untie(%LIB);
218             eval { dbmtie($MEMDB,\%MEM) } || do
219             {
220                 print "\n${beep}Unable to open members database: $!\n";
221                 return;
222             };
223             $hasname = (split(/;/,$MEM{$whohad}))[0];
224             dbmuntie(\%MEM);
225
226             print "\n${beep}This book is presently signed out to $hasname.\n";
227             print "Please sign it back in first.\n\n";
228             return;
229         }
230
231         ## Check the flags
232         $LIB{$bid} =~ /T\{([^\}]*)\}/;
233         $flags = $1;
234         if ($flags =~ /r/i)
235         {
236             ## Red dot
237             print "This book has a red dot.  It may not be removed from the CSC.\n";
238             untie(%LIB);
239             return;
240         }
241         if ($flags =~ /b/i)
242         {
243             ## Blue rectangle
244             print "This book has a blue rectangle.  It may only be taken to labs in MC and must be\n";
245             print "returned promptly.\n";
246         }
247
248         ## Mark the book as being out
249         $LIB{$bid} =~ s/W\{[^\}]*\}/W\{$memnum\}/;
250         chop($date = `date`);
251         $LIB{$bid} =~ s/D\{[^\}]*\}/D\{$date\}/;
252
253         ($btitle) = $LIB{$bid} =~ /N\{([^\}]*)\}/;
254
255         untie(%LIB);
256         &Backup("$LIBDB.db");
257                 &Backup("$LIBDB.dir");
258                 &Backup("$LIBDB.pag");
259
260         print "\"$btitle\" has been signed out.\n";
261
262         ## Make an entry in the library log file
263         open (LIBLOG, ">>$LIBRARYLOG") || do
264         {
265             print "\n${beep}Error writing library log file: $!\n";
266             return;
267         };
268         print LIBLOG "$date;$memnum;$thename;OUT;$bid;$btitle\n";
269         close(LIBLOG);
270
271         &Backup($LIBRARYLOG);
272         &Gopher_Outstanding;
273
274         print "Thank you.  Please return it as soon as possible.\n\n";
275     }
276 }
277
278 sub Lib_Newbook
279 {
280     local($bookid) = shift;
281     @answers = ("","","","","","N","N");
282     while(1)
283     {
284     &Editscreen(<<EOS);
285 This book is not in the library database.
286 Please enter the requested information.
287 Separate multiple entries of the same type (e.g. multiple authors)
288 by semicolons (;).
289
290 Do NOT break an entry across lines; let the line wrap.
291
292 Name/Title    : $answers[0]
293 Author/Editor : $answers[1]
294 Publisher     : $answers[2]
295 Year published: $answers[3]
296 ISBN          : $answers[4]
297 Does the book have a Red dot, Blue rectangle, or Nothing?
298        (R/B/N): $answers[5]
299 Is the book on loan to CSC?
300          (Y/N): $answers[6]
301 EOS
302     &VI;
303     @answers = split("\n",&Filterscreen);
304     grep(s/\}/\]/g,@answers);
305     if ($answers[0] =~ /^\s*$/)
306     {
307         print "\n${beep}No title given - aborting.\n\n";
308         return;
309     }
310     $answers[3] =~ s/\D//g;
311     $answers[4] =~ s/[^\dxX -]//g;
312     $answers[4] =~ s/x/X/g;
313     $answers[5] =~ s/^(.).*$/\u$1/;
314     $answers[5] =~ s/[^RBN]//g;
315     if ($answers[5] eq "")
316     {
317         print "\n${beep}Entry for R/B/N required.\n";
318         sleep 2;
319         next;
320     }
321     $answers[6] =~ s/^(.).*$/\u$1/;
322     $answers[6] =~ s/[^YN]//g;
323     if ($answers[6] eq "")
324     {
325         print "\n${beep}Entry for Y/N required.\n";
326         sleep 2;
327         next;
328     }
329     $answers[6] =~ s/N//;
330     $answers[6] =~ s/Y/L/;
331     last;
332     }
333
334     $LIB{$bookid} = "N{$answers[0]}A{$answers[1]}P{$answers[2]}Y{$answers[3]}I{$answers[4]}T{$answers[5]$answers[6]}W{0}D{Epoch}";
335
336 }
337
338
339 sub MakeOutstandFile
340 {
341  ## Read the library file
342     tie(%LIB, NDBM_File, $LIBDB, O_RDWR, 0600) || do
343     {
344         print "\n${beep}Error opening library database: $!\n";
345         return;
346     };
347     %Outstand = ();
348     foreach $bid (keys %LIB)
349     {
350         ($whohas) = $LIB{$bid} =~ /W\{(\d+)\}/;
351         next if $whohas == 0;
352         ($btitle) = $LIB{$bid} =~ /N\{([^\}]*)\}/;
353         ($bodate) = $LIB{$bid} =~ /D\{([^\}]*)\}/;
354                 $bodate =~ s/^[^ ]* (.*):\d* E.T/$1/;
355         $Outstand{$bid}="$whohas#$btitle#$bodate";
356     }
357     untie(%LIB);
358
359     eval { dbmtie($MEMDB,\%MEM) } || do
360     {
361         print "\n${beep}Error opening members database: $!\n";
362         return;
363     };
364     open (OUTSTAND, ">$editfile") || do
365     {
366         print "\n${beep}Unable to open outstanding books file: $!\n";
367         dbmuntie(\%MEM);
368         return;
369     };
370     select(OUTSTAND);
371     $-=0;
372     $= = shift;
373     foreach $obid (keys %Outstand)
374     {
375         ($onum,$obtitle,$odate) = $Outstand{$obid} =~ /^(.*)#(.*)#(.*)$/;
376         $oname = (split(/;/,$MEM{$onum}))[0];
377         write;
378     }
379     dbmuntie(\%MEM);
380     select(STDOUT);
381     close(OUTSTAND);
382 }
383
384 sub DisplayLibLog
385 {
386     open(LIBLOG, $LIBRARYLOG) || do
387     {
388         print "\n${beep}Unable to open library log: $!\n";
389         return;
390     };
391     open(SCRLIBLOG, ">$editfile") || do
392     {
393         print "\n${beep}Unable to open output file: $!\n";
394         close(LIBLOG);
395         return;
396     };
397     select(SCRLIBLOG);
398     $-=0;
399     $= = $ROWS - 1;
400     ##$_ = `stty size`; ($=) = /^(\d+)/; $= -= 2;
401     while(<LIBLOG>)
402     {
403         next if (/^\s*$/ || /^\s*#/);
404         ($ldate, $lnum, $lname, $ldir, $bid, $lbtitle) = split(/;/);
405         next if $lnum==0;
406                 ($ldate) = $ldate =~ /^... (.*):.. .*$/;
407         write;
408     }
409     close(LIBLOG);
410     select(STDOUT);
411     close(SCRLIBLOG);
412     &MORE;
413 }
414
415 sub Gopher_Outstanding
416 {
417  ## Read the library file
418     tie(%LIB, NDBM_File, $LIBDB, O_RDWR, 0600) || do
419     {
420         print "\n${beep}Error opening library database: $!\n";
421         return;
422     };
423     %Outstand = ();
424     foreach $bid (keys %LIB)
425     {
426         ($whohas) = $LIB{$bid} =~ /W\{(\d+)\}/;
427         next if $whohas == 0;
428         ($btitle) = $LIB{$bid} =~ /N\{([^\}]*)\}/;
429         ($bodate) = $LIB{$bid} =~ /D\{([^\}]*)\}/;
430         $Outstand{$bid}="$whohas#$btitle#$bodate";
431     }
432     untie(%LIB);
433
434     eval { dbmtie($MEMDB,\%MEM) } || do
435     {
436         print "\n${beep}Error opening members database: $!\n";
437         return;
438     };
439     open (OUTSTAND, ">$GOPHERDIR/library_outstand") || do
440     {
441         print "\n${beep}Unable to open outstanding books file: $!\n";
442         dbmuntie(\%MEM);
443         return;
444     };
445     select(OUTSTAND);
446     $-=0;
447     $= = 50000;
448     foreach $obid (keys %Outstand)
449     {
450         ($onum,$obtitle,$odate) = $Outstand{$obid} =~ /^(.*)#(.*)#(.*)$/;
451         $oname = (split(/;/,$MEM{$onum}))[0];
452         write;
453     }
454     dbmuntie(\%MEM);
455     select(STDOUT);
456     close(OUTSTAND);
457 #   &MakeOutstandFile(50000);
458 #   system <<EOJ;
459 #rcp $editfile csc_disk@descartes:Gopher/office_info/library_outstand
460 #EOJ
461 }
462
463 sub validbookID
464 {
465     local($bid) = shift;
466     return 1;
467 }
468
469 sub dooutstanding
470 {
471     ##$_ = `stty size`; ($height) = /^(\d+)/; $height -= 2;
472     $height = $ROWS - 2;
473     &MakeOutstandFile($height);
474     &MORE;
475 }
476
477 sub doeditdb
478 {
479     local($memnum,$thename,$thepw,$bid,$flags,$btitle);
480     ## Who wants it?
481     unless ($ENV{'CALUM'} == 1){
482                 print "Enter CSC member number: ";
483                 chop($memnum=<STDIN>);
484                 $memnum =~ s/\D//g;
485                 if ($memnum =~ /^\s*$/)
486                 {
487                         print "\n${beep}No member number supplied - aborting.\n";
488                         return;
489                 }
490                 $match = grep(/^$memnum$/,@oslist);
491                 unless (($match || $cscmem == 0) && $cscmem =~ /\d/)
492                 {
493                         print "Access denied.\n";
494                         return;
495                 }
496
497                 ## Get the info on this member
498                 eval { dbmtie($MEMDB,\%MEM) } || do
499                 {
500                         print "\n${beep}Unable to open member database: $!\n";
501                         return;
502                 };
503                 unless (defined $MEM{$memnum})
504                 {
505                         print "\n${beep}No such member number is on record - aborting\n";
506                         dbmuntie(\%MEM);
507                         return;
508                 }
509                 $match = grep(/^$TERM$/,split(/,/,(split(/;/,$MEM{$memnum}))[7]));
510                 unless ($match)
511                 {
512                         print "\n${beep}This member has not paid for the current term.\n";
513                         dbmuntie(\%MEM);
514                         return;
515                 }
516                 ($thename, $thepw) = (split(/;/,$MEM{$memnum}))[0,5];
517                 dbmuntie(\%MEM);
518
519                 if ($thepw ne "" && $ENV{'CALUM'} != 1)
520                 {
521                         print "Enter your CSC password: ";
522                         if (crypt(&GetPass, $thepw) ne $thepw)
523                         {
524                                 print "\n${beep}Incorrect password - aborting\n";
525                                 return;
526                         }
527                 }
528         }
529
530         $edit_choice = "not done";
531
532         while( $edit_choice ne "done" ){
533                 ## This is necessary because domenu eats the first character
534                 ## of the option selected. Who did that, and when are they
535                 ## available for a severe beating?
536             @edit_opts = ('eeasy','sscary','ldone');
537                 $edit_choice = &domenu(<<EOM,@edit_opts);
538 Choose an option:
539   (E)asy book list edit
540   (S)cary edit (things office minions were not meant to know)
541   (L)ibrary menu (don't leave this menu up when you are done!)
542
543 (E,S,L): 
544 EOM
545                 
546                 if( $edit_choice eq "scary" ){
547                         &scary_edit;
548                 } elsif( $edit_choice eq "easy" ){
549                         &easy_edit;
550                 }
551         }
552
553         &Backup("$LIBDB.db");
554         &Backup("$LIBDB.dir");
555         &Backup("$LIBDB.pag");
556
557         &Gopher_Outstanding;
558 }
559
560
561 sub scary_edit
562 {
563         if( !open(TMPFILE, ">lib.edit") ){
564         print "\n${beep}Error opening temporary file: $!\n";
565         }
566
567     ## Read the library file
568     tie(%LIB, NDBM_File, $LIBDB, O_RDWR, 0600) || do
569     {
570         print "\n${beep}Error opening library database: $!\n";
571                 close TMPFILE;
572         return;
573     };
574
575         for (keys %LIB){
576                 print TMPFILE "$_#$LIB{$_}\n";
577         }
578
579         close TMPFILE;
580
581         system( "rm -f lib.backup;cp lib.edit lib.backup" );
582         system( "/opt/bin/nvi lib.edit" );
583
584         if( open(TMPFILE, "lib.edit") ){
585                 %LIB = ();
586                 while( $_ = <TMPFILE> ){
587                         chomp $_;
588                         /^([^ ]*)#(.*)$/;
589                         $LIB{$1} = $2;
590                 }
591                 close TMPFILE;
592         } else {
593         print "\n${beep}Error opening temporary file: $!\n";
594         }
595
596         untie(%LIB);
597 }
598
599 # fixlib: allows library fixing
600 #
601 # Date                  Name                            Modification
602 # ----          ----                ------------
603 # 95/08/07              Alex Brodsky            Initial implementation
604 #               mlvanbie            Integrated it
605
606
607 sub ModLib
608 {
609         my($TMPFILE) = "ceofixlib.tmpfile";
610         local( $bid ) = shift;
611         local( @answers );
612         local( @r );
613         local( $dstr );
614
615     @answers = ($LIB{$bid} =~ m/.\{([^\}]*)\}/g);
616         $answers[8] = $bid;
617
618         open (EDIT, ">$TMPFILE") || do {
619                 print "\a\nUnable to open edit file: $!\n";
620                 return;
621         };
622
623         print EDIT "Title     : $answers[0]\n";
624         print EDIT "Author    : $answers[1]\n";
625         print EDIT "Publisher : $answers[2]\n";
626         print EDIT "Year      : $answers[3]\n";
627         print EDIT "ISBN      : $answers[4]\n";
628         print EDIT "Type      : $answers[5]\n";
629         print EDIT "Who has it: $answers[6]\n";
630         print EDIT "Date      : $answers[7]\n";
631         print EDIT "Book ID   : $answers[8]\n";
632         close(EDIT);
633
634         system("$EDITOR $TMPFILE");
635
636         open(EDIT, $TMPFILE) || do {
637                 print "\a\nUnable to open edit file: $!\n";
638                 return;
639         };
640         @r = <EDIT>;
641         close(EDIT);
642
643         @r = grep( s/^.*: //g, @r );
644         @r = grep( s/\n//g, @r );
645
646         $dstr = "N{$r[0]}A{$r[1]}P{$r[2]}Y{$r[3]}I{$r[4]}T{$r[5]}W{$r[6]}D{$r[7]}";
647
648         if( ( $dstr ne $LIB{$bid} ) || ( $bid ne $r[8] ) ) {
649                 print "Changing entry\n";
650                 print "Old: $LIB{$bid}\n";
651                 print "New: $dstr\n";
652                 delete $LIB{$bid};
653                 $LIB{$r[8]} = $dstr;
654         } else {
655                 print "No change made\n";
656         }
657 }
658
659
660 sub easy_edit
661 {
662         my($bid);
663         my($TMPFILE) = "ceofixlib.tmpfile";
664
665     ## open database
666     tie(%LIB, NDBM_File, $LIBDB, O_RDWR, 0600) || do
667     {
668         print "\n\aError opening library database: $!\n";
669         return;
670     };
671
672         print "\nEnter book ID (or enter for list): ";
673         $bid = <STDIN>;
674         chomp $bid;
675         $bid =~ s/^\s*(.*\S)\s*$/$1/;
676
677         if( $bid eq "" ) {
678                 local($a);
679                 local($b);
680                 $a = $b = 0;
681
682                 print "ISBN key required to edit entry, here is complete list\n";
683
684                 open(SCRLIBLOG, ">$editfile") || do
685                 {
686                         print "\n${beep}Unable to open output file: $!\n";
687                         untie( %LIB );
688                         return;
689                 };
690
691                 select(SCRLIBLOG);
692         @list = sort {$a<=>$b} keys %LIB;
693                 foreach $bid (@list)
694                 {
695                         ($title) = ($LIB{$bid} =~ m/.\{([^\}]*)\}/g);
696                 print "$title $bid\n";
697                 }
698                 select(STDOUT);
699                 close(SCRLIBLOG);
700                 &MORE;
701         } else {
702                 if( defined $LIB{ $bid } ) {
703                         &ModLib( $bid );
704                 } else {
705                         print "Entry not found\n";
706                 }
707         }
708
709         untie(%LIB);
710 }
711
712 1;