wok annotate syslinux/stuff/iso2exe/iso2exe.c @ rev 18780

syslinux/isohybrib.exe: check EXE file
author Pascal Bellard <pascal.bellard@slitaz.org>
date Fri Jan 01 21:39:40 2016 +0100 (2016-01-01)
parents 4145d548de53
children d334cc1613e2
rev   line source
pascal@17451 1 #ifdef __TURBOC__
pascal@17451 2 #include <io.h>
pascal@17451 3 #endif
pascal@14150 4 #include <sys/types.h>
pascal@14150 5 #include <fcntl.h>
pascal@14150 6 #include <stdio.h>
pascal@17451 7 #include <stdlib.h>
pascal@17451 8 #include <string.h>
pascal@14268 9 #ifdef WIN32
pascal@14268 10 #include <windows.h>
pascal@14268 11 #endif
pascal@18775 12 #ifdef __MSDOS__
pascal@18775 13 #define ftruncate(a,b)
pascal@18775 14 #endif
pascal@18775 15 #ifdef __MINGW32__
pascal@18775 16 #define ftruncate chsize
pascal@18775 17 #endif
pascal@18775 18 #if !defined(__MSDOS__) && !defined(WIN32)
pascal@18775 19 #define O_BINARY 0
pascal@18775 20 #endif
pascal@17591 21 typedef unsigned char uint8_t;
pascal@17591 22 typedef unsigned long uint32_t;
pascal@14150 23 #include "iso2exe.h"
pascal@14150 24
pascal@18780 25 static int fd, forced, uninstall;
pascal@18780 26 static unsigned status = 1;
pascal@18775 27 static char *append, *initrd;
pascal@17489 28 static char tazlitoinfo[0x8000U - BOOTISOSZ];
pascal@14264 29 #define buffer tazlitoinfo
pascal@14264 30 #define BUFFERSZ 2048
pascal@17451 31 #define WORD(n) * (unsigned short *) (n)
pascal@17451 32 #define LONG(n) * (unsigned long *) (n)
pascal@14150 33
pascal@14150 34 static void readsector(unsigned long sector)
pascal@14150 35 {
pascal@14264 36 if (lseek(fd, sector * BUFFERSZ, SEEK_SET) == -1 ||
pascal@14268 37 read(fd, buffer, BUFFERSZ) != BUFFERSZ) {
pascal@17451 38 puts(bootiso+READSECTORERR);
pascal@14268 39 exit(1);
pascal@14268 40 }
pascal@14150 41 }
pascal@14150 42
pascal@18775 43 static unsigned long getcustomsector(void)
pascal@18775 44 {
pascal@18775 45 readsector(16UL);
pascal@18775 46 return 16UL + LONG(buffer + 80);
pascal@18775 47 }
pascal@18775 48
pascal@17810 49 static int skipmd5 = 0;
pascal@17591 50 #define ALIGN1
pascal@17591 51
pascal@17591 52 typedef struct {
pascal@17591 53 uint32_t l;
pascal@17591 54 uint32_t h;
pascal@17591 55 } uint64_t;
pascal@17591 56 static uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */
pascal@17591 57 static uint64_t total64; /* must be directly before hash[] */
pascal@17591 58 static uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */
pascal@17591 59
pascal@17591 60 //#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
pascal@17591 61 static uint32_t rotl32(uint32_t x, unsigned n)
pascal@17591 62 {
pascal@17591 63 return (x << n) | (x >> (32 - n));
pascal@17591 64 }
pascal@17591 65
pascal@17591 66 static void md5_process_block64(void);
pascal@17591 67
pascal@17591 68 /* Feed data through a temporary buffer.
pascal@17591 69 * The internal buffer remembers previous data until it has 64
pascal@17591 70 * bytes worth to pass on.
pascal@17591 71 */
pascal@17591 72 static void common64_hash(const void *buffer, size_t len)
pascal@17591 73 {
pascal@17591 74 unsigned bufpos = total64.l & 63;
pascal@17591 75
pascal@17591 76 total64.l += len; if (total64.l < len) total64.h++;
pascal@17591 77
pascal@17591 78 while (1) {
pascal@17591 79 unsigned remaining = 64 - bufpos;
pascal@17591 80 if (remaining > len)
pascal@17591 81 remaining = len;
pascal@17591 82 /* Copy data into aligned buffer */
pascal@17591 83 memcpy(wbuffer + bufpos, buffer, remaining);
pascal@17591 84 len -= remaining;
pascal@17591 85 buffer = (const char *)buffer + remaining;
pascal@17591 86 bufpos += remaining;
pascal@17591 87 /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */
pascal@17591 88 bufpos -= 64;
pascal@17591 89 if (bufpos != 0)
pascal@17591 90 break;
pascal@17591 91 /* Buffer is filled up, process it */
pascal@17591 92 md5_process_block64();
pascal@17591 93 /*bufpos = 0; - already is */
pascal@17591 94 }
pascal@17591 95 }
pascal@17591 96
pascal@17591 97 /* Process the remaining bytes in the buffer */
pascal@17591 98 static void common64_end(void)
pascal@17591 99 {
pascal@17591 100 unsigned bufpos = total64.l & 63;
pascal@17591 101 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
pascal@17591 102 wbuffer[bufpos++] = 0x80;
pascal@17591 103
pascal@17591 104 /* This loop iterates either once or twice, no more, no less */
pascal@17591 105 while (1) {
pascal@17591 106 unsigned remaining = 64 - bufpos;
pascal@17591 107 memset(wbuffer + bufpos, 0, remaining);
pascal@17591 108 /* Do we have enough space for the length count? */
pascal@17591 109 if (remaining >= 8) {
pascal@17591 110 /* Store the 64-bit counter of bits in the buffer */
pascal@17591 111 //uint64_t t = total64 << 3;
pascal@17591 112 uint32_t *t = (uint32_t *) (&wbuffer[64 - 8]);
pascal@17591 113 /* wbuffer is suitably aligned for this */
pascal@17591 114 //*(uint64_t *) (&wbuffer[64 - 8]) = t;
pascal@17591 115 t[0] = total64.l << 3;
pascal@17591 116 t[1] = (total64.h << 3) | (total64.l >> 29);
pascal@17591 117 }
pascal@17591 118 md5_process_block64();
pascal@17591 119 if (remaining >= 8)
pascal@17591 120 break;
pascal@17591 121 bufpos = 0;
pascal@17591 122 }
pascal@17591 123 }
pascal@17591 124
pascal@17591 125 /* These are the four functions used in the four steps of the MD5 algorithm
pascal@17591 126 * and defined in the RFC 1321. The first function is a little bit optimized
pascal@17591 127 * (as found in Colin Plumbs public domain implementation).
pascal@17591 128 * #define FF(b, c, d) ((b & c) | (~b & d))
pascal@17591 129 */
pascal@17591 130 #undef FF
pascal@17591 131 #undef FG
pascal@17591 132 #undef FH
pascal@17591 133 #undef FI
pascal@17591 134 #define FF(b, c, d) (d ^ (b & (c ^ d)))
pascal@17591 135 #define FG(b, c, d) FF(d, b, c)
pascal@17591 136 #define FH(b, c, d) (b ^ c ^ d)
pascal@17591 137 #define FI(b, c, d) (c ^ (b | ~d))
pascal@17591 138
pascal@17591 139 /* Hash a single block, 64 bytes long and 4-byte aligned */
pascal@17591 140 static void md5_process_block64(void)
pascal@17591 141 {
pascal@17591 142 uint32_t *words = (void*) wbuffer;
pascal@17591 143 uint32_t A = hash[0];
pascal@17591 144 uint32_t B = hash[1];
pascal@17591 145 uint32_t C = hash[2];
pascal@17591 146 uint32_t D = hash[3];
pascal@17591 147
pascal@17591 148 const uint32_t *pc;
pascal@17591 149 const char *pp;
pascal@17591 150 const char *ps;
pascal@17591 151 int i;
pascal@17591 152 uint32_t temp;
pascal@17591 153
pascal@17591 154
pascal@17591 155 pc = C_array;
pascal@17591 156 pp = P_array;
pascal@17591 157 ps = S_array - 4;
pascal@17591 158
pascal@17591 159 for (i = 0; i < 64; i++) {
pascal@17591 160 if ((i & 0x0f) == 0)
pascal@17591 161 ps += 4;
pascal@17591 162 temp = A;
pascal@17591 163 switch (i >> 4) {
pascal@17591 164 case 0:
pascal@17591 165 temp += FF(B, C, D);
pascal@17591 166 break;
pascal@17591 167 case 1:
pascal@17591 168 temp += FG(B, C, D);
pascal@17591 169 break;
pascal@17591 170 case 2:
pascal@17591 171 temp += FH(B, C, D);
pascal@17591 172 break;
pascal@17591 173 case 3:
pascal@17591 174 temp += FI(B, C, D);
pascal@17591 175 }
pascal@17591 176 temp += words[(int) (*pp++)] + *pc++;
pascal@17591 177 temp = rotl32(temp, ps[i & 3]);
pascal@17591 178 temp += B;
pascal@17591 179 A = D;
pascal@17591 180 D = C;
pascal@17591 181 C = B;
pascal@17591 182 B = temp;
pascal@17591 183 }
pascal@17591 184 /* Add checksum to the starting values */
pascal@17591 185 hash[0] += A;
pascal@17591 186 hash[1] += B;
pascal@17591 187 hash[2] += C;
pascal@17591 188 hash[3] += D;
pascal@17591 189
pascal@17591 190 }
pascal@17591 191 #undef FF
pascal@17591 192 #undef FG
pascal@17591 193 #undef FH
pascal@17591 194 #undef FI
pascal@17591 195
pascal@17591 196 /* Initialize structure containing state of computation.
pascal@17591 197 * (RFC 1321, 3.3: Step 3)
pascal@17591 198 */
pascal@17591 199 static void md5_begin(void)
pascal@17591 200 {
pascal@17591 201 hash[0] = 0x67452301;
pascal@17591 202 hash[1] = 0xefcdab89;
pascal@17591 203 hash[2] = 0x98badcfe;
pascal@17591 204 hash[3] = 0x10325476;
pascal@17591 205 total64.l = total64.h = 0;
pascal@17591 206 }
pascal@17591 207
pascal@17591 208 /* Used also for sha1 and sha256 */
pascal@17591 209 #define md5_hash common64_hash
pascal@17591 210
pascal@17591 211 /* Process the remaining bytes in the buffer and put result from CTX
pascal@17591 212 * in first 16 bytes following RESBUF. The result is always in little
pascal@17591 213 * endian byte order, so that a byte-wise output yields to the wanted
pascal@17591 214 * ASCII representation of the message digest.
pascal@17591 215 */
pascal@17591 216 #define md5_end common64_end
pascal@17591 217
pascal@18775 218 static int writenhash(void *buffer, size_t len)
pascal@18775 219 {
pascal@18775 220 md5_hash(buffer, len);
pascal@18775 221 return write(fd, buffer, len);
pascal@18775 222 }
pascal@18775 223
pascal@17591 224 static void md5sum(void)
pascal@17591 225 {
pascal@17591 226 unsigned long sectors = 0;
pascal@17591 227 int count;
pascal@17591 228
pascal@17591 229 lseek(fd, 32768UL, SEEK_SET);
pascal@17591 230
pascal@17591 231 md5_begin();
pascal@17591 232 while ((count = read(fd, buffer, BUFFERSZ)) > 0) {
pascal@17591 233 if (sectors == 0)
pascal@17591 234 sectors = LONG(buffer + 80);
pascal@17591 235 md5_hash(buffer, count);
pascal@17591 236 if (--sectors == 0)
pascal@17591 237 break;
pascal@17591 238 }
pascal@17591 239
pascal@17591 240 if (count < 0)
pascal@17591 241 return;
pascal@17591 242
pascal@17591 243 md5_end();
pascal@17591 244
pascal@17591 245 lseek(fd, 32752UL, SEEK_SET);
pascal@17591 246 write(fd, hash, 16);
pascal@17591 247 memcpy(bootiso + BOOTISOSZ - 16, hash, 16);
pascal@17591 248 }
pascal@17591 249
pascal@17591 250 static unsigned chksum(unsigned start, unsigned stop)
pascal@17591 251 {
pascal@17591 252 unsigned i, n = 0;
pascal@17591 253
pascal@17591 254 lseek(fd, 0UL /* (unsigned long) (start / BUFFERSZ) */, SEEK_SET);
pascal@17591 255 while (1) {
pascal@17591 256 if (read(fd, buffer, BUFFERSZ) != BUFFERSZ)
pascal@17591 257 return 0;
pascal@17591 258 for (i = start % BUFFERSZ; i < BUFFERSZ; i += 2, start += 2) {
pascal@17591 259 if (start >= stop)
pascal@17591 260 return - n;
pascal@17591 261 n += WORD(buffer + i);
pascal@17591 262 }
pascal@17591 263 }
pascal@17591 264 }
pascal@17591 265
pascal@18779 266 static void clear_config(unsigned i)
pascal@18779 267 {
pascal@18779 268 for (;i % 512; i++) {
pascal@18779 269 /* clear custom config */
pascal@18779 270 write(fd, buffer + 2048, 2048);
pascal@18779 271 }
pascal@18779 272 }
pascal@18779 273
pascal@17451 274 static unsigned install(char *filename)
pascal@14150 275 {
pascal@14150 276 #define heads 64
pascal@14150 277 #define sectors 32
pascal@17489 278 #define partition (446+16)
pascal@17451 279 #define trksz (512UL * heads * sectors)
pascal@14150 280 unsigned long size, catalog, lba;
pascal@14261 281 int cylinders, i, j, isohybrid;
pascal@14150 282 unsigned n;
pascal@18775 283 #ifdef __MSDOS__
pascal@14268 284 for (bootiso = (char *) install;
pascal@17451 285 bootiso[0] != 'M' || bootiso[1] != 'Z' || bootiso[2] != '\xEB';
pascal@17451 286 bootiso++) if (bootiso < (char *) install) {
pascal@17451 287 bootiso = "No bootiso data";
pascal@17451 288 return 0;
pascal@17451 289 }
pascal@14150 290 #endif
pascal@14268 291 if (!filename)
pascal@17451 292 return USAGE;
pascal@14268 293 fd = open(filename,O_RDWR|O_BINARY);
pascal@14150 294 if (fd == -1)
pascal@17451 295 return OPENERR;
pascal@14150 296
pascal@17591 297 if (uninstall) {
pascal@17591 298 struct { char check[sizeof(tazlitoinfo) - BUFFERSZ - 1024]; };
pascal@17591 299 readsector(0UL);
pascal@18775 300 n = BUFFERSZ; /* fill with zeros */
pascal@17591 301 if (WORD(buffer) == 23117) {
pascal@18775 302 /* restore isolinux hybrid boot */
pascal@17810 303 readsector((unsigned long) buffer[417]);
pascal@18775 304 n = 0; /* fill with hybrid boot */
pascal@17591 305 }
pascal@17591 306 lseek(fd, 0UL, SEEK_SET);
pascal@17591 307 for (i = 0; i < 32; i++, n = BUFFERSZ) {
pascal@17591 308 write(fd, buffer + n, 1024);
pascal@17591 309 }
pascal@18775 310 i = getcustomsector();
pascal@18775 311 lseek(fd, i * 2048UL, SEEK_SET);
pascal@18779 312 clear_config(i);
pascal@18775 313 ftruncate(fd, i * 2048UL);
pascal@17591 314 close(fd);
pascal@17591 315 status = 0;
pascal@17591 316 return UNINSTALLMSG;
pascal@17591 317 }
pascal@17591 318
pascal@18780 319 do {
pascal@18780 320 readsector(0UL);
pascal@18780 321 status = ALREADYEXEERR;
pascal@18780 322 if (buffer[0] == 'M' && buffer[1] == 'Z')
pascal@18780 323 break;
pascal@18780 324
pascal@18780 325 /* Install hybridiso boot sector */
pascal@18780 326 readsector(17UL);
pascal@18780 327 status = ELTORITOERR;
pascal@18780 328 if (strncmp(buffer+7, bootiso+ELTORITOERR+ELTORITOOFS, 23))
pascal@18780 329 break;
pascal@18780 330 catalog = LONG(buffer + 71);
pascal@18780 331 readsector(catalog);
pascal@18780 332 status = CATALOGERR;
pascal@18780 333 if (LONG(buffer) != 1 || LONG(buffer + 30) != 0x88AA55UL)
pascal@18780 334 break;
pascal@18780 335 lba = LONG(buffer + 40);
pascal@18780 336 readsector(lba);
pascal@18780 337 status = HYBRIDERR;
pascal@18780 338 if (LONG(buffer + 64) != 1886961915UL)
pascal@18780 339 break;
pascal@18780 340 isohybrid = bootiso[417] * 512;
pascal@18780 341 LONG(bootiso + isohybrid + 432) = lba * 4;
pascal@18780 342 LONG(bootiso + isohybrid + 440) = rand();
pascal@18780 343 LONG(bootiso + isohybrid + partition) = 0x10080UL;
pascal@18780 344 WORD(bootiso + isohybrid + 510) = 0xAA55U;
pascal@18780 345 #if 0
pascal@18780 346 size = lseek(fd, 0UL, SEEK_END);
pascal@18780 347 size += 0x000FFFFFUL;
pascal@18780 348 size &= 0xFFF00000UL;
pascal@18780 349 #else
pascal@18780 350 for (size = 0x000FFFFFUL; /* 1M - 1 */
pascal@18780 351 read(fd, tazlitoinfo, 1024) == 1024;
pascal@18780 352 size += 1024);
pascal@18780 353 size &= 0xFFF00000UL; /* round */
pascal@18780 354 #endif
pascal@18780 355 cylinders = (size >> 20) - 1;
pascal@18780 356 bootiso[isohybrid + partition + 4] = 23; /* "Windows hidden IFS" */
pascal@18780 357 bootiso[isohybrid + partition + 5] = heads - 1;
pascal@18780 358 bootiso[isohybrid + partition + 6] = ((cylinders & 0x300) >> 2) + sectors;
pascal@18780 359 bootiso[isohybrid + partition + 7] = cylinders & 0xFF;
pascal@18780 360 LONG(bootiso + isohybrid + partition + 8) = 0;
pascal@18780 361 LONG(bootiso + isohybrid + partition + 12) = (size >> 9);
pascal@18780 362
pascal@18780 363 /* Copy the partition table */
pascal@18780 364 memcpy(bootiso + 0x1BE, bootiso + isohybrid + 0x1BE, 66);
pascal@18780 365 status = 0;
pascal@18780 366 } while (0);
pascal@18780 367
pascal@18780 368 if (forced == 0 && status)
pascal@18780 369 return status;
pascal@18780 370
pascal@18780 371 status = 1;
pascal@18775 372 if (append || initrd) {
pascal@18775 373 unsigned long pos = getcustomsector() * 2048UL;
pascal@18775 374 lseek(fd, pos, SEEK_SET);
pascal@18779 375 clear_config(pos);
pascal@18779 376 lseek(fd, pos, SEEK_SET);
pascal@18775 377 write(fd, "#!boot 00000000000000000000000000000000\n", 40);
pascal@18775 378 md5_begin();
pascal@18775 379 if (append) {
pascal@18775 380 writenhash("append=", 7);
pascal@18775 381 writenhash(append, strlen(append));
pascal@18775 382 writenhash("\n", 1);
pascal@18775 383 }
pascal@18775 384 if (initrd) {
pascal@18775 385 char number[16], *p;
pascal@18775 386 unsigned long end, x;
pascal@18775 387 int data = open(initrd,O_RDONLY|O_BINARY);
pascal@18775 388 if (data == -1)
pascal@18775 389 return OPENINITRDERR;
pascal@18775 390 for (end = 0;; end += i) {
pascal@18775 391 i = read(data, buffer, BUFFERSZ);
pascal@18775 392 if (i <= 0)
pascal@18775 393 break;
pascal@18775 394 }
pascal@18775 395 p = number + sizeof(number) -1;
pascal@18775 396 x = end; *p-- = '\n';
pascal@18775 397 do {
pascal@18775 398 *p-- = '0' + (x % 10);
pascal@18775 399 x /= 10;
pascal@18775 400 } while (x);
pascal@18775 401 if (*++p != '0') {
pascal@18775 402 writenhash("initrd:", 7);
pascal@18775 403 i = number - p + sizeof(number);
pascal@18775 404 writenhash(p, i);
pascal@18775 405 lseek(data, 0UL, SEEK_SET);
pascal@18775 406 do {
pascal@18775 407 i = read(data, buffer, BUFFERSZ);
pascal@18775 408 if (i <= 0)
pascal@18775 409 break;
pascal@18775 410 if (i > end)
pascal@18775 411 i = end;
pascal@18775 412 writenhash(buffer, i);
pascal@18775 413 end -= i;
pascal@18775 414 } while (end != 0);
pascal@18775 415 }
pascal@18775 416 close(data);
pascal@18775 417 }
pascal@18775 418 md5_end();
pascal@18775 419 {
pascal@18779 420 static char h[] = "0123456789abcdef";
pascal@18775 421 char string[32], *s = string + 30;
pascal@18775 422 unsigned char *p = (void *) hash;
pascal@18775 423
pascal@18775 424 lseek(fd, 7 + pos, SEEK_SET);
pascal@18775 425 for (p += 15; s >= string; p--, s -= 2) {
pascal@18775 426 s[1] = h[ *p & 15 ];
pascal@18775 427 s[0] = h[ *p >> 4 ];
pascal@18775 428 }
pascal@18775 429 write(fd, string, 32);
pascal@18775 430 }
pascal@18775 431 }
pascal@18775 432
pascal@17451 433 /* Install iso2exe boot sector */
pascal@17810 434 LONG(bootiso + 440) = time(NULL);
pascal@14150 435
pascal@17451 436 /* read tazlito flavor data */
pascal@14261 437 lseek(fd, 1024UL, SEEK_SET);
pascal@14261 438 read(fd, tazlitoinfo, sizeof(tazlitoinfo));
pascal@14261 439
pascal@17451 440 /* Update iso image */
pascal@17810 441 n = (bootiso[417] + 1) * 512;
pascal@14151 442 lseek(fd, 0UL, SEEK_SET);
pascal@17451 443 write(fd, bootiso, n); /* EXE/PE + isohybrid mbr */
pascal@17489 444 write(fd, tazlitoinfo, sizeof(tazlitoinfo));
pascal@17451 445 write(fd, bootiso + n, BOOTISOSZ - n); /* COM + rootfs + EXE/DOS */
pascal@14150 446
pascal@17810 447 /* Compute the boot checksums */
pascal@17810 448 if (!skipmd5) {
pascal@17591 449 puts(bootiso + MD5MSG);
pascal@17591 450 md5sum();
pascal@17591 451 lseek(fd, 0UL, SEEK_SET);
pascal@17591 452 write(fd, bootiso, 512);
pascal@17810 453 n = WORD(bootiso + 2) - 512*(WORD(bootiso + 4) - 1);
pascal@17810 454 WORD(bootiso + 18) = chksum(0, (unsigned short) n) - 1;
pascal@17591 455 }
pascal@17810 456 lseek(fd, 0UL, SEEK_SET);
pascal@17810 457 write(fd, bootiso, 512);
pascal@14150 458 close(fd);
pascal@14268 459 status = 0;
pascal@17451 460 return SUCCESSMSG;
pascal@14150 461 }
pascal@14268 462
pascal@14268 463 int main(int argc, char *argv[])
pascal@14268 464 {
pascal@17591 465 int i;
pascal@18775 466 char *s;
pascal@18775 467
pascal@18775 468 while (argc > 2) {
pascal@18775 469 s = argv[1];
pascal@18775 470 if (*s != '-') break;
pascal@18775 471 while (*s == '-') s++;
pascal@18775 472 switch (*s | 0x20) {
pascal@18775 473 case 'a' : append=argv[2]; break;
pascal@18775 474 case 'i' : initrd=argv[2]; break;
pascal@18775 475 }
pascal@18775 476 argv += 2;
pascal@18775 477 argc -= 2;
pascal@18775 478 }
pascal@17591 479 for (i = 2; i < argc; i++) {
pascal@17591 480 char *s = argv[i];
pascal@17591 481 while ((unsigned)(*s - '-') <= ('/' - '-')) s++;
pascal@17591 482 switch (*s | 0x20) {
pascal@17591 483 case 'f' : forced++; break;
pascal@17810 484 case 'q' : skipmd5++; break;
pascal@17591 485 case 'u' : uninstall++; break;
pascal@17591 486 }
pascal@17591 487 }
pascal@17451 488 puts(bootiso + install(argv[1]));
pascal@16055 489 if (status > 1)
pascal@17451 490 puts(bootiso + FORCEMSG);
pascal@14268 491 #ifdef WIN32
pascal@14268 492 Sleep(2000);
pascal@14268 493 #endif
pascal@14268 494 return status;
pascal@14268 495 }