summaryrefslogtreecommitdiff
path: root/usr/src/lib/libpkg/common/pkgtrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libpkg/common/pkgtrans.c')
-rw-r--r--usr/src/lib/libpkg/common/pkgtrans.c592
1 files changed, 24 insertions, 568 deletions
diff --git a/usr/src/lib/libpkg/common/pkgtrans.c b/usr/src/lib/libpkg/common/pkgtrans.c
index a717360580..cfc4009b08 100644
--- a/usr/src/lib/libpkg/common/pkgtrans.c
+++ b/usr/src/lib/libpkg/common/pkgtrans.c
@@ -20,6 +20,10 @@
*/
/*
+ * Copyright (c) 2017 Peter Tribble.
+ */
+
+/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,11 +50,6 @@
#include <dirent.h>
#include <signal.h>
#include <devmgmt.h>
-#include <openssl/pkcs12.h>
-#include <openssl/x509.h>
-#include <openssl/pkcs7.h>
-#include <openssl/err.h>
-#include <openssl/pem.h>
#include <note.h>
#include "pkginfo.h"
#include "pkgstrct.h"
@@ -58,9 +57,7 @@
#include "pkgdev.h"
#include "pkglib.h"
#include "pkglibmsgs.h"
-#include "keystore.h"
#include "pkglocale.h"
-#include "pkgerr.h"
extern char *pkgdir; /* pkgparam.c */
@@ -113,12 +110,9 @@ static int cat_and_count(struct dm_buf *, char *);
static int ckoverwrite(char *dir, char *inst, int options);
static int pkgxfer(char *srcinst, int options);
-static int wdsheader(struct dm_buf *, char *src, char *device,
- char **pkg, PKCS7 *);
+static int wdsheader(struct dm_buf *, char *device, char **pkg);
static struct dm_buf *genheader(char *, char **);
-static int dump_hdr_and_pkgs(BIO *, struct dm_buf *, char **);
-
extern int ds_fd; /* open file descriptor for data stream WHERE? */
static char *root_names[] = {
@@ -170,8 +164,7 @@ pkghead(char *device)
}
/* check for datastream */
- if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY,
- NULL, NULL)) {
+ if (n = pkgtrans(device, (char *)0, allpkg, PT_SILENT|PT_INFO_ONLY)) {
cleanup();
return (n);
}
@@ -239,90 +232,12 @@ rd_map_size(FILE *fp, int *npts, int *maxpsz, int *cmpsize)
/* will return 0, 1, 3, or 99 */
static int
-_pkgtrans(char *device1, char *device2, char **pkg, int options,
- keystore_handle_t keystore, char *keystore_alias)
+_pkgtrans(char *device1, char *device2, char **pkg, int options)
{
- BIO *p7_bio = NULL;
- EVP_PKEY *privkey = NULL;
- PKCS7 *sec_pkcs7 = NULL;
- PKCS7_SIGNER_INFO *sec_signerinfo = NULL;
- PKG_ERR *err;
- STACK_OF(X509) *cacerts = NULL;
- STACK_OF(X509) *clcerts = NULL;
- STACK_OF(X509) *sec_chain = NULL;
- X509 *pubcert = NULL;
- boolean_t making_sig = B_FALSE;
char *src, *dst;
int errflg, i, n;
struct dm_buf *hdr;
- making_sig = (keystore != NULL) ? B_TRUE : B_FALSE;
-
- if (making_sig) {
-
- /* new error object */
- err = pkgerr_new();
-
- /* find matching cert and key */
- if (find_key_cert_pair(err, keystore,
- keystore_alias, &privkey, &pubcert) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /* get CA certificates */
- if (find_ca_certs(err, keystore, &cacerts) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /* get CL (aka "chain") certificates */
- if (find_cl_certs(err, keystore, &clcerts) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /* initialize PKCS7 object to be filled in later */
- sec_pkcs7 = PKCS7_new();
- (void) PKCS7_set_type(sec_pkcs7, NID_pkcs7_signed);
- sec_signerinfo = PKCS7_add_signature(sec_pkcs7,
- pubcert, privkey, EVP_sha1());
-
- if (sec_signerinfo == NULL) {
- progerr(gettext(ERR_SEC), keystore_alias);
- ERR_print_errors_fp(stderr);
- pkgerr_free(err);
- return (1);
- }
-
- /* add signer cert into signature */
- (void) PKCS7_add_certificate(sec_pkcs7, pubcert);
-
- /* attempt to resolve cert chain starting at the signer cert */
- if (get_cert_chain(err, pubcert, clcerts, cacerts,
- &sec_chain) != 0) {
- pkgerr(err);
- pkgerr_free(err);
- return (1);
- }
-
- /*
- * add the verification chain of certs into the signature.
- * The first cert is the user cert, which we don't need,
- * since it's baked in already, so skip it
- */
- for (i = 1; i < sk_X509_num(sec_chain); i++) {
- (void) PKCS7_add_certificate(sec_pkcs7,
- sk_X509_value(sec_chain, i));
- }
-
- pkgerr_free(err);
- err = NULL;
- }
-
if (signal_received > 0) {
return (1);
}
@@ -417,17 +332,6 @@ _pkgtrans(char *device1, char *device2, char **pkg, int options,
logerr(pkg_gt(MSG_TWODSTREAM));
return (1);
}
- } else {
- /*
- * output device isn't a stream. If we're making a signed
- * package, then fail, since we can't make signed,
- * non-stream pkgs
- */
- if (making_sig) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(ERR_CANTSIGN));
- return (1);
- }
}
if ((srcdev.dirname && dstdev.dirname) &&
@@ -531,59 +435,13 @@ _pkgtrans(char *device1, char *device2, char **pkg, int options,
cleanup();
return (1);
}
- if (making_sig) {
- /* start up signature data stream */
- (void) PKCS7_content_new(sec_pkcs7, NID_pkcs7_data);
- (void) PKCS7_set_detached(sec_pkcs7, 1);
- p7_bio = PKCS7_dataInit(sec_pkcs7, NULL);
-
- /*
- * Here we generate all the data that will go into
- * the package, and send it through the signature
- * generator, essentially calculating the signature
- * of the entire package so we can place it in the
- * header. Otherwise we'd have to place it at the end
- * of the pkg, which would break the ABI
- */
- if (!(options & PT_SILENT)) {
- (void) fprintf(stderr, pkg_gt(MSG_SIGNING),
- get_subject_display_name(pubcert));
- }
- if (dump_hdr_and_pkgs(p7_bio, hdr, pkg) != 0) {
- progerr(gettext(ERR_NOGEN));
- logerr(pkg_gt(MSG_GETVOL));
- cleanup();
- return (1);
-
- }
-
- BIO_flush(p7_bio);
- /*
- * now generate PKCS7 signature
- */
- if (!PKCS7_dataFinal(sec_pkcs7, p7_bio)) {
- progerr(gettext(ERR_NOGEN));
- logerr(pkg_gt(MSG_GETVOL));
- cleanup();
- return (1);
- }
-
- (void) BIO_free(p7_bio);
- }
-
- /* write out header to stream, which includes signature */
- if (wdsheader(hdr, src, ods_name, pkg, sec_pkcs7)) {
+ /* write out header to stream */
+ if (wdsheader(hdr, ods_name, pkg)) {
cleanup();
return (1);
}
- if (sec_pkcs7 != NULL) {
- /* nuke in-memory signature for safety */
- PKCS7_free(sec_pkcs7);
- sec_pkcs7 = NULL;
- }
-
ds_volno = 1; /* number of volumes in datastream */
pinput = hdrbuf.text_buffer;
/* skip past first line in header */
@@ -630,8 +488,7 @@ _pkgtrans(char *device1, char *device2, char **pkg, int options,
}
int
-pkgtrans(char *device1, char *device2, char **pkg, int options,
- keystore_handle_t keystore, char *keystore_alias)
+pkgtrans(char *device1, char *device2, char **pkg, int options)
{
int r;
struct sigaction nact;
@@ -683,7 +540,7 @@ pkgtrans(char *device1, char *device2, char **pkg, int options,
* perform the package translation
*/
- r = _pkgtrans(device1, device2, pkg, options, keystore, keystore_alias);
+ r = _pkgtrans(device1, device2, pkg, options);
/*
* reset signal handlers
@@ -922,20 +779,12 @@ genheader(char *src, char **pkg)
}
static int
-wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
+wdsheader(struct dm_buf *hdr, char *device, char **pkg)
{
- FILE *fp;
- char path[PATH_MAX], tmp_entry[ENTRY_MAX],
- tmp_file[L_tmpnam+1];
- char srcpath[PATH_MAX];
+ char tmp_entry[ENTRY_MAX], tmp_file[L_tmpnam+1];
int i, n;
int list_fd;
int block_cnt;
- int len;
- char cwd[MAXPATHLEN + 1];
- boolean_t making_sig = B_FALSE;
-
- making_sig = (sig != NULL) ? B_TRUE : B_FALSE;
(void) ds_close(0);
if (dstdev.pathname)
@@ -982,161 +831,32 @@ wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
* Create a cpio-compatible list of the requisite files in
* the temporary file.
*/
- if (!making_sig) {
- for (i = 0; pkg[i]; i++) {
- register ssize_t entry_size;
-
- /*
- * Copy pkginfo and pkgmap filenames into the
- * temporary string allowing for the first line
- * as a special case.
- */
- entry_size = sprintf(tmp_entry,
- (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
- pkg[i], PKGINFO, pkg[i], PKGMAP);
-
- if (write(list_fd, tmp_entry,
- entry_size) != entry_size) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
- (void) close(list_fd);
- ecleanup();
- return (1);
- }
- }
-
- } else {
+ for (i = 0; pkg[i]; i++) {
register ssize_t entry_size;
/*
- * if we're making a signature, we must make a
- * temporary area full of symlinks to the requisite
- * files, plus an extra entry for the signature, so
- * that cpio will put all files and signature in the
- * same archive in a single invocation of cpio.
+ * Copy pkginfo and pkgmap filenames into the
+ * temporary string allowing for the first line
+ * as a special case.
*/
- tmpsymdir = xstrdup(tmpnam(NULL));
+ entry_size = sprintf(tmp_entry,
+ (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
+ pkg[i], PKGINFO, pkg[i], PKGMAP);
- if (mkdir(tmpsymdir, S_IRWXU)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_MKDIR), tmpsymdir);
- return (1);
- }
-
- /* generate the signature */
- if (((len = snprintf(path, PATH_MAX, "%s/%s",
- tmpsymdir, SIGNATURE_FILENAME)) >= PATH_MAX) ||
- len < 0) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), tmpsymdir);
- cleanup();
- return (1);
- }
-
- if ((fp = fopen(path, "w")) == NULL) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), path);
- cleanup();
- return (1);
- }
- (void) PEM_write_PKCS7(fp, sig);
- (void) fclose(fp);
-
- for (i = 0; pkg[i]; i++) {
- (void) snprintf(path, sizeof (path),
- "%s/%s", tmpsymdir, pkg[i]);
- if (mkdir(path, 0755)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_MKDIR), path);
- cleanup();
- return (1);
- }
- (void) snprintf(path, sizeof (path),
- "%s/%s/%s", tmpsymdir, pkg[i], PKGINFO);
- (void) snprintf(srcpath, sizeof (srcpath),
- "%s/%s/%s", src, pkg[i], PKGINFO);
- if (symlink(srcpath, path) != 0) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
- cleanup();
- return (1);
- }
-
- (void) snprintf(path, sizeof (path),
- "%s/%s/%s", tmpsymdir, pkg[i], PKGMAP);
- (void) snprintf(srcpath, sizeof (srcpath),
- "%s/%s/%s", src, pkg[i], PKGMAP);
- if (symlink(srcpath, path) != 0) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_SYMLINK), path, srcpath);
- cleanup();
- return (1);
- }
-
- /*
- * Copy pkginfo and pkgmap filenames into the
- * temporary string allowing for the first line
- * as a special case.
- */
- entry_size = snprintf(tmp_entry, sizeof (tmp_entry),
- (i == 0) ? "%s/%s\n%s/%s" : "\n%s/%s\n%s/%s",
- pkg[i], PKGINFO, pkg[i], PKGMAP);
-
- if (write(list_fd, tmp_entry,
- entry_size) != entry_size) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
- (void) close(list_fd);
- ecleanup();
- cleanup();
- return (1);
- }
- }
-
- /* add signature to list of files */
- entry_size = snprintf(tmp_entry, sizeof (tmp_entry), "\n%s",
- SIGNATURE_FILENAME);
- if (write(list_fd, tmp_entry, entry_size) != entry_size) {
+ if (write(list_fd, tmp_entry,
+ entry_size) != entry_size) {
progerr(pkg_gt(ERR_TRANSFER));
logerr(pkg_gt(MSG_NOTMPFIL), tmp_file);
(void) close(list_fd);
ecleanup();
- cleanup();
return (1);
}
}
(void) lseek(list_fd, 0, SEEK_SET);
- if (!making_sig) {
- (void) snprintf(tmp_entry, sizeof (tmp_entry),
- "%s -ocD -C %d", CPIOPROC, (int)BLK_SIZE);
- } else {
- /*
- * when making a signature, we must make sure to follow
- * symlinks during the cpio so that we don't archive
- * the links themselves
- */
- (void) snprintf(tmp_entry, sizeof (tmp_entry),
- "%s -ocDL -C %d", CPIOPROC, (int)BLK_SIZE);
- }
-
- if (making_sig) {
- /* save cwd and change to symlink dir for cpio invocation */
- if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
- logerr(pkg_gt(ERR_GETWD));
- progerr(pkg_gt(ERR_TRANSFER));
- cleanup();
- return (1);
- }
-
- if (chdir(tmpsymdir)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), tmpsymdir);
- cleanup();
- return (1);
- }
- }
+ (void) snprintf(tmp_entry, sizeof (tmp_entry),
+ "%s -ocD -C %d", CPIOPROC, (int)BLK_SIZE);
if (n = esystem(tmp_entry, list_fd, ds_fd)) {
rpterr();
@@ -1151,15 +871,6 @@ wdsheader(struct dm_buf *hdr, char *src, char *device, char **pkg, PKCS7 *sig)
(void) close(list_fd);
(void) unlink(tmp_file);
- if (making_sig) {
- /* change to back to src dir for subsequent operations */
- if (chdir(cwd)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), cwd);
- cleanup();
- return (1);
- }
- }
return (0);
}
@@ -1679,135 +1390,6 @@ pkgxfer(char *srcinst, int options)
return (0);
}
-/*
- * Name: pkgdump
- * Description: Dump a cpio archive of a package's contents to a BIO.
- *
- * Arguments: srcinst - Name of package, which resides on the
- * device pointed to by the static 'srcdev' variable,
- * to dump.
- * bio - BIO object to dump data to
- *
- * Returns : 0 - success
- * nonzero - failure. errors printed to screen.
- */
-static int
-pkgdump(char *srcinst, BIO *bio)
-{
- FILE *fp;
- char *src;
- char temp[MAXPATHLEN],
- srcdir[MAXPATHLEN],
- cmd[CMDSIZE];
- int i, n, part, nparts, maxpartsize, iscomp;
-
- /*
- * when this routine is entered, the entire package
- * is already available at 'src' - including the
- * pkginfo/pkgmap files and the objects as well.
- */
-
- /* read the pkgmap to get it's size information */
- if ((fp = fopen(PKGMAP, "r")) == NULL) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_NOPKGMAP), srcinst);
- return (1);
- }
-
- nparts = 1;
- if (!rd_map_size(fp, &nparts, &maxpartsize, &compressedsize))
- return (1);
- else
- (void) fclose(fp);
-
- /* make sure the first volume is available */
- if (srcdev.mount) {
- src = srcdev.dirname;
- (void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, srcinst);
- if (ckvolseq(srcdir, 1, nparts)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_SEQUENCE));
- return (1);
- }
- }
-
- /*
- * form cpio command that will output the contents of all of
- * this package's parts
- */
- for (part = 1; part <= nparts; /* void */) {
-
- if (part == 1) {
- (void) snprintf(cmd, CMDSIZE, "find %s %s",
- PKGINFO, PKGMAP);
- if (nparts && (isdir(INSTALL) == 0)) {
- (void) strlcat(cmd, " ", sizeof (cmd));
- (void) strlcat(cmd, INSTALL, sizeof (cmd));
- }
- } else
- (void) snprintf(cmd, CMDSIZE, "find %s", PKGINFO);
-
- if (nparts > 1) {
- (void) snprintf(temp, MAXPATHLEN, "%s.%d", RELOC, part);
- if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, temp, CMDSIZE);
- }
- (void) snprintf(temp, MAXPATHLEN, "%s.%d", ROOT, part);
- if (iscpio(temp, &iscomp) || isdir(temp) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, temp, CMDSIZE);
- }
- (void) snprintf(temp, MAXPATHLEN, "%s.%d",
- ARCHIVE, part);
- if (isdir(temp) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, temp, CMDSIZE);
- }
- } else if (nparts) {
- for (i = 0; reloc_names[i] != NULL; i++) {
- if (iscpio(reloc_names[i], &iscomp) ||
- isdir(reloc_names[i]) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, reloc_names[i],
- CMDSIZE);
- }
- }
- for (i = 0; root_names[i] != NULL; i++) {
- if (iscpio(root_names[i], &iscomp) ||
- isdir(root_names[i]) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, root_names[i],
- CMDSIZE);
- }
- }
- if (isdir(ARCHIVE) == 0) {
- (void) strlcat(cmd, " ", CMDSIZE);
- (void) strlcat(cmd, ARCHIVE, CMDSIZE);
- }
- }
-
- (void) snprintf(cmd + strlen(cmd),
- sizeof (cmd) - strlen(cmd),
- " -print | %s -ocD -C %d",
- CPIOPROC, (int)BLK_SIZE);
- /*
- * execute the command, dumping all standard output
- * to the BIO.
- */
- n = BIO_dump_cmd(cmd, bio);
- if (n != 0) {
- rpterr();
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CMDFAIL), cmd, n);
- return (1);
- }
-
- part++;
- }
- return (0);
-}
-
static void
sigtrap(int signo)
{
@@ -1845,129 +1427,3 @@ cleanup(void)
(void) pkgumount(&dstdev);
(void) ds_close(1);
}
-
-/*
- * Name: dump_hdr_and_pkgs
- * Description: Dumps datastream header and each package's contents
- * to the supplied BIO
- *
- * Arguments: bio - BIO object to dump data to
- * hdr - Header for the datastream being dumped
- * pkglist - NULL-terminated list of packages
- * to dump. The location of the packages are stored
- * in the static 'srcdev' variable.
- *
- * Returns : 0 - success
- * nonzero - failure. errors printed to screen.
- */
-static int
-dump_hdr_and_pkgs(BIO *bio, struct dm_buf *hdr, char **pkglist)
-{
- int block_cnt, i;
- char srcdir[MAXPATHLEN];
- char cwd[MAXPATHLEN + 1];
- char *src;
-
- /* write out the header to the signature stream */
- for (block_cnt = 0; block_cnt < hdr->allocation;
- block_cnt += BLK_SIZE) {
- (void) BIO_write(bio, (hdr->text_buffer + block_cnt), BLK_SIZE);
- }
-
- /* save current directory */
- if (getcwd(cwd, MAXPATHLEN + 1) == NULL) {
- logerr(pkg_gt(ERR_GETWD));
- progerr(pkg_gt(ERR_TRANSFER));
- return (1);
- }
-
- /* now write out each package's contents */
- for (i = 0; pkglist[i]; i++) {
- /*
- * change to the source dir, so we can find and dump
- * the package(s) bits into the BIO
- *
- */
- src = srcdev.dirname;
-
- /* change to the package source directory */
- (void) snprintf(srcdir, MAXPATHLEN, "%s/%s", src, pkglist[i]);
- if (chdir(srcdir)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), srcdir);
- return (1);
- }
-
- if (pkgdump(pkglist[i], bio)) {
- pkglist[i] = NULL;
- return (1);
- }
- }
-
- /* change back to directory we were in upon entering this routine */
- if (chdir(cwd)) {
- progerr(pkg_gt(ERR_TRANSFER));
- logerr(pkg_gt(MSG_CHDIR), cwd);
- return (1);
- }
-
- return (0);
-}
-
-/*
- * Name: BIO_dump_cmd
- * Description: Dump the output of invoking a command
- * to a BIO.
- *
- * Arguments: cmd - Command to invoke
- * bio - BIO to dump output of command to
- * only 'stdout' is dumped.
- * Returns : 0 - success
- * nonzero - failure. errors printed to screen.
- */
-int
-BIO_dump_cmd(char *cmd, BIO *bio)
-{
- char buf[BLK_SIZE];
- FILE *fp;
- int rc;
-
- /* start up the process */
- if ((fp = epopen(cmd, "r")) == NULL) {
- rpterr();
- return (1);
- }
-
- /* read output in chunks, transfer to BIO */
- while (fread(buf, BLK_SIZE, 1, fp) == 1) {
- if (BIO_write(bio, buf, BLK_SIZE) != BLK_SIZE) {
- (void) sighold(SIGINT);
- (void) sighold(SIGHUP);
- (void) epclose(fp);
- (void) sigrelse(SIGINT);
- (void) sigrelse(SIGHUP);
- rpterr();
- return (1);
- }
- }
-
- /* done with stream, make sure no errors were encountered */
- if (ferror(fp)) {
- (void) epclose(fp);
- rpterr();
- return (1);
- }
-
- /* done, close stream, report any errors */
- (void) sighold(SIGINT);
- (void) sighold(SIGHUP);
- rc = epclose(fp);
- (void) sigrelse(SIGINT);
- (void) sigrelse(SIGHUP);
- if (rc != 0) {
- rpterr();
- return (1);
- }
-
- return (rc);
-}