home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / UNIFLEX / UNIFLEX / UniFLEX_Std.Utils1.tar.Z / UniFLEX_Std.Utils1.tar / utils1 / mail < prev    next >
Text File  |  1984-05-02  |  24KB  |  1,275 lines

  1.  opt pag,nol
  2.  ttl Mail Utility
  3.  lib sysdef
  4.  spc 4
  5. **   Local Macro Definitions.
  6.  spc 2
  7. **   msg - define message
  8. *
  9. * tag msg "text"[,terminator]
  10. *
  11. * defines "tag" concatencated with "l" to be length of message
  12.  spc 2
  13. msg macro
  14.  fcc "&1"
  15.  ifnc &2,""
  16.  fcb &2
  17.  endif
  18. &0l equ *-&0
  19.  endm
  20.  spc 2
  21. **   Messag - Write message.
  22. *
  23. *    messag file-descriptor,message-address[,message-length]
  24. *
  25. *    if "message-length" is not specified, the symbol for
  26. *    "message-address", concatenated with an "l", is used.
  27.  spc 2
  28. messag macro
  29.  ldd #&1
  30.  ifnc &3,""
  31.  sys write,&2,&3
  32.  else
  33.  sys write,&2,&2l
  34.  endif
  35.  endm
  36.  opt lis
  37.  pag
  38.  info UniFLEX mail
  39.  info Version 1.21, Released March 28, 1984
  40.  info Copyright, (C) 1981, by
  41.  info Technical Systems Consultants, Inc.
  42.  info All rights reserved.
  43.  
  44. *
  45. * Mail Utility - send or read mail.
  46. *
  47.  
  48.  org 0
  49.  
  50. mail sts stkptr save system stack ptr
  51.  jsr pop process options
  52.  ldd 0,s get arg count
  53.  cmpd #1 list or send?
  54.  lbhi smail
  55.  
  56. * list mail
  57.  
  58. lmail sys guid reset effective user id
  59.  std uid save for fndnam
  60.  sys suid to actual id (for perms)
  61.  jsr opnpass open password file
  62. 1 jsr getlin get a line from password file
  63.  lbeq lmail8 if eof
  64.  ldx #linbuf point to line buffer
  65.  jsr fcol find end of user name
  66.  jsr fcol find end of password
  67.  pshs x save ptr to user id #
  68.  jsr fcol find end of user id #
  69.  clr -1,x set term
  70.  leay 0,x save x
  71.  puls x restore ptr to user if #
  72.  pshs y save ptr to login dir
  73.  jsr decvt convert user id to binary
  74.  puls y restore ptr to login dir
  75.  cmpd uid
  76.  bne 1b if not a match
  77.  jsr fcol find end of login dir
  78.  clr -1,x set term
  79.  leax 0,y (x)=ptr to login dir
  80.  pshs x save ptr to login dir
  81.  jsr cpylog copy log dir to usst
  82.  puls x restore login dir ptr
  83.  jsr cpyml copy log dir to usst2
  84.  jsr clspass close the password file
  85.  sys status,usst,stb get file status
  86.  bes lmail8 error?
  87.  ldd stb+9 check for non zero size
  88.  bne lmail2
  89.  ldd stb+11
  90.  beq lmail9
  91. lmail2 sys open,usst,0 open mail file
  92.  bes lmail8 error?
  93.  std mfd save file desc
  94.  jsr cptt copy mail to terminal
  95.  ldd mfd close the mail file
  96.  sys close
  97.  ldd #1 prompt user
  98.  sys write,savms,SAVSZ 'Save mail?'
  99.  ldd #0 set input file desc
  100.  sys read,ibuf,32 get response
  101.  cmpd #0 eof?
  102.  beq quit
  103.  lda ibuf get 1st char of response
  104.  anda #$5F make upper case
  105.  cmpa #'Y responde yes?
  106.  beq lmail5
  107.  cmpa #'N response no?
  108.  beq lmail6
  109. quit ldd #0 exit with no action
  110. abort lds stkptr restore stack ptr
  111.  sys term
  112. lmail5 jsr savml save the mail file
  113. lmail6 jsr trnml truncate .mail file
  114.  jmp quit exit
  115. lmail8 pshs d save error
  116.  ldd #2 set error file desc
  117.  sys write,comms,COSZ output error
  118.  puls d get error
  119.  jmp abort
  120. lmail9 ldd #1 set file desc
  121.  sys write,noms,NOMSZ output error
  122.  jmp quit exit
  123.  
  124.  pag
  125.  
  126. *
  127. * Send mail
  128. *
  129.  
  130. smail leax 4,s point to arg list
  131.  stx argpt save arg pointer
  132.  jsr crtmp create mail temp file
  133.  tst all
  134.  bne sndall if sending mail to all
  135. 1 jsr opnpass open password file
  136. 2 ldx argpt get arg pointer
  137.  ldy 0,x++ get next arg
  138.  beq 6f finished?
  139.  stx argpt
  140.  lda 0,y get 1st char of arg
  141.  cmpa #'+
  142.  beq 2b if arg is an option
  143.  pshs y save ptr to user name arg
  144. 3 jsr getlin get a line from the password file
  145.  beq 7f if eof
  146.  ldx #linbuf point to the line
  147.  ldy 0,s restore ptr to user name arg
  148. 4 lda 0,y+ get char from user name arg
  149.  beq 5f if end of user name arg
  150.  cmpa 0,x+ check against password file
  151.  bne 3b if no match
  152.  bra 4b not done yet
  153. 5 lda 0,x+ next char of password file
  154.  cmpa #': should be a ":"
  155.  bne 3b if no match
  156.  puls y restore stack
  157.  jsr setup setup for mailing
  158.  bne 8f error?
  159.  jsr head send out header
  160.  jsr copy copy mail to file
  161.  ldd tfd close the dest file
  162.  sys close
  163.  ldd mfd
  164.  sys close
  165.  bra 8f repeat for next user
  166. 6 sys unlink,tmpn delete temp file
  167.  jmp quit
  168.  
  169. 7 puls x get ptr to user name arg
  170.  jsr prter "Can't send mail to"
  171. 8 jsr clspass close the password file
  172.  bra 1b process next user
  173.  
  174.  
  175. sndall jsr opnpass open password file
  176. 3 jsr getlin get a line from the password file
  177.  beq 4f if eof
  178.  jsr setup setup for mailing
  179.  bne 3b error?
  180.  jsr head send out header
  181.  jsr copy copy mail to file
  182.  ldd tfd close the dest file
  183.  sys close
  184.  ldd mfd
  185.  sys close
  186.  bra 3b repeat for next user
  187. 4 sys unlink,tmpn delete temp file
  188.  jsr clspass close the password file
  189.  jmp quit
  190.  
  191. *
  192. * trnml
  193. *
  194. * Truncate the '.mail' file to zero length.
  195. *
  196.  
  197. trnml sys status,usst,stb get file status
  198.  bes trnml2 error?
  199.  ldb stb+5 get perm bits
  200.  clra make 16 bit word
  201.  std icrt2 set up create call
  202.  sys ind,icrt create .mail file (truncate)
  203.  bes trnml2 error?
  204.  sys close close the file
  205. trnml2 rts return
  206.  
  207. *
  208. * cptt
  209. *
  210. * Copy mail file to terminal.
  211. *
  212.  
  213. cptt ldd #1 set file desc (standard output)
  214.  std tfd save it
  215.  
  216. * fall thru to copy
  217.  
  218.  pag
  219.  
  220. *
  221. * copy
  222. *
  223. * Copy file (mfd) to file (tfd).
  224. *
  225.  
  226. copy ldd mfd get file desc
  227.  sys read,ibuf,32 read some of file
  228.  bes copy5 error?
  229.  std iwrt2 save count
  230.  beq copy5
  231.  ldd tfd get file desc
  232.  sys ind,iwrt write out data
  233.  bra copy repeat
  234. copy5 rts return
  235.  
  236. *
  237. * savml
  238. *
  239. * Save the .mail file by writing it to the end
  240. * of the 'mailbox' file if it exists.
  241. *
  242.  
  243. savml sys chacc,usst2,0 check if 'mailbox' exists
  244.  bec savml2 error?
  245.  sys create,usst2,3 create mailbox file
  246.  bes savml4 error?
  247.  std tfd save file desc
  248.  bra savml3
  249. savml2 sys open,usst2,1 open mailbox for write
  250.  bes savml4 error?
  251.  std tfd save file desc
  252.  sys seek,0,0,2 seek to end of file
  253. savml3 sys open,usst,0 open '.mail' for read
  254.  bes savml4 error?
  255.  std mfd save file desc
  256.  bsr copy copy file
  257.  ldd mfd get file desc
  258.  sys close close .mail file
  259.  ldd tfd get file desc
  260.  sys close close mailbox file
  261.  rts return
  262. savml4 pshs d save error
  263.  ldd #2 set file desc
  264.  sys write,nbmms,NBSZ output error
  265.  puls d get error
  266.  jmp abort
  267.  
  268.  pag
  269.  
  270. *
  271. * setup
  272. *
  273. * Setup the sending of mail.
  274. *
  275. *   entry linbuf contains line from password file.
  276. *         mail will be sent to this user.
  277. *
  278.  
  279. setup bsr copynm copy user name
  280.  jsr fnddir locate login dir
  281.  bsr cpylog copy log dir to usst
  282.  ldx #usst point to complete file name
  283. 4 stx iopn2 set up sys call
  284.  sys ind,iopn open file for write
  285.  bes 6f error?
  286.  std tfd save file desc
  287.  sys ofstat,stb get status
  288.  lda stb+6 check link count
  289.  deca
  290.  bne 6f if not 1 - error
  291.  lda stb+4 regular file?
  292.  bita #%00001110
  293.  bne 6f if not - error
  294.  ldd tfd
  295.  sys seek,0,0,2 seek to end of file
  296.  sys open,tmpn,0 open temp file for read
  297.  std mfd save file desc
  298.  sez set status
  299.  rts return
  300. 6 ldx #usrnm point to user name
  301.  jsr prter print error
  302.  clz set error status
  303.  rts return
  304.  
  305. *
  306. * copynm - copy user name from password file to "usrnm"
  307. *
  308.  
  309. copynm ldx #linbuf get ptr to user name
  310.  ldy #usrnm
  311. 1 lda 0,x+ get char from file
  312.  cmpa #':
  313.  beq 2f if colon found
  314.  sta 0,y+
  315.  bra 1b not done yet
  316. 2 clra set term
  317.  sta 0,y+
  318.  rts
  319.  
  320. *
  321. * cpylog - build .mail path name
  322. *
  323.  
  324. cpylog ldy #usst point to file name string
  325. 2 lda 0,x+ get char from password file
  326.  sta 0,y+ copy char to file name
  327.  bne 2b end of login dir?
  328.  lda #'/ set path sep char
  329.  sta -1,y
  330.  ldx #mlnam set up .mail name
  331. 3 lda 0,x+
  332.  sta 0,y+
  333.  bne 3b
  334.  rts
  335.  
  336. *
  337. * cpyml - build mailbox path name
  338. *
  339.  
  340. cpyml ldy #usst2 point to file name string
  341. 2 lda 0,x+ get char from password file
  342.  sta 0,y+ copy char to file name
  343.  bne 2b end of login dir?
  344.  lda #'/ set path sep char
  345.  sta -1,y
  346.  ldx #mbnam set up .mail name
  347. 3 lda 0,x+
  348.  sta 0,y+
  349.  bne 3b
  350.  rts
  351.  
  352. *
  353. * fnddir - find login dir in paswword file line
  354. *
  355. *  entry linbuf contains line from password file.
  356. *   exit (x)=ptr to login dir
  357. *
  358.  
  359. fnddir ldx #linbuf point to line
  360.  jsr fcol find end of user name
  361.  clr -1,x set term
  362.  jsr fcol find end of password
  363.  clr -1,x set term
  364.  jsr fcol find end of user id #
  365.  pshs x (x)=ptr to 1st char of login dir
  366.  jsr fcol find end of login dir
  367.  clr -1,x set term
  368.  puls x get login dir pointer
  369.  rts return
  370.  
  371. *
  372. * fcol
  373. *
  374. * Find colon in string pointed at by X.
  375. *
  376.  
  377. fcol lda 0,x+ get char
  378.  cmpa #': is it ':'?
  379.  bne fcol
  380.  rts return
  381.  
  382.  pag
  383.  
  384. *
  385. * crtmp
  386. *
  387. * Create temp mail file.
  388. *
  389.  
  390. crtmp sys gtid get task id
  391.  ldx #tmpn2 point to name slot
  392.  jsr decstn convert to string
  393.  lda #'. overwrite leading space
  394.  sta tmpn2
  395.  sys status,tmpn,stb2 see if temp file exists
  396.  bec crtmp4 error if so
  397.  sys create,tmpn,3 create temp file
  398.  bes crtmp4 error?
  399.  std tfd save file desc
  400.  ldd #0 set s.input file desc
  401.  std mfd
  402.  jsr copy copy input to temp file
  403.  ldd tfd close file
  404.  sys close
  405.  rts return
  406. crtmp4 pshs d save error
  407.  ldd #2 set file desc
  408.  sys write,cctms,CCSZ output error
  409.  puls d
  410.  jmp abort
  411.  
  412.  pag
  413.  
  414. *
  415. * head
  416. *
  417. * Output mail header (date and user name)
  418. *
  419.  
  420. head sys time,tbuf get current time
  421.  ldx #tbuf point to time
  422.  jsr tmloc convert time to local
  423.  jsr tasc convert to ascii string
  424.  lda #$20 set spaces in string
  425.  sta tstr+24
  426.  sta tstr+25
  427.  jsr fndusr find this user's name
  428.  ldy #namslt point to name slot
  429.  ldb #HDSZ set up counter
  430. head2 incb bump the count
  431.  lda 0,x+ move the name
  432.  sta 0,y+
  433.  bne head2 repeat?
  434.  lda #'. term the name with period
  435.  sta -1,y
  436.  pshs b
  437.  ldd #$d0d set cr
  438.  std 0,y
  439.  puls b
  440.  addb #2 adjust count
  441.  clra
  442.  std hwrt2 setup call
  443.  ldd tfd get file desc
  444.  sys ind,hwrt output header
  445.  rts return
  446.  
  447. *
  448. * fndusr
  449. *
  450. * Find the user's name.  Return in linbuf.
  451. *
  452.  
  453. fndusr sys guid get the user id
  454.  std uid save it
  455.  bsr fndnam look up in pswd file
  456.  ldx #linbuf point to name
  457.  rts return
  458.  
  459.  pag
  460.  
  461. *
  462. * fndnam
  463. *
  464. * Find name in password file.
  465. *   entry uid contains user id to search for
  466. *
  467.  
  468. fndnam ldx linpt get current line ptr
  469.  pshs x save it
  470.  ldx linend get current line end ptr
  471.  pshs x save it
  472.  ldd namfd
  473.  sys seek,0,0,1 get current position
  474.  pshs x save hi pos
  475.  pshs d save lo pos
  476.  ldx #fbuf point to file buffer
  477.  stx linpt init buf ptrs
  478.  stx linend
  479.  ldd namfd rewind password file
  480.  sys seek,0,0,0
  481. 2 jsr getlin get a line from the file
  482.  beq 3f eof?
  483.  ldx #linbuf point to line
  484.  jsr fcol find colon
  485.  clr -1,x set term
  486.  jsr fcol find next colon
  487.  pshs x save pointer
  488.  jsr fcol find end of field
  489.  clr -1,x set term
  490.  puls x get user id field pointer
  491.  jsr decvt convert to binary
  492.  cmpd uid user id match?
  493.  bne 2b
  494. 3 puls d restore low pos
  495.  std iseek2
  496.  puls x restore hi pos
  497.  stx iseek1
  498.  ldd namfd get file desc
  499.  sys ind,iseek
  500.  puls x restore line end ptr
  501.  stx linend
  502.  puls x restore line ptr
  503.  stx linpt
  504. 4 rts return
  505.  
  506. *
  507. * opnpass - open the password file
  508. *
  509. opnpass ldx #fbuf point to file buffer
  510.  stx linpt init buffer ptrs
  511.  stx linend
  512.  sys open,nfile,0 open the password file
  513.  std namfd save file desc
  514.  rts
  515.  
  516. *
  517. * clspass - close the password file
  518. *
  519. clspass ldd namfd restore file desc
  520.  sys close
  521.  rts
  522.  
  523. *
  524. * pop
  525. *
  526. * process options.
  527. *
  528. pop leax 6,s point to list of args
  529. 1 ldy 0,x++ get arg address
  530.  beq 7f if end of arg list
  531.  lda 0,y check char
  532.  cmpa #'+
  533.  bne 1b if not an option arg
  534.  leay 1,y advance to first opt letter
  535.  
  536. 2 lda 0,y+ get option letter
  537.  beq 1b if end of option string
  538.  ldu #poptbl (u)=option table addr
  539.  
  540. 3 cmpa 0,u+ check char
  541.  beq 5f if found
  542.  leau 2,u advance option tbl ptr
  543.  tst 0,u check entry
  544.  bne 3b if not end of table
  545.  messag 2,popms "Unknown option specified"
  546.  jmp abort quit processing
  547.  
  548. 5 lda 0,y+ check char
  549.  cmpa #'=
  550.  beq 6f
  551.  leay -1,y
  552. 6 jsr [0,u] execute option processor
  553.  bra 2b loop for next option
  554.  
  555. 7 rts
  556.  
  557. poptbl fcb 'a a - send mail to all users
  558.  fdb pop1
  559.  fcb 0 end of table
  560.  
  561. pop1 sys guid get actual user id
  562.  cmpd #0 system manager?
  563.  bne 1f if not system manager
  564.  ldd [stkptr] get count of args
  565.  cmpd #2
  566.  bne 2f if too many args
  567.  inc all set all flag
  568.  rts
  569. 1 messag 2,noper "no permission"
  570.  jmp abort
  571. 2 messag 2,syner "command syntax error"
  572.  jmp abort
  573.  
  574.  
  575. popms msg "Unknown option specified.",$d
  576. noper msg "No permission.",$d
  577. syner msg 'Command syntax error',$d
  578.  
  579.  opt nol
  580. *
  581. * getlin
  582. *
  583. * Get a line from the password file.  Put it
  584. * in the linbuf.
  585. *
  586.  
  587. getlin ldx #linbuf point to line buffer
  588. getli2 bsr gtch get a character
  589.  beq getli4 eof?
  590.  sta 0,x+ save character in buffer
  591.  cmpa #$d end of line?
  592.  bne getli2
  593.  clz set ok status
  594. getli4 rts return
  595.  
  596.  pag
  597.  
  598. *
  599. * gtch
  600. *
  601. * Get a character from the password file.  Return
  602. * eq status if eof.
  603. *
  604.  
  605. gtch pshs x save x
  606. gtch2 ldx linpt get line pointer
  607.  cmpx linend end of buffer?
  608.  bne gtch4
  609.  ldd namfd get file desc
  610.  sys read,fbuf,512 read in some file
  611.  bes gtch6 error?
  612.  cmpd #0 eof?
  613.  beq gtch6
  614.  ldx #fbuf point to buffer begin
  615.  stx linpt save pointer
  616.  leax d,x mark end of buffer
  617.  stx linend
  618.  ldx linpt reset pointer
  619. gtch4 lda 0,x+ get next character
  620.  stx linpt save pointer
  621.  clz set ok status
  622.  puls x,pc return
  623. gtch6 sez set error
  624.  puls x,pc return
  625.  
  626.  pag
  627.  
  628. *
  629. * decvt
  630. *
  631. * Decimal convert routine.  Convert ascii string
  632. * pointed at by x and null terminated.
  633. * Return number in D and ne if error.
  634. *
  635.  
  636. decvt ldd #0 set up zero
  637.  pshs d
  638. decvt2 lda 0,x+ get character
  639.  beq decvt4 end of list?
  640.  cmpa #'0 check for valid number
  641.  blo decvt3 error?
  642.  cmpa #'9
  643.  bhi decvt3
  644.  anda #$F mask character
  645.  pshs a save digit
  646.  ldd 1,s get number
  647.  aslb multiply by 8
  648.  rola
  649.  aslb
  650.  rola
  651.  aslb
  652.  rola
  653.  addd 1,s add in original twice
  654.  addd 1,s
  655.  addb 0,s+ add in new digit
  656.  adca #0
  657.  std 0,s save result
  658.  bra decvt2 repeat
  659. decvt3 clz set error
  660. decvt4 puls d,pc return
  661.  
  662.  pag
  663.  
  664. *
  665. * decst
  666. *
  667. * Convert the number in D into an ascii string
  668. * representing a decimal number.  The string
  669. * is pointed at by X (X should be set on entry!)
  670. * Also on exit, D has the length of the string.
  671. * The second entry point, 'decstn' will not print
  672. * leading spaces for leading zeroes, but will
  673. * suppress all leading zero info.  All strings
  674. * start with a space.
  675. *
  676.  
  677. decst pshs x save user pointer
  678.  clr 0,-s set suppression flag
  679.  bra decst2
  680. *
  681. decstn pshs x save user pointer
  682.  clr 0,-s
  683.  inc 0,s set for no fielding
  684. decst2 pshs a
  685.  lda #$20 setup leading space
  686.  sta 0,x+ save in buffer
  687.  puls a
  688.  clr 0,-s set up bookkeeping
  689.  clr 0,-s
  690.  ldy #conlst point to constants
  691. decst4 cmpd 0,y compare number to constant
  692.  blo decst5
  693.  subd 0,y do subtraction of constant
  694.  inc 1,s bump digits counter
  695.  bra decst4
  696. decst5 pshs a save number
  697.  tst 2,s zero digit?
  698.  bne decst6
  699.  tst 1,s any numbers output yet?
  700.  bne decst6
  701.  tst 3,s doing suppression?
  702.  bne decst8
  703.  lda #$20 set up space
  704.  bra decst7
  705. decst6 lda 2,s get digit count
  706.  inc 1,s set 'got one' flag
  707.  ora #$30 make ascii
  708. decst7 sta 0,x+ save in buffer
  709. decst8 puls a reset number
  710.  clr 1,s clear out digit
  711.  leay 2,y bump constant ptr
  712.  cmpy #conend end of list?
  713.  bne decst4
  714.  leas 3,s clean up stack
  715.  orb #$30 make last digit
  716.  stb 0,x+ save in buffer
  717.  clr 0,x null terminate string
  718.  tfr x,d
  719.  subd 0,s calculate string length
  720.  puls x,pc return
  721.  
  722. * constants for convert
  723.  
  724. conlst fdb 10000
  725.  fdb 1000
  726.  fdb 100
  727.  fdb 10
  728. conend equ * end of list
  729.  
  730.  pag
  731.  
  732. *
  733. * prter
  734. *
  735. * Print  "Can't send mail to _____ "
  736. *   entry (x)=ptr to user name
  737. *
  738.  
  739. prter stx ewrt2 set in os call
  740.  ldd #2 set file desc
  741.  sys write,ermsg1,ERSZ1
  742.  clrb set count to 0
  743. 2 lda 0,x+ look for name end
  744.  beq 4f
  745.  incb bump char count
  746.  bra 2b
  747. 4 std ewrt3 save count in call
  748.  ldd #2 set up file desc
  749.  sys ind,ewrt output file name
  750.  ldd #2 set file desc
  751.  sys write,ermsg2,ERSZ2 output rest of message
  752.  rts return
  753.  
  754.  pag
  755.  
  756. *
  757. * tmloc
  758. *
  759. * Convert time pointed at by x to vector time (local).
  760. *
  761.  
  762. tmloc ldd 0,x get time
  763.  std ltime
  764.  ldd 2,x
  765.  std ltime+2
  766.  lda 7,x get day light savings flag
  767.  sta dlflg
  768.  clr eutc init flag
  769.  ldd 5,x get time zone
  770.  bpl tmloc2 west of GMT?
  771.  inc eutc if not - set flag
  772.  coma and make pos number
  773.  comb
  774.  addd #1
  775. tmloc2 std r0+2 save time zone
  776.  ldd #60 calculate zone seconds
  777.  std r1+2
  778.  ldd #0 set hi bytes to 0
  779.  std r0
  780.  std r1
  781.  jsr lmul calculate time zone seconds
  782.  ldd r0 get result
  783.  std tzn save it
  784.  ldd r0+2
  785.  std tzn+2
  786.  jsr adjtim adjust time for zone
  787.  ldx #ltime point to time
  788.  jsr tmutc convert to vector
  789.  tst dlflg do dlst?
  790.  beq tmloc6
  791.  jsr chkdl in dlst?
  792.  bne tmloc6
  793. tmloc5 ldd #3600 adjust for dlst
  794.  addd ltime+2
  795.  std ltime+2
  796.  ldd ltime
  797.  adcb #0
  798.  adca #0
  799.  std ltime
  800.  ldx #ltime point to time
  801.  jsr tmutc convert to vector
  802.  inc daylit set daylit flag
  803. tmloc6 ldx #second point to vector
  804.  rts return
  805.  
  806.  pag
  807.  
  808. *
  809. * tmutc
  810. *
  811. * Convert the internal system time (4 bytes
  812. * pointed at by X on entry) to an 18 byte
  813. * vector representing the broken down time.
  814. * The time in this form is UTC (Universal
  815. * Coordinated Time).
  816. *
  817.  
  818. tmutc ldd #0 set daylight savings word
  819.  std daylit
  820.  ldd 0,x get hi word of time
  821.  std r0 save ir divide register
  822.  ldd 2,x get lo word of time
  823.  std r0+2
  824.  ldd #60*60 seconds*minutes constant
  825.  std r1 set up for divide
  826.  jsr ldiv min*sec=time % 3600
  827.  ldd work hour*day=time / 3600
  828.  pshs d save min*sec
  829.  ldd #24 set up hours per day constant
  830.  std r1
  831.  jsr ldiv hours= (hour*day) % 24
  832.  ldd work day= (hour*day) / 24
  833.  std hours set hours word
  834.  ldd r0+2 get day number
  835.  std day save the day
  836.  addd #2 add in day bias (Jan 1 80 => Tue)
  837.  std r0 set up for divide
  838.  ldb #7 days per week constant
  839.  stb r1
  840.  jsr div wday=(day+2) % 7
  841.  ldb work get result
  842.  clra make into word
  843.  std wday set week day
  844.  puls d get min*sec
  845.  std r0 set up for divide
  846.  ldb #60 seconds per minute
  847.  stb r1
  848.  jsr div seconds= (min*sec) % 60
  849.  ldb work minutes= (min*sec) / 60
  850.  clra
  851.  std second set seconds word
  852.  ldd r0 get minutes
  853.  std minute save it
  854.  
  855.  pag
  856.  
  857. * continue tutc for year and month data
  858.  
  859.  clr 0,-s clear year counter
  860. tutc2 ldx #ylen point to year length table
  861.  lda 0,s get year number
  862.  bita #$3 is it leap year?
  863.  bne tutc3
  864.  leax 2,x if so, move to long year value
  865. tutc3 ldd day get day number
  866.  cmpd 0,x day in current year?
  867.  blo tutc4 if 'lt' - we got the year!
  868.  subd 0,x subtract off years days
  869.  std day save new day count
  870.  inc 0,s bump the year count
  871.  bra tutc2 repeat
  872. tutc4 std yday set day of year word
  873.  puls b get year count
  874.  addb #80 add to '1980'
  875.  clra make 16 bits long
  876.  std year save the year
  877.  bitb #$3 is it leap year?
  878.  bne tutc5
  879.  ldd #29 if so, set Feb day count to 29
  880.  std mdays+2
  881. tutc5 ldx #mdays point to month-day table
  882.  clr 0,-s set month count to zero
  883.  ldd yday get day of the year
  884. tutc6 cmpd 0,x in the month?
  885.  blo tutc7 if 'lt' - we got the month!
  886.  inc 0,s bump the month counter
  887.  subd 0,x++ subtract of this month's days
  888.  bra tutc6
  889. tutc7 addd #1 add 1 to month day (day 1 is 1 - not 0!)
  890.  std mday save the month day
  891.  puls b get the month
  892.  std month save it
  893.  ldd #28 reset month - day table
  894.  std mdays+2
  895.  rts return
  896.  
  897.  pag
  898.  
  899. *
  900. * chkdl
  901. *
  902. * Check if in dlst - return 'eq' if so.
  903. *
  904.  
  905. chkdl ldd #119 check for last Sun in Apr
  906.  bsr fixtim
  907.  std fstdl first day of dlst
  908.  ldd #303 last Sun in Oct
  909.  bsr fixtim
  910.  std lstdl last day of dlst
  911.  ldd yday get day of year
  912.  cmpd fstdl up to 1st day yet?
  913.  blo chkdl6
  914.  bhi chkdl4
  915.  ldd hours on the 1st day - so
  916.  cmpd #2 is it 2:00 AM yet?
  917.  blo chkdl6
  918.  bra chkdl5
  919. chkdl4 ldd yday get day of year
  920.  cmpd lstdl past last day of dlst?
  921.  bhi chkdl6
  922.  blo chkdl5
  923.  ldd hours on the last day - so
  924.  cmpd #1 is it 1:00 AM yet?
  925.  bhs chkdl6
  926. chkdl5 sez we are in dlst!
  927.  rts return
  928. chkdl6 clz not in dlst
  929.  rts return
  930.  
  931.  pag
  932.  
  933. *
  934. * adjtim
  935. *
  936. * Adjust time for time zone.
  937. *
  938.  
  939. adjtim ldd ltime+2 get time
  940.  tst eutc east of UTC?
  941.  bne adjti2
  942.  subd r0+2 subtract time zone minutes
  943.  std ltime+2
  944.  ldd ltime get hi part
  945.  sbcb r0+1
  946.  sbca r0
  947.  bra adjti4
  948. adjti2 addd r0+2 add in minutes
  949.  std ltime+2
  950.  ldd ltime
  951.  adcb r0+1
  952.  adca r0
  953. adjti4 std ltime save new time
  954. adjti5 rts return
  955.  
  956. *
  957. * fixtim
  958. *
  959. * Return the closest day to the date in D
  960. * which is a Sunday.
  961. *
  962.  
  963. fixtim pshs d save day number
  964.  ldd year get year
  965.  bitb #$3 is it leap year?
  966.  puls d
  967.  bne fixti2
  968.  addd #1 if so - bump day number
  969. fixti2 pshs d save day number
  970.  addd #420 add in 420 so no negatives result
  971.  addd wday add in day of week
  972.  subd yday subtract day of year
  973.  std r0 save result
  974.  ldb #7
  975.  stb r1 set up for divide
  976.  jsr div do: (day+420+wday-yday) % 7
  977.  puls d get day number
  978.  subb work
  979.  sbca #0
  980.  rts return day in d
  981.  
  982.  pag
  983.  
  984. *
  985. * Divide routines for time conversion use.  'Ldiv'
  986. * divides a 32 bit number (r0 -> r0+3) by a 16 bit
  987. * number (r1 -> r1+1) and produces a 32 bit result
  988. * in r0 and a 16 bit remainder in 'work'.  'Div'
  989. * divides a 16 bit number (r0 -> r0+1) by an 8 bit
  990. * number (r1) and produces a 16 bit result (r0)
  991. * and an 8 bit remainder (work).
  992. *
  993.  
  994. div lda #17 set up loop counter
  995.  clrb do initialize
  996.  stb work
  997.  bra div2
  998. div1 ldb work
  999.  subb r1 do subtraction
  1000.  bcs div2 s3et new work?
  1001.  stb work yes!
  1002. div2 rol r0+1 do shift left
  1003.  rol r0
  1004.  rol work
  1005.  deca dec the loop count
  1006.  bne div1 repeat?
  1007.  com r0 fix up result
  1008.  com r0+1
  1009.  lsr work fix remainder
  1010.  rts
  1011.  
  1012.  
  1013.  pag
  1014.  
  1015. *
  1016. * Long divide
  1017. *
  1018.  
  1019. ldiv ldb #33 set loop counter
  1020.  pshs b
  1021.  ldd #0 do init
  1022.  std work
  1023.  bra ldiv2
  1024. ldiv1 ldd work do subtraction
  1025.  subd r1
  1026.  bcs ldiv2 work > r1 ?
  1027.  std work set new work value
  1028. ldiv2 rol r0+3 do shifting
  1029.  rol r0+2
  1030.  rol r0+1
  1031.  rol r0
  1032.  rol work+1
  1033.  rol work
  1034.  dec 0,s dec the loop count
  1035.  bne ldiv1
  1036.  com r0 compliment the result
  1037.  com r0+1
  1038.  com r0+2
  1039.  com r0+3
  1040.  lsr work adjust the remainder
  1041.  ror work+1
  1042.  puls b,pc return
  1043.  
  1044.  pag
  1045.  
  1046. *
  1047. * lmul
  1048. *
  1049. * Long multiply - 32 bits (r0) X 32 bits (r1).
  1050. * Result is in r0.
  1051. *
  1052.  
  1053. lmul ldb #32 set loop count
  1054.  pshs b
  1055.  ldd #0 init variables
  1056.  std work
  1057.  std work+2
  1058.  lsr r0 do initial shift
  1059.  ror r0+1
  1060.  ror r0+2
  1061.  ror r0+3
  1062. lmul1 bcc lmul2 need to add?
  1063.  ldd work+2
  1064.  addd r1+2
  1065.  std work+2
  1066.  ldd work
  1067.  adcb r1+1
  1068.  adca r1
  1069.  std work save result
  1070. lmul2 ror work do shifting
  1071.  ror work+1
  1072.  ror work+2
  1073.  ror work+3
  1074.  ror r0
  1075.  ror r0+1
  1076.  ror r0+2
  1077.  ror r0+3
  1078.  dec 0,s dec the loop count
  1079.  bne lmul1 repeat?
  1080.  puls b,pc return
  1081.  
  1082.  pag
  1083.  
  1084. *
  1085. * tasc
  1086. *
  1087. * Convert the time vector data (18 bytes) pointed
  1088. * at by x into an ascii string.  Return x pointing
  1089. * to the string.
  1090. *
  1091.  
  1092. tasc tfr x,u save vector pointer
  1093.  ldx #tstr point to string
  1094.  ldd 4,u get hours
  1095.  jsr cvt convert to ascii
  1096.  leax 1,x skip the ':'
  1097.  ldd 2,u get minutes
  1098.  jsr cvt convert to ascii
  1099.  leax 1,x skip the ':'
  1100.  ldd 0,u get seconds
  1101.  jsr cvt convert to ascii
  1102.  leax 1,x skip space
  1103.  ldd 6,u get day of week
  1104.  ldy #dtab point to day table
  1105.  bsr tasxfr xfr to string
  1106.  ldd 10,u get month
  1107.  ldy #mtab point to month table
  1108.  bsr tasxfr xfr to string
  1109.  ldd 8,u get month day
  1110.  bsr cvt convert to ascii
  1111.  leax 1,x
  1112.  ldd #('1<<8)|'9 set up '19'
  1113.  std 0,x save in string
  1114.  ldd 12,u get year
  1115.  cmpd #100 >100 (year 2000 yet?)
  1116.  blo tasc4
  1117.  subd #100 remove bias
  1118.  pshs d save year
  1119.  ldd #('2<<8)|'0 set up '20'
  1120.  std 0,x set in string
  1121.  puls d reset year
  1122. tasc4 leax 2,x
  1123.  bsr cvt convert year to ascii
  1124.  ldx #tstr point to string
  1125.  rts return
  1126.  
  1127.  pag
  1128.  
  1129. *
  1130. * tasxfr
  1131. *
  1132. * Transfer the 3 bytes of ascii indexed by b
  1133. * at y to location pointed at by x.
  1134. *
  1135.  
  1136. tasxfr pshs b index * 3
  1137.  aslb
  1138.  addb 0,s+
  1139.  leay b,y point to indexed data
  1140.  ldd 0,y xfr the data to x
  1141.  std 0,x++
  1142.  lda 2,y
  1143.  sta 0,x
  1144.  leax 2,x bump string pointer
  1145.  rts return
  1146.  
  1147. *
  1148. * cvt
  1149. *
  1150. * Convert number in b to ascii at x.
  1151. *
  1152.  
  1153. cvt lda #'0 set ascii 0
  1154. cvt2 cmpb #10 >10?
  1155.  blo cvt4
  1156.  subb #10 subtract off 10
  1157.  inca bump ascii
  1158.  bra cvt2 repeat
  1159. cvt4 addb #'0 make 1's ascii
  1160.  std 0,x++ save ascii at x
  1161.  rts return
  1162.  
  1163.  pag
  1164.  
  1165. *
  1166. * Strings and constants
  1167. *
  1168.  
  1169. nbmms fcc "Can't save mail.",$d
  1170. NBSZ equ *-nbmms
  1171. cctms fcc "Can't create temp file.",$d
  1172. CCSZ equ *-cctms
  1173. noms fcc 'You have no mail.',$d
  1174. NOMSZ equ *-noms
  1175. mlnam fcc '.mail',0
  1176. nfile fcc '/etc/log/password',0
  1177. savms fcb $d
  1178.  fcc 'Save mail? '
  1179. SAVSZ equ *-savms
  1180. mbnam fcc 'mailbox',0
  1181. comms fcc "Can't open '.mail'.",$d
  1182. COSZ equ *-comms
  1183. ermsg1 fcc "Can't send mail to '"
  1184. ERSZ1 equ *-ermsg1
  1185. ermsg2 fcc "'.",$d
  1186. ERSZ2 equ *-ermsg2
  1187. tmpn fcc '/tmp/mail'
  1188. tmpn2 fcc '        '
  1189. ylen fdb 365 year length
  1190.  fdb 366 leap year
  1191.  
  1192. mdays fdb 31,28,31,30,31,30,31,31,30,31,30,31
  1193.  
  1194.  
  1195. hdst fcb $d
  1196. tstr fcc 'xx:xx:xx xxx xxx xx xxxx',$d,0
  1197.  fcc 'received from '
  1198. HDSZ equ *-hdst
  1199. namslt fcc '            '
  1200.  
  1201. dtab fcc 'SunMonTueWedThuFriSat'
  1202.  
  1203. mtab fcc 'JanFebMarAprMayJunJulAugSepOctNovDec'
  1204.  
  1205. stkptr fdb 0 system stack ptr
  1206. all fcb 0 mail to all flag
  1207. usrnm fdb 0,0,0,0,0,0
  1208.  fdb 0,0,0,0,0,0
  1209.  
  1210. second fdb 0 seconds (0-59)
  1211. minute fdb 0 minutes (0-59)
  1212. hours fdb 0 hours (0-23)
  1213. wday fdb 0 week day (0-6) 0=Sunday
  1214. mday fdb 0 month day (1-31)
  1215. month fdb 0 month (0-11)
  1216. year fdb 0 year (80+)
  1217. yday fdb 0 day of year (0-355)
  1218. daylit fdb 0 daylight savings flag
  1219.  
  1220. icrt fcb create
  1221.  fdb usst
  1222. icrt2 fdb 0
  1223.  
  1224. iseek fcb seek
  1225. iseek1 fdb 0 hi pos
  1226. iseek2 fdb 0 low pos
  1227.  fdb 0 from beginning of file
  1228.  
  1229. iwrt fcb write
  1230.  fdb ibuf
  1231. iwrt2 fdb 0
  1232.  
  1233. iopn fcb open
  1234. iopn2 fdb 0,1
  1235.  
  1236. hwrt fcb write
  1237.  fdb hdst
  1238. hwrt2 fdb 0
  1239.  
  1240. ewrt fcb write
  1241. ewrt2 fdb 0
  1242. ewrt3 fdb 0
  1243.  
  1244. r0 fdb 0,0 regs for div and mul
  1245. r1 fdb 0,0
  1246. work fdb 0,0
  1247. day fdb 0 day temp
  1248. ntime fdb 0,0 new time
  1249. eutc fcb 0 east of utc flag
  1250. fstdl fdb 0 1st day of dlst
  1251. lstdl fdb 0 last day of dlst
  1252. dlflg fcb 0 dlst flag
  1253. ltime fdb 0,0 local time
  1254. tzn fdb 0,0 time zone seconds
  1255. tfd fdb 0 file desc
  1256. mfd fdb 0 file desc
  1257. argpt fdb 0 arg pointer
  1258. uid fdb 0 user id
  1259. linpt fdb 0 line pointer
  1260. linend fdb 0 end pointer
  1261. namfd fdb 0 file desc
  1262.  
  1263. tbuf rmb 8 time buffer
  1264. ibuf rmb 32 input buffer
  1265. stb rmb 24 status buffer
  1266. stb2 rmb 24 temp status buffer
  1267.  
  1268. linbuf rmb 128 line buffer
  1269. fbuf rmb 512 file buffer
  1270. usst rmb 100 path name for ".mail"
  1271. usst2 rmb 100 path name for "mailbox"
  1272.  
  1273.  
  1274.  end mail
  1275.