home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume05 / flock < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  10.5 KB

  1. From decwrl!labrea!rutgers!ukma!cwjcc!hal!ncoast!allbery Sun Oct 30 15:06:24 PST 1988
  2. Article 691 of comp.sources.misc:
  3. Path: granite!decwrl!labrea!rutgers!ukma!cwjcc!hal!ncoast!allbery
  4. From: ksb@s.cc.purdue.edu (Kevin Braunsdorf)
  5. Newsgroups: comp.sources.misc
  6. Subject: v05i014: flock - shell level access to flock(2)
  7. Message-ID: <8810232013.AA06867@s.cc.purdue.edu>
  8. Date: 28 Oct 88 02:46:21 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Reply-To: ksb@s.cc.purdue.edu (Kevin Braunsdorf)
  11. Lines: 411
  12. Approved: allbery@ncoast.UUCP
  13.  
  14. Posting-number: Volume 5, Issue 14
  15. Submitted-by: "Kevin Braunsdorf" <ksb@s.cc.purdue.edu>
  16. Archive-name: flock
  17.  
  18. [This was supposed to have been posted a few weeks ago but somehow found a
  19. crack to get lost in!  (oops!)  ++bsa]
  20.  
  21. #    This is a shell archive.
  22. #    Remove everything above and including the cut line.
  23. #    Then run the rest of the file through sh.
  24. #----cut here-----cut here-----cut here-----cut here----#
  25. #!/bin/sh
  26. # shar:    Shell Archiver
  27. #    Run the following text with /bin/sh to create:
  28. #    README        Makefile
  29. #    flock.1l     flock.c
  30. # This archive created: Sun Oct 23 15:09:58 1988
  31. # By:    Kevin Braunsdorf (Purdue UNIX Group)
  32. sed 's/^K//' << \SHAR_EOF > README
  33. KFlock applies or removes an advisory lock on the named file or file
  34. Kdescriptor.  Advisory locks allow cooperating processes to perform
  35. Kconsistent operations on files see flock(2).  This program is *very*
  36. Kuseful on a Sequent machine; almost as useful on fast uniprocessors.
  37. K
  38. KHere is a case where flock(1) is very useful: on a Sequent Balance
  39. Kseries machine parallel make can be used to compile many files at the
  40. Ksame time.  This doesn't work for programs that use xstr(1) because
  41. Kcompeting processes using xstrings fails.  In the Makefile for vi one
  42. Kmight use a flock on the Makefile to force (only) the xstr to be run
  43. Ksequentially:
  44. K
  45. K    .c.o:
  46. K        ${CC} -E ${CFLAGS} $*.c | \
  47. K        flock Makefile sh -c "${XSTR} -c -; mv x.c $*.p.x"; \
  48. K        sed '/rcsid\[\]/d' < $*.p.x > $*.p.c; \
  49. K        ${CC} ${CFLAGS} -c $*.p.c; \
  50. K        mv $*.p.o $*.o; \
  51. K        rm $*.p.x $*.p.c
  52. K      
  53. KWhich will start a few cpps in parallel and run only one xstr at a time,
  54. Kas soon as it can it will run the sed/cc/mv/rm allowing another process
  55. Kto begin using xstr.
  56. K
  57. K(I flock the Makefile by convention, because I know I always have one.
  58. K If more then one command set needs to work from the same Makefile I
  59. K flock `complie.lock', and `yacc.lock' or some such, not using Makefile
  60. K for either.  The clean target in the Makefile removes these files.)
  61. K
  62. Kkayessbee (Kevin S Braunsdorf) ksb@j.cc.purdue.edu, pur-ee!ksb
  63. SHAR_EOF
  64. sed 's/^K//' << \SHAR_EOF > flock.1l
  65. K.\" $Id: flock.1l,v 1.3 88/10/23 14:53:53 ksb Exp $
  66. K.\" by Kevin Braunsdorf and Matthew Bradburn
  67. K.TH FLOCK 1L LOCAL
  68. K.SH NAME
  69. Kflock - lock a file to synchronize command streams
  70. K.SH SYNOPSIS
  71. K\fBflock\fP [-\fBc\fP\fBh\fP\fBn\fP] [\-\fBEX\fP|\fBSH\fP|\fBUN\fP|\fBNB\fP] \fIfile\fP|\fIfd\fP [\fIcmd\fP]
  72. K.SH DESCRIPTION
  73. KFlock applies or removes an advisory lock on the named file or file descriptor.
  74. KAdvisory locks allow cooperating processes to perform consistent operations
  75. Kon files see \fIflock\fP(2).
  76. K.PP
  77. KThe exit status from the \fBflock\fP command is the exit status of
  78. Kits child.  The default \fIcmd\fP is ``/bin/true'' so that by default
  79. K\fBflock\fP will succeed.  \fBFlock\fP with exit nonzero if either
  80. K\-\fBNB\fP (nonblocking) is specified and flock fails, or
  81. Kthe specified \fIfile\fP (\fIfd\fP) cannot be (isn't) opened.
  82. K.PP
  83. KIt \fBflock\fP has to open the file to get the lock it will not pass
  84. Kthe created file descriptor to the child process.  (Said process might
  85. Kunlock the descriptor.)
  86. K.SH OPTIONS
  87. K.TP
  88. K.BI \-c
  89. KCreate the lock file if it doesn't exist.
  90. K.TP
  91. K.BI \-h
  92. KGive a brief help message.
  93. K.TP
  94. K.BI \-n
  95. KDo not create the lock file if it doesn't exist.  This is the default.
  96. K.TP
  97. K.BI \-EX
  98. KSet or reset the LOCK_EX bit in the arguments to \fIflock\fP(2).
  99. KThis is the default if no locking bits are given.
  100. K.TP
  101. K.BI \-NB
  102. KSet or reset the LOCK_NB bit in the arguments to \fIflock\fP(2).
  103. K.TP
  104. K.BI \-SH
  105. KSet or reset the LOCK_SH bit in the arguments to \fIflock\fP(2).
  106. K.TP
  107. K.BI \-UN
  108. KSet or reset the LOCK_UN bit in the arguments to \fIflock\fP(2).
  109. KThis option is only useful when a file descriptor is given as the
  110. K`file' on which to operate.
  111. K.PP
  112. KThe option \-\fBEX\fP may be spelled \-\fBLOCK_EX\fP, likewise the other
  113. Klocking bits may be spelled more verbosely.
  114. K.PP
  115. KThe locking bits may be inclusive or'ed together with a pipe (`|'), which
  116. Kmust be quoted from the shell.
  117. K.SH EXAMPLES
  118. K.PP
  119. KIf a given daemon flocks its log file before each group of writes
  120. Kone might use:
  121. K.sp 1
  122. K    flock -EX 1 echo \*(lqsomething important\*(rq >>daemon.log
  123. K.sp 1
  124. Kto avoid interlaminate writes to the log.
  125. K.PP
  126. KIn a shell script:
  127. K.sp 1
  128. K    # stdout is a (possibly) shared file so we wait for it
  129. K.br
  130. K    flock -EX 1
  131. K.br
  132. K    # these have to be run under one lock
  133. K.br
  134. K    doit1 ; doit2; doit3
  135. K.br
  136. K    # end critical code, unlock the descriptor
  137. K.br
  138. K    flock -UN 1
  139. K.sp 1
  140. KTo edit a shared file:
  141. K.sp 1
  142. K    flock share.c vi share.c
  143. K.sp 1
  144. K.SH BUGS
  145. KNone known.
  146. K.SH AUTHOR
  147. KKevin Braunsdorf
  148. K.br
  149. KPurdue University, West Laffayette IN
  150. K.br
  151. Kpur-ee!ksb, ksb@j.cc.purdue.edu
  152. K.SH "SEE ALSO"
  153. Ksh(1), true(1), flock(2), open(2)
  154. SHAR_EOF
  155. sed 's/^K//' << \SHAR_EOF > Makefile
  156. K# makefile for flock
  157. K#            by Kevin S Braunsdorf, PUCC
  158. K
  159. KBIN=    ${DESTDIR}$$HOME/bin
  160. K
  161. KI=/usr/include
  162. KS=/usr/include/sys
  163. K
  164. KINCLUDE=
  165. KDEBUG=    -O
  166. KCDEFS=    -Dbsd
  167. KCFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
  168. K
  169. KHDR=    
  170. KSRC=    flock.c
  171. KOBJ=    flock.o
  172. KSOURCE=    Makefile ${HDR} ${SRC}
  173. K
  174. Kall: flock
  175. K
  176. Kflock:
  177. K    ${CC} -o $@ ${CFLAGS} flock.c
  178. K
  179. Kclean: FRC
  180. K    rm -f Makefile.bak flock *.o a.out core errs tags
  181. K
  182. Kdepend: ${SRC} ${HDR} FRC
  183. K    maketd -a ${CDEFS} ${INCLUDE} -b flock.c
  184. K
  185. Kinstall: all FRC
  186. K    install -c -s flock ${BIN}
  187. K
  188. Klint: ${HDR} ${SRC} FRC
  189. K    lint -hnx ${CDEFS} ${INCLUDE} ${SRC}
  190. K
  191. Kprint: source FRC
  192. K    lpr -J'flock source' ${SOURCE}
  193. K
  194. Ksource: ${SOURCE}
  195. K
  196. Kspotless: clean
  197. K    rcsclean ${SOURCE}
  198. K
  199. Ktags: ${SRC} ${HDR}
  200. K    ctags -t ${SRC} ${HDR}
  201. K
  202. K${SOURCE}:
  203. K    co $@
  204. K
  205. KFRC:
  206. K
  207. K# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
  208. K
  209. Kflock: $I/fcntl.h $I/stdio.h $S/file.h $S/types.h $S/wait.h flock.c
  210. K
  211. K# *** Do not add anything here - It will go away. ***
  212. SHAR_EOF
  213. sed 's/^K//' << \SHAR_EOF > flock.c
  214. K/*
  215. K * flock a file and wait for a process to exit                (ksb)
  216. K *
  217. K * Copyright 1988, All Rights Reserved
  218. K *    Kevin S Braunsdorf
  219. K *    ksb@j.cc.purdue.edu, pur-ee!ksb
  220. K *    Math/Sci Building, Purdue Univ
  221. K *    West Lafayette, IN
  222. K *
  223. K *  `You may redistibute this code as long as you don't claim to have
  224. K *   written it. -- kayessbee'
  225. K *
  226. K * $Compile: ${cc-cc} ${DEBUG--C} ${SYS--Dbsd} %f -o %F
  227. K */
  228. K#include <sys/types.h>
  229. K#include <sys/file.h>
  230. K#include <sys/wait.h>
  231. K#include <fcntl.h>
  232. K#include <stdio.h>
  233. K
  234. K#if defined(bsd)
  235. K#define strchr    index
  236. K#define strrchr    rindex
  237. K#endif
  238. K
  239. Kstatic char *progname =
  240. K    "$Id: flock.c,v 2.0 88/10/23 15:06:21 ksb Exp $";
  241. K
  242. Kstatic char acUsage[] =        /* this is the usage line for the user    */
  243. K    "%s: usage [-chn] [-EX|SH|UN|NB] file|fd [cmd]\n";
  244. Kstatic char *apcHelp[] = {    /* help text                */
  245. K    "c    create file, if nonexistant",
  246. K    "h    print this help message",
  247. K    "n    do not create file",
  248. K    "EX    exclusive lock, default",
  249. K    "NB    do not block for lock",
  250. K    "SH    shared lock",
  251. K    "UN    unlock",
  252. K    (char *)0
  253. K};
  254. K
  255. Ktypedef struct LKnode {        /* a cmd line option implies a lock bit    */
  256. K    char *pcflag;
  257. K    int iflag;
  258. K} LOCKKEY;
  259. K
  260. Kstatic LOCKKEY aLKLocks[] = {    /* the list of the cmd lines we know    */
  261. K    {"LOCK_EX", LOCK_EX},
  262. K    {"LOCK_SH", LOCK_SH},
  263. K    {"LOCK_UN", LOCK_UN},
  264. K    {"LOCK_NB", LOCK_NB},
  265. K    {"EX", LOCK_EX},
  266. K    {"SH", LOCK_SH},
  267. K    {"UN", LOCK_UN},
  268. K    {"NB", LOCK_NB},
  269. K    {(char *)0, -1}
  270. K};
  271. K
  272. K/*
  273. K * determine which flag the use wants to set/clear            (ksb)
  274. K */
  275. Kint
  276. KFlag(pcCmd)
  277. Kchar *pcCmd;
  278. K{
  279. K    register char *pcTry;
  280. K    register LOCKKEY *pLK;
  281. K    extern char *strchr();
  282. K
  283. K    for (pLK = aLKLocks; (char *)0 != (pcTry = pLK->pcflag); ++pLK) {
  284. K        if (0 == strcmp(pcTry, pcCmd)) {
  285. K            return pLK->iflag;
  286. K        }
  287. K    }
  288. K    if ((char *)0 != (pcTry = strchr(pcCmd, '|'))) {
  289. K        *pcTry++ = '\000';
  290. K        return Flag(pcCmd)|Flag(pcTry);
  291. K    }
  292. K
  293. K    fprintf(stderr, "%s: `%s' is not a flock key\n", progname, pcCmd);
  294. K    exit(1);
  295. K    /*NOTREACHED*/
  296. K}
  297. K
  298. K/*
  299. K * is this character string all digits                    (ksb)
  300. K */
  301. Kint
  302. Kisnumber(pc)
  303. Kchar *pc;
  304. K{
  305. K    while (*pc) {
  306. K        if (*pc < '0' || *pc > '9')
  307. K            break;
  308. K        ++pc;
  309. K    }
  310. K    return *pc == '\000';
  311. K}
  312. K
  313. K/*
  314. K * Get a lock on the named file and execute the rest of our arguments    (ksb)
  315. K * while the lock is active, when this command exits exit with it's
  316. K * extit status.
  317. K */
  318. Kint
  319. Kmain(argc, argv)
  320. Kint argc;
  321. Kchar **argv;
  322. K{
  323. K    extern int atoi();
  324. K    extern char *strrchr();
  325. K    static char *apcTrue[] = {"true", (char *)0};
  326. K    auto union wait wait_buf;
  327. K    auto int fd, tClose, oFlags, fCreate = 0;
  328. K    auto int iLock = -1;
  329. K    auto char **ppcHelp;
  330. K
  331. K
  332. K    if ((char *)0 != (progname = strrchr(*argv, '/'))) {
  333. K        ++progname;
  334. K    } else {
  335. K        progname = *argv;
  336. K    }
  337. K    ++argv, --argc;
  338. K    while (argc > 0 && '-' == argv[0][0]) {
  339. K        switch (*++argv[0]) {
  340. K        case '\000':
  341. K            break;
  342. K        case 'n':
  343. K        case 'c':
  344. K            fCreate = argv[0][0] == 'c';
  345. K            argv[0][0] = '-';
  346. K            continue;
  347. K        case 'h':
  348. K            fprintf(stdout, acUsage, progname);
  349. K            for (ppcHelp = apcHelp; (char *)0 != *ppcHelp; ++ppcHelp) {
  350. K                fprintf(stdout, "%s\n", *ppcHelp);
  351. K            }
  352. K            exit(0);
  353. K        default:
  354. K            if (-1 == iLock)
  355. K                iLock = 0;
  356. K            iLock ^= Flag(argv[0]);
  357. K            break;
  358. K        }
  359. K        ++argv, --argc;
  360. K    }
  361. K
  362. K    if (-1 == iLock) {
  363. K        iLock = LOCK_EX;
  364. K    }
  365. K
  366. K    if (0 == argc) {
  367. K        fprintf(stderr, acUsage, progname);
  368. K        exit(1);
  369. K    }
  370. K
  371. K    tClose = 1;
  372. K    if (-1 == (fd = open(argv[0], O_RDONLY, 0600))) {
  373. K        oFlags = 0 != fCreate ? O_CREAT|O_WRONLY|O_APPEND : O_WRONLY|O_APPEND;
  374. K        if (-1 == (fd = open(argv[0], oFlags, 0666))) {
  375. K            if (!isnumber(argv[0])) {
  376. K                fprintf(stderr, "%s: open: ", progname);
  377. K                perror(argv[0]);
  378. K                exit(1);
  379. K            }
  380. K            fd = atoi(argv[0]);
  381. K            if (-1 == fcntl(fd, F_GETFD, 0)) {
  382. K                fprintf(stderr, "%s: %d: ", progname, fd);
  383. K                perror("fcntl");
  384. K                exit(1);
  385. K            }
  386. K            tClose = 0;
  387. K        }
  388. K    }
  389. K    if (-1 == flock(fd, iLock)) {
  390. K        fprintf(stderr, "%s: flock: ", progname);
  391. K        perror(argv[0]);
  392. K        exit(1);
  393. K    }
  394. K    ++argv, --argc;
  395. K
  396. K    if (0 == argc) {
  397. K        argv = apcTrue;
  398. K    }
  399. K    if (tClose != 0) {        /* save a fork */
  400. K        switch (fork()) {
  401. K        case 0:
  402. K            close(fd);
  403. K            break;
  404. K        case -1:
  405. K            fprintf(stderr, "%s: ", progname);
  406. K            perror("fork");
  407. K            exit(1);
  408. K            /*NOTREACHED*/
  409. K        default:
  410. K            wait(& wait_buf);
  411. K            /* exit will close fd for us */
  412. K            exit((int) wait_buf.w_retcode);
  413. K            /*NOTREACHED*/
  414. K        }
  415. K    }
  416. K    execvp(argv[0], argv);
  417. K    fprintf(stderr, "%s: ", progname);
  418. K    perror(argv[0]);
  419. K    exit(1);
  420. K    /*NOTREACHED*/
  421. K}
  422. SHAR_EOF
  423. #    End of shell archive
  424. exit 0
  425.  
  426.  
  427.