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