home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / config / nsinstall.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  9.7 KB  |  397 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. ** Netscape portable install command.
  20. **
  21. ** Brendan Eich, 7/20/95
  22. */
  23. #include <stdio.h>  /* OSF/1 requires this before grp.h, so put it first */
  24. #include <assert.h>
  25. #include <fcntl.h>
  26.  
  27. #ifndef XP_OS2
  28. #include <grp.h>
  29. #include <pwd.h>
  30. #endif
  31.  
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35.  
  36. #ifndef XP_OS2
  37. #include <unistd.h>
  38. #include <utime.h>
  39. #endif
  40.  
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include "pathsub.h"
  44.  
  45. #ifdef NEED_GETOPT_H
  46. #include <getopt.h>
  47. #endif
  48.  
  49. #ifdef XP_OS2
  50. #include <dirent.h>
  51. #include <direct.h>
  52. #include <io.h>
  53. #include <sys\utime.h>
  54. #include <sys\types.h>
  55. #include "getopt.h" /*yes... we had to build this...*/
  56. #endif
  57.  
  58. #ifdef SUNOS4
  59. #include "sunos4.h"
  60. #endif
  61.  
  62. #ifdef NEED_S_ISLNK
  63. #if !defined(S_ISLNK) && defined(S_IFLNK)
  64. #define S_ISLNK(a)    (((a) & S_IFMT) == S_IFLNK)
  65. #endif
  66. #endif
  67.  
  68. #ifdef NEED_FCHMOD_PROTO
  69. extern int fchmod(int fildes, mode_t mode);
  70. #endif
  71.  
  72. #ifdef XP_OS2
  73. /*Note: OS/2 has no concept of users or groups, or symbolic links...*/
  74. #define lstat stat
  75. /*looks reasonably safe based on OS/2's stat.h...*/
  76. #define S_ISLNK(mode)   0 /*no way in hell on a file system that doesn't support it*/
  77. typedef unsigned short mode_t;
  78. typedef unsigned short uid_t;
  79. typedef unsigned short gid_t;
  80. #define mkdir(path, mode) mkdir(path)
  81. #define W_OK 1
  82. #define touid(spam) 0
  83. #define togid(spam) 0
  84. #define access(spam, spam2) 0
  85. #define chown(spam1, spam2, spam3) 0
  86. #define lchown(spam1, spam2, spam3) 0
  87. #define fchown(spam1, spam2, spam3) 0
  88. #define readlink(spam1, spam2, spam3) -1
  89. #define symlink(spam1, spam2) -1
  90. unsigned long _System DosSetFileSize(int, int);
  91. #define ftruncate(spam1, spam2) DosSetFileSize(spam1, spam2)
  92. #endif
  93.  
  94. static void
  95. usage(void)
  96. {
  97.     fprintf(stderr,
  98.     "usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
  99.     "       %*s [-DdltR] file [file ...] directory\n",
  100.     program, strlen(program), "");
  101.     exit(2);
  102. }
  103.  
  104. static int
  105. mkdirs(char *path, mode_t mode)
  106. {
  107.     char *cp;
  108.     struct stat sb;
  109.  
  110.     while (*path == '/' && path[1] == '/')
  111.     path++;
  112.     while ((cp = strrchr(path, '/')) && cp[1] == '\0')
  113.     *cp = '\0';
  114.     if (cp && cp != path) {
  115.     *cp = '\0';
  116.     if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
  117.         mkdirs(path, mode) < 0) {
  118.         return -1;
  119.     }
  120.     *cp = '/';
  121.     }
  122.     return mkdir(path, mode);
  123. }
  124.  
  125. #ifndef XP_OS2
  126. static uid_t
  127. touid(char *owner)
  128. {
  129.     struct passwd *pw;
  130.     uid_t uid;
  131.     char *cp;
  132.  
  133.     pw = getpwnam(owner);
  134.     if (pw)
  135.     return pw->pw_uid;
  136.     uid = strtol(owner, &cp, 0);
  137.     if (uid == 0 && cp == owner)
  138.     fail("cannot find uid for %s", owner);
  139.     return uid;
  140. }
  141.  
  142. static gid_t
  143. togid(char *group)
  144. {
  145.     struct group *gr;
  146.     gid_t gid;
  147.     char *cp;
  148.  
  149.     gr = getgrnam(group);
  150.     if (gr)
  151.     return gr->gr_gid;
  152.     gid = strtol(group, &cp, 0);
  153.     if (gid == 0 && cp == group)
  154.     fail("cannot find gid for %s", group);
  155.     return gid;
  156. }
  157. #endif
  158.  
  159. int
  160. main(int argc, char **argv)
  161. {
  162.     int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists, fromfd, tofd, cc, wc;
  163.     mode_t mode = 0755;
  164.     char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, *bp, buf[BUFSIZ];
  165.     uid_t uid;
  166.     gid_t gid;
  167.     struct stat sb, tosb, fromsb;
  168.     struct utimbuf utb;
  169.  
  170.     program = argv[0];
  171.     cwd = linkname = linkprefix = owner = group = 0;
  172.     onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
  173.  
  174.     while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
  175.     switch (opt) {
  176.       case 'C':
  177.         cwd = optarg;
  178.         break;
  179.       case 'D':
  180.         onlydir = 1;
  181.         break;
  182.       case 'd':
  183.         dodir = 1;
  184.         break;
  185.       case 'l':
  186.         dolink = 1;
  187.         break;
  188.       case 'L':
  189.         linkprefix = optarg;
  190.         lplen = strlen(linkprefix);
  191.         dolink = 1;
  192.         break;
  193.      case 'R':
  194. #ifdef XP_OS2
  195.  /* treat like -t since no symbolic links on OS2 */
  196.         dotimes = 1;
  197. #else
  198.         dolink = dorelsymlink = 1;
  199. #endif
  200.         break;
  201.       case 'm':
  202.         mode = strtoul(optarg, &cp, 8);
  203.         if (mode == 0 && cp == optarg)
  204.         usage();
  205.         break;
  206.       case 'o':
  207.         owner = optarg;
  208.         break;
  209.       case 'g':
  210.         group = optarg;
  211.         break;
  212.       case 't':
  213.         dotimes = 1;
  214.         break;
  215.       default:
  216.         usage();
  217.     }
  218.     }
  219.  
  220.     argc -= optind;
  221.     argv += optind;
  222.     if (argc < 2 - onlydir)
  223.     usage();
  224.  
  225.     todir = argv[argc-1];
  226.     if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
  227.     mkdirs(todir, 0777) < 0) {
  228.     fail("cannot make directory %s", todir);
  229.     }
  230.     if (onlydir)
  231.     return 0;
  232.  
  233.     if (!cwd)
  234. #ifdef RHAPSODY
  235.     {
  236.       cwd = malloc(PATH_MAX + 1);
  237.       cwd = getcwd(cwd, PATH_MAX);
  238.         }
  239. #else
  240.     cwd = getcwd(0, PATH_MAX);
  241. #endif
  242.     xchdir(todir);
  243. #ifdef RHAPSODY
  244.     todir = malloc(PATH_MAX + 1);
  245.     todir = getcwd(todir, PATH_MAX);
  246. #else
  247.     todir = getcwd(0, PATH_MAX);
  248. #endif
  249.     tdlen = strlen(todir);
  250.     xchdir(cwd);
  251.     tdlen = strlen(todir);
  252.  
  253.     uid = owner ? touid(owner) : -1;
  254.     gid = group ? togid(group) : -1;
  255.  
  256.     while (--argc > 0) {
  257.     name = *argv++;
  258.     len = strlen(name);
  259.     base = xbasename(name);
  260.     bnlen = strlen(base);
  261.     toname = xmalloc(tdlen + 1 + bnlen + 1);
  262.     sprintf(toname, "%s/%s", todir, base);
  263.     exists = (lstat(toname, &tosb) == 0);
  264.  
  265.     if (dodir) {
  266.         /* -d means create a directory, always */
  267.         if (exists && !S_ISDIR(tosb.st_mode)) {
  268.         (void) unlink(toname);
  269.         exists = 0;
  270.         }
  271.         if (!exists && mkdir(toname, mode) < 0)
  272.         fail("cannot make directory %s", toname);
  273.         if ((owner || group) && chown(toname, uid, gid) < 0)
  274.         fail("cannot change owner of %s", toname);
  275.     } else if (dolink) {
  276.         if (*name == '/') {
  277.         /* source is absolute pathname, link to it directly */
  278.         linkname = 0;
  279.         } else {
  280.         if (linkprefix) {
  281.             /* -L implies -l and prefixes names with a $cwd arg. */
  282.             len += lplen + 1;
  283.             linkname = xmalloc(len + 1);
  284.             sprintf(linkname, "%s/%s", linkprefix, name);
  285.         } else if (dorelsymlink) {
  286.             /* Symlink the relative path from todir to source name. */
  287.             linkname = xmalloc(PATH_MAX);
  288.  
  289.             if (*todir == '/') {
  290.             /* todir is absolute: skip over common prefix. */
  291.             lplen = relatepaths(todir, cwd, linkname);
  292.             strcpy(linkname + lplen, name);
  293.             } else {
  294.             /* todir is named by a relative path: reverse it. */
  295.             reversepath(todir, name, len, linkname);
  296.             xchdir(cwd);
  297.             }
  298.  
  299.             len = strlen(linkname);
  300.         }
  301.         name = linkname;
  302.         }
  303.  
  304.         /* Check for a pre-existing symlink with identical content. */
  305.         if ((exists && (!S_ISLNK(tosb.st_mode) ||
  306.                         readlink(toname, buf, sizeof buf) != len ||
  307.                         strncmp(buf, name, len) != 0)) || 
  308.             ((stat(name, &fromsb) == 0) && 
  309.              (fromsb.st_mtime > tosb.st_mtime))) {
  310.         (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
  311.         exists = 0;
  312.         }
  313.         if (!exists && symlink(name, toname) < 0)
  314.         fail("cannot make symbolic link %s", toname);
  315. #ifdef HAVE_LCHOWN
  316.         if ((owner || group) && lchown(toname, uid, gid) < 0)
  317.         fail("cannot change owner of %s", toname);
  318. #endif
  319.  
  320.         if (linkname) {
  321.         free(linkname);
  322.         linkname = 0;
  323.         }
  324.     } else {
  325.         /* Copy from name to toname, which might be the same file. */
  326. #ifdef XP_OS2_FIX
  327.         fromfd = open(name, O_RDONLY | O_BINARY);
  328. #else
  329.         fromfd = open(name, O_RDONLY);
  330. #endif
  331.         if (fromfd < 0 || fstat(fromfd, &sb) < 0)
  332.         fail("cannot access %s", name);
  333.         if (exists && (!S_ISREG(tosb.st_mode) || access(toname, W_OK) < 0))
  334.         (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
  335. #ifdef XP_OS2
  336.         chmod(toname, S_IREAD | S_IWRITE);
  337. #endif
  338. #ifdef XP_OS2_FIX
  339.         tofd = open(toname, O_CREAT | O_WRONLY | O_BINARY, 0666);
  340. #else
  341.         tofd = open(toname, O_CREAT | O_WRONLY, 0666);
  342. #endif
  343.         if (tofd < 0)
  344.         fail("cannot create %s", toname);
  345.  
  346.         bp = buf;
  347.         while ((cc = read(fromfd, bp, sizeof buf)) > 0) {
  348.         while ((wc = write(tofd, bp, cc)) > 0) {
  349.             if ((cc -= wc) == 0)
  350.             break;
  351.             bp += wc;
  352.         }
  353.         if (wc < 0)
  354.             fail("cannot write to %s", toname);
  355.         }
  356.         if (cc < 0)
  357.         fail("cannot read from %s", name);
  358.  
  359.         if (ftruncate(tofd, sb.st_size) < 0)
  360.         fail("cannot truncate %s", toname);
  361. #ifndef XP_OS2
  362.         if (dotimes) {
  363.         utb.actime = sb.st_atime;
  364.         utb.modtime = sb.st_mtime;
  365.         if (utime(toname, &utb) < 0)
  366.             fail("cannot set times of %s", toname);
  367.         }
  368.         if (fchmod(tofd, mode) < 0)
  369.         fail("cannot change mode of %s", toname);
  370. #endif
  371.         if ((owner || group) && fchown(tofd, uid, gid) < 0)
  372.         fail("cannot change owner of %s", toname);
  373.  
  374.         /* Must check for delayed (NFS) write errors on close. */
  375.         if (close(tofd) < 0)
  376.         fail("cannot write to %s", toname);
  377.         close(fromfd);
  378. #ifdef XP_OS2
  379.         if (dotimes) {
  380.         utb.actime = sb.st_atime;
  381.         utb.modtime = sb.st_mtime;
  382.         if (utime(toname, &utb) < 0)
  383.             fail("cannot set times of %s", toname);
  384.         }
  385.         if (chmod(toname, (mode & (S_IREAD | S_IWRITE))) < 0)
  386.         fail("cannot change mode of %s", toname);
  387. #endif
  388.     }
  389.  
  390.     free(toname);
  391.     }
  392.  
  393.     free(cwd);
  394.     free(todir);
  395.     return 0;
  396. }
  397.