/* * NOSAPW.CMD - NOSA Administrator V1.10 - cla@clanganke.de - 1999-2008 * * Syntax: * NOSAPW.CMD -add username password * NOSAPW.CMD -remove username password * NOSAPW.CMD -passwd username password new_password * NOSAPW.CMD -query username [username [...]] * NOSAPW.CMD -distribute * */ /* This program is a substitute for cvspw.exe. It calls cvspw.exe to * create or modify the file passwd in the bin directory of the * NOSA Administrator package. * After modifying this file, it is being distributed to all archives * being hosted by the NOSA administrator, thus, keeping all user ids * in sync for all archives. * * NOTE: You are still required to maintain the CVSROOT/writers and * CVSROOT/writeinfo files of all archives in order to give a user write * access to one or more archives. */ /* First comment is used as help text */ /* CHECKVER */ /* ***** BEGIN LICENSE BLOCK ***** * Version: CDDL 1.0 * * The contents of this file are subject to the COMMON DEVELOPMENT AND * DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use * this file except in compliance with the License. You may obtain a copy of * the License at http://www.sun.com/cddl/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is * "netlabs.org Open Source Archive Administrator/Client" * * The Original Distribution Package is named * "netlabs.org Open Source Archive Administrator/Client" * and maintained and distributed by the Initial Developer * and/or netlabs.org only. * * In addition to the CDDL the following applies: * If you modify the Original Code, you may distribute it only * as a part of a distribution package where * - the name of the package, created directories or * OS2.INI entries do not contain any of the terms * - "netlabs.org Open Source Archive" * - "NOSA" * - "NOSAC" * - "NOSAADM" * - neither netlabs.org nor the Initial Developer is stated as * the vendor or originator of the resulting Distribution Package, * which contains the Modified Code. * * The Initial Developer of the Original Code is * netlabs.org: Christian Langanke . * Portions created by the Initial Developer are Copyright (C) 1999-2008 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ SIGNAL ON HALT TitleLine = STRIP(SUBSTR(SourceLine(2), 3)); PARSE VAR TitleLine CmdName'.CMD 'Info Title = CmdName Info env = 'OS2ENVIRONMENT'; TRUE = (1 = 1); FALSE = (0 = 1); Redirection = '> NUL 2>&1'; CrLf = "0d0a"x; '@ECHO OFF' /* OS/2 errorcodes */ ERROR.NO_ERROR = 0; ERROR.INVALID_FUNCTION = 1; ERROR.FILE_NOT_FOUND = 2; ERROR.PATH_NOT_FOUND = 3; ERROR.ACCESS_DENIED = 5; ERROR.NOT_ENOUGH_MEMORY = 8; ERROR.INVALID_FORMAT = 11; ERROR.INVALID_DATA = 13; ERROR.NO_MORE_FILES = 18; ERROR.WRITE_FAULT = 29; ERROR.READ_FAULT = 30; ERROR.GEN_FAILURE = 31; ERROR.INVALID_PARAMETER = 87; ERROR.ENVVAR_NOT_FOUND = 203; GlobalVars = 'Title CmdName env TRUE FALSE Redirection ERROR. CrLf'; SAY; /* show help */ ARG Parm . IF (POS('?', Parm) > 0) THEN DO rc = ShowHelp(); EXIT(ERROR.INVALID_PARAMETER); END; /* load RexxUtil */ CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'; CALL SysLoadFuncs; /* Defaults */ GlobalVars = GlobalVars 'fVerbose fCleanUp LineDelimiter TmpDir LogHeader Fullname.'; rc = ERROR.NO_ERROR; fVerbose = FALSE; TmpDir = VALUE('TMP',,env); CallDir = GetCalldir(); CvsRoot = VALUE('CVSROOT',,env); IniAppName = 'NOSAADM'; fForceDistribute = FALSE; fDirectorySwitched = FALSE; DirectoryOfCurrentDrive = ''; DirectoryOfNewDrive = ''; PasswdFile = 'passwd'; TimeStamp = ''; TmpFile = SysTempFilename( TmpDir'\nosapw.???'); DO UNTIL (TRUE) /* read some vars from ini */ CvsArchiveRoot = ReadIniValue(, IniAppName, 'CVS_ARCHIVEROOT'); IF (CvsArchiveRoot = '') THEN DO SAY CmdName': error: installation not run yet.'; rc = ERROR.PATH_NOT_FOUND; LEAVE; END; /* is cvspw available ? */ IF (SysSearchPath( 'PATH', 'cvspw.exe') = '') THEN DO SAY CmdName': error: environment not set or cvspw.exe not available.'; rc = ERROR.FILE_NOT_FOUND; LEAVE; END; /* make sure we can reset system to current state */ DirectoryCurrentDrive = DIRECTORY(); DirectoryOfNewDrive = DIRECTORY( FILESPEC('D', CallDir)); /* change to bin directory for crating the */ /* passwd file at the proper place */ fDirectorySwitched = (DIRECTORY( CallDir) \= ''); /* check the current timestamp of passwd file */ OldFileInfo = GetFileInfo( PasswdFile); /* get parms */ PARSE ARG Action Parms; Action = STRIP( Action); Parms = STRIP( Parms); /* make standard parms of cvspw more useable */ SELECT WHEN (POS( Action, '-add') = 1) THEN Action = '-add'; WHEN (POS( Action, '-remove') = 1) THEN Action = '-remove'; WHEN (POS( Action, '-passwd') = 1) THEN Action = '-passwd'; OTHERWISE NOP; END; /* special handling for new parameter */ SELECT WHEN (POS( Action, '-query') = 1) THEN DO rc = QueryUser( PasswdFile, Parms); LEAVE; END; WHEN (POS( Action, '-distribute') = 1) THEN /* force distribution of passwd file */ fForceDistribute = TRUE; OTHERWISE DO /* call the original program */ 'CALL cvspw' Action Parms '>' TmpFile '2>&1'; END; END; SELECT WHEN (rc = 2) THEN DO rcx = ShowHelp(); SAY 'error: wrong arguments.'; END; OTHERWISE DO DO WHILE (LINES( TmpFile) > 0) Line = LINEIN( TmpFile); IF (WORD( Line, 1) = 'cvspw:') THEN Line = 'nosapw:' DELWORD( Line, 1, 1); SAY Line; END; END; END; rcx = STREAM( TmpFile, 'C', 'CLOSE'); rcx = SysFileDelete( TmpFile); /* check the new timestamp: is file being modified ? */ NewFileinfo = GetFileInfo( PasswdFile); IF (NewFileinfo = '') THEN DO SAY CmdName': error: passwd file not found.'; SAY 'Secure any archive first and/or add a user!'; rc = ERROR.FILE_NOT_FOUND; LEAVE; END; IF ((fForceDistribute) | ((NewFileInfo \= '') & (OldFileInfo \= NewFileinfo))) THEN DO /* search all archive base directories */ CALL CHAROUT, 'Searching current archives ...'; rc = SysFileTree( CvsArchiveRoot'\*', 'Dir.', 'DO'); IF (rc \= ERROR.NO_ERROR) THEN DO SAY; SAY CmdName': error in SysfileTree. rc='rc; LEAVE; END; SAY 'Ok.'; /* distribute the new file */ SAY 'Distributing file' PasswdFile 'to archives:'; ArchiveCount = 0; ErrorList = ''; DO d = 1 TO Dir.0 /* do the job */ TargetDir = Dir.d'\CVSROOT'; TargetFile = TargetDir'\'PasswdFile; CALL CHAROUT, ' ' Dir.d '...'; rc = ReplacePasswdFile( PasswdFile, TargetFile, TargetDir'\readinfo',TargetDir'\writeinfo', fForceDistribute); IF (rc = ERROR.NO_ERROR) THEN DO ArchiveCount = ArchiveCount + 1; SAY ' Ok.'; END; ELSE SAY ' Error !' TargetFile'\'PasswdFile; END; ErrorList = STRIP(ErrorList); SAY 'Distributed to' ArchiveCount 'archives'; END; END; /* cleanup */ IF (fDirectorySwitched) THEN DO rcx = DIRECTORY( DirectoryOfNewDrive); rcx = DIRECTORY( DirectoryCurrentDrive); END; EXIT( rc); /* ------------------------------------------------------------------------- */ HALT: SAY; SAY 'Interrupted by user.'; EXIT(ERROR.GEN_FAILURE); /* ------------------------------------------------------------------------- */ ShowHelp: PROCEDURE EXPOSE (GlobalVars) SAY Title; SAY; PARSE SOURCE . . ThisFile DO i = 1 TO 3 rc = LINEIN(ThisFile); END; ThisLine = LINEIN(Thisfile); DO WHILE (ThisLine \= ' */') SAY SUBSTR(ThisLine, 7); ThisLine = LINEIN(Thisfile); END; rc = LINEOUT(Thisfile); RETURN(''); /* ------------------------------------------------------------------------- */ GetCalldir: PROCEDURE PARSE SOURCE . . CallName CallDir = FILESPEC('Drive', CallName)||FILESPEC('Path', CallName); RETURN(LEFT(CallDir, LENGTH(CallDir) - 1)); /* ------------------------------------------------------------------------- */ FileExist: PROCEDURE PARSE ARG FileName RETURN(STREAM(Filename, 'C', 'QUERY EXISTS') > ''); /* ========================================================================= */ GetFileInfo: PROCEDURE PARSE ARG Filename; RETURN( STRIP( STREAM( Filename, 'C', 'QUERY DATETIME') STREAM( Filename, 'C', 'QUERY SIZE'))); /* ========================================================================= */ ReadIniValue: PROCEDURE PARSE ARG IniFile, IniAppname, IniKeyName IniValue = SysIni(IniFile, IniAppname, IniKeyName); IF (IniValue = 'ERROR:') THEN IniValue = ''; IF ((IniValue \= '') & (RIGHT(IniValue, 1) = "00"x)) THEN IniValue = LEFT( IniValue, LENGTH( IniValue) - 1); RETURN( IniValue); /* ========================================================================= */ QueryUser: PROCEDURE EXPOSE (GlobalVars) PARSE ARG File, UserNames; rc = 0; /* use cvspw error codes in this routine ! */ DO UNTIL (TRUE) /* check file */ IF ((\FileExist( File)) | (STREAM( File, 'C', 'QUERY SIZE') = 0)) THEN DO SAY 'no users yet in' File'.'; rc = 1; /* give same error code here as cvspw would */ LEAVE; END; SAY 'Checking userid(s):'; /* check every user */ DO WHILE (UserNames \= '') /* say what we are doing */ PARSE VAR UserNames ThisUser UserNames; CALL CHAROUT, ' check' ThisUser '...'; /* search the file */ rc = SysFileSearch( ThisUser':', File, 'Line.'); IF (rc \= ERROR.NO_ERROR) THEN DO SAY; SAY CmdName': error in SysFileSearch. rc='rc; rc = 2; LEAVE; END; /* make sure it is not just a substring */ fUserFound = FALSE; DO i = 1 TO Line.0 PARSE VAR Line.i User':'.; IF (User = ThisUser) THEN DO fUserFound = TRUE; LEAVE; END; END; /* tell if the user is there */ IF (\fUserFound) THEN CALL CHAROUT, ' not'; SAY ' found.'; END; END; RETURN(rc); /* ========================================================================= */ ReplacePasswdFile: PROCEDURE EXPOSE (GlobalVars) PARSE ARG SourceFile, TargetFile, ReadInfoFile, WriteInfoFile, fForceDistribute; rc = ERROR.NO_ERROR; UserList = ''; DO UNTIL (TRUE) /* check read info of private accesses */ IF (fVerbose) THEN DO SAY SAY '-> read readinfo file from:' ReadInfoFile; END; IF (FileExist( ReadInfoFile)) THEN DO rcx = SysFileTree( ReadInfoFile, 'File.', 'F', '*****','-----'); rcx = STREAM( ReadInfoFile, 'C', 'OPEN READ'); DO WHILE (LINES( ReadInfoFile) > 0) ThisLine = STRIP( LINEIN( ReadInfoFile)); IF (ThisLine = '') THEN ITERATE; IF (LEFT( ThisLine, 1) = ';') THEN ITERATE; PARSE VAR ThisLine ThisUser .; UserList = UserList ThisUser; END; rcx = STREAM( ReadInfoFile, 'C', 'CLOSE'); END; /* check write info of private accesses */ IF (fVerbose) THEN DO SAY SAY '-> read writeinfo file from:' WriteInfoFile; END; IF (FileExist( WriteInfoFile)) THEN DO rcx = SysFileTree( WriteInfoFile, 'File.', 'F', '*****','-----'); rcx = STREAM( WriteInfoFile, 'C', 'OPEN READ'); DO WHILE (LINES( WriteInfoFile) > 0) ThisLine = STRIP( LINEIN( WriteInfoFile)); IF (ThisLine = '') THEN ITERATE; IF (LEFT( ThisLine, 1) = ';') THEN ITERATE; PARSE VAR ThisLine ThisUser .; UserList = UserList ThisUser; END; rcx = STREAM( WriteInfoFile, 'C', 'CLOSE'); END; /* copy filtered passwd file */ rcx = SysFileTree( TargetFile, 'File.', 'F', '*****','-----'); IF (UserList = '') THEN DO IF (fVerbose) THEN DO SAY SAY '-> distribute complete passwd file'; END; 'COPY' SourceFile TargetFile Redirection; END; ELSE DO IF (fVerbose) THEN DO SAY SAY '-> distribute part of passwd file for:' UserList; END; ELSE CALL CHAROUT, '('STRIP( UserList)')'; /* filter passwd file through userlist */ rcx = SysFileDelete( TargetFile); rcx = STREAM( SourceFile, 'C', 'OPEN READ'); DO WHILE (LINES( SourceFile) > 0) ThisLine = LINEIN( SourceFile); IF (ThisLine = '') THEN ITERATE; IF (LEFT( ThisLine, 1) = ';') THEN ITERATE; PARSE VAR ThisLine ThisUser':'.; IF (WORDPOS( ThisUser, UserList) > 0) THEN rcx = LINEOUT( TargetFile, ThisLine); END; rcx = STREAM( SourceFile, 'C', 'CLOSE'); rcx = STREAM( TargetFile, 'C', 'CLOSE'); END; END; RETURN( rc);