1adf8f7d4Seric # include <stdio.h> 2adf8f7d4Seric # include <sys/types.h> 3adf8f7d4Seric # include <sys/stat.h> 4b2538d76Seric # include <sys/dir.h> 5adf8f7d4Seric # include <sysexits.h> 6b5d4f080Seric # include <whoami.h> 7adf8f7d4Seric 8*2444cd3eSeric static char SccsId[] = "@(#)sccs.c 1.19 07/28/80"; 9c4432be4Seric 10c4432be4Seric # define bitset(bit, word) ((bit) & (word)) 11c4432be4Seric 12c4432be4Seric typedef char bool; 137de81dc7Seric # define TRUE 1 147de81dc7Seric # define FALSE 0 15d02a4f42Seric 16adf8f7d4Seric struct sccsprog 17adf8f7d4Seric { 18adf8f7d4Seric char *sccsname; /* name of SCCS routine */ 197de81dc7Seric short sccsoper; /* opcode, see below */ 207de81dc7Seric short sccsflags; /* flags, see below */ 21adf8f7d4Seric char *sccspath; /* pathname of binary implementing */ 22adf8f7d4Seric }; 23adf8f7d4Seric 247de81dc7Seric /* values for sccsoper */ 257de81dc7Seric # define PROG 0 /* call a program */ 261777fbcbSeric # define CMACRO 1 /* command substitution macro */ 27172147faSeric # define FIX 2 /* fix a delta */ 28b2538d76Seric # define CLEAN 3 /* clean out recreatable files */ 29e39a5722Seric # define UNEDIT 4 /* unedit a file */ 307de81dc7Seric 31c4432be4Seric /* bits for sccsflags */ 327de81dc7Seric # define NO_SDOT 0001 /* no s. on front of args */ 337de81dc7Seric # define REALUSER 0002 /* protected (e.g., admin) */ 34adf8f7d4Seric 35b5d4f080Seric # ifdef CSVAX 36b5d4f080Seric # define PROGPATH(name) "/usr/local/name" 37b5d4f080Seric # endif CSVAX 38b5d4f080Seric 39b5d4f080Seric # ifndef PROGPATH 40b5d4f080Seric # define PROGPATH(name) "/usr/sccs/name" 41b5d4f080Seric # endif PROGPATH 42b5d4f080Seric 43adf8f7d4Seric struct sccsprog SccsProg[] = 44adf8f7d4Seric { 45b5d4f080Seric "admin", PROG, REALUSER, PROGPATH(admin), 46b5d4f080Seric "chghist", PROG, 0, PROGPATH(rmdel), 47b5d4f080Seric "comb", PROG, 0, PROGPATH(comb), 48b5d4f080Seric "delta", PROG, 0, PROGPATH(delta), 49b5d4f080Seric "get", PROG, 0, PROGPATH(get), 50b5d4f080Seric "help", PROG, NO_SDOT, PROGPATH(help), 51b5d4f080Seric "prt", PROG, 0, PROGPATH(prt), 52b5d4f080Seric "rmdel", PROG, REALUSER, PROGPATH(rmdel), 53b5d4f080Seric "what", PROG, NO_SDOT, PROGPATH(what), 54f0cc3246Seric "edit", CMACRO, 0, "get -e", 55f0cc3246Seric "delget", CMACRO, 0, "delta/get", 56d7e8b658Seric "deledit", CMACRO, 0, "delta/get -e", 571777fbcbSeric "del", CMACRO, 0, "delta/get", 58172147faSeric "delt", CMACRO, 0, "delta/get", 59172147faSeric "fix", FIX, 0, NULL, 603a208c77Seric "clean", CLEAN, REALUSER, (char *) TRUE, 613a208c77Seric "info", CLEAN, REALUSER, (char *) FALSE, 62e39a5722Seric "unedit", UNEDIT, 0, NULL, 637de81dc7Seric NULL, -1, 0, NULL 64adf8f7d4Seric }; 65adf8f7d4Seric 66e39a5722Seric struct pfile 67e39a5722Seric { 68e39a5722Seric char *p_osid; /* old SID */ 69e39a5722Seric char *p_nsid; /* new SID */ 70e39a5722Seric char *p_user; /* user who did edit */ 71e39a5722Seric char *p_date; /* date of get */ 72e39a5722Seric char *p_time; /* time of get */ 73e39a5722Seric }; 74e39a5722Seric 75c4432be4Seric char *SccsPath = "SCCS"; /* pathname of SCCS files */ 76c4432be4Seric bool RealUser; /* if set, running as real user */ 77f0cc3246Seric # ifdef DEBUG 78f0cc3246Seric bool Debug; /* turn on tracing */ 79f0cc3246Seric # endif 80adf8f7d4Seric 81adf8f7d4Seric main(argc, argv) 82adf8f7d4Seric int argc; 83adf8f7d4Seric char **argv; 84adf8f7d4Seric { 85adf8f7d4Seric register char *p; 86b1ed8a43Seric extern struct sccsprog *lookup(); 87adf8f7d4Seric 88adf8f7d4Seric /* 89adf8f7d4Seric ** Detect and decode flags intended for this program. 90adf8f7d4Seric */ 91adf8f7d4Seric 927de81dc7Seric if (argc < 2) 93adf8f7d4Seric { 947de81dc7Seric fprintf(stderr, "Usage: sccs [flags] command [flags]\n"); 957de81dc7Seric exit(EX_USAGE); 967de81dc7Seric } 977de81dc7Seric argv[argc] = NULL; 987de81dc7Seric 99b1ed8a43Seric if (lookup(argv[0]) == NULL) 100b1ed8a43Seric { 1017de81dc7Seric while ((p = *++argv) != NULL) 1027de81dc7Seric { 103adf8f7d4Seric if (*p != '-') 104adf8f7d4Seric break; 105adf8f7d4Seric switch (*++p) 106adf8f7d4Seric { 107adf8f7d4Seric case 'r': /* run as real user */ 108adf8f7d4Seric setuid(getuid()); 109c4432be4Seric RealUser++; 110adf8f7d4Seric break; 111adf8f7d4Seric 112adf8f7d4Seric case 'p': /* path of sccs files */ 113adf8f7d4Seric SccsPath = ++p; 114adf8f7d4Seric break; 115adf8f7d4Seric 116f0cc3246Seric # ifdef DEBUG 117f0cc3246Seric case 'T': /* trace */ 118f0cc3246Seric Debug++; 119f0cc3246Seric break; 120f0cc3246Seric # endif 121f0cc3246Seric 122adf8f7d4Seric default: 123adf8f7d4Seric fprintf(stderr, "Sccs: unknown option -%s\n", p); 124adf8f7d4Seric break; 125adf8f7d4Seric } 126adf8f7d4Seric } 1275cabffd9Seric if (SccsPath[0] == '\0') 1285cabffd9Seric SccsPath = "."; 129b1ed8a43Seric } 130adf8f7d4Seric 1311777fbcbSeric command(argv, FALSE); 1327de81dc7Seric exit(EX_OK); 1337de81dc7Seric } 1347de81dc7Seric 1351777fbcbSeric command(argv, forkflag) 1367de81dc7Seric char **argv; 1371777fbcbSeric bool forkflag; 1387de81dc7Seric { 1397de81dc7Seric register struct sccsprog *cmd; 1407de81dc7Seric register char *p; 1411777fbcbSeric register char *q; 1421777fbcbSeric char buf[40]; 143b1ed8a43Seric extern struct sccsprog *lookup(); 144f0cc3246Seric char *nav[7]; 145f0cc3246Seric char **avp; 146f0cc3246Seric 147f0cc3246Seric # ifdef DEBUG 148f0cc3246Seric if (Debug) 149f0cc3246Seric { 150f0cc3246Seric printf("command:\n"); 151f0cc3246Seric for (avp = argv; *avp != NULL; avp++) 152f0cc3246Seric printf(" \"%s\"\n", *avp); 153f0cc3246Seric } 154f0cc3246Seric # endif 155c4432be4Seric 156c4432be4Seric /* 157adf8f7d4Seric ** Look up command. 1587de81dc7Seric ** At this point, argv points to the command name. 159adf8f7d4Seric */ 160adf8f7d4Seric 161e39a5722Seric cmd = lookup(argv[0]); 162b1ed8a43Seric if (cmd == NULL) 163adf8f7d4Seric { 164e39a5722Seric fprintf(stderr, "Sccs: Unknown command \"%s\"\n", argv[0]); 165adf8f7d4Seric exit(EX_USAGE); 166adf8f7d4Seric } 167adf8f7d4Seric 168adf8f7d4Seric /* 1697de81dc7Seric ** Interpret operation associated with this command. 170c4432be4Seric */ 171c4432be4Seric 1727de81dc7Seric switch (cmd->sccsoper) 1737de81dc7Seric { 1747de81dc7Seric case PROG: /* call an sccs prog */ 1751777fbcbSeric callprog(cmd->sccspath, cmd->sccsflags, argv, forkflag); 1761777fbcbSeric break; 1771777fbcbSeric 1781777fbcbSeric case CMACRO: /* command macro */ 1791777fbcbSeric for (p = cmd->sccspath; *p != '\0'; p++) 1801777fbcbSeric { 181f0cc3246Seric avp = nav; 182f0cc3246Seric *avp++ = buf; 1831777fbcbSeric for (q = buf; *p != '/' && *p != '\0'; p++, q++) 184f0cc3246Seric { 185f0cc3246Seric if (*p == ' ') 186f0cc3246Seric { 1871777fbcbSeric *q = '\0'; 188f0cc3246Seric *avp++ = &q[1]; 189f0cc3246Seric } 190f0cc3246Seric else 191f0cc3246Seric *q = *p; 192f0cc3246Seric } 193f0cc3246Seric *q = '\0'; 194f0cc3246Seric *avp = NULL; 195f0cc3246Seric xcommand(&argv[1], *p != '\0', nav[0], nav[1], nav[2], 196f0cc3246Seric nav[3], nav[4], nav[5], nav[6]); 1971777fbcbSeric } 1981777fbcbSeric fprintf(stderr, "Sccs internal error: CMACRO\n"); 1997de81dc7Seric exit(EX_SOFTWARE); 2007de81dc7Seric 201172147faSeric case FIX: /* fix a delta */ 202b2538d76Seric if (strcmpn(argv[1], "-r", 2) != 0) 203172147faSeric { 204172147faSeric fprintf(stderr, "Sccs: -r flag needed for fix command\n"); 205172147faSeric break; 206172147faSeric } 207172147faSeric xcommand(&argv[1], TRUE, "get", "-k", NULL); 208172147faSeric xcommand(&argv[1], TRUE, "rmdel", NULL); 209172147faSeric xcommand(&argv[2], FALSE, "get", "-e", "-g", NULL); 210172147faSeric fprintf(stderr, "Sccs internal error: FIX\n"); 211172147faSeric exit(EX_SOFTWARE); 212172147faSeric 213b2538d76Seric case CLEAN: 2143a208c77Seric clean((bool) cmd->sccspath); 215b2538d76Seric break; 216b2538d76Seric 217e39a5722Seric case UNEDIT: 218e39a5722Seric for (avp = &argv[1]; *avp != NULL; avp++) 219e39a5722Seric unedit(*avp); 220e39a5722Seric break; 221e39a5722Seric 2227de81dc7Seric default: 2237de81dc7Seric fprintf(stderr, "Sccs internal error: oper %d\n", cmd->sccsoper); 2247de81dc7Seric exit(EX_SOFTWARE); 2257de81dc7Seric } 2267de81dc7Seric } 227b1ed8a43Seric /* 228b1ed8a43Seric ** LOOKUP -- look up an SCCS command name. 229b1ed8a43Seric ** 230b1ed8a43Seric ** Parameters: 231b1ed8a43Seric ** name -- the name of the command to look up. 232b1ed8a43Seric ** 233b1ed8a43Seric ** Returns: 234b1ed8a43Seric ** ptr to command descriptor for this command. 235b1ed8a43Seric ** NULL if no such entry. 236b1ed8a43Seric ** 237b1ed8a43Seric ** Side Effects: 238b1ed8a43Seric ** none. 239b1ed8a43Seric */ 240b1ed8a43Seric 241b1ed8a43Seric struct sccsprog * 242b1ed8a43Seric lookup(name) 243b1ed8a43Seric char *name; 244b1ed8a43Seric { 245b1ed8a43Seric register struct sccsprog *cmd; 246b1ed8a43Seric 247b1ed8a43Seric for (cmd = SccsProg; cmd->sccsname != NULL; cmd++) 248b1ed8a43Seric { 249b1ed8a43Seric if (strcmp(cmd->sccsname, name) == 0) 250b1ed8a43Seric return (cmd); 251b1ed8a43Seric } 252b1ed8a43Seric return (NULL); 253b1ed8a43Seric } 2547de81dc7Seric 255172147faSeric 256172147faSeric xcommand(argv, forkflag, arg0) 257172147faSeric char **argv; 258172147faSeric bool forkflag; 259172147faSeric char *arg0; 260172147faSeric { 261172147faSeric register char **av; 262172147faSeric char *newargv[1000]; 263172147faSeric register char **np; 264172147faSeric 265172147faSeric np = newargv; 266172147faSeric for (av = &arg0; *av != NULL; av++) 267172147faSeric *np++ = *av; 268172147faSeric for (av = argv; *av != NULL; av++) 269172147faSeric *np++ = *av; 270172147faSeric *np = NULL; 271172147faSeric command(newargv, forkflag); 272172147faSeric } 273172147faSeric 2747de81dc7Seric callprog(progpath, flags, argv, forkflag) 2757de81dc7Seric char *progpath; 2767de81dc7Seric short flags; 2777de81dc7Seric char **argv; 2787de81dc7Seric bool forkflag; 2797de81dc7Seric { 2807de81dc7Seric register char *p; 2817de81dc7Seric register char **av; 2827de81dc7Seric extern char *makefile(); 2837de81dc7Seric register int i; 2841777fbcbSeric auto int st; 2857de81dc7Seric 2867de81dc7Seric if (*argv == NULL) 2877de81dc7Seric return (-1); 288c4432be4Seric 289c4432be4Seric /* 290172147faSeric ** Fork if appropriate. 291adf8f7d4Seric */ 292adf8f7d4Seric 2937de81dc7Seric if (forkflag) 2947de81dc7Seric { 295f0cc3246Seric # ifdef DEBUG 296f0cc3246Seric if (Debug) 297f0cc3246Seric printf("Forking\n"); 298f0cc3246Seric # endif 2997de81dc7Seric i = fork(); 3007de81dc7Seric if (i < 0) 3017de81dc7Seric { 3027de81dc7Seric fprintf(stderr, "Sccs: cannot fork"); 3037de81dc7Seric exit(EX_OSERR); 3047de81dc7Seric } 3057de81dc7Seric else if (i > 0) 3061777fbcbSeric { 3071777fbcbSeric wait(&st); 3081777fbcbSeric return (st); 3091777fbcbSeric } 3107de81dc7Seric } 3117de81dc7Seric 3127de81dc7Seric /* 313172147faSeric ** Build new argument vector. 314172147faSeric */ 315172147faSeric 316172147faSeric /* copy program filename arguments and flags */ 317172147faSeric av = argv; 318172147faSeric while ((p = *++av) != NULL) 319172147faSeric { 320172147faSeric if (!bitset(NO_SDOT, flags) && *p != '-') 321172147faSeric *av = makefile(p); 322172147faSeric } 323172147faSeric 324172147faSeric /* 3257de81dc7Seric ** Set protection as appropriate. 3267de81dc7Seric */ 3277de81dc7Seric 3287de81dc7Seric if (bitset(REALUSER, flags)) 3297de81dc7Seric setuid(getuid()); 3307de81dc7Seric 3317de81dc7Seric /* 332172147faSeric ** Call real SCCS program. 3337de81dc7Seric */ 3347de81dc7Seric 335172147faSeric execv(progpath, argv); 336adf8f7d4Seric fprintf(stderr, "Sccs: cannot execute "); 3377de81dc7Seric perror(progpath); 338adf8f7d4Seric exit(EX_UNAVAILABLE); 339adf8f7d4Seric } 340adf8f7d4Seric 341adf8f7d4Seric 342adf8f7d4Seric char * 343adf8f7d4Seric makefile(name) 344adf8f7d4Seric char *name; 345adf8f7d4Seric { 346adf8f7d4Seric register char *p; 347adf8f7d4Seric register char c; 348adf8f7d4Seric char buf[512]; 349adf8f7d4Seric struct stat stbuf; 350adf8f7d4Seric extern char *malloc(); 351adf8f7d4Seric 352adf8f7d4Seric /* 353adf8f7d4Seric ** See if this filename should be used as-is. 354adf8f7d4Seric ** There are three conditions where this can occur. 355adf8f7d4Seric ** 1. The name already begins with "s.". 356adf8f7d4Seric ** 2. The name has a "/" in it somewhere. 357adf8f7d4Seric ** 3. The name references a directory. 358adf8f7d4Seric */ 359adf8f7d4Seric 360b2538d76Seric if (strcmpn(name, "s.", 2) == 0) 361adf8f7d4Seric return (name); 362adf8f7d4Seric for (p = name; (c = *p) != '\0'; p++) 363adf8f7d4Seric { 364adf8f7d4Seric if (c == '/') 365adf8f7d4Seric return (name); 366adf8f7d4Seric } 367adf8f7d4Seric if (stat(name, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) == S_IFDIR) 368adf8f7d4Seric return (name); 369adf8f7d4Seric 370adf8f7d4Seric /* 371adf8f7d4Seric ** Prepend the path of the sccs file. 372adf8f7d4Seric */ 373adf8f7d4Seric 374adf8f7d4Seric strcpy(buf, SccsPath); 375c4432be4Seric strcat(buf, "/s."); 376adf8f7d4Seric strcat(buf, name); 377adf8f7d4Seric p = malloc(strlen(buf) + 1); 378adf8f7d4Seric if (p == NULL) 379adf8f7d4Seric { 380adf8f7d4Seric perror("Sccs: no mem"); 381adf8f7d4Seric exit(EX_OSERR); 382adf8f7d4Seric } 383adf8f7d4Seric strcpy(p, buf); 384adf8f7d4Seric return (p); 385adf8f7d4Seric } 386b2538d76Seric /* 387b2538d76Seric ** CLEAN -- clean out recreatable files 388b2538d76Seric ** 389b2538d76Seric ** Any file for which an "s." file exists but no "p." file 390b2538d76Seric ** exists in the current directory is purged. 391b2538d76Seric ** 392b2538d76Seric ** Parameters: 3933a208c77Seric ** really -- if TRUE, remove everything. 3943a208c77Seric ** else, just report status. 395b2538d76Seric ** 396b2538d76Seric ** Returns: 397b2538d76Seric ** none. 398b2538d76Seric ** 399b2538d76Seric ** Side Effects: 400b2538d76Seric ** removes files in the current directory. 401b2538d76Seric */ 402b2538d76Seric 4033a208c77Seric clean(really) 4043a208c77Seric bool really; 405b2538d76Seric { 406b2538d76Seric struct direct dir; 407b2538d76Seric struct stat stbuf; 408b2538d76Seric char buf[100]; 409bf9c1e66Seric char pline[120]; 4103a208c77Seric register FILE *dirfd; 4113a208c77Seric register char *basefile; 4122caac8fdSeric bool gotedit; 413bf9c1e66Seric FILE *pfp; 414b2538d76Seric 415b2538d76Seric dirfd = fopen(SccsPath, "r"); 416b2538d76Seric if (dirfd == NULL) 417b2538d76Seric { 418b2538d76Seric fprintf(stderr, "Sccs: cannot open %s\n", SccsPath); 419b2538d76Seric return; 420b2538d76Seric } 421b2538d76Seric 422b2538d76Seric /* 423b2538d76Seric ** Scan the SCCS directory looking for s. files. 424b2538d76Seric */ 425b2538d76Seric 4262caac8fdSeric gotedit = FALSE; 427b2538d76Seric while (fread(&dir, sizeof dir, 1, dirfd) != NULL) 428b2538d76Seric { 429b2538d76Seric if (dir.d_ino == 0 || strcmpn(dir.d_name, "s.", 2) != 0) 430b2538d76Seric continue; 431b2538d76Seric 432b2538d76Seric /* got an s. file -- see if the p. file exists */ 433b2538d76Seric strcpy(buf, SccsPath); 434b2538d76Seric strcat(buf, "/p."); 4353a208c77Seric basefile = &buf[strlen(buf)]; 4363a208c77Seric strcpyn(basefile, &dir.d_name[2], sizeof dir.d_name - 2); 437bf9c1e66Seric basefile[sizeof dir.d_name - 2] = '\0'; 438bf9c1e66Seric pfp = fopen(buf, "r"); 439bf9c1e66Seric if (pfp != NULL) 4403a208c77Seric { 441bf9c1e66Seric while (fgets(pline, sizeof pline, pfp) != NULL) 442*2444cd3eSeric printf("%12s: being edited: %s", basefile, pline); 443bf9c1e66Seric fclose(pfp); 4442caac8fdSeric gotedit = TRUE; 445b2538d76Seric continue; 4463a208c77Seric } 447b2538d76Seric 448b2538d76Seric /* the s. file exists and no p. file exists -- unlink the g-file */ 4493a208c77Seric if (really) 4503a208c77Seric { 451b2538d76Seric strcpyn(buf, &dir.d_name[2], sizeof dir.d_name - 2); 4523a208c77Seric buf[sizeof dir.d_name - 2] = '\0'; 453b2538d76Seric unlink(buf); 454b2538d76Seric } 4553a208c77Seric } 456b2538d76Seric 457b2538d76Seric fclose(dirfd); 4582caac8fdSeric if (!gotedit && !really) 459*2444cd3eSeric printf("Nothing being edited\n"); 460b2538d76Seric } 461e39a5722Seric /* 462e39a5722Seric ** UNEDIT -- unedit a file 463e39a5722Seric ** 464e39a5722Seric ** Checks to see that the current user is actually editting 465e39a5722Seric ** the file and arranges that s/he is not editting it. 466e39a5722Seric ** 467e39a5722Seric ** Parameters: 468*2444cd3eSeric ** fn -- the name of the file to be unedited. 469e39a5722Seric ** 470e39a5722Seric ** Returns: 471e39a5722Seric ** none. 472e39a5722Seric ** 473e39a5722Seric ** Side Effects: 474e39a5722Seric ** fn is removed 475e39a5722Seric ** entries are removed from pfile. 476e39a5722Seric */ 477e39a5722Seric 478e39a5722Seric unedit(fn) 479e39a5722Seric char *fn; 480e39a5722Seric { 481e39a5722Seric register FILE *pfp; 482e39a5722Seric char *pfn; 483e39a5722Seric static char tfn[] = "/tmp/sccsXXXXX"; 484e39a5722Seric FILE *tfp; 485e39a5722Seric register char *p; 486e39a5722Seric register char *q; 487e39a5722Seric bool delete = FALSE; 488e39a5722Seric bool others = FALSE; 489e39a5722Seric char *myname; 490e39a5722Seric extern char *getlogin(); 491e39a5722Seric struct pfile *pent; 492e39a5722Seric extern struct pfile *getpfile(); 493e39a5722Seric char buf[120]; 494e39a5722Seric 495e39a5722Seric /* make "s." filename & find the trailing component */ 496e39a5722Seric pfn = makefile(fn); 497e39a5722Seric q = &pfn[strlen(pfn) - 1]; 498e39a5722Seric while (q > pfn && *q != '/') 499e39a5722Seric q--; 500e39a5722Seric if (q <= pfn && (q[0] != 's' || q[1] != '.')) 501e39a5722Seric { 502e39a5722Seric fprintf(stderr, "Sccs: bad file name \"%s\"\n", fn); 503e39a5722Seric return; 504e39a5722Seric } 505e39a5722Seric 506e39a5722Seric /* turn "s." into "p." */ 507e39a5722Seric *++q = 'p'; 508e39a5722Seric 509e39a5722Seric pfp = fopen(pfn, "r"); 510e39a5722Seric if (pfp == NULL) 511e39a5722Seric { 512*2444cd3eSeric printf("%12s: not being edited\n", fn); 513e39a5722Seric return; 514e39a5722Seric } 515e39a5722Seric 516e39a5722Seric /* 517e39a5722Seric ** Copy p-file to temp file, doing deletions as needed. 518e39a5722Seric */ 519e39a5722Seric 520e39a5722Seric mktemp(tfn); 521e39a5722Seric tfp = fopen(tfn, "w"); 522e39a5722Seric if (tfp == NULL) 523e39a5722Seric { 524e39a5722Seric fprintf(stderr, "Sccs: cannot create \"%s\"\n", tfn); 525e39a5722Seric exit(EX_OSERR); 526e39a5722Seric } 527e39a5722Seric 528e39a5722Seric myname = getlogin(); 529e39a5722Seric while ((pent = getpfile(pfp)) != NULL) 530e39a5722Seric { 531e39a5722Seric if (strcmp(pent->p_user, myname) == 0) 532e39a5722Seric { 533e39a5722Seric /* a match */ 534e39a5722Seric delete++; 535e39a5722Seric } 536e39a5722Seric else 537e39a5722Seric { 538e39a5722Seric fprintf(tfp, "%s %s %s %s %s\n", pent->p_osid, 539e39a5722Seric pent->p_nsid, pent->p_user, pent->p_date, 540e39a5722Seric pent->p_time); 541e39a5722Seric others++; 542e39a5722Seric } 543e39a5722Seric } 544e39a5722Seric 545e39a5722Seric /* do final cleanup */ 546e39a5722Seric if (others) 547e39a5722Seric { 548e39a5722Seric if (freopen(tfn, "r", tfp) == NULL) 549e39a5722Seric { 550e39a5722Seric fprintf(stderr, "Sccs: cannot reopen \"%s\"\n", tfn); 551e39a5722Seric exit(EX_OSERR); 552e39a5722Seric } 553e39a5722Seric if (freopen(pfn, "w", pfp) == NULL) 554e39a5722Seric { 555e39a5722Seric fprintf(stderr, "Sccs: cannot create \"%s\"\n", pfn); 556e39a5722Seric return; 557e39a5722Seric } 558e39a5722Seric while (fgets(buf, sizeof buf, tfp) != NULL) 559e39a5722Seric fputs(buf, pfp); 560e39a5722Seric } 561e39a5722Seric else 562e39a5722Seric { 563e39a5722Seric unlink(pfn); 564e39a5722Seric } 565e39a5722Seric fclose(tfp); 566e39a5722Seric fclose(pfp); 567e39a5722Seric unlink(tfn); 568e39a5722Seric 569e39a5722Seric if (delete) 570e39a5722Seric { 571e39a5722Seric unlink(fn); 572e39a5722Seric printf("%12s: removed\n", fn); 573e39a5722Seric } 574e39a5722Seric else 575e39a5722Seric { 576*2444cd3eSeric printf("%12s: not being edited by you\n", fn); 577e39a5722Seric } 578e39a5722Seric } 579e39a5722Seric /* 580e39a5722Seric ** GETPFILE -- get an entry from the p-file 581e39a5722Seric ** 582e39a5722Seric ** Parameters: 583e39a5722Seric ** pfp -- p-file file pointer 584e39a5722Seric ** 585e39a5722Seric ** Returns: 586e39a5722Seric ** pointer to p-file struct for next entry 587e39a5722Seric ** NULL on EOF or error 588e39a5722Seric ** 589e39a5722Seric ** Side Effects: 590e39a5722Seric ** Each call wipes out results of previous call. 591e39a5722Seric */ 592e39a5722Seric 593e39a5722Seric struct pfile * 594e39a5722Seric getpfile(pfp) 595e39a5722Seric FILE *pfp; 596e39a5722Seric { 597e39a5722Seric static struct pfile ent; 598e39a5722Seric static char buf[120]; 599e39a5722Seric register char *p; 600e39a5722Seric extern char *nextfield(); 601e39a5722Seric 602e39a5722Seric if (fgets(buf, sizeof buf, pfp) == NULL) 603e39a5722Seric return (NULL); 604e39a5722Seric 605e39a5722Seric ent.p_osid = p = buf; 606e39a5722Seric ent.p_nsid = p = nextfield(p); 607e39a5722Seric ent.p_user = p = nextfield(p); 608e39a5722Seric ent.p_date = p = nextfield(p); 609e39a5722Seric ent.p_time = p = nextfield(p); 610e39a5722Seric if (p == NULL || nextfield(p) != NULL) 611e39a5722Seric return (NULL); 612e39a5722Seric 613e39a5722Seric return (&ent); 614e39a5722Seric } 615e39a5722Seric 616e39a5722Seric 617e39a5722Seric char * 618e39a5722Seric nextfield(p) 619e39a5722Seric register char *p; 620e39a5722Seric { 621e39a5722Seric if (p == NULL || *p == '\0') 622e39a5722Seric return (NULL); 623e39a5722Seric while (*p != ' ' && *p != '\n' && *p != '\0') 624e39a5722Seric p++; 625e39a5722Seric if (*p == '\n' || *p == '\0') 626e39a5722Seric { 627e39a5722Seric *p = '\0'; 628e39a5722Seric return (NULL); 629e39a5722Seric } 630e39a5722Seric *p++ = '\0'; 631e39a5722Seric return (p); 632e39a5722Seric } 633