home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / wu-ftpd-2.4.2b13-MIHS / support / sco.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-03  |  18.9 KB  |  694 lines

  1. #ifndef _SCO_DS /* none of this is required on SCO OpenServer 5 */
  2. /* Written in 1992, 1993 by Eduard Vopicka, Prague University of Economics */
  3.  
  4. #include "../src/config.h"
  5.  
  6. #include <sys/types.h>
  7. #include <stdio.h>
  8. #include <fcntl.h>
  9. #include <sys/immu.h>
  10. #include <sys/dir.h>        /* required by <sys/user.h> */
  11. #include <sys/user.h>
  12. #include <sys/signal.h>
  13. #include <sys/fs/s5param.h>
  14. #include <string.h>
  15. #include <syslog.h>
  16. #include <sys/stat.h>
  17. #include <varargs.h>
  18.  
  19. static int KmemFd = -1;
  20.  
  21. kmem_open()
  22. {
  23.     if (KmemFd < 0 && (KmemFd = open("/dev/kmem", O_RDWR, 0)) < 0) {
  24.         syslog(LOG_EMERG, "kmem open failed: %m");
  25.         exit(1);
  26.     }
  27. }
  28.  
  29. int
  30. wrub(addr, off, len)
  31.     char    *addr;
  32.     off_t   off;
  33.     int len;
  34. {
  35.     off_t seek_off = UVUBLK+off;
  36.     kmem_open();                /* make sure it is open */
  37.     if (lseek(KmemFd, (char*)seek_off, SEEK_SET) != seek_off) {
  38.         syslog(LOG_EMERG, "lseek failed on /dev/kmem: %m");
  39.         exit(1);
  40.     }
  41.     if (write(KmemFd, addr, len) != len) {
  42.         syslog(LOG_EMERG, "write failed on /dev/kmem: %m");
  43.         exit(1);
  44.     }
  45.     return(0);
  46. }
  47.  
  48. /* UHUHUH, this crazy code is still required for 3.2v4.2 */
  49.  
  50. uid_t
  51. seteuid(id)
  52.     uid_t   id;
  53. {
  54.     struct  user u;
  55.     return(wrub(&id, (off_t)&u.u_uid-(off_t)&u, sizeof(id)));
  56. }
  57.  
  58. uid_t
  59. setruid(id)
  60.     uid_t   id;
  61. {
  62.     struct  user u;
  63.     return(wrub(&id, (off_t)&u.u_ruid-(off_t)&u, sizeof(id)));
  64. }
  65.  
  66.  
  67. uid_t
  68. setegid(id)
  69.     uid_t   id;
  70. {
  71.     struct  user u;
  72.     return(wrub(&id, (off_t)&u.u_gid-(off_t)&u, sizeof(id)));
  73. }
  74.  
  75. uid_t
  76. setrgid(id)
  77.     uid_t   id;
  78. {
  79.     struct  user u;
  80.     return(wrub(&id, (off_t)&u.u_rgid-(off_t)&u, sizeof(id)));
  81. }
  82.  
  83. uid_t
  84. setuid(id)
  85.     uid_t   id;
  86. {
  87.     (void)seteuid(id);
  88.     (void)setruid(id);
  89.     return(0);
  90. }
  91.  
  92. uid_t
  93. setgid(id)
  94.     uid_t   id;
  95. {
  96.     (void)setegid(id);
  97.     (void)setrgid(id);
  98.     return(0);
  99. }
  100.  
  101. uid_t
  102. setreuid(ruid, euid)
  103.     uid_t   ruid, euid;
  104. {
  105.     if (ruid != 0xffff)
  106.         (void)setruid(ruid);
  107.     if (euid != 0xffff)
  108.         (void)seteuid(euid);
  109.     return(0);
  110. }
  111.  
  112. /*
  113.  * Copyright (c) 1989, 1991 The Regents of the University of California.
  114.  * All rights reserved.
  115.  *
  116.  * Redistribution and use in source and binary forms, with or without
  117.  * modification, are permitted provided that the following conditions
  118.  * are met:
  119.  * 1. Redistributions of source code must retain the above copyright
  120.  *    notice, this list of conditions and the following disclaimer.
  121.  * 2. Redistributions in binary form must reproduce the above copyright
  122.  *    notice, this list of conditions and the following disclaimer in the
  123.  *    documentation and/or other materials provided with the distribution.
  124.  * 3. All advertising materials mentioning features or use of this software
  125.  *    must display the following acknowledgement:
  126.  *  This product includes software developed by the University of
  127.  *  California, Berkeley and its contributors.
  128.  * 4. Neither the name of the University nor the names of its contributors
  129.  *    may be used to endorse or promote products derived from this software
  130.  *    without specific prior written permission.
  131.  *
  132.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  133.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  134.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  135.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  136.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  137.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  138.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  139.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  140.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  141.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  142.  * SUCH DAMAGE.
  143.  */
  144.  
  145. #if defined(SYSLOGFILE)
  146.  
  147. #include <sys/types.h>
  148. #include <sys/file.h>
  149. #include <sys/signal.h>
  150. #include <sys/syslog.h>
  151. #include <sys/uio.h>
  152. #include <fcntl.h>
  153. #include <varargs.h>
  154. #include <stdio.h>
  155. #include <string.h>
  156. #include <strings.h>
  157.  
  158. #ifndef CONSOLE
  159. # define CONSOLE "/dev/console"
  160. #endif
  161.  
  162. static int  LogFile = -1;       /* fd for log */
  163. static int  LogStat = 0;        /* status bits, set by openlog() */
  164. static char *LogTag = "syslog"; /* string to tag the entry with */
  165. static int  LogFacility = LOG_USER; /* default facility code */
  166. static int  LogMask = 0xff;     /* mask of priorities to be logged */
  167.  
  168. syslog(va_alist)
  169.     va_dcl
  170. {
  171.     va_list args;
  172.     int pri;
  173.     char *fmt;
  174.  
  175.     va_start(args);
  176.  
  177.     pri = va_arg(args, int);
  178.     fmt = va_arg(args, char *);
  179.  
  180.     vsyslog(pri, fmt, args);
  181.  
  182.     va_end(args);
  183. }
  184.  
  185. vsyslog(pri, fmt, ap)
  186.     int pri;
  187.     register char *fmt;
  188.     va_list ap;
  189. {
  190.     extern int errno;
  191.     register int cnt;
  192.     register char *p;
  193.     time_t now, time();
  194.     int pid, saved_errno;
  195.     char tbuf[2048], fmt_cpy[1024], *stdp, *ctime();
  196.  
  197.     sigset_t newmask, oldmask;
  198.  
  199.     saved_errno = errno;
  200.  
  201. #ifndef LOG_FAC
  202. #define LOG_FAC(pri)    (((pri) & LOG_FACMASK) >> 3)
  203. #endif
  204. #ifndef LOG_PRI
  205. #define LOG_PRI(pri)    ((pri) & LOG_PRIMASK)
  206. #endif
  207.  
  208.     /* see if we should just throw out this message */
  209.     if ((u_int)LOG_FAC(pri) >= (1 << LOG_NFACILITIES) ||
  210.         (!(LOG_MASK(LOG_PRI(pri))&LogMask)) ||
  211.         (pri &~ (LOG_PRIMASK|LOG_FACMASK)))
  212.         return;
  213.     if (LogFile < 0)
  214.         openlog(LogTag, LogStat | LOG_NDELAY, 0);
  215.  
  216.     /* set default facility if none specified */
  217.     if ((pri & LOG_FACMASK) == 0)
  218.         pri |= LogFacility;
  219.  
  220.     /* build the message */
  221.     (void)time(&now);
  222.     (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); /**/
  223. /*  (void)sprintf(tbuf, "%3o %.15s ", pri, ctime(&now) + 4); /**/
  224.     for (p = tbuf; *p; ++p);
  225. #ifndef LOG_PERROR
  226. #define LOG_PERROR 0x20
  227. #endif
  228.     if (LogStat & LOG_PERROR)
  229.         stdp = p;
  230.     if (LogTag) {
  231.         (void)strcpy(p, LogTag);
  232.         for (; *p; ++p);
  233.     }
  234.     if (LogStat & LOG_PID) {
  235.         (void)sprintf(p, "[%d]", getpid());
  236.         for (; *p; ++p);
  237.     }
  238.     if (LogTag) {
  239.         *p++ = ':';
  240.         *p++ = ' ';
  241.     }
  242.  
  243.     /* substitute error message for %m */
  244.     {
  245.         register char ch, *t1, *t2;
  246. /*      char *strerror(); /**/
  247.  
  248.         for (t1 = fmt_cpy; ch = *fmt; ++fmt)
  249.             if (ch == '%' && fmt[1] == 'm') {
  250.                 ++fmt;
  251.                 for (t2 = strerror(saved_errno);
  252.                     *t1 = *t2++; ++t1);
  253.             }
  254.             else
  255.                 *t1++ = ch;
  256.         *t1 = '\0';
  257.     }
  258.  
  259.     (void)vsprintf(p, fmt_cpy, ap);
  260.  
  261.     cnt = strlen(tbuf);
  262.     tbuf[cnt++]='\n';
  263.  
  264.     /* output to stderr if requested */
  265.     if (LogStat & LOG_PERROR)
  266.         write(2, stdp, cnt - (stdp - tbuf));
  267.  
  268.     /* output the message to the local logger */
  269.     if (write(LogFile, tbuf, cnt) == cnt)
  270.         return;
  271.  
  272.     /* output the message to the console */
  273.     pid = vfork();
  274.     if (pid == -1)
  275.         return;
  276.     if (pid == 0) {
  277.         int fd;
  278.  
  279.         sigfillset(&newmask); sigdelset(&newmask, SIGALRM);
  280.         (void) sigprocmask(SIG_SETMASK, &newmask, &oldmask);
  281.         (void)signal(SIGALRM, SIG_DFL);
  282.         (void)alarm((u_int)5);
  283.         if ((fd = open(CONSOLE, O_WRONLY, 0)) < 0)
  284.             return;
  285.         (void)alarm((u_int)0);
  286.         (void)strcat(tbuf, "\r");
  287.         p = index(tbuf, '>') + 1;
  288.         (void)write(fd, p, cnt + 1 - (p - tbuf));
  289.         (void)close(fd);
  290.         _exit(0);
  291.     }
  292.     if (!(LogStat & LOG_NOWAIT))
  293.         while ((cnt = wait((int *)0)) > 0 && cnt != pid);
  294. }
  295.  
  296. /*
  297.  * OPENLOG -- open system log
  298.  */
  299. openlog(ident, logstat, logfac)
  300.     char *ident;
  301.     int logstat, logfac;
  302. {
  303.     if (ident != NULL)
  304.         LogTag = ident;
  305.     LogStat = logstat;
  306.     if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
  307.         LogFacility = logfac;
  308.     if (LogFile == -1) {
  309.         LogFile = open(SYSLOGFILE, O_WRONLY|O_APPEND|O_SYNC);   /**/
  310. /*      LogFile = open(SYSLOGFILE, O_WRONLY|O_APPEND);      /**/
  311.     }
  312. }
  313.  
  314. /*
  315.  * CLOSELOG -- close the system log
  316.  */
  317. closelog()
  318. {
  319.     (void) close(LogFile);
  320.     LogFile = -1;
  321. }
  322.  
  323. /*
  324.  * SETLOGMASK -- set the log mask level
  325.  */
  326. setlogmask(pmask)
  327.     int pmask;
  328. {
  329.     int omask;
  330.  
  331.     omask = LogMask;
  332.     if (pmask != 0)
  333.         LogMask = pmask;
  334.     return (omask);
  335. }
  336.  
  337. #endif /* defined(SYSLOGFILE) */
  338.  
  339. /* Need own getcwd() because of the way getcwd is implemented in SCO UNIX */
  340.  
  341. /*
  342.  * Copyright (c) 1989, 1991 The Regents of the University of California.
  343.  * All rights reserved.
  344.  *
  345.  * Redistribution and use in source and binary forms, with or without
  346.  * modification, are permitted provided that the following conditions
  347.  * are met:
  348.  * 1. Redistributions of source code must retain the above copyright
  349.  *    notice, this list of conditions and the following disclaimer.
  350.  * 2. Redistributions in binary form must reproduce the above copyright
  351.  *    notice, this list of conditions and the following disclaimer in the
  352.  *    documentation and/or other materials provided with the distribution.
  353.  * 3. All advertising materials mentioning features or use of this software
  354.  *    must display the following acknowledgement:
  355.  *  This product includes software developed by the University of
  356.  *  California, Berkeley and its contributors.
  357.  * 4. Neither the name of the University nor the names of its contributors
  358.  *    may be used to endorse or promote products derived from this software
  359.  *    without specific prior written permission.
  360.  *
  361.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  362.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  363.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  364.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  365.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  366.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  367.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  368.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  369.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  370.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  371.  * SUCH DAMAGE.
  372.  */
  373.  
  374. #if defined(LIBC_SCCS) && !defined(lint)
  375. static char sccsid[] = "@(#)getcwd.c    5.11 (Berkeley) 2/24/91";
  376. #endif /* LIBC_SCCS and not lint */
  377.  
  378. #include <sys/param.h>
  379.  
  380. #ifndef HAVE_SYMLINK
  381. # define lstat stat
  382. #endif
  383.  
  384. #include <sys/stat.h>
  385. #include <errno.h>
  386. #include <dirent.h>
  387. #include <stdio.h>
  388. #include <string.h>
  389.  
  390. #ifdef HAVE_D_NAMLEN
  391. # define DNAMLEN(dp) (dp->d_namlen)
  392. #else
  393. # define DNAMLEN(dp) (strlen(dp->d_name))
  394. #endif
  395.  
  396. #define ISDOT(dp) \
  397.     (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
  398.         dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
  399.  
  400. char *
  401. getcwd(pt, size)
  402.     char *pt;
  403.     int size;
  404. {
  405.     register struct dirent *dp;
  406.     register DIR *dir;
  407.     register dev_t dev;
  408.     register ino_t ino;
  409.     register int first;
  410.     register char *bpt, *bup;
  411.     struct stat s;
  412.     dev_t root_dev;
  413.     ino_t root_ino;
  414.     size_t ptsize, upsize;
  415.     int save_errno;
  416.     char *ept, *eup, *up, *ptr;
  417.  
  418.     /*
  419.      * If no buffer specified by the user, allocate one as necessary.
  420.      * If a buffer is specified, the size has to be non-zero.  The path
  421.      * is built from the end of the buffer backwards.
  422.      */
  423.     if (pt) {
  424.         ptsize = 0;
  425.         if (!size) {
  426.             errno = EINVAL;
  427.             return((char *)NULL);
  428.         }
  429.         ept = pt + size;
  430.     } else {
  431.         if (!(pt = (char *)malloc(ptsize = 1024 - 4)))
  432.             return((char *)NULL);
  433.         ept = pt + ptsize;
  434.     }
  435.     bpt = ept - 1;
  436.     *bpt = '\0';
  437.  
  438.     /*
  439.      * Allocate bytes (1024 - malloc space) for the string of "../"'s.
  440.      * Should always be enough (it's 340 levels).  If it's not, allocate
  441.      * as necessary.  Special * case the first stat, it's ".", not "..".
  442.      */
  443.     if (!(up = (char *)malloc(upsize = 1024 - 4)))
  444.         goto err;
  445.     eup = up + MAXPATHLEN;
  446.     bup = up;
  447.     up[0] = '.';
  448.     up[1] = '\0';
  449.  
  450.     /* Save root values, so know when to stop. */
  451.     if (stat("/", &s))
  452.         goto err;
  453.     root_dev = s.st_dev;
  454.     root_ino = s.st_ino;
  455.  
  456.     errno = 0;          /* XXX readdir has no error return. */
  457.  
  458.     for (first = 1;; first = 0) {
  459.         /* Stat the current level. */
  460.         if (lstat(up, &s))
  461.             goto err;
  462.  
  463.         /* Save current node values. */
  464.         ino = s.st_ino;
  465.         dev = s.st_dev;
  466.  
  467.         /* Check for reaching root. */
  468.         if (root_dev == dev && root_ino == ino) {
  469.             *--bpt = '/';
  470.             /*
  471.              * It's unclear that it's a requirement to copy the
  472.              * path to the beginning of the buffer, but it's always
  473.              * been that way and stuff would probably break.
  474.              */
  475.             (void)bcopy(bpt, pt, ept - bpt);
  476.             free(up);
  477.             return(pt);
  478.         }
  479.  
  480.         /*
  481.          * Build pointer to the parent directory, allocating memory
  482.          * as necessary.  Max length is 3 for "../", the largest
  483.          * possible component name, plus a trailing NULL.
  484.          */
  485.         if (bup + 3  + MAXNAMLEN + 1 >= eup) {
  486.             off_t len = bup - up;
  487.             if (!(ptr = (char *)realloc(up, upsize *= 2)))
  488.                 goto err;
  489.             up = ptr;
  490.             bup = up + len;
  491.             eup = up + upsize;
  492.         }
  493.         *bup++ = '.';
  494.         *bup++ = '.';
  495.         *bup = '\0';
  496.  
  497.         /* Open and stat parent directory. */
  498.         if (!(dir = opendir(up)) || fstat(dir->dd_fd, &s))
  499.             goto err;
  500.  
  501.         /* Add trailing slash for next directory. */
  502.         *bup++ = '/';
  503.  
  504.         /*
  505.          * If it's a mount point, have to stat each element because
  506.          * the inode number in the directory is for the entry in the
  507.          * parent directory, not the inode number of the mounted file.
  508.          */
  509.         save_errno = 0;
  510.         if (s.st_dev == dev) {
  511.             for (;;) {
  512.                 if (!(dp = readdir(dir)))
  513.                     goto notfound;
  514.                 if (dp->d_fileno == ino)
  515.                     break;
  516.             }
  517.         } else
  518.             for (;;) {
  519.                 if (!(dp = readdir(dir)))
  520.                     goto notfound;
  521.                 if (ISDOT(dp))
  522.                     continue;
  523.                 bcopy(dp->d_name, bup, DNAMLEN(dp) + 1);
  524.  
  525.                 /* Save the first error for later. */
  526.                 if (lstat(up, &s)) {
  527.                     if (!save_errno)
  528.                         save_errno = errno;
  529.                     errno = 0;
  530.                     continue;
  531.                 }
  532.                 if (s.st_dev == dev && s.st_ino == ino)
  533.                     break;
  534.             }
  535.  
  536.         /*
  537.          * Check for length of the current name, preceding slash,
  538.          * leading slash.
  539.          */
  540.         if (bpt - pt <= DNAMLEN(dp) + (first ? 1 : 2)) {
  541.             size_t len, off;
  542.  
  543.             if (!ptsize) {
  544.                 errno = ERANGE;
  545.                 goto err;
  546.             }
  547.             off = bpt - pt;
  548.             len = ept - bpt;
  549.             if (!(ptr = (char *)realloc(pt, ptsize *= 2)))
  550.                 goto err;
  551.             pt = ptr;
  552.             bpt = pt + off;
  553.             ept = pt + ptsize;
  554.             (void)bcopy(bpt, ept - len, len);
  555.             bpt = ept - len;
  556.         }
  557.         if (!first)
  558.             *--bpt = '/';
  559.         bpt -= DNAMLEN(dp);
  560.         bcopy(dp->d_name, bpt, DNAMLEN(dp));
  561.         (void)closedir(dir);
  562.  
  563.         /* Truncate any file name. */
  564.         *bup = '\0';
  565.     }
  566.  
  567. notfound:
  568.     /*
  569.      * If readdir set errno, use it, not any saved error; otherwise,
  570.      * didn't find the current directory in its parent directory, set
  571.      * errno to ENOENT.
  572.      */
  573.     if (!errno)
  574.         errno = save_errno ? save_errno : ENOENT;
  575.     /* FALLTHROUGH */
  576. err:
  577.     if (ptsize && !pt)
  578.         free(pt);
  579.     if (!up)
  580.         free(up);
  581.     return((char *)NULL);
  582. }
  583.  
  584. char *
  585. getwd(b)
  586.     char *b;
  587. {
  588.     char *p;
  589.     uid_t euid = geteuid();
  590.     seteuid(0);
  591.     getcwd(b, MAXPATHLEN);
  592.     p = getcwd(b, MAXPATHLEN);
  593.     seteuid(euid);
  594.     return(p);
  595. }
  596.  
  597. /*
  598.  * Copyright (c) 1983 Regents of the University of California.
  599.  * All rights reserved.
  600.  *
  601.  * Redistribution and use in source and binary forms, with or without
  602.  * modification, are permitted provided that the following conditions
  603.  * are met:
  604.  * 1. Redistributions of source code must retain the above copyright
  605.  *    notice, this list of conditions and the following disclaimer.
  606.  * 2. Redistributions in binary form must reproduce the above copyright
  607.  *    notice, this list of conditions and the following disclaimer in the
  608.  *    documentation and/or other materials provided with the distribution.
  609.  * 3. All advertising materials mentioning features or use of this software
  610.  *    must display the following acknowledgement:
  611.  *  This product includes software developed by the University of
  612.  *  California, Berkeley and its contributors.
  613.  * 4. Neither the name of the University nor the names of its contributors
  614.  *    may be used to endorse or promote products derived from this software
  615.  *    without specific prior written permission.
  616.  *
  617.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  618.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  619.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  620.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  621.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  622.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  623.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  624.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  625.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  626.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  627.  * SUCH DAMAGE.
  628.  */
  629.  
  630. # if !defined(lint)
  631. static char sccsid[] = "@(#)initgroups.c    5.6 (Berkeley) 6/1/90";
  632. static char  rcsid[] = "@(#)$Id: sco.c,v 1.5 1997/03/03 09:12:24 sob Exp $";
  633. # endif /* !lint */
  634.  
  635. #include <stdio.h>
  636.  
  637. # include <grp.h>
  638. # ifndef NGROUPS
  639. #  ifdef NGROUPS_MAX
  640. #   define NGROUPS  NGROUPS_MAX
  641. #  else /* !NGROUPS_MAX */
  642. #   define NGROUPS  8
  643. #  endif /* NGROUPS_MAX */
  644. # endif /* !NGROUPS */
  645.  
  646. struct group *getgrent();
  647.  
  648. initgroups(uname, agroup)
  649.     char *uname;
  650.     int agroup;
  651. {
  652.     int groups[NGROUPS], ngroups = 0;
  653.     register struct group *grp;
  654.     register int i;
  655.  
  656.     /*
  657.      * If installing primary group, duplicate it;
  658.      * the first element of groups is the effective gid
  659.      * and will be overwritten when a setgid file is executed.
  660.      */
  661.     if (agroup >= 0) {
  662.         groups[ngroups++] = agroup;
  663.         groups[ngroups++] = agroup;
  664.     }
  665.     setgrent();
  666.     while (grp = getgrent()) {
  667.         if (grp->gr_gid == agroup)
  668.             continue;
  669.         for (i = 0; grp->gr_mem[i]; i++)
  670.             if (!strcmp(grp->gr_mem[i], uname)) {
  671.                 if (ngroups == NGROUPS) {
  672. fprintf(stderr, "initgroups: %s is in too many groups\n", uname);
  673.                     goto toomany;
  674.                 }
  675.                 groups[ngroups++] = grp->gr_gid;
  676.             }
  677.     }
  678. toomany:
  679.     endgrent();
  680.     if (setgroups(ngroups, groups) < 0) {
  681.         perror("setgroups");
  682.         return (-1);
  683.     }
  684.     return (0);
  685. }
  686. #else
  687. /* this will keep the preprocessor quiet */
  688. int
  689. SCOdummy()
  690. {
  691. return(0);
  692. }
  693. #endif /* _SCO_DS */
  694.