148905Srnordier/*
248905Srnordier * Copyright (c) 1999 Global Technology Associates, Inc.
348905Srnordier * All rights reserved.
448905Srnordier *
548905Srnordier * Redistribution and use in source and binary forms, with or without
648905Srnordier * modification, are permitted provided that the following conditions
748905Srnordier * are met:
848905Srnordier * 1. Redistributions of source code must retain the above copyright
948905Srnordier *    notice, this list of conditions and the following disclaimer.
1048905Srnordier * 2. Redistributions in binary form must reproduce the above copyright
1148905Srnordier *    notice, this list of conditions and the following disclaimer in the
1248905Srnordier *    documentation and/or other materials provided with the distribution.
1348905Srnordier *
1448905Srnordier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
1548905Srnordier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1648905Srnordier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1748905Srnordier * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
1848905Srnordier * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
1948905Srnordier * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
2048905Srnordier * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2148905Srnordier * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2248905Srnordier * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
2348905Srnordier * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
2448905Srnordier * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2548905Srnordier */
2648905Srnordier
2748905Srnordier#ifndef lint
2848905Srnordierstatic const char rcsid[] =
2950479Speter  "$FreeBSD$";
3048905Srnordier#endif /* not lint */
3148905Srnordier
3248905Srnordier#include <sys/types.h>
3348905Srnordier#include <err.h>
3464214Skris#include <paths.h>
3548905Srnordier#include <stdio.h>
3648905Srnordier#include <stdlib.h>
3748905Srnordier#include <string.h>
3848905Srnordier#include <unistd.h>
3948905Srnordier
4048905Srnordier#include "kgzip.h"
4148905Srnordier
4248905Srnordier#define FN_SRC		0	/* Filename: source */
4348905Srnordier#define FN_OBJ		1	/* Filename: relocatable */
4448905Srnordier#define FN_KGZ		2	/* Filename: executable */
4548905Srnordier#define FN_CNT		3	/* Number of filenames */
4648905Srnordier
4748905Srnordier#define SFX_OBJ 	".o"	/* Filename suffix: relocatable */
4848905Srnordier#define SFX_KGZ 	".kgz"	/* Filename suffix: executable */
4948905Srnordier#define SFX_MAX 	5	/* Size of larger filename suffix */
5048905Srnordier
5148905Srnordierconst char *loader = "/usr/lib/kgzldr.o";  /* Default loader */
5268313Srnordierint format;			/* Output format */
5348905Srnordier
5456128Skrischar *tname;			/* Name of temporary file */
5548905Srnordier
5648905Srnordierstatic void cleanup(void);
5748905Srnordierstatic void mk_fn(int, const char *, const char *, char *[]);
5848905Srnordierstatic void usage(void);
5948905Srnordier
6048905Srnordier/*
6148905Srnordier * Compress a kernel.
6248905Srnordier */
6348905Srnordierint
6448905Srnordiermain(int argc, char *argv[])
6548905Srnordier{
6648905Srnordier    static char *fn[FN_CNT];
6748905Srnordier    struct kgz_hdr kh;
6848905Srnordier    const char *output;
6964214Skris    char *tmpdir;
7048905Srnordier    int cflag, vflag, c;
7148905Srnordier
7264214Skris    tmpdir = getenv("TMPDIR");
7368966Srnordier    if (asprintf(&tname, "%s/kgzXXXXXXXXXX",
7468966Srnordier		 tmpdir == NULL ? _PATH_TMP : tmpdir) == -1)
7568313Srnordier	errx(1, "Out of memory");
7648905Srnordier    output = NULL;
7748905Srnordier    cflag = vflag = 0;
7868313Srnordier    while ((c = getopt(argc, argv, "cvf:l:o:")) != -1)
7948905Srnordier	switch (c) {
8048905Srnordier	case 'c':
8148905Srnordier	    cflag = 1;
8248905Srnordier	    break;
8348905Srnordier	case 'v':
8448905Srnordier	    vflag = 1;
8548905Srnordier	    break;
8668313Srnordier	case 'f':
8768313Srnordier	    if (!strcmp(optarg, "aout"))
8868313Srnordier		format = F_AOUT;
8968313Srnordier	    else if (!strcmp(optarg, "elf"))
9068313Srnordier		format = F_ELF;
9168313Srnordier	    else
9268313Srnordier		errx(1, "%s: Unknown format", optarg);
9368313Srnordier	    break;
9448905Srnordier	case 'l':
9548905Srnordier	    loader = optarg;
9648905Srnordier	    break;
9748905Srnordier	case 'o':
9848905Srnordier	    output = optarg;
9948905Srnordier	    break;
10048905Srnordier	default:
10148905Srnordier	    usage();
10248905Srnordier	}
10348905Srnordier    argc -= optind;
10448905Srnordier    argv += optind;
10548905Srnordier    if (argc != 1)
10648905Srnordier	usage();
10748905Srnordier    atexit(cleanup);
10848905Srnordier    mk_fn(cflag, *argv, output, fn);
10948905Srnordier    memset(&kh, 0, sizeof(kh));
11068313Srnordier    if (fn[FN_SRC]) {
11168313Srnordier	if (!format)
11268313Srnordier	    format = F_ELF;
11348905Srnordier	kgzcmp(&kh, fn[FN_SRC], fn[FN_OBJ]);
11468313Srnordier    }
11548905Srnordier    if (!cflag)
11648905Srnordier	kgzld(&kh, fn[FN_OBJ], fn[FN_KGZ]);
11748905Srnordier    if (vflag)
11848905Srnordier	printf("dload=%#x dsize=%#x isize=%#x entry=%#x nsize=%#x\n",
11948905Srnordier	       kh.dload, kh.dsize, kh.isize, kh.entry, kh.nsize);
12048905Srnordier    return 0;
12148905Srnordier}
12248905Srnordier
12348905Srnordier/*
12448905Srnordier * Clean up after processing.
12548905Srnordier */
12648905Srnordierstatic void
12748905Srnordiercleanup(void)
12848905Srnordier{
12948905Srnordier    if (tname)
13048905Srnordier	unlink(tname);
13148905Srnordier}
13248905Srnordier
13348905Srnordier/*
13448905Srnordier * Make the required filenames.
13548905Srnordier */
13648905Srnordierstatic void
13748905Srnordiermk_fn(int cflag, const char *f1, const char *f2, char *fn[])
13848905Srnordier{
13948905Srnordier    const char *p, *s;
14048905Srnordier    size_t n;
14156128Skris    int i, fd;
14248905Srnordier
14348905Srnordier    i = 0;
14448905Srnordier    s = strrchr(f1, 0);
14548905Srnordier    n = sizeof(SFX_OBJ) - 1;
14648905Srnordier    if ((size_t)(s - f1) > n && !memcmp(s - n, SFX_OBJ, n)) {
14748905Srnordier	s -= n;
14848905Srnordier	i++;
14948905Srnordier    }
15048905Srnordier    fn[i++] = (char *)f1;
15148905Srnordier    if (i == FN_OBJ && !cflag) {
15256128Skris	if ((fd = mkstemp(tname)) == -1)
15348905Srnordier	    err(1, NULL);
15456128Skris	close(fd);
155116222Sobrien	fn[i++] = tname;
15648905Srnordier    }
15748905Srnordier    if (!(fn[i] = (char *)f2)) {
15848905Srnordier	p = (p = strrchr(f1, '/')) ? p + 1 : f1;
15948905Srnordier	n = (size_t)(s - p);
16048905Srnordier	if (!(fn[i] = malloc(n + SFX_MAX)))
16148905Srnordier	    err(1, NULL);
16248905Srnordier	memcpy(fn[i], p, n);
16348905Srnordier	strcpy(fn[i] + n, i == FN_OBJ ? SFX_OBJ : SFX_KGZ);
16448905Srnordier    }
16548905Srnordier}
16648905Srnordier
16748905Srnordier/*
16848905Srnordier * Display usage information.
16948905Srnordier */
17048905Srnordierstatic void
17148905Srnordierusage(void)
17248905Srnordier{
17348905Srnordier    fprintf(stderr,
174112048Sru      "usage: kgzip [-cv] [-f format] [-l loader] [-o output] file\n");
17548905Srnordier    exit(1);
17648905Srnordier}
177