home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume15 / net-notify < prev    next >
Text File  |  1988-06-01  |  23KB  |  950 lines

  1. Subject:  v15i029:  Network message system, sort of like wall
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4.  
  5. Submitted-by: Paul Davison <cs.qmc.ac.uk!pd>
  6. Posting-number: Volume 15, Issue 29
  7. Archive-name: net-notify
  8.  
  9. Here's a message sending program for distributed networks that I thought
  10. you might be interested in. Full documentation and a Makefile are
  11. included. I am the author, and I declare it to be in the public domain.
  12.  
  13. In our lab, it soon became obvious to me that some quick and efficient way
  14. of sending short messages to users of the network was needed, without the
  15. sender having to be aware of the physical location of the recipient.
  16. Therefore I wrote a network-wide message system, which is presented here.
  17. It is a one-shot mechanism, similar to "wall", expect that it can be sent
  18. to specific users or specific machines.
  19.  
  20. The server is invoked from inetd, so appropriate entries have to be
  21. inserted in either "inetd.conf" or "servers", depending on the machine,
  22. and also in "services", of course. I have found this software extremely
  23. useful and hope that others find it so as well.
  24.  
  25. The program has been tested under Sequent's DYNIX, 4.2BSD, Sun 3.4, and
  26. Whitechapel 42nix. It won't work with System V.
  27.  
  28.     Cheers,
  29.         Paul Davison.
  30. --
  31. Paul Davison
  32.  
  33. UUCP:      pd@qmc-cs.uucp   or       ...seismo!mcvax!ukc!qmc-cs!pd
  34. Internet:  pd@cs.qmc.ac.uk              Post:   Dept of Computer Science
  35. JANET:     pd@uk.ac.qmc.cs                      Queen Mary College
  36. Easylink:  19019285                             University of London
  37. Telex:     893750 QMCUOL G                      Mile End Road
  38. Fax:       +44 1 981 7517                       London E1 4NS
  39. Voice:     +44 1 980 4811  x3950                England
  40.  
  41. #         This is a shar archive.
  42. #         Remove everything above and including the cut line.
  43. #         Then run the rest of the file through sh.
  44. #--------cut--------cut--------cut--------cut--------cut--------
  45. #! /bin/sh
  46. #  shar:  Shell Archiver
  47. #         Run the following with /bin/sh to create:
  48. #             README
  49. #             inform.1
  50. #             notifyd.8
  51. #             Makefile
  52. #             in.notifyd.c
  53. #             inform.c
  54. #             init_socket_out.c
  55. #             wcwin.notifyd.c
  56. #             notify.h
  57. #             services
  58. #             servers
  59. #             inetd.conf
  60. echo shar: extracting "README" '('996 chars')'
  61. if test -f README
  62. then
  63.     echo shar: will not overwrite existing file "README"
  64. else
  65. cat << \SHAR_EOF > README
  66. Here at QMC we run a large network of machines, with a VAX, a Sequent
  67. Balance, and some Suns serving files via NFS. The undergradute lab
  68. consists of 43 Whitechapel MG1's, all providing the same "virtual"
  69. system to the users. It became obvious to me that some quick and
  70. efficient way of sending short messages to users of the network was
  71. needed, without the sender having to be aware of the physical location of the
  72. recipient. Therefore I wrote a network-wide message system, which is
  73. presented here. It is a one-shot mechanism, similar to "wall", expect
  74. that it can be sent to specific users or specific machines.
  75.  
  76. The server is invoked from inetd, so appropriate entries have to be
  77. inserted in either "inetd.conf" or "servers", depending on the machine, and
  78. also in "services", of course. I have found this software extremely
  79. useful and hope that others find it so as well.
  80.  
  81. The program has been tested under Sequent's DYNIX, 4.2BSD, Sun 3.4, and
  82. Whitechapel 42nix. It won't work with System V.
  83. SHAR_EOF
  84. if test 996 -ne `wc -c < README`
  85. then
  86.     echo shar: error transmitting "README" '('should be 996 chars')'
  87. else
  88.     echo README
  89. fi
  90. fi
  91. echo shar: extracting "inform.1" '('1909 chars')'
  92. if test -f inform.1
  93. then
  94.     echo shar: will not overwrite existing file "inform.1"
  95. else
  96. cat << \SHAR_EOF > inform.1
  97. .TH INFORM 1 LOCAL "18th March 1988"
  98. .SH NAME
  99. inform \- network message sender
  100. .SH SYNOPSIS
  101. .B inform
  102. [
  103. .B -m
  104. ][
  105. .B -s
  106. ][
  107. .B -w
  108. ][
  109. .B -v
  110. ]
  111. .I "users or machines..."
  112. .SH DESCRIPTION
  113. .I Inform
  114. is used to send one-off messages either to a list of people who are
  115. logged in somewhere on the network, or to a list of machines on the net.
  116. The standard action is to send to users. The
  117. .B -m
  118. flag causes 
  119. .I inform
  120. to expect machine names instead.
  121. .PP
  122. The message is typed in directly, and ends either with a CTRL-D or a
  123. line containing a single ".".
  124. .I Inform
  125. then forks itself and sits in the background sending the messages to all
  126. appropriate machines. The information in the 
  127. .I rwho
  128. directory is used to ascertain who is logged on where.
  129. The
  130. .B -v
  131. flag sets verbose mode, so that the program doesn't fork and tells you
  132. which machines are being sent to. The
  133. .B -w
  134. flag sets visual mode for the recipient. Currently this only works on
  135. Whitechapels, but versions for other machines could be written. The
  136. Whitechapel visual mode bounces an icon around the screen, which then
  137. opens up into a window containing the message.
  138. .PP
  139. Finally, the
  140. .B -s
  141. flag prevents the normal "Message from pd@sequent ..." style of message
  142. header from being printed. This is useful for messages generated
  143. automatically by programs; it is used at QMC for mail notification and
  144. network status information.
  145. .SH BUGS
  146. The 
  147. .I rwho
  148. data structures set a limit of 41 users on each machine in the network.
  149. If there are more than this on any machine then only the first 41 are
  150. written into the database. This means that if you are the 42nd or higher
  151. user, you will not receive the messages. This is extremely frustrating!
  152. .SH FILES
  153. /usr/spool/rwho for information on who is logged in, on which machine.
  154. .SH SEE ALSO
  155. notifyd(8)
  156. .SH AUTHOR
  157. Paul Davison at Queen Mary College, University of London. I would love
  158. to hear about any bugs or improvements.
  159. SHAR_EOF
  160. if test 1909 -ne `wc -c < inform.1`
  161. then
  162.     echo shar: error transmitting "inform.1" '('should be 1909 chars')'
  163. else
  164.     echo inform.1
  165. fi
  166. fi
  167. echo shar: extracting "notifyd.8" '('1425 chars')'
  168. if test -f notifyd.8
  169. then
  170.     echo shar: will not overwrite existing file "notifyd.8"
  171. else
  172. cat << \SHAR_EOF > notifyd.8
  173. .TH NOTIFYD 8 LOCAL "18th March 1988"
  174. .SH NAME
  175. in.notifyd 
  176. .SH SYNOPSIS
  177. in.notifyd is run from 
  178. .I inetd.
  179. .SH DESCRIPTION
  180. The
  181. .I notifyd
  182. daemon runs on a machine at the receiving end of a message generated by 
  183. .I inform.
  184. Depending on the type of message, it either sends it to all logged in
  185. users, or to a particular one. The messages are written irrespective of
  186. the user's tty permissions. Therefore it is sensible to restrict
  187. execution of
  188. .I inform
  189. to an appropriate group such as
  190. .B operator
  191. or
  192. .B wheel,
  193. unless all your users are very responsible.
  194. .PP
  195. Another version of 
  196. .I notifyd
  197. for Whitechapel MG1's can be used to provide a visual message if the 
  198. .I -w
  199. option is used in
  200. .I inform.
  201. This expects to find an icon in /usr/lib/icons entitled "not.icn", which
  202. is the default. If the icon has a text box, this will be filled in with
  203. the sender's name. If an icon exists in /usr/lib/icons with the name of
  204. the sender appended with "icn" (such as "pd.icn") then this icon is used
  205. instead. This is used for personal icons, and is used at QMC for mail
  206. notification purposes.
  207. .PP
  208. The files
  209. .I /etc/servers
  210. or 
  211. .I /etc/inetd.conf,
  212. and
  213. .I /etc/servcices
  214. must be updated to make this software work. Example entries are included
  215. in the distribution.
  216. .SH BUGS
  217. None that I can remember!
  218. .SH SEE ALSO
  219. inform(1)
  220. .SH AUTHOR
  221. Paul Davison at Queen Mary College, University of London. I would love
  222. to hear about any bugs or improvements.
  223. SHAR_EOF
  224. if test 1425 -ne `wc -c < notifyd.8`
  225. then
  226.     echo shar: error transmitting "notifyd.8" '('should be 1425 chars')'
  227. else
  228.     echo notifyd.8
  229. fi
  230. fi
  231. echo shar: extracting "Makefile" '('411 chars')'
  232. if test -f Makefile
  233. then
  234.     echo shar: will not overwrite existing file "Makefile"
  235. else
  236. cat << \SHAR_EOF > Makefile
  237. all: inform in.notifyd
  238.  
  239. in.notifyd: notify.h in.notifyd.o
  240.     cc in.notifyd.o -o in.notifyd
  241.  
  242. wcwin.notifyd: wcwin.notifyd.c
  243.     ccg wcwin.notifyd.c -o wcwin.notifyd
  244.  
  245. inform: notify.h inform.o init_socket_out.o
  246.     cc inform.o init_socket_out.o -o inform
  247.  
  248. install:
  249.     strip in.notifyd
  250.     cp in.notifyd /usr/etc
  251.     strip inform
  252.     cp inform /usr/local/bin
  253.     cp inform.1 /usr/man/man1
  254.     cp notifyd.8 /usr/man/man8
  255.  
  256. .c.o:
  257.     cc -c $*.c
  258. SHAR_EOF
  259. if test 411 -ne `wc -c < Makefile`
  260. then
  261.     echo shar: error transmitting "Makefile" '('should be 411 chars')'
  262. else
  263.     echo Makefile
  264. fi
  265. fi
  266. echo shar: extracting "in.notifyd.c" '('1444 chars')'
  267. if test -f in.notifyd.c
  268. then
  269.     echo shar: will not overwrite existing file "in.notifyd.c"
  270. else
  271. cat << \SHAR_EOF > in.notifyd.c
  272. #include "notify.h"
  273. #include <utmp.h>
  274. #include <sys/file.h>
  275.  
  276. #define UTMP "/etc/utmp"
  277.  
  278. int my_socket = 0;    /* inetd gives us fd 0 */
  279. notify data;
  280. int debug = 0;        /* set to 1 for debug output on fp 'out' */
  281. char *progname;
  282. FILE *out;
  283.  
  284. main(argc,argv)
  285. int argc;
  286. char *argv[];
  287. {
  288.     int c,fromlen;
  289.     struct sockaddr_in from;
  290.     out = stderr;    /* or fopen ("/dev/console","w"); */
  291.     progname = argv[0];
  292.     c = recvfrom(my_socket, &data, sizeof(notify), 0, 
  293.         (struct sockaddr *) &from, &fromlen);
  294.     if(debug)
  295.         fprintf(out,"RECVD to %s data %s ID %s type %d size %d\n",
  296.             data.to, data.mess, data.id, data.type, c);
  297.     if (c != sizeof(notify)) exit(0);
  298.     if(debug)
  299.         fprintf(out,"Size OK\n");
  300.     if(!strcmp(data.id,"notify")) show(data);
  301.     if(debug)
  302.         fprintf(out,"Showed data OK\n");
  303.     exit (0);
  304. }
  305.  
  306. show(data)    /* this version ignores the windowing options */
  307. notify data;
  308. {
  309.     int fd;
  310.     FILE *fp;
  311.     struct utmp entry;
  312.     char tty[20];
  313.  
  314.     fd = open(UTMP,O_RDONLY,NULL);
  315.     if (fd < 0) return;
  316.     while (read(fd, &entry, sizeof(struct utmp)) > 0) {
  317.         if ((data.type == MACHINE_WIDE) ||
  318.            (data.type == MACH_AND_WIN)||
  319.            (!strncmp(data.to,entry.ut_name,8))) {
  320.             strcpy(tty,"/dev/");
  321.             if (strncmp("tty",entry.ut_line,3)) continue;
  322.             if (*entry.ut_name == '\0') continue;
  323.             strncat(tty,entry.ut_line,8);
  324.             fp = fopen(tty,"w");
  325.             if (debug) fprintf(out,"Trying %s\n",tty);
  326.             if (fp == NULL) continue;
  327.             fprintf(fp,"%s",data.mess);
  328.             fclose(fp);
  329.         }
  330.     }
  331.     close(fd);
  332. }
  333. SHAR_EOF
  334. if test 1444 -ne `wc -c < in.notifyd.c`
  335. then
  336.     echo shar: error transmitting "in.notifyd.c" '('should be 1444 chars')'
  337. else
  338.     echo in.notifyd.c
  339. fi
  340. fi
  341. echo shar: extracting "inform.c" '('3859 chars')'
  342. if test -f inform.c
  343. then
  344.     echo shar: will not overwrite existing file "inform.c"
  345. else
  346. cat << \SHAR_EOF > inform.c
  347. #include "notify.h"
  348. #include <pwd.h>
  349. #include <protocols/rwhod.h>
  350. #include <sys/dir.h>
  351. #include <sys/time.h>
  352.  
  353. notify data;
  354. int debug = 0, verbose=0, windowed=0;
  355. char *progname;
  356. int listlen;
  357. char hostlist[500][32];
  358. int silent=0, broadcast=0;
  359.  
  360. struct whod wd;
  361.  
  362. #define WHDRSIZE (sizeof(wd) - sizeof(wd.wd_we))
  363. #define RWHODIR  "/usr/spool/rwho"
  364.  
  365. extern int my_socket;
  366. extern struct sockaddr_in all;
  367.  
  368. main(argc,argv)
  369. int argc;
  370. char *argv[];
  371. {
  372.     int i,j;
  373.     int c,pid;
  374.     char *p = data.mess;
  375.     char host[32];
  376.     struct passwd *entry = getpwuid(getuid());
  377.     struct tm *loctime;
  378.     struct timeval tp;
  379.  
  380.     progname = argv[0];
  381.     if (argc <2) {
  382.         fprintf(stderr, "Usage: %s [-m][-s][-w] user/machine [user ..]\n",argv[0]);
  383.         exit(1);
  384.     }
  385.     strncpy(data.from,entry->pw_name,8);
  386.     for (i=1;i<argc;i++) {
  387.         if(!strcmp(argv[i],"-s")) 
  388.             silent++;
  389.         else if (!strcmp(argv[i],"-m"))
  390.             broadcast++;
  391.         else if (!strcmp(argv[i],"-v"))
  392.             verbose++;
  393.         else if (!strcmp(argv[i],"-w"))
  394.             windowed++;
  395.         else if (!strncmp(argv[i],"-o",2))
  396.             strncpy(data.from,&argv[i][2],8);
  397.     }
  398.     if (*data.from == '\0') strcpy(data.from, "anon");
  399.     
  400.     if(broadcast && !windowed) data.type = MACHINE_WIDE;
  401.     else if(windowed && !broadcast) data.type = WINDOWED;
  402.     else if(windowed && broadcast) data.type = MACH_AND_WIN;
  403.     else data.type = PERSON_ONLY;
  404.  
  405.     gettimeofday(&tp, (struct timezone *)NULL);
  406.     loctime = localtime(&tp);
  407.         
  408.     if(!silent) {
  409.         gethostname(host,32);
  410.         sprintf(data.mess,"\n\rMessage from %.8s@%s [%02d:%02d]... \n\r\n\r%c",
  411.             data.from,host,loctime->tm_hour,loctime->tm_min,7);
  412.         p = &data.mess[strlen(data.mess)];
  413.     }
  414.     while((c=getc(stdin)) != EOF) {
  415.         *p++ = c;
  416.         if (c == '\n') *p++ = '\r';
  417.         if((p - data.mess) >= MESS_SIZE) {
  418.             fprintf(stderr,"%s: message too long\n",argv[0]);
  419.             exit(1);
  420.         }
  421.         if (!strncmp((p-5),"\n\r.\n\r",5)) { 
  422.             fclose (stdin);
  423.             p -= 3;
  424.         }
  425.     }
  426.     *p = NULL;
  427.     if (debug) printf("Data is %s\n",data.mess);
  428.  
  429.     if(!verbose) {    
  430.         while ((pid=fork()) < 0) sleep(5);
  431.         if (pid) exit(0);        /* fork child to save delays */
  432.     }
  433.  
  434.     strcpy(data.id,"notify");
  435.  
  436.     if (verbose && broadcast) 
  437.         printf("Broadcasting to");
  438.     for(i=1;i<argc;i++) {
  439.         listlen=0;
  440.         if (*argv[i]=='-') continue;
  441.         if (!broadcast) {
  442.             makehostlist(argv[i]);
  443.             strncpy(data.to, argv[i], 8);
  444.             if (verbose)
  445.                 printf("For %s writing to machines",argv[i]);
  446.             for(j=0;j<listlen;j++) {
  447.                 init_socket(0,hostlist[j]);
  448.                 if (verbose) {
  449.                     printf(" %s",hostlist[j]);
  450.                     fflush(stdout);
  451.                 }
  452.                 sendto(my_socket, &data, sizeof(notify),0,
  453.                     &all, sizeof(all));
  454.             }
  455.         } else {
  456.             if (verbose) {
  457.                 printf(" %s",argv[i]);
  458.                 fflush(stdout);
  459.             }
  460.             init_socket(0,argv[i]);
  461.             strcpy(data.to,"nobody");
  462.             sendto(my_socket, &data, sizeof(notify),0,
  463.                 &all, sizeof(all));
  464.         }
  465.         if (!broadcast && verbose) printf(".\n");
  466.         if (debug)
  467.             printf("TO %s ID %s MESS %s\n",data.to, data.id,
  468.                 data.mess);
  469.         close(my_socket);
  470.     }
  471.     if (verbose && broadcast) printf(".\n");
  472. }
  473.  
  474. makehostlist(name)
  475. char *name;
  476. {
  477.     int i,cc,f,n;
  478.     DIR *rwhodir;
  479.     struct direct *dp;
  480.     register struct whod *w = &wd;
  481.     register struct whoent *we;
  482.  
  483.     if(chdir(RWHODIR) <0) {
  484.         perror(RWHODIR);
  485.         exit(1);
  486.     }
  487.     rwhodir = opendir(".");
  488.     if (rwhodir == NULL) {
  489.         perror(RWHODIR);
  490.         exit(1);
  491.     }
  492.  
  493.     listlen=0;
  494.     while (dp=readdir(rwhodir)) {
  495.         if(dp->d_ino == 0)
  496.             continue;
  497.         if(strncmp(dp->d_name,"whod.",5))
  498.             continue;
  499.         f = open(dp->d_name,0);
  500.         if (f < 0) continue;
  501.         cc = read(f,(char *)&wd,sizeof(struct whod));
  502.         if (cc < WHDRSIZE) {
  503.             close(f);
  504.             continue;
  505.         }
  506.         we = w->wd_we;
  507.         cc -= WHDRSIZE;
  508.         for(n=cc/sizeof(struct whoent); n>0; n--) {
  509.             if(!strncmp(we->we_utmp.out_name,name,8)) {
  510.                 addtolist(w->wd_hostname);
  511.                 break;
  512.             }
  513.             we++;
  514.         }
  515.         close(f);
  516.     }
  517.     closedir(rwhodir);
  518. }
  519.  
  520. addtolist(host)
  521. char *host;
  522. {
  523.     register int i;
  524.     for(i=0;i<listlen;i++)
  525.         if(!strcmp(host,hostlist[i])) return;
  526.     strcpy(hostlist[listlen++],host);
  527. }
  528. SHAR_EOF
  529. if test 3859 -ne `wc -c < inform.c`
  530. then
  531.     echo shar: error transmitting "inform.c" '('should be 3859 chars')'
  532. else
  533.     echo inform.c
  534. fi
  535. fi
  536. echo shar: extracting "init_socket_out.c" '('1842 chars')'
  537. if test -f init_socket_out.c
  538. then
  539.     echo shar: will not overwrite existing file "init_socket_out.c"
  540. else
  541. cat << \SHAR_EOF > init_socket_out.c
  542. #include "notify.h"
  543. #include <netdb.h>
  544.  
  545. int my_socket;
  546. struct sockaddr_in my_address;
  547. struct sockaddr_in all;         /* broadcast address */
  548.  
  549. extern char *progname;
  550. extern int debug;
  551.  
  552. init_socket(trigger,rhost)
  553. int trigger;
  554. char *rhost;
  555. {
  556.     char host[128];
  557.     char *service_name;
  558.     long host_net;
  559.     struct in_addr *host_addr, *tohost_addr;
  560.  
  561.     struct hostent *hp, *tohp;
  562.     struct servent *sp;
  563.     int bound;
  564.  
  565.     my_socket = socket(AF_INET, SOCK_DGRAM, 0, 0);
  566.     if (my_socket < 0) {
  567.     perror(progname);
  568.     exit(-1);
  569.     }
  570.  
  571.     /* Get any old local port and the local address */
  572.  
  573.     my_address.sin_addr.s_addr = INADDR_ANY;
  574.     my_address.sin_port        = 0;
  575.  
  576.     bound = bind(my_socket, &my_address, sizeof(my_address), 0);
  577.     if (bound < 0) {
  578.     perror(progname);
  579.     exit(-1);
  580.     }
  581.  
  582.     /* Now create the broadcast address with the well known
  583.      * port number - use a different number according to the
  584.      * value of "trigger".
  585.      */
  586.  
  587.     gethostname(host, sizeof(host));
  588.  
  589.     hp = gethostbyname(host);
  590.     if (hp == NULL) {
  591.     fprintf(stderr,"%s: couldn't get hostent ", progname);
  592.     perror(host);
  593.     }
  594.     tohp = gethostbyname(rhost);
  595.     if (tohp == NULL) {
  596.     fprintf(stderr,"%s: couldn't get hostent ", progname);
  597.     perror(rhost);
  598.     }
  599.  
  600.     host_addr = (struct in_addr *) hp->h_addr;
  601.     host_net  = inet_netof(host_addr->s_addr);
  602.  
  603.     tohost_addr = (struct in_addr *) tohp->h_addr;
  604.  
  605.     service_name = SERVICE_NAME;
  606.     sp = getservbyname(service_name, "udp");
  607.     if (sp == NULL) {
  608.     perror(progname);
  609.     }
  610.  
  611.     all.sin_family  = AF_INET;
  612.     all.sin_addr    = *(struct in_addr *)(tohp -> h_addr);
  613.     all.sin_port    = sp->s_port;
  614.  
  615.     if (debug) {
  616.     printf("Broadcast address = (%08x) = %s, %d (family %d)\n",
  617.         all.sin_addr.s_addr,
  618.         inet_ntoa(all.sin_addr),
  619.         htons(all.sin_port),
  620.         all.sin_family);
  621.     }
  622. }
  623. SHAR_EOF
  624. if test 1842 -ne `wc -c < init_socket_out.c`
  625. then
  626.     echo shar: error transmitting "init_socket_out.c" '('should be 1842 chars')'
  627. else
  628.     echo init_socket_out.c
  629. fi
  630. fi
  631. echo shar: extracting "wcwin.notifyd.c" '('4554 chars')'
  632. if test -f wcwin.notifyd.c
  633. then
  634.     echo shar: will not overwrite existing file "wcwin.notifyd.c"
  635. else
  636. cat << \SHAR_EOF > wcwin.notifyd.c
  637. #include "notify.h"
  638. #include <utmp.h>
  639. #include <sys/file.h>
  640. #include <win.h>
  641. #include <pen.h>
  642. #include <signal.h>
  643. #include <icon.h>
  644. #include <pen.h>
  645. #include <rfont.h>
  646.  
  647. static int  panel;
  648. static  RSize posn, ipos;
  649. static  RSize size;
  650. static  Raster * raster;
  651. static  Window * window;
  652. static  Pen * pen;
  653. static  Raster * RasterCreate ();
  654. static  Window * WinCreate ();
  655. static  Pen * PenCreate ();
  656. static  IconList *iconlist;
  657. void pdIconWriteLabels();
  658.  
  659. int pageno = 0;
  660. int stopit();
  661.  
  662. #define UTMP "/etc/utmp"
  663.  
  664. int my_socket = 0;
  665. notify data;
  666. int debug = 0;
  667. char *progname;
  668. FILE *out;
  669.  
  670. main(argc,argv)
  671. int argc;
  672. char *argv[];
  673. {
  674.     int c,fromlen;
  675.     struct sockaddr_in from;
  676.  
  677.     out = stdout;
  678.     progname = argv[0];
  679.     c = recvfrom(my_socket, &data, sizeof(notify), 0, 
  680.         (struct sockaddr *) &from, &fromlen);
  681.     if(fork() >0) exit(0);
  682.     if(debug)
  683.         fprintf(out,"RECVD to %s data %s ID %s type %d size %d\n",
  684.             data.to, data.mess, data.id, data.type, c);
  685.     if (c != sizeof(notify)) exit(0);
  686.     if(debug)
  687.         fprintf(out,"Size OK\n");
  688.     if(!strcmp(data.id,"notify")) show(data);
  689.     if(debug)
  690.         fprintf(out,"Showed data OK\n");
  691.     exit (0);
  692. }
  693.  
  694. show(data)
  695. notify data;
  696. {
  697.     int fd, showit=0;
  698.     FILE *fp;
  699.     struct utmp entry;
  700.     char tty[20];
  701.  
  702.     fd = open(UTMP,O_RDONLY,NULL);
  703.     if (fd < 0) return;
  704.     while (read(fd, &entry, sizeof(struct utmp)) > 0) {
  705.         if ((data.type == MACHINE_WIDE) ||
  706.             (data.type == MACH_AND_WIN) ||
  707.             (!strncmp(data.to,entry.ut_name,8))) {
  708.             strcpy(tty,"/dev/");
  709.             if (strncmp("tty",entry.ut_line,3)) continue;
  710.             if (*entry.ut_name == '\0') continue;
  711.             if (((data.type == WINDOWED)||
  712.                (data.type == MACH_AND_WIN)) &&
  713.                (entry.ut_line[3]=='v')) {
  714.                    showit++;
  715.                    continue;
  716.                }
  717.             strncat(tty,entry.ut_line,8);
  718.             fp = fopen(tty,"w");
  719.             if (debug) fprintf(out,"Trying %s\n",tty);
  720.             if (fp == NULL) continue;
  721.             fprintf(fp,"%s",data.mess);
  722.             fclose(fp);
  723.         }
  724.     }
  725.     close(fd);
  726.  
  727.     if(showit) {
  728.         MGblast(data.mess, data.from);
  729.     }
  730. }
  731.  
  732. MGblast(buf,from)
  733. char *buf, *from;
  734. {
  735.     int i=0,j;
  736.     int lineno = 10;
  737.     Event event;
  738.  
  739.     show_page(pageno,from,buf);
  740.     at(5,lineno);
  741.     for (j=0;j<strlen(buf);j++) {
  742.         if((++i % 115) == 0 || (buf[j] == '\n')) {
  743.             at(5,lineno);
  744.             lineno += 10;
  745.             i = 1;
  746.         }
  747.         else if ((buf[j] > 31) && (buf[j] < 128)) 
  748.             writech(buf[j]);
  749.     } 
  750.     page_update();
  751.         signal(SIGALRM,stopit);
  752.     alarm(600);    /* 10 minutes */
  753.     PanelRead(panel,&event,1);
  754. }
  755.  
  756.  
  757. show_page (pos,sentfrom,mess)
  758. int pos;
  759. char *sentfrom, *mess;
  760. {
  761.     int i;
  762.     char iconname[80];
  763.     posn.w = 160;
  764.     posn.h = 300;
  765.     size.w = 700;
  766.     size.h = 10*linecount(mess)+5;
  767.     if(size.h <40) size.h = 40;
  768.     ipos.w = 980;
  769.     ipos.h = 0;
  770.     raster = RasterCreate (size.w, size.h, 0, R_PIXD (1));
  771.     pen = PenCreate (raster);
  772.     strcpy(iconname,sentfrom);
  773.     strcat(iconname,".icn");
  774.     iconlist = (IconList *)IconListRead(iconname,NULL);
  775.     if(iconlist == NULL) 
  776.     iconlist = (IconList *)IconListRead("not.icn",NULL);
  777.     pdIconWriteLabels(iconlist,sentfrom);
  778.     window = WinCreate (&posn, &size, 0, &ipos, NULL, 1, iconlist,
  779.         sentfrom, NULL, W_FULL_TYPE);
  780.     panel = WinGetPanel (window);
  781.     PanelSetMask(panel,E_CLICK_CLASS | E_SEL_CLASS);
  782.     PageDefine (panel, 0, raster, NULL, NULL);
  783.     PageSelect (panel, 0);
  784.     PanelUpdate (panel, 0, 1);
  785.     WinDisplay (window);
  786. }
  787.  
  788. kill_page () {
  789.     WinDestroy (window);
  790.     PenDestroy (pen);
  791.     RasterDestroy (raster);
  792. }
  793.  
  794. writech(c) char c;
  795. {
  796.     TextWritef(pen,"%c",c);
  797. }
  798.  
  799.  
  800. page_update () {
  801.     PanelUpdate(panel,0,1);
  802.     ipos.w = 0;
  803.     IconSetPosition(WinGetID(window), &ipos); 
  804.     ipos.h = 760;
  805.     IconSetPosition(WinGetID(window), &ipos); 
  806.     ipos.w = 980;
  807.     IconSetPosition(WinGetID(window), &ipos); 
  808.     ipos.h = 0;
  809.     IconSetPosition(WinGetID(window), &ipos); 
  810.     IconShow(WinGetID(window));    
  811.     WindowUnstow(WinGetID(window));
  812. }
  813.  
  814. at (x, y)
  815. int     x,
  816.     y;
  817. {
  818.     PenSetXY (pen, x, y);
  819. }
  820.  
  821. int linecount(s)
  822. char *s;
  823. { int lines=0;
  824.   while(*s != NULL) 
  825.     if(*(s++) == '\n') lines++;
  826.   return lines;
  827. }
  828.  
  829. int stopit()
  830. {
  831.     exit(0);
  832. }
  833.  
  834. static Pen    *mypen = 0;
  835.  
  836. void pdIconWriteLabels (ilist, label)
  837.     IconList        *ilist;
  838.     char        *label;
  839. {
  840.     register Icon    *ip = ilist->Icons;
  841.     int            i;
  842.     RFont *font;
  843.  
  844.     if (!mypen)
  845.     mypen = PenCreate (ip->Image);
  846.     font = (RFont *)FontAcquire("stdicon","i",8);
  847.     PenSetFont(mypen,font);
  848.  
  849.     for (i = ilist->Count; i != 0; i--, ip++) {
  850.     PenSetSheet (mypen, ip->Image);
  851.  
  852.         if (ip->TextBox.size.w != 0 && ip->TextBox.size.h != 0) {
  853.         PenSetPos (mypen, &ip->TextBox.pos);
  854.         TextCentreStr (mypen, label, &ip->TextBox.size);
  855.     }
  856.     }
  857. }
  858. SHAR_EOF
  859. if test 4554 -ne `wc -c < wcwin.notifyd.c`
  860. then
  861.     echo shar: error transmitting "wcwin.notifyd.c" '('should be 4554 chars')'
  862. else
  863.     echo wcwin.notifyd.c
  864. fi
  865. fi
  866. echo shar: extracting "notify.h" '('471 chars')'
  867. if test -f notify.h
  868. then
  869.     echo shar: will not overwrite existing file "notify.h"
  870. else
  871. cat << \SHAR_EOF > notify.h
  872. #include <stdio.h>
  873. #include <sys/types.h>
  874. #include <sys/socket.h>
  875. #include <netinet/in.h>
  876. #include <arpa/inet.h>
  877.  
  878. #define SERVICE_NAME "notify"
  879. #define MESS_SIZE 1000
  880.  
  881. #define MACHINE_WIDE 0
  882. #define PERSON_ONLY  1
  883. #define WINDOWED     2
  884. #define MACH_AND_WIN 3
  885.  
  886. typedef struct {
  887.     char id[8];
  888.     char mess[MESS_SIZE];         /* The message */
  889.     char to[9];                /* who it's to */
  890.     char from[9];            /* who it's from */
  891.     char type;            /* MACHINE_WIDE, PERSON or WINDOWED */
  892. } notify;
  893. SHAR_EOF
  894. if test 471 -ne `wc -c < notify.h`
  895. then
  896.     echo shar: error transmitting "notify.h" '('should be 471 chars')'
  897. else
  898.     echo notify.h
  899. fi
  900. fi
  901. echo shar: extracting "services" '('54 chars')'
  902. if test -f services
  903. then
  904.     echo shar: will not overwrite existing file "services"
  905. else
  906. cat << \SHAR_EOF > services
  907. notify          1113/udp        # for pd notify stuff
  908. SHAR_EOF
  909. if test 54 -ne `wc -c < services`
  910. then
  911.     echo shar: error transmitting "services" '('should be 54 chars')'
  912. else
  913.     echo services
  914. fi
  915. fi
  916. echo shar: extracting "servers" '('51 chars')'
  917. if test -f servers
  918. then
  919.     echo shar: will not overwrite existing file "servers"
  920. else
  921. cat << \SHAR_EOF > servers
  922. notify  udp     /usr/etc/in.notifyd     in.notifyd
  923. SHAR_EOF
  924. if test 51 -ne `wc -c < servers`
  925. then
  926.     echo shar: error transmitting "servers" '('should be 51 chars')'
  927. else
  928.     echo servers
  929. fi
  930. fi
  931. echo shar: extracting "inetd.conf" '('70 chars')'
  932. if test -f inetd.conf
  933. then
  934.     echo shar: will not overwrite existing file "inetd.conf"
  935. else
  936. cat << \SHAR_EOF > inetd.conf
  937. notify  dgram   udp     wait  root    /usr/etc/in.notifyd     notifyd
  938. SHAR_EOF
  939. if test 70 -ne `wc -c < inetd.conf`
  940. then
  941.     echo shar: error transmitting "inetd.conf" '('should be 70 chars')'
  942. else
  943.     echo inetd.conf
  944. fi
  945. fi
  946. #         End of shar archive
  947. exit 0
  948.  
  949.  
  950.