xref: /minix/minix/tests/test17.c (revision 7f5f010b)
1 /* Comment on usage and program: ark!/mnt/rene/prac/os/unix/comment.changes */
2 
3 /* "const.h", created by Rene Montsma and Menno Wilcke */
4 
5 #include <sys/types.h>		/* type defs */
6 #include <sys/stat.h>		/* struct stat */
7 #include <sys/wait.h>
8 #include <errno.h>		/* the error-numbers */
9 #include <fcntl.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <utime.h>
14 #include <stdio.h>
15 #include <limits.h>
16 #include <assert.h>
17 
18 #define NOCRASH 1		/* test11(), 2nd pipe */
19 #define PDPNOHANG  1		/* test03(), write_standards() */
20 int max_error = 2;
21 #include "common.h"
22 
23 
24 #define USER_ID   12
25 #define GROUP_ID   1
26 #define FF        3		/* first free filedes. */
27 #define USER      1		/* uid */
28 #define GROUP     0		/* gid */
29 
30 #define ARSIZE   256		/* array size */
31 #define PIPESIZE 3584		/* max number of bytes to be written on pipe */
32 #define MAXOPEN  (OPEN_MAX-3)		/* maximum number of extra open files */
33 #define MAXLINK 0177		/* maximum number of links per file */
34 #define LINKCOUNT 5
35 #define MASK    0777		/* selects lower nine bits */
36 #define END_FILE     0		/* returned by read-call at eof */
37 
38 #define OK      0
39 #define FAIL   -1
40 
41 #define R       0		/* read (open-call) */
42 #define W       1		/* write (open-call) */
43 #define RW      2		/* read & write (open-call) */
44 
45 #define RWX     7		/* read & write & execute (mode) */
46 
47 #define NIL     ""
48 #define UMASK   "umask"
49 #define CREAT   "creat"
50 #define WRITE   "write"
51 #define READ    "read"
52 #define OPEN    "open"
53 #define CLOSE   "close"
54 #define LSEEK   "lseek"
55 #define ACCESS  "access"
56 #define CHDIR   "chdir"
57 #define CHMOD   "chmod"
58 #define LINK    "link"
59 #define UNLINK  "unlink"
60 #define PIPE    "pipe"
61 #define STAT    "stat"
62 #define FSTAT   "fstat"
63 #define DUP     "dup"
64 #define UTIME   "utime"
65 
66 
67 /* "decl.c", created by Rene Montsma and Menno Wilcke */
68 
69 /* Used in open_alot, close_alot */
70 char *filenames[MAXOPEN];
71 
72 #define MODES 8
73 char *mode_fnames[MODES] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"},
74 *mode_dir[MODES] = {"d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x", "drw-", "drwx"};
75 
76  /* Needed for easy creating and deleting of directories */
77 
78 /* "test.c", created by Rene Montsma and Menno Wilcke */
79 
80 
81 int main(int argc, char *argv []);
82 void test(int mask);
83 void test01(void);
84 void test02(void);
85 void test08(void);
86 void test09(void);
87 void test10(void);
88 int link_alot(char *bigboss);
89 int unlink_alot(int number);
90 void get_new(char name []);
91 void test11(void);
92 void nlcr(void);
93 void str(char *s);
94 void test03(void);
95 void put_file_in_dir(char *dirname, int mode);
96 void init_array(char *a);
97 void clear_array(char *b);
98 int comp_array(char *a, char *b, int range);
99 void try_close(int filedes, char *name);
100 void try_unlink(char *fname);
101 void Remove(int fdes, char *fname);
102 int get_mode(char *name);
103 void check(char *scall, int number);
104 void put(int nr);
105 int open_alot(void);
106 int close_alot(int number);
107 void clean_up_the_mess(void);
108 void chmod_8_dirs(int sw);
109 void quit(void);
110 
111 /*****************************************************************************
112  *                              TEST                                         *
113  ****************************************************************************/
114 int main(argc, argv)
115 int argc;
116 char *argv[];
117 {
118   int n, mask, i;
119   pid_t child;
120 
121   start(17);
122 
123   /* Create filenames for MAXOPEN files, the *filenames[] array. */
124   for(i = 0; i < MAXOPEN; i++) {
125 	if(asprintf(&filenames[i], "file%d", i) == -1) {
126 		fprintf(stderr, "asprintf failed\n");
127 		quit();
128 	}
129   }
130 
131 
132   mask = (argc == 2 ? atoi(argv[1]) : 0xFFFF);
133   subtest = 0;
134   child = fork();
135   if (child == -1) {
136   	e(1);
137   	quit();
138   } else if (child == 0) {
139   	test(mask);
140   	return(0);
141   } else {
142   	wait(&n);
143 	clean_up_the_mess();
144 	quit();
145   }
146   return(-1);			/* impossible */
147 }
148 
149 void test(mask)
150 int mask;
151 {
152   umask(0);			/* not honest, but i always forget */
153 
154   if (mask & 00001) test01();
155   if (mask & 00002) test03();
156   if (mask & 00004) test02();
157   if (mask & 00010) test08();
158   if (mask & 00020) test09();
159   if (mask & 00040) test10();
160   if (mask & 00100) test11();
161   umask(022);
162 }				/* test */
163 
164 /* "t1.c" created by Rene Montsma and Menno Wilcke */
165 
166 /*****************************************************************************
167  *                              test UMASK                                   *
168  ****************************************************************************/
169 void test01()
170 {
171   int oldvalue, newvalue, tempvalue;
172   int nr;
173 
174   subtest = 1;
175   if ((oldvalue = umask(0777)) != 0) e(1);
176 
177   /* Special test: only the lower 9 bits (protection bits) may part- *
178    * icipate. ~0777 means: 111 000 000 000. Giving this to umask must*
179    * not change any value.                                           */
180 
181   if ((newvalue = umask(~0777)) != 0777) e(2);
182   if (oldvalue == newvalue) e(3);
183 
184   if ((tempvalue = umask(0)) != 0) e(4);
185 
186   /* Now test all possible modes of umask on a file */
187   for (newvalue = MASK; newvalue >= 0; newvalue -= 0111) {
188 	tempvalue = umask(newvalue);
189 	if (tempvalue != oldvalue) {
190 		e(5);
191 		break;		/* no use trying more */
192 	} else if ((nr = creat("file01", 0777)) < 0)
193 		e(6);
194 	else {
195 		try_close(nr, "'file01'");
196 		if (get_mode("file01") != (MASK & ~newvalue))
197 			e(7);
198 		try_unlink("file01");
199 	}
200 	oldvalue = newvalue;
201   }
202 
203   /* The loop has terminated with umask(0) */
204   if ((tempvalue = umask(0)) != 0)
205 	e(8);
206 }				/* test01 */
207 
208 /*****************************************************************************
209  *                              test CREAT                                   *
210  ****************************************************************************/
211 void test02()
212 {
213   int n, n1, mode;
214   char a[ARSIZE], b[ARSIZE];
215   struct stat stbf1;
216 
217   subtest = 2;
218   mode = 0;
219 
220   for (n = 0; n < MAXOPEN; n++) {
221 	if (creat(filenames[n], mode) != FF + n)
222 		e(1);
223 	else {
224 		if (get_mode(filenames[n]) != mode)
225 			e(2);
226 
227 		/* Change  mode of file to standard mode, we want to *
228 		 * use a lot (20) of files to be opened later, see   *
229 		 * open_alot(), close_alot().                        */
230 		if (chmod(filenames[n], 0700) != OK) e(3);
231 	}
232 	mode = (mode + 0100) % 01000;
233   }
234 
235   /* Already twenty files opened; opening another has to fail */
236   if (creat("file02", 0777) != FAIL)
237 	e(4);
238   else
239   	if (errno != EMFILE) e(5);
240 
241   /* Close all files: seems blunt, but it isn't because we've  *
242    * checked all fd's already                                  */
243   if ((n = close_alot(MAXOPEN)) < MAXOPEN) e(6);
244 
245   /* Creat 1 file twice; check */
246   if ((n = creat("file02", 0777)) < 0)
247 	e(7);
248   else {
249 	init_array(a);
250 	if (write(n, a, ARSIZE) != ARSIZE) e(8);
251 
252 	if ((n1 = creat("file02", 0755)) < 0)	/* receate 'file02' */
253 		e(9);
254 	else {
255 		/* Fd should be at the top after recreation */
256 		if (lseek(n1, 0L, SEEK_END) != 0)
257 			e(10);
258 		else {
259 			/* Try to write on recreated file */
260 			clear_array(b);
261 
262 			if (lseek(n1, 0L, SEEK_SET) != 0) e(11);
263 			if (write(n1, a, ARSIZE) != ARSIZE) e(12);
264 
265 			/* In order to read we've to close and open again */
266 			try_close(n1, "'file02'  (2nd creation)");
267 			if ((n1 = open("file02", RW)) < 0)
268 				e(13);
269 
270 			/* Continue */
271 			if (lseek(n1, 0L, SEEK_SET) != 0) e(14);
272 			if (read(n1, b, ARSIZE) != ARSIZE) e(15);
273 
274 			if (comp_array(a, b, ARSIZE) != OK) e(16);
275 		}
276 		if (get_mode("file02") != 0777) e(17);
277 		try_close(n1, "recreated 'file02'");
278 
279 	}
280 	Remove(n, "file02");
281   }
282 
283   /* Give 'creat' wrong input: dir not searchable */
284   if (creat("drw-/file02", 0777) != FAIL) e(18);
285   else
286   	if (errno != EACCES) e(19);
287 
288   /* Dir not writable */
289   if (creat("dr-x/file02", 0777) != FAIL) e(20);
290   else
291 	if (errno != EACCES) e(21);
292 
293   /* File not writable */
294   if (creat("drwx/r-x", 0777) != FAIL) e(22);
295   else
296   	if (errno != EACCES) e(23);
297 
298   /* Try to creat a dir */
299   if ((n = creat("dir", 040777)) != FAIL) {
300 	if (fstat(n, &stbf1) != OK) e(24);
301 	else if (stbf1.st_mode != (mode_t) 0100777)
302 				/* cast because mode is negative :-( */
303 		e(25);
304 	Remove(n, "dir");
305   }
306 
307   /* We don't consider it to be a bug when creat * does not accept
308    * tricky modes                */
309 
310   /* File is an existing dir */
311   if (creat("drwx", 0777) != FAIL) e(26);
312   else
313 	if (errno != EISDIR) e(27);
314 }				/* test02 */
315 
316 void test08()
317 {
318   subtest = 8;
319 
320   /* Test chdir to searchable dir */
321   if (chdir("drwx") != OK) e(1);
322   else if (chdir("..") != OK) e(2);
323 
324   /* Check the chdir(".") and chdir("..") mechanism */
325   if (chdir("drwx") != OK) e(3);
326   else {
327 	if (chdir(".") != OK) e(4);
328 
329 	/* If we still are in 'drwx' , we should be able to access *
330 	 * file 'rwx'.                                              */
331 	if (access("rwx", 0) != OK) e(5);
332 
333 	/* Try to return to previous dir ('/' !!) */
334 	if (chdir("././../././d--x/../d--x/././..") != OK) e(6);
335 
336 	/* Check whether we are back in '/' */
337 	if (chdir("d--x") != OK) e(7);
338   }  /* Return to '..' */
339   if (chdir("..") != OK) e(8);
340 
341   if (chdir("././././drwx") != OK) e(9);
342   else if (chdir("././././..") != OK) e(10);
343 
344   /* Try giving chdir wrong parameters */
345   if (chdir("drwx/rwx") != FAIL) e(11);
346   else
347 	if (errno != ENOTDIR) e(12);
348 
349   if (chdir("drw-") != FAIL) e(13);
350   else
351 	if (errno != EACCES) e(14);
352 
353 }				/* test08 */
354 
355 /*****************************************************************************
356  *                              test CHMOD                                   *
357  ****************************************************************************/
358 void test09()
359 {
360   int n;
361 
362   subtest = 9;
363 
364   /* Prepare file09 */
365   if ((n = creat("drwx/file09", 0644)) != FF) e(1);
366 
367   try_close(n, "'file09'");
368 
369   /* Try to chmod a file, check and restore old values, check */
370   if (chmod("drwx/file09", 0700) != OK) e(2);
371   else {
372 	/* Check protection */
373 	if (get_mode("drwx/file09") != 0700) e(3);
374 
375 	/* Test if chmod accepts just filenames too */
376 	if (chdir("drwx") != OK) e(4);
377 	else if (chmod("file09", 0177) != OK) e(5);
378 	else
379 		/* Check if value has been restored */
380 	if (get_mode("../drwx/file09") != 0177) e(6);
381   }
382 
383   /* Try setuid and setgid */
384   if ((chmod("file09", 04777) != OK) || (get_mode("file09") != 04777))
385 	e(7);
386   if ((chmod("file09", 02777) != OK) || (get_mode("file09") != 02777))
387 	e(8);
388 
389   /* Remove testfile */
390   try_unlink("file09");
391 
392   if (chdir("..") != OK) e(9);
393 
394   /* Try to chmod directory */
395   if (chmod("d---", 0777) != OK) e(10);
396   else {
397 	if (get_mode("d---") != 0777) e(11);
398 	if (chmod("d---", 0000) != OK) e(12);
399 
400 	/* Check if old value has been restored */
401 	if (get_mode("d---") != 0000) e(13);
402   }
403 
404   /* Try to make chmod failures */
405 
406   /* We still are in dir root */
407   /* Wrong filename */
408   if (chmod("non-file", 0777) != FAIL) e(14);
409   else
410 	if (errno != ENOENT) e(15);
411 
412 }				/* test 09 */
413 
414 
415 /* "t4.c", created by Rene Montsma and Menno Wilcke */
416 
417 /*****************************************************************************
418  *                              test LINK/UNLINK                             *
419  ****************************************************************************/
420 void test10()
421 {
422   int n, n1;
423   char a[ARSIZE], b[ARSIZE], *f, *lf;
424 
425   subtest = 10;
426 
427   f = "anotherfile10";
428   lf = "linkfile10";
429 
430   if ((n = creat(f, 0702)) != FF) e(1);	/* no other open files */
431   else {
432 	/* Now link correctly */
433 	if (link(f, lf) != OK) e(2);
434 	else if ((n1 = open(lf, RW)) < 0) e(3);
435 	else {
436 		init_array(a);
437 		clear_array(b);
438 
439 		/* Write on 'file10' means being able to    * read
440 		 * through linked filedescriptor       */
441 		if (write(n, a, ARSIZE) != ARSIZE) e(4);
442 		if (read(n1, b, ARSIZE) != ARSIZE) e(5);
443 		if (comp_array(a, b, ARSIZE) != OK) e(6);
444 
445 		/* Clean up: unlink and close (twice): */
446 		Remove(n, f);
447 		try_close(n1, "'linkfile10'");
448 
449 		/* Check if "linkfile" exists and the info    * on it
450 		 * is correct ('file' has been deleted) */
451 		if ((n1 = open(lf, R)) < 0) e(7);
452 		else {
453 			/* See if 'linkfile' still contains 0..511 ? */
454 
455 			clear_array(b);
456 			if (read(n1, b, ARSIZE) != ARSIZE) e(8);
457 			if (comp_array(a, b, ARSIZE) != OK) e(9);
458 
459 			try_close(n1, "'linkfile10' 2nd time");
460 			try_unlink(lf);
461 		}
462 	}
463   }
464 
465   /* Try if unlink fails with incorrect parameters */
466   /* File does not exist: */
467   if (unlink("non-file") != FAIL) e(10);
468   else
469   	if (errno != ENOENT) e(11);
470 
471   /* Dir can't be written */
472   if (unlink("dr-x/rwx") != FAIL) e(12);
473   else
474   	if (errno != EACCES) e(13);
475 
476   /* Try to unlink a dir being user */
477   if (unlink("drwx") != FAIL) e(14);
478   else
479 	if (errno != EPERM) e(15);
480 
481   /* Try giving link wrong input */
482 
483   /* First try if link fails with incorrect parameters * name1 does not
484    * exist.                             */
485   if (link("non-file", "linkfile") != FAIL) e(16);
486   else
487 	if (errno != ENOENT) e(17);
488 
489   /* Name2 exists already */
490   if (link("drwx/rwx", "drwx/rw-") != FAIL) e(18);
491   else
492 	if (errno != EEXIST) e(19);
493 
494   /* Directory of name2 not writable:  */
495   if (link("drwx/rwx", "dr-x/linkfile") != FAIL) e(20);
496   else
497 	if (errno != EACCES) e(21);
498 
499   /* Try to link a dir, being a user */
500   if (link("drwx", "linkfile") != FAIL) e(22);
501   else
502 	if (errno != EPERM) e(23);
503 
504   /* File has too many links */
505   if ((n = link_alot("drwx/rwx")) != LINKCOUNT - 1)	/* file already has one
506 							 * link */
507 	e(24);
508   if (unlink_alot(n) != n) e(25);
509 
510 }				/* test10 */
511 
512 int link_alot(bigboss)
513 char *bigboss;
514 {
515   int i;
516   static char employee[6] = "aaaaa";
517 
518   /* Every file has already got 1 link, so link 0176 times */
519   for (i = 1; i < LINKCOUNT; i++) {
520 	if (link(bigboss, employee) != OK)
521 		break;
522 	else
523 		get_new(employee);
524   }
525 
526   return(i - 1);		/* number of linked files */
527 }				/* link_alot */
528 
529 int unlink_alot(number)
530 int number;			/* number of files to be unlinked */
531 {
532   int j;
533   static char employee[6] = "aaaaa";
534 
535   for (j = 0; j < number; j++) {
536 	if (unlink(employee) != OK)
537 		break;
538 	else
539 		get_new(employee);
540   }
541 
542   return(j);			/* return number of unlinked files */
543 }				/* unlink_alot */
544 
545 void get_new(name)
546 char name[];
547  /* Every call changes string 'name' to a string alphabetically          *
548   * higher. Start with "aaaaa", next value: "aaaab" .                    *
549   * N.B. after "aaaaz" comes "aaabz" and not "aaaba" (not needed).       *
550   * The last possibility will be "zzzzz".                                *
551   * Total # possibilities: 26+25*4 = 126 = MAXLINK -1 (exactly needed)   */
552 {
553   int i;
554 
555   for (i = 4; i >= 0; i--)
556 	if (name[i] != 'z') {
557 		name[i]++;
558 		break;
559 	}
560 }				/* get_new */
561 
562 
563 /*****************************************************************************
564  *                              test PIPE                                    *
565  ****************************************************************************/
566 void test11()
567 {
568   int n, fd[2];
569   char a[ARSIZE], b[ARSIZE];
570 
571   subtest = 11;
572 
573   if (pipe(fd) != OK) e(1);
574   else {
575 	/* Try reading and writing on a pipe */
576 	init_array(a);
577 	clear_array(b);
578 
579 	if (write(fd[1], a, ARSIZE) != ARSIZE) e(2);
580 	else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2)) e(3);
581 	else if (comp_array(a, b, (ARSIZE / 2)) != OK) e(4);
582 	else if (read(fd[0], b, (ARSIZE / 2)) != (ARSIZE / 2)) e(5);
583 	else if (comp_array(&a[ARSIZE / 2], b, (ARSIZE / 2)) != OK) e(6);
584 
585 	/* Try to let the pipe make a mistake */
586 	if (write(fd[0], a, ARSIZE) != FAIL) e(7);
587 	if (read(fd[1], b, ARSIZE) != FAIL) e(8);
588 
589 	try_close(fd[1], "'fd[1]'");
590 
591 	/* Now we shouldn't be able to read, because fd[1] has been closed */
592 	if (read(fd[0], b, ARSIZE) != END_FILE) e(9);
593 
594 	try_close(fd[0], "'fd[0]'");
595   }
596   if (pipe(fd) < 0) e(10);
597   else {
598 	/* Test lseek on a pipe: should fail */
599 	if (write(fd[1], a, ARSIZE) != ARSIZE) e(11);
600 	if (lseek(fd[1], 10L, SEEK_SET) != FAIL) e(12);
601 	else
602 		if (errno != ESPIPE) e(13);
603 
604 	/* Eat half of the pipe: no writing should be possible */
605 	try_close(fd[0], "'fd[0]'  (2nd time)");
606 
607 	/* This makes UNIX crash: omit it if pdp or VAX */
608 #ifndef NOCRASH
609 	if (write(fd[1], a, ARSIZE) != FAIL) e(14);
610 	else
611 		if (errno != EPIPE) e(15);
612 #endif
613 	try_close(fd[1], "'fd[1]'  (2nd time)");
614   }
615 
616   /* BUG :                                                            *
617    * Here we planned to test if we could write 4K bytes on a pipe.    *
618    * However, this was not possible to implement, because the whole   *
619    * Monix system crashed when we tried to write more then 3584 bytes *
620    * (3.5K) on a pipe. That's why we try to write only 3.5K in the    *
621    * folowing test.                                                   */
622   if (pipe(fd) < 0) e(16);
623   else {
624 	for (n = 0; n < (PIPESIZE / ARSIZE); n++)
625 		if (write(fd[1], a, ARSIZE) != ARSIZE) e(17);
626 	try_close(fd[1], "'fd[1]' (3rd time)");
627 
628 	for (n = 0; n < (PIPESIZE / ARSIZE); n++)
629 		if (read(fd[0], b, ARSIZE) != ARSIZE) e(18);
630 	try_close(fd[0], "'fd[0]' (3rd time)");
631   }
632 
633   /* Test opening a lot of files */
634   if ((n = open_alot()) != MAXOPEN) e(19);
635   if (pipe(fd) != FAIL) e(20);
636   else
637 	if (errno != EMFILE) e(21);
638   if (close_alot(n) != n) e(22);
639 }				/* test11 */
640 
641 
642 /* Err, test03, init_array, clear_array, comp_array,
643    try_close, try_unlink, Remove, get_mode, check, open_alot,
644    close_alot, clean_up_the_mess.
645 */
646 
647 
648 /*****************************************************************************
649 *                                                                            *
650 *                          MAKE_AND_FILL_DIRS                                *
651 *                                                                            *
652 *****************************************************************************/
653 
654 void test03()
655  /* Create 8 dir.'s: "d---", "d--x", "d-w-", "d-wx", "dr--", "dr-x",     *
656   * "drw-", "drwx".                                     * Then create 8 files
657   * in "drwx", and some needed files in other dirs.  */
658 {
659   int mode, i;
660   subtest = 3;
661   for (i = 0; i < MODES; i++) {
662 	mkdir(mode_dir[i], 0700);
663 	chown(mode_dir[i], USER_ID, GROUP_ID);
664   }
665   setuid(USER_ID);
666   setgid(GROUP_ID);
667 
668   for (mode = 0; mode < 8; mode++) put_file_in_dir("drwx", mode);
669 
670   put_file_in_dir("d-wx", RWX);
671   put_file_in_dir("dr-x", RWX);
672   put_file_in_dir("drw-", RWX);
673 
674   chmod_8_dirs(8);		/* 8 means; 8 different modes */
675 
676 }				/* test03 */
677 
678 void put_file_in_dir(dirname, mode)
679 char *dirname;
680 int mode;
681  /* Fill directory 'dirname' with file with mode 'mode'.   */
682 {
683   int nr;
684 
685   if (chdir(dirname) != OK) e(1);
686   else {
687 	/* Creat the file */
688 	assert(mode >= 0 && mode < MODES);
689 	if ((nr = creat(mode_fnames[mode], mode * 0100)) < 0) e(2);
690 	else {
691 		try_close(nr, mode_fnames[mode]);
692 	}
693 
694 	if (chdir("..") != OK) e(3);
695   }
696 }				/* put_file_in_dir */
697 
698 /*****************************************************************************
699 *                                                                            *
700 *                               MISCELLANEOUS                                *
701 *                                                                            *
702 *(all about arrays, 'try_close', 'try_unlink', 'Remove', 'get_mode')*
703 *                                                                            *
704 *****************************************************************************/
705 
706 void init_array(a)
707 char *a;
708 {
709   int i;
710 
711   i = 0;
712   while (i++ < ARSIZE) *a++ = 'a' + (i % 26);
713 }				/* init_array */
714 
715 void clear_array(b)
716 char *b;
717 {
718   int i;
719 
720   i = 0;
721   while (i++ < ARSIZE) *b++ = '0';
722 
723 }				/* clear_array */
724 
725 int comp_array(a, b, range)
726 char *a, *b;
727 int range;
728 {
729   assert(range >= 0 && range <= ARSIZE);
730   while (range-- && (*a++ == *b++));
731   if (*--a == *--b)
732 	return(OK);
733   else
734 	return(FAIL);
735 }				/* comp_array */
736 
737 void try_close(filedes, name)
738 int filedes;
739 char *name;
740 {
741   if (close(filedes) != OK) e(90);
742 }				/* try_close */
743 
744 void try_unlink(fname)
745 char *fname;
746 {
747   if (unlink(fname) != 0) e(91);
748 }				/* try_unlink */
749 
750 void Remove(fdes, fname)
751 int fdes;
752 char *fname;
753 {
754   try_close(fdes, fname);
755   try_unlink(fname);
756 }				/* Remove */
757 
758 int get_mode(name)
759 char *name;
760 {
761   struct stat stbf1;
762 
763   if (stat(name, &stbf1) != OK) {
764 	e(92);
765 	return(stbf1.st_mode);	/* return a mode which will cause *
766 				 * error in the calling function  *
767 				 * (file/dir bit)                 */
768   } else
769 	return(stbf1.st_mode & 07777);	/* take last 4 bits */
770 }				/* get_mode */
771 
772 
773 /*****************************************************************************
774 *                                                                            *
775 *                                ALOT-functions                              *
776 *                                                                            *
777 *****************************************************************************/
778 
779 int open_alot()
780 {
781   int i;
782 
783   for (i = 0; i < MAXOPEN; i++)
784 	if (open(filenames[i], R) == FAIL) break;
785   if (i == 0) e(93);
786   return(i);
787 }				/* open_alot */
788 
789 int close_alot(number)
790 int number;
791 {
792   int i, count = 0;
793 
794   if (number > MAXOPEN)
795 	e(94);
796   else
797 	for (i = FF; i < number + FF; i++)
798 		if (close(i) != OK) count++;
799 
800   return(number - count);	/* return number of closed files */
801 }				/* close_alot */
802 
803 /*****************************************************************************
804 *                                                                            *
805 *                         CLEAN UP THE MESS                                  *
806 *                                                                            *
807 *****************************************************************************/
808 
809 void clean_up_the_mess()
810 {
811   int i;
812   char dirname[6];
813 
814   /* First remove 'a lot' files */
815   for (i = 0; i < MAXOPEN; i++) {
816 	try_unlink(filenames[i]);
817 }
818 
819   /* Unlink the files in dir 'drwx' */
820   if (chdir("drwx") != OK)
821 	e(95);
822   else {
823 	for (i = 0; i < MODES; i++) {
824 		try_unlink(mode_fnames[i]);
825 	}
826 	if (chdir("..") != OK) e(96);
827   }
828 
829   /* Before unlinking files in some dirs, make them writable */
830   chmod_8_dirs(RWX);
831 
832   /* Unlink files in other dirs */
833   try_unlink("d-wx/rwx");
834   try_unlink("dr-x/rwx");
835   try_unlink("drw-/rwx");
836 
837   /* Unlink dirs */
838   for (i = 0; i < MODES; i++) {
839 	strcpy(dirname, "d");
840 	strcat(dirname, mode_fnames[i]);
841 
842 	/* 'dirname' contains the directoryname */
843 	rmdir(dirname);
844   }
845 
846   /* FINISH */
847 }				/* clean_up_the_mess */
848 
849 void chmod_8_dirs(sw)
850 int sw;				/* if switch == 8, give all different
851 			 * mode,else the same mode */
852 {
853   int mode;
854   int i;
855 
856   if (sw == 8)
857 	mode = 0;
858   else
859 	mode = sw;
860 
861   for (i = 0; i < MODES; i++) {
862 	chmod(mode_dir[i], 040000 + mode * 0100);
863 	if (sw == 8) mode++;
864   }
865 }
866 
867