home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume30 / sendopr / part01 < prev    next >
Encoding:
Text File  |  1992-06-20  |  31.8 KB  |  1,168 lines

  1. Newsgroups: comp.sources.misc
  2. From: brianb@julian.uwo.ca (Brian Borowski)
  3. Subject:  v30i071:  sendopr - Send messages to the operator, Part01/01
  4. Message-ID: <1992Jun20.171221.2372@sparky.imd.sterling.com>
  5. X-Md4-Signature: 52786afab6e8bb1342cb52aa4402ad63
  6. Date: Sat, 20 Jun 1992 17:12:21 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brianb@julian.uwo.ca (Brian Borowski)
  10. Posting-number: Volume 30, Issue 71
  11. Archive-name: sendopr/part01
  12. Environment: UNIX
  13.  
  14. >From the README file:
  15.  
  16. This software has been tested on Sun3, Sun4, mips, and SGI.
  17. It is currently in use here on these platforms.
  18. The original author was Hyman Wong, and there have been significant
  19. upgrades and modifications made by Reg Quinton and myself.
  20.  
  21. Sendopr allows users to send messages to the operator.  
  22. It is a queuing system which delivers messages to an operator's
  23. Xterminal.  Xmessage is used to display the information.
  24. ------
  25. #! /bin/sh
  26. # This is a shell archive.  Remove anything before this line, then feed it
  27. # into a shell via "sh file" or similar.  To overwrite existing files,
  28. # type "sh file -c".
  29. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  30. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  31. # Contents:  README BEWARE Makefile sendopr.c sendopr.man sendoprd.c
  32. #   sendoprd.h sendoprd.man tcpopen.c
  33. # Wrapped by kent@sparky on Sat Jun 20 11:55:50 1992
  34. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  35. echo If this archive is complete, you will see the following message:
  36. echo '          "shar: End of archive 1 (of 1)."'
  37. if test -f 'README' -a "${1}" != "-c" ; then 
  38.   echo shar: Will not clobber existing file \"'README'\"
  39. else
  40.   echo shar: Extracting \"'README'\" \(2542 characters\)
  41.   sed "s/^X//" >'README' <<'END_OF_FILE'
  42. XThis software has been tested on Sun3, Sun4, mips, and SGI.
  43. XIt is currently in use here on these platforms.
  44. XThe original author was Hyman Wong, and there have been significant
  45. Xupgrades and modifications made by Reg Quinton and myself.
  46. X
  47. XSendopr allows users to send messages to the operator.  
  48. XIt is a queuing system which delivers messages to an operator's
  49. XXterminal.  Xmessage is used to display the information.
  50. X
  51. XMulti-line messages can come from standard input if the user
  52. Xis not a tty.  The messages appear on the operator's console
  53. Xwhich is assumed to be an Xterminal.
  54. XThe geometry of the window should be defined in the operator's
  55. X.xdefaults file: see man page for more details.
  56. X
  57. XTo install:
  58. X    1.  make
  59. X
  60. X    2.  Include a line in /etc/services similar to:
  61. Xsendopr         xxx/tcp
  62. X    Where xxx is the port number to be used for the service
  63. X    for sendoprd.
  64. X
  65. X    3.  Include a line in /etc/inetd.conf similar to:
  66. Xsendopr stream  tcp     nowait  nobody  /usr/ccs/lib/sendoprd           sendoprd
  67. X
  68. X    4.  Then execute the command:
  69. Xkill -HUP "pid of inetd"
  70. X    For kill: Arguments should be jobs or process id's.
  71. X    This will reinitialize inetd.
  72. X
  73. XREADME -- July 12, 1991
  74. X
  75. XSendopr was written by me, Hyman Wong, for the department of Computing
  76. Xand Communications Services at the University of Western Ontario.  I am
  77. Xa student working here as a consultant and applications programmer.
  78. XSendopr is a program utility that allows users to send a message to the
  79. Xoperator's terminal.  Sendopr was written to reduce the clutter on the
  80. Xoperator's screen by opening up an xmessage window at the same place on
  81. Xthe operator's display.
  82. X
  83. XNov 18, 1991 (Reg Quinton)
  84. X
  85. XSendopr sends things to the daemon via E-mail. This requires an E-mail
  86. Xpipe like
  87. X
  88. X    sendopr: "|/usr/ccs/lib/sendord"
  89. X
  90. Xin /usr/lib/aliases.
  91. X
  92. XBrian Borowski:
  93. XMar. 31, 1992,  Revised sendoprd.c to use advisory locks on the .busy file.
  94. XThis will let the program execute when it is supposed to.
  95. XResolves the problem with .busy file lock up.
  96. X
  97. XApril 9, 1992  (Brian Borowski)
  98. XThe shell script sendopr was rewritten in C and this implementation
  99. Xhas been done as a client using a host on the net when messages
  100. Xare to be queued.  In all other respects I have attempted to
  101. Xduplicate the behaviour of the shell script version of sendopr.
  102. X
  103. XApril 16, 1992 (Brian Borowski)
  104. XPerformed upgrade to fix the getuser problem which arose when the
  105. Xprogram was being run with no tty (for example, from cron.)
  106. XAlso modified interface so that the input for the message could come
  107. Xfrom standard input, rather than just the command line.
  108. END_OF_FILE
  109.   if test 2542 -ne `wc -c <'README'`; then
  110.     echo shar: \"'README'\" unpacked with wrong size!
  111.   fi
  112.   # end of 'README'
  113. fi
  114. if test -f 'BEWARE' -a "${1}" != "-c" ; then 
  115.   echo shar: Will not clobber existing file \"'BEWARE'\"
  116. else
  117.   echo shar: Extracting \"'BEWARE'\" \(1153 characters\)
  118.   sed "s/^X//" >'BEWARE' <<'END_OF_FILE'
  119. X $Author: reggers $
  120. X $Date: 91/07/23 12:31:59 $
  121. X $Header: /ccs/export/src/usr.local/sendopr/RCS/BEWARE,v 1.1 91/07/23 12:31:59 reggers Exp $
  122. X $Source: /ccs/export/src/usr.local/sendopr/RCS/BEWARE,v $
  123. X $State: Exp $
  124. X
  125. XOriginal work by Hyman Wong -- Thu Jul 12 12:42:41 EDT 1991
  126. X
  127. XBEWARE:
  128. X
  129. XSince sendopr uses echo and xmessage, the same restrictions and bugs are
  130. Xalso found in sendop.  
  131. X
  132. XMessages can't contain "?" or "!" because of their shell interpretation.
  133. X
  134. XThe switches must always come before the message. 
  135. X
  136. XThe operator's Xresources should be configured to allow messages to be
  137. Xreceived, ie. "xhost +" should be set.  In the operator's .xdefaults file,
  138. Xthere should be a line similar to:
  139. X      Important.Geometry:        800x500+700+200
  140. Xto indicate the size and the location of the message window   
  141. X
  142. XSendopr assumes the operator's terminal is X-based.  If the terminal
  143. Xdoes not support X11, then an email message will be sent to the operator
  144. Xand the sender will not get a confirmation of the message being received.
  145. X
  146. XSendopr does not wrap long lines around to the next line.  If a sentence
  147. Xis longer than the window size, the end of the line is cut off.
  148. X
  149. END_OF_FILE
  150.   if test 1153 -ne `wc -c <'BEWARE'`; then
  151.     echo shar: \"'BEWARE'\" unpacked with wrong size!
  152.   fi
  153.   # end of 'BEWARE'
  154. fi
  155. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  156.   echo shar: Will not clobber existing file \"'Makefile'\"
  157. else
  158.   echo shar: Extracting \"'Makefile'\" \(1397 characters\)
  159.   sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  160. X#
  161. X# $Author: reggers $
  162. X# $Date: 1992/06/10 14:02:03 $
  163. X# $Id: Makefile,v 1.10 1992/06/10 14:02:03 reggers Exp $
  164. X#
  165. X# Make and install things in the right places
  166. X#
  167. XSHELL=/bin/sh
  168. XGET = co
  169. XCC=cc
  170. X# On SGI's you might need to use a different SIGRET, say void
  171. X# Instead you can say "make CFLAGS='-O -DSIGRET=void'"
  172. X#
  173. X#CFLAGS=-g -DDEBUG 
  174. XCFLAGS=-O
  175. XOWNER=daemon
  176. XGROUP=daemon
  177. X# where do things go?
  178. XOLD=/usr/ccs/old
  179. XLIB=/usr/ccs/lib
  180. XBIN=/usr/ccs/bin
  181. XSPOOL=/usr/spool/sendoprd
  182. XMAN1=/usr/ccs/man/man1
  183. XMAN8=/usr/ccs/man/man8
  184. XMAN1EXT=1
  185. XMAN8EXT=8
  186. X# Sources
  187. XSRC=Makefile sendopr.c tcpopen.c sendopr.man sendopr.h sendoprd.c sendoprd.man
  188. XOBJECTS = sendopr.o tcpopen.o
  189. X
  190. Xall:    sendopr sendoprd
  191. X
  192. X${SRC}:
  193. X    ${GET} $@
  194. X
  195. X.c.o:
  196. X    ${CC} ${CFLAGS} -c $*.c
  197. X
  198. Xsendopr: ${OBJECTS}
  199. X    ${CC} -o $@ ${OBJECTS}
  200. X
  201. Xsendoprd: sendoprd.c sendoprd.h
  202. X    ${CC} ${CFLAGS} -o $@ $@.c
  203. X
  204. X# On the machine that spools you'll need a spool area
  205. X
  206. X${SPOOL}:
  207. X    umask 027; mkdir -p ${SPOOL}
  208. X    chown ${OWNER}.${GROUP} ${SPOOL}
  209. X
  210. Xinstall: sendopr sendopr.man sendoprd sendoprd.man
  211. X    -cp ${BIN}/sendopr ${OLD}
  212. X    install -c -m 755 sendopr ${BIN}
  213. X    -cp ${MAN1}/sendopr.${MAN1EXT} ${OLD}
  214. X    install -c -m 644 sendopr.man ${MAN1}/sendopr.${MAN1EXT}
  215. X    -cp ${LIB}/sendoprd ${OLD}
  216. X    install -s -c -m 6755 -o ${OWNER} -g ${GROUP} sendoprd ${LIB}
  217. X    -cp ${MAN8}/sendoprd.${MAN8EXT} ${OLD}
  218. X    install -c -m 644 sendoprd.man ${MAN8}/sendoprd.${MAN8EXT}
  219. X
  220. Xclean:    
  221. X    -rm sendoprd *.o core *~
  222. X
  223. END_OF_FILE
  224.   if test 1397 -ne `wc -c <'Makefile'`; then
  225.     echo shar: \"'Makefile'\" unpacked with wrong size!
  226.   fi
  227.   # end of 'Makefile'
  228. fi
  229. if test -f 'sendopr.c' -a "${1}" != "-c" ; then 
  230.   echo shar: Will not clobber existing file \"'sendopr.c'\"
  231. else
  232.   echo shar: Extracting \"'sendopr.c'\" \(4602 characters\)
  233.   sed "s/^X//" >'sendopr.c' <<'END_OF_FILE'
  234. X/*    $Author: reggers $
  235. X*    $Date: 1992/04/21 14:31:46 $
  236. X*    $Id: sendopr.c,v 1.5 1992/04/21 14:31:46 reggers Exp $
  237. X*    $Source: /usr/src/usr.local/utilities/sendopr/RCS/sendopr.c,v $
  238. X*    $State: Exp $
  239. X*
  240. X*  Original work done by Brian Borowski on April 10 1992
  241. X*  done during a placement here at UWO
  242. X*  This program sends messages to the operator in one of two modes.
  243. X*  These are immediate where the message on the command line is sent via
  244. X*  xmessage.  In this mode the program will pause until the operator
  245. X*  clicks on the button at the bottom of the message window, at which
  246. X*  point the sender will see "okay" and be returned to the prompt.
  247. X*  In the second mode queued mode the message is sent via a host
  248. X*  socket pair using tcp and the message is queued for future reading
  249. X*  by the operator.  Immediate and queued can be controlled from the
  250. X*  command line by the -i and -q options.  If the controlling device
  251. X*  is not a tty then queued mode is assumed.
  252. X*/
  253. X
  254. Xstatic    char    *rcsid="$Id: sendopr.c,v 1.5 1992/04/21 14:31:46 reggers Exp $";
  255. X
  256. X#ifndef SENDOPRHOST
  257. X#define SENDOPRHOST "sendoprhost"
  258. X#endif
  259. X
  260. X#ifndef SENDOPRPORT
  261. X#define SENDOPRPORT "sendopr"
  262. X#endif
  263. X
  264. X#define CFG "/usr/local/share/etc/operator"
  265. X
  266. X#include <stdio.h>
  267. X#include <sysexits.h>
  268. X#include <sys/types.h>
  269. X#include <pwd.h>
  270. X#include <errno.h>
  271. X#include "sendoprd.h"
  272. X
  273. Xchar display_buf[BUFSIZ];
  274. Xchar msg_buf[BUFSIZ];
  275. Xchar *usage="sendopr [-i|-q] [-d display] [-s subject] message";
  276. Xchar *display = DISPLAY;
  277. Xchar *title = TITLE;
  278. Xchar *name = NAME;
  279. Xchar *subject=NAME, *logname, *date;
  280. Xchar myhost[BUFSIZ]; /* name of host */
  281. Xint from_stdin=0; /* assume input is from args rather than stdin */
  282. Xint debug=0;
  283. X
  284. X/* msg_print: feeds the users message into the file pointer.
  285. X    Returns no value.  Called by main. */
  286. Xvoid msg_print(argv, argc, start, fp)
  287. Xchar *argv[];
  288. Xint argc, start;
  289. XFILE *fp;
  290. X{ int i;
  291. X
  292. Xfprintf(fp, "From: %s@%s\n", logname, myhost);
  293. Xfprintf(fp, "Subject: %s\n", subject);
  294. Xfprintf(fp, "Date: %s\n", date);
  295. Xif (from_stdin) /* get message from stdin and feed it out */
  296. X    while (fgets(msg_buf, BUFSIZ, stdin) != NULL)
  297. X    fputs(msg_buf, fp);
  298. X    else /* else get message from argv */
  299. X  { for (i = start; argv[i]; i++) /* feed rest of argv into pipe */
  300. X      { fprintf(fp, "%s", argv[i]);
  301. X        if (i < argc-1) putc(' ', fp);
  302. X        } /* end for args */
  303. X    putc('\n', fp);
  304. X    } /* end else from args */
  305. Xfflush(fp);
  306. X} /* end msg_print */
  307. X
  308. X
  309. Xmain(argc, argv)
  310. Xint argc;
  311. Xchar *argv[];
  312. X{ int unit, i;
  313. Xtime_t secs;
  314. Xchar *getlogin(), *ctime();
  315. Xextern int optind;
  316. Xextern char *optarg;
  317. Xextern int tcpopen();
  318. Xint immediate, c;
  319. Xstruct passwd *pw_info;
  320. XFILE *fp_out, *fp1;
  321. X
  322. Xif (isatty(fileno(stdin)))
  323. X    immediate = 1; /* set immediate to true if tty */
  324. X    else immediate = 0;
  325. X/* parse command line arguments: */
  326. Xif (argc == 1) /* assume input from stdin */
  327. X    from_stdin=1;
  328. X    else /* check the argv */
  329. X    while ((c = getopt(argc, argv, "iqd:s:")) != EOF)
  330. X    switch(c)
  331. X      { case 'i' : if (optind == 2)
  332. X            immediate=1;
  333. X        break;
  334. X        case 'q' : if (optind == 2)
  335. X            immediate=0;
  336. X        break;
  337. X        case 'd' : display=optarg;
  338. X        break;
  339. X        case 's' : subject = (optarg)? optarg: NAME;
  340. X        break;
  341. X        default : fprintf(stderr, usage);
  342. X        exit(EX_USAGE);
  343. X        } /* end case */
  344. X
  345. Xif (optind == argc) from_stdin=1; /* message from stdin */
  346. Xif (display == DISPLAY) /* then hasn't been changed by command line */
  347. X    if ((fp1=fopen(CFG, "r")) != NULL) /* check for config file */
  348. X      { fgets(display_buf,BUFSIZ,fp1);
  349. X    display = display_buf;
  350. X    fclose(fp1);
  351. X    }  /* end get display info */
  352. Xtime(&secs);
  353. Xdate = ctime(&secs);
  354. Xif ((logname = getlogin()) == NULL)
  355. X  { pw_info = getpwuid(getuid()); /* not attached to a tty */
  356. X    logname = pw_info->pw_name;
  357. X    }
  358. Xif (gethostname(myhost, BUFSIZ) == -1)
  359. X  { fprintf(stderr, "***-cannot get name of host");
  360. X    exit(127);
  361. X    }
  362. Xif (debug) fprintf(stderr,"got user, date and host\n");
  363. Xif (immediate) /* send using xmessage */
  364. X  { sprintf(msg_buf, "%s -display %s -title %s -name %s -",
  365. X    XMESSAGE,display,title,name);
  366. X    if ((fp_out=popen(msg_buf, "w")) == NULL)
  367. X      { fprintf(stderr, "cannot pipe to xmessage");
  368. X    exit(127);
  369. X    }
  370. X    msg_print(argv, argc, optind, fp_out);
  371. X    pclose(fp_out);
  372. X    } /* end if immediate */
  373. X    else /* use the sendopr host */
  374. X    { if ((unit=tcpopen(SENDOPRHOST, SENDOPRPORT)) < 0)
  375. X      { fprintf(stderr, "**cannot create a socket\n");
  376. X    exit(127);
  377. X    }
  378. X    fp_out=fdopen(unit, "w");
  379. X    /* feed in the message */
  380. X    msg_print(argv, argc, optind, fp_out);
  381. X    fclose(fp_out);
  382. X    } /* end else use the sendopr host */
  383. Xexit(0);
  384. X    } /* end main */
  385. END_OF_FILE
  386.   if test 4602 -ne `wc -c <'sendopr.c'`; then
  387.     echo shar: \"'sendopr.c'\" unpacked with wrong size!
  388.   fi
  389.   # end of 'sendopr.c'
  390. fi
  391. if test -f 'sendopr.man' -a "${1}" != "-c" ; then 
  392.   echo shar: Will not clobber existing file \"'sendopr.man'\"
  393. else
  394.   echo shar: Extracting \"'sendopr.man'\" \(4085 characters\)
  395.   sed "s/^X//" >'sendopr.man' <<'END_OF_FILE'
  396. X./"    $Author: brianb $
  397. X./"     $Date: 1992/04/16 17:24:24 $
  398. X./"     $Header: /usr/src/usr.local/utilities/sendopr/RCS/sendopr.man,v 1.6 1992/04/16 17:24:24 brianb Exp $
  399. X./"     $Source: /usr/src/usr.local/utilities/sendopr/RCS/sendopr.man,v $
  400. X./"
  401. X./"  Sendopr's man page was written by Hyman Wong -- July 11, 1991.
  402. X./"
  403. X.TH SENDOPR Local "11 July 1991"
  404. X.UC 4
  405. X.SH NAME
  406. Xsendopr \- send a message to the operator
  407. X.SH SYNOPSIS
  408. X.B sendopr 
  409. X[
  410. X.B \-i,-q
  411. X] [
  412. X.BI \-d " display"
  413. X] [
  414. X.BI \-s " subject"
  415. X] [
  416. X.BI message
  417. X]
  418. X.br
  419. X.SH DESCRIPTION
  420. X.PP
  421. X.I Sendopr
  422. Xwill send a short one line message to the operator, if the message is part
  423. Xof the command-line.  Otherwise, standard input is used.
  424. XInput will terminate when EOF is received.
  425. X.I Sendopr
  426. Xhas two modes, 
  427. X.I immediate 
  428. Xand 
  429. X.I queued
  430. Xthat are set with the
  431. X.B -i
  432. Xand 
  433. X.B -q
  434. Xflags.
  435. X.PP
  436. XJobs that aren't attached to a terminal (ie. they have no user at a
  437. Xcontrolling tty device), for example
  438. Xcron(1) jobs, will use the queued mode as the default. User jobs work
  439. Xin an immediate mode by default.
  440. XIn either case
  441. Xflags can be used to select a mode different from the default.
  442. X.PP
  443. XWith the
  444. X.B \-i
  445. Xswitch specified, 
  446. X.I sendopr
  447. Xis in immediate mode and the message is sent immediately to the operator's
  448. XX-terminal.  After the operator reads the message, they will acknowledge
  449. Xits receipt by clicking on a button in the message window.  The button
  450. Xwill cause
  451. X.I sendopr
  452. Xto echo back a short note to the user that the message has been read.
  453. X.PP
  454. XIn 
  455. X.I queued
  456. Xmode, 
  457. X.I sendopr 
  458. Xwill send the message via a queueing strategy and the operators will
  459. Xread the message only when they check the queue.  A verification message
  460. Xwill not be relayed back to the sender in this case.
  461. XIn this mode the message is sent via a host on the network.
  462. X.PP
  463. XIf the display is specified with the 
  464. X.B \-d 
  465. Xoption, the message will go to the specified Xstation instead of the
  466. Xdefault display. The default is
  467. X.BR operator:0 ;
  468. Xhowever, that can be overridden by the file 
  469. X.B /usr/local/share/etc/operator.
  470. X.SH ENVIRONMENT
  471. X.PP
  472. X.I Sendopr
  473. Xhonours the following environment variables.  The default
  474. Xvalues can be changed to suit the operator's needs, otherwise
  475. Xthey will be set to the default values.
  476. X.PP
  477. X.TP
  478. X.B DISPLAY
  479. Xwhich terminal to open the message window on.  The default is
  480. X.B operator:0
  481. Xbut this can be over ridden with the
  482. Xcontents of
  483. X.B /usr/local/share/etc/operator.
  484. XThe display is over-ridden yet again if
  485. X.BI \-d " display"
  486. Xis specified. 
  487. X.TP
  488. X.B TITLE 
  489. Xthe title given to the window and the icon when the window is closed.
  490. XThe default is set to:
  491. X.BR Important.
  492. X.TP
  493. X.B SUBJECT
  494. Xthe Subject: line of the message sent. The default is set to:
  495. X.BR Important .
  496. XAgain, this can be set with the
  497. X.BI \-s " subject"
  498. Xflag.
  499. X.SH FILES
  500. X.TP
  501. X.B /usr/local/share/etc/operator
  502. Xcontains the address of the station where the message will be sent.
  503. X.SH DIAGNOSTICS
  504. X.PP
  505. XThere aren't any.  Sorry, but you're on your own.
  506. X.SH BUGS
  507. X.PP
  508. XSince 
  509. X.I sendopr
  510. Xuses 
  511. X.I xmessage,
  512. Xthe same restrictions and bugs for 
  513. X.I xmessage
  514. Xapply to 
  515. X.I sendopr.  
  516. XSome punctuation marks, such as "!" and "?" cannot be used
  517. Xin the message because of their shell interpretation.  (Command recall
  518. Xand wildcard)
  519. X.PP
  520. XIt's desired if
  521. X.I sendopr
  522. Xcould beep the terminal at the start of the message to get the
  523. Xoperator's attention and cause an interfaced lamp to flash, but 
  524. X.I xmessage
  525. Xseems to filter out any ^G's sent to it.
  526. X.PP
  527. XThe operator's Xresources should be configured to allow messages to be
  528. Xreceived, 
  529. X.I ie. xhost +
  530. Xshould be set, and in the operator's 
  531. X.I .xdefaults
  532. Xfile, there should be a line similar to:
  533. X.SP
  534. X.NF
  535. X.I     Important.Geometry:    800x500+700+200  
  536. X.BL
  537. X.FI
  538. X.SP
  539. Xto indicate the size and location of the message window on the Xterminal.
  540. X.PP
  541. X.I Sendopr
  542. Xassumes the operator's terminal is X-based.
  543. X.PP
  544. X.I Sendopr
  545. Xdoes not wrap long lines around to the next line if the message
  546. Xis on the command-line.
  547. XIf a sentence is
  548. Xlonger than the window size, the end of the line is cut off.  
  549. XThis restriction is not imposed when standard input is used.
  550. X.SH SEE ALSO
  551. Xxmessage(1)
  552. X.SH AUTHOR
  553. XHyman Wong; July 1991.
  554. X
  555. END_OF_FILE
  556.   if test 4085 -ne `wc -c <'sendopr.man'`; then
  557.     echo shar: \"'sendopr.man'\" unpacked with wrong size!
  558.   fi
  559.   # end of 'sendopr.man'
  560. fi
  561. if test -f 'sendoprd.c' -a "${1}" != "-c" ; then 
  562.   echo shar: Will not clobber existing file \"'sendoprd.c'\"
  563. else
  564.   echo shar: Extracting \"'sendoprd.c'\" \(6814 characters\)
  565.   sed "s/^X//" >'sendoprd.c' <<'END_OF_FILE'
  566. X/* 
  567. X * $Author: brianb $
  568. X * $Date: 1992/03/31 20:26:52 $ 
  569. X * $Id: sendoprd.c,v 1.4 1992/03/31 20:26:52 brianb Exp $
  570. X * $Source: /usr/src/usr.local/utilities/sendopr/RCS/sendoprd.c,v $
  571. X *
  572. X * Written by Hyman Wong -- August 1, 1991
  573. X * Spooling routines by Reg Quinton.
  574. X *
  575. X * This program will copy messages  coming from stdin  to temporary files
  576. X * on disk.   Once all the input  has been spooled  to  disk, the program
  577. X * will try to  create a "busy"  lock by  opening  a  file on disk called
  578. X * ".busy".  If  the file already exists, which  means  there  is another
  579. X * copy of the daemon running, OPEN  will cause an  error and the program
  580. X * will exit.  If there is no .busy file, the current program is the only
  581. X * copy running and it  will then create  the busy  lock.  It  will  then
  582. X * change  directory to  the  spool area  and xmessage  each  file to the
  583. X * operator's terminal one at  a time and  wait for the operator to click
  584. X * the   "okay" button before  displaying  the   next message.  When  all
  585. X * messages  have been xmessaged, the  program will remove the .busy file
  586. X * and exit.
  587. X */
  588. X
  589. X#include    <stdio.h>
  590. X#include    <sysexits.h>
  591. X#include    <syslog.h>
  592. X#include    <signal.h>
  593. X#include    <sys/ioctl.h>
  594. X#include    <sys/file.h>
  595. X
  596. X#include     "sendoprd.h"
  597. X
  598. X/* some global variables */
  599. X
  600. Xchar    *display=DISPLAY;
  601. Xchar    *title=TITLE;
  602. Xchar    *name=NAME;
  603. Xint    debug=0;
  604. X
  605. X/* copy one file to another */
  606. X
  607. Xint copy(input,output)
  608. XFILE    *input,*output;
  609. X{    
  610. X    int    c;
  611. X
  612. X    while ((c=getc(input)) != EOF) fputc(c,output);
  613. X    fclose(input);    fclose(output);
  614. X}
  615. X
  616. X/* take care of a file, display it to the operator */
  617. X
  618. Xshow(text)
  619. Xchar    *text;
  620. X{
  621. X    FILE    *input;
  622. X    int    pid,r;
  623. X
  624. X    if (debug) fprintf(stderr,"Displaying %s\n",text);
  625. X
  626. X    /* gotta have that file */
  627. X
  628. X    if (!(input=fopen(text,"r"))) return(0);
  629. X
  630. X        /*      report fork problem if encountered    */
  631. X
  632. X        if ((pid=fork()) == -1)
  633. X        {       syslog(LOG_CRIT,"Cannot fork");
  634. X                return(0);
  635. X        }
  636. X
  637. X        /*      parent waits until *all* children have died    */
  638. X
  639. X        if (pid)
  640. X        {       fclose(input);
  641. X        if (debug) fprintf(stderr,"Parent waiting for children\n");
  642. X                for (pid=wait(&r); pid != -1; pid=wait(&r));
  643. X        if (debug) fprintf(stderr,"All children have terminated\n");
  644. X                return(1);
  645. X        }
  646. X
  647. X        /*      child closes all files and dups file to stdin    */
  648. X
  649. X        close(0);       dup(fileno(input));     fclose(input);
  650. X
  651. X        /*      child does an exec      */
  652. X
  653. X    if (debug) fprintf(stderr,"Child execs %s\n",XMESSAGE);
  654. X        execl(XMESSAGE,XMESSAGE,"-display",display,
  655. X            "-title",title,"-name",name,"-",0);
  656. X        syslog(LOG_CRIT,"Cannot exec %s",XMESSAGE);
  657. X        exit(127);      /*      exec failed     */
  658. X}
  659. X    
  660. X/* given a file, rename it into the spool. Return a success code */
  661. X
  662. Xint    spool(file)
  663. Xchar    *file;
  664. X{
  665. X    char    name[BUFSIZ];
  666. X    int    q,tail,head;
  667. X
  668. X    if ((q=open(SPLRC,O_RDWR | O_CREAT,0644)) < 0)
  669. X    {    syslog(LOG_CRIT,"spool \"%s\" cannot open",SPLRC);
  670. X        return(0);
  671. X    };
  672. X
  673. X    flock(q,LOCK_EX);    lseek(q,0,L_SET);
  674. X
  675. X    if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
  676. X        (read(q,&head,sizeof(int)) != sizeof(int))) tail=head=0;
  677. X
  678. X    sprintf(name,"./%d",tail);
  679. X    if (rename(file,name) != 0)
  680. X    {    
  681. X        flock(q,LOCK_UN);    close(q);
  682. X        return(0);
  683. X    }
  684. X
  685. X    if (debug) fprintf(stderr,"Spooled as number %d\n",tail);
  686. X
  687. X    lseek(q,0,L_SET);    tail++;
  688. X    write(q,&tail,sizeof(int));
  689. X    write(q,&head,sizeof(int));
  690. X
  691. X    flock(q,LOCK_UN);    close(q);
  692. X
  693. X    return(1);
  694. X}
  695. X
  696. X/*    take care of the queue, return a success code    */
  697. X
  698. Xint    unspool()
  699. X{
  700. X    char    name[BUFSIZ];
  701. X    int    q,tail,head;
  702. X
  703. X    if ((q=open(SPLRC,O_RDWR | O_CREAT, 0664)) < 0)
  704. X    {
  705. X        syslog(LOG_CRIT,"unspool \"%s\" cannot open\n",SPLRC);
  706. X        return(0);
  707. X    }
  708. X
  709. X    if (debug) fprintf(stderr,"Unspooling\n");
  710. X    while (1)
  711. X    {    flock(q,LOCK_EX);    lseek(q,0,L_SET);
  712. X
  713. X        if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
  714. X            (read(q,&head,sizeof(int)) != sizeof(int)))
  715. X        {
  716. X            lseek(q,0,L_SET);    tail=head=0;
  717. X            write(q,&tail,sizeof(int));
  718. X            write(q,&head,sizeof(int));
  719. X        }
  720. X
  721. X        if (tail == head)
  722. X        {    flock(q,LOCK_UN);    close(q);
  723. X            return(1);
  724. X        };
  725. X
  726. X        /* ok got the head name, release the queue manager */
  727. X
  728. X        flock(q,LOCK_UN);
  729. X
  730. X        /* now do it, display the file */
  731. X
  732. X        if (debug) fprintf(stderr,"Will display %d\n",head);
  733. X        sprintf(name,"./%d",head);
  734. X        if (!show(name)) return(0);
  735. X        unlink(name);
  736. X    
  737. X        /* now advance the queue */
  738. X
  739. X        flock(q,LOCK_EX);    lseek(q,0,L_SET);
  740. X
  741. X        if ((read(q,&tail,sizeof(int)) != sizeof(int)) ||
  742. X            (read(q,&head,sizeof(int)) != sizeof(int)))
  743. X        {
  744. X            lseek(q,0,L_SET);    tail=head=0;
  745. X            write(q,&tail,sizeof(int));
  746. X            write(q,&head,sizeof(int));
  747. X        }
  748. X
  749. X        if (tail == head)
  750. X        {    flock(q,LOCK_UN);    close(q);
  751. X            return(1);
  752. X        };
  753. X
  754. X        lseek(q,0,L_SET);    head++;
  755. X
  756. X        write(q,&tail,sizeof(int));
  757. X        write(q,&head,sizeof(int));
  758. X        flock(q,LOCK_UN);
  759. X    }
  760. X}
  761. X
  762. X/* see Unix World Tutorial, Dec. 88 */
  763. X
  764. Xvoid    detach()
  765. X{
  766. X    int    i;
  767. X
  768. X    /* let parent go quitely */
  769. X
  770. X    if (fork()) exit(0);
  771. X    
  772. X    /* change process group */
  773. X
  774. X        setpgrp(0,getpid());
  775. X
  776. X        /* get rid of controlling tty */
  777. X
  778. X        if ((i=open("/dev/tty",O_RDWR)) >= 0)
  779. X        {
  780. X            ioctl(i,TIOCNOTTY,0);
  781. X                close(i);
  782. X        }
  783. X
  784. X        /*  ignore key-board signals */
  785. X
  786. X        signal(SIGHUP,SIG_IGN);
  787. X        signal(SIGINT,SIG_IGN);
  788. X        signal(SIGQUIT,SIG_IGN);
  789. X        signal(SIGTERM,SIG_IGN);
  790. X        signal(SIGTSTP,SIG_IGN);
  791. X
  792. X        /* close all open files */
  793. X
  794. X        for (i=0; i < 3; close(i++));
  795. X}
  796. X    
  797. X/* main program starts here */
  798. X
  799. Xchar    *USAGE="Usage: sendoprd [-d display] [-t title] [-n name]\n";
  800. X
  801. Xmain(argc, argv)
  802. Xint    argc;
  803. Xchar    *argv[];
  804. X{
  805. X    int    lockf,c;
  806. Xextern    int    optind;
  807. Xextern     char    *optarg;
  808. X    char    *tmpfile="./tmp.XXXXXX";
  809. X    FILE    *output;
  810. X
  811. X    /* Some day, I'll put this into inetd ... */
  812. X
  813. X    while ((c=getopt(argc,argv,"xd:t:n:")) != EOF)
  814. X        switch (c)
  815. X        {
  816. X        case 'x':    debug++;
  817. X                break;
  818. X
  819. X        case 'd':    display=optarg;
  820. X                break;
  821. X
  822. X        case 't':    title=optarg;
  823. X                break;
  824. X
  825. X        case 'n':    name=optarg;
  826. X                break;
  827. X
  828. X        default:    fprintf(stderr,USAGE);
  829. X                exit(EX_USAGE);
  830. X        }
  831. X    
  832. X    /* we're going to gripe to syslog */
  833. X
  834. X    openlog("sendopr",LOG_PID,LOG_DAEMON);
  835. X
  836. X    /* go to the spool area */
  837. X
  838. X    if (chdir(SPOOL) != 0) 
  839. X    {    syslog(LOG_CRIT,"Cannot chdir to %s\n",SPOOL);
  840. X        if (debug) fprintf(stderr,"Cannot chdir to %s\n",SPOOL);
  841. X        exit(EX_OSFILE);
  842. X    }
  843. X
  844. X    umask(UMASK);
  845. X
  846. X    /* copy the input to a file whose name is given by spool */
  847. X
  848. X    mktemp(tmpfile);    
  849. X
  850. X    if (debug) fprintf(stderr,"Creating tmpfile %s\n",tmpfile);
  851. X
  852. X    if (!(output=fopen(tmpfile,"w")))
  853. X    {    syslog(LOG_CRIT,"can't create tempfile\n");
  854. X        exit(EX_OSFILE);
  855. X    }
  856. X
  857. X    copy(stdin,output);    spool(tmpfile);
  858. X
  859. X    /* try to create the busy lock */
  860. X
  861. X    if ((lockf=open(BUSYLOCK,O_WRONLY|O_CREAT, 644)) < 0)
  862. X        exit(EX_OSFILE);
  863. X    if (flock(lockf, LOCK_EX|LOCK_NB) >= 0)
  864. X    {
  865. X        if (debug) fprintf(stderr,"Busy lock created, will unspool\n");
  866. X        else detach();
  867. X        unspool();
  868. X        flock(lockf, LOCK_UN);
  869. X        close(lockf);
  870. X        unlink(BUSYLOCK);
  871. X    }
  872. X
  873. X    exit(0);
  874. X}
  875. X
  876. END_OF_FILE
  877.   if test 6814 -ne `wc -c <'sendoprd.c'`; then
  878.     echo shar: \"'sendoprd.c'\" unpacked with wrong size!
  879.   fi
  880.   # end of 'sendoprd.c'
  881. fi
  882. if test -f 'sendoprd.h' -a "${1}" != "-c" ; then 
  883.   echo shar: Will not clobber existing file \"'sendoprd.h'\"
  884. else
  885.   echo shar: Extracting \"'sendoprd.h'\" \(802 characters\)
  886.   sed "s/^X//" >'sendoprd.h' <<'END_OF_FILE'
  887. X/*
  888. X * $Author: reggers $
  889. X * $Date: 91/11/18 09:44:38 $
  890. X * $Header: /ccs/export/share/ftp/pub/unix/utilities/sendoprd/RCS/sendoprd.h,v 1.1 91/11/18 09:44:38 reggers Exp $
  891. X *
  892. X * Various defines used by this code. Customize here.
  893. X*/
  894. X
  895. X#ifndef        DISPLAY
  896. X#define        DISPLAY        "operator:0.0"
  897. X#endif
  898. X
  899. X/* where is the Xmessage service, what should it be titled? */
  900. X
  901. X#ifndef        XMESSAGE
  902. X#define        XMESSAGE    "/usr/bin/X11/xmessage"
  903. X#endif
  904. X
  905. X#ifndef        NAME
  906. X#define        NAME        "Important"
  907. X#endif
  908. X
  909. X#ifndef        TITLE
  910. X#define        TITLE        "Important"
  911. X#endif
  912. X
  913. X/* where are files spooled for processing? */
  914. X
  915. X#ifndef        SPOOL
  916. X#define        SPOOL        "/usr/spool/sendoprd/"
  917. X#endif
  918. X
  919. X#ifndef        BUSYLOCK
  920. X#define        BUSYLOCK    "./.busy"
  921. X#endif
  922. X
  923. X#ifndef        SPLRC
  924. X#define        SPLRC        "./.splrc"
  925. X#endif
  926. X
  927. X/* file creation mask */
  928. X
  929. X#ifndef        UMASK
  930. X#define        UMASK        037
  931. X#endif
  932. END_OF_FILE
  933.   if test 802 -ne `wc -c <'sendoprd.h'`; then
  934.     echo shar: \"'sendoprd.h'\" unpacked with wrong size!
  935.   fi
  936.   # end of 'sendoprd.h'
  937. fi
  938. if test -f 'sendoprd.man' -a "${1}" != "-c" ; then 
  939.   echo shar: Will not clobber existing file \"'sendoprd.man'\"
  940. else
  941.   echo shar: Extracting \"'sendoprd.man'\" \(2989 characters\)
  942.   sed "s/^X//" >'sendoprd.man' <<'END_OF_FILE'
  943. X./"    $Author: reggers $
  944. X./"     $Date: 91/11/18 10:30:11 $
  945. X./"     $Header: /ccs/export/share/ftp/pub/unix/utilities/sendoprd/RCS/sendoprd.man,v 1.4 91/11/18 10:30:11 reggers Exp $
  946. X./"     $Source: /ccs/export/share/ftp/pub/unix/utilities/sendoprd/RCS/sendoprd.man,v $
  947. X./"
  948. X./"  Sendoprd's man page was written by Hyman Wong -- August 1, 1991.
  949. X./"
  950. X.TH SENDOPRD Local "1 August 1991"
  951. X.SH NAME
  952. Xsendoprd \- sendopr message daemon.
  953. X.SH SYNOPSIS
  954. X.B sendoprd
  955. X[ -d display ] [ -t title ] [ -n name ] [-x]
  956. X.br
  957. X.SH DESCRIPTION
  958. X.PP
  959. X.I Sendoprd
  960. Xis a daemon that queues and displays messages on the operator's
  961. Xterminal using 
  962. X.BR xmessage(1) .
  963. XThe user interface is the command
  964. X.BR sendopr(l) .
  965. X.PP
  966. X.I Sendoprd 
  967. Xwill spool standard input as a unique file and then attempt to deliver
  968. Xall messages that have been spooled.
  969. X.PP
  970. XWhen the message has been spooled 
  971. X.I sendoprd
  972. Xwill try to create an exclusive lock file called
  973. X.BR .busy .
  974. XIf the file already exits then there is an active daemon processing the
  975. Xqueue \(em this instance will exit.
  976. XOtherwise, this instance processes the queue and finally removes the lock.
  977. X.PP
  978. XThe strategy ensures that only one daemon delivers
  979. Xthe spooled messages to the operator's console. This also means that
  980. Xmessages are displayed and dealt with one at a time.
  981. X.SH OPTIONS
  982. X.PP
  983. XOptions are usually not required.
  984. X.TP
  985. X.BI \-d " display"
  986. XTo change the display terminal, the default display is
  987. X.BR operator:0.0 .
  988. X.TP
  989. X.BI \-t " title"
  990. XTo change the title of the display, the default is
  991. X.BR Important .
  992. X.TP
  993. X.BI \-n " name"
  994. XTo change the name of the display, the default is
  995. X.BR Important .
  996. X.TP
  997. X.B \-x
  998. XTo turn on debugging.
  999. X.SH FILES
  1000. X.TP
  1001. X.B /usr/spool/sendopr
  1002. XThe spool area for messages received. Messages are filed with a unique
  1003. Xnumber starting at zero.
  1004. X.TP
  1005. X.B /usr/spool/sendopr/.busy
  1006. XThe busy lock. This file will exist when a daemon is
  1007. Xprocessing the queue.
  1008. X.TP
  1009. X.B /usr/spool/sendopr/.splrc
  1010. XThe spool control file, contains numbers for the head and tail of the queue.
  1011. X.SH DIAGNOSTICS
  1012. X.PP
  1013. XAll error messages are sent to
  1014. X.IR syslog(3) .
  1015. X.SH FUTURES
  1016. XThe current implementation is fed messages by the E-mail system,
  1017. Xfutures
  1018. Xinclude a sendopr client that talks to a daemon over the net.
  1019. X.SH BUGS
  1020. X.PP
  1021. X.I Sendoprd
  1022. Xwill not run if the busy lock exists.
  1023. X.PP
  1024. X.I Sendoprd
  1025. Xassumes the operator's terminal is X-based.
  1026. X.PP
  1027. XThe operator's Xresources should be configured to allow messages to be
  1028. Xreceived, ie.
  1029. X.I "xhost +"
  1030. Xshould be set, and in the operator's 
  1031. X.I .xdefaults
  1032. Xfile, there should be a line similar to:
  1033. X.sp
  1034. X.nf
  1035. X     Important.Geometry:    800x500+700+200  
  1036. X.fi
  1037. X.sp
  1038. Xto indicate the size and location of the message window on the Xterminal.
  1039. X.PP
  1040. X.I Sendoprd
  1041. Xdoes not wrap long lines around to the next line.  If a sentence is
  1042. Xlonger than the window size, the end of the line is cut off.  
  1043. X.PP
  1044. XAfter the operator reads the message, the "okay" from 
  1045. X.I xmessage 
  1046. Xis echoed back the to the sender.
  1047. X.SH SEE ALSO
  1048. Xsendopr(l), xmessage(1)
  1049. X.SH AUTHOR
  1050. X.PP
  1051. XHyman Wong and Reg Quinton, CCS, UWO.
  1052. END_OF_FILE
  1053.   if test 2989 -ne `wc -c <'sendoprd.man'`; then
  1054.     echo shar: \"'sendoprd.man'\" unpacked with wrong size!
  1055.   fi
  1056.   # end of 'sendoprd.man'
  1057. fi
  1058. if test -f 'tcpopen.c' -a "${1}" != "-c" ; then 
  1059.   echo shar: Will not clobber existing file \"'tcpopen.c'\"
  1060. else
  1061.   echo shar: Extracting \"'tcpopen.c'\" \(1983 characters\)
  1062.   sed "s/^X//" >'tcpopen.c' <<'END_OF_FILE'
  1063. X/*
  1064. X* $Author: reggers $
  1065. X* $Date: 1992/06/10 14:02:26 $
  1066. X* $Header: /usr/src/usr.local/utilities/sendopr/RCS/tcpopen.c,v 1.2 1992/06/10 14:02:26 reggers Exp $
  1067. X*
  1068. X* Abstract: open a connection to a host/service
  1069. X*
  1070. X* Original work by Reg Quinton; 30 Apr 1991
  1071. X*/
  1072. X
  1073. X#include    <stdio.h>
  1074. X#include    <signal.h>
  1075. X#include    <setjmp.h>
  1076. X#include    <sys/types.h>
  1077. X#include    <sys/socket.h>
  1078. X#include    <netinet/in.h>
  1079. X#include    <netdb.h>
  1080. X
  1081. X#ifndef SIGRET
  1082. X#define SIGRET  int
  1083. X#endif
  1084. X
  1085. X#ifndef TIMEOUT
  1086. X#define TIMEOUT 60
  1087. X#endif
  1088. X
  1089. Xstatic    jmp_buf    env;    /* for jump back */
  1090. X
  1091. Xstatic
  1092. XSIGRET    catcher()
  1093. X{    longjmp(env,1);    }
  1094. X
  1095. X/* open a connection to some service on some host */
  1096. X
  1097. Xint    tcpopen(host,service)
  1098. Xchar    *service, *host;
  1099. X{       int     unit;
  1100. Xstatic  struct  sockaddr_in     sin;
  1101. Xstatic  struct  servent         *sp;
  1102. Xstatic  struct  hostent         *hp;
  1103. X    SIGRET    (*oldsig)();
  1104. X
  1105. X    oldsig=signal(SIGALRM,catcher);
  1106. X
  1107. X    if (setjmp(env))
  1108. X    {    signal(SIGALRM,oldsig);    alarm(0);
  1109. X        return(-1);
  1110. X    }
  1111. X
  1112. X    alarm(TIMEOUT);
  1113. X
  1114. X       /* this is straight line lifting from the 4.2BSD IPC Primer
  1115. X           example of section 3.5... the famous figure 1 */
  1116. X
  1117. X        if ((sp=getservbyname(service,"tcp")) == NULL)
  1118. X        {       fprintf(stderr,"Oops ... no such service \"%s\"\n",service);
  1119. X                return(-1);
  1120. X        }
  1121. X
  1122. X        if ((hp=gethostbyname(host)) == NULL)
  1123. X        {       fprintf(stderr,"Oops ... unknown host \"%s\"\n",host);
  1124. X                return(-1);
  1125. X        }
  1126. X
  1127. X        bzero((char *)&sin, sizeof(sin));
  1128. X        bcopy(hp->h_addr,(char *)&sin.sin_addr,hp->h_length);
  1129. X        sin.sin_family=hp->h_addrtype;
  1130. X        sin.sin_port=sp->s_port;
  1131. X
  1132. X        if ((unit=socket(AF_INET,SOCK_STREAM,0)) < 0)
  1133. X        {       fprintf(stderr,"Oops ... tcp/ip cannot open socket\n");
  1134. X                return(-1);
  1135. X        }
  1136. X
  1137. X        if (connect(unit,(char *)&sin,sizeof(sin)) < 0)
  1138. X        {       fprintf(stderr,"Oops ... tcp/ip cannot connect to server\n");
  1139. X                return(-1);
  1140. X        }
  1141. X
  1142. X    signal(SIGALRM,oldsig);    alarm(0);
  1143. X    return(unit);
  1144. X}
  1145. END_OF_FILE
  1146.   if test 1983 -ne `wc -c <'tcpopen.c'`; then
  1147.     echo shar: \"'tcpopen.c'\" unpacked with wrong size!
  1148.   fi
  1149.   # end of 'tcpopen.c'
  1150. fi
  1151. echo shar: End of archive 1 \(of 1\).
  1152. cp /dev/null ark1isdone
  1153. MISSING=""
  1154. for I in 1 ; do
  1155.     if test ! -f ark${I}isdone ; then
  1156.     MISSING="${MISSING} ${I}"
  1157.     fi
  1158. done
  1159. if test "${MISSING}" = "" ; then
  1160.     echo You have the archive.
  1161.     rm -f ark[1-9]isdone
  1162. else
  1163.     echo You still must unpack the following archives:
  1164.     echo "        " ${MISSING}
  1165. fi
  1166. exit 0
  1167. exit 0 # Just in case...
  1168.