home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume13 / with < prev    next >
Text File  |  1988-01-31  |  20KB  |  730 lines

  1. Subject:  v13i048:  Resource allocation program
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Rob McMahon <daisy.warwick.ac.uk!cudcv>
  7. Posting-number: Volume 13, Issue 48
  8. Archive-name: with
  9.  
  10. With will reserve exclusive use of a device by creating a lock file,
  11. changing ownership of the device to your current user id, setting the
  12. device to mode 600 (rw by you, nothing to others), and giving you a new
  13. shell.  When the shell terminates, the device is released.  In the event
  14. that a device is in use by another user you will be notified of this, and
  15. with can wait until it is available.
  16.  
  17. For example:
  18.     with -n tape "Rob's tape, to read, please"
  19.     with tape "..." -c "tar xvp ; mt offl" > tar.out &
  20. ----
  21. #!/bin/sh
  22. echo 'Start of pack.out, part 01 of 01:'
  23. echo 'x - Makefile'
  24. sed 's/^X//' > Makefile << '/'
  25. X# makefile for with
  26. X
  27. X# DESTDIR is the destination directory (in which the compiled source lives)
  28. X# CFLAGS contains the arguments passed to the C compiler
  29. X# SEPID whether to be compiled with -i or -n (not used on the VAX)
  30. X# R prefix to destination names (ie. an optional root)
  31. X# HACKS - local flags to the C compiler to define/undefine symbols
  32. X
  33. XDESTDIR=/usr/local
  34. XHACKS=
  35. XSEPID=
  36. XCFLAGS=-O $(SEPID) $(HACKS)
  37. XR=
  38. X
  39. X.SUFFIXES:    .c,v
  40. X
  41. Xall with: with.o
  42. X    $(CC) $(CFLAGS) with.o -o with
  43. X
  44. Xcp install:     with
  45. X    install -s -o root -g general -m 4710 with $R$(DESTDIR)
  46. X
  47. Xcmp:    with
  48. X    -cmp with $R$(DESTDIR)/with
  49. X    rm -f with *.o
  50. X
  51. Xclean:
  52. X    rm -f with *.o
  53. X
  54. X.c,v.o:
  55. X    co -q $*.c
  56. X    $(CC) $(CFLAGS) -c $*.c
  57. X    rm -f $*.c
  58. X
  59. X# entry points are (at least):
  60. X#  all, with - compile with and leave it where it is
  61. X#  cp, install - compile and install with
  62. X#  cmp         - compile and compare with, remove dross
  63. X#  clean       - removes any garbage
  64. X# default action is to compile and leave the binary in situ
  65. X
  66. X
  67. X# there are problems if the command name is the same as an entry point.
  68. X# there are problems moving mv to /usr/ucb/mv (text in use)
  69. X#       or cping cp to /bin/cp
  70. X#
  71. X# clean does not remove .c files when the source is in sccs s. ... .c format
  72. /
  73. echo 'x - README'
  74. sed 's/^X//' > README << '/'
  75. XWith is based on a set of programs, written by Dave Butterfield at the
  76. XUCLA Dept. of Mathamatics, called get & rls.  These programs had a
  77. Xnumber of problems in our environment, the worst being that you couldn't
  78. Xuse them to run a job in the background.  Out of this grew with.
  79. X
  80. XWith uses a lockfile (LOCKSFILE, "/etc/locks/lockfiles" by default),
  81. Xwith lines consisting of: name of file to create and flock, name of
  82. Xresources as known to user, and a list of up to MAXPDEV (16) devices
  83. Xwhich are chown'ed to the user, and given mode OWNERONLY (0600,
  84. X-rw-------), before a subshell is started.  When the shell exits, the
  85. Xdevices are chown'ed back to Rootuid, Rootgid (0,3), and the flock is
  86. Xremoved by with exiting.  (The lockfile is not removed, as someone else
  87. Xcould have an flock pending on it.)
  88. X
  89. XA second argument can be given to with, and if it is not an empty string
  90. Xit is a request which is sent to the operators via syslog, and with then
  91. Xwaits for a signal back from the operators to say whether the request
  92. Xhas been fulfilled or denied (SIGEMT or SIGTERM).  Any extra arguments
  93. Xare passed to the subshell.
  94. X
  95. XA pseudo-resource '-' is available, which allows a request to the
  96. Xoperators without actually getting any resource.  This is useful for
  97. Xe.g. loading the second tape.
  98. X
  99. Xe.g.
  100. X
  101. Xwith -n tape "Rob's tape, to read, please"
  102. X...
  103. Xmt offl
  104. Xwith - "second tape, please"
  105. X...
  106. Xmt offl
  107. X^D
  108. X
  109. XThe -n tells with not to wait if someone else is already using the tape
  110. Xdeck.  We recommend the 'mt offl's so that your tape is unavailable to
  111. Xanyone else using with after you release the tape deck.
  112. X
  113. XIn an 'at' job:
  114. X
  115. Xwith tape "..." << EOF
  116. X...
  117. Xmt offl
  118. XEOF
  119. X
  120. XIn the background:
  121. X
  122. Xwith tape "..." -c "tar xvp ; mt offl" > tar.out &
  123. X
  124. X---
  125. XUUCP:   ...!mcvax!ukc!warwick!cudcv    PHONE:  +44 203 523037
  126. XJANET:  cudcv@uk.ac.warwick.daisy       ARPA:   cudcv@daisy.warwick.ac.uk
  127. XRob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England
  128. /
  129. echo 'x - with.1'
  130. sed 's/^X//' > with.1 << '/'
  131. X.TH with 1 local
  132. X.SH NAME
  133. Xwith \- a program to reserve exclusive use of a device
  134. X.SH SYNOPSIS
  135. X.I
  136. X.B with
  137. X[
  138. X.B \-sn
  139. X]
  140. X.I dev
  141. X[
  142. X.I request
  143. X[
  144. X.I shell parameters
  145. X]
  146. X]
  147. X.SH DESCRIPTION
  148. X.I With
  149. Xwill reserve exclusive use of a device by creating a lock file, changing
  150. Xownership of the device to your current user id, setting the device to
  151. Xmode 600 (rw by you, nothing to others), and giving you a new shell.  When the
  152. Xshell terminates, the device is released.
  153. XIn the event that a device is in
  154. Xuse by another user you will be notified of this, and
  155. X.I with
  156. Xwill wait until it is available, or if the
  157. X.B \-n
  158. Xflag is given will return immediately with an indication of failure.
  159. XThe
  160. X.B \-s
  161. Xswitch causes
  162. X.I with
  163. Xto perform its work silently.
  164. X.I With
  165. Xreturns a nonzero return code to indicate failure.
  166. X.PP
  167. XIf a request is specified, the operators are asked to fulfil the request once
  168. Xthe device is available.  E.g.
  169. X.PP
  170. Xwith tape "cudcv's tape to read, please"
  171. X.PP
  172. XA request can be made without actually locking a device by specifying the
  173. Xdevice as `-'.  In this case no shell is started, but with waits until the
  174. Xrequest is fulfilled, and then exits.
  175. X.PP
  176. XArguments after the
  177. X.I request
  178. Xare handed to the shell.  A null request can be specified as `-', to grab a
  179. Xdevice and execute a command without making a request.
  180. X.PP
  181. XCurrently known devices are:
  182. X.TP 8
  183. Xtape
  184. XThe magtape; all 16 logical devices 800 & 1600 BPI: ({,n}{,r}mt{0,4,8,12}).
  185. X.SH FILES
  186. X.TP 30
  187. X/etc/locks/lockfiles
  188. Xfor device names, lock file names, and /dev/minordev names.
  189. X.SH ENVIRONMENT
  190. X.TP 20
  191. XSHELL
  192. Xfor user's default shell
  193. X.SH DIAGNOSTICS
  194. XA non-zero return code indicates one of the devices was not available, or with
  195. Xwas interrupted.
  196. X.nf
  197. Xdev is yours.
  198. Xdev is in use ... waiting
  199. Xdev is in use - try again later.
  200. Xdev released.
  201. XI don't know how to get dev.
  202. X.fi
  203. X.SH BUGS
  204. /
  205. echo 'x - with.c'
  206. sed 's/^X//' > with.c << '/'
  207. X/*
  208. X *      with --- a program to do simple device locking.
  209. X */
  210. X/*
  211. X * format of working file (lockfiles)
  212. X * full_name_of_lock_file name_of_device minor0 minor1 ...
  213. X * full name of files must include path (in great detail /.../.../...)
  214. X * there may be as many as MAXPDEV minor devices associated with name_of_device
  215. X * note that name_of_device need not be the same as any minor device
  216. X * example
  217. X * /etc/tape0.lock tape0 /dev/mt0 /dev/mt4 /dev/rmt0 /dev/rmt4
  218. X * /usr/spool/uucp/LCK..cul0 cul0 /dev/cul0
  219. X *
  220. X * $Log:    with.c,v $
  221. X * Revision 2.0  87/10/26  09:32:15  cudcv
  222. X * "Stable"
  223. X * 
  224. X * Revision 1.11  87/10/26  09:19:37  cudcv
  225. X * Cleanup comments, lint
  226. X * 
  227. X * Revision 1.10  86/09/17  09:01:42  cudcv
  228. X * 'waiting for confirmation' message wasn't getting out if stderr buffered.
  229. X * 
  230. X * Revision 1.9  86/08/06  10:34:33  cudcv
  231. X * Make handling of null resource cleaner, allow - as null request.
  232. X * 
  233. X * Revision 1.8  86/06/17  13:14:44  cudcv
  234. X * Allow further arguments to be passed to the shell
  235. X * Return status from shell
  236. X * 
  237. X * Revision 1.7  86/06/17  12:28:45  cudcv
  238. X * Slip of the editor
  239. X * 
  240. X * Revision 1.6  86/01/24  15:01:36  cudcv
  241. X * Restart shell when with is restarted
  242. X * 
  243. X * Revision 1.5  86/01/24  12:09:59  cudcv
  244. X * With would hang if shell was stopped
  245. X * 
  246. X * Revision 1.4  86/01/23  09:38:23  cudcv
  247. X * Was ignoring last device
  248. X * 
  249. X * Revision 1.3  86/01/23  09:02:20  cudcv
  250. X * Make more portable for Gould
  251. X * 
  252. X * Revision 1.2  86/01/21  15:04:35  cudcv
  253. X * Allow second argument with request to operators
  254. X * Record usercode of requester
  255. X * With no arguments lists current locks
  256. X * 
  257. X * Revision 1.1  85/10/07  10:31:25  cudcv
  258. X * Initial revision
  259. X * 
  260. X */
  261. Xstatic char RCSid[] = "$Header: with.c,v 2.0 87/10/26 09:32:15 cudcv Exp $";
  262. X#include <ctype.h>
  263. X#include <pwd.h>
  264. X#include <signal.h>
  265. X#include <stdio.h>
  266. X#include <strings.h>
  267. X#include <syslog.h>
  268. X#include <sys/time.h>
  269. X#include <sys/types.h>
  270. X#include <sys/dir.h>
  271. X#include <sys/file.h>
  272. X#include <sys/resource.h>
  273. X#include <sys/stat.h>
  274. X#include <sys/wait.h>
  275. X
  276. X#ifndef    PW_NAMEL
  277. X#define    PW_NAMEL    8
  278. X#endif
  279. X
  280. X#ifndef LOCKSFILE
  281. X#define    LOCKSDIR    "/etc/locks"
  282. X#define LOCKSFILE    "/etc/locks/lockfiles"
  283. X#endif
  284. X#define MAXSTLEN        40      /*much more than necessary*/
  285. X#define NLOCKS          10      /* "    "     "      "  */
  286. X#define MAXPDEV         16    /* max # phys. devices associate with a name*/
  287. X#define OWNERONLY       0600    /*protection mode for the devices*/
  288. X#define    LOGLEVEL    LOG_CRIT    /* level for syslog's */
  289. X
  290. X#define subdev(LP,n)     (& ( (LP)->physdev[n][0]))         /*all dave's fault*/
  291. X#define    mask(i)    (1 << (i-1))    /* for signals */
  292. X
  293. XFILE *fopen();
  294. X
  295. X#ifdef    RLIMIT_INTACT
  296. Xstruct rlimit intact = {1, 1};        /* make ourselves interactive */
  297. X#endif
  298. X
  299. Xtypedef struct {
  300. X    char    lok[MAXSTLEN],        /* lock (flock) */
  301. X            dev[MAXSTLEN],        /* what the user calls it (with dev) */
  302. X            physdev[MAXPDEV][MAXSTLEN];    /* /dev/dev */
  303. X    int    locked;            /*got lock on this*/
  304. X} dev_lk;
  305. X
  306. Xdev_lk    locks[NLOCKS];
  307. Xdev_lk    nolok;
  308. X
  309. Xchar    *progname;
  310. Xextern    int    optind;
  311. Xchar    *malloc(), *sprintf();
  312. Xstruct passwd *getpwuid();
  313. Xextern    char    *sys_siglist[];
  314. Xextern    char    *sys_errlist[];
  315. Xextern    int    errno;
  316. X
  317. Xint     silent = 0;
  318. Xint     nowait = 0;        /* don't wait until available */
  319. Xint     nerrs = 0;
  320. Xint    nlock = 0;
  321. Xint    Rootuid = 0, Rootgid = 3;     /* magic numbers */
  322. Xint     uuid, ugid;
  323. Xchar     *resource;
  324. Xint    needrequest = 0;    /* got resource, need extra request */
  325. Xint    requested = 0;        /* have warned of need, while waiting */
  326. Xint    fulfilled = 0;        /* request fulfilled */
  327. Xstruct passwd *pw;
  328. Xchar    buf[BUFSIZ];
  329. Xchar    **shellargs;
  330. X
  331. Xvoid    print_locks();
  332. X
  333. Xmain(argc,argv)
  334. Xint argc;
  335. Xchar *argv[];
  336. X{
  337. X        register int     i, pdev;
  338. X        register dev_lk *lkp;
  339. X    char    *request = NULL;
  340. X        int     c, lockfile, omask;
  341. X    int     mypid = getpid();
  342. X    int    cleanup(), fulfil();
  343. X
  344. X    uuid = getuid();
  345. X    ugid = getgid();
  346. X    if ((pw = getpwuid(uuid)) == (struct passwd *)NULL) {
  347. X        Printf("Who are you ?\n");
  348. X        exit(1);
  349. X    }
  350. X    (void) endpwent();
  351. X    progname = argv[0];
  352. X    while ((c = getopt(argc, argv, "sn")) != EOF)
  353. X        switch (c) {
  354. X        case 's':    silent++; break;
  355. X        case 'n':    nowait++; break;
  356. X        case '?':    nerrs++;  break;
  357. X        }
  358. X        if (nerrs){
  359. X        Printf("usage: %s [-sn] device [request [parameters]]\n",
  360. X        progname);
  361. X        Printf("eg:    %s tape \"cudcv's tape for read, please\"",
  362. X        progname);
  363. X        Printf(" -c dd if=/dev/rmt8 ...\n");
  364. X        exit(1);
  365. X    }
  366. X        if((nlock = read_loks(LOCKSFILE, locks)) < 0){
  367. X        Printf("%s:%s unopenable or messed up.\n",progname,LOCKSFILE);
  368. X        exit(1);
  369. X    }
  370. X        /* locks have been read-in */
  371. X
  372. X    if (argc == optind) {
  373. X        print_locks();
  374. X        exit(0);
  375. X    }
  376. X
  377. X        /*can't be interrupted once we start linking things so ...*/
  378. X    omask = sigsetmask((int)0x7fffffff);
  379. X        for(i = 1; i < NSIG; i++) {
  380. X        /* allow stopping */
  381. X        if (i == SIGTSTP || i == SIGTTIN || i == SIGTTOU) continue;
  382. X        /* don't catch those normally ignored */
  383. X        if (i == SIGURG  || i == SIGCONT ||
  384. X            i == SIGCHLD || i == SIGIO
  385. X#ifdef    SIGENQ
  386. X                     || i == SIGENQ
  387. X#endif
  388. X            ) continue;
  389. X        /* don't catch those currently ignored */
  390. X        if (signal(i, cleanup) == SIG_IGN)
  391. X            (void) signal(i, SIG_IGN);
  392. X    }
  393. X    (void) sigsetmask(omask);
  394. X    /* don't want to get clobbered by XCPU either */
  395. X#ifdef    RLIMIT_INTACT
  396. X    if (setrlimit(RLIMIT_INTACT, &intact)) {
  397. X        perror("setrlimit");
  398. X        exit(1);
  399. X    }
  400. X#endif
  401. X        /*now get resource*/
  402. X    resource = argv[optind++];
  403. X    if (argc > optind) {
  404. X        request = argv[optind++];
  405. X        if (!*request || !strcmp(request, "-"))
  406. X        request = NULL;
  407. X        (void) sprintf(buf, "(%s) with", pw->pw_name);
  408. X        openlog(buf, LOG_PID);
  409. X    }
  410. X    shellargs = &argv[optind-1];
  411. X    if (!strcmp(resource, "-")) {
  412. X        resource = NULL;
  413. X        lkp = &nolok;
  414. X        (void) sprintf(lkp->lok, "%s/%d", LOCKSDIR, getpid());
  415. X        (void) strcpy(lkp->dev, "request");
  416. X    } else {
  417. X        for (i = 0;i < nlock; i++)
  418. X                if (strcmp(locks[i].dev, resource) == 0) break;
  419. X            if(i >= nlock){
  420. X            Printf("I don't know how to get %s.\n", resource);
  421. X            nerrs++;
  422. X            cleanup(0);
  423. X        }
  424. X        lkp = &locks[i];
  425. X    }
  426. X
  427. X    if ((lockfile = open(lkp->lok, O_WRONLY|O_CREAT, 0644)) < 0) {
  428. X        Printf("%s : cannot open %s : %s\n",
  429. X        progname, lkp->lok, sys_errlist[errno]);
  430. X        nerrs++;
  431. X        cleanup(0);
  432. X    }
  433. X    if (flock(lockfile, LOCK_EX|LOCK_NB) < 0) {
  434. X        if (!resource) {
  435. X        Printf("%s: cannot lock %s : %s\n",
  436. X            progname, lkp->lok, sys_errlist[errno]);
  437. X        nerrs++;
  438. X        cleanup(0);
  439. X        }
  440. X        Printf("%s is in use", lkp->dev);
  441. X        if (nowait) {
  442. X        Printf(" - try again later.\n");
  443. X        nerrs++;
  444. X        cleanup(0);
  445. X        } else {
  446. X        Printf(" ... waiting");
  447. X        (void) fflush(stderr);
  448. X        if (request)
  449. X            syslog(LOGLEVEL, "will need %s, when %s is available",
  450. X            request, resource);
  451. X        requested++;
  452. X        if (flock(lockfile, LOCK_EX) < 0) {
  453. X            Printf("\n%s : cannot lock : %s\n",
  454. X            progname, sys_errlist[errno]);
  455. X            nerrs++;
  456. X            cleanup(0);
  457. X        } else
  458. X            Printf("\n");
  459. X        }
  460. X    }
  461. X    (void) write(lockfile, (char *)&mypid, sizeof(int));
  462. X    (void) write(lockfile, pw->pw_name, PW_NAMEL);
  463. X    (void) ftruncate(lockfile, sizeof(int) + PW_NAMEL);
  464. X    lkp->locked++;
  465. X    for(pdev = 0;pdev < MAXPDEV && (*subdev(lkp,pdev));pdev++){
  466. X        (void) chown( subdev(lkp,pdev),uuid,ugid );
  467. X        (void) chmod( subdev(lkp,pdev),OWNERONLY);
  468. X    }
  469. X    if (resource)
  470. X        Printf("%s is yours", lkp->dev);
  471. X    if (request) {
  472. X        if (resource)
  473. X        Printf(" - ");
  474. X        Printf("waiting for confirmation of request");
  475. X        (void) fflush(stderr);
  476. X        omask = sigblock(SIGEMT);
  477. X        (void) signal(SIGEMT, fulfil);
  478. X        needrequest++; requested = 0;
  479. X        (void) write(lockfile, request, strlen(request));
  480. X        if (resource)
  481. X        syslog(LOGLEVEL, "have %s, need %s", resource, request);
  482. X        else
  483. X        syslog(LOGLEVEL, "need %s", request);
  484. X        syslog(LOGLEVEL, "`kill -EMT %d' or `kill -TERM %d'",
  485. X        getpid(), getpid());
  486. X        do {
  487. X            sigpause(omask & ~mask(SIGEMT));
  488. X        } while (!fulfilled);
  489. X        (void) ftruncate(lockfile, sizeof(int) + PW_NAMEL);
  490. X        Printf(" - going");
  491. X        syslog(LOGLEVEL, "going");
  492. X    }
  493. X    Printf("\n");
  494. X
  495. X    if (resource) shell();
  496. X
  497. X    cleanup(0);
  498. X}
  499. X
  500. X
  501. Xint
  502. Xread_loks(lf, lks)
  503. Xchar *lf;
  504. Xregister dev_lk lks[];
  505. X{
  506. X        register FILE *lfp;
  507. X        register dev_lk *dp;
  508. X        register int i;
  509. X        int n;
  510. X        char line[BUFSIZ];
  511. X
  512. X        lfp = fopen(lf, "r");
  513. X        if(lfp == NULL)
  514. X                return -1;      /*error*/
  515. X
  516. X        /*now read in the entries*/
  517. X        for(dp = lks,i=0; i < NLOCKS ;dp++, i++){
  518. X                if( fgets(line,sizeof(line),lfp) == NULL)       /* if EOF*/
  519. X                        break;
  520. X                                /*read at most 2 + MAXPDEV entries from line*/
  521. X                n = sscanf(line,"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  522. X                dp->lok, dp->dev,
  523. X                                subdev(dp,0),subdev(dp,1),
  524. X                                subdev(dp,2),subdev(dp,3),
  525. X                                subdev(dp,4),subdev(dp,5),
  526. X                                subdev(dp,6),subdev(dp,7),
  527. X                                subdev(dp,8),subdev(dp,9),
  528. X                                subdev(dp,10),subdev(dp,11),
  529. X                                subdev(dp,12),subdev(dp,13),
  530. X                                subdev(dp,14),subdev(dp,15));
  531. X                if(n < 3){      /*if line was bad format or blank ...*/
  532. X                        dp--;i--;                               /*try again*/
  533. X                        continue;}
  534. X                if(n < MAXPDEV + 2)
  535. X                        *subdev(dp, n - 2) = '\0';              /*no string*/
  536. X        dp->locked = 0;
  537. X                }
  538. X    (void) fclose(lfp);
  539. X        return i;       /*'i' is the # of lines read successfully*/
  540. X}
  541. X
  542. Xvoid
  543. Xprint_locks()
  544. X{
  545. X    register dev_lk *lkp;
  546. X    int nent;
  547. X    struct direct **dp, **names;
  548. X    int pids(), numsort();
  549. X
  550. X    for (lkp = &locks[0]; lkp < &locks[nlock]; lkp++) {
  551. X        print_lock(lkp->lok, lkp->dev);
  552. X    }
  553. X    if (chdir(LOCKSDIR)) {
  554. X        perror(LOCKSDIR);
  555. X        return;
  556. X    }
  557. X    if ((nent = scandir(".", &names, pids, numsort)) < 0) {
  558. X        perror("scandir");
  559. X        return;
  560. X    }
  561. X    for (dp = &names[0]; dp < &names[nent]; dp++) {
  562. X        print_lock((*dp)->d_name, (char *)NULL);
  563. X    }
  564. X}
  565. X
  566. Xprint_lock(lok, dev)
  567. X    char *lok, *dev;
  568. X{
  569. X    int i, lockfile, pid;
  570. X
  571. X    if ((lockfile = open(lok, O_RDONLY)) < 0)
  572. X        return;
  573. X    if (flock(lockfile, LOCK_SH|LOCK_NB) < 0) {
  574. X        (void) read(lockfile, (char *)&pid, sizeof(int));
  575. X        (void) read(lockfile, buf, PW_NAMEL);
  576. X        buf[PW_NAMEL] = '\0';
  577. X        if (dev)
  578. X            Printf("%s in use by ", dev);
  579. X        Printf("%u (%s)", pid, buf);
  580. X        if ((i = read(lockfile, buf, BUFSIZ)) > 0) {
  581. X            buf[i] = '\0';
  582. X            Printf(": needs %s", buf);
  583. X        }
  584. X        Printf("\n");
  585. X    }
  586. X    (void) close(lockfile);
  587. X}
  588. X
  589. Xint
  590. Xpids(dp)
  591. X    struct direct *dp;
  592. X{
  593. X    register char *p = dp->d_name;
  594. X    while (*p)
  595. X        if (!isdigit(*p++))
  596. X            return(0);
  597. X    return(1);
  598. X}
  599. X
  600. Xint
  601. Xnumsort(d1, d2)
  602. X    struct direct **d1, **d2;
  603. X{
  604. X    int p1, p2;
  605. X
  606. X    p1 = atoi((*d1)->d_name);
  607. X    p2 = atoi((*d2)->d_name);
  608. X    return p1 - p2;
  609. X}
  610. X
  611. Xstatic int child;
  612. X
  613. Xsigcont()
  614. X{
  615. X    (void) kill(child, SIGCONT);
  616. X}
  617. X
  618. Xshell()
  619. X{
  620. X    register i;
  621. X    char *myshell, *shellt;
  622. X    union wait status;
  623. X    char *getenv(), *rindex();
  624. X    int omask;
  625. X
  626. X    if (!(myshell = getenv("SHELL")))
  627. X        myshell = "/bin/sh";
  628. X    if (shellt = rindex(myshell, '/'))
  629. X        shellt++;
  630. X    else
  631. X        shellt = myshell;
  632. X
  633. X    /* ignore keyboard generated signals now - could manipulate process
  634. X     * groups I suppose, but I'm lazy
  635. X     * First block them over the fork
  636. X     */
  637. X    omask = sigblock(mask(SIGINT)|mask(SIGQUIT));
  638. X    (void) fflush(stderr);
  639. X    if ((child = vfork()) == 0) {
  640. X        /* normal keyboard signals in shell */
  641. X        (void) sigsetmask(omask);
  642. X        child = getpid();
  643. X        (void) setuid(uuid);
  644. X        (void) setgid(ugid);
  645. X        for(i = getdtablesize(); i > 3; )
  646. X            (void) close(--i);
  647. X        shellargs[0] = shellt;
  648. X        execv(myshell, shellargs);
  649. X        Printf("%s : couldn't execute %s : %s\n",
  650. X            progname, myshell, sys_errlist[errno]);
  651. X        _exit(1);
  652. X    } else if (child < 0) {
  653. X        Printf("%s : couldn't fork : %s\n",
  654. X            progname, sys_errlist[errno]);
  655. X    } else {
  656. X        /* ignore keyboard signals in parent */
  657. X        (void) signal(SIGINT, SIG_IGN);
  658. X        (void) signal(SIGQUIT, SIG_IGN);
  659. X        (void) signal(SIGCONT, sigcont);
  660. X        (void) sigsetmask(omask);
  661. X        do {
  662. X            while((i = wait3(&status,
  663. X                    WUNTRACED,
  664. X                    (struct rusage *)NULL)) > 0
  665. X                && i != child);
  666. X            if (status.w_stopval == WSTOPPED)
  667. X                (void) kill(0, (int)status.w_stopsig);
  668. X            else
  669. X                nerrs = status.w_retcode;
  670. X        } while (status.w_stopval == WSTOPPED);
  671. X    }
  672. X}
  673. X
  674. Xrestore(lkp)    /*restores ownership and protections for resources unlocked*/
  675. Xregister dev_lk *lkp;
  676. X{
  677. X        register int pdev;
  678. X
  679. X        for(pdev = 0;pdev < MAXPDEV && (*subdev(lkp,pdev));pdev++){
  680. X                (void) chown( subdev(lkp,pdev),Rootuid,Rootgid );
  681. X                (void) chmod( subdev(lkp,pdev),OWNERONLY);
  682. X        }
  683. X}
  684. X
  685. X/* VARARGS1 */
  686. XPrintf(f, a, b, c, d) char *f;
  687. X{
  688. X    if (!silent) (void) fprintf(stderr, f, a, b, c, d);
  689. X}
  690. X
  691. Xfulfil() { fulfilled = 1; }
  692. X
  693. Xcleanup(sig)
  694. X{
  695. X    register dev_lk *lkp;
  696. X
  697. X    /* wait for child to finish before we go ourselves */
  698. X    if (!nerrs || sig) Printf("\n");
  699. X    if (sig) Printf("%s\n", sys_siglist[sig]);
  700. X    if (requested) syslog(LOGLEVEL, "request withdrawn");
  701. X    if (needrequest) {
  702. X        if (sig) {
  703. X            Printf("Request denied\n");
  704. X            syslog(LOGLEVEL, "request denied");
  705. X        } else if (resource) {
  706. X            syslog(LOGLEVEL, "done with %s", resource);
  707. X        }
  708. X    }
  709. X    /* check if there's anything to wait for */
  710. X    if (!wait3((union wait *)NULL, WNOHANG, (struct rusage *)NULL))
  711. X        Printf("waiting for shell to exit\n");
  712. X    (void) fflush(stderr);
  713. X    while (wait((union wait *)NULL) > 0);
  714. X    for (lkp = &locks[0]; lkp < &locks[nlock]; lkp++)
  715. X        if (lkp->locked) {
  716. X        restore(lkp);
  717. X        Printf("%s released.\n", lkp->dev);
  718. X        }
  719. X    if (!resource)
  720. X        (void) unlink(nolok.lok);
  721. X        exit(sig ? -1 : nerrs);
  722. X}
  723. /
  724. echo 'Part 01 of pack.out complete.'
  725. exit
  726. ----
  727. UUCP:   ...!mcvax!ukc!warwick!cudcv    PHONE:  +44 203 523037
  728. JANET:  cudcv@uk.ac.warwick.daisy       ARPA:   cudcv@daisy.warwick.ac.uk
  729. Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England
  730.