findnewrcs.c 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these librararies and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /***************************************************************************
  24. *
  25. * File: findnewrcs.c
  26. * RCS: $XConsortium: findnewrcs.c /main/3 1995/10/30 13:42:46 rswiston $
  27. * Description: The 'findnewrcs' command is used to descend a tree, checking
  28. * out the newest version of any RCS file which has been updated.
  29. * It can also be used to create a clone of a source tree using
  30. * symbolic links.
  31. * Author: Dave Serisky, Corvallis Workstation Operation
  32. * Created: Tue Jun 7 09:39:47 1988
  33. * Modified: Brian Cripe, (bcripe@hpcvlx) bcripe@hpcvxbc
  34. * Modified: Marc Ayotte, (marca@hpcvlx)
  35. * Language: C
  36. * Package: N/A
  37. * Status: Experimental (Do Not Distribute)
  38. *
  39. * (c) Copyright 1988, Hewlett-Packard Company, all rights reserved.
  40. *
  41. ********************************************************************************
  42. */
  43. static char version[] = "@(#) $XConsortium: findnewrcs.c /main/3 1995/10/30 13:42:46 rswiston $";
  44. #include <stdio.h>
  45. #include <string.h>
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #ifdef apollo
  49. #ifndef S_ISLNK
  50. #define S_ISLNK(m) (((m) & 0170000) == 0120000)
  51. #endif
  52. #ifndef S_ISDIR
  53. #define S_ISDIR(m) (((m) & 0170000) == 0040000)
  54. #endif
  55. #ifndef S_ISREG
  56. #define S_ISREG(m) (((m) & 0170000) == 0100000)
  57. #endif
  58. #define UID_NO_CHANGE -1
  59. #include <sys/dir.h>
  60. #else
  61. # if defined(USL) && !defined(S_ISLNK)
  62. # define S_ISLNK(m) ((m&0xF000) == S_IFLNK)
  63. # endif
  64. #include <dirent.h>
  65. #endif
  66. #ifndef __hpux
  67. #define UID_NO_CHANGE -1
  68. #endif
  69. #include <errno.h>
  70. #include <fcntl.h>
  71. #include <grp.h>
  72. #ifdef apollo
  73. #include <sys/time.h>
  74. #else
  75. #include <utime.h>
  76. #endif
  77. extern char *getcwd();
  78. extern char *malloc();
  79. extern DIR *opendir();
  80. #ifdef apollo
  81. extern struct direct *readdir();
  82. #else
  83. extern struct dirent *readdir();
  84. #endif
  85. extern long telldir();
  86. extern char *mktemp();
  87. char Buffer[BUFSIZ];
  88. char *WorkingDirCmp;
  89. int WorkingLen;
  90. char *SourceDirCmp;
  91. int SourceLen;
  92. void GetNew();
  93. char *ResolveLink();
  94. static int Debug = 0;
  95. static int Quiet = 0;
  96. static int Verbose = 0;
  97. static int MakeDirs = 0;
  98. static int DoDiffs = 0;
  99. static int SourcePriority = 0;
  100. static int NoRcsLinks = 0;
  101. static int NoRealFiles = 0;
  102. static int LinkFiles = 0;
  103. static int CloneDotA = 0;
  104. static int CloneDotO = 0;
  105. static int CloneMakefile = 0;
  106. static int CloneExecutables = 0;
  107. static int Check = 0;
  108. static int DoExecute = 0;
  109. static int FollowDirLinks = 0;
  110. static int ResolveFileLinks = 1;
  111. static int ProcessSCCSdirs = 0;
  112. static char *DiffCommand = "diff";
  113. static char *OutFile = "/tmp/,outXXXXXX";
  114. static char *Makefile = "Makefile";
  115. typedef struct _flist {
  116. char *fullname;
  117. char *keyname;
  118. int keylen;
  119. int used;
  120. struct stat st;
  121. int st_valid;
  122. struct stat lst;
  123. int lst_valid;
  124. struct _flist *next;
  125. } flist;
  126. void
  127. Usage(ProgName)
  128. char *ProgName;
  129. {
  130. (void) fprintf(stderr, "\
  131. usage: %s [options] [-W <working dir>] [-S <RCS dir>] [subdir ...] \n\
  132. \n\
  133. options:\n\
  134. -i[Aaoxm]\n\
  135. clone: A - all the following\n\
  136. a - \"*.a\" files\n\
  137. o - \"*.o\" files\n\
  138. x - executables ('x' mode bits set)\n\
  139. m - \"Makefile*\" files\n\
  140. -v verbose (the more, the verboser)\n\
  141. source files\n\
  142. -L take checked out source over RCS regardless of time\n\
  143. -O don't check out new files, Only create symbolic links to exiting files\n\
  144. (this option is for cloning build trees from controlled source trees)\n\
  145. -R don't create any RCS links\n\
  146. -l symbolicly link files instead of copying them\n\
  147. -m make any missing directories\n\
  148. -q quiet\n\
  149. -d diff new versions of existing files\n\
  150. -c<cmd> use <cmd> to do diffs (default is diffc)\n\
  151. -o<out> write diffs to <out> instead of /tmp/,out??????\n\
  152. -W<dir> use working directory <dir> (default is \".\")\n\
  153. -S<dir> use RCS/source directory <dir>\n\
  154. (default is /RCS directories of working tree)\n\
  155. -f follow source-tree links to non-RCS dirs (old behavior)\n\
  156. -X execute instead of generating shell script\n\
  157. -C process SCCS directories if present\n\
  158. -s do not resolve symbolic links for files. use file name\n\
  159. ", ProgName);
  160. (void) exit(1);
  161. }
  162. static void do_rm_rf(), do_touch(), do_ln_s(), do_diff(), do_rm_f();
  163. static void do_cp(), do_chmod(), do_co_q(), do_mkdir(), do_chgrp();
  164. main(argc, argv)
  165. int argc;
  166. char **argv;
  167. {
  168. char *WorkingDir = (char *) 0;
  169. char *SourceDir = (char *) 0;
  170. register int i;
  171. register char *c;
  172. int same = 0;
  173. struct stat st;
  174. extern int getopt();
  175. extern char *optarg;
  176. extern int optind;
  177. extern int opterr;
  178. (void) setvbuf(stdout, (char *) 0, _IOLBF, BUFSIZ);
  179. OutFile = mktemp(OutFile);
  180. while ((i = getopt(argc, argv, "-S:-W:i:OLRXflsCmqvd~c:o:")) != EOF) {
  181. switch (i) {
  182. case 'W' :
  183. /* Working directory. Default is current directory */
  184. WorkingDir = optarg;
  185. break;
  186. case 'S' :
  187. /* Source directory. Default is to use working directories
  188. ** /RCS directories.
  189. */
  190. SourceDir = optarg;
  191. break;
  192. case 'i' :
  193. /* Parse off no ignore options */
  194. for (c = optarg; *c; c++) {
  195. switch (*c) {
  196. case 'A' :
  197. /* don't ignore any... */
  198. (void) CloneDotA++;
  199. (void) CloneDotO++;
  200. (void) CloneExecutables++;
  201. (void) CloneMakefile++;
  202. break;
  203. case 'a' :
  204. /* don't ignore *.a files */
  205. (void) CloneDotA++;
  206. break;
  207. case 'o' :
  208. /* don't ignore *.o files */
  209. (void) CloneDotO++;
  210. break;
  211. case 'x' :
  212. /* don't ignore executables */
  213. (void) CloneExecutables++;
  214. break;
  215. case 'm' :
  216. /* don't ignore Makefiles */
  217. (void) CloneMakefile++;
  218. break;
  219. default :
  220. (void) Usage(argv[0]);
  221. (void) exit(1);
  222. break;
  223. }
  224. }
  225. break;
  226. case 'R' :
  227. /* dont create any links for "/RCS" */
  228. (void) NoRcsLinks++;
  229. break;
  230. case 'L' :
  231. /* Take existing checked out files even if they are older than
  232. ** the RCS copy.
  233. */
  234. (void) SourcePriority++;
  235. break;
  236. case 'O' :
  237. /* Don't check out new files, just create sym links to existing files.
  238. ** This is to protect controlled source/build trees from having
  239. ** files bypass the crt process.
  240. */
  241. (void) NoRealFiles++;
  242. break;
  243. case 'f' :
  244. FollowDirLinks = 1;
  245. break;
  246. case 'C' :
  247. ProcessSCCSdirs = 1;
  248. break;
  249. case 'X' :
  250. DoExecute = 1;
  251. break;
  252. case 'l' :
  253. /* Link files (when possible) instead of creating them. */
  254. (void) LinkFiles++;
  255. break;
  256. case 'm' :
  257. /* Make any directories necessary. */
  258. (void) MakeDirs++;
  259. break;
  260. case 'q' :
  261. /* Be quiet. */
  262. (void) Quiet++;
  263. break;
  264. case 'v' :
  265. /* Increase verbosity. */
  266. (void) Verbose++;
  267. break;
  268. case 'd' :
  269. /* Diff out new files. */
  270. (void) DoDiffs++;
  271. break;
  272. case 'c' :
  273. /* Alternative diff command. */
  274. DiffCommand = optarg;
  275. break;
  276. case 'o' :
  277. /* Output file name for diffs */
  278. OutFile = optarg;
  279. break;
  280. case 's' :
  281. /* don't resolve symbolic links for files */
  282. ResolveFileLinks = 0;
  283. break;
  284. case '~' :
  285. /* Increment debug switch */
  286. (void) Debug++;
  287. break;
  288. default:
  289. (void) Usage(argv[0]);
  290. (void) exit(1);
  291. break;
  292. }
  293. }
  294. /* no WorkingDir specified or not root relative? */
  295. if (!WorkingDir || !*WorkingDir || ('/' != *WorkingDir)) {
  296. /* get the current directory */
  297. if (NULL == (c = getcwd(Buffer, sizeof(Buffer)))) {
  298. (void) fprintf(stderr, "%s: can't get current working directory\n",
  299. argv[0]);
  300. (void) exit(1);
  301. }
  302. /* did they specify a partial path? */
  303. if (WorkingDir && *WorkingDir) {
  304. /* prepend the path to the working dir */
  305. char *c2;
  306. c2 = malloc((unsigned) (strlen(c) + strlen(WorkingDir) + 2));
  307. (void) sprintf(c2, "%s/%s", c, WorkingDir);
  308. WorkingDir = c2;
  309. } else {
  310. /* working dir is current path */
  311. WorkingDir = malloc((unsigned) (strlen(c) + 1));
  312. (void) strcpy(WorkingDir, c);
  313. }
  314. }
  315. /* SourceDir specified? */
  316. if (!SourceDir || !*SourceDir) {
  317. /* Let's see if there is an /RCS dir in WorkingDir */
  318. SourceDir = malloc((unsigned) (strlen(WorkingDir) + 5));
  319. (void) strcpy(SourceDir, WorkingDir);
  320. (void) strcat(SourceDir, "/RCS");
  321. if (!lstat(SourceDir, &st)) {
  322. if (S_ISLNK(st.st_mode)) {
  323. SourceDir = ResolveLink(SourceDir, 1);
  324. }
  325. }
  326. /* strip off the "/RCS" portion of it */
  327. c = strrchr(SourceDir, '/');
  328. if (*c && !strcmp(c, "/RCS"))
  329. *c = '\0';
  330. (void) fprintf(stderr, "using sourcedir of \"%s\"\n", SourceDir);
  331. } else {
  332. /* is it root relative? */
  333. if ('/' != *SourceDir) {
  334. /* get the current directory */
  335. char *c2;
  336. if (NULL == (c = getcwd(Buffer, sizeof(Buffer)))) {
  337. (void) fprintf(stderr,
  338. "%s: can't get current working directory\n",
  339. argv[0]);
  340. (void) exit(1);
  341. }
  342. c2 = malloc((unsigned) (strlen(c) + strlen(SourceDir) + 2));
  343. (void) sprintf(c2, "%s/%s", c, SourceDir);
  344. SourceDir = c2;
  345. }
  346. }
  347. /* are the 2 directories the same name?
  348. */
  349. if (!strcmp(SourceDir, WorkingDir)) {
  350. (void) same++;
  351. }
  352. WorkingDirCmp = malloc((unsigned) (strlen(WorkingDir) + 2));
  353. (void) strcpy(WorkingDirCmp, WorkingDir);
  354. (void) strcat(WorkingDirCmp, "/");
  355. SourceDirCmp = malloc((unsigned) (strlen(SourceDir) + 2));
  356. (void) strcpy(SourceDirCmp, SourceDir);
  357. (void) strcat(SourceDirCmp, "/");
  358. WorkingLen = strlen(WorkingDirCmp);
  359. SourceLen = strlen(SourceDirCmp);
  360. if (DoExecute)
  361. {
  362. if (DoDiffs)
  363. {
  364. do_rm_rf(OutFile);
  365. do_touch(OutFile);
  366. }
  367. }
  368. else
  369. {
  370. printf("#!/bin/sh\n");
  371. printf("#\n# the following makes things more readeable\n\n");
  372. printf("w='%s'\t# Working directory\n", WorkingDir);
  373. printf("s='%s'\t# Source directory\n", SourceDir);
  374. if (DoDiffs)
  375. printf("rm -rf %s; touch %s\n", OutFile, OutFile);
  376. printf("\n");
  377. }
  378. if (optind < argc) {
  379. char *SubSourceDir;
  380. char *SubWorkingDir;
  381. for (; optind < argc; optind++) {
  382. SubSourceDir = malloc((unsigned) (strlen(SourceDir) +
  383. strlen(argv[optind]) + 2));
  384. (void) sprintf(SubSourceDir, "%s/%s", SourceDir, argv[optind]);
  385. SubWorkingDir = malloc((unsigned) (strlen(WorkingDir) +
  386. strlen(argv[optind]) + 2));
  387. (void) sprintf(SubWorkingDir, "%s/%s", WorkingDir, argv[optind]);
  388. (void) GetNew(SubWorkingDir, SubSourceDir, same);
  389. (void) free(SubWorkingDir);
  390. (void) free(SubSourceDir);
  391. }
  392. } else {
  393. (void) GetNew(WorkingDir, SourceDir, same);
  394. }
  395. (void) exit(0);
  396. /*NOTREACHED*/
  397. }
  398. void
  399. GetNew(WorkingDir, SourceDir, same)
  400. char *WorkingDir;
  401. char *SourceDir;
  402. int same;
  403. {
  404. FILE *f;
  405. char *NextSourceDir;
  406. char *NextWorkingDir;
  407. char *RcsDir;
  408. char *SourceFile;
  409. char *WorkingFile;
  410. int FreeSourceFile;
  411. int FreeWorkingFile;
  412. DIR *D;
  413. #ifdef apollo
  414. struct direct *dir;
  415. #else
  416. struct dirent *dir;
  417. #endif
  418. struct stat st;
  419. int Tries;
  420. char *c,*d;
  421. char buf[BUFSIZ];
  422. flist *WorkingHead = (flist *) 0;
  423. flist *SourceHead = (flist *) 0;
  424. flist *RcsHead = (flist *) 0;
  425. flist *WorkingPtr;
  426. flist *SourcePtr;
  427. flist *RcsPtr;
  428. int shouldnt_have_source;
  429. if (Verbose)
  430. (void) fprintf(stderr, "Scanning directory \"%s\"\n", SourceDir);
  431. if (Debug > 1)
  432. (void) fprintf(stderr, ">> GetNew(\"%s\", \"%s\")\n", WorkingDir,
  433. SourceDir);
  434. /* set up the working directory's RCS directory name */
  435. RcsDir = malloc((unsigned char *) strlen(WorkingDir) + strlen("/RCS") + 1);
  436. (void) sprintf(RcsDir, "%s/RCS", WorkingDir);
  437. if (Debug > 0)
  438. (void) fprintf(stderr, ">> RcsDir=\"%s\"\n", RcsDir);
  439. /* check to see if the working dir's RCS directory exists */
  440. /* if you can't stat it and it is a symlink to nowhere, do not
  441. * recreate the link. The cde source server works on RCS symlinks
  442. * to nowhere.
  443. */
  444. if (stat(RcsDir, &st)) {
  445. /* if not a symlink, create the RCS directory */
  446. if (readlink(RcsDir, buf, sizeof(buf)) < 0) {
  447. /* no -- create one off of the SourceDir */
  448. c = malloc((unsigned char *) strlen(SourceDir) +
  449. strlen("/RCS") + 1);
  450. (void) sprintf(c, "%s/RCS", SourceDir);
  451. d = malloc((unsigned char *) strlen(SourceDir) +
  452. strlen("/RCS") + 1);
  453. (void) sprintf(d, "%s/RCS", SourceDir);
  454. /* resolve out symbolic links */
  455. c = ResolveLink(c, 1);
  456. if (Debug > 0)
  457. (void) fprintf(stderr, ">> RCS RcsDir=\"%s\"\n", c);
  458. /* do we want RCS links? */
  459. /* If Rcsdir points to a symlink, recreate the link
  460. * even if no destination directory exists.
  461. */
  462. if ((!stat(c, &st) || (readlink(d, buf, sizeof(buf)) > 0))
  463. && !NoRcsLinks) {
  464. /* yes -- since the WorkingDir didn't have an /RCS directory,
  465. ** let's make one.
  466. */
  467. if (!Quiet)
  468. (void) fprintf(stderr, "%s: creating symlink\n",
  469. RcsDir + WorkingLen);
  470. /* check and see if the RCS dir is in the SourceDir */
  471. if (DoExecute)
  472. {
  473. do_rm_f(RcsDir);
  474. do_ln_s(c, RcsDir);
  475. }
  476. else
  477. {
  478. /* remove the link before linking */
  479. (void) printf("rm -f ${w}/%s\n",
  480. RcsDir + WorkingLen);
  481. if (strncmp(c, SourceDir, SourceLen) ||
  482. (c[SourceLen] != '/')) {
  483. /* need full RCS path */
  484. (void) printf("ln -s %s ${w}/%s\n",
  485. c, RcsDir + WorkingLen);
  486. }
  487. else {
  488. /* RCS path is relative to SourceDir */
  489. (void) printf("ln -s ${s}/%s ${w}/%s\n",
  490. c + SourceLen, RcsDir + WorkingLen);
  491. }
  492. }
  493. }
  494. (void) free(RcsDir);
  495. RcsDir = c;
  496. }
  497. }
  498. /* resolve "fake" symbolic links to get a real directory */
  499. for (Tries = 10; Tries > 0; Tries--) {
  500. if (!lstat(RcsDir, &st)) {
  501. if (S_ISLNK(st.st_mode)) {
  502. RcsDir = ResolveLink(RcsDir, 1);
  503. } else if (S_ISREG(st.st_mode)) {
  504. /* open the file... */
  505. if (f = fopen(RcsDir, "r")) {
  506. /* read it... */
  507. (void) fgets(Buffer, sizeof(Buffer), f);
  508. Buffer[strlen(Buffer) - 1] = '\0';
  509. (void) free(RcsDir);
  510. /* RcsDir is the contents of the file... */
  511. RcsDir = malloc((unsigned) strlen(Buffer) + 1);
  512. (void) strcpy(RcsDir, Buffer);
  513. if (Debug)
  514. (void) fprintf(stderr, ">> soft link RcsDir=\"%s\"\n",
  515. RcsDir);
  516. /* we are done, close it... */
  517. (void) fclose(f);
  518. }
  519. } else {
  520. /* not a symlink or "soft" link */
  521. break;
  522. }
  523. } else {
  524. /* directory does not exist */
  525. break;
  526. }
  527. }
  528. if (Tries <= 0) {
  529. if (!Quiet)
  530. (void) fprintf(stderr, "%s: >10 \"soft\" links\n", RcsDir);
  531. }
  532. /* cd to the RcsDir, and scan it */
  533. RcsHead = (flist *) 0;
  534. if (chdir(RcsDir)) {
  535. if (errno != ENOENT)
  536. (void) perror(RcsDir);
  537. } else {
  538. if (D = opendir(".")) {
  539. while (dir = readdir(D)) {
  540. /* all RCS files have a length > 2 */
  541. #ifndef apollo
  542. if (strlen(dir->d_name) < 3)
  543. #else
  544. if (dir->d_namlen < 3)
  545. #endif
  546. continue;
  547. /* all RCS files have a name ending in ",v" */
  548. #ifndef apollo
  549. if (strcmp(dir->d_name + strlen(dir->d_name) - 2, ",v"))
  550. #else
  551. if (strcmp(dir->d_name + dir->d_namlen - 2, ",v"))
  552. #endif
  553. continue;
  554. /* build the full name of the file */
  555. (void) strcpy(Buffer, RcsDir);
  556. (void) strcat(Buffer, "/");
  557. (void) strcat(Buffer, dir->d_name);
  558. /* stat the file */
  559. if (stat(dir->d_name, &st)) {
  560. (void) perror(Buffer);
  561. continue;
  562. }
  563. /* Valid entry. It's time to stuff it away */
  564. if (RcsHead) {
  565. RcsPtr->next = (flist *) malloc(sizeof(flist));
  566. RcsPtr = RcsPtr->next;
  567. } else {
  568. RcsHead = (flist *) malloc(sizeof(flist));
  569. RcsPtr = RcsHead;
  570. }
  571. /* null out link */
  572. RcsPtr->next = (flist *) 0;
  573. /* this entry is new */
  574. RcsPtr->used =0;
  575. /* stuff away full path */
  576. RcsPtr->fullname = malloc((unsigned) (strlen(Buffer) + 1));
  577. (void) strcpy(RcsPtr->fullname, Buffer);
  578. /* drop ",v" of dir->d_name */
  579. /* stuff away key path */
  580. #ifndef apollo
  581. dir->d_name[strlen(dir->d_name) - 2] = '\0';
  582. RcsPtr->keyname = malloc((unsigned) (strlen(dir->d_name) + 1));
  583. (void) strcpy(RcsPtr->keyname, dir->d_name);
  584. RcsPtr->keylen = strlen(dir->d_name);
  585. #else
  586. dir->d_name[dir->d_namlen - 2] = '\0';
  587. dir->d_namlen -= 2;
  588. RcsPtr->keyname = malloc((unsigned) (dir->d_namlen + 1));
  589. (void) strcpy(RcsPtr->keyname, dir->d_name);
  590. RcsPtr->keylen = dir->d_namlen;
  591. #endif
  592. /* stuff away stat structure */
  593. RcsPtr->st = st;
  594. RcsPtr->st_valid = 1;
  595. RcsPtr->lst_valid = 0;
  596. }
  597. (void) closedir(D);
  598. }
  599. }
  600. /* cd to the WorkingDir, and scan it */
  601. WorkingHead = (flist *) 0;
  602. if (chdir(WorkingDir)) {
  603. if (errno != ENOENT)
  604. (void) perror(WorkingDir);
  605. } else {
  606. if (D = opendir(".")) {
  607. while (dir = readdir(D)) {
  608. /* ignore "." and ".." */
  609. #ifndef apollo
  610. if (('.' == *(dir->d_name)) || (!strcmp(dir->d_name, "..")))
  611. continue;
  612. #else
  613. if (((1 == dir->d_namlen) && ('.' == *(dir->d_name))) ||
  614. ((2 == dir->d_namlen) && !strcmp(dir->d_name, "..")))
  615. continue;
  616. #endif
  617. /* build the full name of the file */
  618. (void) strcpy(Buffer, WorkingDir);
  619. (void) strcat(Buffer, "/");
  620. (void) strcat(Buffer, dir->d_name);
  621. /* stat the file */
  622. if (stat(dir->d_name, &st)) {
  623. /* don't send error if RCS directory is a
  624. * symlink to nowhere.
  625. */
  626. if (strcmp("RCS",dir->d_name)) {
  627. (void) perror(Buffer);
  628. }
  629. continue;
  630. }
  631. /* Valid entry. It's time to stuff it away */
  632. if (WorkingHead) {
  633. WorkingPtr->next = (flist *) malloc(sizeof(flist));
  634. WorkingPtr = WorkingPtr->next;
  635. } else {
  636. WorkingHead = (flist *) malloc(sizeof(flist));
  637. WorkingPtr = WorkingHead;
  638. }
  639. /* null out link */
  640. WorkingPtr->next = (flist *) 0;
  641. /* this entry is new */
  642. WorkingPtr->used =0;
  643. /* stuff away full path */
  644. WorkingPtr->fullname = malloc((unsigned) (strlen(Buffer) + 1));
  645. (void) strcpy(WorkingPtr->fullname, Buffer);
  646. /* stuff away key path */
  647. #ifndef apollo
  648. WorkingPtr->keyname = malloc((unsigned) (strlen(dir->d_name) + 1));
  649. (void) strcpy(WorkingPtr->keyname, dir->d_name);
  650. WorkingPtr->keylen = strlen(dir->d_name);
  651. #else
  652. WorkingPtr->keyname = malloc((unsigned) (dir->d_namlen + 1));
  653. (void) strcpy(WorkingPtr->keyname, dir->d_name);
  654. WorkingPtr->keylen = dir->d_namlen;
  655. #endif
  656. /* stuff away stat structure */
  657. WorkingPtr->st = st;
  658. WorkingPtr->st_valid = 1;
  659. if (S_ISDIR(st.st_mode) && !lstat(dir->d_name, &st))
  660. {
  661. WorkingPtr->lst = st;
  662. WorkingPtr->lst_valid = 1;
  663. }
  664. else
  665. WorkingPtr->lst_valid = 0;
  666. }
  667. (void) closedir(D);
  668. }
  669. }
  670. /* cd to the SourceDir, and scan it. If the dirs are the same, we
  671. ** can just forget this part
  672. */
  673. SourceHead = (flist *) 0;
  674. if (!same) {
  675. if (chdir(SourceDir)) {
  676. if (errno != ENOENT)
  677. (void) perror(SourceDir);
  678. } else {
  679. if (D = opendir(".")) {
  680. while (dir = readdir(D)) {
  681. /* ignore "." and ".." */
  682. #ifndef apollo
  683. if ((('.' == *(dir->d_name))) ||
  684. (!strcmp(dir->d_name, "..")))
  685. continue;
  686. #else
  687. if (((1 == dir->d_namlen) && ('.' == *(dir->d_name))) ||
  688. ((2 == dir->d_namlen) &&
  689. !strcmp(dir->d_name, "..")))
  690. continue;
  691. #endif
  692. /* build the full name of the file */
  693. (void) strcpy(Buffer, SourceDir);
  694. (void) strcat(Buffer, "/");
  695. (void) strcat(Buffer, dir->d_name);
  696. /* lstat the file */
  697. if (lstat(dir->d_name, &st)) {
  698. (void) perror(Buffer);
  699. continue;
  700. }
  701. /* Valid entry. It's time to stuff it away */
  702. if (SourceHead) {
  703. SourcePtr->next = (flist *) malloc(sizeof(flist));
  704. SourcePtr = SourcePtr->next;
  705. } else {
  706. SourceHead = (flist *) malloc(sizeof(flist));
  707. SourcePtr = SourceHead;
  708. }
  709. /* null out link */
  710. SourcePtr->next = (flist *) 0;
  711. /* this entry is new */
  712. SourcePtr->used =0;
  713. /* stuff away full path */
  714. SourcePtr->fullname =
  715. malloc((unsigned) (strlen(Buffer) + 1));
  716. (void) strcpy(SourcePtr->fullname, Buffer);
  717. /* stuff away key path */
  718. #ifndef apollo
  719. SourcePtr->keyname = malloc((unsigned) (strlen(dir->d_name) + 1));
  720. (void) strcpy(SourcePtr->keyname, dir->d_name);
  721. SourcePtr->keylen = strlen(dir->d_name);
  722. #else
  723. SourcePtr->keyname = malloc((unsigned) (dir->d_namlen + 1));
  724. (void) strcpy(SourcePtr->keyname, dir->d_name);
  725. SourcePtr->keylen = dir->d_namlen;
  726. #endif
  727. /* stuff away lstat structure */
  728. SourcePtr->lst = st;
  729. SourcePtr->lst_valid = 1;
  730. /* was it a symbolic link? */
  731. if (S_ISLNK(st.st_mode)) {
  732. /* do a plain stat on it */
  733. (void) stat(dir->d_name, &st);
  734. }
  735. /* stuff it away */
  736. SourcePtr->st = st;
  737. SourcePtr->st_valid = 1;
  738. }
  739. (void) closedir(D);
  740. }
  741. }
  742. }
  743. /*
  744. ** PASS 1:
  745. **
  746. ** Check all the files in the working dir.
  747. */
  748. if (Debug)
  749. (void) fprintf(stderr, ">> Pass 1: scanning WorkingDir \"%s\"\n",
  750. WorkingDir);
  751. for (WorkingPtr = WorkingHead; WorkingPtr; WorkingPtr = WorkingPtr->next) {
  752. /* initialize */
  753. if (Debug > 1)
  754. (void) fprintf(stderr, ">> keyname=\"%s\", fullname=\"%s\"\n",
  755. WorkingPtr->keyname, WorkingPtr->fullname);
  756. shouldnt_have_source = 0;
  757. /* ignore .o and .a files */
  758. c = WorkingPtr->keyname + WorkingPtr->keylen - 2;
  759. if (WorkingPtr->keylen >= 2) {
  760. if (!strcmp(c, ".o")) {
  761. (void) shouldnt_have_source++;
  762. if (!CloneDotO) {
  763. if (Debug > 1)
  764. (void) fprintf(stderr, ">> .o -- ignored\n");
  765. continue;
  766. }
  767. }
  768. if (!strcmp(c, ".a")) {
  769. (void) shouldnt_have_source++;
  770. if (!CloneDotA) {
  771. if (Debug > 1)
  772. (void) fprintf(stderr, ">> .a -- ignored\n");
  773. continue;
  774. }
  775. }
  776. }
  777. if (!strncmp(WorkingPtr->keyname, Makefile, strlen(Makefile))) {
  778. (void) shouldnt_have_source++;
  779. if (!CloneMakefile) {
  780. if (Debug > 1)
  781. (void) fprintf(stderr, ">> Makefile* -- ignored\n");
  782. continue;
  783. }
  784. }
  785. /* ignore RCS as well */
  786. if (!strcmp(WorkingPtr->keyname, "RCS")) {
  787. if (Debug > 1)
  788. (void) fprintf(stderr, ">> RCS -- ignored\n");
  789. continue;
  790. }
  791. /* ignore SCCS as well */
  792. if (!(ProcessSCCSdirs)) {
  793. if (!strcmp(WorkingPtr->keyname, "SCCS")) {
  794. if (Debug > 1)
  795. (void) fprintf(stderr, ">> SCCS -- ignored\n");
  796. continue;
  797. }
  798. }
  799. /* ignore regular files with x mode */
  800. if (!CloneExecutables && WorkingPtr->st_valid &&
  801. (S_ISREG(WorkingPtr->st.st_mode)) &&
  802. (0111 == (WorkingPtr->st.st_mode & 0111))) {
  803. if (Debug > 1)
  804. (void) fprintf(stderr, ">> executable -- ignored\n");
  805. continue;
  806. }
  807. /* find corresponding sourcefile */
  808. for (SourcePtr = SourceHead; SourcePtr; SourcePtr = SourcePtr->next) {
  809. if ((WorkingPtr->keylen == SourcePtr->keylen) &&
  810. !strcmp(WorkingPtr->keyname, SourcePtr->keyname)) {
  811. /* mark it as used */
  812. (void) SourcePtr->used++;
  813. break;
  814. }
  815. }
  816. if (Debug > 1)
  817. if (SourcePtr)
  818. (void) fprintf(stderr,
  819. " source: keyname=\"%s\" fullname=\"%s\"\n",
  820. SourcePtr->keyname, SourcePtr->fullname);
  821. else
  822. (void) fprintf(stderr, " no source file\n");
  823. /* is the working file actually a directory? */
  824. if (WorkingPtr->st_valid &&
  825. (S_ISDIR(WorkingPtr->st.st_mode))) {
  826. /* yes, go recursive... */
  827. if (FollowDirLinks ||
  828. !WorkingPtr->lst_valid ||
  829. !S_ISLNK(WorkingPtr->lst.st_mode))
  830. {
  831. if (Debug > 1)
  832. (void) fprintf(stderr, ">> directory\n");
  833. (void) GetNew(WorkingPtr->fullname,
  834. SourcePtr ? SourcePtr->fullname : WorkingPtr->fullname,
  835. same);
  836. }
  837. } else {
  838. /* find corresponding RCS file */
  839. for (RcsPtr = RcsHead; RcsPtr; RcsPtr = RcsPtr->next) {
  840. if ((WorkingPtr->keylen == RcsPtr->keylen) &&
  841. !strcmp(WorkingPtr->keyname, RcsPtr->keyname)) {
  842. /* mark it as used */
  843. (void) RcsPtr->used++;
  844. break;
  845. }
  846. }
  847. if (Debug > 1)
  848. if (RcsPtr)
  849. (void) fprintf(stderr,
  850. " rcs: keyname=\"%s\" fullname=\"%s\"\n",
  851. RcsPtr->keyname, RcsPtr->fullname);
  852. else
  853. (void) fprintf(stderr, " no rcs file\n");
  854. /* print a message if there is no corresponding source */
  855. if (!RcsPtr && !SourcePtr) {
  856. /* don't print a message for .snf files */
  857. if ((WorkingPtr->keylen > 4) && !strcmp(WorkingPtr->keyname +
  858. WorkingPtr->keylen - 4, ".snf"))
  859. (void) shouldnt_have_source++;
  860. if (Verbose && !shouldnt_have_source)
  861. (void) fprintf(stderr, "%s: no source or RCS file\n",
  862. WorkingPtr->fullname + WorkingLen);
  863. }
  864. if (!RcsPtr || !RcsPtr->st_valid ||
  865. (SourcePtr &&
  866. (SourcePtr->st.st_mtime >= RcsPtr->st.st_mtime)) ||
  867. (SourcePriority && SourcePtr)) {
  868. /* no RCS file, or source newer than RCS, or source
  869. ** exists and has priority
  870. */
  871. if (Debug > 1)
  872. (void) fprintf(stderr, ">> source newer than rcs\n");
  873. if (SourcePtr &&
  874. (WorkingPtr->st.st_mtime < SourcePtr->st.st_mtime)) {
  875. if (Debug > 1)
  876. (void) fprintf(stderr,
  877. ">> source newer than working\n");
  878. /* does the WorkingFile have any write mode bits
  879. ** set?
  880. */
  881. if (WorkingPtr->st.st_mode & 0222) {
  882. if (!Quiet)
  883. (void) fprintf(stderr,
  884. "%s: writable -- not updated\n",
  885. WorkingPtr->fullname + WorkingLen);
  886. continue;
  887. }
  888. if (!Quiet)
  889. (void) fprintf(stderr, "%s: newer file\n",
  890. WorkingPtr->fullname + WorkingLen);
  891. /* check to see if file symlinks should resolve */
  892. if (ResolveFileLinks)
  893. if (SourcePtr->lst_valid &&
  894. S_ISLNK(SourcePtr->lst.st_mode)) {
  895. SourceFile = ResolveLink(SourcePtr->fullname, 0);
  896. FreeSourceFile = 1;
  897. }
  898. else {
  899. SourceFile = SourcePtr->fullname;
  900. }
  901. else {
  902. SourceFile = SourcePtr->fullname;
  903. }
  904. /* do we need to do a diff? */
  905. if (DoDiffs) {
  906. if (DoExecute)
  907. {
  908. do_diff(NULL,
  909. DiffCommand,
  910. WorkingPtr->fullname,
  911. SourceFile,
  912. OutFile);
  913. }
  914. else
  915. {
  916. if (strncmp(SourceFile, SourceDirCmp, SourceLen))
  917. /* not in SourceDir... */
  918. (void) printf("%s ${w}/%s %s >>%s 2>&1\n",
  919. DiffCommand,
  920. WorkingPtr->fullname + WorkingLen,
  921. SourceFile, OutFile);
  922. else
  923. /* in SourceDir... */
  924. (void) printf("%s ${w}/%s ${s}/%s >>%s 2>&1\n",
  925. DiffCommand,
  926. WorkingPtr->fullname + WorkingLen,
  927. SourceFile + SourceLen, OutFile);
  928. }
  929. }
  930. if (DoExecute)
  931. {
  932. do_rm_f(WorkingPtr->fullname);
  933. if (LinkFiles)
  934. do_ln_s(SourceFile, WorkingPtr->fullname);
  935. else
  936. do_cp(SourceFile, WorkingPtr->fullname);
  937. }
  938. else
  939. {
  940. if (strncmp(SourceFile, SourceDirCmp, SourceLen)) {
  941. /* not in SourceDir... */
  942. (void) printf("rm -f ${w}/%s\n",
  943. WorkingPtr->fullname + WorkingLen);
  944. (void) printf("\t%s %s ${w}/%s\n",
  945. LinkFiles ? "ln -s" : "cp",
  946. SourceFile,
  947. WorkingPtr->fullname + WorkingLen);
  948. } else {
  949. /* in SourceDir... */
  950. (void) printf("rm -f ${w}/%s\n",
  951. WorkingPtr->fullname + WorkingLen);
  952. (void) printf("\t%s ${s}/%s ${w}/%s\n",
  953. LinkFiles ? "ln -s" : "cp",
  954. SourceFile + SourceLen,
  955. WorkingPtr->fullname + WorkingLen);
  956. }
  957. }
  958. if (!LinkFiles)
  959. {
  960. /* don't chmod the file if we did a link... */
  961. if (DoExecute)
  962. {
  963. do_chmod(WorkingPtr->fullname,
  964. (SourcePtr->st.st_mode & 07777 & ~0222) | 0444);
  965. }
  966. else
  967. (void) printf("\tchmod 0%03o ${w}/%s\n",
  968. (SourcePtr->st.st_mode & 07777 & ~0222) | 0444,
  969. WorkingPtr->fullname + WorkingLen);
  970. }
  971. if (FreeSourceFile)
  972. (void) free(SourceFile);
  973. } else {
  974. if (Debug > 1)
  975. (void) fprintf(stderr,
  976. ">> source older than working\n");
  977. }
  978. } else {
  979. /* RCS file is the newest */
  980. if (Debug > 1)
  981. (void) fprintf(stderr, ">> rcs newer than source\n");
  982. if (RcsPtr && (WorkingPtr->st.st_mtime < RcsPtr->st.st_mtime)) {
  983. if (Debug > 1)
  984. (void) fprintf(stderr,
  985. ">> rcs newer than working\n");
  986. /* does the WorkingFile have any write mode bits
  987. ** set?
  988. */
  989. if (WorkingPtr->st.st_mode & 0222) {
  990. if (!Quiet)
  991. (void) fprintf(stderr,
  992. "%s: writable -- not updated\n",
  993. WorkingPtr->fullname + WorkingLen);
  994. continue;
  995. }
  996. if (!Quiet)
  997. (void) fprintf(stderr, "%s: newer RCS file\n",
  998. WorkingPtr->fullname + WorkingLen);
  999. if (DoExecute)
  1000. {
  1001. do_diff(RcsDir, DiffCommand,
  1002. RcsPtr->keyname,
  1003. WorkingPtr->fullname,
  1004. OutFile);
  1005. if (! NoRealFiles)
  1006. {
  1007. do_co_q(RcsDir, WorkingPtr->fullname);
  1008. }
  1009. }
  1010. else
  1011. {
  1012. if (strncmp(RcsDir, SourceDir, SourceLen) ||
  1013. (RcsDir[SourceLen] != '/')) {
  1014. /* RcsDir is not in SourceDir */
  1015. if (DoDiffs) {
  1016. /* diff the file */
  1017. (void) printf("\t (cd %s; %s %s ${w}/%s >>%s 2>&1)\n",
  1018. RcsDir,
  1019. DiffCommand,
  1020. RcsPtr->keyname,
  1021. WorkingPtr->fullname + WorkingLen,
  1022. OutFile);
  1023. }
  1024. if (! NoRealFiles)
  1025. {
  1026. /* check out the file */
  1027. (void) printf("(cd %s; co -q ${w}/%s) \n",
  1028. RcsDir, WorkingPtr->fullname + WorkingLen);
  1029. }
  1030. } else {
  1031. /* RcsDir is in SourceDir */
  1032. if (DoDiffs) {
  1033. /* diff the file */
  1034. (void) printf("\t (cd ${s}/%s; %s %s ${w}/%s >>%s 2>&1)\n",
  1035. RcsDir + SourceLen,
  1036. DiffCommand,
  1037. RcsPtr->keyname,
  1038. WorkingPtr->fullname + WorkingLen,
  1039. OutFile);
  1040. }
  1041. if (! NoRealFiles)
  1042. {
  1043. /* check out the file */
  1044. (void) printf("(cd ${s}/%s; co -q ${w}/%s) \n",
  1045. RcsDir + SourceLen, WorkingPtr->fullname + WorkingLen);
  1046. }
  1047. }
  1048. }
  1049. } else {
  1050. if (Debug > 1)
  1051. (void) fprintf(stderr,
  1052. ">> source older than working\n");
  1053. }
  1054. }
  1055. }
  1056. }
  1057. /*
  1058. ** PASS 2:
  1059. ** Check all the files in the source (checked out) dir.
  1060. */
  1061. if (Debug)
  1062. (void) fprintf(stderr, ">> Pass 2: scanning SourceDir \"%s\"\n",
  1063. SourceDir);
  1064. for (SourcePtr = SourceHead; SourcePtr; SourcePtr = SourcePtr->next) {
  1065. /* did we get this one already? */
  1066. if (SourcePtr->used)
  1067. continue;
  1068. /* ignore "RCS" */
  1069. if (!strcmp(SourcePtr->keyname, "RCS"))
  1070. continue;
  1071. /* ignore SCCS as well */
  1072. if (!(ProcessSCCSdirs)) {
  1073. if (!strcmp(SourcePtr->keyname, "SCCS")) {
  1074. if (Debug > 1)
  1075. (void) fprintf(stderr, ">> SCCS -- ignored\n");
  1076. continue;
  1077. }
  1078. }
  1079. /* find corresponding RCS file */
  1080. for (RcsPtr = RcsHead; RcsPtr; RcsPtr = RcsPtr->next) {
  1081. if ((SourcePtr->keylen == RcsPtr->keylen) &&
  1082. !strcmp(SourcePtr->keyname, RcsPtr->keyname)) {
  1083. /* mark it as used */
  1084. break;
  1085. }
  1086. }
  1087. /* which one do we use, RCS or source? */
  1088. if (RcsPtr) {
  1089. if (!SourcePriority &&
  1090. (SourcePtr->st.st_mtime < RcsPtr->st.st_mtime)) {
  1091. /* we'll catch this on pass 3 */
  1092. continue;
  1093. } else {
  1094. /* mark the RCS file as used */
  1095. (void) RcsPtr->used++;
  1096. }
  1097. }
  1098. /* ignore .o and .a files */
  1099. c = SourcePtr->keyname + SourcePtr->keylen - 2;
  1100. if (SourcePtr->keylen >= 2) {
  1101. if (!strcmp(c, ".o")) {
  1102. (void) shouldnt_have_source++;
  1103. if (!CloneDotO)
  1104. continue;
  1105. }
  1106. if (!strcmp(c, ".a")) {
  1107. (void) shouldnt_have_source++;
  1108. if (!CloneDotA)
  1109. continue;
  1110. }
  1111. }
  1112. /* the files might be Makefile's */
  1113. if (!CloneMakefile && !strncmp(SourcePtr->keyname, Makefile,
  1114. strlen(Makefile)))
  1115. continue;
  1116. WorkingFile = malloc((unsigned) strlen(WorkingDir) +
  1117. SourcePtr->keylen + 2);
  1118. (void) strcpy(WorkingFile, WorkingDir);
  1119. (void) strcat(WorkingFile, "/");
  1120. (void) strcat(WorkingFile, SourcePtr->keyname);
  1121. if (S_ISDIR(SourcePtr->st.st_mode)) {
  1122. /* check for directories present in the source tree,
  1123. ** but not in this tree. Don't bother if the SourceDir
  1124. ** is the same as WorkingDir. If the directory exists
  1125. ** in the working tree, we already set the used flag
  1126. ** and never got here in the first place.
  1127. */
  1128. if (!same) {
  1129. if (MakeDirs) {
  1130. if (!Quiet)
  1131. (void) fprintf(stderr, "%s: building directory\n",
  1132. WorkingFile + WorkingLen);
  1133. if (!FollowDirLinks &&
  1134. SourcePtr->lst_valid &&
  1135. S_ISLNK(SourcePtr->lst.st_mode))
  1136. {
  1137. /* check to see if file symlinks should resolve */
  1138. if (ResolveFileLinks)
  1139. SourceFile = ResolveLink(SourcePtr->fullname, 0);
  1140. else
  1141. SourceFile = SourcePtr->fullname;
  1142. if (DoExecute)
  1143. do_ln_s(SourceFile, WorkingFile);
  1144. else
  1145. {
  1146. if (strncmp(SourceFile, SourceDir, SourceLen))
  1147. (void) printf("ln -s %s ${w}/%s\n",
  1148. SourceFile,
  1149. WorkingFile + WorkingLen);
  1150. else
  1151. (void) printf("ln -s ${s}/%s ${w}/%s\n",
  1152. SourceFile + SourceLen,
  1153. WorkingFile + WorkingLen);
  1154. }
  1155. free(SourceFile);
  1156. }
  1157. else
  1158. {
  1159. if (DoExecute)
  1160. {
  1161. do_rm_rf(WorkingFile);
  1162. do_mkdir(WorkingFile);
  1163. do_chmod(WorkingFile, 0755);
  1164. /* bad for other architectures */
  1165. /* do_chgrp(WorkingFile, "users"); */
  1166. }
  1167. else
  1168. {
  1169. (void) printf("rm -rf ${w}/%s\n",
  1170. WorkingFile + WorkingLen);
  1171. (void) printf("\tmkdir ${w}/%s\n",
  1172. WorkingFile + WorkingLen);
  1173. (void) printf("\tchmod 0755 ${w}/%s\n",
  1174. WorkingFile + WorkingLen);
  1175. /* bad for other architectures */
  1176. /*(void) printf("\tchgrp users ${w}/%s\n",
  1177. WorkingFile + WorkingLen); */
  1178. }
  1179. (void) GetNew(WorkingFile, SourcePtr->fullname, same);
  1180. }
  1181. } else {
  1182. if (!Quiet)
  1183. (void) fprintf(stderr, "%s: missing directory\n",
  1184. WorkingFile + WorkingLen);
  1185. }
  1186. }
  1187. } else {
  1188. /* regular file (probably)... */
  1189. /* check to see if file symlinks should resolve */
  1190. if (ResolveFileLinks)
  1191. if (SourcePtr->lst_valid && S_ISLNK(SourcePtr->lst.st_mode)) {
  1192. SourceFile = ResolveLink(SourcePtr->fullname, 0);
  1193. FreeSourceFile = 1;
  1194. }
  1195. else {
  1196. SourceFile = SourcePtr->fullname;
  1197. FreeSourceFile = 0;
  1198. }
  1199. else {
  1200. SourceFile = SourcePtr->fullname;
  1201. FreeSourceFile = 0;
  1202. }
  1203. if (!Quiet)
  1204. (void) fprintf(stderr, "%s: new file\n",
  1205. WorkingFile + WorkingLen);
  1206. if (DoExecute)
  1207. {
  1208. if (LinkFiles)
  1209. do_ln_s(SourceFile, WorkingFile);
  1210. else
  1211. do_cp(SourceFile, WorkingFile);
  1212. }
  1213. else
  1214. {
  1215. if (strncmp(SourceFile, SourceDir, SourceLen)) {
  1216. (void) printf("%s %s ${w}/%s\n",
  1217. LinkFiles ? "ln -s" : "cp",
  1218. SourceFile,
  1219. WorkingFile + WorkingLen);
  1220. } else {
  1221. (void) printf("%s ${s}/%s ${w}/%s\n",
  1222. LinkFiles ? "ln -s" : "cp",
  1223. SourceFile + SourceLen,
  1224. WorkingFile + WorkingLen);
  1225. }
  1226. }
  1227. if (!LinkFiles)
  1228. {
  1229. if (DoExecute)
  1230. do_chmod(WorkingFile,
  1231. (SourcePtr->st.st_mode & 07777 & ~0222) | 0444);
  1232. else
  1233. (void) printf("\tchmod 0%03o ${w}/%s\n",
  1234. (SourcePtr->st.st_mode & 07777 & ~0222) | 0444,
  1235. WorkingFile + WorkingLen);
  1236. }
  1237. if (FreeSourceFile)
  1238. (void) free(SourceFile);
  1239. }
  1240. (void) free(WorkingFile);
  1241. }
  1242. /*
  1243. ** PASS 3:
  1244. **
  1245. ** Check all the files in the RCS dir.
  1246. */
  1247. if (Debug)
  1248. (void) fprintf(stderr, ">> scanning RcsDir \"%s\"\n", RcsDir);
  1249. for (RcsPtr = RcsHead; RcsPtr; RcsPtr = RcsPtr->next) {
  1250. /* did we get this one already? */
  1251. if (RcsPtr->used)
  1252. continue;
  1253. /* build the WorkingFile */
  1254. WorkingFile = malloc((unsigned) strlen(WorkingDir) +
  1255. RcsPtr->keylen + 2);
  1256. (void) strcpy(WorkingFile, WorkingDir);
  1257. (void) strcat(WorkingFile, "/");
  1258. (void) strcat(WorkingFile, RcsPtr->keyname);
  1259. /* New RCS file */
  1260. if (!Quiet)
  1261. (void) fprintf(stderr, "%s: new RCS file\n",
  1262. WorkingFile + WorkingLen);
  1263. if (DoExecute)
  1264. {
  1265. if (! NoRealFiles)
  1266. {
  1267. do_co_q(RcsDir, WorkingFile);
  1268. }
  1269. }
  1270. else
  1271. {
  1272. if (strncmp(RcsDir, SourceDir, SourceLen) ||
  1273. (RcsDir[SourceLen] != '/')) {
  1274. /* RcsDir is not in SourceDir */
  1275. if (! NoRealFiles)
  1276. {
  1277. /* check it out... */
  1278. (void) printf("(cd %s; co -q ${w}/%s)\n",
  1279. RcsDir,
  1280. WorkingFile + WorkingLen);
  1281. }
  1282. } else {
  1283. /* RcsDir is in SourceDir */
  1284. if (! NoRealFiles)
  1285. {
  1286. /* check it out... */
  1287. (void) printf("(cd %s; co -q ${w}/%s)\n",
  1288. RcsDir + SourceLen,
  1289. WorkingFile + WorkingLen);
  1290. }
  1291. }
  1292. }
  1293. (void) free(WorkingFile);
  1294. }
  1295. /* free storage */
  1296. while (WorkingHead) {
  1297. WorkingPtr = WorkingHead;
  1298. WorkingHead = WorkingPtr->next;
  1299. (void) free(WorkingPtr->fullname);
  1300. (void) free(WorkingPtr->keyname);
  1301. (void) free((char *) WorkingPtr);
  1302. }
  1303. while (SourceHead) {
  1304. SourcePtr = SourceHead;
  1305. SourceHead = SourcePtr->next;
  1306. (void) free(SourcePtr->fullname);
  1307. (void) free(SourcePtr->keyname);
  1308. (void) free((char *) SourcePtr);
  1309. }
  1310. while (RcsHead) {
  1311. RcsPtr = RcsHead;
  1312. RcsHead = RcsPtr->next;
  1313. (void) free(RcsPtr->fullname);
  1314. (void) free(RcsPtr->keyname);
  1315. (void) free((char *) RcsPtr);
  1316. }
  1317. (void) free(RcsDir);
  1318. return;
  1319. }
  1320. char
  1321. *ResolveLink(filename, freeit)
  1322. char *filename;
  1323. int freeit;
  1324. {
  1325. int len;
  1326. int try;
  1327. char *c;
  1328. char *tname;
  1329. tname = filename;
  1330. if (Debug) {
  1331. (void) fprintf(stderr, "ResolveLink %s->", tname);
  1332. (void) fflush(stderr);
  1333. }
  1334. for (try = 0; try < 10; try++) {
  1335. if ((len = readlink(tname, Buffer, sizeof(Buffer))) < 0) {
  1336. break;
  1337. } else {
  1338. Buffer[len] = '\0';
  1339. if ('/' != *Buffer) {
  1340. if (c = strrchr(tname, '/')) {
  1341. *c = '\0';
  1342. c = malloc((unsigned) (strlen(tname) +
  1343. strlen(Buffer) + 2));
  1344. (void) sprintf(c, "%s/%s", tname, Buffer);
  1345. } else {
  1346. c = malloc((unsigned) (strlen(Buffer) + 1));
  1347. (void) strcpy(c, Buffer);
  1348. }
  1349. } else {
  1350. c = malloc((unsigned) (strlen(Buffer) + 1));
  1351. (void) strcpy(c, Buffer);
  1352. }
  1353. if (freeit++)
  1354. (void) free(tname);
  1355. tname = c;
  1356. }
  1357. }
  1358. if (!freeit) {
  1359. c = malloc((unsigned) (strlen(tname) + 1));
  1360. (void) strcpy(c, tname);
  1361. tname = c;
  1362. }
  1363. if (Debug) {
  1364. (void) fprintf(stderr, "%s\n", tname);
  1365. (void) fflush(stderr);
  1366. }
  1367. return(tname);
  1368. }
  1369. /* New code for -X option */
  1370. static void do_rm_rf(target)
  1371. char *target;
  1372. {
  1373. char *malloc(), *temp;
  1374. struct stat buf;
  1375. if (lstat(target, &buf) != -1)
  1376. {
  1377. if (S_ISDIR(buf.st_mode))
  1378. {
  1379. DIR *thisdir;
  1380. #ifdef apollo
  1381. struct direct *thisent;
  1382. #else
  1383. struct dirent *thisent;
  1384. #endif
  1385. thisdir = opendir(target);
  1386. if (thisdir != NULL)
  1387. {
  1388. while (thisent = readdir(thisdir))
  1389. {
  1390. if (strcmp(thisent->d_name, ".") &&
  1391. strcmp(thisent->d_name, ".."))
  1392. {
  1393. temp = malloc(strlen(target) +
  1394. strlen(thisent->d_name) + 2);
  1395. if (temp != NULL)
  1396. {
  1397. (void)strcpy(temp, target);
  1398. (void)strcat(temp, "/");
  1399. (void)strcat(temp, thisent->d_name);
  1400. do_rm_rf(temp);
  1401. free(temp);
  1402. }
  1403. }
  1404. }
  1405. closedir(thisdir);
  1406. (void)rmdir(target);
  1407. }
  1408. }
  1409. else
  1410. (void)unlink(target);
  1411. }
  1412. }
  1413. static void do_touch(filename)
  1414. char *filename;
  1415. {
  1416. #ifdef apollo
  1417. struct timeval tvp[2];
  1418. struct timezone tzp;
  1419. gettimeofday(tvp, &tzp);
  1420. tvp[1] = tvp[0];
  1421. if (utimes(filename, tvp) == -1 &&
  1422. errno == ENOENT)
  1423. #else
  1424. if (utime(filename, (struct utimbuf *)NULL) == -1 &&
  1425. errno == ENOENT)
  1426. #endif
  1427. (void)creat(filename, 0777);
  1428. }
  1429. static void do_ln_s(src, dest)
  1430. char *src, *dest;
  1431. {
  1432. if (symlink(src, dest) == -1)
  1433. perror(dest);
  1434. }
  1435. static void do_diff(dirname, diffcmd, file1, file2, outfile)
  1436. char *dirname, *diffcmd, *file1, *file2, *outfile;
  1437. {
  1438. pid_t pid, res, fork();
  1439. pid = fork();
  1440. if (pid == -1)
  1441. perror("fork() failed");
  1442. else
  1443. {
  1444. if (pid == 0)
  1445. {
  1446. if (dirname != NULL && chdir(dirname) == -1)
  1447. perror("dirname");
  1448. else
  1449. {
  1450. int des;
  1451. des = open(outfile, O_WRONLY | O_APPEND | O_CREAT, 0777);
  1452. if (des == -1)
  1453. {
  1454. perror(outfile);
  1455. exit(1);
  1456. }
  1457. (void)dup2(des, fileno(stdout));
  1458. (void)dup2(des, fileno(stderr));
  1459. execlp(diffcmd, diffcmd, file1, file2, NULL);
  1460. perror(diffcmd);
  1461. }
  1462. exit(1);
  1463. }
  1464. while ((res = wait(NULL)) != pid && res != -1);
  1465. }
  1466. }
  1467. static void do_rm_f(target)
  1468. char *target;
  1469. {
  1470. struct stat buf;
  1471. if (lstat(target, &buf) != -1 &&
  1472. !(S_ISDIR(buf.st_mode)))
  1473. (void)unlink(target);
  1474. }
  1475. static void do_cp(src, dest)
  1476. char *src, *dest;
  1477. {
  1478. int res1, res2, fd1, fd2;
  1479. char buf[BUFSIZ];
  1480. fd1 = open(src, O_RDONLY);
  1481. if (fd1 == -1)
  1482. {
  1483. perror(src);
  1484. return;
  1485. }
  1486. fd2 = open(dest, O_WRONLY | O_CREAT, 0777);
  1487. if (fd2 == -1)
  1488. {
  1489. perror(dest);
  1490. close(fd1);
  1491. return;
  1492. }
  1493. while ((res1 = read(fd1, buf, BUFSIZ)) > 0)
  1494. {
  1495. while ((res2 = write(fd2, buf, res1)) > 0 && (res1 -= res2));
  1496. if (res2 == -1) break;
  1497. }
  1498. if (res1 == -1)
  1499. perror(src);
  1500. else if (res2 == -1)
  1501. perror(dest);
  1502. close(fd1);
  1503. close(fd2);
  1504. }
  1505. static void do_chmod(filename, newmode)
  1506. char *filename;
  1507. int newmode;
  1508. {
  1509. if (chmod(filename, newmode) == -1)
  1510. perror(filename);
  1511. }
  1512. static void do_co_q(dirname, targetname)
  1513. char *dirname, *targetname;
  1514. {
  1515. pid_t pid, res, fork();
  1516. pid = fork();
  1517. if (pid == -1)
  1518. perror("fork() failed");
  1519. else
  1520. {
  1521. if (pid == 0)
  1522. {
  1523. if (chdir(dirname) == -1)
  1524. perror("dirname");
  1525. else
  1526. {
  1527. execlp("co", "co", "-q", targetname, NULL);
  1528. perror("failed to exec co(1)");
  1529. }
  1530. exit(1);
  1531. }
  1532. while ((res = wait(NULL)) != pid && res != -1);
  1533. }
  1534. }
  1535. static void do_mkdir(dirname)
  1536. char *dirname;
  1537. {
  1538. if (mkdir(dirname, 0777) == -1)
  1539. perror(dirname);
  1540. }
  1541. static void do_chgrp(filename, newgroup)
  1542. char *filename, *newgroup;
  1543. {
  1544. struct group *group, *getgrnam();
  1545. group = getgrnam(newgroup);
  1546. if (group == NULL)
  1547. fprintf(stderr, "%s: no such group\n", newgroup);
  1548. else
  1549. chown(filename, UID_NO_CHANGE, group->gr_gid);
  1550. }