dda977621312734bdf80df41fcdabe71c792f209
# include "../hdr/defines.h"
Program to remove a specified delta from an SCCS file,
or to change the MRs and/or comments of a specified delta,
when invoked as 'chghist'.
(The program has two links to it, one called 'rmdel', the
The delta to be removed (or whose MRs and/or comments
are to be changed) is specified via the
r argument, in the form of an SID.
If the delta is to be removed, it must be the most recent one
in its branch in the delta tree (a so-called 'leaf' delta).
For either function, the delta being processed must not
have any 'delivered' MRs, and the user must have basically
the same permissions as are required to make deltas.
If a directory is given as an argument, each SCCS file
within the directory will be processed as if it had been
specifically named. If a name of '-' is given, the standard
input will be read for a list of names of SCCS files to be
processed. Non SCCS files are ignored.
Set flags for 'fatal' to issue message, call clean-up
routine, and terminate processing.
Fflags
= FTLMSG
| FTLCLN
| FTLEXIT
;
if(argv
[i
][0] == '-' && (c
= argv
[i
][1])) {
fatal("r has no sid (rc11)");
chksid(sid_ab(p
,&sid
),&sid
);
fatal("unknown key letter (cm1)");
fatal("key letter twice (cm2)");
fatal("missing file arg (cm3)");
if (*(p
= sname(argv
[0])) == 'n')
D_type
= 'R'; /* invoked as 'rmdel' */
else if (equal(p
,"chghist"))
D_type
= 'D'; /* invoked as 'chghist' */
fatal("bad invocation (rc10)");
Change flags for 'fatal' so that it will return to this
routine (main) instead of terminating processing.
Call 'rmchg' routine for each file argument.
Routine that actually causes processing of the delta.
Processing on the file takes place on a
temporary copy of the SCCS file (the x-file).
The name of the x-file is the same as that of the
s-file (SCCS file) with the 's.' replaced by 'x.'.
At end of processing, the s-file is removed
and the x-file is renamed with the name of the old s-file.
This routine makes use of the z-file to lock out simultaneous
updates to the SCCS file by more than one user.
struct packet gpkt
; /* see file s.h */
USXALLOC(); /* defines alloc() and free() */
struct deltab dt
; /* see file s.defines.h */
struct stats stats
; /* see file s.defines.h */
int fowner
, downer
, user
;
if (setjmp(Fjmp
)) /* set up to return here from 'fatal' */
return; /* and return to caller of rmchg */
fatal("missing r (rc1)");
if (D_type
== 'D' && first_time
) {
fatal(sprintf(Error
,"file %s does not exist (rc2)",file
));
Lock out any other user who may be trying to process
if (lockit(auxf(file
,'z'),2,getpid()))
fatal("cannot create lock file (cm4)");
sinit(&gpkt
,file
,1); /* initialize packet and open s-file */
Flag for 'putline' routine to tell it to open x-file
Save requested SID for later checking of
permissions (by 'permiss').
bcopy(&sid
,&gpkt
.p_reqsid
,sizeof(gpkt
.p_reqsid
));
Now read-in delta table. The 'dodelt' routine
will read the table and change the delta entry of the
requested SID to be of type 'R' if this is
being executed as 'rmdel'; otherwise, for 'chghist', only
the MR and comments sections will be changed
(by 'escdodelt', called by 'dodelt').
if (dodelt(&gpkt
,&stats
,&sid
,D_type
) == 0)
Get serial number of requested SID from
delta table just processed.
D_serial
= sidtoser(&gpkt
.p_reqsid
,&gpkt
);
If SID has not been zeroed (by 'dodelt'),
SID was not found in file.
fatal("nonexistent sid (rc3)");
Replace 'sid' with original 'sid'
bcopy(&gpkt
.p_reqsid
,&sid
,sizeof(gpkt
.p_reqsid
));
Check that user is either owner of file or
directory, or is one who made the delta.
fstat(fileno(gpkt
.p_iop
),&Statbuf
);
fowner
= Statbuf
.st_uid
& 0377;
copy(gpkt
.p_file
,line
); /* temporary for dname() */
if (stat(dname(line
),&Statbuf
))
downer
= Statbuf
.st_uid
& 0377;
if (user
!= fowner
|| user
!= downer
)
if (!equal(Pgmr
,logname()))
"you are neither owner nor '%s' (rc4)",Pgmr
));
For 'rmdel', check that delta being removed is a
for (n
= maxser(&gpkt
); n
> D_serial
; n
--) {
if (p
->i_pred
== D_serial
)
fatal("not a 'leaf' delta (rc5)");
For 'rmdel' check that the sid requested is
not contained in p-file, should a p-file
if (exists(auxf(gpkt
.p_file
,'p')))
flushto(&gpkt
,EUSERTXT
,COPY
);
gpkt
.p_chkeof
= 1; /* set EOF is ok */
while ((p
= getline(&gpkt
)) != NULL
) {
Convert serial number to binary.
if (*(p
= satoi(p
,&n
)) != '\n')
This is for invocation as 'chghist'.
if (!(p
= Sflags
[VALFLAG
- 'a']))
fatal("MRs not allowed (rc6)");
if (*p
&& valmrs(&gpkt
,p
))
fatal("inavlid MRs (rc7)");
if (Sflags
[VALFLAG
- 'a'])
fatal("MRs required (rc8)");
Indicate that EOF at this point is ok, and
flush rest of s-file to x-file.
Delete old s-file, change x-file name to s-file.
rename(auxf(&gpkt
,'x'),&gpkt
);
if (D_type
== 'D' && First_esc
) { /* chghist, first time */
putline(pkt
,sprintf(line
,"%c%c ",CTLCHAR
,COMMENTS
));
putline(pkt
,sprintf(line
,"%c%c ",CTLCHAR
,COMMENTS
));
putline(pkt
,"*** CHANGED *** ");
date_ba(&Timenow
,line
); /* get date and time */
putline(pkt
,sprintf(line
," %s\n",logname()));
if (pkt
->p_line
[1] == MRNUM
) {
fatal("delta specified has delivered MR (rc9)");
if (D_type
== 'D') /* turn MRs into comments */
pkt
->p_line
[1] = COMMENTS
;
for (argv
= &Varg
[VSTART
]; *argv
; argv
++)
putline(pkt
,sprintf(str
,"%c%c %s\n",CTLCHAR
,MRNUM
,*argv
));
unlockit(auxf(gpkt
.p_file
,'z'),getpid());
if (exists(auxf(gpkt
.p_file
,'x')))
xunlink(auxf(gpkt
.p_file
,'x'));
register struct packet
*pkt
;
in
= xfopen(auxf(pkt
->p_file
,'p'),0);
while (fgets(line
,sizeof(line
),in
) != NULL
) {
if (sp
->s_rel
== pf
.pf_gsid
.s_rel
&&
sp
->s_lev
== pf
.pf_gsid
.s_lev
&&
sp
->s_br
== pf
.pf_gsid
.s_br
&&
sp
->s_seq
== pf
.pf_gsid
.s_seq
) {
fatal("being edited -- sid is in p-file (rc12)");