Unix.cpp
资源名称:warftpd.zip [点击查看]
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:18k
源码类别:
Ftp客户端
开发平台:
Visual C++
- // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
- // Copyright 1996 by Jarle Aase. All rights reserved.
- // See the "War Software Series Licende Agreement" for details concerning
- // use and distribution.
- // ---
- // This source code, executables and programs containing source code or
- // binaries or proprietetary technology from the War Software Series are
- // NOT alloed used, viewed or tested by any governmental agencies in
- // any countries. This includes the government, departments, police,
- // military etc.
- // ---
- // This file is intended for use with Tab space = 2
- // Created and maintained in MSVC Developer Studio
- // ---
- // NAME : Unix.cpp
- // PURPOSE : UNIX commands
- // PROGRAM :
- // DATE : Sept. 27 1996
- // AUTHOR : Jarle Aase
- // ---
- // REVISION HISTORY
- //
- // This module contains code from free-bsd
- /*
- * Copyright (c) 1987 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #include "stdafx.h"
- #include "WarSoftware.h"
- #include "Unix.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define index(a,b) strchr(a,b)
- #define rindex(a,b) strrchr(a,b)
- #define BADCH (int)'?'
- #define EMSG ""
- CUnix::CUnix()
- {
- m_TmpName = NULL;
- m_stdio = NULL;
- place = EMSG;
- opterr = 0; /* if error message should be printed */
- optind = 0; /* index into parent argv vector */
- optopt = 0; /* character checked for validity */
- optarg = NULL;
- }
- CUnix::~CUnix()
- {
- if (m_TmpName)
- delete m_TmpName;
- if (m_stdio && (m_stdio != BUFFER_STDIO))
- fclose(m_stdio);
- }
- BOOL CUnix::Create(CCmdArgs *CmdArgs, CLog *Log, FILE *OutFile, CUserFsys *Fsys)
- {
- m_Fsys = Fsys;
- m_CmdArgs = CmdArgs;
- m_Log = Log;
- optind = 1;
- opterr = 1;
- m_stdio = OutFile;
- m_HavePrintedSomething = FALSE;
- m_ShowLinkAsFile = FALSE;
- m_UseBufferOutput = FALSE;
- return TRUE;
- }
- int CUnix::Exec()
- {
- if (!m_stdio)
- {
- // Open a temporary file
- LPCSTR TmpDir = getenv("TEMP");
- ASSERT(TmpDir ? AfxIsValidString(TmpDir) : TRUE);
- if ((m_TmpName = _tempnam(TmpDir, "~CUnix")) == NULL)
- {
- LogMsg(LOGF_WARNINGS,"Exec: Failed to get temporary file name.");
- return FALSE;
- }
- ASSERT(AfxIsValidString(m_TmpName));
- if ((m_stdio = fopen(m_TmpName,"w+b")) == NULL)
- {
- LogMsg(LOGF_WARNINGS,"Exec: Failed to open temporary file '%s'.", m_TmpName);
- return FALSE;
- }
- }
- else if (m_stdio == BUFFER_STDIO)
- {
- m_stdout.Empty();
- m_UseBufferOutput = TRUE;
- }
- // Call the main function
- ASSERT(AfxIsValidAddress(m_CmdArgs,sizeof(m_CmdArgs)));
- ASSERT(m_CmdArgs->m_argc >= 1);
- return main(m_CmdArgs->m_argc, m_CmdArgs->m_argv);
- }
- int CUnix::main(int argc, char **argv)
- {
- // Must be overridden
- ASSERT(FALSE);
- return -1;
- }
- void CUnix::LogMsg(int flag, LPCSTR Format, ...)
- {
- CString cBuf;
- if (!ShouldLog(m_Log, flag))
- return;
- ASSERT(AfxIsValidString(Format, FALSE));
- cBuf.Format("CUnix: %s", Format);
- va_list argList;
- va_start(argList, Format);
- m_Log->LogMsgV(flag, cBuf, argList);
- va_end(argList);
- }
- BOOL CUnix::BldFileInfoList(CFileInfoList& FileList, LPCSTR Path, BOOL ListDir)
- {
- return m_Fsys->BldFileInfoList(FileList, Path, ListDir);
- }
- int CUnix::printf(LPCSTR format, ... )
- {
- ASSERT(AfxIsValidString(format));
- int Rval;
- va_list marker;
- va_start(marker,format);
- if (m_UseBufferOutput)
- {
- Rval = m_stdout.FormatCatV(format, marker);
- }
- else
- {
- Rval = ::vfprintf(m_stdio, format, marker);
- }
- va_end(marker);
- BOOL m_HavePrintedSomething = TRUE;
- return Rval;
- }
- int CUnix::putchar(int ch)
- {
- BOOL m_HavePrintedSomething = TRUE;
- if (ch == 'n')
- return puts(m_CRLF);
- if (m_UseBufferOutput)
- {
- m_stdout += ch;
- return ch;
- }
- return fputc(ch, m_stdio);
- }
- int CUnix::putc(int ch)
- {
- BOOL m_HavePrintedSomething = TRUE;
- if (ch == 'n')
- return puts(m_CRLF);
- return fputc(ch, m_stdio);
- }
- int CUnix::puts(LPCSTR str)
- {
- ASSERT(AfxIsValidString(str));
- BOOL m_HavePrintedSomething = TRUE;
- if (m_UseBufferOutput)
- {
- m_stdout += str;
- return 1;
- }
- else
- return fputs(str, m_stdio);
- }
- /////////////////////////////////////////////////////////////////////////////////////
- // Misc standard UNIX lib functions
- int CUnix::getuid()
- {
- if (m_Fsys->m_IsAdmin)
- return 0; // root
- return m_Fsys->m_User;
- }
- int CUnix::getopt(int nargc, char * const *nargv, const char *ostr)
- {
- register char *oli; /* option letter list index */
- char *p;
- if (!*place) { /* update scanning pointer */
- if (optind >= nargc || *(place = nargv[optind]) != '-') {
- place = EMSG;
- return(EOF);
- }
- if (place[1] && *++place == '-') { /* found "--" */
- ++optind;
- place = EMSG;
- return(EOF);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = index(ostr, optopt))) {
- /*
- * if the user didn't specify '-' as an option,
- * assume it means EOF.
- */
- if (optopt == (int)'-')
- return(EOF);
- if (!*place)
- ++optind;
- if (opterr) {
- if (!(p = rindex(*nargv, '/')))
- p = *nargv;
- else
- ++p;
- LogMsg(LOGF_WARNINGS, "getopt(): %s: illegal option -- %cn", p, optopt);
- }
- return(BADCH);
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- }
- else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- if (!(p = rindex(*nargv, '/')))
- p = *nargv;
- else
- ++p;
- if (opterr)
- LogMsg(LOGF_WARNINGS, "getopt() %s: option requires an argument -- %cn", p, optopt);
- return(BADCH);
- }
- else /* white space */
- optarg = nargv[optind];
- place = EMSG;
- ++optind;
- }
- return(optopt); /* dump back option letter */
- }
- LPCSTR CUnix::userfromuid(int uid, int nouser)
- {
- uid;
- nouser;
- return "ftp";
- }
- LPCSTR CUnix::groupfromgid(int gid, int nouser)
- {
- gid;
- nouser;
- return "ftp";
- }
- void CUnix::strmode(DWORD Flags, char *bp)
- {
- ASSERT(AfxIsValidAddress(bp, 16));
- sprintf(bp,"%c%c%c%c%c%c%c%c%c%c",
- (!m_ShowLinkAsFile && (Flags & NODE_LINK)) ? 'l' : (Flags & NODE_DIR) ? 'd' : '-',
- Flags & NODE_OREAD ? 'r' : '-',
- Flags & NODE_0WRITE ? 'w' : '-',
- Flags & NODE_OEXEC ? 'x' : '-',
- Flags & NODE_GREAD ? 'r' : '-',
- Flags & NODE_GWRITE ? 'w' : '-',
- Flags & NODE_GEXEC ? 'x' : '-',
- Flags & NODE_AREAD ? 'r' : '-',
- Flags & NODE_AWRITE ? 'w' : '-',
- Flags & NODE_AEXEC ? 'x' : '-');
- }
- int CUnix::readlink(LPCSTR path, LPSTR buf, int bufsiz)
- {
- return -1;
- }
- /*
- * Get next token from string *stringp, where tokens are possibly-empty
- * strings separated by characters from delim.
- *
- * Writes NULs into the string at *stringp to end tokens.
- * delim need not remain constant from call to call.
- * On return, *stringp points past the last NUL written (if there might
- * be further tokens), or is NULL (if there are definitely no more tokens).
- *
- * If *stringp is NULL, strsep returns NULL.
- */
- LPSTR CUnix::strsep(LPSTR *stringp, LPCSTR delim)
- {
- register char *s;
- register const char *spanp;
- register int c, sc;
- char *tok;
- if ((s = *stringp) == NULL)
- return (NULL);
- for (tok = s;;) {
- c = *s++;
- spanp = delim;
- do {
- if ((sc = *spanp++) == c) {
- if (c == 0)
- s = NULL;
- else
- s[-1] = 0;
- *stringp = s;
- return (tok);
- }
- } while (sc != 0);
- }
- /* NOTREACHED */
- }
- #define SET_LEN 6 /* initial # of bitcmd struct to malloc */
- #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
- typedef struct bitcmd {
- char cmd;
- char cmd2;
- int bits;
- } BITCMD;
- #define CMD2_CLR 0x01
- #define CMD2_SET 0x02
- #define CMD2_GBITS 0x04
- #define CMD2_OBITS 0x08
- #define CMD2_UBITS 0x10
- static void compress_mode(BITCMD *set);
- static BITCMD *addcmd(BITCMD *set, int op, int who, int oparg, u_int mask);
- /*
- * Given the old mode and an array of bitcmd structures, apply the operations
- * described in the bitcmd structures to the old mode, and return the new mode.
- * Note that there is no '=' command; a strict assignment is just a '-' (clear
- * bits) followed by a '+' (set bits).
- */
- int CUnix::getmode(void *bbox, int omode)
- {
- register BITCMD *set;
- register int clrval, newmode, value;
- set = (BITCMD *)bbox;
- newmode = omode;
- for (value = 0;; set++)
- switch(set->cmd) {
- /*
- * When copying the user, group or other bits around, we "know"
- * where the bits are in the mode so that we can do shifts to
- * copy them around. If we don't use shifts, it gets real
- * grundgy with lots of single bit checks and bit sets.
- */
- case 'u':
- value = (newmode & S_IRWXU) >> 6;
- goto common;
- case 'g':
- value = (newmode & S_IRWXG) >> 3;
- goto common;
- case 'o':
- value = newmode & S_IRWXO;
- common: if (set->cmd2 & CMD2_CLR) {
- clrval =
- (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
- if (set->cmd2 & CMD2_UBITS)
- newmode &= ~((clrval<<6) & set->bits);
- if (set->cmd2 & CMD2_GBITS)
- newmode &= ~((clrval<<3) & set->bits);
- if (set->cmd2 & CMD2_OBITS)
- newmode &= ~(clrval & set->bits);
- }
- if (set->cmd2 & CMD2_SET) {
- if (set->cmd2 & CMD2_UBITS)
- newmode |= (value<<6) & set->bits;
- if (set->cmd2 & CMD2_GBITS)
- newmode |= (value<<3) & set->bits;
- if (set->cmd2 & CMD2_OBITS)
- newmode |= value & set->bits;
- }
- break;
- case '+':
- newmode |= set->bits;
- break;
- case '-':
- newmode &= ~set->bits;
- break;
- case 'X':
- //if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
- if (omode & (NODE_DIR|S_IXUSR|S_IXGRP|S_IXOTH))
- newmode |= set->bits;
- break;
- case ' ':
- default:
- #ifdef SETMODE_DEBUG
- (void)printf("getmode:%04o -> %04on", omode, newmode);
- #endif
- return (newmode);
- }
- }
- #define ADDCMD(a, b, c, d)
- if (set >= endset) {
- register BITCMD *newset;
- setlen += SET_LEN_INCR;
- newset = (BITCMD *)realloc(saveset, sizeof(BITCMD) * setlen);
- if (!saveset)
- return (NULL);
- set = newset + (set - saveset);
- saveset = newset;
- endset = newset + (setlen - 2);
- }
- set = addcmd(set, (a), (b), (c), (d))
- #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
- LPVOID CUnix::setmode(LPCSTR p)
- {
- register int perm, who;
- register char op;
- BITCMD *set, *saveset, *endset;
- int mask = 0;
- int equalopdone=0, permXbits, setlen;
- if (!*p)
- return (NULL);
- /*
- * Get a copy of the mask for the permissions that are mask relative.
- * Flip the bits, we want what's not set. Since it's possible that
- * the caller is opening files inside a signal handler, protect them
- * as best we can.
- */
- setlen = SET_LEN + 2;
- if ((set = (BITCMD *)malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
- return (NULL);
- saveset = set;
- endset = set + (setlen - 2);
- /*
- * If an absolute number, get it and return; disallow non-octal digits
- * or illegal bits.
- */
- if (isdigit(*p)) {
- perm = (int)strtol(p, NULL, 8);
- if (perm & ~(STANDARD_BITS|S_ISTXT)) {
- free(saveset);
- return (NULL);
- }
- while (*++p)
- if (*p < '0' || *p > '7') {
- free(saveset);
- return (NULL);
- }
- ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
- return (saveset);
- }
- /*
- * Build list of structures to set/clear/copy bits as described by
- * each clause of the symbolic mode.
- */
- for (;;) {
- /* First, find out which bits might be modified. */
- for (who = 0;; ++p) {
- switch (*p) {
- case 'a':
- who |= STANDARD_BITS;
- break;
- case 'u':
- who |= S_ISUID|S_IRWXU;
- break;
- case 'g':
- who |= S_ISGID|S_IRWXG;
- break;
- case 'o':
- who |= S_IRWXO;
- break;
- default:
- goto getop;
- }
- }
- getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
- free(saveset);
- return (NULL);
- }
- if (op == '=')
- equalopdone = 0;
- who &= ~S_ISTXT;
- for (perm = 0, permXbits = 0;; ++p) {
- switch (*p) {
- case 'r':
- perm |= S_IRUSR|S_IRGRP|S_IROTH;
- break;
- case 's':
- /* If only "other" bits ignore set-id. */
- if (who & ~S_IRWXO)
- perm |= S_ISUID|S_ISGID;
- break;
- case 't':
- /* If only "other" bits ignore sticky. */
- if (who & ~S_IRWXO) {
- who |= S_ISTXT;
- perm |= S_ISTXT;
- }
- break;
- case 'w':
- perm |= S_IWUSR|S_IWGRP|S_IWOTH;
- break;
- case 'X':
- permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
- break;
- case 'x':
- perm |= S_IXUSR|S_IXGRP|S_IXOTH;
- break;
- case 'u':
- case 'g':
- case 'o':
- /*
- * When ever we hit 'u', 'g', or 'o', we have
- * to flush out any partial mode that we have,
- * and then do the copying of the mode bits.
- */
- if (perm) {
- ADDCMD(op, who, perm, mask);
- perm = 0;
- }
- if (op == '=')
- equalopdone = 1;
- if (op == '+' && permXbits) {
- ADDCMD('X', who, permXbits, mask);
- permXbits = 0;
- }
- ADDCMD(*p, who, op, mask);
- break;
- default:
- /*
- * Add any permissions that we haven't already
- * done.
- */
- if (perm || (op == '=' && !equalopdone)) {
- if (op == '=')
- equalopdone = 1;
- ADDCMD(op, who, perm, mask);
- perm = 0;
- }
- if (permXbits) {
- ADDCMD('X', who, permXbits, mask);
- permXbits = 0;
- }
- goto apply;
- }
- }
- apply: if (!*p)
- break;
- if (*p != ',')
- goto getop;
- ++p;
- }
- set->cmd = 0;
- #ifdef SETMODE_DEBUG
- (void)printf("Before compress_mode()n");
- dumpmode(saveset);
- #endif
- compress_mode(saveset);
- #ifdef SETMODE_DEBUG
- (void)printf("After compress_mode()n");
- dumpmode(saveset);
- #endif
- return (saveset);
- }
- static BITCMD *addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
- {
- switch (op) {
- case '=':
- set->cmd = '-';
- set->bits = who ? who : STANDARD_BITS;
- set++;
- op = '+';
- /* FALLTHROUGH */
- case '+':
- case '-':
- case 'X':
- set->cmd = op;
- set->bits = (who ? who : mask) & oparg;
- break;
- case 'u':
- case 'g':
- case 'o':
- set->cmd = op;
- if (who) {
- set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
- ((who & S_IRGRP) ? CMD2_GBITS : 0) |
- ((who & S_IROTH) ? CMD2_OBITS : 0);
- set->bits = ~0;
- } else {
- set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
- set->bits = mask;
- }
- if (oparg == '+')
- set->cmd2 |= CMD2_SET;
- else if (oparg == '-')
- set->cmd2 |= CMD2_CLR;
- else if (oparg == '=')
- set->cmd2 |= CMD2_SET|CMD2_CLR;
- break;
- }
- return (set + 1);
- }
- /*
- * Given an array of bitcmd structures, compress by compacting consecutive
- * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
- * 'g' and 'o' commands continue to be separate. They could probably be
- * compacted, but it's not worth the effort.
- */
- static void compress_mode(BITCMD *set)
- {
- register BITCMD *nset;
- register int setbits, clrbits, Xbits, op;
- for (nset = set;;) {
- /* Copy over any 'u', 'g' and 'o' commands. */
- while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
- *set++ = *nset++;
- if (!op)
- return;
- }
- for (setbits = clrbits = Xbits = 0;; nset++) {
- if ((op = nset->cmd) == '-') {
- clrbits |= nset->bits;
- setbits &= ~nset->bits;
- Xbits &= ~nset->bits;
- } else if (op == '+') {
- setbits |= nset->bits;
- clrbits &= ~nset->bits;
- Xbits &= ~nset->bits;
- } else if (op == 'X')
- Xbits |= nset->bits & ~setbits;
- else
- break;
- }
- if (clrbits) {
- set->cmd = '-';
- set->cmd2 = 0;
- set->bits = clrbits;
- set++;
- }
- if (setbits) {
- set->cmd = '+';
- set->cmd2 = 0;
- set->bits = setbits;
- set++;
- }
- if (Xbits) {
- set->cmd = 'X';
- set->cmd2 = 0;
- set->bits = Xbits;
- set++;
- }
- }
- }
- int CUnix::chmod(LPCSTR path, int mode,
- int SetOwner, int SetClass, LPCSTR SetComment,
- int DefDirMode, int DefFileMode)
- {
- ASSERT(FALSE);
- return -1;
- }