home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / config / nsinstall.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.0 KB  |  318 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20. ** Netscape portable install command.
  21. **
  22. ** Brendan Eich, 7/20/95
  23. */
  24. #include <stdio.h>  /* OSF/1 requires this before grp.h, so put it first */
  25. #include <assert.h>
  26. #include <fcntl.h>
  27. #include <grp.h>
  28. #include <pwd.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <unistd.h>
  33. #include <utime.h>
  34. #include <sys/types.h>
  35. #include <sys/stat.h>
  36. #include "pathsub.h"
  37.  
  38. #define HAVE_LCHOWN
  39.  
  40. #if defined(AIX) || defined(BSDI) || defined(HPUX) || defined(LINUX) || defined(SUNOS4) || defined(SCO) || defined(UNIXWARE)
  41. #undef HAVE_LCHOWN
  42. #endif
  43.  
  44. #ifdef LINUX
  45. #include <getopt.h>
  46. #endif
  47.  
  48. #if defined(SCO) || defined(UNIXWARE) || defined(SNI) || defined(NCR) || defined(NEC)
  49. #if !defined(S_ISLNK) && defined(S_IFLNK)
  50. #define S_ISLNK(a)    (((a) & S_IFMT) == S_IFLNK)
  51. #endif
  52. #endif
  53.  
  54. #if defined(SNI)
  55. extern int fchmod(int fildes, mode_t mode);
  56. #endif
  57.  
  58. static void
  59. usage(void)
  60. {
  61.     fprintf(stderr,
  62.     "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
  63.     "       %*s [-DdltR] file [file ...] directory\n",
  64.     program, strlen(program), "");
  65.     exit(2);
  66. }
  67.  
  68. static int
  69. mkdirs(char *path, mode_t mode)
  70. {
  71.     char *cp;
  72.     struct stat sb;
  73.     
  74.     while (*path == '/' && path[1] == '/')
  75.     path++;
  76.     while ((cp = strrchr(path, '/')) && cp[1] == '\0')
  77.     *cp = '\0';
  78.     if (cp && cp != path) {
  79.     *cp = '\0';
  80.     if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
  81.         mkdirs(path, mode) < 0) {
  82.         return -1;
  83.     }
  84.     *cp = '/';
  85.     }
  86.     return mkdir(path, mode);
  87. }
  88.  
  89. static uid_t
  90. touid(char *owner)
  91. {
  92.     struct passwd *pw;
  93.     uid_t uid;
  94.     char *cp;
  95.  
  96.     pw = getpwnam(owner);
  97.     if (pw)
  98.     return pw->pw_uid;
  99.     uid = strtol(owner, &cp, 0);
  100.     if (uid == 0 && cp == owner)
  101.     fail("cannot find uid for %s", owner);
  102.     return uid;
  103. }
  104.  
  105. static gid_t
  106. togid(char *group)
  107. {
  108.     struct group *gr;
  109.     gid_t gid;
  110.     char *cp;
  111.  
  112.     gr = getgrnam(group);
  113.     if (gr)
  114.     return gr->gr_gid;
  115.     gid = strtol(group, &cp, 0);
  116.     if (gid == 0 && cp == group)
  117.     fail("cannot find gid for %s", group);
  118.     return gid;
  119. }
  120.  
  121. int
  122. main(int argc, char **argv)
  123. {
  124.     int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
  125.     mode_t mode = 0755;
  126.     char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
  127.     uid_t uid;
  128.     gid_t gid;
  129.     struct stat sb, tosb;
  130.     struct utimbuf utb;
  131.  
  132.     program = argv[0];
  133.     cwd = linkname = linkprefix = owner = group = 0;
  134.     onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
  135.  
  136.     while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
  137.     switch (opt) {
  138.       case 'C':
  139.         cwd = optarg;
  140.         break;
  141.       case 'D':
  142.         onlydir = 1;
  143.         break;
  144.       case 'd':
  145.         dodir = 1;
  146.         break;
  147.       case 'l':
  148.         dolink = 1;
  149.         break;
  150.       case 'L':
  151.         linkprefix = optarg;
  152.         lplen = strlen(linkprefix);
  153.         dolink = 1;
  154.         break;
  155.       case 'R':
  156.         dolink = dorelsymlink = 1;
  157.         break;
  158.       case 'm':
  159.         mode = strtoul(optarg, &cp, 8);
  160.         if (mode == 0 && cp == optarg)
  161.         usage();
  162.         break;
  163.       case 'o':
  164.         owner = optarg;
  165.         break;
  166.       case 'g':
  167.         group = optarg;
  168.         break;
  169.       case 't':
  170.         dotimes = 1;
  171.         break;
  172.       default:
  173.         usage();
  174.     }
  175.     }
  176.  
  177.     argc -= optind;
  178.     argv += optind;
  179.     if (argc < 2 - onlydir)
  180.     usage();
  181.  
  182.     todir = argv[argc-1];
  183.     if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
  184.     mkdirs(todir, 0777) < 0) {
  185.     fail("cannot make directory %s", todir);
  186.     }
  187.     if (onlydir)
  188.     return 0;
  189.  
  190.     if (!cwd)
  191.     cwd = getcwd(0, PATH_MAX);
  192.     xchdir(todir);
  193.     todir = getcwd(0, PATH_MAX);
  194.     tdlen = strlen(todir);
  195.     xchdir(cwd);
  196.     tdlen = strlen(todir);
  197.  
  198.     uid = owner ? touid(owner) : -1;
  199.     gid = group ? togid(group) : -1;
  200.  
  201.     while (--argc > 0) {
  202.     name = *argv++;
  203.     len = strlen(name);
  204.     base = xbasename(name);
  205.     bnlen = strlen(base);
  206.     toname = (char*)xmalloc(tdlen + 1 + bnlen + 1);
  207.     sprintf(toname, "%s/%s", todir, base);
  208.     exists = (lstat(toname, &tosb) == 0);
  209.  
  210.     if (dodir) {
  211.         /* -d means create a directory, always */
  212.         if (exists && !S_ISDIR(tosb.st_mode)) {
  213.         (void) unlink(toname);
  214.         exists = 0;
  215.         }
  216.         if (!exists && mkdir(toname, mode) < 0)
  217.         fail("cannot make directory %s", toname);
  218.         if ((owner || group) && chown(toname, uid, gid) < 0)
  219.         fail("cannot change owner of %s", toname);
  220.     } else if (dolink) {
  221.         if (*name == '/') {
  222.         /* source is absolute pathname, link to it directly */
  223.         linkname = 0;
  224.         } else {
  225.         if (linkprefix) {
  226.             /* -L implies -l and prefixes names with a $cwd arg. */
  227.             len += lplen + 1;
  228.             linkname = (char*)xmalloc(len + 1);
  229.             sprintf(linkname, "%s/%s", linkprefix, name);
  230.         } else if (dorelsymlink) {
  231.             /* Symlink the relative path from todir to source name. */
  232.             linkname = (char*)xmalloc(PATH_MAX);
  233.  
  234.             if (*todir == '/') {
  235.             /* todir is absolute: skip over common prefix. */
  236.             lplen = relatepaths(todir, cwd, linkname);
  237.             strcpy(linkname + lplen, name);
  238.             } else {
  239.             /* todir is named by a relative path: reverse it. */
  240.             reversepath(todir, name, len, linkname);
  241.             xchdir(cwd);
  242.             }
  243.  
  244.             len = strlen(linkname);
  245.         }
  246.         name = linkname;
  247.         }
  248.  
  249.         /* Check for a pre-existing symlink with identical content. */
  250.         if (exists &&
  251.         (!S_ISLNK(tosb.st_mode) ||
  252.          readlink(toname, buf, sizeof buf) != len ||
  253.          strncmp(buf, name, len) != 0)) {
  254.         (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
  255.         exists = 0;
  256.         }
  257.         if (!exists && symlink(name, toname) < 0)
  258.         fail("cannot make symbolic link %s", toname);
  259. #ifdef HAVE_LCHOWN
  260.         if ((owner || group) && lchown(toname, uid, gid) < 0)
  261.         fail("cannot change owner of %s", toname);
  262. #endif
  263.  
  264.         if (linkname) {
  265.         free(linkname);
  266.         linkname = 0;
  267.         }
  268.     } else {
  269.         /* Copy from name to toname, which might be the same file. */
  270.         fromfd = open(name, O_RDONLY);
  271.         if (fromfd < 0 || fstat(fromfd, &sb) < 0)
  272.         fail("cannot access %s", name);
  273.         if (exists && (!S_ISREG(tosb.st_mode) || access(toname, W_OK) < 0))
  274.         (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
  275.         tofd = open(toname, O_CREAT | O_WRONLY, 0666);
  276.         if (tofd < 0)
  277.         fail("cannot create %s", toname);
  278.  
  279.         bp = buf;
  280.         while ((cc = read(fromfd, bp, sizeof buf)) > 0) {
  281.         while ((wc = write(tofd, bp, cc)) > 0) {
  282.             if ((cc -= wc) == 0)
  283.             break;
  284.             bp += wc;
  285.         }
  286.         if (wc < 0)
  287.             fail("cannot write to %s", toname);
  288.         }
  289.         if (cc < 0)
  290.         fail("cannot read from %s", name);
  291.  
  292.         if (ftruncate(tofd, sb.st_size) < 0)
  293.         fail("cannot truncate %s", toname);
  294.         if (dotimes) {
  295.         utb.actime = sb.st_atime;
  296.         utb.modtime = sb.st_mtime;
  297.         if (utime(toname, &utb) < 0)
  298.             fail("cannot set times of %s", toname);
  299.         }
  300.         if (fchmod(tofd, mode) < 0)
  301.         fail("cannot change mode of %s", toname);
  302.         if ((owner || group) && fchown(tofd, uid, gid) < 0)
  303.         fail("cannot change owner of %s", toname);
  304.  
  305.         /* Must check for delayed (NFS) write errors on close. */
  306.         if (close(tofd) < 0)
  307.         fail("cannot write to %s", toname);
  308.         close(fromfd);
  309.     }
  310.  
  311.     free(toname);
  312.     }
  313.  
  314.     free(cwd);
  315.     free(todir);
  316.     return 0;
  317. }
  318.