From: maupb@csv.warwick.ac.uk (Mr J L Saunders)
Newsgroups: comp.unix.misc,comp.unix.questions,comp.sys.sgi,comp.graphics
Subject: Re: Interactive vs Background users
Date: 16 Nov 92 19:18:54 GMT
Organization: Computing Services, University of Warwick, UK
NNTP-Posting-Host: violet.csv.warwick.ac.uk

In article <BxsApH.4FH@news.cso.uiuc.edu> ercolessi@uimrl3.mrl.uiuc.edu (furio ercolessi) writes:

>SGI users are particularly lucky to have the 'npri' command which
>allows to define the time slice, which is the critical parameter.   

I noticed someone earlier in this thread suggested npri - unfortunately
not everyone has it.

Here's a pseudo(ish)code version of a process that will turn it's child on and
off depending on who's logged on (a lot of it's ripped out of one of my own
programs - so flames about readability, incompatible pointer types and the
like to /dev/null) ...

<daemonname> whatever command you want to execute

[More comments at the end]

---cut here---

#include <stdio.h>
#include <utmp.h>
#include <rpcsvc/rusers.h>
#include <signal.h>

char user[8];
int child_process_number;

main(int argc, char **argv) {

getenv("USER",user);


if (!(child_process_number=fork()) {
  execvp(*argv[1],argv[1]);
  fprintf(stderr,"demon: Cannot exec process\n"); /* Only gets here is exec
							fails */
  kill(getppid(),1); /* Kill the parent process */
}

signal(SIGHUP,SIG_IGN);
signal(SIGCHLD,childgone);

while (1) {
  if (!consolefree()) {
    kill(child_process_number,SIGSTOP); /* Stop the child */
    while (!consolefree()) sleep(30); /* Check console every 30 seconds */
  }
  kill(child_process_number,SIGCONT); /* Cont the child */
  sleep(30); /* Wait another 30 seconds */
} /* while */

/* Alternatively, if you're concerned about anyone using a tty it's simpler..

int numer_of_users;
while (1) {
if (rnusers("localhost")>0) { /* 1 or more users */
  stop the child etc...
}

*/

/* Or we may just want to stop 9 to 5, then we'd need to have
#include <time.h>
time_t TIME;
int hour;

while(1) {
time(&TIME);
hour=localtime(&TIME)->tm_hour;
if ((hour>=9)|&&|(hour<17)) {
  kill(child_process_number,SIGSTOP);
  while ((hour>=9)&&(hour<17)) {
    sleep(60);     /* Check every 60 seconds - gosh we're keen */
    time(&TIME);
    hour=localtime(&TIME)->tm_hour;
  }
sleep(60);
}
*/


} /* main */


int consolefree() {

  struct utmpidlearr users;
    bzero((char *)&users,sizeof(users)); /* Zero it out otherwise rusers()
						might complain! */
      rusers("localhost", &users); /* Shove utmp information into users */

        if (strcmp(users.uia_arr[0]->ui_utmp.ut_line,"console")) {
          fprintf(stderr,"demon: Console clear on %s. Continuing...\n",host);
          return 1;
        } /* Noone on console */

        if (!strcmp(users.uia_arr[0]->ui_utmp.ut_name,user)) 
	  fprintf(stderr,"demon: Console clear on %s. Continuing...\n",host);
          return 1;
	} /* User is on console */

    fprintf(stderr,"demon: Someone else is on %s console! waiting...\n",host);

    return 0; /* Someone else on console */
}

childgone() {
fprintf(stderr,"demon: Your program has exited\n");
exit(0);
}

---cut here---

Of course, there's loads of nested comments, which you need to strip and
you'll need to remove whatever code you don't need. I'm assuming that console
will be the first entry in utmp. If this isn't so on your system then you can
easily check each member of users.uia_arr[]

I'm not sure about whether my signal(SIGCHLD,childgone) will do as it's
supposed - if it doesn't I'd be glad if someone would email me the correct
thing (does a child signal the parent when it dies, for instance?).


Hope this does the trick!

Jason
-- 
                       Jason L Saunders [ RouE ]      
                     email: maupb@csv.warwick.ac.uk
snail: Warwick Business School, University of Warwick, Coventry CV4 7AL, UK