xref: /original-bsd/sbin/newfs/newfs.c (revision eafa6506)
1 /*
2  * Copyright (c) 1983, 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)newfs.c	6.22.1.1 (Berkeley) 12/18/90";
10 #endif /* not lint */
11 
12 #ifndef lint
13 char copyright[] =
14 "@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\
15  All rights reserved.\n";
16 #endif /* not lint */
17 
18 /*
19  * newfs: friendly front end to mkfs
20  */
21 #include <sys/param.h>
22 #include <sys/stat.h>
23 #include <ufs/fs.h>
24 #include <ufs/dir.h>
25 #include <sys/ioctl.h>
26 #include <sys/disklabel.h>
27 #include <sys/file.h>
28 #include <sys/mount.h>
29 
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <paths.h>
33 
34 #define COMPAT			/* allow non-labeled disks */
35 
36 /*
37  * The following two constants set the default block and fragment sizes.
38  * Both constants must be a power of 2 and meet the following constraints:
39  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
40  *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
41  *	DESBLKSIZE / DESFRAGSIZE <= 8
42  */
43 #define	DFL_FRAGSIZE	1024
44 #define	DFL_BLKSIZE	8192
45 
46 /*
47  * Cylinder groups may have up to many cylinders. The actual
48  * number used depends upon how much information can be stored
49  * on a single cylinder. The default is to use 16 cylinders
50  * per group.
51  */
52 #define	DESCPG		16	/* desired fs_cpg */
53 
54 /*
55  * MINFREE gives the minimum acceptable percentage of file system
56  * blocks which may be free. If the freelist drops below this level
57  * only the superuser may continue to allocate blocks. This may
58  * be set to 0 if no reserve of free blocks is deemed necessary,
59  * however throughput drops by fifty percent if the file system
60  * is run at between 90% and 100% full; thus the default value of
61  * fs_minfree is 10%. With 10% free space, fragmentation is not a
62  * problem, so we choose to optimize for time.
63  */
64 #define MINFREE		10
65 #define DEFAULTOPT	FS_OPTTIME
66 
67 /*
68  * ROTDELAY gives the minimum number of milliseconds to initiate
69  * another disk transfer on the same cylinder. It is used in
70  * determining the rotationally optimal layout for disk blocks
71  * within a file; the default of fs_rotdelay is 4ms.
72  */
73 #define ROTDELAY	4
74 
75 /*
76  * MAXCONTIG sets the default for the maximum number of blocks
77  * that may be allocated sequentially. Since UNIX drivers are
78  * not capable of scheduling multi-block transfers, this defaults
79  * to 1 (ie no contiguous blocks are allocated).
80  */
81 #define MAXCONTIG	1
82 
83 /*
84  * MAXBLKPG determines the maximum number of data blocks which are
85  * placed in a single cylinder group. The default is one indirect
86  * block worth of data blocks.
87  */
88 #define MAXBLKPG(bsize)	((bsize) / sizeof(daddr_t))
89 
90 /*
91  * Each file system has a number of inodes statically allocated.
92  * We allocate one inode slot per NFPI fragments, expecting this
93  * to be far more than we will ever need.
94  */
95 #define	NFPI		4
96 
97 /*
98  * For each cylinder we keep track of the availability of blocks at different
99  * rotational positions, so that we can lay out the data to be picked
100  * up with minimum rotational latency.  NRPOS is the default number of
101  * rotational positions that we distinguish.  With NRPOS of 8 the resolution
102  * of our summary information is 2ms for a typical 3600 rpm drive.
103  */
104 #define	NRPOS		8	/* number distinct rotational positions */
105 
106 
107 int	mfs;			/* run as the memory based filesystem */
108 int	Nflag;			/* run without writing file system */
109 int	fssize;			/* file system size */
110 int	ntracks;		/* # tracks/cylinder */
111 int	nsectors;		/* # sectors/track */
112 int	nphyssectors;		/* # sectors/track including spares */
113 int	secpercyl;		/* sectors per cylinder */
114 int	trackspares = -1;	/* spare sectors per track */
115 int	cylspares = -1;		/* spare sectors per cylinder */
116 int	sectorsize;		/* bytes/sector */
117 #ifdef tahoe
118 int	realsectorsize;		/* bytes/sector in hardware */
119 #endif
120 int	rpm;			/* revolutions/minute of drive */
121 int	interleave;		/* hardware sector interleave */
122 int	trackskew = -1;		/* sector 0 skew, per track */
123 int	headswitch;		/* head switch time, usec */
124 int	trackseek;		/* track-to-track seek, usec */
125 int	fsize = 0;		/* fragment size */
126 int	bsize = 0;		/* block size */
127 int	cpg = DESCPG;		/* cylinders/cylinder group */
128 int	cpgflg;			/* cylinders/cylinder group flag was given */
129 int	minfree = MINFREE;	/* free space threshold */
130 int	opt = DEFAULTOPT;	/* optimization preference (space or time) */
131 int	density;		/* number of bytes per inode */
132 int	maxcontig = MAXCONTIG;	/* max contiguous blocks to allocate */
133 int	rotdelay = ROTDELAY;	/* rotational delay between blocks */
134 int	maxbpg;			/* maximum blocks per file in a cyl group */
135 int	nrpos = NRPOS;		/* # of distinguished rotational positions */
136 int	bbsize = BBSIZE;	/* boot block size */
137 int	sbsize = SBSIZE;	/* superblock size */
138 int	mntflags;		/* flags to be passed to mount */
139 u_long	memleft;		/* virtual memory available */
140 caddr_t	membase;		/* start address of memory based filesystem */
141 #ifdef COMPAT
142 char	*disktype;
143 int	unlabelled;
144 #endif
145 
146 char	device[MAXPATHLEN];
147 char	*progname;
148 
149 extern	int errno;
150 char	*index();
151 char	*rindex();
152 
153 main(argc, argv)
154 	int argc;
155 	char *argv[];
156 {
157 	char *cp, *special, *rindex();
158 	register struct partition *pp;
159 	register struct disklabel *lp;
160 	struct disklabel *getdisklabel();
161 	struct partition oldpartition;
162 	struct mfs_args args;
163 	struct stat st;
164 	int fsi, fso;
165 	register int i;
166 	int status;
167 	char buf[BUFSIZ];
168 
169 	if ((progname = rindex(*argv, '/') + 1) == (char *)1)
170 		progname = *argv;
171 	if (!strcmp(progname, "mfs")) {
172 		Nflag++;
173 		mfs++;
174 	}
175 	argc--, argv++;
176 	while (argc > 0 && argv[0][0] == '-') {
177 		for (cp = &argv[0][1]; *cp; cp++)
178 			switch (*cp) {
179 
180 			case 'F':
181 				if (!mfs)
182 					fatal("-F: unknown flag");
183 				if (argc < 1)
184 					fatal("-F: mount flags");
185 				argc--, argv++;
186 				mntflags = atoi(*argv);
187 				if (mntflags == 0)
188 					fatal("%s: bad mount flags", *argv);
189 				goto next;
190 
191 			case 'N':
192 				Nflag++;
193 				break;
194 
195 			case 'S':
196 				if (argc < 1)
197 					fatal("-S: missing sector size");
198 				argc--, argv++;
199 				sectorsize = atoi(*argv);
200 				if (sectorsize <= 0)
201 					fatal("%s: bad sector size", *argv);
202 				goto next;
203 
204 #ifdef COMPAT
205 			case 'T':
206 				if (argc < 1)
207 					fatal("-T: missing disk type");
208 				argc--, argv++;
209 				disktype = *argv;
210 				goto next;
211 #endif
212 
213 			case 'a':
214 				if (argc < 1)
215 					fatal("-a: missing max contiguous blocks\n");
216 				argc--, argv++;
217 				maxcontig = atoi(*argv);
218 				if (maxcontig <= 0)
219 					fatal("%s: bad max contiguous blocks\n",
220 						*argv);
221 				goto next;
222 
223 			case 'b':
224 				if (argc < 1)
225 					fatal("-b: missing block size");
226 				argc--, argv++;
227 				bsize = atoi(*argv);
228 				if (bsize < MINBSIZE)
229 					fatal("%s: bad block size", *argv);
230 				goto next;
231 
232 			case 'c':
233 				if (argc < 1)
234 					fatal("-c: missing cylinders/group");
235 				argc--, argv++;
236 				cpg = atoi(*argv);
237 				if (cpg <= 0)
238 					fatal("%s: bad cylinders/group", *argv);
239 				cpgflg++;
240 				goto next;
241 
242 			case 'd':
243 				if (argc < 1)
244 					fatal("-d: missing rotational delay\n");
245 				argc--, argv++;
246 				rotdelay = atoi(*argv);
247 				if (rotdelay < 0)
248 					fatal("%s: bad rotational delay\n",
249 						*argv);
250 				goto next;
251 
252 			case 'e':
253 				if (argc < 1)
254 					fatal("-e: missing blocks pre file in a cyl group\n");
255 				argc--, argv++;
256 				maxbpg = atoi(*argv);
257 				if (maxbpg <= 0)
258 					fatal("%s: bad blocks per file in a cyl group\n",
259 						*argv);
260 				goto next;
261 
262 			case 'f':
263 				if (argc < 1)
264 					fatal("-f: missing frag size");
265 				argc--, argv++;
266 				fsize = atoi(*argv);
267 				if (fsize <= 0)
268 					fatal("%s: bad frag size", *argv);
269 				goto next;
270 
271 			case 'i':
272 				if (argc < 1)
273 					fatal("-i: missing bytes per inode\n");
274 				argc--, argv++;
275 				density = atoi(*argv);
276 				if (density <= 0)
277 					fatal("%s: bad bytes per inode\n",
278 						*argv);
279 				goto next;
280 
281 			case 'k':
282 				if (argc < 1)
283 					fatal("-k: track skew");
284 				argc--, argv++;
285 				trackskew = atoi(*argv);
286 				if (trackskew < 0)
287 					fatal("%s: bad track skew", *argv);
288 				goto next;
289 
290 			case 'l':
291 				if (argc < 1)
292 					fatal("-l: interleave");
293 				argc--, argv++;
294 				interleave = atoi(*argv);
295 				if (interleave <= 0)
296 					fatal("%s: bad interleave", *argv);
297 				goto next;
298 
299 			case 'm':
300 				if (argc < 1)
301 					fatal("-m: missing free space %%\n");
302 				argc--, argv++;
303 				minfree = atoi(*argv);
304 				if (minfree < 0 || minfree > 99)
305 					fatal("%s: bad free space %%\n",
306 						*argv);
307 				goto next;
308 
309 			case 'n':
310 				if (argc < 1)
311 					fatal("-n: missing rotational layout count\n");
312 				argc--, argv++;
313 				nrpos = atoi(*argv);
314 				if (nrpos <= 0)
315 					fatal("%s: bad rotational layout count\n",
316 						*argv);
317 				goto next;
318 
319 			case 'o':
320 				if (argc < 1)
321 					fatal("-o: missing optimization preference");
322 				argc--, argv++;
323 				if (strcmp(*argv, "space") == 0)
324 					opt = FS_OPTSPACE;
325 				else if (strcmp(*argv, "time") == 0)
326 					opt = FS_OPTTIME;
327 				else
328 					fatal("%s: bad optimization preference %s",
329 					    *argv,
330 					    "(options are `space' or `time')");
331 				goto next;
332 
333 			case 'p':
334 				if (argc < 1)
335 					fatal("-p: spare sectors per track");
336 				argc--, argv++;
337 				trackspares = atoi(*argv);
338 				if (trackspares < 0)
339 					fatal("%s: bad spare sectors per track", *argv);
340 				goto next;
341 
342 			case 'r':
343 				if (argc < 1)
344 					fatal("-r: missing revs/minute\n");
345 				argc--, argv++;
346 				rpm = atoi(*argv);
347 				if (rpm <= 0)
348 					fatal("%s: bad revs/minute\n", *argv);
349 				goto next;
350 
351 			case 's':
352 				if (argc < 1)
353 					fatal("-s: missing file system size");
354 				argc--, argv++;
355 				fssize = atoi(*argv);
356 				if (fssize <= 0)
357 					fatal("%s: bad file system size",
358 						*argv);
359 				goto next;
360 
361 			case 't':
362 				if (argc < 1)
363 					fatal("-t: missing track total");
364 				argc--, argv++;
365 				ntracks = atoi(*argv);
366 				if (ntracks <= 0)
367 					fatal("%s: bad total tracks", *argv);
368 				goto next;
369 
370 			case 'u':
371 				if (argc < 1)
372 					fatal("-u: missing sectors/track");
373 				argc--, argv++;
374 				nsectors = atoi(*argv);
375 				if (nsectors <= 0)
376 					fatal("%s: bad sectors/track", *argv);
377 				goto next;
378 
379 			case 'x':
380 				if (argc < 1)
381 					fatal("-x: spare sectors per cylinder");
382 				argc--, argv++;
383 				cylspares = atoi(*argv);
384 				if (cylspares < 0)
385 					fatal("%s: bad spare sectors per cylinder", *argv);
386 				goto next;
387 
388 			default:
389 				fatal("-%c: unknown flag", *cp);
390 			}
391 next:
392 		argc--, argv++;
393 	}
394 	if (argc < 1) {
395 		if (mfs)
396 			fprintf(stderr,
397 			    "usage: mfs [ fsoptions ] special-device %s\n",
398 			    "mount-point");
399 		else
400 #ifdef COMPAT
401 			fprintf(stderr, "usage: %s\n",
402 			    "newfs [ fsoptions ] special-device [device-type]");
403 #else
404 			fprintf(stderr,
405 			    "usage: newfs [ fsoptions ] special-device\n");
406 #endif
407 		fprintf(stderr, "where fsoptions are:\n");
408 		fprintf(stderr, "\t-N do not create file system, %s\n",
409 			"just print out parameters");
410 #ifdef COMPAT
411 		fprintf(stderr, "\t-T disktype\n");
412 #endif
413 		fprintf(stderr, "\t-b block size\n");
414 		fprintf(stderr, "\t-f frag size\n");
415 		fprintf(stderr, "\t-m minimum free space %%\n");
416 		fprintf(stderr, "\t-o optimization preference %s\n",
417 			"(`space' or `time')");
418 		fprintf(stderr, "\t-a maximum contiguous blocks\n");
419 		fprintf(stderr, "\t-d rotational delay between %s\n",
420 			"contiguous blocks");
421 		fprintf(stderr, "\t-e maximum blocks per file in a %s\n",
422 			"cylinder group");
423 		fprintf(stderr, "\t-i number of bytes per inode\n");
424 		fprintf(stderr, "\t-c cylinders/group\n");
425 		fprintf(stderr, "\t-n number of distinguished %s\n",
426 			"rotational positions");
427 		fprintf(stderr, "\t-s file system size (sectors)\n");
428 		fprintf(stderr, "\t-r revolutions/minute\n");
429 		fprintf(stderr, "\t-S sector size\n");
430 		fprintf(stderr, "\t-u sectors/track\n");
431 		fprintf(stderr, "\t-t tracks/cylinder\n");
432 		fprintf(stderr, "\t-p spare sectors per track\n");
433 		fprintf(stderr, "\t-x spare sectors per cylinder\n");
434 		fprintf(stderr, "\t-l hardware sector interleave\n");
435 		fprintf(stderr, "\t-k sector 0 skew, per track\n");
436 		exit(1);
437 	}
438 	special = argv[0];
439 	cp = rindex(special, '/');
440 	if (cp != 0)
441 		special = cp + 1;
442 	if (*special == 'r'
443 #if defined(vax) || defined(tahoe)
444 	    && special[1] != 'a' && special[1] != 'b'
445 #endif
446 #if defined(hp300)
447 	    && special[1] != 'd'
448 #endif
449 	   )
450 		special++;
451 	(void)sprintf(device, "%s/r%s", _PATH_DEV, special);
452 	special = device;
453 	if (!Nflag) {
454 		fso = open(special, O_WRONLY);
455 		if (fso < 0) {
456 			perror(special);
457 			exit(2);
458 		}
459 	} else
460 		fso = -1;
461 	fsi = open(special, O_RDONLY);
462 	if (fsi < 0) {
463 		perror(special);
464 		exit(3);
465 	}
466 	if (fstat(fsi, &st) < 0) {
467 		fprintf(stderr, "%s: ", progname); perror(special);
468 		exit(4);
469 	}
470 	if ((st.st_mode & S_IFMT) != S_IFCHR)
471 		fatal("%s: not a character device", special);
472 	cp = index(argv[0], '\0') - 1;
473 	if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
474 		fatal("%s: can't figure out file system partition", argv[0]);
475 #ifdef COMPAT
476 	if (!mfs && disktype == NULL)
477 		disktype = argv[1];
478 #endif
479 	lp = getdisklabel(special, fsi);
480 	if (isdigit(*cp))
481 		pp = &lp->d_partitions[0];
482 	else
483 		pp = &lp->d_partitions[*cp - 'a'];
484 	if (pp->p_size == 0)
485 		fatal("%s: `%c' partition is unavailable", argv[0], *cp);
486 	if (fssize == 0)
487 		fssize = pp->p_size;
488 	if (fssize > pp->p_size && !mfs)
489 	       fatal("%s: maximum file system size on the `%c' partition is %d",
490 			argv[0], *cp, pp->p_size);
491 	if (rpm == 0) {
492 		rpm = lp->d_rpm;
493 		if (rpm <= 0)
494 			rpm = 3600;
495 	}
496 	if (ntracks == 0) {
497 		ntracks = lp->d_ntracks;
498 		if (ntracks <= 0)
499 			fatal("%s: no default #tracks", argv[0]);
500 	}
501 	if (nsectors == 0) {
502 		nsectors = lp->d_nsectors;
503 		if (nsectors <= 0)
504 			fatal("%s: no default #sectors/track", argv[0]);
505 	}
506 	if (sectorsize == 0) {
507 		sectorsize = lp->d_secsize;
508 		if (sectorsize <= 0)
509 			fatal("%s: no default sector size", argv[0]);
510 	}
511 	if (trackskew == -1) {
512 		trackskew = lp->d_trackskew;
513 		if (trackskew < 0)
514 			trackskew = 0;
515 	}
516 	if (interleave == 0) {
517 		interleave = lp->d_interleave;
518 		if (interleave <= 0)
519 			interleave = 1;
520 	}
521 	if (fsize == 0) {
522 		fsize = pp->p_fsize;
523 		if (fsize <= 0)
524 			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
525 	}
526 	if (bsize == 0) {
527 		bsize = pp->p_frag * pp->p_fsize;
528 		if (bsize <= 0)
529 			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
530 	}
531 	if (density == 0)
532 		density = NFPI * fsize;
533 	if (minfree < 10 && opt != FS_OPTSPACE) {
534 		fprintf(stderr, "Warning: changing optimization to space ");
535 		fprintf(stderr, "because minfree is less than 10%%\n");
536 		opt = FS_OPTSPACE;
537 	}
538 	if (trackspares == -1) {
539 		trackspares = lp->d_sparespertrack;
540 		if (trackspares < 0)
541 			trackspares = 0;
542 	}
543 	nphyssectors = nsectors + trackspares;
544 	if (cylspares == -1) {
545 		cylspares = lp->d_sparespercyl;
546 		if (cylspares < 0)
547 			cylspares = 0;
548 	}
549 	secpercyl = nsectors * ntracks - cylspares;
550 	if (secpercyl != lp->d_secpercyl)
551 		fprintf(stderr, "%s (%d) %s (%d)\n",
552 			"Warning: calculated sectors per cylinder", secpercyl,
553 			"disagrees with disk label", lp->d_secpercyl);
554 	if (maxbpg == 0)
555 		maxbpg = MAXBLKPG(bsize);
556 	headswitch = lp->d_headswitch;
557 	trackseek = lp->d_trkseek;
558 	/* Reno fix: label may be 0 if faked up by kernel */
559 #ifdef notdef
560 	bbsize = lp->d_bbsize;
561 	sbsize = lp->d_sbsize;
562 #endif
563 	oldpartition = *pp;
564 #ifdef tahoe
565 	realsectorsize = sectorsize;
566 	if (sectorsize != DEV_BSIZE) {		/* XXX */
567 		int secperblk = DEV_BSIZE / sectorsize;
568 
569 		sectorsize = DEV_BSIZE;
570 		nsectors /= secperblk;
571 		nphyssectors /= secperblk;
572 		secpercyl /= secperblk;
573 		fssize /= secperblk;
574 		pp->p_size /= secperblk;
575 	}
576 #endif
577 	mkfs(pp, special, fsi, fso);
578 #ifdef tahoe
579 	if (realsectorsize != DEV_BSIZE)
580 		pp->p_size *= DEV_BSIZE / realsectorsize;
581 #endif
582 	if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
583 		rewritelabel(special, fso, lp);
584 	if (!Nflag)
585 		close(fso);
586 	close(fsi);
587 	if (mfs) {
588 		sprintf(buf, "mfs:%d", getpid());
589 		args.name = buf;
590 		args.base = membase;
591 		args.size = fssize * sectorsize;
592 		if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0) {
593 			perror("mfs: mount");
594 			exit(5);
595 		}
596 	}
597 	exit(0);
598 }
599 
600 #ifdef COMPAT
601 char lmsg[] = "%s: can't read disk label; disk type must be specified";
602 #else
603 char lmsg[] = "%s: can't read disk label";
604 #endif
605 
606 struct disklabel *
607 getdisklabel(s, fd)
608 	char *s;
609 	int fd;
610 {
611 	static struct disklabel lab;
612 
613 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
614 #ifdef COMPAT
615 		if (disktype) {
616 			struct disklabel *getdiskbyname();
617 
618 			unlabelled++;
619 			return (getdiskbyname(disktype));
620 		}
621 #endif
622 		perror("ioctl (GDINFO)");
623 		fatal(lmsg, s);
624 	}
625 	return (&lab);
626 }
627 
628 rewritelabel(s, fd, lp)
629 	char *s;
630 	int fd;
631 	register struct disklabel *lp;
632 {
633 
634 #ifdef COMPAT
635 	if (unlabelled)
636 		return;
637 #endif
638 	lp->d_checksum = 0;
639 	lp->d_checksum = dkcksum(lp);
640 	if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
641 		perror("ioctl (WDINFO)");
642 		fatal("%s: can't rewrite disk label", s);
643 	}
644 #if vax
645 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
646 		register i;
647 		int cfd;
648 		daddr_t alt;
649 		char specname[64];
650 		char blk[1024];
651 		char *cp;
652 
653 		/*
654 		 * Make name for 'c' partition.
655 		 */
656 		strcpy(specname, s);
657 		cp = specname + strlen(specname) - 1;
658 		if (!isdigit(*cp))
659 			*cp = 'c';
660 		cfd = open(specname, O_WRONLY);
661 		if (cfd < 0) {
662 			perror(specname);
663 			exit(6);
664 		}
665 		bzero(blk, sizeof(blk));
666 		*(struct disklabel *)(blk + LABELOFFSET) = *lp;
667 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
668 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
669 			if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) {
670 				perror("lseek to badsector area");
671 				exit(7);
672 			}
673 			if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) {
674 				int oerrno = errno;
675 				fprintf(stderr, "alternate label %d ", i/2);
676 				errno = oerrno;
677 				perror("write");
678 			}
679 		}
680 		close(cfd);
681 	}
682 #endif
683 }
684 
685 /*VARARGS*/
686 fatal(fmt, arg1, arg2)
687 	char *fmt;
688 {
689 
690 	fprintf(stderr, "%s: ", progname);
691 	fprintf(stderr, fmt, arg1, arg2);
692 	putc('\n', stderr);
693 	exit(8);
694 }
695