1: #include "remind.h" 2: 3: bye() 4: { unlink(rmdproc); 5: unlink(rmdlock); 6: unlink(reminders); 7: exit(1); 8: } 9: 10: cleanup() 11: { 12: unlink (reminders); 13: link (rmdtemp, reminders); 14: unlink (rmdtemp); 15: unlink(rmdlock); 16: } 17: 18: /* Forking is complicated by the fact that a process 19: * that exits becomes a "ZOMBIE". It does not leave 20: * UNIX until it is waited for by its parent. Thus, 21: * when remind spawns a process, it actually spawns 22: * a child and a grandchild, so that the grandchild, 23: * which actually does the work, will be adopted by 24: * the init process when the child exits. 25: */ 26: spawn() 27: { register int k, l; 28: int pstat; 29: 30: while ((k = fork()) == -1) sleep(10); 31: if (k) 32: { wait(&pstat); /* Wait for k below to exit */ 33: return (1); /* Returns non-zero in parent */ 34: } 35: else 36: { while ((l = fork()) == -1) sleep(10); 37: if (l) exit(0); /* After creating l, exit. */ 38: return(0); 39: } 40: } 41: 42: /* Use lock file as semaphore. Can't run as superuser, so forks. */ 43: lock() 44: { register int i; 45: int x; 46: if (fork()) 47: wait(&x); 48: else 49: { setuid(3); /* 3 is bin, NOT root */ 50: while ((i = creat(rmdlock,0444)) == -1) 51: sleep(5); 52: close(i); 53: exit(0); 54: } 55: } 56: 57: puserid(p) 58: char *p; 59: { if (m.nrcvrs < MAXRCVRS) 60: strxfer(p,rcvrlist[m.nrcvrs++],8); 61: else 62: fprintf (stderr,"Receiver list too long. '%.8s truncated\n", p); 63: } 64: 65: puidfil(p) 66: char *p; 67: { char username[8]; 68: register FILE *pf; 69: register int c, i; 70: 71: if ((pf = fopen(p,"r")) == NULL) 72: { 73: fprintf (stderr,nofile,p); 74: exit(1); 75: } 76: do 77: { while ((c=getc(pf)) == '\n' || c==' ' || c=='\0' || c=='\t') ; 78: for (i = 0; 79: i<8 && (c!='\n' && c!=' ' && c!='\t' 80: && c!= -1 && c!='\0') ; 81: c = getc(pf)) 82: username[i++] = c; 83: if (i < 8) username[i] = '\0'; 84: if (i > 0) puserid(username); 85: } while (c != EOF); 86: fclose(pf); 87: } 88: 89: pflags(pp) 90: char *pp; 91: { register char *p; 92: register int i; 93: p = pp; 94: switch (*p++) 95: { 96: case 'p': 97: m.bits |= PRIORITY; 98: return; 99: case 'x': 100: case 'e': 101: *exdir = getuid(); /* Real user id */ 102: getwdir(); /* Working directory */ 103: return; 104: case 'm': 105: case 'r': 106: for (i = 0; i<MAXMSG && (msg[i++] = *p++); ) ; 107: m.msgbytes = --i; 108: return; 109: case 'f': 110: puidfile(p); /* filename of receivers */ 111: return; 112: case 'l': /* letter only */ 113: lflag = 1; 114: return; 115: default: 116: printf (invalid, p-2); 117: } 118: } 119: 120: getmsg() 121: { register int i,c; 122: register char *cp; 123: FILE *input; 124: 125: if((input=fdopen(0,"r"))==NULL) 126: { 127: fprintf(stderr,"Cannot read message\n"); 128: bye(); 129: } 130: cp = msg; 131: for (i = 0; i++<MAXMSG && ((c = getc(input)) != -1); ) 132: *cp++ = c; 133: if (i==MAXMSG) fprintf(stderr,"...Message truncated\n"); 134: m.msgbytes = --i; 135: } 136: 137: /* Get name of working directory to exdir[1]..., its length+1 to m.dirsize */ 138: getwdir() 139: { register int i; 140: int fd[2], x; 141: 142: pipe(fd); 143: while ((i = fork()) == -1) sleep(5); 144: if (i) 145: { wait(&x); /* Any address */ 146: exdir[1] = '/'; 147: i = read (fd[0], &exdir[2], DIRSIZE-2); 148: if (i>0 && exdir[i+1] == '\n') 149: { m.dirsize = i+2; /* uid, /, (name, \n) */ 150: close (fd[0]); 151: close (fd[1]); 152: return; 153: } 154: } 155: else 156: { close (1); 157: dup (fd[1]); 158: execl("/bin/pwd","remindpwd",0); 159: } 160: error("Bad working directory"); 161: } 162: 163: strxfer(pp,qq,nn) 164: /* Transfer string pp to qq, null padding to nn chars */ 165: char *pp, *qq; 166: int nn; 167: { register char *p, *q; 168: register int n; 169: p = pp; 170: q = qq; 171: for (n = nn; n && *p && *p!=' '; n--) 172: *q++ = *p++; 173: while (n--) 174: *q++ = '\0'; 175: } 176: 177: nametty(flag, tt, nm) 178: int flag; /* 1 to get name, 0 to get tty(s). 179: * If name or tty not found in login file (/etc/utmp), 180: * returns 0. If flag is 1, returns name in nm and 1 as 181: * value. If flag is 0, returns number of ttys at which 182: * user specified in nm is logged in, filling in the 183: * array tt with the tty names. 184: */ 185: char *tt[], *nm; 186: { 187: register FILE *ut; 188: register int i; 189: register char *ttp; 190: struct utmp logins; 191: int tcount = 0; 192: 193: ttp = (char *)tt++; 194: if ((ut = fopen(loginfile,"r")) == NULL) 195: { 196: fprintf(stderr,"remind: %s unreadable\n",loginfile); 197: return(0); 198: } 199: while (fread((char *)&logins,sizeof logins,1,ut) == 1) 200: { if (flag) 201: { 202: if (strcmp(logins.ut_line,ttp)==0) 203: { strxfer(logins.ut_name,nm,8); 204: fclose(ut); 205: return(1); 206: } 207: } 208: else 209: { for (i = 0; i<8 && 210: logins.ut_name[i] == nm[i]; 211: i++ ) ; 212: if (i >= 8 || (nm[i]=='\0' && logins.ut_name[i]==' ')) 213: { 214: strncpy(ttp,logins.ut_line,8); 215: tcount++; 216: ttp = tt[tcount]; 217: } 218: } 219: } 220: fclose(ut); 221: return(tcount); 222: } 223: 224: checkusers() 225: /* Verify that all receivers exist (are in password file) */ 226: { register int i,c; 227: register int found; 228: char name[8]; 229: char foundflg[MAXRCVRS]; 230: FILE *pf; 231: 232: if((pf=fopen(usrfile,"r"))==NULL) 233: { fprintf (stderr,nofile, usrfile); 234: exit(1); 235: } 236: for (i = found = m.nrcvrs; i--; ) foundflg[i] = 0; 237: 238: do 239: { /* Get a name */ 240: for (i = 0; (c=getc(pf)) != ':' && i < 8 && c != -1 ; ) 241: name[i++] = c; 242: if (c == ':') 243: { while (i<8) name[i++] = '\0'; 244: for (i=0; i<m.nrcvrs; i++) 245: { if (foundflg[i]==0 && equal(name,rcvrlist[i])) 246: if (--found <= 0) 247: { fclose(pf); 248: return(0); 249: } 250: else foundflg[i] = 1; 251: } 252: while ((c=getc(pf)) != '\n' && c != -1) ; 253: } 254: } while (c != -1); 255: for (i = 0; i<m.nrcvrs; i++) 256: if (foundflg[i] == 0) 257: fprintf(stderr,"'%.8s' is not a UNIX user\n",rcvrlist[i]); 258: 259: fclose(pf); 260: return(1); 261: } 262: 263: equal(pp,qq) 264: char *pp, *qq; 265: { register char *p, *q; 266: register int i; 267: p = pp; 268: q = qq; 269: for (i = 8; i--; ) 270: { if (*p != *q++) return(0); 271: if (*p++ == '\0') break; 272: } 273: return(1); 274: } 275: 276: error(s) 277: char *s; 278: { 279: fprintf (stderr,"remind: %s\n",s); 280: exit(1); 281: }