1
0
Files
irix-657m-src/eoe/cmd/rcs/rlibutil.c
2022-09-29 17:59:04 +03:00

261 lines
7.6 KiB
C

/* RCS library APIs (helpers/protocol) */
/* Copyright 1996 Silicon Graphics, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING.
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/*
* $Log: rlibutil.c,v $
* Revision 1.1 1996/06/29 00:38:35 msf
* Initial revision
*
*/
#include "rcsbase.h"
#define DEVNULL "/dev/null"
/* Exported variables */
int Ttimeflag; /* -T set for session (set RCS file time) */
sigjmp_buf rcsApiEnv; /* environment at entry to RCS library */
char rcsParamName[MAXPATHLEN]; /* rcspathname last passed as parameter */
static RCSCONN processconn = (RCSCONN)-1;
/* session running in this process */
/* Structs and tables to track files, connections, etc */
#define MAXCONN 1
/* table of options/state for each connection/sess */
static struct {
#ifdef has_signal
signal_type (*interrupt)(int sig); /* application interrupt handler */
#endif
bool Ttimeflag; /* does -T flag apply (affect ,v timestamp) */
bool noquietflag; /* should we turn off quiet (-q) flag? */
const char *auth; /* -w: default is login */
const char *suffixes; /* -x: default is ,v/ */
FILE *debugout; /* output file for debug info */
} connection[MAXCONN];
int rcsOpenConnection(host, opts, conn)
const char *host; /* server machine; ignored on server */
struct rcsConnOpts *opts; /* options (service opt ignored on server) */
RCSCONN *conn; /* returned connection object */
{
/* largely a no-op on the server. Saves connection information. */
int conn_num = 0;
/* Find an available connection.
* We only support one simultaneous connection per process.
*/
if (processconn != (RCSCONN)-1) return ERR_TOOMANY_CONNECTIONS;
processconn = (RCSCONN)conn_num;
/* Remember connection/session information */
connection[conn_num].interrupt = opts->interrupt;
connection[conn_num].Ttimeflag = opts->Ttimeflag;
connection[conn_num].noquietflag = opts->noquietflag;
connection[conn_num].auth = /* opts->auth ?
str_save(opts->auth) : */
getcaller();
connection[conn_num].suffixes = opts->suffixes ?
str_save(opts->suffixes) :
X_DEFAULT;
#ifdef has_signal
connection[conn_num].interrupt = opts->interrupt;
rcsusrhdlr = opts->interrupt;
#endif
/* Redirect diagnostic/error output, as requested (but never to stderr) */
if (opts->debugout) {
if (!(connection[conn_num].debugout = fopen(opts->debugout, "w")))
return ERR_BAD_FCREATE;
}
else connection[conn_num].debugout = fopen(DEVNULL, "w");
/* Copy per-connection values into global variables
* (FIX if we allow multiple connections within a process)
*/
suffixes = connection[conn_num].suffixes;
interactiveflag = false; /* library not "interactive" -I */
cmdid = "rcslib"; /* generic "command" for err msgs */
quietflag = connection[conn_num].noquietflag &&
connection[conn_num].debugout ?
false : true; /* only print info if place to write */
author = connection[conn_num].auth;
finform = connection[conn_num].debugout;
/* Initialize other global variables, as needed */
rcsParamName[0] = '\0'; /* "cached" RCS file */
/* Return connection number, and success (0) */
*conn = (RCSCONN)conn_num;
return 0;
}
int
rcsCloseConnection(conn)
RCSCONN conn;
{
/* Method for destroying a connection/session.
* Within the library (standalone), all that is required
* is that the heap associated with the session be freed.
*/
/* Map connection to internal representation */
if ((int)conn >= MAXCONN) return ERR_APPL_ARGS;
tempunlink();
#ifdef has_signal
rcsusrhdlr = NULL;
#endif
processconn = (RCSCONN)-1;
if (finform != stderr) fclose(finform);
/* For multiple sessions in a single process, free per-session
* memory here.
*/
return 0;
}
/* Needed for DOS and OS/2 ?? */
/* By calling exiterr(), routines may return to the library interface,
* indicate a system error, and not exit the program.
*/
void
exiterr()
{
/* Shortcircuit memory frees, stdio usage, since this may
* be called in an interrupt, where most state info is suspect.
* Just clean up files, and exit.
*/
ORCSerror(); /* normally done for file assoc'd w/session */
dirtempunlink(); /* ditto */
if ((int)processconn >= 0)
rcsCloseConnection(processconn);
siglongjmp(rcsApiEnv, ERR_FATAL); /* return to caller w/ fatal error */
_exit(EXIT_FAILURE); /* just in case */
}
int
rcsOpenArch(openforwrite, mustexist, rcspath)
bool openforwrite;
bool mustexist;
const char *rcspath;
{
/* Open an RCS file (via pairnames(), and initializing the
* lexer (all the way up through calling getadmin()).
*
* Returns: 0 on success (if archive file exists)
* 1 on success (if archive file does not exist, but not
* required to exist)
* ERR_OPEN_ARCH < 0 (on generic error, such as EPERM, etc.,
* including archive not existing, if
* mustexist is set)
* ERR_TOOMANY_ARCH_OPEN (above limit, now 1)
* ERR_NETWORK_DOWN (transmission cut)
*
* Additional bookkeeping: whether the revision tree has
* been parsed yet, and associating the open file with
* the session, so that when the session is destroyed, all
* open files are also closed.
*/
int i, j;
int rc;
static const char *pairpath = rcsParamName;
/* Copy string to rcsParamName, because pairnames may set workname
* or RCSname to the string, so it must be static. Also, rcsParamName
* is used to recognize that a subsequent API call is operating
* on the same archive.
*/
strcpy(rcsParamName, rcspath);
i = pairnames(1, &pairpath,
(openforwrite ? rcswriteopen : rcsreadopen),
mustexist, quietflag);
if (i) { /* File has been initialized (and opened if it exists) */
if (i > 0) { /* archive file exists */
rc = 0;
}
else { /* archive file does not exist (okay) */
rc = 1;
}
}
else rc = ERR_OPEN_ARCH;
fcopy = NULL;
frewrite = NULL;
return rc;
}
int
rcsCloseArch()
{
/* Write portions of RCS files to disk as needed
* Unlink per-file temp files, lock file.
* Reclaim per-file memory.
*/
/* if(file-needs-to-be-written-out && no-errors)
* {
* putadmin();
* if (Head) puttree(Head, frewrite);
* putdesc(X, textfile); NB: X is true for rcs -t only;
* change desc even if not new file
* cmd-specific-cleanup
* donerewrite(has-changed?, Tflag?RCSstat.st_mtime : -1);
* }
*/
Izclose(&finptr); /* tests for NULL, and sets to NULL */
Ozclose(&fcopy);
ORCSclose(); /* close frewrite; close lockfile */
/* For a number of reasons, a session can only handle
* a single open file at a time. One of them is that
* makedirtemp/dirtempunlink use statics which are assumed
* to be reusable for the next file.
*
* We extend that reliance here, and invoke dirtempunlink
* to do some per-file cleanup.
*/
dirtempunlink(); /* unlinks lockfile for RCS file */
ffree(); /* free all per-file memory */
rcsParamName[0] = '\0'; /* no file "cached" */
return 0;
}