1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #if HAVE_UNISTD_H
7 # include <unistd.h>
8 #endif
9 #if HAVE_FCNTL_H
10 # include <fcntl.h>
11 #endif
12 #include "deco.h"
13 #include "dir.h"
14 #include "scr.h"
15 #include "env.h"
16
17 #define SHELL (usecshell ? cshname : shname)
18 #define ABSSHELL (usecshell ? cshabsname : shabsname)
19
20 #define MAXARGV 400
21
22 static char shname [] = "sh";
23 static char cshname [] = "csh";
24 static char shabsname [] = "/bin/sh";
25 static char cshabsname [] = "/bin/csh";
26
27 int usecshell;
28 int useredit, userview;
29 int showhidden = 1;
30 char editname [40], viewname [40];
31
32 static int metas (char *s);
33 static int cmpfil (char *d1, char *f1, char *d2, char *f2);
34
35 char *sysmsg [] = {
36 0,
37 "Hangup", /* SIGHUP 1 hangup */
38 "Interrupt", /* SIGINT 2 interrupt (rubout) */
39 "Quit", /* SIGQUIT 3 quit */
40 "Illegal instruction", /* SIGILL 4 illegal instruction */
41 "Trace/BPT trap", /* SIGTRAP 5 trace trap */
42 "IOT trap", /* SIGIOT 6 IOT instruction */
43 "EMT trap", /* SIGEMT 7 EMT instruction */
44 "Floating exception", /* SIGFPE 8 floating point exception */
45 "Killed", /* SIGKILL 9 kill */
46 "Bus error", /* SIGBUS 10 bus error */
47 "Memory fault", /* SIGSEGV 11 segmentation violation */
48 "Bad system call", /* SIGSYS 12 bad argument to system call */
49 "Broken pipe", /* SIGPIPE 13 write on a pipe with no one to read it */
50 "Alarm call", /* SIGALRM 14 alarm clock */
51 "Terminated", /* SIGTERM 15 software termination signal from kill */
52 };
53
54 int numsysmsg = (sizeof sysmsg / sizeof sysmsg[0]);
55
56 /* ARGSUSED */
57
directory(int k,int sk)58 void directory (int k, int sk)
59 {
60 setdir (cur, sk == 'r' ? "/" : home);
61 }
62
switchalign(int k)63 void switchalign (int k)
64 {
65 struct dir *d = k=='l' ? &left : &right;
66
67 d->alignext ^= 1;
68 }
69
switchcmdreg()70 void switchcmdreg ()
71 {
72 cmdreg ^= 1;
73 }
74
switchhidden()75 void switchhidden ()
76 {
77 showhidden ^= 1;
78 setdir (cur == &left ? &right : &left, 0);
79 setdir (cur, 0);
80 }
81
switchpanels()82 void switchpanels ()
83 {
84 cur = cur==&left ? &right : &left;
85 chdir (cur->cwd);
86 }
87
setstatus()88 void setstatus ()
89 {
90 if (cur == &left)
91 right.status ^= 1;
92 else
93 left.status ^= 1;
94 }
95
fullscreen(int k,int sk)96 void fullscreen (int k, int sk)
97 {
98 VClearBox (1, 0, LINES-2, 80);
99 if (H == LINES/2-1)
100 H = LINES-7;
101 else
102 H = LINES/2-1;
103 while (left.topfile + PAGELEN (&left) <= left.curfile)
104 left.topfile += H;
105 while (right.topfile + PAGELEN (&right) <= right.curfile)
106 right.topfile += H;
107 }
108
redraw()109 void redraw ()
110 {
111 VRedraw ();
112 }
113
reread(int k,int sk)114 void reread (int k, int sk)
115 {
116 struct dir *d = k=='l' ? &left : &right;
117 register char *p;
118
119 if (! (p = getwstring (50, d->cwd, " Change directory ", "Change directory to")))
120 return;
121 if (! strcmp (p, d->cwd))
122 setdir (d, 0);
123 else if (chdir (p) < 0)
124 error ("Cannot chdir to %s", p);
125 else
126 setdir (d, ".");
127 chdir (cur->cwd);
128 }
129
setdwid()130 void setdwid ()
131 {
132 VClearBox (1, 0, LINES-2, 80);
133 widewin ^= 1;
134 while (left.topfile + PAGELEN (&left) <= left.curfile)
135 left.topfile += H;
136 while (right.topfile + PAGELEN (&right) <= right.curfile)
137 right.topfile += H;
138 }
139
setfull(int k,int sk)140 void setfull (int k, int sk)
141 {
142 register struct dir *c = k=='l' ? &left : &right;
143
144 switch (sk) {
145 case 'b':
146 c->view = VIEW_BRIEF;
147 break;
148 case 'l':
149 c->view = VIEW_LONG;
150 break;
151 case 'w':
152 c->view = VIEW_WIDE;
153 break;
154 case 'f':
155 c->view = VIEW_FULL;
156 if (! widewin)
157 setdwid ();
158 break;
159 case 'i':
160 c->view = VIEW_INFO;
161 if (! widewin)
162 setdwid ();
163 break;
164 }
165 while (c->topfile + PAGELEN (c) <= c->curfile)
166 c->topfile += H;
167 }
168
setsort(int k,int sk)169 void setsort (int k, int sk)
170 {
171 register struct dir *c = k=='l' ? &left : &right;
172
173 switch (sk) {
174 case 'n': c->sort = SORTNAME; break;
175 case 'x': c->sort = SORTEXT; break;
176 case 't': c->sort = SORTTIME; break;
177 case 'z': c->sort = SORTSIZE; break;
178 case 'u': c->sort = SORTSKIP; break;
179 }
180 setdir (c, 0);
181 chdir (cur->cwd);
182 }
183
settypesort(int k)184 void settypesort (int k)
185 {
186 register struct dir *c = k=='l' ? &left : &right;
187
188 c->typesort ^= 1;
189 setdir (c, 0);
190 chdir (cur->cwd);
191 }
192
setrevsort(int k)193 void setrevsort (int k)
194 {
195 register struct dir *c = k=='l' ? &left : &right;
196
197 c->revsort ^= 1;
198 setdir (c, 0);
199 chdir (cur->cwd);
200 }
201
setviewname()202 void setviewname ()
203 {
204 register char *p;
205
206 switch (getchoice (0, " View ", "Select which viewer to use for F3:",
207 0, " Built-in ", " External ", 0)) {
208 case 0:
209 userview = 0;
210 default:
211 return;
212 case 1:
213 break;
214 }
215 if (! (p = getstring (40, viewname, " View ", "Viewer to use")))
216 return;
217 strncpy (viewname, p, 40);
218 viewname [39] = 0;
219 userview = 1;
220 }
221
setshellname()222 void setshellname ()
223 {
224 switch (getchoice (0, " Shell ", "Select which shell to use:",
225 0, " Shell ", " Cshell ", 0)) {
226 case 0:
227 usecshell = 0;
228 break;
229 case 1:
230 usecshell = 1;
231 break;
232 }
233 }
234
seteditname()235 void seteditname ()
236 {
237 register char *p;
238
239 switch (getchoice (0, " Edit ", "Select which editor to use for F4:",
240 0, " Built-in ", " External ", 0)) {
241 case 0:
242 useredit = 0;
243 default:
244 return;
245 case 1:
246 break;
247 }
248 if (! (p = getstring (40, editname, " Edit ", "Editor to use")))
249 return;
250 strncpy (editname, p, 40);
251 editname [39] = 0;
252 useredit = 1;
253 }
254
view()255 void view ()
256 {
257 char buf [80];
258 register char *name = cur->cat[cur->curfile].name;
259 register d;
260
261 if (userview) {
262 strcpy (buf, viewname);
263 strcat (buf, " ");
264 strcat (buf, name);
265 VRestore ();
266 syscmd (buf);
267 VReopen ();
268 VRedraw ();
269 setdir (cur == &left ? &right : &left, 0);
270 setdir (cur, 0);
271 return;
272 }
273 if ((d = open (name, 0)) < 0) {
274 error ("Cannot open %s", name);
275 return;
276 }
277 viewfile (d, name);
278 close (d);
279 }
280
viewinfo()281 void viewinfo ()
282 {
283 char buf [80];
284 char name [512];
285 register d;
286
287 sprintf (name, "%s/.info/%s", cur->cwd, cur->cat[cur->curfile].name);
288 if (userview) {
289 strcpy (buf, viewname);
290 strcat (buf, " ");
291 strcat (buf, name);
292 VRestore ();
293 syscmd (buf);
294 VReopen ();
295 VRedraw ();
296 setdir (cur == &left ? &right : &left, 0);
297 setdir (cur, 0);
298 return;
299 }
300 if ((d = open (name, 0)) < 0) {
301 error ("Cannot open %s", name);
302 return;
303 }
304 viewfile (d, name);
305 close (d);
306 }
307
editfnam(char * name)308 static void editfnam (char *name)
309 {
310 register d;
311 register char *p;
312 char buf [80];
313 struct stat st;
314
315 if (stat (name, &st) >= 0) {
316 if ((st.st_mode & S_IFMT) != S_IFREG) {
317 error ("Cannot edit special files");
318 return;
319 }
320 } else {
321 d = creat (name, 0644);
322 if (d < 0) {
323 error ("Cannot create %s", name);
324 return;
325 }
326 close (d);
327 }
328 if (useredit) {
329 strcpy (buf, editname);
330 strcat (buf, " ");
331 strcat (buf, name);
332 VRestore ();
333 syscmd (buf);
334 VReopen ();
335 VRedraw ();
336 setdir (cur == &left ? &right : &left, 0);
337 setdir (cur, 0);
338 return;
339 }
340 if ((d = open (name, 2)) < 0) {
341 error ("Cannot open %s for writing", name);
342 return;
343 }
344 /* skip directory name */
345 for (p=name; *p; ++p);
346 for (; p>=name && *p!='/'; --p);
347 editfile (d, name, p+1);
348 close (d);
349 }
350
edit()351 void edit ()
352 {
353 register char *name = cur->cat[cur->curfile].name;
354 char namebuf [50];
355
356 if (strcmp (name, ".") == 0) {
357 name = getstring (40, 0, " Edit ",
358 "Enter name of file to edit");
359 if (! name)
360 return;
361 strcpy (namebuf, name);
362 editfnam (namebuf);
363 return;
364 }
365 editfnam (name);
366 }
367
editinfo()368 void editinfo ()
369 {
370 char name [512];
371
372 sprintf (name, "%s/.info/%s", cur->cwd, cur->cat[cur->curfile].name);
373 editfnam (name);
374 }
375
menuedit()376 void menuedit ()
377 {
378 char buf [80];
379
380 switch (getchoice (0, " Menu Edit ", "Select which menu to edit:",
381 0, " Current menu ", " Home menu ", 0)) {
382 case 0:
383 editfnam (".menu");
384 break;
385 case 1:
386 strcpy (buf, home);
387 strcat (buf, "/.menu");
388 editfnam (buf);
389 break;
390 }
391 }
392
extedit()393 void extedit ()
394 {
395 char buf [80];
396
397 strcpy (buf, home);
398 strcat (buf, "/.deco");
399 editfnam (buf);
400 }
401
quit()402 void quit ()
403 {
404 int choice;
405
406 choice = getchoice (ppid == 1, " Demos Commander ",
407 ppid == 1 ? "Do you want to log out ?" :
408 "Do you want to quit the Demos Commander ?",
409 0, " Yes ", " No ", " Exec shell ");
410 if (choice == 0)
411 quitdeco ();
412 if (choice == 2) {
413 /* exec shell */
414 VClear ();
415 VSync ();
416 VClose ();
417 execle (ABSSHELL, SHELL, "-i", 0, EnvVector);
418 exit (0);
419 }
420 /* else stay here */
421 }
422
quitdeco()423 void quitdeco ()
424 {
425 VMove (LINES-1, 0);
426 VClearLine ();
427 VSync ();
428 VClose ();
429 exit (0);
430 }
431
swappanels()432 void swappanels ()
433 {
434 struct dir dir;
435 int ro, lo;
436
437 ro = right.shortcwd - right.cwd;
438 lo = left.shortcwd - left.cwd;
439 dir = left;
440 left = right;
441 right = dir;
442 left.basecol = 0;
443 right.basecol = 40;
444 right.shortcwd = lo + right.cwd;
445 left.shortcwd = ro + left.cwd;
446 cur = (cur == &left ? &right : &left);
447 }
448
shell()449 void shell ()
450 {
451 /* run shell */
452 VClear ();
453 VSync ();
454 VRestore ();
455 runl (0, ABSSHELL, SHELL, "-i", NULL);
456 VReopen ();
457 VClear ();
458 setdir (cur == &left ? &right : &left, 0);
459 setdir (cur, 0);
460 }
461
tagged()462 int tagged ()
463 {
464 register i, n;
465
466 for (i=n=0; i<cur->num; ++i)
467 if (cur->cat[i].tag)
468 ++n;
469 return (n);
470 }
471
copy()472 void copy ()
473 {
474 char buf [80];
475 char *name;
476 register struct file *p;
477 register c;
478 int done, all, ch;
479 int exd, exf;
480
481 c = tagged ();
482 if (c) {
483 /* copy group of files */
484
485 sprintf (buf, "Copy %d file%s to", c, c>1 ? "s" : "");
486 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd,
487 " Copy ", buf)))
488 return;
489 runset (name);
490 exd = exist (name);
491 all = 0;
492 for (p=cur->cat; p<cur->cat+cur->num; ++p)
493 if (p->tag) {
494 sprintf (buf, "%s/%s", name, p->name);
495 exf = exd=='d' ? exist (buf) : 0;
496 if (exd=='f' || exf=='f') {
497 if (! all) {
498 ch = getchoice (1, " Copy ", "File exists",
499 exf=='f' ? buf : name,
500 " Overwrite ", " All ", " Cancel ");
501 switch (ch) {
502 case 2: /* cancel */
503 --c;
504 continue;
505 case 1: /* all */
506 all = 1;
507 case 0: /* all */
508 break;
509 default:
510 runcancel ();
511 return;
512 }
513 }
514 } else if (exf == 'd') {
515 error ("%s is a directory", buf);
516 continue;
517 }
518 runarg (p->name);
519 p->tag = 0;
520 }
521 if (c <= 0) {
522 runcancel ();
523 return;
524 }
525 message (" Copy ", "Copying %d file%s to %s ...", c, c>1 ? "s" : "", name);
526 done = rundone ("/bin/cp", "cp", "-f", "-p");
527 if (done) {
528 endmesg ();
529 message (" Copy ", "Done");
530 } else
531 error ("Error while copying %d file%s to %s",
532 c, c>1 ? "s" : "", name);
533 endmesg ();
534 } else if ((c = (p = &cur->cat[cur->curfile])->mode & S_IFMT) == S_IFDIR) {
535 /* copying directory */
536 } else if (c == S_IFREG) {
537 /* copy regular file */
538
539 sprintf (buf, "Copy \"%s\" to", p->name);
540 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd, " Copy ", buf)))
541 return;
542 exd = exist (name);
543 sprintf (buf, "%s/%s", name, p->name);
544 exf = exd=='d' ? exist (buf) : 0;
545 if (exd=='f' || exf=='f') {
546 if (getchoice (1, " Copy ", "File exists",
547 exf=='f' ? buf : name,
548 " Overwrite ", " Cancel ", 0))
549 return;
550 } else if (exf == 'd') {
551 error ("%s is a directory", buf);
552 return;
553 }
554 if (runl (1, "/bin/cp", "cp", "-f", "-p", p->name, name, NULL)) {
555 error ("Cannot copy %s to %s", p->name, name);
556 return;
557 }
558 }
559 setdir (cur == &left ? &right : &left, 0);
560 setdir (cur, 0);
561 }
562
makelink()563 void makelink ()
564 {
565 char buf [80];
566 char *name;
567 register struct file *p;
568 register c;
569 int done;
570 int exd, exf;
571
572 c = tagged ();
573 if (c) {
574 /* link group of files */
575
576 sprintf (buf, "Link %d file%s to", c, c>1 ? "s" : "");
577 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd,
578 " Link ", buf)))
579 return;
580 runset (name);
581 exd = exist (name);
582 for (p=cur->cat; p<cur->cat+cur->num; ++p)
583 if (p->tag) {
584 sprintf (buf, "%s/%s", name, p->name);
585 exf = exd=='d' ? exist (buf) : 0;
586 if (exd=='f' || exf=='f') {
587 if (getchoice (1, " Link ", "File exists",
588 exf=='f' ? buf : name,
589 " Overwrite ", " Cancel ", 0))
590 continue;
591 } else if (exf == 'd') {
592 error ("%s is a directory", buf);
593 continue;
594 }
595 runarg (p->name);
596 p->tag = 0;
597 }
598 message (" Link ", "Linking %d file%s to %s ...", c, c>1 ? "s" : "", name);
599 done = rundone ("/bin/ln", "ln", "-f", 0);
600 if (done) {
601 endmesg ();
602 message (" Link ", "Done");
603 } else
604 error ("Error while linking %d file%s to %s",
605 c, c>1 ? "s" : "", name);
606 endmesg ();
607 } else if ((c = (p = &cur->cat[cur->curfile])->mode & S_IFMT) == S_IFDIR) {
608 /* linking directory */
609 } else if (c == S_IFREG) {
610 /* link regular file */
611
612 sprintf (buf, "Link \"%s\" to", p->name);
613 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd, " Link ", buf)))
614 return;
615 exd = exist (name);
616 sprintf (buf, "%s/%s", name, p->name);
617 exf = exd=='d' ? exist (buf) : 0;
618 if (exd=='f' || exf=='f') {
619 if (getchoice (1, " Link ", "File exists",
620 exf=='f' ? buf : name,
621 " Overwrite ", " Cancel ", 0))
622 return;
623 } else if (exf == 'd') {
624 error ("%s is a directory", buf);
625 return;
626 }
627 if (runl (1, "/bin/ln", "ln", "-f", p->name, name, NULL)) {
628 error ("Cannot link %s to %s", p->name, name);
629 return;
630 }
631 }
632 setdir (cur == &left ? &right : &left, 0);
633 setdir (cur, 0);
634 }
635
636 #ifdef S_IFLNK
makeslink()637 void makeslink ()
638 {
639 char buf [80];
640 char *name;
641 register struct file *p;
642 register c;
643 int done;
644 int exd, exf;
645
646 c = tagged ();
647 if (c) {
648 /* symlink group of files */
649
650 sprintf (buf, "Symlink %d file%s to", c, c>1 ? "s" : "");
651 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd,
652 " Symlink ", buf)))
653 return;
654 runset (name);
655 exd = exist (name);
656 for (p=cur->cat; p<cur->cat+cur->num; ++p)
657 if (p->tag) {
658 sprintf (buf, "%s/%s", name, p->name);
659 exf = exd=='d' ? exist (buf) : 0;
660 if (exd=='f' || exf=='f') {
661 if (getchoice (1, " Symlink ", "File exists",
662 exf=='f' ? buf : name,
663 " Overwrite ", " Cancel ", 0))
664 continue;
665 } else if (exf == 'd') {
666 error ("%s is a directory", buf);
667 continue;
668 }
669 runarg (p->name);
670 p->tag = 0;
671 }
672 message (" Symlink ", "Linking %d file%s to %s ...", c, c>1 ? "s" : "", name);
673 done = rundone ("/bin/ln", "ln", "-s", "-f");
674 if (done) {
675 endmesg ();
676 message (" Symlink ", "Done");
677 } else
678 error ("Error while linking %d file%s to %s",
679 c, c>1 ? "s" : "", name);
680 endmesg ();
681 } else if ((c = (p = &cur->cat[cur->curfile])->mode & S_IFMT) == S_IFDIR) {
682 /* symlinking directory */
683 } else if (c == S_IFREG) {
684 /* symlink regular file */
685
686 sprintf (buf, "Symlink \"%s\" to", p->name);
687 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd, " Symlink ", buf)))
688 return;
689 exd = exist (name);
690 sprintf (buf, "%s/%s", name, p->name);
691 exf = exd=='d' ? exist (buf) : 0;
692 if (exd=='f' || exf=='f') {
693 if (getchoice (1, " Symlink ", "File exists",
694 exf=='f' ? buf : name,
695 " Overwrite ", " Cancel ", 0))
696 return;
697 } else if (exf == 'd') {
698 error ("%s is a directory", buf);
699 return;
700 }
701 if (runl (1, "/bin/ln", "ln", "-s", "-f", p->name, name, NULL)) {
702 error ("Cannot symlink %s to %s", p->name, name);
703 return;
704 }
705 }
706 setdir (cur == &left ? &right : &left, 0);
707 setdir (cur, 0);
708 }
709 #endif /* S_IFLNK */
710
renmove()711 void renmove ()
712 {
713 char buf [MAXPATHLEN+20];
714 char *name = 0;
715 register struct file *p;
716 register c;
717 int done, all, ch;
718 int exd, exf;
719
720 c = tagged ();
721 if (c) {
722 /* move group of files */
723
724 sprintf (buf, "Rename or move %d file%s to", c, c>1 ? "s" : "");
725 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd,
726 " Rename ", buf)))
727 return;
728 runset (name);
729 exd = exist (name);
730 all = 0;
731 for (p=cur->cat; p<cur->cat+cur->num; ++p)
732 if (p->tag) {
733 sprintf (buf, "%s/%s", name, p->name);
734 exf = exd=='d' ? exist (buf) : 0;
735 if (exd=='f' || exf=='f') {
736 if (! all) {
737 ch = getchoice (1, " Rename ", "File exists",
738 exf=='f' ? buf : name,
739 " Overwrite ", " All ", " Cancel ");
740 switch (ch) {
741 default:
742 case 2: /* cancel */
743 continue;
744 case 1: /* all */
745 all = 1;
746 }
747 }
748 } else if (exf == 'd') {
749 error ("%s is a directory", buf);
750 continue;
751 }
752 runarg (p->name);
753 }
754 message (" Move ", "Moving %d file%s to %s ...", c, c>1 ? "s" : "", name);
755 done = rundone ("/bin/mv", "mv", "-f", 0);
756 if (done) {
757 endmesg ();
758 message (" Move ", "Done");
759 } else
760 error ("Error while moving %d file%s to %s",
761 c, c>1 ? "s" : "", name);
762 endmesg ();
763 name = 0;
764 } else if ((c = (p = &cur->cat[cur->curfile])->mode & S_IFMT) == S_IFDIR) {
765 /* rename directory */
766
767 sprintf (buf, "Rename \"%s\" to", strtail (p->name, '/', 60));
768 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd, " Rename ", buf)))
769 return;
770 exd = exist (name);
771 sprintf (buf, "%s/%s", name, p->name);
772 exf = exd=='d' ? exist (buf) : 0;
773 if (exd=='f' || exf=='f') {
774 if (getchoice (1, " Rename ", "File exists",
775 exf=='f' ? buf : name,
776 " Overwrite ", " Cancel ", 0))
777 return;
778 } else if (exf == 'd') {
779 error ("Directory %s exists", buf);
780 return;
781 }
782 if (runl (1, "/bin/mv", "mv", "-f", p->name, name, NULL)) {
783 error ("Cannot move %s to %s", p->name, name);
784 return;
785 }
786 } else if (c == S_IFREG) {
787 /* move regular file */
788
789 sprintf (buf, "Rename or move \"%s\" to", p->name);
790 if (! (name = getstring (60, (cur==&left?&right:&left)->cwd, " Rename ", buf)))
791 return;
792 exd = exist (name);
793 sprintf (buf, "%s/%s", name, p->name);
794 exf = exd=='d' ? exist (buf) : 0;
795 if (exd=='f' || exf=='f') {
796 if (getchoice (1, " Rename ", "File exists",
797 exf=='f' ? buf : name,
798 " Overwrite ", " Cancel ", 0))
799 return;
800 } else if (exf == 'd') {
801 error ("%s is a directory", buf);
802 return;
803 }
804 if (runl (1, "/bin/mv", "mv", "-f", p->name, name, NULL)) {
805 error ("Cannot move %s to %s", p->name, name);
806 return;
807 }
808 }
809 setdir (cur == &left ? &right : &left, 0);
810 setdir (cur, 0);
811 if (name)
812 findfile (cur, name);
813 }
814
makedir()815 void makedir ()
816 {
817 register char *p;
818
819 if (! (p = getstring (60, 0, " Make directory ", "Create the directory")))
820 return;
821 switch (exist (p)) {
822 default:
823 case 'f':
824 error ("File %s exists", p);
825 break;
826 case 'd':
827 error ("Directory %s already exists", p);
828 break;
829 case 0:
830 if (runl (1, "/bin/mkdir", "mkdir", p, NULL)) {
831 error ("Cannot create directory %s", p);
832 break;
833 }
834 setdir (cur == &left ? &right : &left, 0);
835 setdir (cur, 0);
836 findfile (cur, p);
837 break;
838 }
839 }
840
delete()841 void delete ()
842 {
843 char buf [80];
844 register struct file *p;
845 register c;
846
847 c = tagged ();
848 if (c) {
849 /* delete group of files */
850
851 sprintf (buf, "You have selected %d file%s.", c, c>1 ? "s" : "");
852 if (getchoice (0, " Delete ", buf, 0, " Delete ", " Cancel ", 0))
853 return;
854 sprintf (buf, "You are DELETING %d selected file%s from", c, c>1 ? "s" : "");
855 if (getchoice (1, " Delete ", buf, cur->cwd, " Ok ", " Cancel ", 0))
856 return;
857 for (p=cur->cat; p<cur->cat+cur->num; ++p)
858 if (p->tag && unlink (p->name) < 0)
859 error ("Cannot delete %s", p->name);
860 } else if ((c = (p = &cur->cat[cur->curfile])->mode & S_IFMT) == S_IFDIR) {
861 /* delete directory */
862
863 if (getchoice (0, " Delete ", "Do you wish to delete directory",
864 p->name, " Delete ", " Cancel ", 0))
865 return;
866 if (runl (1, "/bin/rmdir", "rmdir", p->name, NULL)) {
867 error ("Cannot delete directory %s", p->name);
868 return;
869 }
870 } else if (c == S_IFREG) {
871 /* delete regular file */
872
873 if (getchoice (0, " Delete ", "Do you wish to delete",
874 p->name, " Delete ", " Cancel ", 0))
875 return;
876 if (unlink (p->name) < 0) {
877 error ("Cannot delete %s", p->name);
878 return;
879 }
880 }
881 setdir (cur == &left ? &right : &left, 0);
882 setdir (cur, 0);
883 }
884
findname()885 void findname ()
886 {
887 register char *s, *q;
888 register char *p;
889 register struct file *f;
890
891 if (! (p = getwstring (20, "", " Find file ", "Enter file name")) || ! *p)
892 return;
893 for (f=cur->cat; f<cur->cat+cur->num; ++f) {
894 s=p;
895 q=f->name;
896 for (;;) {
897 if (! *s) {
898 cur->curfile = f - cur->cat;
899 if (cur->topfile > cur->curfile || cur->topfile + PAGELEN (cur) <= cur->curfile)
900 cur->topfile = cur->curfile - PAGELEN (cur) + 1;
901 while (cur->topfile + PAGELEN (cur) - H > cur->curfile)
902 cur->topfile -= H;
903 if (cur->topfile < 0)
904 cur->topfile = 0;
905 return;
906 } else if (*s != *q)
907 break;
908 ++s;
909 ++q;
910 }
911 }
912 error ("File not found");
913 }
914
tagall()915 void tagall ()
916 {
917 register char *p;
918 register struct file *f;
919 static char pat [20];
920
921 if (! pat[0])
922 strcpy (pat, "*");
923 if (! (p = getwstring (20, pat, " Select ", "Select the files")))
924 return;
925 strncpy (pat, p, 20);
926 pat [19] = 0;
927 for (f=cur->cat; f<cur->cat+cur->num; ++f)
928 if ((f->mode & S_IFMT) == (unsigned) S_IFREG &&
929 (! pat[0] || match (f->name, pat)))
930 f->tag = 1;
931 counttag (cur);
932 }
933
untagall()934 void untagall ()
935 {
936 register char *p;
937 register struct file *f;
938 static char pat [20];
939
940 if (! pat[0])
941 strcpy (pat, "*");
942 if (! (p = getwstring (20, pat, " Unselect ", "Unselect the files")))
943 return;
944 strncpy (pat, p, 20);
945 pat [19] = 0;
946 for (f=cur->cat; f<cur->cat+cur->num; ++f)
947 if ((f->mode & S_IFMT) == (unsigned) S_IFREG &&
948 (! pat[0] || match (f->name, pat)))
949 f->tag = 0;
950 counttag (cur);
951 }
952
setpattern(int k)953 void setpattern (int k)
954 {
955 struct dir *d = k=='l' ? &left : &right;
956 register char *p;
957
958 if (! (p = getwstring (20, d->pattern, " Set pattern ", "Set pattern for files")))
959 return;
960 strncpy (d->pattern, p, PATSZ);
961 d->pattern [PATSZ-1] = 0;
962 setdir (d, 0);
963 chdir (cur->cwd);
964 }
965
cmpdir()966 void cmpdir ()
967 {
968 register struct file *f, *of;
969 register struct dir *d, *od;
970 struct file *end, *oend;
971 int cmp;
972
973 d = &left;
974 od = &right;
975 end = d->cat + d->num;
976 oend = od->cat + od->num;
977 for (of=od->cat; of<oend; ++of)
978 if ((of->mode & S_IFMT) == (unsigned) S_IFREG)
979 of->tag = 1;
980 for (f=d->cat; f<end; ++f)
981 if ((f->mode & S_IFMT) == (unsigned) S_IFREG)
982 f->tag = 1;
983 for (f=d->cat, of=od->cat; of<oend; ++of) {
984 while ((cmp = compfile (f, of)) < 0)
985 if (++f >= end)
986 goto breakloop;
987 if (! of->tag || ! f->tag)
988 continue;
989 if (cmp || f->size != of->size)
990 continue;
991 if (cmpfil (d->cwd, f->name, od->cwd, of->name))
992 f->tag = of->tag = 0;
993 }
994 breakloop:
995 counttag (d);
996 counttag (od);
997 }
998
cmpfil(char * d1,char * f1,char * d2,char * f2)999 static int cmpfil (char *d1, char *f1, char *d2, char *f2)
1000 {
1001 register i;
1002 int fd1, fd2;
1003 char buf1 [512], buf2 [512];
1004 int n1, n2, rez;
1005
1006 sprintf (buf1, "%s/%s", d1, f1);
1007 sprintf (buf2, "%s/%s", d2, f2);
1008 if ((fd1 = open (buf1, 0)) < 0)
1009 return (0);
1010 if ((fd2 = open (buf2, 0)) < 0) {
1011 close (fd1);
1012 return (0);
1013 }
1014 rez = 0;
1015 for (;;) {
1016 n1 = read (fd1, buf1, sizeof (buf1));
1017 n2 = read (fd2, buf2, sizeof (buf2));
1018 if (n1 < 0 || n2 < 0 || n1 != n2)
1019 break;
1020 if (n1 == 0) {
1021 rez = 1;
1022 goto breakloop;
1023 }
1024 for (i=0; i<n1; ++i)
1025 if (buf1 [i] != buf2 [i])
1026 goto breakloop;
1027 }
1028 breakloop:
1029 close (fd1);
1030 close (fd2);
1031 return (rez);
1032 }
1033
syscmd(char * s)1034 void syscmd (char *s)
1035 {
1036 register status, sig;
1037
1038 if (metas (s)) {
1039 if (usecshell)
1040 runl (0, cshabsname, cshname, "-f", "-c", s, NULL);
1041 else
1042 runl (0, shabsname, shname, "-c", s, NULL);
1043 return;
1044 }
1045 status = doexec (s);
1046 if (status < 0) {
1047 TtyReset ();
1048 outerr ("\n[%d] %s\n", -status, s);
1049 jobcmd (-status, s);
1050 return;
1051 }
1052 sig = status & 0177;
1053 if (! sig)
1054 return;
1055 if (sig == 0177)
1056 outerr ("ptrace: ");
1057 else if (sig < numsysmsg && sysmsg [sig])
1058 outerr (sysmsg [sig]);
1059 else
1060 outerr ("Signal %d", sig);
1061 if (status & 0200)
1062 outerr (" - core dumped\n");
1063 else
1064 outerr ("\n");
1065 }
1066
1067 /*
1068 * Are there are any Shell meta-characters?
1069 */
metas(char * s)1070 static int metas (char *s)
1071 {
1072 while (*s)
1073 switch (*s++) {
1074 case '|': case '^': case ';': case '&':
1075 case '(': case ')': case '<': case '>':
1076 case '[': case ']': case '*': case '?':
1077 case '\'': case '\"': case '\\': case '`':
1078 case '$': case '~':
1079 /* case '\n': case '=': case ':': */
1080 return (1);
1081 }
1082 return (0);
1083 }
1084
doexec(char * str)1085 int doexec (char *str)
1086 {
1087 register char *t;
1088 char *argv [MAXARGV+1];
1089 register char **p;
1090 int status;
1091
1092 while (*str == ' ' || *str == '\t')
1093 ++str;
1094 if (! *str)
1095 return (-1); /* no command */
1096 t = malloc (strlen (str) + 1);
1097 strcpy (t, str);
1098 str = t;
1099 p = argv;
1100 for (t = str; *t;) {
1101 if (p >= argv+MAXARGV) {
1102 error ("%s: Too many arguments", str);
1103 break;
1104 }
1105 *p++ = t;
1106 while (*t && *t!=' ' && *t!='\t')
1107 ++t;
1108 if (*t)
1109 for (*t++ =0; *t==' ' || *t=='\t'; ++t);
1110 }
1111 *p = 0;
1112 status = runv (0, str, argv);
1113 free (str);
1114 return (status);
1115 }
1116