home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume11 / bsmtp < prev    next >
Internet Message Format  |  1987-08-27  |  45KB

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v11i021:  Batch SMTP program
  5. Message-ID: <1245@uunet.UU.NET>
  6. Date: 28 Aug 87 13:03:19 GMT
  7. Sender: Unknown@uunet.UU.NET
  8. Organization: UUNET Communications Services, Arlington, VA
  9. Lines: 1494
  10. Approved: rs@uunet.UU.NET
  11.  
  12. Submitted-by: David Herron E-Mail Hack <david@ms.uky.edu>
  13. Posting-number: Volume 11, Issue 21
  14. Archive-name: bsmtp
  15.  
  16.  
  17. BSMTP stands for "Batch Simple Mail Transfer Protocol".  It is a form
  18. of SMTP for use over a network where you communicate by way of files
  19. rather than interactive channels.  Both the UUCP network and BITNET are
  20. file oriented networks.  This protocol was originally developed for
  21. BITNET by E. Alan Crosswell of Columbia University, and is documented
  22. in "CUVMB BSMTP" which is available from NETSERVE's on BITNET.  I've
  23. included a copy of CUVMB BSMTP in this distribution; it is in it's
  24. original form (complete with fortran carraige control).  The idea is to
  25. take the same sorts of things the sender says in an SMTP transaction,
  26. put it all in a file, and send that to the reciever.
  27.  
  28. I'd sent you a copy of this a few months ago (April?) just
  29. before you changed jobs.  Apparently it got lost in the shuffle,
  30. but no matter as it allowed for a couple of bugs to be fixed.
  31.  
  32.     -- David
  33. [  This is pitifully late because I seem to be unable to get E-mail to
  34.    David, sigh.  --r$ ]
  35.  
  36. #! /bin/sh
  37. : This is a shell archive, meaning:
  38. : 1. Remove everything above the '#! /bin/sh' line.
  39. : 2. Save the resulting text in a file.
  40. : 3. Execute the file with /bin/sh '(not csh)' to create the files:
  41. :    'README'
  42. :    'CUVMB.BSMTP'
  43. :    'Makefile'
  44. :    'copyright'
  45. :    'ibsmtp.1'
  46. :    'ibsmtp.c'
  47. :    'sendbsmtp'
  48. : This archive created: 'Mon Jul 13 19:10:13 1987'
  49. : By:    'David Herron -- Resident E-mail Hack ()'
  50. export PATH; PATH=/bin:$PATH
  51. echo shar: extracting "'README'" '(5972 characters)'
  52. if test -f 'README'
  53. then
  54.     echo shar: will not over-write existing file "'README'"
  55. else
  56. sed 's/^X//'  >'README' <<'SHAR_EOF'
  57. X(C) Copyright 1987,
  58. X    David Herron and the University of Kentucky Computer Science Dept.
  59. X
  60. XRights are granted to use, distribute, modify, and distribute
  61. Xmodifications of this work, provided that you subscribe to
  62. Xbsmtp-users@ms.uky.edu and describe there any modifications you 
  63. Xmake.
  64. X---
  65. X
  66. XThis package of files contains my BSMTP programs.
  67. X
  68. XBSMTP stands for "Batch Simple Mail Transfer Protocol".  It is a form
  69. Xof SMTP for use over a network where you communicate by way of files
  70. Xrather than interactive channels.  Both the UUCP network and BITNET are
  71. Xfile oriented networks.  This protocol was originally developed for
  72. XBITNET by E. Alan Crosswell of Columbia University, and is documented
  73. Xin "CUVMB BSMTP" which is available from NETSERVE's on BITNET.  I've
  74. Xincluded a copy of CUVMB BSMTP in this distribution; it is in it's
  75. Xoriginal form (complete with fortran carraige control).  The idea is to
  76. Xtake the same sorts of things the sender says in an SMTP transaction,
  77. Xput it all in a file, and send that to the reciever.
  78. X
  79. XExample:
  80. X
  81. XHELO sending-domain
  82. XMAIL FROM: <reverse-path>    # <path> is a regular rfc-822 route/addr
  83. XRCPT TO: <forward-path>
  84. X   ...
  85. XDATA
  86. X   ...  RFC-822 style message (preferably) ...
  87. X.
  88. XQUIT
  89. X
  90. XThe other half of the conversation is to be returned to the sending
  91. Xprocess.  Assumably the sending process will look through the file and
  92. Xsee if there are error codes, and return an error message to the human
  93. Xsender if there are any.  To aid in this, Crosswell added two commands
  94. Xto the SMTP command set, "TICK <id-number>" and "VERBOSE {ON,OFF}".
  95. XThe id-number for the TICK command isn't the Message-ID:, but is
  96. Xsomething else and should be used to get back the message when an error
  97. Xreply comes back.  The VERBOSE command controls the verbosity of the
  98. Xreply file.
  99. X
  100. XThe TICK and VERBOSE commands are seen and ignored because we don't
  101. Xgenerate the reply file.  Instead we just give the message to the
  102. Xmail system and let it generate error messages as necessary.  This
  103. Xis a policy decision that Crosswell saw in a different light than
  104. XI saw it.  I do not know his reasoning behind deciding to generate
  105. Xreply files; possibly to keep the SMTP model as closely as possible;
  106. Xpossibly the crudeness of the systems at the time (1982).  Nevertheless
  107. XI don't see any use for reply files so long as your underlying mail
  108. Xsystem is good, and can generate error messages back to the original
  109. Xsender as necessary.
  110. X
  111. XThe other "known difference" is that RFC-821 specifies that a
  112. XReturn-Path: header be added to the beginning of the message, and that
  113. Xeach host to handle the message add themselves to the beginning of the
  114. XReturn-Path:.  Back in the dark ages when RFC-821 was written, that was
  115. Xprobably a useful thing to do.  Nowadays that isn't so useful since
  116. Xdomains point exactly at the intended host without need to be able to
  117. Xtrace routes back through the network in order to reply.
  118. X
  119. X
  120. X
  121. X
  122. X
  123. XHOW TO USE "ibsmtp"
  124. X
  125. XRight now I'm only using it for receiving BSMTP from BITNET.  I hacked
  126. Xon urep until we weren't using simple any more and using ibsmtp instead.
  127. X(Basically, the hacking involved changes in profile() in daemon/dafile.c
  128. Xand in mailer/damail.c, the sort of changes necessary should be obvious
  129. Xonce you've gotten to those sections of the code).
  130. X
  131. XOn BITNET, BSMTP files arrive in "pure" form.
  132. X
  133. XIn RFC-976, Mark suggests a different form for using BSMTP.
  134. XYou generate a UUCP envelope and RFC-822 envelope for a regular
  135. Xmessage headed for b-smtp@some.site.somewhere.  The body of
  136. Xthis message contains a BSMTP envelope with #'s prepended to
  137. Xeach line.  I might argue with some of his reasoning in deciding
  138. Xthat is the way to do this, however it is the documented method
  139. Xand will definitely do the job.
  140. X
  141. XYet this still leaves us with the problem of using BSMTP.  We will
  142. Xhave to have some way of knowing who can do BSMTP.  We will have
  143. Xto come up with a way for generating routes to the sites which
  144. Xcan do BSMTP.  Also we will have to know what domains the sites
  145. Xwho can do BSMTP can service.
  146. X
  147. XAfter a few minutes thought it seems that we really need to meld this
  148. Xin with the map in some way.  A possibility is to set a special cost of
  149. XBSMTP which isn't really a cost, as in:
  150. X
  151. Xsite    .edu(BSMTP), .gov(BSMTP), ...
  152. X
  153. Xcould automagically generate a path ".edu ...!site!b-smtp".
  154. X
  155. XI think that a few people will want to implement bsmtp immediately.
  156. X(In fact, if I had someone who wanted to do that I'd be happy go ahead
  157. Xand implement it on our uucp side right now).  BUT those sites will
  158. Xlikely be spread out meaning we'd have to make extra links just to do
  159. Xbsmtp over, or have some way to get across the network.  To get started
  160. Xit will work to have hand generated routes and the like, but if it
  161. Xgrows big enough we'll want to have some sort of tools to help out.
  162. X
  163. X
  164. X
  165. XWHY YOU WANT TO USE "ibsmtp"
  166. X
  167. XThe main reason you want to use BSMTP format in your mail is
  168. Xto avoid sending addresses through command lines, and the resultant
  169. Xmucking that the shell can do.  The addresses are hidden in the
  170. XBSMTP file which avoids handling by the shell, for most cases.
  171. X
  172. XThe other reason for using BSMTP is to bring the UUCP world
  173. Xcloser to using domains.
  174. X
  175. X
  176. X
  177. XFUTURE NEEDS
  178. X
  179. X1) Need to have this running under uucp systems.
  180. X2) Need to fix up an rmail which will handle b-smtp.  I think that
  181. X   it would be better to hack rmail to look at the address to see
  182. X   if it is b-smtp rather than send it on into the mail system.
  183. X   Sending it into the mail system will be extra overhead which
  184. X   could get nasty if this stuff ever gets used a lot.
  185. X3) Tools to help us get bsmtp stuff across the net.
  186. X4) Also, some way of knowing the right bsmtp capable place to send
  187. X   things for particular domains to.
  188. X5) "obsmtp" to create bsmtp packages.  Right now I've got a silly
  189. X   shell script which can be used.
  190. X6) A discussion group somewhere.  To get the ball rolling I've created
  191. X   an alias here "bsmtp-users" and "bsmtp-users-request".  The first
  192. X   is for discussion and the second is for administrivia.
  193. X
  194. SHAR_EOF
  195. if test 5972 -ne "`wc -c < 'README'`"
  196. then
  197.     echo shar: error transmitting "'README'" '(should have been 5972 characters)'
  198. fi
  199. fi # end of overwriting check
  200. echo shar: extracting "'CUVMB.BSMTP'" '(12346 characters)'
  201. if test -f 'CUVMB.BSMTP'
  202. then
  203.     echo shar: will not over-write existing file "'CUVMB.BSMTP'"
  204. else
  205. sed 's/^X//'  >'CUVMB.BSMTP' <<'SHAR_EOF'
  206. X0
  207. X0
  208. X0
  209. X0
  210. X0
  211. X                     BATCH SIMPLE MAIL TRANSFER PROTOCOL
  212. X+                    BATCH SIMPLE MAIL TRANSFER PROTOCOL
  213. X+                    BATCH SIMPLE MAIL TRANSFER PROTOCOL
  214. X0
  215. X0
  216. X0
  217. X0
  218. X0
  219. X0
  220. X0
  221. X0
  222. X0
  223. X0
  224. X                              E. Alan Crosswell
  225. X0            Columbia University Center for Computing Activities
  226. X0
  227. X0
  228. X0
  229. X0
  230. X0
  231. X0
  232. X0         Prepared for presentation at BITNET programmers' meeting
  233. X0
  234. X                              13 September 1982
  235. X1                                                                          1
  236. X0
  237. X 1. Acknowledgements
  238. X+1. Acknowledgements
  239. X+1. Acknowledgements
  240. X0                                                                 ______
  241. X+  The following paper is based on electronic mail discussions on BITNET and
  242. X0original  ideas for a Batch SMTP implementation developed by Mike O'Dell on
  243. X0_______
  244. X+ARPAnet.  Thanks to Greg Minshall for making Mike's ideas known.
  245. X0
  246. X02. Introduction
  247. X+2. Introduction
  248. X+2. Introduction
  249. X0  SMTP [1] is an interactive protocol that defines  a  transaction  between
  250. X0two  mail transport servers.  One is defined to be the sender and the other
  251. X0the recipient.
  252. X0
  253. X             1      2
  254. X   Using RSCS , UUCP , or any other store-and-forward transfer system  where
  255. X0   ____
  256. X+a  file  is  the  smallest unit of transmission it is clearly impossible to
  257. X0maintain such a full-duplex transaction.  In RSCS, only files may  be  used
  258. X0to communicate between service machines and no guarantee can be made of the
  259. X0order  of arrival of one file with respect to another.  Also, communication
  260. X0with other than VM systems is required.  Systems connected  via  HASP  SML,
  261. X0NJE/NJI and other links exist (MVS, Unix, Tops-20, etc.).
  262. X0
  263. X0  Why  then  should SMTP be used?  Maybe it shouldn't.  However, since ARPA
  264. X0supports it, it  will  be  well  defined  and  understood  by  the  largest
  265. X0internet.    Also,  it  seems relatively straightforward to create programs
  266. X0that will take a Batch SMTP (BSMTP) file and pass  it  to  a  SMTP  system,
  267. X0
  268. X0_______________
  269. X0  1
  270. X    IBM VM/370 Remote Spooling Communications Subsystem
  271. X   2
  272. X    Unix to Unix Communication Program
  273. X1                                                                          2
  274. X0
  275. X simulating a real SMTP hookup.
  276. X0
  277. X03. Batch SMTP operation
  278. X+3. Batch SMTP operation
  279. X+3. Batch SMTP operation
  280. X0  BSMTP uses seperate files for whole sections of a transaction rather than
  281. X0each  line.   The idea is to create a list of commands that would be issued
  282. X0assuming all previous commands had received OK replies.   This  transaction
  283. X0log  could  then  be sent to the receiver BSMTP server which reads the file
  284. X0and logs its responses.  The response log is then returned, etc.
  285. X0
  286. X0  An example of an SMTP transaction is in in figure 1 and an example of the
  287. X0equivalent BSMTP transaction is in figures 2 and 3 below.
  288. X0    S: HELO CUVMB.BITNET                   ! begin session
  289. X     R: 250 CUVMA.DECNET                    ! acknowledgement and ID
  290. X     S: MAIL FROM:<EACUS@CUVMB.BITNET>      ! request to send mail
  291. X     R: 250 OK                              ! receiver agrees to accept
  292. X     S: RCPT TO:<AC2US@CUVMA.BITNET>        ! recipient #1 is named
  293. X     R: 250 OK                              ! receiver will do it
  294. X     S: RCPT TO:<FOO@CUVMA.BITNET>          ! recipient #2 is named
  295. X     R: 551 No such user                    ! denied this one
  296. X     S: DATA                                ! ready to send data
  297. X     R: Start mail input, end with record containing only "."
  298. X     Date: Monday, 13-Sep-82 10:32 EST
  299. X     From: Alan Crosswell <EACUS@CUVMB>
  300. X     Subject: Hello
  301. X     To: AC2US@CUVMA
  302. X0    Hello there....
  303. X     .
  304. X0
  305. X                     Figure 1:
  306. X+                    Figure 1:
  307. X+                    Figure 1:   Sample SMTP transaction
  308. X1                                                                          3
  309. X0
  310. X     HELO CUVMB.BITNET
  311. X     MAIL FROM:<EACUS@CUVMB.BITNET>
  312. X     RCPT TO:<AC2US@CUVMA.BITNET>
  313. X     RCPT TO:<FOO@CUVMA.BITNET>
  314. X     DATA
  315. X     Date: Monday, 13-Sep-82 10:32 EST
  316. X     From: Alan Crosswell <EACUS@CUVMB>
  317. X     Subject: Hello
  318. X     To: AC2US@CUVMA
  319. X0    Hello there....
  320. X     .
  321. X     QUIT
  322. X0
  323. X                 Figure 2:
  324. X+                Figure 2:
  325. X+                Figure 2:   BSMTP: File from CUVMB to CUVMA
  326. X0
  327. X     220 CUVMA.BITNET Batch Simple Mail Transfer Service Ready
  328. X     250 CUVMA.BITNET
  329. X     250 OK
  330. X     250 OK
  331. X     551 No such user
  332. X     354 Start mail input.  End with "."
  333. X     250 OK
  334. X     221 CUVMA.BITNET Service closing transmission...
  335. X0
  336. X                 Figure 3:
  337. X+                Figure 3:
  338. X+                Figure 3:   BSMTP: File from CUVMA to CUVMB
  339. X0
  340. X04. Modifications to SMTP syntax
  341. X+4. Modifications to SMTP syntax
  342. X+4. Modifications to SMTP syntax
  343. X0  How  does the server on CUVMB in the preceding example know which file in
  344. X0its reader is the reply to which file it sent?  There's no way to  be  sure
  345. X0unless  some  sort  of  extra identification is imbedded in the files.  The
  346. X0following proposed additions to the SMTP commands would solve this and  the
  347. X0problem of coordinating processing of replies:
  348. X1                                                                          4
  349. X0
  350. X 4.1. Ticket command
  351. X+4.1. Ticket command
  352. X+4.1. Ticket command
  353. X0
  354. X     TICK
  355. X+    TICK
  356. X+    TICK <ticket-id>
  357. X0
  358. X        ______
  359. X+  The  Ticket  command  is  used to mark a file with additional identifying
  360. X0information.  This would be a unique message indentifier generated  by  the
  361. X0                                     ______
  362. X+sending BSMTP system.  By use of the ticket, the BSMTP sender would be able
  363. X0to identify a later BSMTP reply.
  364. X0
  365. X 4.2. Verbose command
  366. X+4.2. Verbose command
  367. X+4.2. Verbose command
  368. X0
  369. X     
  370. X             ON
  371. X+            ON
  372. X+            ON
  373. X     VERB
  374. X+    VERB
  375. X+    VERB
  376. X             OFF
  377. X+            OFF
  378. X+            OFF
  379. X     
  380. X0
  381. X       _______
  382. X+  The Verbose command solves the problem of coordinating BSMTP transactions
  383. X0further  by  specifying  that  all  commands received by the receiver BSMTP
  384. X0system be echoed in its reply along with its usual reply codes  (VERB  ON).
  385. X0Data  other  than  that  on  command  lines need not be echoed, so the file
  386. X0overhead is not substantial.
  387. X0
  388. X 4.3. Advantages
  389. X+4.3. Advantages
  390. X+4.3. Advantages
  391. X0         ______     _______                             ______
  392. X+  Use of Ticket and Verbose has several advantages, The ticket  provides  a
  393. X0unique identifier that the sender can use to keep track of the files it has
  394. X0shipped.   When a reply arrives, the sender simply looks up the information
  395. X0                                ______
  396. X+it stored when it generated the ticket and uses the information  to  inform
  397. X0any  interested parties (the person who sent the mail) of the status of the
  398. X0request.
  399. X1                                                                          5
  400. X0
  401. X               _______
  402. X+  The  use of verbose takes the burden off the sender to remember and later
  403. X0synchronize the commands it sent with the replies it  receives.    Assuming
  404. X0the  sender  trusts  the  replying BSMTP system, it has all the information
  405. X0needed in the proper order.  This information could very easily be  "piped"
  406. X0into a program that simulates the SMTP full-duplex interaction.
  407. X0
  408. X0  A  very simple sender implementation would not even have to keep track of
  409. X0_______                _______
  410. X+tickets as long as the verbose information is supplied to it.
  411. X0
  412. X05. Example of BSMTP operations
  413. X+5. Example of BSMTP operations
  414. X+5. Example of BSMTP operations
  415. X0  A complete example would be as follows:
  416. X0
  417. X    1. The CUVMB mailer receives a file from a local user to be sent to
  418. X       a user at CUVMA.
  419. X0               ______
  420. X+   2. A unique ticket is created and a file is punched to CUVMA.   The
  421. X       ______
  422. X+      ticket is stored for later recall.
  423. X0   3. The CUVMA mailer receives the file from CUVMB.
  424. X0   4. Mail is sent to the CUVMA user.
  425. X0         ________                                               ______
  426. X+   5. A  verbsose  reply  file  is generated which contains the ticket
  427. X       supplied by CUVMB and is punched to the CUVMB mailer.
  428. X0   6. The CUVMB mailer receives the file.
  429. X0   7. The file is recognized as a reply rather than an  original  file
  430. X       sent  from  CUVMA  by  the  presence  of reply codes rather than
  431. X       commands.
  432. X0   8. Each code 250 line is read and skipped.
  433. X0   9. Each code 050 line (the echoed  command)  is  processed  to  the
  434. X                                              TICK
  435. X+                                             TICK
  436. X+      degree  desired.    In  this case, the TICK is found and used to
  437. X                  ______
  438. X+      access the ticket that was previously saved.
  439. X0  10. Other code 050 lines and their replies  are  processed  and  the
  440. X                                            _____
  441. X+      appropriate  action  is  taken (i.e. EACUS is informed that user
  442. X       ___
  443. X+      FOO was not found).
  444. X1                                                                          6
  445. X0
  446. X     HELO CUVMB.BITNET
  447. X     VERB ON
  448. X     TICK 0001
  449. X     MAIL FROM:<EACUS@CUVMB.BITNET>
  450. X     RCPT TO:<AC2US@CUVMA.BITNET>
  451. X     RCPT TO:<FOO@CUVMA.BITNET>
  452. X     DATA
  453. X     Date: Monday, 13-Sep-82 10:32 EST
  454. X     From: Alan Crosswell <EACUS@CUVMB>
  455. X     Subject: Hello
  456. X     To: AC2US@CUVMA
  457. X0    Hello there....
  458. X     .
  459. X     QUIT
  460. X0
  461. X                 Figure 4:
  462. X+                Figure 4:
  463. X+                Figure 4:   BSMTP: file generated by sender
  464. X0
  465. X     220 CUVMA.BITNET Batch Simple Mail Transfer Service Ready
  466. X     250 CUVMA.BITNET
  467. X     050 VERB ON
  468. X     250 OK
  469. X     050 TICK 0001
  470. X     250 OK
  471. X     050 MAIL FROM:<EACUS@CUVMB.BITNET>
  472. X     250 OK
  473. X     050 RCPT TO:<AC2US@CUVMA.BITNET>
  474. X     250 OK
  475. X     050 RCPT TO:<FOO@CUVMA.BITNET>
  476. X     551 No such user
  477. X     050 DATA
  478. X     354 Start mail input.  End with "."
  479. X     250 OK
  480. X     050 QUIT
  481. X     221 CUVMB.BITNET closing transmission...
  482. X0
  483. X                Figure 5:
  484. X+               Figure 5:
  485. X+               Figure 5:   BSMTP: file returned by recipient
  486. X0
  487. X06. Compatibility with SMTP
  488. X+6. Compatibility with SMTP
  489. X+6. Compatibility with SMTP
  490. X0       ______      _______
  491. X+  The  Ticket  and Verbose commands and 050 reply code are additions on top
  492. X0of the current SMTP specification.  Assuming that they would be ignored  by
  493. X0                                                   _______
  494. X+an SMTP process, compatibility is maintained.  The Verbose command has even
  495. X0been suggested as a debugging aid for SMTP implementers.
  496. X1                                                                          7
  497. X0
  498. X                                 REFERENCES
  499. X+                                REFERENCES
  500. X+                                REFERENCES
  501. X0
  502. X [1]   Jonathan B. Postel.
  503. X       ______ ____ ________ ________
  504. X+      Simple Mail Transfer Protocol.
  505. X       ARPANET Request for Comments, No. 821; Information Sciences
  506. X          Institute, University of Southern California, 4676 Admirality Way,
  507. X          Marina del Rey, California 90291, 1982.
  508. X1                                                                          i
  509. X0
  510. X Table of Contents
  511. X+Table of Contents
  512. X+Table of Contents
  513. X0     1. Acknowledgements                                                  1
  514. X      2. Introduction                                                      1
  515. X      3. Batch SMTP operation                                              2
  516. X      4. Modifications to SMTP syntax                                      3
  517. X           4.1. Ticket command                                             4
  518. X           4.2. Verbose command                                            4
  519. X           4.3. Advantages                                                 4
  520. X      5. Example of BSMTP operations                                       5
  521. X      6. Compatibility with SMTP                                           6
  522. X1                                                                         ii
  523. X0
  524. X List of Figures
  525. X+List of Figures
  526. X+List of Figures
  527. X0     Figure 1:
  528. X+     Figure 1:
  529. X+     Figure 1:   Sample SMTP transaction                                  2
  530. X      Figure 2:
  531. X+     Figure 2:
  532. X+     Figure 2:   BSMTP: File from CUVMB to CUVMA                          3
  533. X      Figure 3:
  534. X+     Figure 3:
  535. X+     Figure 3:   BSMTP: File from CUVMA to CUVMB                          3
  536. X      Figure 4:
  537. X+     Figure 4:
  538. X+     Figure 4:   BSMTP: file generated by sender                          6
  539. X      Figure 5:
  540. X+     Figure 5:
  541. X+     Figure 5:   BSMTP: file returned by recipient                        6
  542. SHAR_EOF
  543. if test 12346 -ne "`wc -c < 'CUVMB.BSMTP'`"
  544. then
  545.     echo shar: error transmitting "'CUVMB.BSMTP'" '(should have been 12346 characters)'
  546. fi
  547. fi # end of overwriting check
  548. echo shar: extracting "'Makefile'" '(1082 characters)'
  549. if test -f 'Makefile'
  550. then
  551.     echo shar: will not over-write existing file "'Makefile'"
  552. else
  553. sed 's/^X//'  >'Makefile' <<'SHAR_EOF'
  554. X# Makefile for BSMTP programs...
  555. X#
  556. X# Author: David Herron <david@ms.uky.edu>
  557. X#    University of Kentucky, CS Dept.
  558. X#    Patterson Office Tower, Room 915
  559. X#    Lexington, KY  40506-0027
  560. X#
  561. X# (C) Copyright 1987,
  562. X#     David Herron and the University of Kentucky Computer Science Dept.
  563. X# 
  564. X# Rights are granted to use, distribute, modify, and distribute
  565. X# modifications of this work, provided that you subscribe to
  566. X# bsmtp-users@ms.uky.edu and describe there any modifications you 
  567. X# make.
  568. X#
  569. X# Tue Apr 21 15:38:29 EST 1987
  570. X
  571. XDESTDIR=/usr/lib/rscs
  572. X
  573. Xall: ibsmtp
  574. X
  575. Xinstall: all $(DESTDIR)/ibsmtp
  576. X
  577. X$(DESTDIR)/ibsmtp: ibsmtp
  578. X    rm -f $(DESTDIR)/ibsmtp
  579. X    cp ibsmtp $(DESTDIR)/ibsmtp
  580. Xibsmtp: ibsmtp.o
  581. X    cc ibsmtp.o -o ibsmtp $(LDFLAGS)
  582. Xibsmtp.o: ibsmtp.c
  583. X    cc -c ibsmtp.c $(CFLAGS)
  584. X
  585. Xnotes:
  586. X    @echo
  587. X
  588. Xclean:
  589. X    rm -f *.o ibsmtp obsmtp a.out core
  590. X
  591. Xuninstall:
  592. X    rm -f $(DESTDIR)/ibsmtp
  593. X
  594. X# "addman" is a local command which basically copies the named
  595. X# file to /usr/man/manl ... but takes care of doing it right
  596. X# when we're doing it from the "wrong" host and it would fail
  597. X# due to the NFS.
  598. Xdoc:
  599. X    addman ibsmtp.1 1
  600. SHAR_EOF
  601. if test 1082 -ne "`wc -c < 'Makefile'`"
  602. then
  603.     echo shar: error transmitting "'Makefile'" '(should have been 1082 characters)'
  604. fi
  605. fi # end of overwriting check
  606. echo shar: extracting "'copyright'" '(286 characters)'
  607. if test -f 'copyright'
  608. then
  609.     echo shar: will not over-write existing file "'copyright'"
  610. else
  611. sed 's/^X//'  >'copyright' <<'SHAR_EOF'
  612. X(C) Copyright 1987,
  613. X    David Herron and the University of Kentucky Computer Science Dept.
  614. X
  615. XRights are granted to use, distribute, modify, and distribute
  616. Xmodifications of this work, provided that you subscribe to
  617. Xbsmtp-users@ms.uky.edu and describe there any modifications you 
  618. Xmake.
  619. SHAR_EOF
  620. if test 286 -ne "`wc -c < 'copyright'`"
  621. then
  622.     echo shar: error transmitting "'copyright'" '(should have been 286 characters)'
  623. fi
  624. fi # end of overwriting check
  625. echo shar: extracting "'ibsmtp.1'" '(1724 characters)'
  626. if test -f 'ibsmtp.1'
  627. then
  628.     echo shar: will not over-write existing file "'ibsmtp.1'"
  629. else
  630. sed 's/^X//'  >'ibsmtp.1' <<'SHAR_EOF'
  631. X.\" (C) Copyright 1987,
  632. X.\"     David Herron and the University of Kentucky Computer Science Dept.
  633. X.\" 
  634. X.\" Rights are granted to use, distribute, modify, and distribute
  635. X.\" modifications of this work, provided that you subscribe to
  636. X.\" bsmtp-users@ms.uky.edu and describe there any modifications you 
  637. X.\" make.
  638. X.\"
  639. X.TH IBSMTP 8 "April 20, 1987"
  640. X.UC 4
  641. X.SH NAME
  642. Xibsmtp \- Input BSMTP format mail into the mail system.
  643. X.SH SYNOPSIS
  644. X.B ibsmtp
  645. X[
  646. X.B -c
  647. Xmmdf-channel ] [
  648. X.B -d
  649. Xfile-name ] [
  650. X.B -D
  651. Xour-domain ] [ file ... ]
  652. X.br
  653. X.SH DESCRIPTION
  654. X.B Ibsmtp
  655. Xreads the specified files
  656. X(or standard input if there are no files given),
  657. Xand extracts the RFC-822 style messages embedded in the BSMTP information.
  658. XOnce the message (or messages) are extracted,
  659. Xit is handed over to the mail system for delivery.
  660. X.IP -c
  661. XThis specifies which mmdf channel to bring the mail in through.
  662. XThis only makes sense for mmdf sites.
  663. X.IP -d
  664. XThis enables debugging output to the named file.
  665. X.IP -D
  666. XSpecifies what the domain name of this host is.
  667. X.PP
  668. XOther arguments are taken to be BSMTP files,
  669. Xthe standard input is specified by saying just "-".
  670. X.SH "SEE ALSO"
  671. Xsendmail(8), recvprog(8), mail(1)
  672. X.br
  673. XBSMTP is documented in the file "CUVMB BSMTP",
  674. Xavailable on the NETSERV's on BITNET.
  675. X.SH BUGS
  676. XGiving the domain name on the command line is bogus.
  677. XWe should look in the environment somewhere,
  678. Xbut there is no standard place to look.
  679. X.PP
  680. XFor MMDF we use recvprog to put the message into the system,
  681. Xinstead of the mm_*() routines.
  682. XThis is for ease of implementation, and version 2
  683. Xmight use those routines.
  684. X.PP
  685. XInstead of specifying at compile time what mail system is
  686. Xon the host,
  687. Xthe program tries all of them in turn and uses the
  688. Xfirst one which works.
  689. SHAR_EOF
  690. if test 1724 -ne "`wc -c < 'ibsmtp.1'`"
  691. then
  692.     echo shar: error transmitting "'ibsmtp.1'" '(should have been 1724 characters)'
  693. fi
  694. fi # end of overwriting check
  695. echo shar: extracting "'ibsmtp.c'" '(16498 characters)'
  696. if test -f 'ibsmtp.c'
  697. then
  698.     echo shar: will not over-write existing file "'ibsmtp.c'"
  699. else
  700. sed 's/^X//'  >'ibsmtp.c' <<'SHAR_EOF'
  701. Xchar *ProgramId = "(C) Copyright 1987,\
  702. X    David Herron and the University of Kentucky Computer Science Dept.\n\
  703. X    ibsmtp Version 1.0";
  704. X
  705. X/*
  706. X * Rights are granted to use, distribute, modify, and distribute
  707. X * modifications of this work, provided that you subscribe to
  708. X * bsmtp-users@ms.uky.edu and describe there any modifications you 
  709. X * make.
  710. X */
  711. X
  712. X/*
  713. X * ibsmtp.c -- Input BSMTP style mail messages into the system.
  714. X *
  715. X * Originally written by David S. Herron, Thu Nov 20 16:47:29 EST 1986.
  716. X *
  717. X *    My E-mail addresses are:
  718. X *        {BITNET,UUCP}:   david@ukma
  719. X *        CSNET, Internet: david@ms.uky.edu
  720. X *
  721. X *--------------
  722. X * This is the first official release of my BSMTP programs.  They've
  723. X * been held up while mod.sources/comp.sources.unix were in flux,
  724. X * but that allowed for Sjoerd Mullender <sjoerd@cs.vu.nl> to find
  725. X * and fix a couple of bugs.  (Thanks muchly)!
  726. X *    David Herron, Mon Jul 13 19:08:04 EDT 1987
  727. X */
  728. X
  729. X#include <sys/types.h>
  730. X#include <time.h>
  731. X#include <stdio.h>
  732. X#include <ctype.h>
  733. X#include <sys/wait.h>
  734. X
  735. X/*
  736. X * Path names for the various possible mail daemons.
  737. X * If one fails, domail() tries the next one in line.
  738. X */
  739. X#define RECVPROG "/usr/mmdf/chans/recvprog"
  740. X#define SENDMAIL "/usr/lib/sendmail"
  741. X#define BINMAIL "/bin/mail"
  742. X
  743. Xextern char **environ;
  744. X
  745. Xchar *ReversePath = NULL;
  746. Xchar *Channel = NULL;
  747. Xchar *SendingDomain = NULL;
  748. Xchar *OurDomain = NULL;
  749. X
  750. X/*
  751. X * C PURISTS BEWARE!  This data structure is of a type which usually
  752. X * causes confusion.  "ForwardPaths" is being used as a list (char *)'s.
  753. X * Normally this would be declared as "char *a[size];" but I didn't
  754. X * want to leave a limit on the number of ForwardPaths.  ForwardPaths
  755. X * is manipulated ONLY in addpath().  Note the hook that if nForwardPaths
  756. X * is 0 but ForwardPaths points somewhere, that the memory allocated
  757. X * to it is free()'d.
  758. X */
  759. Xchar **ForwardPaths = (char **)NULL;
  760. Xint nForwardPaths = 0;
  761. X
  762. Xint Errors = 0;        /* bumped every time we have an error.
  763. X             * If we have some, then we exit with
  764. X             * an error status, and our calling shell
  765. X             * script will be able to save the output
  766. X             * for us.
  767. X             */
  768. X
  769. XFILE *dbgout;
  770. X
  771. X
  772. X/***********   First, some utility functions.    *****************/
  773. X
  774. X
  775. X/*
  776. X * arpadate() -- make a string saying what time it is as specified
  777. X * in RFC-822.  Note the year is %'d by 100 because the spec says
  778. X * that the year is a 2DIGIT.  Won't this cause problems in another
  779. X * 13 years or so?
  780. X *
  781. X * This routine was written on 4.3BSD, but using the SysVr3 manuals
  782. X * for reference.  In particluar, the 4.3 manuals claim that time()
  783. X * returns a long instead of a time_t.  Anyway, it works and it should
  784. X * work everywhere.
  785. X */
  786. Xchar *
  787. Xarpadate()
  788. X{
  789. X    time_t now;
  790. X    struct tm *tmnow;
  791. X    static char buf[BUFSIZ];
  792. X    extern time_t time();
  793. X    static char *days[] = 
  794. X        { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
  795. X    static char *months[] = 
  796. X        { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
  797. X          "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
  798. X
  799. X    now = time((long *)0);
  800. X    tmnow = gmtime(&now);
  801. X    (void) sprintf(buf, "%s, %d %s %d %02d:%02d:%02d GMT",
  802. X        days[tmnow->tm_wday], tmnow->tm_mday, months[tmnow->tm_mon],
  803. X        tmnow->tm_year % 100, tmnow->tm_hour, tmnow->tm_min,
  804. X        tmnow->tm_sec);
  805. X    return(buf);
  806. X}
  807. X
  808. X/*
  809. X * killnl(s) -- kill a newline in s.
  810. X */
  811. Xvoid
  812. Xkillnl(s)
  813. Xchar *s;
  814. X{    
  815. X    char *s2, *index();
  816. X
  817. X    if ((s2=index(s, '\n')) != NULL)
  818. X        *s2 = '\0';
  819. X}
  820. X
  821. X/*
  822. X * copystr(s) -- make a copy of the string.
  823. X */
  824. Xchar *
  825. Xcopystr(s)
  826. Xchar *s;
  827. X{
  828. X    char *rval, *malloc(), *strcpy();
  829. X
  830. X    if (!s)
  831. X        return((char *)NULL);
  832. X    rval = malloc((unsigned)(sizeof(char)*strlen(s)+1));
  833. X    return(strcpy(rval, s));
  834. X}
  835. X
  836. X/*
  837. X * copypath(s) -- make a copy of a string, but strip leading '<' 
  838. X * and trailing '>'.  (i.e. suitable for copying <path> out of 
  839. X * one of the BSMTP command lines.
  840. X */
  841. Xchar *
  842. Xcopypath(s)
  843. Xchar *s;
  844. X{
  845. X    char *rval, *s2, *index(), *malloc(), *strcpy();
  846. X
  847. X    if (!s)
  848. X        return(NULL);
  849. X    rval = malloc((unsigned)(strlen(s)+1));
  850. X    if ((s2=index(s, '<')) != NULL)
  851. X        (void) strcpy(rval, s2+1);
  852. X    else
  853. X        (void) strcpy(rval, s);
  854. X    if ((s2=index(rval, '>')) != NULL)
  855. X        *s2 = '\0';
  856. X    return(rval);
  857. X}
  858. X
  859. X/*
  860. X * stripsp(s) -- Strip out excess spacing from a string.
  861. X *        (Only from the front and back of the string).
  862. X */
  863. Xvoid
  864. Xstripsp(s)
  865. Xchar *s;
  866. X{
  867. X    char *outs, *ins;
  868. X
  869. X    if (!s)
  870. X        return;
  871. X    outs = s;
  872. X    ins = s;
  873. X    while (*ins != '\0') {
  874. X        if (*ins == '\t')
  875. X            *ins = ' ';
  876. X        if (*ins == ' ') {
  877. X            if (*(ins-1) != ' ' && outs != s)
  878. X                *outs++ = *ins;
  879. X        }
  880. X        else
  881. X            *outs++ = *ins;
  882. X        ins++;
  883. X    }
  884. X    *outs++ = '\0';
  885. X}
  886. X
  887. X
  888. X/*
  889. X * split(s) -- split a character string into its fields.
  890. X *
  891. X * The return value is a group of pointers into a pair of
  892. X * static areas.  The first (veclist) is a pointer to the 
  893. X * base of a vector of pointers which point at various parts
  894. X * of the second area (buf).  
  895. X *
  896. X * The upshot of that is:
  897. X *
  898. X *    1) Don't expect the data to remain after a call to split,
  899. X *       so be prepared to make a copy of it.
  900. X *    2) Be nice and don't muck with split()'s copy.
  901. X *
  902. X * Oh, one last thing.  Notice that the last element in veclist[]
  903. X * is marked by being NULL.
  904. X */
  905. Xchar **
  906. Xsplit(s)
  907. Xchar *s;
  908. X{
  909. X    static char *buf = (char *)NULL;
  910. X    static int buflen = 0;
  911. X    static char **veclist = (char **)NULL;
  912. X    int nvecs;
  913. X    int slen;
  914. X    register char *sp, *lastp, *s2;
  915. X    char *malloc(), *realloc(), *index();
  916. X
  917. X    if (!s)
  918. X        return((char **)NULL);
  919. X    if (veclist) {
  920. X        free((char *)veclist);
  921. X    }
  922. X    veclist = (char **)malloc((unsigned)(sizeof(char *)));
  923. X    veclist[0] = (char *)NULL;
  924. X    nvecs = 1;
  925. X    stripsp(s);
  926. X    slen = strlen(s);
  927. X    if (dbgout) fprintf(dbgout, "Original string \"%s\"\n", s);
  928. X    if (buflen < (slen+1)) {
  929. X        buflen = slen+1;
  930. X        if (buf)
  931. X            buf = realloc(buf, (unsigned)(sizeof(char)*buflen));
  932. X        else
  933. X            buf = malloc((unsigned)(sizeof(char)*buflen));
  934. X    }
  935. X    (void) strcpy(buf, s);
  936. X    for (lastp = sp = buf; *sp != '\0'; sp++) {
  937. X        if (*sp == ' ') {
  938. X            nvecs++;
  939. X            veclist = (char **)realloc((char *)veclist, 
  940. X                (unsigned)(sizeof(char *)*nvecs));
  941. X            (*(veclist+nvecs-1)) = (char *)NULL;
  942. X            (*(veclist+nvecs-2)) = lastp;
  943. X            *sp = '\0';
  944. X            if ((s2=index(lastp, '\n')) != NULL)
  945. X                *s2 = '\0';
  946. X            if (dbgout) 
  947. X                fprintf(dbgout, 
  948. X                    "Part %d \"%s\"\n", 
  949. X                    nvecs-2, veclist[nvecs-2]);
  950. X            lastp = sp+1;
  951. X        }
  952. X    }
  953. X    nvecs++;
  954. X    veclist = (char **)realloc((char *)veclist, 
  955. X        (unsigned)(sizeof(char *)*nvecs));
  956. X    veclist[nvecs-1] = (char *)NULL;
  957. X    veclist[nvecs-2] = lastp;
  958. X    if (dbgout) fprintf(dbgout, "Part %d \"%s\"\n", nvecs-2, lastp);
  959. X    return(veclist);
  960. X}
  961. X
  962. X/*
  963. X * lexequ(s1, s2) -- strcmp of s1 and s2, but ignoring case.
  964. X */
  965. Xint
  966. Xlexequ(s1, s2)
  967. Xregister char *s1, *s2;
  968. X{
  969. X    register char c1, c2;
  970. X
  971. X    if (dbgout) fprintf(dbgout, "lexequ(\"%s\", \"%s\")\n", s1, s2);
  972. X    if (!s1 && !s2)
  973. X        return(0);
  974. X    if (!s1 && s2)
  975. X        return(-1);
  976. X    if (s1 && !s2)
  977. X        return(1);
  978. X    while (*s1 && *s2) {
  979. X        if (islower(*s1))
  980. X            c1 = toupper(*s1);
  981. X        else
  982. X            c1 = *s1;
  983. X        if (islower(*s2))
  984. X            c2 = toupper(*s2);
  985. X        else
  986. X            c2 = *s2;
  987. X        /* printf("<%c,0%o> == <%c,0%o>?\n", c1, c1, c2, c2); */
  988. X        if (c1 != c2)
  989. X            break;
  990. X        s1++;
  991. X        s2++;
  992. X    }
  993. X    return(c1 - c2);
  994. X}
  995. X
  996. X/********     Next, specific stuff for bsmtp processing    *******/
  997. X
  998. X/*
  999. X * addpath(s) -- Add address in s to address list.
  1000. X */
  1001. Xvoid
  1002. Xaddpath(s)
  1003. Xchar *s;
  1004. X{
  1005. X    int i;
  1006. X    char *malloc(), *realloc();
  1007. X
  1008. X    if (!s)
  1009. X        return;
  1010. X    if (!ForwardPaths || nForwardPaths==0) {
  1011. X        if (ForwardPaths) {
  1012. X            for (i=0; ForwardPaths[i]; i++)
  1013. X                if (ForwardPaths[i])
  1014. X                    free(ForwardPaths[i]);
  1015. X            free((char *)ForwardPaths);
  1016. X        }
  1017. X        nForwardPaths = 1;
  1018. X        ForwardPaths = (char **)malloc((unsigned)(sizeof(char *)));
  1019. X        ForwardPaths[0] = copypath(s);
  1020. X        if (dbgout) fprintf(dbgout, "addpath(%s, 0)\n", ForwardPaths[0]);
  1021. X    }
  1022. X    else {
  1023. X        nForwardPaths++;
  1024. X        ForwardPaths = (char **)realloc((char *)ForwardPaths, 
  1025. X                    (unsigned)(sizeof(char *)*nForwardPaths));
  1026. X        ForwardPaths[nForwardPaths-1] = copypath(s);
  1027. X        if (dbgout) fprintf(dbgout, "addpath(%s, %d)\n", 
  1028. X            ForwardPaths[nForwardPaths-1], nForwardPaths-1);
  1029. X    }
  1030. X}
  1031. X
  1032. X/*
  1033. X * domail(f) -- Process that part of the input stream which is the
  1034. X * mail message (Between "DATA" and ".") and send it to the addresses
  1035. X * which have already been saved away.
  1036. X *
  1037. X * According to RFC821, lines in the DATA part which should have 
  1038. X * a leading "." have the dot doubled.  We need to remove the 
  1039. X * doubled dot here.
  1040. X */
  1041. Xint
  1042. Xdomail(f)
  1043. XFILE *f;
  1044. X{
  1045. X    FILE *tmpfil;
  1046. X    char fname[40], buf[BUFSIZ], **argv;
  1047. X    int argc, argp, i, pid;
  1048. X    union wait status;
  1049. X    extern char *mktemp();
  1050. X
  1051. X    (void) strcpy(fname, "/tmp/bsmtxtXXXXXX");
  1052. X    (void) mktemp(fname);
  1053. X    (void) close(creat(fname, 0644));
  1054. X    tmpfil = fopen(fname, "w");
  1055. X    fprintf(tmpfil, "Received: ");
  1056. X    if (SendingDomain)
  1057. X        fprintf(tmpfil, "from %s ", SendingDomain);
  1058. X    if (OurDomain)
  1059. X        fprintf(tmpfil, "by %s ", OurDomain);
  1060. X    if (ReversePath)
  1061. X        fprintf(tmpfil, "for %s ", ReversePath);
  1062. X    fprintf(tmpfil, "with BSMTP (1.0);\n\t%s\n", arpadate());
  1063. X    while (fgets(buf, BUFSIZ, f) != NULL) {
  1064. X        if (buf[0] == '.') {
  1065. X            if (buf[1] == '\n' || buf[1] == '\0')
  1066. X                break;
  1067. X            else {
  1068. X                (void) fputs(&(buf[1]), tmpfil);
  1069. X                if (dbgout) (void) fputs(&(buf[1]), dbgout);
  1070. X            }
  1071. X        }
  1072. X        else {
  1073. X            (void) fputs(&(buf[0]), tmpfil);
  1074. X            if (dbgout) (void) fputs(&(buf[0]), dbgout);
  1075. X        }
  1076. X    }
  1077. X    (void) fclose(tmpfil);
  1078. X    if (nForwardPaths == 0)
  1079. X        return(1);
  1080. X    if ((pid=fork()) == 0) {
  1081. X        /* In child process */
  1082. X
  1083. X        /* Need to exec a mailer with the file on stdin */
  1084. X        (void) fclose(stdin);
  1085. X        tmpfil = fopen(fname, "r");
  1086. X
  1087. X/* First try RECVPROG */
  1088. X        argc = 1 +             /* "recvprog" */
  1089. X            (Channel?2:0) +        /* -c Channel */
  1090. X            (SendingDomain?2:0) +    /* -h SendingDomain */
  1091. X            (ReversePath?2:0) +    /* -s ReversePath */
  1092. X            nForwardPaths;
  1093. X        argv = (char **)malloc((unsigned)(sizeof(char *)*(argc+1)));
  1094. X        argp = 0;
  1095. X        if (dbgout) fputs("recvprog", dbgout);
  1096. X        argv[argp++] = "recvprog";
  1097. X        if (Channel) {
  1098. X            argv[argp++] = "-c";
  1099. X            argv[argp++] = Channel;
  1100. X            if (dbgout) fputs(Channel, dbgout);
  1101. X        }
  1102. X        if (SendingDomain) {
  1103. X            argv[argp++] = "-h";
  1104. X            argv[argp++] = SendingDomain;
  1105. X            if (dbgout) fputs(SendingDomain, dbgout);
  1106. X        }
  1107. X        if (ReversePath) {
  1108. X            argv[argp++] = "-s";
  1109. X            argv[argp++] = ReversePath;
  1110. X            if (dbgout) fputs(ReversePath, dbgout);
  1111. X        }
  1112. X        for (i=0; i<nForwardPaths; i++) {
  1113. X            argv[argp++] = ForwardPaths[i];
  1114. X            if (dbgout) fputs(argv[argp-1], dbgout);
  1115. X        }
  1116. X        argv[argp++] = NULL;
  1117. X        if (dbgout) (void) fflush(dbgout);
  1118. X        execve(RECVPROG, argv, environ);
  1119. X
  1120. X        perror("recvprog failed, trying sendmail");
  1121. X
  1122. X/* Gosh, it didn't work, try SENDMAIL */
  1123. X        free((char *)argv);
  1124. X        argc = 1 +            /* "sendmail" */
  1125. X            (SendingDomain?1:0) +    /* "-ffrom" */
  1126. X            nForwardPaths;
  1127. X        argv = (char **)malloc((unsigned)(sizeof(char *)*(argc+1)));
  1128. X        argp = 0;
  1129. X        if (dbgout) fputs("sendmail", dbgout);
  1130. X        argv[argp++] = "sendmail";
  1131. X        if (ReversePath) {
  1132. X            /* We won't need buf below here */
  1133. X            (void) sprintf(buf, "-f%s", ReversePath);
  1134. X            argv[argp++] = buf;
  1135. X            if (dbgout) fputs(argv[argp-1], dbgout);
  1136. X        }
  1137. X        for (i=0; i<nForwardPaths; i++) {
  1138. X            argv[argp++] = ForwardPaths[i];
  1139. X            if (dbgout) fputs(argv[argp-1], dbgout);
  1140. X        }
  1141. X        argv[argp++] = NULL;
  1142. X        if (dbgout) (void) fflush(dbgout);
  1143. X        execve(SENDMAIL, argv, environ);
  1144. X
  1145. X        perror("sendmail failed, trying binmail");
  1146. X
  1147. X/* Gosh, it still didn't work... next try BINMAIL */
  1148. X        free((char *)argv);
  1149. X        argc = 1 +            /* "mail" */
  1150. X            (ReversePath?2:0) +    /* -f from */
  1151. X            nForwardPaths;
  1152. X        argv = (char **)malloc((unsigned)(sizeof(char *)*(argc+1)));
  1153. X        argp = 0;
  1154. X        if (dbgout) fputs("mail", dbgout);
  1155. X        argv[argp++] = "mail";
  1156. X        if (ReversePath) {
  1157. X            /* We won't need buf below here */
  1158. X            argv[argp++] = "-f";
  1159. X            argv[argp++] = ReversePath;
  1160. X            if (dbgout) fputs(argv[argp-1], dbgout);
  1161. X        }
  1162. X        for (i=0; i<nForwardPaths; i++) {
  1163. X            argv[argp++] = ForwardPaths[i];
  1164. X            if (dbgout) fputs(argv[argp-1], dbgout);
  1165. X        }
  1166. X        argv[argp++] = NULL;
  1167. X        if (dbgout) (void) fflush(dbgout);
  1168. X        execve(BINMAIL, argv, environ);
  1169. X
  1170. X        perror("binmail failed, nowhere to turn");
  1171. X
  1172. X        /* Gosh, it STILL didn't work, but we tried everything! */
  1173. X        if (dbgout) fputs("AAAARRRRGGGGHHHH!!!!", dbgout);
  1174. X        exit(1);
  1175. X    }
  1176. X    else {
  1177. X        /* In parent, first order of business is to wait for the child */
  1178. X        while (wait(&status) != pid)
  1179. X            ;
  1180. X        /*
  1181. X         * Need to do something in case status indicates error.
  1182. X         * Right now, it'll just disappear into thin air.
  1183. X         * Well, not exactly... 
  1184. X         */
  1185. X        (void) unlink(fname);
  1186. X        if (status.w_status != 0)
  1187. X            return(1);
  1188. X        else
  1189. X            return(0);
  1190. X    }
  1191. X    return(1);
  1192. X}
  1193. X
  1194. X
  1195. X
  1196. X
  1197. X/*
  1198. X * parse(f) -- parse the bsmtp thing on the given file.
  1199. X */
  1200. Xint
  1201. Xparse(f)
  1202. XFILE *f;
  1203. X{
  1204. X    char **words;
  1205. X    char buf[BUFSIZ];
  1206. X
  1207. Xinit_state:
  1208. X    if (fgets(buf, BUFSIZ, f) == NULL) {
  1209. X        /* early EOF */
  1210. X        goto seen_QUIT;
  1211. X    }
  1212. X    killnl(buf);
  1213. X    words = split(buf);
  1214. X    if (lexequ("HELO", words[0]) == 0) {
  1215. X        if (dbgout) 
  1216. X            fprintf(dbgout, "Howdy %s, how the hell are ya?\n", words[1]);
  1217. X        SendingDomain = copystr(words[1]);
  1218. X        goto seen_HELO;
  1219. X    }
  1220. X    else if (lexequ("NOOP", words[0]) == 0)
  1221. X        goto init_state;
  1222. X    else if (lexequ("RSET", words[0]) == 0)
  1223. X        goto init_state;
  1224. X    else
  1225. X        goto seen_ERROR;
  1226. X
  1227. Xseen_HELO:
  1228. X    if (fgets(buf, BUFSIZ, f) == NULL)
  1229. X        goto seen_QUIT;
  1230. X    killnl(buf);
  1231. X    words = split(buf);
  1232. X    if (lexequ("MAIL", words[0]) == 0) {
  1233. X        if (lexequ("FROM:", words[1])) {
  1234. X            /* MAIL FROM: <path> */
  1235. X            ReversePath = copypath(words[2]);
  1236. X        }
  1237. X        else {
  1238. X            /* MAIL FROM:<path> */
  1239. X            ReversePath = copypath(index(words[1], ':'));
  1240. X        }
  1241. X        if (dbgout) 
  1242. X            fprintf(dbgout, "Oh, you're sending from %s eh?\n", ReversePath);
  1243. X        goto seen_MAIL;
  1244. X    }
  1245. X    else if (lexequ("NOOP", words[0]) == 0)
  1246. X        goto seen_HELO;
  1247. X    else if (lexequ("TICK", words[0]) == 0)
  1248. X        goto seen_HELO;
  1249. X    else if (lexequ("VERB", words[0]) == 0)
  1250. X        goto seen_HELO;
  1251. X    else if (lexequ("QUIT", words[0]) == 0)
  1252. X        goto seen_QUIT;
  1253. X    else if (lexequ("RSET", words[0]) == 0)
  1254. X        goto seen_RSET;
  1255. X    else
  1256. X        goto seen_ERROR;
  1257. X
  1258. Xseen_MAIL:
  1259. X    if (fgets(buf, BUFSIZ, f) == NULL)
  1260. X        goto seen_QUIT;
  1261. X    killnl(buf);
  1262. X    words = split(buf);
  1263. X    if (lexequ("RCPT", words[0]) == 0) {
  1264. X        if (lexequ("TO:", words[1])) {
  1265. X            /* RCPT TO: <path> */
  1266. X            addpath(words[2]);
  1267. X        }
  1268. X        else {
  1269. X            /* RCTP TO:<path> */
  1270. X            addpath(index(words[1], ':'));
  1271. X        }
  1272. X        goto seen_MAIL;
  1273. X    }
  1274. X    else if (lexequ("DATA", words[0]) == 0)
  1275. X        goto seen_DATA;
  1276. X    else if (lexequ("RSET", words[0]) == 0)
  1277. X        goto seen_RSET;
  1278. X    else if (lexequ("NOOP", words[0]) == 0)
  1279. X        goto seen_MAIL;
  1280. X    else if (lexequ("TICK", words[0]) == 0)
  1281. X        goto seen_MAIL;
  1282. X    else if (lexequ("VERB", words[0]) == 0)
  1283. X        goto seen_MAIL;
  1284. X    else if (lexequ("QUIT", words[0]) == 0)
  1285. X        goto seen_QUIT;
  1286. X    else
  1287. X        goto seen_ERROR;
  1288. X
  1289. Xseen_RSET:
  1290. X    if (ReversePath) {
  1291. X        free(ReversePath);
  1292. X        ReversePath = (char *)NULL;
  1293. X    }
  1294. X    nForwardPaths = 0;
  1295. X    goto seen_HELO;
  1296. X
  1297. Xseen_DATA:
  1298. X    if (domail(f) != 0) {
  1299. X        if (dbgout) fprintf(dbgout, "oops\n");
  1300. X        Errors++;
  1301. X    }
  1302. X    goto seen_RSET;
  1303. X
  1304. Xseen_QUIT:
  1305. X    return(0);
  1306. X
  1307. Xseen_ERROR:
  1308. X    return(1);
  1309. X}
  1310. X
  1311. X
  1312. X/*
  1313. X * doparse(s) -- open file named in s and run parse on it.
  1314. X */
  1315. Xvoid
  1316. Xdoparse(s)
  1317. Xchar *s;
  1318. X{
  1319. X    char fname[BUFSIZ], buf[BUFSIZ];
  1320. X    FILE *infile;
  1321. X
  1322. X    if (!s) {
  1323. X        /*
  1324. X         * If the creat() fails then everything else will
  1325. X         * fail and the whole file will be dropped on the
  1326. X         * floor.  What's a mother to do?
  1327. X         */
  1328. X        (void) strcpy(fname, "/tmp/bsinXXXXXX");
  1329. X        (void) mktemp(fname);
  1330. X        (void) close(creat(fname, 0600));
  1331. X        infile = fopen(fname, "w");
  1332. X        while (fgets(buf, BUFSIZ, stdin) != NULL)
  1333. X            fputs(buf, infile);
  1334. X        (void) fclose(infile);
  1335. X        infile = fopen(fname, "r");
  1336. X    }
  1337. X    else {
  1338. X        infile = fopen(s, "r");
  1339. X    }
  1340. X    if (infile && parse(infile)) {
  1341. X        Errors++;
  1342. X    }
  1343. X    else {
  1344. X        (void) unlink(fname);
  1345. X    }
  1346. X}
  1347. X
  1348. X/*
  1349. X * main(argc, argv) -- main program.
  1350. X */
  1351. Xmain(argc, argv)
  1352. Xint argc;
  1353. Xchar **argv;
  1354. X{
  1355. X    int i;
  1356. X    int didanything = 0;
  1357. X
  1358. X    Errors = 0;
  1359. X    for (i=1; i<argc; i++) {
  1360. X        if (argv[i][0] == '-') {
  1361. X            switch (argv[i][1]) {
  1362. X            case '\0': /* "-"     read stdin */
  1363. X                if (dbgout) fprintf(dbgout, "doparse(NULL)\n");
  1364. X                didanything++;
  1365. X                doparse((char *)NULL);
  1366. X                break;
  1367. X            case 'c': /* -c channel    specify a channel */
  1368. X                if (dbgout)
  1369. X                    fprintf(dbgout, "Channel = %s\n", argv[i+1]);
  1370. X                Channel = argv[i+1];
  1371. X                i++;
  1372. X                break;
  1373. X            case 'd': /* -d file    enable debugging messages */
  1374. X                dbgout = fopen(argv[i+1], "w");
  1375. X                if (!dbgout) perror("opening dbgout");
  1376. X                i++;
  1377. X                break;
  1378. X            case 'D': /* -D domain    specify the local domain name */
  1379. X                if (dbgout)
  1380. X                    fprintf(dbgout, "OurDomain = %s\n", argv[i+1]);
  1381. X                OurDomain = argv[i+1];
  1382. X                i++;
  1383. X                break;
  1384. X            default: /* eh? */
  1385. X                if (dbgout)
  1386. X                    fprintf(dbgout, "Unknown option %c i=%d\n",
  1387. X                        argv[i][1], i);
  1388. X                break;
  1389. X            }
  1390. X        } 
  1391. X        else {        /* anything else is a file to parse */
  1392. X            if (dbgout) fprintf(dbgout, "doparse(%s)\n", argv[i]);
  1393. X            didanything++;
  1394. X            doparse(argv[i]);
  1395. X        }
  1396. X    }
  1397. X    if (!didanything) {
  1398. X        /* Specifying no files means to try stdin */
  1399. X        if (dbgout) fprintf(dbgout, "doparse(stdin)\n");
  1400. X        didanything++;
  1401. X        doparse((char *)NULL);
  1402. X    }
  1403. X    if (Errors > 0)
  1404. X        exit(1);
  1405. X    else
  1406. X        exit(0);
  1407. X    /*NOTREACHED*/
  1408. X}
  1409. SHAR_EOF
  1410. if test 16498 -ne "`wc -c < 'ibsmtp.c'`"
  1411. then
  1412.     echo shar: error transmitting "'ibsmtp.c'" '(should have been 16498 characters)'
  1413. fi
  1414. fi # end of overwriting check
  1415. echo shar: extracting "'sendbsmtp'" '(1458 characters)'
  1416. if test -f 'sendbsmtp'
  1417. then
  1418.     echo shar: will not over-write existing file "'sendbsmtp'"
  1419. else
  1420. sed 's/^X//'  >'sendbsmtp' <<'SHAR_EOF'
  1421. X#! /bin/sh
  1422. X# sendbsmtp -- send a bsmtp packet given a destination and file.
  1423. X#
  1424. X# USAGE:  sendbsmtp mailer dest [ file ]
  1425. X
  1426. XPATH=/bin:/usr/bin:/usr/local:/usr/ucb:.
  1427. Xexport PATH
  1428. X
  1429. XFROM=`whoami`@ukma
  1430. XMAILER=${1}
  1431. XTO=${2}
  1432. XFILE=${3}
  1433. X
  1434. X#         NOTICE!!!!
  1435. X#
  1436. X# We're zapping the command line args here, so if you need them
  1437. X# take care of getting them before now!
  1438. Xset `date`
  1439. XDAY=${1}
  1440. XMONTH=${2}
  1441. XDATE=${3}
  1442. XTIME=${4}
  1443. XTIMEZONE=${5}
  1444. XYEAR=${6}
  1445. XARPADATE="${DAY}, ${DATE} ${MONTH} ${YEAR} ${TIME} ${TIMEZONE}"
  1446. X
  1447. Xif test -z "${MAILER}" -o -z "${TO}"; then
  1448. X    echo Usage: sendbsmtp mailer dest \[ file \]
  1449. X    echo
  1450. X    echo where, mailer is user@host id of the mailer to send this to, and
  1451. X    echo        dest is the address to send the mail to.
  1452. X    exit 1
  1453. Xfi
  1454. X
  1455. Xif test -z "${FILE}"; then
  1456. X    echo No file name given, stdin used
  1457. Xfi
  1458. X
  1459. X( echo HELO ukma
  1460. X  echo MAIL FROM:\<${FROM}\>
  1461. X  echo RCPT TO:\<${TO}\>
  1462. X  echo DATA
  1463. X  echo "From:    " ${FROM}
  1464. X  echo "To:      " ${TO}
  1465. X  echo "Date:    " ${ARPADATE}
  1466. X  echo -n "Subject: " File sent from ukma.bitnet \(or ms.uky.edu\) " "
  1467. X  if test -z "${FILE}"; then
  1468. X      echo -- Unknown name
  1469. X  else
  1470. X      echo -- ${FILE}
  1471. X  fi
  1472. X  echo " "
  1473. X  if test ! -z "${FILE}"; then
  1474. X      if test -f ${FILE} -a -r ${FILE}; then
  1475. X        # This sed command looks for lines beginning with a '.',
  1476. X        # and adds a '.' to the beginning of the line.  This is
  1477. X        # as per the [B]SMTP spec.
  1478. X          sed '/^\./s/^\..*$/.&/' ${FILE}
  1479. X      fi
  1480. X  else
  1481. X    sed '/^\./s/^\..*$/.&/'
  1482. X  fi
  1483. X  echo .
  1484. X  echo QUIT ) >bsmtp.in
  1485. X
  1486. Xexit 0
  1487. SHAR_EOF
  1488. if test 1458 -ne "`wc -c < 'sendbsmtp'`"
  1489. then
  1490.     echo shar: error transmitting "'sendbsmtp'" '(should have been 1458 characters)'
  1491. fi
  1492. chmod +x 'sendbsmtp'
  1493. fi # end of overwriting check
  1494. :    End of shell archive
  1495. exit 0
  1496. --
  1497. ----- David Herron,  Local E-Mail Hack,  david@ms.uky.edu, david@ms.uky.csnet
  1498. -----                            {uunet,cbosgd}!ukma!david, david@UKMA.BITNET
  1499. ----- bsmtp-users@ms.uky.edu for bsmtp discussion
  1500. ----- bsmtp-users-request@ms.uky.edu for administrivia
  1501. -- 
  1502.  
  1503. Rich $alz
  1504. Cronus Project, BBN Labs            rsalz@bbn.com
  1505. Moderator, comp.sources.unix            sources@uunet.uu.net
  1506.