home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume10 / abcd12 < prev    next >
Text File  |  1990-01-15  |  31KB  |  1,000 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v10i012: abcd V1.2 - an automatic backup copy daemon (Part 1 of 1).
  3. from: richb@Aus.Sun.COM (Rich Burridge)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 10, Issue 12
  7. Submitted-by: richb@Aus.Sun.COM (Rich Burridge)
  8. Archive-name: abcd12
  9.  
  10. Abcd - Version 1.2 January 1989.
  11.  
  12. Permission is given to distribute these sources, as long as the
  13. copyright messages are not removed, and no monies are exchanged.
  14.  
  15. This is the second general release of an automatic backup copy daemon, which
  16. copies files from one filestore area to another using either cp or rcp. Note
  17. the second filestore area could be on another machine if the file system is
  18. NFS mounted.
  19.  
  20. This means that the backup machine should have an identical copy of the
  21. filestore being monitored, give or take a little bit.
  22.  
  23. See the README file and the manual pages for more details.
  24.  
  25. I welcome bug reports and suggestions for improvements.
  26.  
  27. Rich Burridge,          DOMAIN: richb@sunaus.oz.au
  28. PHONE: +61 2 413 2666   UUCP:   {uunet,mcvax,ukc}!munnari!sunaus.oz!richb
  29.  
  30. ---- Cut Here and unpack ----
  31. #!/bin/sh
  32. # shar:    Shell Archiver  (v1.22)
  33. #    Packed Tue Jan  9 12:42:02 EST 1990 by stard!richb
  34. #    from directory /extra/richb/rich_stuff/abcd
  35. #
  36. #                                                                          
  37. #                                                                          
  38. #
  39. #    Run the following text with /bin/sh to create:
  40. #      README
  41. #      Makefile
  42. #      abcd.c
  43. #      ndir.c
  44. #      abcd.h
  45. #      ndir.h
  46. #      patchlevel.h
  47. #      abcd.1
  48. #
  49. if test -r s2_seq_.tmp
  50. then echo "Must unpack archives in sequence!"
  51.      next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
  52.      exit 1; fi
  53. echo "x - extracting README (Text)"
  54. sed 's/^X//' << 'SHAR_EOF' > README &&
  55. X
  56. XREADME for abcd, an automatic backup copy daemon.
  57. X
  58. XVersion 1.2 January 1989.
  59. X
  60. XPermission is given to distribute these sources, as long as the
  61. Xcopyright messages are not removed, and no monies are exchanged.
  62. X
  63. XThis is the second general release of an automatic backup copy daemon, which
  64. Xcopies files from one filestore area to another using either cp or rcp. Note
  65. Xthe second filestore area could be on another machine if the file system is
  66. XNFS mounted.
  67. X
  68. XThis means that the backup machine should have an identical copy of the
  69. Xfilestore being monitored, give or take a little bit.
  70. X
  71. X
  72. XThe original version of this was written in November 1985, and the first
  73. Xgeneral release was made available in May 1988. This version contains a
  74. Xrewrite of the directory reading routines to try to make the code more
  75. Xportable, plus a general tidy up. It has been tested on SunOS v4.0, and
  76. XSCO Xenix 286 (v2.2.3).  I would be interested to here from people who port
  77. Xit to other Unix machines.
  78. X
  79. XI welcome bug reports and suggestions for improvements.
  80. X
  81. X
  82. XAcknowledgements.
  83. X
  84. XMany thanks go to Po Cheung Ng (Andrew) <pcng@cad.jmrc.eecs.unsw.oz> who
  85. Xported abcd to SCO Xenix 286 (v2.2.3), fixing several memory leaks in the
  86. Xprocess.
  87. X
  88. X      Rich.
  89. X
  90. XRich Burridge,          DOMAIN: richb@sunaus.oz.au
  91. XPHONE: +61 2 413 2666   UUCP:   {uunet,mcvax,ukc}!munnari!sunaus.oz!richb
  92. SHAR_EOF
  93. chmod 0444 README || echo "restore of README fails"
  94. set `wc -c README`;Sum=$1
  95. if test "$Sum" != "1345"
  96. then echo original size 1345, current size $Sum;fi
  97. echo "x - extracting Makefile (Text)"
  98. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  99. X#
  100. X#  Makefile for abcd, an automatic backup copy daemon.
  101. X#
  102. X#  @(#)Makefile 1.4 89/04/10
  103. X#
  104. X#  Copyright (c) Rich Burridge.
  105. X#                Sun Microsystems Australia - All rights reserved.
  106. X#
  107. X#  Permission is given to distribute these sources, as long as the
  108. X#  copyright messages are not removed, and no monies are exchanged.
  109. X#
  110. X#  No responsibility is taken for any errors inherent either in the comments
  111. X#  or the code of this program, but if reported to me then an attempt will
  112. X#  be made to fix them.
  113. X#
  114. X#-----------------------------------------------------------------------
  115. X#  Abcd has been written to work in both BSD and System V environments.
  116. X#  If you are running on a BSD4.[23] machine or under SunOS, then OSTYPE
  117. X#  should be commented out. If you are running under SysV, V7 or BSD4.1,
  118. X#  then OSTYPE should be set to -DSYSV (uncommented).
  119. X# 
  120. X#OSTYPE          = -DSYSV 
  121. X#-----------------------------------------------------------------------
  122. X#  If you are running abcd under SCO Xenix 286, then you should have
  123. X#  uncommented the OSTYPE declaration above. You also need to uncomment
  124. X#  the following two lines.
  125. X#
  126. X#X_CFLAGS        = -M21 -K
  127. X#X_LIBS          = -lx
  128. X#-----------------------------------------------------------------------
  129. X
  130. XBINARIES        = abcd
  131. XBINDIR          = /usr/local/bin
  132. XMANDIR          = /usr/man/man$(MANSECT)
  133. XMANSECT         = l
  134. XCFLAGS          = $(X_CFLAGS) -g $(OSTYPE) -DCP=\"$(CP)\" -DRCP=\"$(RCP)\"
  135. XOBJS            = abcd.o
  136. XSRCS            = abcd.c ndir.c
  137. XHDRS            = abcd.h ndir.h patchlevel.h
  138. XLIBS            = $(X_LIBS)
  139. XOTHERS          = Makefile README abcd.1
  140. X
  141. X#  Full pathnames for the cp and rcp commands.
  142. XCP              = /bin/cp
  143. XRCP             = /usr/ucb/rcp
  144. X
  145. Xall:            $(BINARIES)
  146. X
  147. Xabcd:           $(OBJS)
  148. X        cc -o abcd $(CFLAGS) $(OBJS) $(LIBS)
  149. X
  150. Xinstall:        $(BINARIES)
  151. X        install -s -m 751 abcd $(BINDIR)
  152. X        install -c -m 644 abcd.1 $(MANDIR)/abcd.$(MANSECT)
  153. X
  154. Xbackup:;        cp $(SRCS) $(HDRS) $(OTHERS) backdir
  155. X
  156. Xshar:;          shar.script $(SRCS) $(HDRS) $(OTHERS) > archive
  157. X
  158. Xclean:;        rm -f abcd *.o core
  159. X
  160. Xlint:;        lint abcd.c $(LIBS)
  161. X
  162. Xcreate:         SCCS
  163. X        -sccs create $(SRCS) $(HDRS) $(OTHERS)
  164. X
  165. XSCCS:
  166. X        mkdir SCCS
  167. X        chmod 755 SCCS
  168. X
  169. Xabcd.o:         abcd.c $(HDRS)
  170. SHAR_EOF
  171. chmod 0444 Makefile || echo "restore of Makefile fails"
  172. set `wc -c Makefile`;Sum=$1
  173. if test "$Sum" != "2237"
  174. then echo original size 2237, current size $Sum;fi
  175. echo "x - extracting abcd.c (Text)"
  176. sed 's/^X//' << 'SHAR_EOF' > abcd.c &&
  177. X#ifndef lint
  178. Xstatic char sccsid[] = "@(#)abcd.c 1.4 89/04/10" ;
  179. X#endif
  180. X
  181. X/*  This is an automatic backup copy daemon, which copies files from one
  182. X *  filestore area to another using either cp or rcp. Note the second
  183. X *  filestore area could be on another machine if the file system is NFS
  184. X *  mounted.
  185. X *
  186. X *  This means that the backup disk should have an identical copy of the
  187. X *  filestore being monitored, give or take a little bit.
  188. X *
  189. X *  Copyright (c) Rich Burridge.
  190. X *                Sun Microsystems Australia - All rights reserved.
  191. X *
  192. X *  Permission is given to distribute these sources, as long as the
  193. X *  copyright messages are not removed, and no monies are exchanged.
  194. X *
  195. X *  No responsibility is taken for any error in accuracies inherent
  196. X *  either to the comments or the code of this program, but if
  197. X *  reported to me then an attempt will be made to fix them.
  198. X */
  199. X
  200. X#include <stdio.h>
  201. X
  202. X#ifdef SYSV
  203. X#include <string.h>
  204. X#include <fcntl.h>
  205. X#else  SYSV
  206. X#include <strings.h>
  207. X#include <sys/file.h>
  208. X#endif SYSV
  209. X
  210. X#include <errno.h>
  211. X#include <signal.h>
  212. X#include <sys/types.h>
  213. X#include <sys/stat.h>
  214. X
  215. X#ifdef SYSV
  216. X#ifdef M_XENIX
  217. X#include <sys/ndir.h>
  218. X#define  dirent    direct
  219. X#define  d_fileno  d_ino
  220. X#else  M_XENIX
  221. X#include <sys/param.h>
  222. X#include "ndir.h"
  223. X#endif M_XENIX
  224. X#include <memory.h>
  225. X#define  bcopy(s1, s2, n)  memcpy(s2, s1, n)
  226. X#else  SYSV
  227. X#include <dirent.h>
  228. Xchar *sprintf() ;
  229. X#endif SYSV
  230. X
  231. X#include "patchlevel.h"
  232. X#include "abcd.h"
  233. X
  234. Xchar *malloc() ;
  235. X
  236. XDIR *dirp ;                      /* Stream for monitored directory. */
  237. X
  238. Xstruct finfo *cfile ;            /* Information on current file. */
  239. Xstruct finfo *files  = NULL ;    /* Files being monitored. */
  240. Xstruct dinfo *cdir ;             /* Pointer to current directory. */
  241. Xstruct dinfo *dirs = NULL ;      /* Directories being monitored. */
  242. Xstruct stat cstat ;              /* For statistics on current file. */
  243. Xstruct dirent *cur ;             /* Pointer to current directory record. */
  244. X
  245. Xextern int errno ;               /* Standard error reply. */
  246. X
  247. Xchar cname[MAXLINE] ;            /* Copy program to use. */
  248. Xchar coff[MAXLINE] ;             /* Name offset from initial start directory. */
  249. Xchar cp_name[MAXLINE] ;          /* Location of "cp" copy program. */
  250. Xchar curdir[MAXLINE] ;           /* Current directory being monitored. */
  251. Xchar fdir[MAXLINE] ;             /* Directory to start copying from. */
  252. Xchar flist[MAXFILES][MAXLINE] ;  /* Array of filenames to copy. */
  253. Xchar fname[MAXLINE] ;            /* Full pathname of current file. */
  254. Xchar pdir[MAXLINE] ;             /* Current directory for copy request. */
  255. Xchar progname[MAXLINE] ;         /* Name of this program. */
  256. Xchar rcp_name[MAXLINE] ;         /* Location of "rcp" copy program. */
  257. Xchar rhost[MAXLINE] ;            /* Name of remote host for use by rcp. */
  258. Xchar tdir[MAXLINE] ;             /* Directory to start copying to. */
  259. X
  260. Xint copy_found  = 0 ;            /* Whether copy done on this pass. */
  261. Xint debug = 0 ;                  /* If set, status information is given. */
  262. Xint delay = 300 ;                /* Sleep time for program in seconds. */
  263. Xint docopy = 1 ;                 /* Rcp files right from the beginning. */
  264. Xint loc = 0 ;                    /* Current location in the directory block. */
  265. Xint fcnt = 0 ;                   /* No. of files to copy in current request. */
  266. Xint fd ;                         /* File descriptor for various opens. */
  267. Xint no_dirs = 1 ;                /* Number of directories being monitored. */
  268. Xint usercp = 0 ;                 /* Backup method, cp or rcp. */
  269. X
  270. X
  271. Xmain(argc,argv)
  272. Xint argc ;
  273. Xchar *argv[] ;
  274. X{
  275. X  STRCPY(progname, argv[0]) ;    /* Save this programs name. */
  276. X  get_options(argc,argv) ;       /* Get command line options. */
  277. X  setup() ;                      /* Initialise parameters. */
  278. X  while (1)                      /* Do it forever. */
  279. X    {
  280. X      get_next_dir() ;           /* Is there another directory? */
  281. X      while (get_next_entry())   /* Is there another file in directory? */
  282. X        {
  283. X          if (!DOTS(cur->d_name))  /* Is it the . or .. entry? */
  284. X            {
  285. X              if (no_record())     /* Is this file already monitored? */
  286. X                {
  287. X                  if ((cstat.st_mode & S_IFMT) == DIRECTORY)  /* Directory? */
  288. X                    {
  289. X                      if (make_dir_entry())
  290. X                        {
  291. X                          copy(DIRECTORY) ;
  292. X                          free((char *) cur) ;
  293. X                        }
  294. X                    }
  295. X                  else
  296. X                    {
  297. X                      make_file_entry() ;   /* Make a file entry. */
  298. X                      copy(REGULAR) ;       /* Copy it to backup machine. */
  299. X                    }
  300. X                }     
  301. X              else if (file_modified())
  302. X                {
  303. X                  copy(REGULAR) ;           /* File been modified? */
  304. X                  free((char *) cur) ;
  305. X                }
  306. X              else free((char *) cur) ;
  307. X            }
  308. X          else free((char *) cur) ;
  309. X        }
  310. X    }
  311. X}
  312. X
  313. X
  314. X/*  Use the portable BSD directory emulation routines if this is System V. */
  315. X
  316. X#ifdef SYSV
  317. X#ifndef  M_XENIX
  318. X#include "ndir.c"
  319. X#endif   M_XENIX
  320. X#endif SYSV
  321. X
  322. X
  323. Xchar *
  324. XMalloc(n)
  325. Xint n ;
  326. X{
  327. X  char *val ;
  328. X
  329. X  if ((val = malloc((unsigned) n)) == NULL)
  330. X    FPRINTF(stderr,"%s: Out of memory.\n", progname) ;
  331. X  return val ;
  332. X}
  333. X
  334. X
  335. Xcopy(filetype)           /* Copy file to another directory. */
  336. Xint filetype ;
  337. X{
  338. X  char name[MAXLINE] ;
  339. X
  340. X  if (docopy)            /* Are we copying this time around. */
  341. X    {
  342. X      copy_found = 1 ;
  343. X      STRCPY(name, "") ;
  344. X      if (strlen(coff))
  345. X        {
  346. X          STRCAT(name, coff) ;
  347. X          STRCAT(name, "/") ;
  348. X        }
  349. X      STRCAT(name, cur->d_name) ;
  350. X      if (strcmp(curdir, pdir) != 0)  /* This directory != copy directory? */
  351. X        {
  352. X          if (fcnt) output(name, REGULAR) ;
  353. X          STRCPY(pdir, curdir) ;
  354. X        }
  355. X      if (filetype == DIRECTORY)
  356. X        {
  357. X          if (fcnt) output(name, REGULAR) ;
  358. X          output(name, DIRECTORY) ;
  359. X        }
  360. X      else if (fcnt >= MAXFILES)     /* Room in file list for this filename? */
  361. X        {
  362. X          output(name, REGULAR) ;
  363. X          STRCPY(flist[fcnt++], name) ;
  364. X        }
  365. X      else STRCPY(flist[fcnt++], name) ;   /* Save filename in file list. */
  366. X    }
  367. X}
  368. X
  369. X
  370. Xfile_modified()    /* Check if this file has been changed. */
  371. X{
  372. X  if (cfile->mtime == cstat.st_mtime) return(0) ;
  373. X  cfile->mtime = cstat.st_mtime ;
  374. X  return(1) ;
  375. X}
  376. X
  377. X
  378. Xget_next_dir()     /* Get next directory name to monitor. */
  379. X{
  380. X  struct dinfo *temp ;
  381. X  int dirfound ;
  382. X
  383. X  dirfound = 0 ;
  384. X  if (dirp)
  385. X    {
  386. X      CLOSEDIR(dirp) ;
  387. X      if (!strlen(cdir->next->d_name))     /* Complete pass done? */
  388. X        {
  389. X          docopy = 1 ;                     /* Always copy after first pass. */
  390. X          if (!copy_found)
  391. X            sleep((unsigned int) delay) ;  /* Nothing doing so go to sleep. */
  392. X          else copy_found = 0 ;
  393. X        }
  394. X      if (strcmp(curdir, cdir->next->d_name) != 0)
  395. X        if (fcnt) output("", REGULAR) ;
  396. X    }
  397. X  while (!dirfound)
  398. X    {
  399. X      STRCPY(curdir, fdir) ;
  400. X      if (strlen(cdir->next->d_name))
  401. X        {
  402. X          STRCAT(curdir, "/") ;
  403. X          STRCAT(curdir, cdir->next->d_name) ;
  404. X        }
  405. X      STRCPY(coff, cdir->next->d_name) ;
  406. X      if ((dirp = opendir(curdir)) == NULL)
  407. X        {
  408. X          if (EQUAL(curdir, fdir)) exit(0) ;  /* Nothing left to monitor. */
  409. X          else
  410. X            {
  411. X              temp = cdir->next ;
  412. X              if (cdir->next == dirs) dirs = cdir ;
  413. X              cdir->next = cdir->next->next ;
  414. X              free((char *) temp) ;           /* Lose this directory record. */
  415. X              no_dirs-- ;
  416. X            }
  417. X        }
  418. X      else dirfound = 1 ;     /* Directory found. */
  419. X    }
  420. X  cdir = cdir->next ;         /* Point to current directory. */
  421. X  loc = 0 ;                   /* Reset directory buffer pointer. */
  422. X}
  423. X
  424. X
  425. Xget_next_entry()         /* Get next directory filename entry. */
  426. X{
  427. X  struct dirent *temp ;  /* Pointer to next directory entry. */
  428. X
  429. X  for (;;)
  430. X    {
  431. X      if ((temp = readdir(dirp)) == NULL) return(0) ;
  432. X      if (temp->d_fileno == 0) return(0) ;
  433. X      SPRINTF(fname, "%s/%s", curdir, temp->d_name) ;
  434. X      if ((fd = open(fname, O_RDONLY)) != -1)
  435. X        {
  436. X          CLOSE(fd) ;
  437. X          cur = (struct dirent *) Malloc(sizeof(struct dirent)) ;
  438. X          bcopy((char *) temp, (char *) cur, (int) DIRSIZ(temp)) ;
  439. X          STAT(fname, &cstat) ;
  440. X          return(1) ;
  441. X        }
  442. X    }
  443. X}
  444. X
  445. X
  446. Xget_options(argc,argv)     /* Read and process command line options. */
  447. Xint argc ;
  448. Xchar *argv[] ;
  449. X{
  450. X  char next[MAXLINE] ;     /* The next command line parameter. */
  451. X
  452. X  STRCPY(fdir, "/usr") ;   /* Default directory to monitor. */
  453. X  STRCPY(tdir, "/usr2") ;  /* Default directory to copy to. */
  454. X  STRCPY(rhost, "") ;      /* Default is no remote host. */
  455. X
  456. X  INC ;
  457. X  while (argc > 0)
  458. X    {
  459. X      if (argv[0][0] == '-')
  460. X        switch (argv[0][1])
  461. X          {
  462. X            case 'c' : docopy = 0 ;        /* Don't copy files first time. */
  463. X                       break ;
  464. X            case 'd' : debug = 1 ;         /* Print status information. */
  465. X                       break ;
  466. X            case 'f' : INC ;               /* Start directory to monitor. */
  467. X                       getparam(fdir, argv, "-f needs start directory") ;
  468. X                       break ;
  469. X            case 'r' : INC ;               /* Name of remote host. */
  470. X                       getparam(rhost, argv, "-r needs remote host") ;
  471. X                       usercp = 1 ;
  472. X                       break ;
  473. X            case 's' : INC ;               /* Sleep period in seconds. */
  474. X                       getparam(next, argv, "-s needs sleep period") ;
  475. X                       delay = atoi(next) ;
  476. X                       break ;
  477. X            case 't' : INC ;               /* Directory to start copying to. */
  478. X                       getparam(tdir, argv, "-t needs directory to copy to") ;
  479. X                       break ;
  480. X            case 'v' : FPRINTF(stderr,"%s version 1.2.%1d\n",
  481. X                                      progname, PATCHLEVEL) ;
  482. X                       exit(1) ;
  483. X            default  : FPRINTF(stderr,"Usage: %s [-c] [-f fromdir]", progname) ;
  484. X                       FPRINTF(stderr," [-r hostname] [-s sleep] ") ;
  485. X                       FPRINTF(stderr," [-t todir] [-v]\n") ;
  486. X                       exit(1) ;
  487. X          }
  488. X      INC ;
  489. X    }
  490. X}
  491. X
  492. X
  493. Xgetparam(s, argv, errmes)
  494. Xchar *s, *argv[], *errmes ;
  495. X{
  496. X  if (*argv != NULL && argv[0][0] != '-') STRCPY(s, *argv) ;
  497. X  else
  498. X    { 
  499. X      FPRINTF(stderr,"%s: %s as next argument.\n", progname, errmes) ;
  500. X      exit(1) ;
  501. X    }
  502. X}
  503. X
  504. X
  505. Xmake_dir_entry()    /* If not there already, create a new directory record. */
  506. X{
  507. X  int i ;
  508. X  char tempdir[MAXLINE] ;          /* Temporary directory name. */
  509. X  struct dinfo *temp ;
  510. X
  511. X  temp = cdir ;
  512. X  for (i = 0; i < no_dirs; i++)    /* Directory already being monitored? */
  513. X    {
  514. X      temp = temp->next ;
  515. X      STRCPY(tempdir, fdir) ;
  516. X      if (strlen(temp->d_name))
  517. X        {
  518. X          STRCAT(tempdir, "/") ;
  519. X          STRCAT(tempdir, temp->d_name) ;
  520. X        }
  521. X      if (EQUAL(tempdir, fname)) return(0) ;
  522. X    }
  523. X
  524. X  temp = (struct dinfo *) Malloc(sizeof(struct dinfo)) ;
  525. X  temp->next = dirs->next ;
  526. X  dirs->next = temp ;
  527. X  dirs = temp ;
  528. X
  529. X  STRCPY(dirs->d_name, "") ;
  530. X  if (strlen(coff))
  531. X    {
  532. X      STRCAT(dirs->d_name, coff) ;
  533. X      STRCAT(dirs->d_name, "/") ;
  534. X    }
  535. X  STRCAT(dirs->d_name, cur->d_name) ;
  536. X  no_dirs++ ;
  537. X  return(1) ;
  538. X}
  539. X
  540. X
  541. Xmake_file_entry()      /* Make a record for this new file. */
  542. X{
  543. X  struct finfo *temp ;
  544. X
  545. X  if ((cstat.st_mode & S_IFMT) == REGULAR)
  546. X    {
  547. X      temp = (struct finfo *) Malloc(sizeof(struct finfo)) ;
  548. X      temp->next = files ;
  549. X      files = temp ;
  550. X
  551. X      files->dirent = cur ;
  552. X      files->mtime = cstat.st_mtime ;
  553. X    }
  554. X}
  555. X
  556. X
  557. Xno_record()     /* Check is this file is already being monitored. */
  558. X{
  559. X  if (files == NULL) return(1) ;
  560. X  cfile = files ;
  561. X  do
  562. X    if (cfile->dirent->d_fileno == cur->d_fileno) return(0) ;
  563. X  while ((cfile = cfile->next) != NULL) ;
  564. X  return(1) ;
  565. X}
  566. X
  567. X
  568. Xoutput(name,filetype)
  569. Xchar name[MAXLINE] ;
  570. Xint filetype ;
  571. X{
  572. X  char command[MAXLINE*7], rdirname[MAXLINE] ;
  573. X  int i ;
  574. X
  575. X  switch (filetype)
  576. X    {
  577. X      case DIRECTORY : if (usercp)
  578. X                         SPRINTF(command, "%s -r %s/%s %s:%s",
  579. X                                 cname, fdir, name, rhost, curdir) ;
  580. X                       else
  581. X                         {
  582. X                           SPRINTF(rdirname, "%s/%s", tdir, name) ;
  583. X                           if ((fd = open(rdirname, O_RDONLY)) == -1)
  584. X                             SPRINTF(command, "mkdir %s", rdirname) ;
  585. X                           else
  586. X                             {
  587. X                               CLOSE(fd) ;
  588. X                               return ;
  589. X                             }
  590. X                         }
  591. X                       break ;
  592. X      case REGULAR   : if (usercp) SPRINTF(rdirname, "%s:%s", rhost, curdir) ;
  593. X                       else
  594. X                         {
  595. X                           STRCPY(rdirname, tdir) ;
  596. X                           if (strlen(coff))
  597. X                             {
  598. X                               STRCAT(rdirname, "/") ;
  599. X                               STRCAT(rdirname, coff) ;
  600. X                             }
  601. X                         }
  602. X                       STRCPY(command, cname) ;
  603. X                       for (i = 0; i < fcnt; i++)
  604. X                         {
  605. X                           STRCAT(command, " ") ;
  606. X                           STRCAT(command, fdir) ;
  607. X                           STRCAT(command, "/") ;
  608. X                           STRCAT(command, flist[i]) ;
  609. X                         }
  610. X                       STRCAT(command, " ") ;
  611. X                       STRCAT(command, rdirname) ;
  612. X    }
  613. X  if (system(command))
  614. X    FPRINTF(stderr, "%s [FAILED]: %s\n\n", progname, command) ;
  615. X  else if (debug) FPRINTF(stderr, "%s succeeded: %s\n\n", progname, command) ;
  616. X
  617. X  fcnt = 0 ;
  618. X}
  619. X
  620. X
  621. Xsetup()
  622. X{
  623. X  dirs = (struct dinfo *) Malloc(sizeof(struct dinfo)) ;
  624. X  STRCPY(dirs->d_name, "") ;
  625. X  STRCPY(pdir, fdir) ;        /* Start directory for current cp request. */
  626. X  STRCPY(coff, "") ;          /* Name offset from start directory. */
  627. X
  628. X  STRCPY(cp_name, "/bin/cp") ;          /* Default names. */
  629. X  STRCPY(rcp_name, "/usr/ucb/rcp") ;
  630. X#ifdef CP
  631. X  if (access(CP, X_OK)) STRCPY(cp_name, CP) ;
  632. X#endif CP
  633. X#ifdef RCP
  634. X  if (access(RCP, X_OK)) STRCPY(rcp_name, RCP) ;
  635. X#endif RCP
  636. X
  637. X  if (usercp)                 /* Used by the output routine. */
  638. X    STRCPY(cname, rcp_name) ;
  639. X  else STRCPY(cname, cp_name) ;
  640. X  dirs->next = dirs ;
  641. X  cdir = dirs ;
  642. X}
  643. SHAR_EOF
  644. chmod 0444 abcd.c || echo "restore of abcd.c fails"
  645. set `wc -c abcd.c`;Sum=$1
  646. if test "$Sum" != "14484"
  647. then echo original size 14484, current size $Sum;fi
  648. echo "x - extracting ndir.c (Text)"
  649. sed 's/^X//' << 'SHAR_EOF' > ndir.c &&
  650. X
  651. X/*  @(#)ndir.c 1.2 89/01/10
  652. X *
  653. X *  4.2BSD directory access emulation for non-4.2 systems.
  654. X *  Based upon routines in appendix D of Portable C and Unix System
  655. X *  Programming by J. E. Lapin (Rabbit Software).
  656. X *
  657. X *  No responsibility is taken for any error in accuracies inherent
  658. X *  either to the comments or the code of this program, but if
  659. X *  reported to me then an attempt will be made to fix them.
  660. X */
  661. X
  662. X/*  Support for Berkeley directory reading routines on a V7/SysV file
  663. X *  system.
  664. X */
  665. X
  666. X/*  Open a directory. */
  667. X
  668. XDIR *
  669. Xopendir(name)
  670. Xchar *name ;
  671. X{
  672. X  register DIR *dirp ;
  673. X  register int fd ;
  674. X
  675. X  if ((fd = open(name, 0)) == -1) return NULL ;
  676. X  if ((dirp = (DIR *) malloc(sizeof(DIR))) == NULL)
  677. X    {
  678. X      close(fd) ;
  679. X      return NULL ;
  680. X    }
  681. X  dirp->dd_fd = fd ;
  682. X  dirp->dd_loc = 0 ;
  683. X  return dirp ;
  684. X}
  685. X
  686. X
  687. X/*  Read an old style directory entry and present it as a new one. */
  688. X
  689. X#define  ODIRSIZ  14
  690. X
  691. Xstruct olddirent
  692. X{
  693. X  short  od_ino ;
  694. X  char   od_name[ODIRSIZ] ;
  695. X} ;
  696. X
  697. X
  698. X/*  Get next entry in a directory. */
  699. X
  700. Xstruct dirent *
  701. Xreaddir(dirp)
  702. Xregister DIR *dirp ;
  703. X{
  704. X  register struct olddirent *dp ;
  705. X  static struct dirent dir ;
  706. X
  707. X  for (;;)
  708. X    {
  709. X      if (dirp->dd_loc == 0)
  710. X        {
  711. X          dirp->dd_size = read(dirp->dd_fd, fd, dirp->dd_buf, DIRBLKSIZ) ;
  712. X          if (dirp->dd_size <= 0) return NULL ;
  713. X        }
  714. X      if (dirp->dd_loc >= dirp->dd_size)
  715. X        {
  716. X          dirp->dd_loc = 0 ;
  717. X          continue ;
  718. X        }
  719. X
  720. X      dp = (struct olddirent *)(dirp->dd_buf + dirp->dd_loc) ;
  721. X      dirp->dd_loc += sizeof(struct olddirent) ;
  722. X
  723. X      if (dp->od_ino == 0) continue ;
  724. X
  725. X      dir.d_fileno = dp->od_ino ;
  726. X      strncpy(dir.d_name, dp->od_name, ODIRSIZ) ;
  727. X      dir.d_name[ODIRSIZ] = ' ' ;       /* Ensure termination. */
  728. X      dir.d_namlen = strlen(dir.d_name) ;
  729. X      dir.d_reclen = DIRSIZ(&dir) ;
  730. X      return(&dir) ;
  731. X    }
  732. X}
  733. X
  734. X
  735. X/*  Close a directory. */
  736. X
  737. Xvoid
  738. Xclosedir(dirp)
  739. Xregister DIR *dirp ;
  740. X{
  741. X  close(dirp->dd_fd) ;
  742. X  dirp->dd_fd = -1 ;
  743. X  dirp->dd_loc = 0 ;
  744. X  free(dirp) ;
  745. X} 
  746. SHAR_EOF
  747. chmod 0444 ndir.c || echo "restore of ndir.c fails"
  748. set `wc -c ndir.c`;Sum=$1
  749. if test "$Sum" != "1998"
  750. then echo original size 1998, current size $Sum;fi
  751. echo "x - extracting abcd.h (Text)"
  752. sed 's/^X//' << 'SHAR_EOF' > abcd.h &&
  753. X
  754. X/*  @(#)abcd.h 1.2 89/01/08
  755. X *
  756. X *  Definitions used by abcd, the automatic backup copy daemon.
  757. X *
  758. X *  Copyright (c) Rich Burridge.
  759. X *                Sun Microsystems Australia - All rights reserved.
  760. X * 
  761. X *  Permission is given to distribute these sources, as long as the
  762. X *  copyright messages are not removed, and no monies are exchanged.
  763. X *
  764. X *  No responsibility is taken for any error in accuracies inherent
  765. X *  either to the comments or the code of this program, but if
  766. X *  reported to me then an attempt will be made to fix them.
  767. X */
  768. X
  769. X#define  CLOSE       (void) close     /* To make lint happy. */
  770. X#define  CLOSEDIR    (void) closedir
  771. X#define  FPRINTF     (void) fprintf
  772. X#define  SPRINTF     (void) sprintf
  773. X#define  SIGNAL      (void) signal
  774. X#define  STAT        (void) stat
  775. X#define  STRCAT      (void) strcat
  776. X#define  STRCPY      (void) strcpy
  777. X
  778. X#define  DIRECTORY   S_IFDIR          /* Type of files being monitored. */
  779. X#define  REGULAR     S_IFREG
  780. X
  781. X#define  DOTS(A)     (A[0] == '.' && (A[1] == 0 || (A[1] == '.' && A[2] == 0)))
  782. X#define  EQUAL(a,b)  !strcmp(a,b)     /* Test for string equality. */
  783. X#define  INC         argc-- ; argv++ ;
  784. X#define  MAXFILES    5                /* Max no of files to copy in one go. */
  785. X#define  MAXLINE     MAXNAMLEN+1      /* Maximum length of path names. */
  786. X
  787. X
  788. Xstruct dinfo         /* Info record for directories being monitored. */
  789. X         {
  790. X           struct dinfo *next ;
  791. X           char d_name[MAXLINE] ;
  792. X         } ;
  793. X
  794. Xstruct finfo         /* Information record for monitored files. */
  795. X         {
  796. X           struct finfo *next ;
  797. X           struct dirent *dirent ;
  798. X           time_t mtime ;
  799. X          } ;
  800. SHAR_EOF
  801. chmod 0444 abcd.h || echo "restore of abcd.h fails"
  802. set `wc -c abcd.h`;Sum=$1
  803. if test "$Sum" != "1650"
  804. then echo original size 1650, current size $Sum;fi
  805. echo "x - extracting ndir.h (Text)"
  806. sed 's/^X//' << 'SHAR_EOF' > ndir.h &&
  807. X
  808. X/*  @(#)ndir.h 1.2 89/01/10
  809. X *
  810. X *  4.2BSD directory access emulation for non-4.2 systems.
  811. X *  Based upon routines in appendix D of Portable C and Unix System
  812. X *  Programming by J. E. Lapin (Rabbit Software).
  813. X *
  814. X *  No responsibility is taken for any error in accuracies inherent
  815. X *  either to the comments or the code of this program, but if
  816. X *  reported to me then an attempt will be made to fix them.
  817. X */
  818. X
  819. X#ifndef  DEV_BSIZE
  820. X#define  DEV_BSIZE  512           /* Device block size. */
  821. X#endif
  822. X
  823. X#define  DIRBLKSIZ  DEV_BSIZE
  824. X#define  MAXNAMLEN  255           /* Name must be no longer than this. */
  825. X
  826. Xstruct dirent
  827. X{
  828. X  long  d_fileno ;                /* Inode number of entry. */
  829. X  short d_reclen ;                /* Length of this record. */
  830. X  short d_namlen ;                /* Length of d_name string. */
  831. X  char  d_name[MAXNAMLEN + 1] ;   /* Directory name. */
  832. X} ;
  833. X
  834. X
  835. X/*  The DIRSIZ macro gives the minimum record length that will hold the
  836. X *  directory entry. This requires the amount of space in struct direct
  837. X *  without the d_name field, plus enough space for the name with a
  838. X *  terminating null byte (dp->d_namlen+1), rounded up to a 4 byte
  839. X *  boundary.
  840. X */
  841. X
  842. X#undef   DIRSIZ
  843. X#define  DIRSIZ(dp)                                \
  844. X         ((sizeof (struct dirent) - (MAXNAMLEN+1)) \
  845. X         + (((dp)->d_namlen+1 + 3) &~ 3))
  846. X
  847. X/*  Definitions for library routines operating on directories. */
  848. X
  849. Xtypedef struct _dirdesc
  850. X{
  851. X  int    dd_fd ;
  852. X  long   dd_loc ;
  853. X  long   dd_size ;
  854. X  char   dd_buf[DIRBLKSIZ] ;
  855. X} DIR ;
  856. X
  857. X#ifndef  NULL
  858. X#define  NULL  0
  859. X#endif
  860. X
  861. Xextern  DIR              *opendir() ;
  862. Xextern  struct dirent    *readdir() ;
  863. Xextern  long             telldir() ;
  864. Xextern  void             seekdir() ;
  865. X#define rewinddir(dirp)  seekdir((dirp), (long) 0)
  866. Xextern  void             closedir() ;
  867. SHAR_EOF
  868. chmod 0444 ndir.h || echo "restore of ndir.h fails"
  869. set `wc -c ndir.h`;Sum=$1
  870. if test "$Sum" != "1795"
  871. then echo original size 1795, current size $Sum;fi
  872. echo "x - extracting patchlevel.h (Text)"
  873. sed 's/^X//' << 'SHAR_EOF' > patchlevel.h &&
  874. X
  875. X/*  @(#)patchlevel.h 1.3 89/04/10
  876. X *
  877. X *  This is the current patch level for this version of abcd.
  878. X *
  879. X *  Copyright (c) Rich Burridge.
  880. X *                Sun Microsystems, Australia - All rights reserved.
  881. X *
  882. X *  Permission is given to distribute these sources, as long as the
  883. X *  copyright messages are not removed, and no monies are exchanged.
  884. X *
  885. X *  No responsibility is taken for any errors or inaccuracies inherent
  886. X *  either to the comments or the code of this program, but if
  887. X *  reported to me then an attempt will be made to fix them.
  888. X */
  889. X
  890. X#define  PATCHLEVEL  1
  891. SHAR_EOF
  892. chmod 0444 patchlevel.h || echo "restore of patchlevel.h fails"
  893. set `wc -c patchlevel.h`;Sum=$1
  894. if test "$Sum" != "571"
  895. then echo original size 571, current size $Sum;fi
  896. echo "x - extracting abcd.1 (Text)"
  897. sed 's/^X//' << 'SHAR_EOF' > abcd.1 &&
  898. X.\" @(#)abcd.1 1.3 89/04/10
  899. X.TH ABCD 1L "9 January 1989"
  900. X.SH NAME
  901. Xabcd \- automatic backup copy daemon
  902. X.SH SYNOPSIS
  903. X.B "abcd
  904. X[
  905. X.B \-c
  906. X]
  907. X[
  908. X.B \-d
  909. X]
  910. X[
  911. X.B \-f
  912. X.I directory
  913. X]
  914. X[
  915. X.B \-r
  916. X.I hostname
  917. X]
  918. X[
  919. X.B \-s
  920. X.I seconds
  921. X]
  922. X[
  923. X.B \-t
  924. X.I directory
  925. X]
  926. X[
  927. X.B \-v
  928. X]
  929. X.SH DESCRIPTION
  930. X.I Abcd
  931. Xis an automatic backup copy daemon, which copies files from one
  932. Xfilestore area to another using either cp or rcp. Note the second filestore
  933. Xarea could be on another machine if the file system is NFS mounted.
  934. X.LP
  935. XThis means that the backup machine should have an almost identical copy
  936. Xof the filestore being monitored.
  937. X.LP
  938. XA start directory for monitoring is given. All the files including
  939. Xsub-directories and their files are monitored. Whenever any one of
  940. Xthem is changed it is automatically copied to another machine as
  941. Xspecified by the initial parameters to the program.
  942. X.LP
  943. XIf it finds a new directory, then it will make that new directory
  944. Xin the other area if not present.
  945. X.LP
  946. XIf a sub-directory is deleted, then that directory is removed from
  947. Xthe list of directories being monitored. If the original start directory
  948. Xis removed, then the program terminates because there is nothing left
  949. Xto monitor.
  950. X.LP
  951. XIf nothing has changed in one complete pass of all the directories
  952. Xbeen monitored, then the program puts itself to sleep for a specified
  953. Xperiod.
  954. X.LP
  955. XThere is a restart facility whereby if the machine has crashed, then it
  956. Xis possible to tell the program not to copy anything for the first pass,
  957. Xbut to start copying changed files from the second pass onwards.
  958. X.SH OPTIONS
  959. X.TP
  960. X.B -c
  961. XIf given, then abcd won't copy the first time through.
  962. X.TP
  963. X.B -d
  964. XIf used, the more status information will be displayed.
  965. X.TP
  966. X.BI \-f " directory"
  967. XDirectory to start copying from. Defaults to /usr.
  968. X.TP 
  969. X.BI \-r " hostname"
  970. XThis is an alternative form of backup. Uses rcp and copies to
  971. Xhostname supplied.
  972. X.TP 
  973. X.BI \-s " seconds"
  974. XSpecifies the sleep period in seconds for when the program puts
  975. Xitself to sleep. Default is 5 minutes.
  976. X.TP
  977. X.BI \-t " directory"
  978. XDirectory to start copying to. Defaults to /usr2.
  979. X.TP
  980. X.B \-v
  981. XPrint the version number of this release of the
  982. X.B abcd
  983. Xprogram.
  984. X.SH BUGS
  985. XThis program is currently totally inpractical for monitoring filestore
  986. Xareas containing large files which are being continuously updated, such
  987. Xas databases.
  988. X.SH AUTHOR
  989. XRich Burridge,        DOMAIN: richb@sunaus.oz.au
  990. X.nf
  991. XPHONE: +61 2 413 2666   UUCP:   {uunet,mcvax,ukc}!munnari!sunaus.oz!richb
  992. X.fi
  993. SHAR_EOF
  994. chmod 0444 abcd.1 || echo "restore of abcd.1 fails"
  995. set `wc -c abcd.1`;Sum=$1
  996. if test "$Sum" != "2452"
  997. then echo original size 2452, current size $Sum;fi
  998. exit 0
  999.  
  1000.