/* XCOOKIE.C - delta cookie handling routines * * Written for variable cookie configurations with cnf file (SLM 1.6) * Roy Hennegen * 9/25/89 * */ #include #include #define UNICODE #include #undef UNICODE void UnicodeToAnsi(LPWSTR Unicode, LPSTR Ansi, INT Size); #include #include #include #include #include #include #include #include #include #include #include #include "cookie.h" #define OPEN_MAXTRIES 5 /* for DosOpen against cookie file */ #define LLMAX 24 char lock_level[LLMAX]; char szErr[100]; char *pszCookieFile =NULL; /* Name of cookie lock file */ char *pszBase =NULL; /* Name of cookie lock file */ char *pszProject =NULL; /* Name of current project */ char *pszMsgFile =NULL; /* Name of user message file for deny actions */ char *pszCookieLocal=NULL; /* Name of local cookie lock file */ int verbose =FALSE; int infilter =FALSE; int Pswitch =FALSE; int lock_control = FALSE; /* Boolean: overall operation */ int auto_lock = FALSE; /* Boolean: auto_locking operation */ int InDashB = FALSE; /* Boolean: use "-b" flag with diff.exe */ int Rlock_mode =LOCK_WARNING; int Wlock_mode =LOCK_WARNING; int Disk_Min_Read; int Disk_Min_Write; int SLM_Localdrive; int isAuto; int hfCook_glbl = -1; char *read_ops[OPMAX]; char *write_ops[OPMAX]; FILE *fpLocalCookie; void Pause(int); /* function declarations */ int LockFill(char *, char *, int); int open_slm(); int open_slm_ini(void); void trim(char *); int add_cookie_lock(char *, char *, int, int); char *get_station_name(void); /************************************************************************** * * get_station_name () * * find and return the workstation "name" * * parameters- * * NONE * * return- * * character name of workstation or NULL if error * * * ***************************************************************************/ char *get_station_name(void) { char *pszLogName = (char *)NULL; char szComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD cbName = MAX_COMPUTERNAME_LENGTH + 1; /* * Get the workstation name. * First see if LOGNAME is defined. If so, that's the one SLM will use. * If not, get his workstation name. */ if ((pszLogName = getenv("LOGNAME")) != NULL) { pszLogName = _strdup(pszLogName); _strlwr(pszLogName); return (pszLogName); } if (!GetComputerName(szComputerName, &cbName)) return ((char *)NULL); pszLogName = _strdup(szComputerName); _strlwr(pszLogName); return pszLogName; } /************************************************************************** * * add_cookie_lock () * * Add a cookie lock to cookie lock file * The right conditions must exist (ie: many read locks, but one write lock) * * parameters- * * Lockname name of workstation * Lockbuf full text lock-line with name, date, etc. * Locktype READ_LOCK, RB_LOCK, or WRITE_LOCK * autotype TRUE/FALSE * * return- * * OP_OK, OP_DENY or OP_ERR * * ***************************************************************************/ int add_cookie_lock(char *Lockname, char *Lockbuf, int Locktype, int autotype) { char LFreadbuf[LINE_LEN/2]; char LFname[CMAXNAME]; char LFlock[CMAXLOCK]; char LFdate[CMAXDATE]; char tbuf[LINE_LEN/2]; char *tp = tbuf; int hfCookieFile, bufbytes, TotLocks, TotReads; TotLocks = 0; TotReads = 0; if ((hfCookieFile=open_cookie()) < 0) return (OP_SYSERR); while ((bufbytes=_read(hfCookieFile, LFreadbuf, (LINE_LEN/2)-1)) > 0) { char *cp; char c; LFreadbuf[bufbytes] = '\0'; cp = LFreadbuf; while ((c = *cp) != '\0') { *tp++ = *cp++; if (c == '\n') { TotLocks++; *tp = '\0'; if ((sscanf(tbuf,"%s %s %s",LFname, LFlock, LFdate) != 3) || ((strncmp(LFlock,"READ",4) != 0) && (strncmp(LFlock,"WRITE",5) != 0)&& strncmp(LFlock,"READ-BLOCK",10) != 0)) { fprintf(stderr,"%s: cookie lock file corrupt! \n\t%s", pszProject, tbuf); close_cookie(hfCookieFile); return (OP_SYSERR); } else { if (Locktype == WRITE_LOCK) { if ((strcmp(Lockname,LFname) != 0) || (strncmp(LFlock,"WRITE",5) == 0) || (autotype == TRUE)) { close_cookie(hfCookieFile); return (OP_DENY); } else if (strcmp(LFlock,"READ")==0) { TotReads++; } } if (((Locktype == READ_LOCK) && (strcmp(LFlock,"READ") != 0)) && !((strcmp(LFname,Lockname)==0) && (strcmp(LFlock,"READ-BLOCK")==0))) { close_cookie(hfCookieFile); return (OP_DENY); } if ((Locktype == RB_LOCK) && (strcmp(LFlock,"READ") != 0)) { close_cookie(hfCookieFile); return (OP_DENY); } } tp = tbuf; } } } /* now we have reached the end, and the request is not blocked, so add it * but first ensure that a read-to-write lock conversion will be issued * only for 1 outstanding read. If the workstation has mutliple existing * read locks, then return OP_DENY. This honors WKSTA concurrency * from multiple screen groups. */ if ((TotReads > 1) && (Locktype == WRITE_LOCK)) { close_cookie(hfCookieFile); return (OP_DENY); } { unsigned long newFptr; USHORT Dres; /* if there were existing some (read) locks AND we made it here AND the * requested lock type is WRITE, it means that existing READ locks are * owned solely by the requester and they should be REPLACED with WRITE lock. * All that means truncate the file before making the additional lock */ if ((Locktype == WRITE_LOCK) && (TotLocks > 0)) { Dres = _chsize(hfCookieFile, 0); if (Dres != 0) { if (verbose) { sprintf(szErr,"%s: cookie NewSize error\n",pszProject); perror(szErr); } close_cookie(hfCookieFile); return (OP_SYSERR); } } newFptr = _lseek(hfCookieFile,0L,(USHORT) 2); if (newFptr == -1) { if (verbose) { sprintf(szErr,"%s: cookie LSeek error \n",pszProject); perror(szErr); } close_cookie(hfCookieFile); return (OP_SYSERR); } else { bufbytes = _write(hfCookieFile, Lockbuf, strlen(Lockbuf)); if (bufbytes != (int)strlen(Lockbuf)) { if (verbose) { sprintf(szErr,"%s: cookie Write error\n",pszProject); perror(szErr); } close_cookie(hfCookieFile); return (OP_SYSERR); } else { close_cookie(hfCookieFile); return (OP_OK); } } } } /************************************************************************** * * LockFill () * * Given name, create an entire lock-line with KEYWORD, date, time, etc * * * parameters- * * pszId name of workstation * Targbuf target buffer for lock w/ name, date, etc. * Ltype READ_LOCK, or WRITE_LOCK * * return- * * OP_OK or OP_SYSERR * * ***************************************************************************/ int LockFill(char *pszId, char *TargBuf, int Ltype) { time_t ltime; struct tm *tmCurTime; char szLock[CMAXLOCK]; if ((Ltype != READ_LOCK) && (Ltype != WRITE_LOCK) && (Ltype != RB_LOCK)) return (OP_SYSERR); if (Ltype == READ_LOCK) strcpy(szLock,"READ"); if (Ltype == RB_LOCK) strcpy(szLock,"READ-BLOCK"); if (Ltype == WRITE_LOCK) strcpy(szLock,"WRITE"); time(<ime); if ((tmCurTime = localtime(<ime)) == NULL) return (OP_SYSERR); sprintf(TargBuf, "%-16s%-14s %02d/%02d @ %02d:%02d ", pszId, szLock, tmCurTime->tm_mon+1, tmCurTime->tm_mday, tmCurTime->tm_hour, tmCurTime->tm_min); return (OP_OK); } /* Pause - This causes the machine to sit in an idle loop for the number of clock ticks specified by iClockTicks. 18 ticks equals 1 second. This info is kept in the low ram area at 0000:046C. */ void Pause(int iClockTicks) { unsigned long far * ulCurrentTick, ulTickTill; ulCurrentTick = (unsigned long far *)0x0000046C; ulTickTill = *ulCurrentTick+iClockTicks; while (ulTickTill > *ulCurrentTick) ; } /************************************************************************** * * open_cookie () * * Open the cookie file from global file name: pszCookieFile * The file is left open with no sharing allowed * so that we can be sure our access of it is atomic. * * * parameters- * * none * * * return- * * non-zero positive file handle if successful * -1 if error * * * ***************************************************************************/ int open_cookie(void) { int hfCookieFile; int i = 0; while (((hfCookieFile = _open(pszCookieFile,O_CREAT|O_RDWR|O_BINARY, S_IREAD|S_IWRITE)) == -1) && i < OPEN_MAXTRIES) { if (verbose) { fprintf(stderr, "cookie: waiting for access..\n"); } Sleep(3000L); i++; } if (hfCookieFile== -1 && verbose) perror("access denied"); hfCook_glbl = hfCookieFile; return (hfCookieFile); } /************************************************************************** * * close_cookie () * * Close the cookie file given the file handle number * * * parameters- * * none * * * return- * * OP_OK, or OP_SYSERR * * ***************************************************************************/ void close_cookie(int hfCookieFile) { _close(hfCookieFile); hfCook_glbl = -1; } /* ************************************************************* * * set_cookie_config() * * Read slm.ini file from local directory * Read cookie.cnf file from master directory * Set the following global values: * * pszCookieFile = pathname to cookie lock file * pszBase = name of SLM base dir for master tree * pszProject = name of project * pszMsgFile = pathname of msg file for deny action * lock_control = TRUE/FALSE * auto_lock = TRUE/FALSE * Rlock_mode = LOCK_WARNING/LOCK_PROTECT * Wlock_mode = LOCK_WARNING/LOCK_PROTECT * read_ops = char ** set to list of read operations * write_ops = char ** set to list of write operations * * * RETURN: C_COOKIESET if successful lookup AND lock control in effect * C_NOLOCKING if slm.ini OK, but master conf says: no locking * C_BADSLMINI if missing or error with slm.ini file * C_BADCOOCNF if error with master cookie.cnf file * C_SYSERR if internal error or storage allocation error * C_SHAREDENY if cannot access cookie file AND cannot create! * * **************************************************************/ int set_cookie_config(void) { char pszCookieCnf[PATHMAX]; FILE *fh_cnf; char *value, *cend; char fbuf[LINE_LEN]; char *Drive; static fFirsttime = fTrue; lock_level[0] = '\0'; Disk_Min_Read = 0; Disk_Min_Write = 0; lock_control = FALSE; SLM_Localdrive = 0; /* default to most common use: network drive */ /* set pszBase and pszProject */ if (pszBase == NULL || pszProject == NULL) if (open_slm_ini() != 0) return (C_BADSLMINI); Drive = strchr(pszBase,':'); if (Drive != NULL) SLM_Localdrive = (int) *(Drive - 1); else if (strncmp(pszBase,"\\\\",2) == 0) SLM_Localdrive = 0; /* UNC network path */ else { int Dnum; int Dres = 0; char szDir[MAX_PATH]; if (GetCurrentDirectory(sizeof szDir, szDir) > sizeof szDir) Dres = -1; else Dnum = toupper(szDir[0]) - 'A' + 1; if (Dres == 0) SLM_Localdrive = Dnum + (int) 'a' - 1; else fprintf(stderr, "warning: cannot determine local drive\n"); } strcpy(pszCookieCnf,pszBase); cend = pszCookieCnf + strlen(pszCookieCnf) - 1 ; if (*cend != '/' && *cend != '\\') strcat(pszCookieCnf, "\\"); strcat(pszCookieCnf,COOKIE_CNF); /* first try to open the config file for reading. If failure, * then it doesn't exist OR there is network sharing violation. * So try to open the config file for CREATE/APPEND. If failure, * then we have network sharing violation (usually). Otherwise, * close the sucker (NULL FILE) and reopen for reading. */ fh_cnf = fopen(pszCookieCnf, "rt"); if (fh_cnf == NULL) { fh_cnf = fopen(pszCookieCnf, "a+t"); if (fh_cnf == NULL) { pszCookieFile = NULL; lock_control = FALSE; return (C_SHAREDENY); } else { fclose(fh_cnf); fh_cnf = fopen(pszCookieCnf, "rt"); if (fh_cnf == NULL) { pszCookieFile = NULL; lock_control = FALSE; return (C_BADCOOCNF); } } } *read_ops = NULL; *write_ops = NULL; /* Now read the file and assign values */ while (fgets(fbuf, LINE_LEN, fh_cnf) != NULL) { trim(fbuf); /* ignore comments */ if (*fbuf == '#') continue; value = strchr(fbuf, '='); if (value == NULL) continue; /* ignore line if no '=' char */ *value++ = '\0'; _strlwr(fbuf); _strlwr(value); if (strcmp(fbuf, "lock_control_level") == 0) { if (strcmp(value,"none") == 0) { lock_control = FALSE ; } else { if (strlen(value) < LLMAX) strcpy(lock_level,value); } continue; } if (strcmp(fbuf,pszProject) == 0) { if (strlen(value)>0 && (strcmp(value,"pswitch") != 0) && strlen(value)