#include "remind.h" bye() { unlink(rmdproc); unlink(rmdlock); unlink(reminders); exit(1); } cleanup() { unlink (reminders); link (rmdtemp, reminders); unlink (rmdtemp); unlink(rmdlock); } /* Forking is complicated by the fact that a process * that exits becomes a "ZOMBIE". It does not leave * UNIX until it is waited for by its parent. Thus, * when remind spawns a process, it actually spawns * a child and a grandchild, so that the grandchild, * which actually does the work, will be adopted by * the init process when the child exits. */ spawn() { register int k, l; int pstat; while ((k = fork()) == -1) sleep(10); if (k) { wait(&pstat); /* Wait for k below to exit */ return (1); /* Returns non-zero in parent */ } else { while ((l = fork()) == -1) sleep(10); if (l) exit(0); /* After creating l, exit. */ return(0); } } /* Use lock file as semaphore. Can't run as superuser, so forks. */ lock() { register int i; int x; if (fork()) wait(&x); else { setuid(3); /* 3 is bin, NOT root */ while ((i = creat(rmdlock,0444)) == -1) sleep(5); close(i); exit(0); } } puserid(p) char *p; { if (m.nrcvrs < MAXRCVRS) strxfer(p,rcvrlist[m.nrcvrs++],8); else fprintf (stderr,"Receiver list too long. '%.8s truncated\n", p); } puidfil(p) char *p; { char username[8]; register FILE *pf; register int c, i; if ((pf = fopen(p,"r")) == NULL) { fprintf (stderr,nofile,p); exit(1); } do { while ((c=getc(pf)) == '\n' || c==' ' || c=='\0' || c=='\t') ; for (i = 0; i<8 && (c!='\n' && c!=' ' && c!='\t' && c!= -1 && c!='\0') ; c = getc(pf)) username[i++] = c; if (i < 8) username[i] = '\0'; if (i > 0) puserid(username); } while (c != EOF); fclose(pf); } pflags(pp) char *pp; { register char *p; register int i; p = pp; switch (*p++) { case 'p': m.bits |= PRIORITY; return; case 'x': case 'e': *exdir = getuid(); /* Real user id */ getwdir(); /* Working directory */ return; case 'm': case 'r': for (i = 0; i0 && exdir[i+1] == '\n') { m.dirsize = i+2; /* uid, /, (name, \n) */ close (fd[0]); close (fd[1]); return; } } else { close (1); dup (fd[1]); execl("/bin/pwd","remindpwd",0); } error("Bad working directory"); } strxfer(pp,qq,nn) /* Transfer string pp to qq, null padding to nn chars */ char *pp, *qq; int nn; { register char *p, *q; register int n; p = pp; q = qq; for (n = nn; n && *p && *p!=' '; n--) *q++ = *p++; while (n--) *q++ = '\0'; } nametty(flag, tt, nm) int flag; /* 1 to get name, 0 to get tty(s). * If name or tty not found in login file (/etc/utmp), * returns 0. If flag is 1, returns name in nm and 1 as * value. If flag is 0, returns number of ttys at which * user specified in nm is logged in, filling in the * array tt with the tty names. */ char *tt[], *nm; { register FILE *ut; register int i; register char *ttp; struct utmp logins; int tcount = 0; ttp = (char *)tt++; if ((ut = fopen(loginfile,"r")) == NULL) { fprintf(stderr,"remind: %s unreadable\n",loginfile); return(0); } while (fread((char *)&logins,sizeof logins,1,ut) == 1) { if (flag) { if (strcmp(logins.ut_line,ttp)==0) { strxfer(logins.ut_name,nm,8); fclose(ut); return(1); } } else { for (i = 0; i<8 && logins.ut_name[i] == nm[i]; i++ ) ; if (i >= 8 || (nm[i]=='\0' && logins.ut_name[i]==' ')) { strncpy(ttp,logins.ut_line,8); tcount++; ttp = tt[tcount]; } } } fclose(ut); return(tcount); } checkusers() /* Verify that all receivers exist (are in password file) */ { register int i,c; register int found; char name[8]; char foundflg[MAXRCVRS]; FILE *pf; if((pf=fopen(usrfile,"r"))==NULL) { fprintf (stderr,nofile, usrfile); exit(1); } for (i = found = m.nrcvrs; i--; ) foundflg[i] = 0; do { /* Get a name */ for (i = 0; (c=getc(pf)) != ':' && i < 8 && c != -1 ; ) name[i++] = c; if (c == ':') { while (i<8) name[i++] = '\0'; for (i=0; i