|
|
1.1 root 1: /*
2: * build.c
3: * 07/01/93 COH 386 release
4: *
5: * Build (install) COHERENT on a system, part 1.
6: * The second part of the install procedure is in install.c.
7: * Uses common routines in build0.c,
8: * serial number checking in numtab.c and serialno.c.
9: * Requires floating point output: cc build.c build0.c numtab.c serialno.c -f
10: * Usage: build [ -dv ]
11: * Options:
12: * -d Debug, echo commands without executing
13: * -u Update, rather than full installation
14: * -v Verbose
15: *
16: * In addition to the files necessary to run the single user system
17: * (/coherent, /etc/init, /bin/sh, /dev/console, /dev/null, etc.),
18: * the build disk from which this program runs must contain:
19: * In /bin: chgrp, chown, cpdir, date, echo, ln, mkdir, mv, rm, touch
20: * In /conf: boot, mboot, patch, upd_suppress, upd_save
21: * In /dev: at[01][abcdx], rat[01][abcd]
22: * In /etc: ATclock, badscan, fdisk, mkdev, mkfs, mount, umount
23: * It must also contain directories /mnt and /tmp.
24: * This program runs from a write-protected floppy-disk-based COHERENT
25: * boot disk, so it writes only to directory /tmp (mounted on a RAM disk).
26: */
27:
28: #include <stdio.h>
29: #include <canon.h>
30: #include <string.h>
31: #include <time.h>
32: #include <sys/devices.h>
33: #include <sys/fdisk.h>
34: #include <sys/filsys.h>
35: #include <sys/stat.h>
36: #include <sys/types.h>
37: #include <access.h>
38: #include "build0.h"
39: #include "serialno.h"
40:
41: /* Compilation switches. */
42: #define DOSSHRINK 0 /* punt dosshrink for now */
43:
44: /* Manifest constants. */
45: #define VERSION "4.3"
46: #define USAGE "Usage: /etc/build [ -dv ]\n"
47: #define ATDEVS (NPARTN+NPARTN) /* number of AT disk devices */
48: #define BSIZE 512 /* sector size */
49: #if _I386
50: #define BAR_BAR "__" /* 1st copy of serial # */
51: #define BAR_ENTRY "_entry" /* 2nd copy of serial # */
52: #define MAXSIZE 500 /* suggested max size (MB) */
53: #define MINSIZE 10 /* required root size (MB) */
54: #define NEEDSIZE 10 /* suggested min root size (MB) */
55: #define PIPEDEV "pipedev" /* kernel pipe F.S. device */
56: #define RONFLAG "ronflag" /* kernel readonly root F.S. flag */
57: #define ROOTDEV "rootdev" /* kernel root F.S. device */
58: #else
59: #define BAR_BAR "___" /* 1st copy of serial # */
60: #define BAR_ENTRY "_entry_" /* 2nd copy of serial # */
61: #define MAXSIZE 75 /* suggested max size (MB) */
62: #define MINSIZE 8 /* required root size (MB) */
63: #define NEEDSIZE 10 /* suggested min root size (MB) */
64: #define PIPEDEV "pipedev_" /* kernel pipe F.S. device */
65: #define RONFLAG "ronflag_" /* kernel readonly root F.S. flag */
66: #define ROOTDEV "rootdev_" /* kernel root F.S. device */
67: #endif
68: #define NAMESIZE 6 /* max device name buffer size */
69: #define NDEVICES 24 /* number of disk devices */
70:
71: /* (unsigned long) sectors to (double) megabytes. */
72: #define meg(sec) ((double)sec * BSIZE / 1000000.)
73:
74: /* Device table structure. */
75: typedef struct device {
76: char d_xname[NAMESIZE]; /* partition table name */
77: char d_dname[NAMESIZE]; /* device name */
78: int d_major; /* major number */
79: int d_minor; /* minor number */
80: int d_flags; /* flags */
81: unsigned long d_size; /* size in blocks */
82: } DEVICE;
83:
84: /* Flag bits. */
85: #define F_COH 0x01 /* COHERENT partition */
86: #define F_BOOT 0x02 /* Active */
87: #define F_ROOT 0x04 /* Root */
88: #define F_FS 0x08 /* File system exists */
89: #define F_MOUNT 0x10 /* Mounted by /etc/rc */
90: #define F_PROTO 0x20 /* Proto created */
91: #define F_SCAN 0x40 /* Badscanned */
92: #define F_ATDEV 0x80 /* AT device */
93: #define isflag(i, f) ((devices[i].d_flags & (f)) != 0)
94: #define notflag(i, f) ((devices[i].d_flags & (f)) == 0)
95: #define clrflag(i, f) devices[i].d_flags &= ~(f)
96: #define setflag(i, f) devices[i].d_flags |= (f)
97:
98: /*
99: * Device table.
100: * add_devices() adds entries for devices created by /etc/mkdev.
101: * fdisk() zaps the entries for which the xdevice open fails.
102: */
103: DEVICE devices[NDEVICES] = {
104: { "at0x", "at0a", AT_MAJOR, 0, F_ATDEV, 0L },
105: { "at0x", "at0b", AT_MAJOR, 1, F_ATDEV, 0L },
106: { "at0x", "at0c", AT_MAJOR, 2, F_ATDEV, 0L },
107: { "at0x", "at0d", AT_MAJOR, 3, F_ATDEV, 0L },
108: { "at1x", "at1a", AT_MAJOR, 4, F_ATDEV, 0L },
109: { "at1x", "at1b", AT_MAJOR, 5, F_ATDEV, 0L },
110: { "at1x", "at1c", AT_MAJOR, 6, F_ATDEV, 0L },
111: { "at1x", "at1d", AT_MAJOR, 7, F_ATDEV, 0L }
112: };
113:
114: /* Externals. */
115: extern long atol();
116: extern char *fgets();
117: extern long lseek();
118: extern time_t time();
119:
120: /* Forward. */
121: void add_devices();
122: void badscan();
123: void copy();
124: char *devname();
125: void done();
126: int exists_and_nz();
127: void fdisk();
128: void fsck();
129: void get_timezone();
130: int is_fs();
131: void mkdev();
132: void mkfs();
133: void new_boot();
134: void patches();
135: char *protoname();
136: char *rawname();
137: void rootpatch();
138: void save_files();
139: void set_date();
140: void uucp();
141: void user_devices();
142: void welcome();
143: char *xname();
144:
145: /* Globals. */
146: int active = -1; /* active partition */
147: char *activeos; /* active partition OS */
148: char buf2[NBUF]; /* extra buffer */
149: HDISK_S hd; /* hard disk boot block */
150: int mboot; /* mboot replaced */
151: int ncohdev; /* number of COHERENT devices */
152: int ndevices = ATDEVS; /* number of devices */
153: int protoflag; /* prototypes created */
154: int root; /* root partition */
155: char tzone[NBUF]; /* timezone */
156: char tzone5[NBUF]; /* timezone for Sys V */
157: int update; /* update, rather than install */
158:
159: main(argc, argv) int argc; char *argv[];
160: {
161: register char *s;
162:
163: argv0 = argv[0];
164: abortmsg = 1;
165: usagemsg = USAGE;
166: if (argc > 1 && argv[1][0] == '-') {
167: for (s = &argv[1][1]; *s; ++s) {
168: switch(*s) {
169: case 'd': ++dflag; break;
170: case 'u': ++update; break;
171: case 'v': ++vflag; break;
172: case 'V':
173: fprintf(stderr, "%s: V%s\n", argv0, VERSION);
174: break;
175: default: usage(); break;
176: }
177: }
178: --argc;
179: ++argv;
180: }
181: if (argc != 1)
182: usage();
183:
184: welcome();
185: set_date();
186: mkdev();
187: fdisk();
188: if (update) {
189: /* fsck(); */ /* rel notes tells user to do this */
190: new_boot();
191: save_files();
192: } else {
193: badscan();
194: mkfs();
195: }
196: copy();
197: if (!update)
198: user_devices();
199: uucp();
200: rootpatch();
201: /* sys("/conf/ldker", S_FATAL); */
202: patches();
203: sys("/bin/echo /etc/build: success >>/mnt/etc/install.log", S_NONFATAL);
204: sprintf(cmd, "TIMEZONE=\"%s\" /bin/date >>/mnt/etc/install.log", tzone);
205: sys(cmd, S_NONFATAL);
206: sys("/bin/echo >>/mnt/etc/install.log", S_NONFATAL);
207: done();
208: sync();
209: sys("/etc/reboot -p", S_IGNORE);
210: /* NOTREACHED */
211: exit(0);
212: }
213:
214: /*
215: * Append devices as specified by /etc/mkdev to devices table.
216: */
217: void
218: add_devices()
219: {
220: register FILE *fp;
221: register int i, n;
222:
223: if ((fp = fopen("/tmp/devices", "r")) == NULL)
224: return;
225: for (i = ndevices; i < NDEVICES; i++) {
226: n = fscanf(fp, "%s %s %d %d\n",
227: devices[i].d_xname, devices[i].d_dname,
228: &devices[i].d_major, &devices[i].d_minor);
229: if (n == 0 || n == EOF)
230: break;
231: else if (n != 4)
232: fatal("scanf failed on /tmp/devices, n=%d", n);
233: ++ndevices;
234: }
235: if (i == NDEVICES)
236: nonfatal("too many devices, excess ignored");
237: fclose(fp);
238: }
239:
240: /*
241: * Scan each COHERENT device for bad blocks.
242: */
243: void
244: badscan()
245: {
246: register int i;
247: register char *name;
248:
249: cls(1);
250: printf(
251: "The next step in installation is to scan each COHERENT partition\n"
252: "for bad blocks. This will not write to the partition being scanned.\n"
253: "Be patient. This takes a few minutes.\n"
254: );
255: for (i = 0; i < ndevices; i++) {
256: if (notflag(i, F_COH) || notflag(i, F_ATDEV))
257: continue; /* scan only AT device COH partitions */
258: printf("\n");
259: name = devname(i, 0);
260: if (isflag(i, F_FS)) {
261: printf(
262: "Partition %d (%s) already contains a COHERENT filesystem.\n"
263: "If you wish to continue to use the existing filesystem, you can skip\n"
264: "scanning it for bad blocks. If you want to replace it with an empty\n"
265: "filesystem, you must scan it for bad blocks first.\n",
266: i, name);
267: if (yes_no("Do you want to scan %s for bad blocks",
268: name) == 0)
269: continue;
270: }
271: printf("Scanning partition %d:\n", i);
272: setflag(i, F_SCAN);
273: sprintf(cmd, "/etc/badscan -v -o %s %s %s",
274: protoname(i), rawname(i, 1), xname(i, 1));
275: if (sys(cmd, S_NONFATAL) == 0) {
276: setflag(i, F_PROTO);
277: ++protoflag;
278: }
279: }
280: }
281:
282: /*
283: * Mount the root filesystem, copy files to it, patch /coherent.
284: * Kludge around as required.
285: */
286: void
287: copy()
288: {
289: cls(0);
290: printf(
291: "The next step is to copy some COHERENT files from the diskette to the\n"
292: "root filesystem of your hard disk. This will take a few minutes...\n"
293: );
294:
295: /* Mount the filesystem. */
296: sprintf(cmd, "/etc/mount %s /mnt", devname(root, 1));
297:
298: sys(cmd, S_FATAL);
299:
300: /* Copy kernel patch and link scripts in case regen needed some day */
301: /* Do it now - don't wait for the whole diskette to cpdir */
302: sprintf(cmd, "/bin/cpdir -ad%s /conf /mnt/conf", (vflag) ? "v" : "");
303: sys(cmd, S_FATAL);
304: sprintf(cmd, "/bin/cpdir -ad%s /tmp /mnt/conf/gen", (vflag) ? "v" : "");
305: sys(cmd, S_FATAL);
306: printf( "..............\n" );
307:
308: /* Copy the boot floppy to it. */
309: sprintf(cmd, "/bin/cpdir -ad%s -smnt -sbegin -stmp -sconf %s / /mnt",
310: (vflag) ? "v" : "", (update) ? "`cat /conf/upd_suppress`" : "");
311: sys(cmd, S_FATAL);
312: if (!is_dir("/mnt/mnt"))
313: sys("/bin/mkdir /mnt/mnt", S_FATAL);
314: sys("/bin/chmog 0755 bin bin /mnt/mnt", S_NONFATAL);
315:
316: /* Write entry to /etc/install.log. */
317: sprintf(cmd, "/bin/echo /etc/build: %s %s >>/mnt/etc/install.log",
318: #if _I386
319: "386",
320: #else
321: "286",
322: #endif
323: (update) ? "update" : "install");
324: sys(cmd, S_NONFATAL);
325: sprintf(cmd, "TIMEZONE=\"%s\" /bin/date >>/mnt/etc/install.log", tzone);
326: sys(cmd, S_NONFATAL);
327:
328: #if 0
329: /* If /etc/fdisk created patched /tmp/coherent, replace /coherent. */
330: if (exists("/mnt/tmp/coherent")) {
331: sys("/bin/mv /mnt/tmp/coherent /mnt/coherent", S_FATAL);
332: sys("/bin/chmod 0400 /mnt/coherent", S_NONFATAL);
333: sys("/bin/chown sys /mnt/coherent", S_NONFATAL);
334: sys("/bin/chgrp sys /mnt/coherent", S_NONFATAL);
335: }
336: #endif
337:
338: /* If /etc/mkdev created devices in /tmp/dev, copy them to /dev. */
339: /* Remove the copies in /tmp/dev on the hard disk. */
340: if (exists("/tmp/dev"))
341: sys("/bin/cpdir -d /tmp/dev /mnt/dev", S_FATAL);
342: #if !_I386
343: /*
344: * As of COH 3.2, support for COM ports is not built into the system.
345: * Echo lines to /tmp/drvld.all to drvld com line support,
346: * then replace /mnt/etc/drvld.all and make sure permissions are right.
347: */
348: sys("/bin/echo /etc/drvld -r /drv/al0 >>/tmp/drvld.all", S_NONFATAL);
349: sys("/bin/echo /etc/drvld -r /drv/al1 >>/tmp/drvld.all", S_NONFATAL);
350: #endif
351: if (exists("/tmp/drvld.all")) {
352: sys("/bin/cp /tmp/drvld.all /mnt/etc/drvld.all", S_NONFATAL);
353: sys("/bin/chmog 0744 root root /mnt/etc/drvld.all", S_NONFATAL);
354: }
355:
356: sys("/bin/cat /tmp/ttys >>/mnt/etc/ttys", S_NONFATAL);
357:
358: /* Grow /lost+found to make room for files. */
359: sys("cd /mnt/lost+found \n"
360: "/bin/touch `/bin/from 1 to 200` \n"
361: "/bin/rm *", S_IGNORE);
362:
363: /* Create /autoboot. */
364: sys("/bin/ln -f /mnt/coherent /mnt/autoboot", S_FATAL);
365:
366: /* Replace the build version of /etc/brc with the install version. */
367: sys("/bin/rm /mnt/etc/brc", S_NONFATAL);
368: if (update)
369: sys("/bin/ln -f /mnt/etc/brc.update /mnt/etc/brc", S_FATAL);
370: else
371: sys("/bin/ln -f /mnt/etc/brc.install /mnt/etc/brc", S_FATAL);
372:
373: /* Link root device to /dev/root. */
374: sprintf(cmd, "/bin/ln -f /mnt%s /mnt/dev/root", devname(root, 0));
375: sys(cmd, S_FATAL);
376:
377: /* Write the timezone to /etc/timezone. */
378: sprintf(cmd, "/bin/echo export TIMEZONE=\\\"%s\\\" >/mnt/etc/timezone", tzone);
379: sys(cmd, S_NONFATAL);
380: sprintf(cmd, "/bin/echo export TZ=\\\"%s\\\" >>/mnt/etc/timezone", tzone5);
381: sys(cmd, S_NONFATAL);
382:
383: if (!update) {
384: /* Write the serial number to /etc/serialno. */
385: sprintf(cmd, "/bin/echo %s >/mnt/etc/serialno", serialno);
386: sys(cmd, S_NONFATAL);
387: }
388:
389: /* Save the prototypes from /tmp to /conf. */
390: if (protoflag)
391: sys("/bin/mv /tmp/*.proto /mnt/conf", S_NONFATAL);
392: }
393:
394: /*
395: * Generate a device name from a DEVICE entry name.
396: * Return a pointer to the statically allocated name.
397: * If flag and not one of the built-in AT device names,
398: * the device is in /tmp/dev rather than /dev.
399: * Sleazy hack: this always writes "/tmp/dev/..." in the buffer and
400: * massages the return value accordingly so that subsequent calls
401: * with same i but different flag will not clobber previous return values.
402: */
403: char *
404: devname(i, flag) int i, flag;
405: {
406: static char name[4+4+1+NAMESIZE]; /* e.g. "/tmp/dev/at0a" */
407:
408: sprintf(name, "/tmp/dev/%s", devices[i].d_dname);
409: return (flag && notflag(i, F_ATDEV)) ? name : name+4;
410: }
411:
412: /*
413: * Done.
414: * Print useful information.
415: */
416: void
417: done()
418: {
419: cls(1);
420: printf(
421: "You have installed the COHERENT operating system onto your hard disk.\n"
422: "To install files from the remaining diskettes in the installation kit,\n"
423: "you must boot the COHERENT system from the hard disk. It will prompt\n"
424: "you to install the remaining diskettes in the installation kit.\n"
425: "\n"
426: "After you finish reading this information, remove the floppy disk,\n"
427: "hit <Enter> and your system will automatically reboot.\n"
428: "\n"
429: );
430: if (mboot) {
431: printf(
432: "If you type a partition number (0 to 7) while\n"
433: "the boot procedure is trying to read the floppy disk,\n"
434: "your system will boot the operating system on that partition.\n"
435: );
436: if (active != -1) {
437: printf("If you type nothing, your system will boot ");
438: if (active == root)
439: printf("COHERENT (partition %d).\n", active);
440: else {
441: printf("active partition %d", active);
442: if (activeos != NULL)
443: printf(" (%s)", activeos);
444: printf(".\n", active);
445: }
446: }
447: } else
448: printf(
449: "You must boot the new COHERENT root filesystem on partition %d.\n",
450: root);
451: printf("\nNow remove the floppy disk so your system does not boot from the floppy.\n");
452: if (mboot && root != active)
453: printf(
454: "You MUST type %d when the system tries to read the floppy disk during the boot\n"
455: "procedure to boot the partition containing the new COHERENT root filesystem.\n",
456: root);
457: }
458:
459: /*
460: * See if the specified file exists and has non-zero length.
461: */
462: exists_and_nz(fn)
463: char *fn;
464: {
465: struct stat s;
466:
467: if (stat(fn, &s) == -1)
468: return 0; /* does not exist */
469: return (s.st_size > 0); /* exists and length > 0 */
470: }
471:
472: /*
473: * Get partition table information.
474: */
475: void
476: fdisk()
477: {
478: register int fd, i, j, n, part, cohpart, flag;
479: char *fname, *s;
480:
481: cls(1);
482: if (update) {
483: printf("Reading existing partition tables...\n");
484: } else {
485: printf(
486: "This installation procedure allows you to create one or more partitions\n"
487: "on your hard disk to contain the COHERENT system and its files.\n"
488: "Each disk drive may contain no more than four logical partitions.\n"
489: "If all four partitions on your disk are already in use, you will\n"
490: "have to overwrite at least one of them to install COHERENT.\n"
491: "If your disk uses fewer than four partitions and has enough unused space\n"
492: "for COHERENT (%d megabytes), you can install COHERENT into the unused space.\n"
493: "If you intend to install MS-DOS after installing COHERENT,\n"
494: "you must leave the first physical partition free for MS-DOS.\n"
495: "\n"
496: "The next part of the installation procedure will let you change the\n"
497: "partitions on your hard disk. Data on unchanged hard disk partitions\n"
498: "will not be changed. However, data already on your hard disk may be\n"
499: "destroyed if you change the base or the size of a logical partition,\n"
500: "or if you change the order of the partition table entries.\n"
501: "If you need to back up existing data from the hard disk,\n"
502: "type <Ctrl-C> now to interrupt COHERENT installation; then reboot your\n"
503: "system and back up your hard disk data onto diskettes.\n"
504: "\n"
505: , NEEDSIZE);
506: cls(1);
507: printf(
508: "COHERENT initialization normally writes a new master bootstrap program onto\n"
509: "your hard disk. The COHERENT master boot allows you to boot the operating\n"
510: "system on one selected disk partition (the active partition) automatically;\n"
511: "it also allows you to boot the operating system on any disk partition by\n"
512: "typing a key when you reboot. Mark Williams strongly recommends that you\n"
513: "use the COHERENT master boot. However, the COHERENT master boot may not\n"
514: "work with some operating systems (for example, Xenix) if you make the\n"
515: "COHERENT partition active; instead, leave the other partition (e.g. Xenix)\n"
516: "active and boot COHERENT by typing a key. If you do not use the COHERENT\n"
517: "bootstrap, you must understand how to boot the COHERENT partition using your\n"
518: "existing bootstrap program.\n"
519: "\n"
520: );
521: if (yes_no("Do you want to use the COHERENT master boot"))
522: ++mboot;
523:
524: retry:
525: /* Construct an /etc/fdisk command with appropriate xdevice names. */
526: strcpy(cmd, "/etc/fdisk -cB");
527: if (mboot)
528: strcat(cmd, "b /conf/mboot");
529: for (i = 0; i < ndevices; i++) {
530: if (i == 0
531: || strcmp(devices[i-1].d_xname, devices[i].d_xname) != 0) {
532: if ((fd = open(xname(i, 1), 0)) < 0)
533: continue;
534: close(fd);
535: strcat(cmd, " ");
536: strcat(cmd, xname(i, 1));
537: }
538: }
539: sys(cmd, S_FATAL); /* do the fdisk command */
540: } /* !update */
541:
542: /* Read the partition table and set device flags appropriately. */
543: for (i = part = 0; i < ndevices; ++i) {
544: if (i != 0
545: && strcmp(devices[i-1].d_xname, devices[i].d_xname) == 0)
546: continue; /* partition already done */
547: fname = xname(i, 1);
548: if ((fd = open(fname, 0)) < 0)
549: continue; /* cannot open xdevice */
550: if (read(fd, &hd, sizeof hd) != sizeof hd)
551: fatal("%s: read failed", fname);
552: close(fd);
553: if (hd.hd_sig != HDSIG) {
554: nonfatal("%s: invalid partition table", fname);
555: continue;
556: }
557: /* The partition table is valid, check its partitions. */
558: for (j = 0; j < NPARTN && i + j < ndevices; j++) {
559: n = i + j; /* index in devices[] */
560: if (part != n) {
561: /*
562: * Copy over unopenable partitions.
563: * This allows subsequent code to use
564: * the devices[] index as the partition number.
565: */
566: devices[part] = devices[n];
567: n = part;
568: }
569: part++; /* another valid partition */
570: if (hd.hd_partn[j].p_boot != 0) {
571: setflag(n, F_BOOT);
572: if (active == -1)
573: active = n; /* first active partition */
574: switch(hd.hd_partn[j].p_sys) {
575: case SYS_COH:
576: activeos = "COHERENT";
577: break;
578: case SYS_DOS_12:
579: case SYS_DOS_16:
580: case SYS_DOS_XP:
581: case SYS_DOS_LARGE:
582: activeos = "MS-DOS";
583: break;
584: case SYS_XENIX:
585: activeos = "Xenix";
586: break;
587: default:
588: activeos = NULL;
589: break;
590: }
591: }
592: if (hd.hd_partn[j].p_sys != SYS_COH)
593: continue;
594:
595: /* Make sure the device can be accessed. */
596: s = devname(n, 1);
597: if (!exists(s)) {
598: nonfatal("cannot open COHERENT partition %d (%s)",
599: n, devname(n, 0));
600: continue;
601: } else if (hd.hd_partn[j].p_size == 0L) {
602: nonfatal("COHERENT partition %d (%s) is empty",
603: j, devname(n, 0));
604: continue;
605: }
606:
607: /* OK, set flags in the device table. */
608: ++ncohdev;
609: setflag(n, F_COH);
610: devices[n].d_size = hd.hd_partn[j].p_size;
611: if (is_fs(s, devices[n].d_size))
612: setflag(n, F_FS);
613:
614: /* Make sure the device is not mounted. */
615: sprintf(cmd, "/etc/umount %s 2>/dev/null", s);
616: sys(cmd, S_IGNORE);
617: }
618: }
619: ndevices = part;
620: if (ndevices == 0)
621: fatal("cannot open partition tables");
622: else if (ncohdev == 0)
623: fatal("no COHERENT partition found");
624: cls(0);
625: printf("Your system includes %d COHERENT partition%s:\n",
626: ncohdev, (ncohdev == 1) ? "" : "s");
627: printf("Drive Partition\t Device\tMegabytes\n");
628: for (flag = i = 0; i < ndevices; i++)
629: if (isflag(i, F_COH)) {
630: cohpart = i;
631: printf("%3d\t%3d\t%s\t%.2f\n",
632: i/NPARTN,
633: i,
634: devname(i, 0),
635: meg(devices[i].d_size));
636: if (((int)meg(devices[i].d_size)) > MAXSIZE)
637: flag = 1;
638: }
639: if (!update && flag) {
640: printf(
641: "\n"
642: "Your system includes a large COHERENT filesystem (larger than %d megabytes).\n"
643: #if !_I386
644: "The /etc/mkfs command which builds COHERENT 286 filesystems may run out of\n"
645: "memory and fail on large filesystems.\n"
646: #endif
647: "You should repartition the hard disk to define smaller COHERENT partitions.\n",
648: MAXSIZE);
649: if (yes_no("Do you want to repartition the hard disk"))
650: goto retry;
651: printf("\n");
652: }
653:
654: if (ncohdev == 1) {
655: root = cohpart;
656: setflag(root, F_ROOT);
657: return;
658: }
659: printf(
660: "You must specify one COHERENT partition as the root filesystem.\n"
661: );
662: if (!update)
663: printf(
664: "The root filesystem contains the files normally used by COHERENT.\n"
665: "The root filesystem should contain at least %d megabytes.\n",
666: NEEDSIZE);
667: if (ndevices > ATDEVS)
668: printf(
669: "The COHERENT root filesystem must be on partition 0 through 7.\n"
670: );
671: if (active != -1 && isflag(active, F_COH)) {
672: printf("COHERENT partition %d is marked as active in the partition table.\n",
673: active);
674: if (!update)
675: printf(
676: "If you choose it as the root, you can boot COHERENT automatically.\n"
677: );
678: }
679: printf("\n");
680: again:
681: if (update)
682: s = get_line("Which partition contains the COHERENT 286 root filesystem?");
683: else
684: s = get_line("Which partition do you want to be the root filesystem?");
685: root = *s - '0';
686: if (*++s != '\0' || root < 0 || root >= ATDEVS || notflag(root, F_COH)) {
687: printf("Enter a number between 0 and 7 which specifies a COHERENT partition.\n");
688: goto again;
689: }
690:
691: if (meg(devices[root].d_size) < (double)NEEDSIZE) {
692: if (update) {
693: printf(
694: "\n"
695: "Your current COHERENT 286 root filesystem is too small to contain the\n"
696: "COHERENT 386 update along with the on-line manual pages and the on-line\n"
697: "dictionary. If you wish to have the COHERENT 386 on-line manual pages and\n"
698: "the on-line dictionary installed, you will need to do the following:\n\n"
699: "\t1) Exit from the update.\n"
700: "\t2) Boot from your existing COHERENT 286 root partition.\n"
701: "\t3) Perform a full \"backup\" of ALL PARTITIONS on your hard disk\n"
702: "\t include all of your existing programs, files, and any system\n"
703: "\t files that you have modified using backup utilities \"cpio\",\n"
704: "\t \"ustar\", or \"tar\". If your hard disk includes partitions\n"
705: "\t assigned to other operating systems, be sure to back these up also!\n"
706: "\t4) Perform a full installation of COHERENT 386 using the same disks\n"
707: "\t supplied for the update. Note that you will need to increase the\n"
708: "\t size of the root partition, or you will need to select a different\n"
709: "\t partition to contain the root filesystem. Please refer to the\n"
710: "\t chapter on installation found in the COHERENT 386 release notes.\n"
711: );
712: sync();
713: if (yes_no("Do you wish to abort the update"))
714: fatal("Insufficient disk space for update!");
715: } else {
716: printf("Partition %d contains only %.2f megabytes.\n",
717: root, meg(devices[root].d_size));
718: if (meg(devices[root].d_size) < (double)MINSIZE) {
719: printf("It is too small to contain the COHERENT root filesystem.\n");
720: goto again;
721: }
722: if (!yes_no("Are you sure you want it to be the root partition"))
723: goto again;
724: }
725: }
726: setflag(root, F_ROOT);
727: }
728:
729: /*
730: * Perform a file system integrity check
731: */
732: void
733: fsck()
734: {
735: fatal("Need to add code for fsck here!");
736: }
737:
738: /*
739: * Set up a nonstandard timezone.
740: */
741: void
742: get_timezone(dstflag)
743: int dstflag;
744: {
745: register char *s;
746: int diff;
747: char std_abbr[20], dst_abbr[20];
748: int east_of_gr;
749:
750: /* tzone5 is like tzone except no colons and number is in hours */
751:
752: printf(
753: "You need to specify an abbreviation for your timezone,\n"
754: "whether you are east or west of Greenwich, England,\n"
755: "and the difference in minutes between your timezone\n"
756: "and Greenwich Time (called UT or GMT). For example,\n"
757: "Germany is 60 minutes of time east of Greenwich.\n"
758: );
759: s = get_line("Abbreviation for your timezone:");
760: strcpy(std_abbr, s);
761: east_of_gr = yes_no("Is your timezone east of Greenwich");
762: s = get_line("Difference in minutes from GMT:");
763: diff = atoi(s);
764: if (east_of_gr)
765: diff = -diff;
766: if (dstflag) {
767: s = get_line("Abbreviation for your daylight savings timezone:");
768: strcpy(dst_abbr, s);
769: sprintf(tzone, "%s:%d:%s:1.1.4", std_abbr, diff, dst_abbr);
770: sprintf(tzone5, "%s%d%s", std_abbr, diff/60, dst_abbr);
771: } else {
772: sprintf(tzone, "%s:%d:", std_abbr, diff);
773: sprintf(tzone5, "%s%d", std_abbr, diff/60);
774: }
775: }
776:
777: /*
778: * Check if a special file is a well-formed filesystem.
779: * This routine is derived from code in "mount.c".
780: * Here the check that "special" is a block special file is eliminated
781: * and the size is checked against the partition size.
782: */
783: int
784: is_fs(special, size) char *special; unsigned long size;
785: {
786: static struct filsys f;
787: register int fd;
788: register struct filsys *fp;
789: register daddr_t *dp;
790: register ino_t *ip, maxinode;
791:
792: if ((fd = open(special, 0)) < 0 /* cannot open */
793: || lseek(fd, (long)SUPERI*BSIZE, 0) == -1L /* seek failed */
794: || read(fd, &f, sizeof(f)) != sizeof(f)) /* read failed */
795: return 0;
796: close(fd);
797:
798: /* Canonical stuff. */
799: fp = &f;
800: canshort(fp->s_isize);
801: candaddr(fp->s_fsize);
802: canshort(fp->s_nfree);
803: for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
804: candaddr(*dp);
805: canshort(fp->s_ninode);
806: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
807: canino(*ip);
808: candaddr(fp->s_tfree);
809: canino(fp->s_tinode);
810:
811: /* Test for rationality. */
812: maxinode = (fp->s_isize - INODEI) * INOPB + 1;
813: if (fp->s_isize >= fp->s_fsize)
814: return 0;
815: if ((fp->s_tfree < fp->s_nfree)
816: || (fp->s_tfree >= fp->s_fsize - fp->s_isize + 1))
817: return 0;
818: if ((fp->s_tinode < fp->s_ninode) || (fp->s_tinode >= maxinode-1 ))
819: return 0;
820: for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
821: if ((*dp < fp->s_isize) || (*dp >= fp->s_fsize))
822: return 0;
823: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
824: if ((*ip < 1) || (*ip > maxinode))
825: return 0;
826: if (fp->s_fsize > (daddr_t)size)
827: return 0;
828: if (fp->s_fsize > (daddr_t)size)
829: nonfatal("warning: filesystem size=%ld but partition size=%ld",
830: (long)fp->s_fsize, size);
831: return 1;
832: }
833:
834: /*
835: * Make new devices with /etc/mkdev if appropriate.
836: */
837: void
838: mkdev()
839: {
840: int hdc;
841:
842: cls(0);
843: printf("Most PC compatible computer systems use MFM, RLL, IDE, or ESDI disk\n");
844: printf("controllers and disk drives. A few percent use SCSI disk drives.\n");
845: printf("Please indicate the type(s) of disk drive(s) used in your computer system.\n");
846: printf("If you are uncertain of the type, please select choice 1.\n\n");
847: printf("Are you using:\n\n");
848: printf("1. AT-compatible hard drive controller (IDE/RLL/MFM/ESDI).\n");
849: printf("2. SCSI hard drive controller.\n");
850: printf("3. Both.\n\n");
851: hdc = get_int(1, 3, "Enter your choice:");
852:
853: /*
854: * Note: -b option to mkdev also OK for update
855: */
856: sprintf(cmd, "/etc/mkdev -b%s%s %s %s",
857: (dflag) ? "d" : "",
858: (vflag) ? "v" : "",
859: (hdc == 1 || hdc == 3) ? "at" : "",
860: (hdc == 2 || hdc == 3) ? "scsi" : "");
861: sys(cmd, S_NONFATAL);
862: if (hdc == 2 || hdc == 3)
863: add_devices();
864: }
865:
866: /*
867: * Make filesystems on COHERENT partitions.
868: */
869: void
870: mkfs()
871: {
872: register int i;
873: char *name;
874:
875: cls(0);
876: printf(
877: "You must create an empty COHERENT filesystem on each COHERENT partition\n"
878: "before you can use it. Creating an empty filesystem will destroy all\n"
879: "previously existing data on the partition.\n"
880: );
881: for (i = 0; i < ndevices; i++) {
882: if (notflag(i, F_COH) || (isflag(i, F_ATDEV) && notflag(i, F_SCAN)))
883: continue;
884: printf("\n");
885: if (isflag(i, F_FS))
886: printf("Partition %d (%s) already contains a COHERENT filesystem.\n",
887: i, devname(i, 0));
888: if (i == root)
889: printf(
890: "\nWARNING!!!\n\n"
891: "The installation process expects a NEW file system in the root partition.\n"
892: "If you are trying to update an existing COHERENT partition, you must run\n"
893: "the COHERENT update. If you are trying to install again after a partial\n"
894: "or failed installation, a new root file system must be created again now.\n\n"
895: );
896: name = devname(i, 1);
897: again:
898: if (yes_no("Do you want to create a new COHERENT filesystem on partition %d", i)) {
899: if (notflag(i, F_ATDEV))
900: sprintf(cmd, "/etc/mkfs %s %lu", name, devices[i].d_size);
901: else if (notflag(i, F_PROTO)) {
902: printf("The attempt to scan %s for bad blocks previously failed.",
903: name);
904: if (yes_no("Do you want to create a new filesystem on it without a bad block list"))
905: sprintf(cmd, "/etc/mkfs %s %lu", name, devices[i].d_size);
906: else
907: continue;
908: } else
909: sprintf(cmd, "/etc/mkfs %s %s",
910: name, protoname(i));
911: clrflag(i, F_FS);
912: if (sys(cmd, S_NONFATAL) == 0) {
913: setflag(i, F_FS);
914: if (notflag(i, F_PROTO)) {
915: /* Stick a boot block on device. */
916: /* The proto does it in the other case. */
917: sprintf(cmd, "/bin/cp /conf/boot %s", name);
918: sys(cmd, S_NONFATAL);
919: }
920:
921: /*
922: * Mount the file system,
923: * create /lost+found,
924: * unmount it.
925: */
926: sprintf(cmd, "/etc/mount %s /mnt", name);
927: if (sys(cmd, S_NONFATAL))
928: continue;
929: sprintf(cmd, "/bin/mkdir /mnt/lost+found");
930: if (sys(cmd, S_NONFATAL) == 0)
931: sys(
932: "cd /mnt/lost+found \n"
933: "/bin/touch `/bin/from 1 to 200` \n"
934: "/bin/rm *",
935: S_IGNORE);
936: sprintf(cmd, "/etc/umount %s", name);
937: sys(cmd, S_NONFATAL);
938: } else if (i == root)
939: fatal("%s: root partition mkfs failed", name);
940: } else if (i == root) {
941: if (notflag(i, F_FS)) {
942: printf("You must create a filesystem on the root partition.\n");
943: goto again;
944: } else {
945: /* Stick a boot block on the root device. */
946: sprintf(cmd, "/bin/cp /conf/boot %s", name);
947: sys(cmd, S_NONFATAL);
948: }
949: }
950: }
951: }
952:
953: /*
954: * Place a bootstrap on the root filesystem.
955: * This is only called from update.
956: */
957: void
958: new_boot()
959: {
960: sprintf(cmd, "/bin/cp /conf/boot %s", devname(root, 1));
961: sys(cmd, S_FATAL);
962: }
963:
964: /*
965: * Validate "name" to see if its an OK UUCP sitename or domain name. If
966: * anything suspicious is found, query the user and allow them to change
967: * their answer. The domain defaults to UUCP. In order to avoid having
968: * 10,000 machines called bbsuser, no default exists for the sitename.
969: *
970: * Return true if OK, false otherwise.
971: */
972: int
973: ok_name(name, type)
974: unsigned char *name; /* User's response to site/domain question */
975: int type; /* 'd' == domain, 'u' == uucpname/site */
976: {
977: int warn = 0;
978: char save[NBUF]; /* save off name for caller */
979:
980: if (type == 'd' && name[0] == '.')
981: strcpy(name, name+1);
982: strcpy(save, name);
983: if (name[0] == '\0') { /* no input ? */
984: if (type == 'd') {
985: strcpy(name, "UUCP"); /* default to UUCP domain */
986: return 1;
987: } else {
988: return 0; /* no defaults for sitename */
989: }
990: }
991: if (type == 'u' && strlen(name) > 7) {
992: ++warn;
993: printf(
994: "The system name you chose is greater than seven characters in length.\n"
995: );
996: }
997: if ((type == 'd' && strspn(name, "abcdefghijklmnopqrstuvwxyz"
998: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
999: "0123456789"
1000: ".-_") != strlen(name))
1001: || (type == 'u' && strspn(name, "abcdefghijklmnopqrstuvwxyz"
1002: "0123456789") != strlen(name))) {
1003: ++warn;
1004: printf("The name you chose contains invalid characters.\n");
1005: }
1006: if (!warn)
1007: return 1;
1008: if (yes_no("Would you like to choose a different name"))
1009: return 0;
1010: strcpy(name, save);
1011: return 1;
1012: }
1013:
1014: /*
1015: * If PATCHFILE exists, execute it.
1016: */
1017: void patches()
1018: {
1019: printf("The kernel on your hard drive will now be patched to run on your system. You\n");
1020: printf("may see some messages indicating that certain symbols are not present in the\n");
1021: printf("kernel. You should note them, but otherwise ignore them. Install will use these\n");
1022: printf("values after all of the diskettes have been copied to the hard drive.\n\n");
1023: if (access(PATCHFILE, AREAD) == 0) {
1024: sprintf(cmd, "/bin/sh %s", PATCHFILE);
1025: sys(cmd, S_NONFATAL);
1026: }
1027: }
1028:
1029: /*
1030: * Generate a prototype name from a DEVICE entry name.
1031: * Return a pointer to the statically allocated name.
1032: */
1033: char *
1034: protoname(i) int i;
1035: {
1036: static char pname[5+NAMESIZE+6]; /* e.g. "/tmp/at0a.proto" */
1037:
1038: sprintf(pname, "/tmp/%s.proto", devices[i].d_dname);
1039: return pname;
1040: }
1041:
1042: /*
1043: * Generate a raw device name from a DEVICE entry name.
1044: * Return a pointer to the statically allocated name.
1045: * If flag and not one of the built-in AT device names,
1046: * the device is in /tmp/dev rather than /dev.
1047: */
1048: char *
1049: rawname(i, flag) int i, flag;
1050: {
1051: static char rname[4+4+1+1+NAMESIZE]; /* e.g. "/tmp/dev/rat0a" */
1052:
1053: sprintf(rname, "/tmp/dev/r%s", devices[i].d_dname);
1054: return (flag && notflag(i, F_ATDEV)) ? rname : rname+4;
1055: }
1056: /*
1057: * Patches to be done to the kernel - but can't do them yet because
1058: * kernel hasn't been linked.
1059: */
1060: void
1061: rootpatch()
1062: {
1063: /*
1064: * After fdisk() we know "root". Write to PATCHFILE the patches
1065: * that will be needed when a new kernel is linked at /mnt/coherent.
1066: */
1067: sprintf(cmd,
1068: "echo /conf/patch /mnt/coherent %s=0 %s=0x%lx:l %s=0x%lx:l >> %s\n",
1069: RONFLAG, BAR_BAR, atol(serialno),
1070: BAR_ENTRY, atol(serialno), PATCHFILE);
1071: sys(cmd, S_FATAL);
1072: sprintf(cmd,
1073: "echo /conf/patch /mnt/coherent "
1074: "\\\"%s\\=makedev\\(%d,%d\\)\\\" "
1075: "\\\"%s\\=makedev\\(%d,%d\\)\\\" >> %s\n",
1076: ROOTDEV, devices[root].d_major, devices[root].d_minor,
1077: PIPEDEV, devices[root].d_major, devices[root].d_minor, PATCHFILE);
1078: sys(cmd, S_FATAL);
1079: }
1080:
1081: /*
1082: * Need to mount root.
1083: * Need to set serialno.
1084: * Remove /usr/man/{ALL,COHERENT,MULTI}, /usr/man/man.tar*
1085: * Save off any special files before copying in the update
1086: * Need to umount root.
1087: */
1088: void
1089: save_files()
1090: {
1091: char buf[20]; /* more than enough for a serial # */
1092: int fd; /* file descriptor */
1093: int i;
1094: char *s;
1095:
1096: cls(1);
1097: printf("We will now mount your existing COHERENT 286 root filesystem...\n");
1098: sprintf(cmd, "/etc/mount %s /mnt", devname(root, 1));
1099: sys(cmd, S_FATAL);
1100:
1101: if (!is_dir("/mnt/dev")) /* sanity check! */
1102: fatal("Corrupt or incorrect root filesystem specified");
1103: /*
1104: * Read in the old 286 serial number and save it off for later.
1105: * If it doesn't exist on the disk, make the user re-enter
1106: * the old serial number by hand.
1107: */
1108: serialno[0] = '\0';
1109: buf[0] = '\0';
1110: if ((fd = open("/mnt/etc/serialno", 0)) >= 0) {
1111: read(fd, buf, sizeof(buf)-1); /* ignore errors */
1112: close(fd);
1113: if (!isserial(buf)) /* sets serialno[] */
1114: serialno[0] = '\0';
1115: }
1116: if (serialno[0] == '\0') {
1117: printf(
1118: "\nA card included with your original COHERENT 286 distribution gives the\n"
1119: "serial number of your copy of COHERENT.\n\n"
1120: );
1121: for (i = 1; i <= 3; i++) {
1122: s = get_line("Type in the serial number from the card:");
1123: if (isserial(s))
1124: break;
1125: if (i < 3)
1126: printf("Invalid serial number, please try again.\n");
1127: else
1128: fatal("invalid serial number");
1129: }
1130: }
1131:
1132: printf("\nRemoving old on-line COHERENT manual pages -- please wait...\n");
1133: sys("/bin/rm -rf /mnt/usr/man/ALL /mnt/usr/man/COHERENT "
1134: "/mnt/usr/man/MULTI /mnt/usr/man/man.tar*", S_NONFATAL);
1135: sync();
1136:
1137: /*
1138: * Save off any special files just in case the user wants to
1139: * get the old ones back...
1140: */
1141: if (!is_dir("/mnt/old_coh")) {
1142: printf(
1143: "\nSaving existing configuration files to directory /old_coh -- please wait...\n\n"
1144: );
1145: sys("mkdir -r `cat /conf/upd_dirs`", S_NONFATAL);
1146: sys(
1147: "for a in `cat /conf/upd_save` ;"
1148: " do ;"
1149: " cp -d /mnt/$a /mnt/old_coh/$a 2>/dev/null && echo $a... ;"
1150: " done ;"
1151: " echo", S_IGNORE);
1152: sync();
1153: } else
1154: printf("Directory /old_coh contains configuration file backups.\n");
1155:
1156:
1157: sprintf(cmd, "rm -f /mnt/coherent.* /mnt/drv/*"); /* rm stale copies */
1158: sys(cmd, S_FATAL);
1159:
1160: sprintf(cmd, "/etc/umount %s", devname(root, 1));
1161: sys(cmd, S_FATAL);
1162:
1163: }
1164:
1165: /*
1166: * Date and time.
1167: */
1168: void
1169: set_date()
1170: {
1171: register char *s;
1172: int dst_conv; /* 1 if DST conversion will be used */
1173: int dst_now; /* 1 if DST in effect today */
1174: int n;
1175: char *tz;
1176: time_t now;
1177: struct tm *tmp;
1178: char *timestr;
1179:
1180: again:
1181: #if 1 /* new set_date */
1182:
1183: /*
1184: * yyy:
1185: *
1186: * dst_conv = FALSE
1187: * dst_now = FALSE
1188: *
1189: * if using DST conversion
1190: * dst_conv = TRUE
1191: * if DST in effect today
1192: * dst_now = TRUE
1193: * get date from system clock
1194: * if dst_conv and dst_now
1195: * add 1 hour to date fetched
1196: * display date
1197: * while date not correct
1198: * if proceed without setting clock
1199: * goto xxx
1200: * read date from kb
1201: * write date to CMOS clock and RAM clock
1202: * if dst_conv and dst_now
1203: * subtract 1 hour from date entered
1204: * write adjusted date to CMOS clock
1205: * xxx:
1206: * set TIMEZONE and TZ variables
1207: * if date, TIMEZONE, and TZ not all correct
1208: * goto yyy
1209: */
1210: cls(0);
1211: dst_conv = 0;
1212: dst_now = 0;
1213: printf(
1214: "You can run COHERENT with or without conversion for daylight savings time\n"
1215: "(summer time). You should normally run with daylight savings time\n"
1216: "conversion. However, if you are going to use both COHERENT and MS-DOS\n"
1217: "and you choose to run with daylight savings time conversion,\n"
1218: "your time will be wrong (by one hour) during daylight savings time\n"
1219: "while you are running under MS-DOS.\n"
1220: "\n"
1221: );
1222: if (yes_no(
1223: "Do you want COHERENT to use daylight savings time conversion")) {
1224: dst_conv = 1;
1225: printf(
1226: "\n"
1227: "By default, COHERENT assumes daylight savings time begins on the\n"
1228: "first Sunday in April and ends on the last Sunday in October.\n"
1229: "If you want to change the defaults, edit the file \"/etc/timezone\"\n"
1230: "after you finish installing COHERENT.\n"
1231: "\n"
1232: );
1233: if (yes_no("Is daylight savings time currently in effect"))
1234: dst_now = 1;
1235: }
1236: sys("/bin/date `/etc/ATclock` > /dev/null", S_NONFATAL);
1237: now = time(0);
1238: if (dst_conv && dst_now)
1239: now += 3600;
1240: timestr = ctime(&now);
1241: printf(
1242: "\nAccording to your system clock, your local date and time are:\n"
1243: );
1244: printf("%s\n", timestr);
1245: if (!yes_no("Is this correct")) {
1246: n = 0;
1247: do {
1248: if (++n > 3) {
1249: printf(
1250: "The command which sets the internal real-time clock of your system is\n"
1251: "failing repeatedly. Either you are entering the date and time incorrectly\n"
1252: "or your clock hardware is not completely AT-compatible. If your clock\n"
1253: "hardware is incompatible, you can continue with the installation without\n"
1254: "setting the clock correctly. However, if you do so, subsequent clock\n"
1255: "references (including file access and modification time information) will be\n"
1256: "incorrect and some commands (such as \"date\") will not function correctly.\n"
1257: );
1258: if (yes_no("Do you want to proceed without setting the clock correctly"))
1259: break;
1260: n = 0;
1261: }
1262: s = get_line(
1263: "\nEnter the correct date and time in the form YYMMDDHHMM.SS:"
1264: );
1265: sprintf(cmd, "/etc/ATclock %s >/dev/null", s);
1266: } while (sys(cmd, S_NONFATAL) != 0);
1267: sys("/bin/date `/etc/ATclock` >/dev/null", S_NONFATAL);
1268:
1269: if (dst_conv && dst_now) {
1270: /* Adjust for DST: set hardware clock back one hour. */
1271: now = time(0) - 3600;
1272: tmp = localtime(&now);
1273: sprintf(cmd,
1274: "/etc/ATclock %02d%02d%02d%02d%02d.%02d >/dev/null",
1275: tmp->tm_year, tmp->tm_mon + 1, tmp->tm_mday,
1276: tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
1277: sys(cmd, S_NONFATAL);
1278: }
1279:
1280: }
1281:
1282: /* Timezone. */
1283: cls(0);
1284: printf(
1285: "Please choose one of the following timezones:\n"
1286: "\t0\tCentral European\n"
1287: "\t1\tGreenwich\n"
1288: "\t2\tNewfoundland\n"
1289: "\t3\tAtlantic\n"
1290: "\t4\tEastern\n"
1291: "\t5\tCentral\n"
1292: "\t6\tMountain\n"
1293: "\t7\tPacific\n"
1294: "\t8\tYukon\n"
1295: "\t9\tAlaska\n"
1296: "\t10\tBering\n"
1297: "\t11\tHawaii\n"
1298: "\t12\tOther\n"
1299: );
1300: do {
1301: s = get_line("Timezone code:");
1302: } while ((n = atoi(s)) < 0 || n > 12);
1303: switch (n) {
1304: /* N.B. entries truncated at tz[8] below if !dst_conv. */
1305: case 0: tz = "EST:-60:EDT:1.1.4"; break;
1306: case 1: tz = "GMT:000:GDT:1.1.4"; break;
1307: case 2: tz = "NST:210:NDT:1.1.4"; break;
1308: case 3: tz = "AST:240:ADT:1.1.4"; break;
1309: case 4: tz = "EST:300:EDT:1.1.4"; break;
1310: case 5: tz = "CST:360:CDT:1.1.4"; break;
1311: case 6: tz = "MST:420:MDT:1.1.4"; break;
1312: case 7: tz = "PST:480:PDT:1.1.4"; break;
1313: case 8: tz = "YST:540:YDT:1.1.4"; break;
1314: case 9: tz = "AST:600:ADT:1.1.4"; break;
1315: case 10: tz = "BST:660:BDT:1.1.4"; break;
1316: case 11: tz = "HST:600:HDT:1.1.4"; break;
1317: case 12: tz = NULL; break;
1318: }
1319:
1320: if (tz == NULL)
1321: get_timezone(dst_conv);
1322: else {
1323: strcpy(tzone, tz);
1324: if (dst_conv) {
1325: /* for TZ, AST:240:ADT becomes AST4ADT */
1326: sprintf(tzone5, "%.3s%d%cDT",
1327: tz, atoi(tzone + 4)/60, tz[0]);
1328: } else {
1329: /* for TZ, AST:240 becomes AST4 */
1330: sprintf(tzone5, "%.3s%d", tz, atoi(tzone + 4)/60);
1331: tzone[8] = '\0';
1332: }
1333: }
1334: /* Done, print current time and retry if user botched it. */
1335: printf("\nYour current local date and time are now:\n");
1336: sprintf(cmd, "TIMEZONE='%s' /bin/date -s `/etc/ATclock`", tzone);
1337: sys(cmd, S_NONFATAL);
1338:
1339: /* Write the timezone to /tmp/timezone for debug */
1340: sprintf(cmd, "/bin/echo export TIMEZONE=\\\"%s\\\" >/tmp/timezone", tzone);
1341: sys(cmd, S_NONFATAL);
1342: sprintf(cmd, "/bin/echo export TZ=\\\"%s\\\" >>/tmp/timezone", tzone5);
1343: sys(cmd, S_NONFATAL);
1344: #else
1345: cls(0);
1346: /* Get correct local time, set system time accordingly. */
1347: printf(
1348: "It is important for the COHERENT system to know the correct date and time.\n"
1349: "You must provide information about your timezone and daylight savings time.\n"
1350: "\n"
1351: "According to your computer system clock, your current local date and time are:\n"
1352: );
1353: sys("/bin/date `/etc/ATclock`", S_NONFATAL);
1354: if (!yes_no("Is this correct")) {
1355: n = 0;
1356: do {
1357: if (++n > 3) {
1358: printf(
1359: "The command which sets the internal real-time clock of your system is\n"
1360: "failing repeatedly. Either you are entering the date and time incorrectly\n"
1361: "or your clock hardware is not completely AT-compatible. If your clock\n"
1362: "hardware is incompatible, you can continue with the installation without\n"
1363: "setting the clock correctly. However, if you do so, subsequent clock\n"
1364: "references (including file access and modification time information) will be\n"
1365: "incorrect and some commands (such as \"date\") will not function correctly.\n"
1366: );
1367: if (yes_no("Do you want to proceed without setting the clock correctly"))
1368: break;
1369: n = 0;
1370: }
1371: s = get_line(
1372: "Enter the correct date and time in the form YYMMDDHHMM.SS:"
1373: );
1374: sprintf(cmd, "/etc/ATclock %s >/dev/null", s);
1375: } while (sys(cmd, S_NONFATAL) != 0);
1376: sys("/bin/date `/etc/ATclock` >/dev/null", S_NONFATAL);
1377: }
1378:
1379: /* DST. */
1380: cls(0);
1381: printf(
1382: "You can run COHERENT with or without conversion for daylight savings time\n"
1383: "(summer time). You should normally run with daylight savings time\n"
1384: "conversion. However, if you are going to use both COHERENT and MS-DOS\n"
1385: "and you choose to run with daylight savings time conversion,\n"
1386: "your time will be wrong (by one hour) during daylight savings time\n"
1387: "while you are running under MS-DOS.\n"
1388: "\n"
1389: );
1390: dst_conv = yes_no("Do you want COHERENT to use daylight savings time conversion");
1391: if (dst_conv) {
1392: printf(
1393: "\n"
1394: "By default, COHERENT assumes daylight savings time begins on the\n"
1395: "first Sunday in April and ends on the last Sunday in October.\n"
1396: "If you want to change the defaults, edit the file \"/etc/timezone\"\n"
1397: "after you finish installing COHERENT.\n"
1398: "\n"
1399: );
1400: if (yes_no("Is daylight savings time currently in effect")) {
1401: /* Adjust for DST: set hardware clock back one hour. */
1402: now = time(NULL) - 60 * 60;
1403: tmp = localtime(&now);
1404: sprintf(cmd, "/etc/ATclock %02d%02d%02d%02d%02d.%02d >/dev/null",
1405: tmp->tm_year, tmp->tm_mon + 1, tmp->tm_mday,
1406: tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
1407: sys(cmd, S_NONFATAL);
1408: }
1409: }
1410:
1411: /* Timezone. */
1412: cls(0);
1413: printf(
1414: "Please choose one of the following timezones:\n"
1415: "\t0\tCentral European\n"
1416: "\t1\tGreenwich\n"
1417: "\t2\tNewfoundland\n"
1418: "\t3\tAtlantic\n"
1419: "\t4\tEastern\n"
1420: "\t5\tCentral\n"
1421: "\t6\tMountain\n"
1422: "\t7\tPacific\n"
1423: "\t8\tYukon\n"
1424: "\t9\tAlaska\n"
1425: "\t10\tBering\n"
1426: "\t11\tHawaii\n"
1427: "\t12\tOther\n"
1428: );
1429: do {
1430: s = get_line("Timezone code:");
1431: } while ((n = atoi(s)) < 0 || n > 12);
1432: switch (n) {
1433: /* N.B. entries truncated at tz[8] below if !dst_conv. */
1434: case 0: tz = "EST:-60:EDT:1.1.4"; break;
1435: case 1: tz = "GMT:000:GDT:1.1.4"; break;
1436: case 2: tz = "NST:210:NDT:1.1.4"; break;
1437: case 3: tz = "AST:240:ADT:1.1.4"; break;
1438: case 4: tz = "EST:300:EDT:1.1.4"; break;
1439: case 5: tz = "CST:360:CDT:1.1.4"; break;
1440: case 6: tz = "MST:420:MDT:1.1.4"; break;
1441: case 7: tz = "PST:480:PDT:1.1.4"; break;
1442: case 8: tz = "YST:540:YDT:1.1.4"; break;
1443: case 9: tz = "AST:600:ADT:1.1.4"; break;
1444: case 10: tz = "BST:660:BDT:1.1.4"; break;
1445: case 11: tz = "HST:600:HDT:1.1.4"; break;
1446: case 12: tz = NULL; break;
1447: }
1448:
1449: if (tz == NULL)
1450: get_timezone(dst_conv);
1451: else {
1452: strcpy(tzone, tz);
1453: if (!dst_conv)
1454: tzone[8] = '\0';
1455: }
1456:
1457: /* Done, print current time and retry if user botched it. */
1458: printf("\nYour current local date and time are now:\n");
1459: sprintf(cmd, "TIMEZONE='%s' /bin/date -s `/etc/ATclock`", tzone);
1460: sys(cmd, S_NONFATAL);
1461: #endif /* new set_date */
1462: if (!yes_no("Is this correct"))
1463: goto again;
1464: }
1465:
1466: /*
1467: * Configure user devices.
1468: * Assumes hard disk filesystem mounted on /mnt.
1469: * Write lines to /etc/mount.all, /etc/umount.all to [u]mount the user devices.
1470: */
1471: void
1472: user_devices()
1473: {
1474: register int i, status;
1475: register char *s, *s2, *name, *rname;
1476:
1477: if (ncohdev == 1) {
1478: sys("/bin/echo /dev/root >>/mnt/etc/checklist", S_NONFATAL);
1479: return;
1480: }
1481:
1482: /* Create user device names. */
1483: cls(0);
1484: printf(
1485: "Your system includes %d partition%s in addition to the root partition.\n"
1486: "These partitions are usually mounted on directories in the COHERENT\n"
1487: "root filesystem when the system goes into multiuser mode.\n"
1488: "For example, one non-root partition might be mounted on\n"
1489: "directory \"/u\", another on \"/v\", and so on.\n"
1490: "You now may specify where you want each partition mounted.\n",
1491: ncohdev - 1, ncohdev == 2 ? "" : "s");
1492: for (i = 0; i < ndevices; i++) {
1493: if (notflag(i, F_COH) || notflag(i, F_FS) || isflag(i, F_ROOT))
1494: continue;
1495: name = devname(i, 0);
1496: rname = rawname(i, 0);
1497: printf("\nPartition %d (%s):\n", i, name);
1498: if (yes_no("Do you want %s mounted", name)) {
1499: setflag(i, F_MOUNT);
1500: again:
1501: s = get_line("Where do you want to mount it?");
1502: if (*s != '/') {
1503: printf("Type a directory name beginning with '/', such as \"/u\".\n");
1504: goto again;
1505: } else if ((s2 = strchr(s, ' ')) != NULL)
1506: *s2 = '\0';
1507: sprintf(cmd, "/mnt/%s", s);
1508: if ((status = is_dir(cmd)) == -1) {
1509: printf("%s exists but is not a directory.\n", s);
1510: goto again;
1511: } else if (status == 1) {
1512: strcpy(buf2, s);
1513: printf("Directory %s already exists.\n", s);
1514: if (!yes_no("Are you sure you want %s mounted on %s", name, s))
1515: goto again;
1516: s = buf;
1517: strcpy(s, buf2);
1518: } else {
1519: /* Make the target directory, uid=bin, gid=bin. */
1520: sprintf(cmd, "/bin/mkdir -r /mnt%s", s);
1521: if (sys(cmd, S_NONFATAL))
1522: goto again;
1523: sprintf(cmd, "/bin/chown bin /mnt%s", s);
1524: sys(cmd, S_NONFATAL);
1525: sprintf(cmd, "/bin/chgrp bin /mnt%s", s);
1526: sys(cmd, S_NONFATAL);
1527: }
1528: printf("%s will be mounted on %s when COHERENT goes multiuser.\n",
1529: name, s);
1530:
1531: /* Change e.g. /usr/src to usr_src. */
1532: strcpy(buf2, &s[1]);
1533: while ((s2 = strchr(buf2, '/')) != NULL)
1534: *s2 = '_';
1535:
1536: /* Make link to pseudo-device, e.g. "/dev/usr_src". */
1537: sprintf(cmd, "/mnt/dev/%s", buf2);
1538: if (exists(cmd))
1539: status = 1; /* use normal name */
1540: else {
1541: sprintf(cmd, "/bin/ln -f /mnt%s /mnt/dev/%s",
1542: name, buf2);
1543: if ((status = sys(cmd, S_NONFATAL)) == 0)
1544: printf(
1545: "/dev/%s is linked to %s to provide a mnemonic device name.\n",
1546: buf2, name);
1547: }
1548:
1549: /* Add lines to /etc/mount.all, /etc/umount.all. */
1550: if (status == 0)
1551: sprintf(cmd, "/bin/echo /etc/mount /dev/%s %s >>/mnt/etc/mount.all",
1552: buf2, s);
1553: else
1554: sprintf(cmd, "/bin/echo /etc/mount %s %s >>/mnt/etc/mount.all",
1555: name, s);
1556: sys(cmd, S_NONFATAL);
1557: if (status == 0)
1558: sprintf(cmd, "/bin/echo /etc/umount /dev/%s >>/mnt/etc/umount.all",
1559: buf2);
1560: else
1561: sprintf(cmd, "/bin/echo /etc/umount %s >>/mnt/etc/umount.all",
1562: name);
1563: sys(cmd, S_NONFATAL);
1564:
1565: /* And again, for the raw device. */
1566: sprintf(cmd, "/mnt/dev/r%s", buf2);
1567: if (exists(cmd))
1568: status = 1;
1569: else {
1570: sprintf(cmd, "/bin/ln -f /mnt%s /mnt/dev/r%s",
1571: rname, buf2);
1572: if ((status = sys(cmd, S_NONFATAL)) == 0)
1573: printf(
1574: "/dev/r%s is linked to %s to provide a mnemonic device name.\n",
1575: buf2, rname);
1576: }
1577:
1578: /* Add raw device line to /etc/checklist. */
1579: if (status == 0)
1580: sprintf(cmd, "/bin/echo /dev/r%s >>/mnt/etc/checklist",
1581: buf2);
1582: else
1583: sprintf(cmd, "/bin/echo %s >>/mnt/etc/checklist",
1584: rname);
1585: sys(cmd, S_NONFATAL);
1586: } else {
1587: /* Not mounted, check using standard name. */
1588: sprintf(cmd, "/bin/echo %s >>/mnt/etc/checklist", rname);
1589: sys(cmd, S_NONFATAL);
1590: }
1591: }
1592: sys("/bin/echo /dev/root >>/mnt/etc/checklist", S_NONFATAL);
1593:
1594: /* Link /dev/dos if desired. */
1595: if (yes_no("Do you use both COHERENT and MS-DOS on your hard disk")) {
1596: i = get_int(0, ndevices-1, "Enter the partition number of your MS-DOS partition:");
1597: sprintf(cmd, "/bin/ln -f /mnt%s /mnt/dev/dos", devname(i, 0));
1598: if (sys(cmd, S_NONFATAL) == 0)
1599: printf(
1600: "Device name /dev/dos is now linked to %s for use as a mnemonic\n"
1601: "device name. You may use the \"dos*\" family of commands to transfer files\n"
1602: "to and from the MS-DOS partition on your hard disk as well as MS-DOS floppies.\n",
1603: devname(i, 0));
1604: printf("\n");
1605: }
1606: }
1607:
1608:
1609: /*
1610: * Set up site/machine specific info in files /etc/uucpname and /etc/domain
1611: */
1612: void
1613: uucp()
1614: {
1615: unsigned char *cp;
1616:
1617: cls(1);
1618: if (!update || !exists_and_nz("/mnt/etc/uucpname")) {
1619: printf(
1620: "In order to use COHERENT's electronic mail facility and UUCP subsystem,\n"
1621: "you must choose a \"site name\" for your computer system. In general, a site\n"
1622: "name consists of lower case letters or digits and should be at most seven\n"
1623: "characters in length. The name you choose should be unique if you intend\n"
1624: "to access any other computer systems. Some of the more well known site\n"
1625: "names include \"mwc\", \"uunet\", \"clout\", \"decwrl\", \"hp\", \"kgbvax\", "
1626: "\"prep\",\n\"seismo\", and \"ucbvax\".\n\n"
1627: );
1628: for (;;) {
1629: cp = get_line("Please enter the site name for this system: ");
1630: if (ok_name(cp, 'u'))
1631: break;
1632: }
1633: sprintf(cmd, "/bin/echo \"%s\" >/mnt/etc/uucpname", cp);
1634: sys(cmd, S_NONFATAL);
1635: }
1636:
1637: if (!update || !exists_and_nz("/mnt/etc/domain")) {
1638: printf(
1639: "\nThe COHERENT mail subsystem supports \"domain addressing\" in addition to\n"
1640: "traditional \"bang paths\". Until your system becomes part of a registered\n"
1641: "domain, you may use the UUCP pseudo-domain. Domain names consist of groups\n"
1642: "of letters and digits separated by periods (dots). Some of the more well\n"
1643: "known domains include \"com\", \"edu\", \"gov\", \"org\", \"net\", as well as domains\n"
1644: "covering a geographical area, such as the Chicago area \"chi.il.us\" domain.\n"
1645: "If you are not registered in a domain, or if you are uncertain about this\n"
1646: "question, simply press the <Enter> key to default to the UUCP pseudo-domain.\n\n"
1647: );
1648: for (;;) {
1649: cp = get_line("Please enter the domain name for this system: ");
1650: if (ok_name(cp, 'd'))
1651: break;
1652: }
1653: sprintf(cmd, "/bin/echo \"%s\" >/mnt/etc/domain", cp);
1654: sys(cmd, S_NONFATAL);
1655: }
1656: }
1657:
1658: /*
1659: * Hi there.
1660: */
1661: void
1662: welcome()
1663: {
1664: register char *s;
1665: int i;
1666:
1667: cls(0);
1668: printf(
1669: "\n\n\n\n\n\n\n\n"
1670: " The COHERENT System\n\n"
1671: " Copyright (c) 1982, 1992 by Mark Williams Company\n\n"
1672: " 60 Revere Drive, Northbrook, IL 60062\n\n"
1673: " 708-291-6700, 708-291-6750 (FAX)\n"
1674: "\n\n\n\n\n\n"
1675: );
1676:
1677: cls(1);
1678: printf(
1679: "Welcome to the COHERENT operating system!\n\n"
1680: "Your computer is now running COHERENT "
1681: #if _I386
1682: "386"
1683: #else
1684: "286"
1685: #endif
1686: " from the floppy disk.\n");
1687: if (update)
1688: printf(
1689: "This program will update your existing COHERENT 286 system to COHERENT 386.\n"
1690: "\n"
1691: "Be sure to read the section on \"Updating\" in the COHERENT 386 Release\n"
1692: "Notes prior to attempting this update!\n\n"
1693: "Please be patient and read the instructions on the screen carefully.\n"
1694: "\n"
1695: );
1696: else
1697: printf(
1698: "This program will install COHERENT onto your hard disk.\n"
1699: "\n"
1700: "If you are already running COHERENT on your hard disk, you must perform an\n"
1701: "update rather than a full installation. To do so, please REBOOT NOW and\n"
1702: "follow the detailed update instructions in the COHERENT release notes supplied\n"
1703: "with this release.\n"
1704: "\n"
1705: "You can interrupt installation at any time by typing <Ctrl-C>;\n"
1706: "then reboot and start the installation procedure again.\n"
1707: "Please be patient and read the instructions on the screen carefully.\n"
1708: "\n"
1709: );
1710: #if 0
1711: cls(1);
1712: printf(
1713: "If you do not know the BIOS parameters for your hard disk drive,\n"
1714: "please reset your computer NOW and enter \"dpb\" at the boot prompt.\n"
1715: "Copy the displayed parameter values for later reference, then reset\n"
1716: "again and restart installation by entering \"begin\" at the boot prompt.\n"
1717: );
1718: #endif
1719: cls(1);
1720: if (update)
1721: sys("/etc/kbdinstall -u", S_NONFATAL);
1722: else
1723: sys("/etc/kbdinstall -b", S_NONFATAL);
1724:
1725: cls(1);
1726: if (!update) {
1727: printf(
1728: "A card included with your distribution gives the serial number\n"
1729: "of your copy of COHERENT.\n"
1730: );
1731: for (i = 1; i <= 3; i++) {
1732: s = get_line("Type in the serial number from the card:");
1733: if (isserial(s))
1734: return;
1735: printf("Invalid serial number, please try again.\n");
1736: }
1737: fatal("invalid serial number");
1738: }
1739: }
1740:
1741: /*
1742: * Generate a partition table device name from a DEVICE entry name.
1743: * Return a pointer to the statically allocated name.
1744: * If flag and not one of the built-in AT device names,
1745: * the device is in /tmp/dev rather than /dev.
1746: */
1747: char *
1748: xname(i, flag) int i, flag;
1749: {
1750: static char xname[4+4+1+NAMESIZE]; /* e.g. "/tmp/dev/at0x" */
1751:
1752: sprintf(xname, "/tmp/dev/%s", devices[i].d_xname);
1753: return (flag && notflag(i, F_ATDEV)) ? xname : xname+4;
1754: }
1755:
1756: /* end of build.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.