home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / stg_v4.lzh / postman.c < prev    next >
C/C++ Source or Header  |  1994-11-11  |  42KB  |  2,286 lines

  1. /*
  2.  * postman - mail delivery
  3.  *
  4.  * 93/04/18 StG new version from scratch
  5.  *
  6.  * TODO: go through each write() and rig delay for no free and proper
  7.  *            handling for segment list full (and match read len)
  8.  *
  9.  * USER DELIVERY MODE:
  10.  * postman [-tTO] {-sSUBJ} {-f} (file)
  11.  *  -f indicates binary message
  12.  * message is processed and placed in .mq file
  13.  * file is not deleted
  14.  *
  15.  * SERVICE DELIVERY MODE:
  16.  * postman (file)
  17.  * file must be in std STG mail format, must exist in spool dir, and
  18.  * calling process must be service or sysop
  19.  * file is renamed to .sq extension
  20.  *
  21.  * SPOOL DIRECTORY EXTENSIONS:
  22.  * mq - mail queue (must be tagged)
  23.  * mh - mail hold (postman hold queue)
  24.  * si - service in
  25.  * so - service out
  26.  * sq - service queue (must be tagged & named by service)
  27.  * ns - network send
  28.  * nr - network recv
  29.  * nq - network queue (must be tagged & named by system)
  30.  * pi - postman in (postman to postman service request)
  31.  *
  32.  * no external programs should use any of these extensions except
  33.  * network routines which can create .nq files.
  34. */
  35.  
  36. #include "stgnet.h"
  37. #include "pwd.h"
  38. #include "pm_util.h"
  39. #include "nodes.h"
  40. #include "db9.h"
  41.  
  42. #include <time.h>
  43.  
  44. #ifdef _OSK
  45. /* stupid OSK implimentation of dirent! */
  46. #include <direct.h>
  47. #include <dir.h>
  48. #define dirent direct
  49. #else
  50. #include <dirent.h>
  51. #endif
  52.  
  53. #define LOCK_FILE "postman.lck"
  54.  
  55. struct passwd *pw;
  56. char hostname[32];
  57.  
  58. int iPM_ID;
  59. int iPM_PRI;
  60.  
  61. char tempfile[32];
  62.  
  63. long lTime;
  64. struct tm *psTime;
  65.  
  66. /************************************************************************/
  67.  
  68. /* DAEMON globals */
  69. int hLock;            /* handle to lock file */
  70. int hNet;            /* handle to stgnet.db9 file */
  71. int resetroute=1;    /* update routing */
  72. DIR *dp;            /* directory handle */
  73. char rcvd_from[64];    /* RCVD: system/service name */
  74. int iOnHold=0;        /* file being processed is on hold flag */
  75. int iDebug=0;        /* debug mode flag */
  76. int iFromPM=0;        /* message is from postman flag */
  77.  
  78. struct sNode sNode;
  79.  
  80. #ifdef _OSK
  81. #define MAX_ROUTE 25
  82. #else
  83. #define MAX_ROUTE 10
  84. #endif
  85.  
  86. struct route
  87. {
  88.     char dest[32];    /* destination file/user */
  89.     int type;        /* type of route */
  90.     int path;        /* open handle to file */
  91. };
  92.  
  93. /* route type codes */
  94. #define RT_RTS  1    /* return to sender (misc reasons) */
  95. #define RT_HOLD 2    /* hold for later (misc reasons) */
  96. #define RT_NODE 3    /* deliver to node (name.ni) */
  97. #define RT_SERV 4    /* deliver to service (name.si) */
  98. #define RT_USER 5    /* deliver to user (file=user name) */
  99.  
  100. struct route asRoute[MAX_ROUTE];
  101. int routes;
  102.  
  103. char fromline[128];
  104. char fileline[128];
  105. char toline[128];
  106.  
  107. /************************************************************************/
  108.  
  109. Help()
  110. {
  111.     writeln(2,"postman - mail delivery\n",80);
  112.     writeln(2,"  FOR SYSTEM USE ONLY\n",80);
  113.     STGVER;
  114.     exit(0);
  115. }
  116.  
  117. pmlog(code,fmt,va_alist)
  118. int code;
  119. char *fmt;
  120. va_dcl
  121. {
  122.     va_list ap;
  123.     char pm_buf[256];
  124.  
  125.     va_start(ap);
  126.     if (iDebug)
  127.     {
  128.         writeln(iDebug,"LOG: ",5);
  129.         _strfmt(pm_buf,fmt,ap);
  130.         writeln(iDebug,pm_buf,strlen(pm_buf));
  131.         writeln(iDebug,"\n",1);
  132.     }
  133.     return(vsyslog(code,fmt,ap));
  134.     va_end(ap);
  135. }
  136.  
  137. tag(path)
  138. int path;
  139. {
  140. #ifdef _OSK
  141.     int tag;
  142.     struct fildes fd;
  143.  
  144.     if (_gs_gfd(path,&fd,sizeof(fd))==ERR)
  145.         return(ERR);
  146.  
  147.     tag=fd.fd_date[2]*fd.fd_date[3];
  148.     fd.fd_date[4]=tag%60;
  149.  
  150.     if (_ss_pfd(path,&fd)==ERR)
  151.         return(ERR);
  152.  
  153. #endif
  154.     return(0);
  155. }
  156.  
  157. untag(path)
  158. int path;
  159. {
  160. #ifdef _OSK
  161.     int tag;
  162.     struct fildes fd;
  163.  
  164.     if (_gs_gfd(path,&fd,sizeof(fd))==ERR)
  165.         return(ERR);
  166.  
  167.     tag=fd.fd_date[2]*fd.fd_date[3]+1;
  168.     fd.fd_date[4]=tag%60;
  169.  
  170.     if (_ss_pfd(path,&fd)==ERR)
  171.         return(ERR);
  172.  
  173. #endif
  174.     return(0);
  175. }
  176.  
  177. tagged(path)
  178. {
  179. #ifdef _OSK
  180.     int tag;
  181.     struct fildes fd;
  182.  
  183.     if (_gs_gfd(path,&fd,sizeof(fd))==ERR)
  184.         return(0);
  185.  
  186.     tag=fd.fd_date[2]*fd.fd_date[3];
  187.     if (fd.fd_date[4]==tag%60)
  188.         return(1);
  189.  
  190. #endif
  191.     return(0);
  192. }
  193.  
  194. char *vers[]=
  195. {
  196.     "stg_net",
  197.     "smon",
  198.     "syslog",
  199.     "error",
  200.     "slogin",
  201.     "password",
  202.     "smenu",
  203.     "postman",
  204.     "smail",
  205.     "msgedt",
  206.     "termlist",
  207.     "userlist",
  208.     "servlist",
  209.     "nodelist",
  210.     "sroute",
  211.     0
  212. };
  213.  
  214. Interactive()
  215. {
  216.     int n;
  217.     char *args[8];
  218.     char **ppcTemp;
  219.  
  220.     /* run as user postman - all commands should be okay for public use */
  221.     setuid(iPM_ID);
  222.  
  223.     openerr("postman",0,LOG_STGNET);
  224.  
  225.     stringf(b,"POSTMAN @ %s - StG-Net %s\n",hostname,STG_VER);
  226.     writeln(1,b,80);
  227.     writeln(1,"\n",1);
  228.     writeln(1,"Enter 'help' for command list\n",80);
  229.  
  230. prompt:
  231.     writeln(1,"\n",1);
  232.     write(1,"postman: ",9);
  233.     n=readln(0,b,70);
  234.     if (n==ERR)
  235.         exit(syserr("readln: %m"));
  236.     if (!n)
  237.     {
  238.         writeln(1,"[EOF]\n",80);
  239.         goto quit;
  240.     }
  241.     if (!isatty(0))
  242.         writeln(1,b,n);
  243.  
  244.     b[n-1]=0;
  245.  
  246.     if (!stricmp(b,"quit"))
  247.         goto quit;
  248.  
  249.     if (*b=='?' || !stricmp(b,"help"))
  250.     {
  251.         writeln(1,"versions         - list version of modules on this node\n",80);
  252.         writeln(1,"nodelist         - list all network nodes\n",80);
  253.         writeln(1,"servlist         - list availabile services\n",80);
  254.         writeln(1,"userlist         - list known users\n",80);
  255.         writeln(1,"userinfo (name)  - show details about user\n",80);
  256.         writeln(1,"finduser (name)  - search for user by partial name\n",80);
  257.         writeln(1,"sroute           - show network routing for this node\n",80);
  258.         writeln(1,"help -or- ?      - this list\n",80);
  259.         writeln(1,"quit             - exit postman\n",80);
  260.         goto prompt;
  261.     }
  262.  
  263.     if (!stricmp(b,"versions"))
  264.     {
  265.         ppcTemp=vers;
  266.         while (*ppcTemp)
  267.         {
  268.             args[0]=*ppcTemp++;
  269.             args[1]="-#";
  270.             args[2]=0;
  271.             if (_fork(*args,args,environ)==ERR)
  272.                 syserr("fork %s: %m",*args);
  273.             else
  274.                 wait(0);
  275.         }
  276.         goto prompt;
  277.     }
  278.  
  279.     if
  280.     (
  281.         !stricmp(b,"nodelist") ||
  282.         !stricmp(b,"servlist") ||
  283.         !stricmp(b,"userlist") ||
  284.         !stricmp(b,"sroute")
  285.     )
  286.     {
  287.         args[0]=b;
  288.         args[1]=0;
  289.         goto fork_it;
  290.     }
  291.  
  292.     if (!strincmp(b,"nodeinfo ",9) && b[9]!='-')
  293.     {
  294.         args[0]="nodelist";
  295.         args[1]=b+9;
  296.         args[2]=0;
  297.         goto fork_it;
  298.     }
  299.  
  300.     if (!strincmp(b,"userinfo ",9) && b[9]!='-')
  301.     {
  302.         args[0]="userlist";
  303.         args[1]=b+9;
  304.         args[2]=0;
  305.         goto fork_it;
  306.     }
  307.  
  308.     if (!strincmp(b,"finduser ",9) && b[9]!='-')
  309.     {
  310.         args[0]="userlist";
  311.         args[1]="-f";
  312.         args[2]=b+9;
  313.         args[3]=0;
  314.         goto fork_it;
  315.     }
  316.  
  317.     writeln(2,"Unknown command - enter 'help' for list\n",80);
  318.     goto prompt;
  319.  
  320. fork_it:
  321.     if (_fork(*args,args,environ)==ERR)
  322.         syserr("fork %s: %m",*args);
  323.     else
  324.         wait(0);
  325.     goto prompt;
  326.  
  327. quit:
  328.     writeln(1,"\n",1);
  329.     writeln(1,"Nice chatting with you.\n");
  330.     exit(0);
  331. }
  332.  
  333. /* create asRoute[] entry, open file, write fromline, to, etc */
  334. void
  335. Route(to)
  336. char *to;
  337. {
  338.     char dest[32];    /* destination file/user */
  339.     int type;        /* destination type */
  340.     char *reason;    /* reason for rts */
  341.     int n,r;
  342.     int temp;
  343.     char rb[80];    /* route buffer (@*) */
  344.  
  345.     *dest=0;
  346.  
  347.     if (iDebug)
  348.         writeln(iDebug,to,80);
  349.  
  350.     if (_pm_addr(to+6)==ERR)
  351.     {
  352.         type=RT_RTS;
  353.         reason="invalid destination address";
  354.         pmlog(LOG_INFO,"bad destination: %s (rts)",to+6);
  355.         goto route;
  356.     }
  357.  
  358.     if (*A_host)
  359.     {
  360.         if (!*hostname)
  361.         {
  362.             type=RT_RTS;
  363.             reason="network not configured";
  364.             pmlog(LOG_ERR,"message to %s w/o network loaded (rts)",A_host);
  365.             goto route;
  366.         }
  367.  
  368.         if (!strcmp(A_host,"*"))
  369.         {
  370.             /* all hosts mode */
  371.             _db9(DB_SEEK,hNet,0,0);  /* rewind */
  372.             while (n=_db9(DB_NEXT,hNet,&sNode,sizeof(sNode)))
  373.             {
  374.                 if (n==ERR)
  375.                     goto db_err;
  376.                 _db9(DB_ULOCK,hNet,0,0);
  377.                 stringf(rb,"TO  : %s@%s\n",A_user,sNode.acN_Name);
  378.                 if (sNode.bN_Status!=NS_DEAD)
  379.                     Route(rb);
  380.             }
  381.             return;
  382.         }
  383.  
  384.         if (stricmp(A_host,sNode.acN_Name))
  385.         {
  386.             n=_db9(DB_SEEK,hNet,A_host,strlen(A_host)+1);
  387.             if (n==ERR)
  388.                 goto db_err;
  389.             if (!n)
  390.             {
  391.                 type=RT_RTS;
  392.                 reason="destination node is unknown";
  393.                 goto route;
  394.             }
  395.         }
  396.         if (stricmp(hostname,A_host))
  397.         {
  398.             /* need to forward to another node */
  399.  
  400.             if (stricmp(A_host,sNode.acN_Name))
  401.             {
  402.                 if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
  403.                     goto db_err;
  404.                 _db9(DB_ULOCK,hNet,0,0);
  405.             }
  406.  
  407.             if (sNode.bN_Status==NS_DEAD)
  408.             {
  409.                 pmlog(LOG_INFO,"node %s is dead, RTS",A_host);
  410.                 type=RT_RTS;
  411.                 reason="destination node is dead";
  412.                 goto route;
  413.             }
  414.  
  415.             if (!*sNode.sRoute.acN2_Name)
  416.             {
  417.                 pmlog(LOG_INFO,"no route to node %s, holding message",sNode.acN_Name);
  418.                 type=RT_HOLD;
  419.                 goto route;
  420.             }
  421.  
  422.             type=RT_NODE;
  423.             strcpy(dest,sNode.sRoute.acN2_Name);
  424.             goto route;
  425.         }
  426.     }
  427.     /* if drops through to here, message is local */
  428.     pw=getpwnam(A_user);
  429.     if (!pw)
  430.     {
  431.         type=RT_RTS;
  432.         reason="unknown user";
  433.         goto route;
  434.     }
  435.     if (*pw->pw_shell=='!' || *pw->pw_shell=='%')
  436.     {
  437.         type=RT_SERV;
  438.         strcpy(dest,pw->pw_name);
  439.         goto route;
  440.     }
  441.     if (!*pw->pw_dir)
  442.     {
  443.         if (iDebug)
  444.             wstringf(iDebug,"user has no directory\n");
  445.         type=RT_RTS;
  446.         reason="user is not accepting mail";
  447.         goto route;
  448.     }
  449.  
  450.     /* home dir must be accessable as user */
  451.     setuid(pw->pw_uid);
  452.     if (access(pw->pw_dir,
  453. #ifdef _OS9
  454.                 O_DIR|O_RDWR
  455. #else
  456.                 0
  457. #endif
  458.                     )==ERR)
  459.     {
  460.         if (iDebug)
  461.             wstringf(iDebug,"user directory not accessable: %m");
  462.         setuid(0);
  463.         type=RT_RTS;
  464.         reason="user is not accepting mail";
  465.         goto route;
  466.     }
  467.     setuid(0);
  468.  
  469.     type=RT_USER;
  470.     strcpy(dest,pw->pw_name);
  471.     goto route;
  472.  
  473. db_err:
  474.     pmlog(LOG_ERR,"DB9 error (holding msg): %m");
  475.     type=RT_HOLD;
  476.  
  477. route:
  478.     /* check route table for duplicate path */
  479.     r=0;
  480.     while (r<routes)
  481.     {
  482.         if (asRoute[r].type==type)
  483.         {
  484.             if (!*dest || !stricmp(asRoute[r].dest,dest))
  485.                 break;
  486.         }
  487.         r++;
  488.     }
  489.     if (r<routes)
  490.     {
  491.         if (iDebug)
  492.             wstringf(iDebug,"using existing route entry path=%d\n",
  493.                 asRoute[r].path);
  494.         goto addto;
  495.     }
  496.  
  497.     if (routes==MAX_ROUTE-1)
  498.     {
  499.         /* if about to re-use last route entry, put on hold */
  500.         if (iDebug)
  501.             wstringf(iDebug,"route table limit hit - putting msg on hold\n");
  502.         *dest=0;
  503.         type=RT_HOLD;
  504.         goto route;
  505.     }
  506.  
  507.     /* select destination file */
  508.     switch (type)
  509.     {
  510.     case RT_RTS:
  511.         if (iDebug)
  512.             wstringf(iDebug,"route: RTS \"%s\"\n",reason);
  513.  
  514.         /* create normal mail queue file */
  515.         _pm_temp(b);
  516.         strcat(b,".mq");
  517.         temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  518.         if (temp==ERR)
  519.         {
  520.             pmlog(LOG_ERR,"create %s: %m",b);
  521.             type=RT_HOLD;
  522.             goto route;
  523.         }
  524.         /* mail comes from postman */
  525.         strcpy(b,"FROM: postman");
  526.         if (*hostname)
  527.         {
  528.             strcat(b,"@");
  529.             strcat(b,hostname);
  530.         }
  531.         strcat(b," (mail delivery service)\n");
  532.         writeln(temp,b,strlen(b));
  533.  
  534.         if (iFromPM)
  535.         {
  536.             /* mail was already from postman, send to sysop instead */
  537.             strcpy(b,"TO  : sysop\n");
  538.             writeln(temp,b,strlen(b));
  539.  
  540.             strcpy(b,"SUBJ: message returned to postman\n");
  541.             writeln(temp,b,strlen(b));
  542.         }
  543.         else
  544.         {
  545.             /* create to: from from: */
  546.             strcpy(b,"TO  : ");
  547.             strcpy(b+6,fromline+6);
  548.             writeln(temp,b,strlen(b));
  549.  
  550.             /* and subject (mostly to separate real to: from error to: */
  551.             strcpy(b,"SUBJ: message returned to sender\n");
  552.             writeln(temp,b,strlen(b));
  553.         }
  554.  
  555.         /* add to route table */
  556.         *asRoute[r].dest=0;
  557.         asRoute[r].type=RT_RTS;
  558.         asRoute[r].path=temp;
  559.         routes++;
  560.         if (iDebug)
  561.             wstringf(iDebug,"new route path=%d\n",temp);
  562.         break;
  563.         
  564.     case RT_HOLD:
  565.         if (iOnHold)    /* was already on hold */
  566.             break;
  567.         _pm_temp(b);
  568.         strcat(b,".mh");
  569.         if (iDebug)
  570.             wstringf(iDebug,"route: HOLD %s\n",b);
  571.         temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  572.         if (temp==ERR)
  573.         {            
  574.             pmlog(LOG_ERR,"creat %s: %m",b);
  575.             if (iDebug)
  576.                 wstringf(iDebug,"sleeping 5 min\n");
  577.  
  578.             /* what the heck do I do now??? */
  579.             /* try sleeping for a while and retry */
  580.             /* and hope the sysop catches it */
  581.             sleep(5*60);
  582.             goto route;
  583.         }
  584.         writeln(temp,fromline,strlen(fromline));
  585.  
  586.         *asRoute[r].dest=0;
  587.         asRoute[r].type=RT_HOLD;
  588.         asRoute[r].path=temp;
  589.         routes++;
  590.         if (iDebug)
  591.             wstringf(iDebug,"new route path=%d\n",temp);
  592.         break;
  593.  
  594.     case RT_NODE:
  595.         if (iDebug)
  596.             wstringf(iDebug,"route: NODE %s\n",dest);
  597.         strcpy(b,dest);
  598.         strcat(b,".ni");
  599.         temp=open(b,O_EXCL|O_RDWR);
  600.         if (temp==ERR)
  601.         {
  602.             if (errno==253)    /* file is busy */
  603.             {
  604.                 type=RT_HOLD;
  605.                 *dest=0;
  606.                 goto route;
  607.             }
  608.             if (errno!=216) /* file not found */
  609.             {
  610.                 pmlog(LOG_ERR,"open %s: %m",b);
  611.                 type=RT_HOLD;
  612.                 *dest=0;
  613.                 goto route;
  614.             }
  615.             temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  616.             if (temp==ERR)
  617.             {
  618.                 pmlog(LOG_ERR,"creat %s: %m",b);
  619.                 type=RT_HOLD;
  620.                 *dest=0;
  621.                 goto route;
  622.             }
  623.         }
  624.         lseek(temp,0L,2);
  625.         /* put check in for ~ termination ? */
  626.         writeln(temp,fromline,strlen(fromline));
  627.  
  628.         strcpy(asRoute[r].dest,dest);
  629.         asRoute[r].type=RT_NODE;
  630.         asRoute[r].path=temp;
  631.         routes++;
  632.         if (iDebug)
  633.             wstringf(iDebug,"new route path=%d\n",temp);
  634.         break;
  635.  
  636.     case RT_SERV:
  637.         if (iDebug)
  638.             wstringf(iDebug,"route: SERV %s\n",dest);
  639.         strcpy(b,dest);
  640.         if (iFromPM)
  641.             strcat(b,".pi");
  642.         else
  643.             strcat(b,".si");
  644.         temp=open(b,0);
  645.         if (temp!=ERR)
  646.         {
  647.             /* if file exists, put on hold */
  648.             close(temp);
  649.             *dest=0;
  650.             type=RT_HOLD;
  651.             goto route;
  652.         }
  653.         if (temp==ERR && errno!=216) /* if not not found, exists */
  654.         {
  655.             if (errno!=253)
  656.                 pmlog(LOG_ERR,"open %s: %m",b);
  657.             *dest=0;
  658.             type=RT_HOLD;
  659.             goto route;
  660.         }
  661.         temp=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  662.         if (temp==ERR)
  663.         {
  664.             pmlog(LOG_ERR,"creat %s: %m",b);
  665.             type=RT_HOLD;
  666.             *dest=0;
  667.             goto route;
  668.         }
  669.         writeln(temp,fromline,strlen(fromline));
  670.  
  671.         strcpy(asRoute[r].dest,dest);
  672.         asRoute[r].type=RT_SERV;
  673.         asRoute[r].path=temp;
  674.         routes++;
  675.         if (iDebug)
  676.             wstringf(iDebug,"new route path=%d\n",temp);
  677.         break;
  678.             
  679.     case RT_USER:
  680.         if (iDebug)
  681.             wstringf(iDebug,"route: USER %s\n",dest);
  682.         pw=getpwnam(dest);
  683.         if (!pw)
  684.         {
  685.             /* say what!? */
  686.             pmlog(LOG_ERR,"internal bug #1: dest='%s'",dest);
  687.             type=RT_RTS;
  688.             *dest=0;
  689.             goto route;
  690.         }
  691.         stringf(b,"%s/mailbox",pw->pw_dir);
  692.  
  693.         /* don't open exclusive 'cuz mail is written to detect new msgs */
  694.         temp=open(b,/*O_EXCL|*/O_RDWR);
  695.         if (temp==ERR)
  696.         {
  697.             if (errno!=216)
  698.             {
  699.                 pmlog(LOG_ERR,"open %s: %m",b);
  700.                 type=RT_HOLD;
  701.                 *dest=0;
  702.                 goto route;
  703.             }
  704.             temp=create(b,O_RDWR,S_IREAD|S_IWRITE);
  705.             if (temp==ERR)
  706.             {
  707.                 pmlog(LOG_ERR,"creat %s: %m",b);
  708.                 type=RT_HOLD;
  709.                 *dest=0;
  710.                 goto route;
  711.             }
  712.         }
  713.         lseek(temp,0L,2);
  714.         /* check for ~ ? */
  715.         writeln(temp,fromline,strlen(fromline));
  716.  
  717.         strcpy(asRoute[r].dest,dest);
  718.         asRoute[r].type=RT_USER;
  719.         asRoute[r].path=temp;
  720.         routes++;
  721.         if (iDebug)
  722.             wstringf(iDebug,"new route path=%d\n",temp);
  723.         break;
  724.     }
  725.  
  726. addto:
  727.     /* write to: line */
  728.     write(asRoute[r].path,to,strlen(to));
  729.  
  730.     switch (type)
  731.     {
  732.     case RT_RTS:
  733.         stringf(b,"ERR : %s\n",reason);
  734.         writeln(asRoute[r].path,b,strlen(b));
  735.         break;
  736.     }
  737. }
  738.  
  739. /* check tag and return !0 if not okay */
  740. ChkTag(file)
  741. char *file;
  742. {
  743.     int path;
  744.  
  745.     path=open(file,0);
  746.     if (path==ERR)
  747.     {
  748.         if (errno==253);
  749.         {
  750.             if (iDebug)
  751.                 wstringf(iDebug,"File is busy\n");
  752.             return(1);    /* file is busy, try again later */
  753.         }
  754.         pmlog(LOG_ERR,"open %s: %m",file);
  755.         return(1);
  756.     }
  757.  
  758.     if (!tagged(path))
  759.     {
  760.         /* move to temp file, bug sysop about it */
  761.         _pm_temp(tempfile);
  762.         strcat(tempfile,".err");
  763.  
  764.         close(path);
  765.         if (_rename(file,tempfile)==ERR)
  766.         {
  767.             pmlog(LOG_ERR,"rename %s %s: %m",file,tempfile);
  768.             return(1);
  769.         }
  770.         if (iDebug)
  771.             wstringf(iDebug,"File is not tagged - saved to %s\n",tempfile);
  772. /*        MailSysop(tempfile,"file not tagged"); */
  773.         return(1);
  774.     }
  775.     close(path);
  776.     return(0);
  777. }
  778.  
  779. void
  780. Process(file)
  781. char *file;
  782. {
  783.     int path,temp;
  784.     long frompos,currpos,filesize;
  785.     int n,r;
  786.     int da;    /* done already flg */
  787.  
  788.     if (iDebug)
  789.         wstringf(iDebug,"Process(\"%s\")\n",file);
  790.  
  791.     *sNode.acN_Name=0;
  792.  
  793.     if (ChkTag(file))
  794.         return;
  795.  
  796.     path=open(file,O_EXCL|O_RDWR);
  797.     if (path==ERR)
  798.     {
  799.         if (errno==253)
  800.         {
  801.             if (iDebug)
  802.                 wstringf(iDebug,"File is busy\n");
  803.             return;        /* file open by another process??? */
  804.         }
  805.  
  806.         pmlog(LOG_ERR,"open %s: %m",file);
  807.         return;
  808.     }
  809.     iOnHold=(!strcmp(file+strlen(file)-3,".mh"));
  810.  
  811.     while (1)
  812.     {
  813.         da=0;
  814.         *fileline=0;
  815.         routes=0;
  816.  
  817.         frompos=lseek(path,0L,1);
  818.  
  819.         n=readln(path,fromline,80);
  820.         if (!n)
  821.             break;
  822.         if (n==ERR)
  823.         {
  824.             pmlog(LOG_ERR,"read (from): %m");
  825.             break;
  826.         }
  827.         if (iDebug)
  828.             writeln(iDebug,fromline,n);
  829.         fromline[n]=0;
  830.  
  831.         if (*fromline=='f')
  832.         {
  833.             if (iDebug)
  834.                 wstringf(iDebug,"Message has been processed already\n");
  835.             da=1;
  836.             *fromline='F';
  837.         }
  838.  
  839.         if (strncmp(fromline,"FROM: ",6))
  840.         {
  841.             _pm_temp(tempfile);
  842.             strcat(tempfile,".err");
  843.  
  844.             temp=create(tempfile,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  845.             if (temp==ERR)
  846.             {
  847.                 pmlog(LOG_ERR,"creat %s: %m",tempfile);
  848.                 return;
  849.             }
  850.             lseek(path,frompos,0);
  851.             while (1)
  852.             {
  853.                 n=readln(path,b,80);
  854.                 if (!n || n==ERR)
  855.                     break;
  856.                 writeln(temp,b,n);
  857.                 if (n==2 && *b=='~')
  858.                     break;
  859.             }
  860.             if (iDebug)
  861.                 wstringf(iDebug,"missing FROM: - saved to %s\n",tempfile);
  862. /*            MailSysop(tempfile,"missing FROM: header (out of sync)"); */
  863.             continue;
  864.         }
  865.  
  866.         _pm_addr(fromline+6);
  867.         iFromPM=!stricmp(A_user,"postman");
  868.  
  869.         while (1)
  870.         {
  871.             errno=211;
  872.             n=readln(path,toline,80);
  873.             if (!n || n==ERR)
  874.             {
  875.                 pmlog(LOG_ERR,"read (to): %m");
  876.                 goto die;
  877.             }
  878.             if (strncmp(toline,"TO  : ",6))
  879.                 break;
  880.             toline[n]=0;
  881.             if (!da)
  882.                 Route(toline);
  883.         }
  884.         if (!da && !routes)
  885.         {
  886.             if (iOnHold)
  887.             {
  888.                 if (iDebug)
  889.                     writeln(iDebug,"Leaving file on hold\n",80);
  890.                 tag(path);
  891.                 close(path);
  892.                 return;
  893.             }
  894.             Route("TO  : sysop\n");
  895.             strcpy(b,"ERR : message routed to sysop because it has no destination address\n");
  896.             if (routes)
  897.                 writeln(asRoute[0].path,b,strlen(b));
  898.             if (iDebug)
  899.                 writeln(iDebug,b,strlen(b));
  900.         }
  901.         strcpy(b,toline);
  902.         while (1)
  903.         {
  904.             /* if line is terminator, skip back and continue */
  905.             if (n==2 && *b=='~')
  906.             {
  907.                 lseek(path,-2l,1);
  908.                 break;
  909.             }
  910.  
  911.             if (iDebug)
  912.                 writeln(iDebug,b,strlen(b));
  913.  
  914.             r=0;
  915.             if (!strncmp(b,"FILE: ",6))
  916.                 strcpy(fileline,b);
  917.             else
  918.                 while (r<routes)
  919.                     writeln(asRoute[r++].path,b,n);
  920.  
  921.             errno=211;
  922.             n=readln(path,b,80);
  923.             if (!n || n==ERR)
  924.             {
  925.                 pmlog(LOG_ERR,"read (header): %m");
  926.                 goto die;
  927.             }
  928.             b[n]=0;
  929.             if (n==1)
  930.                 break;
  931.         }
  932.         if (*rcvd_from)
  933.         {
  934.             time(&lTime);
  935.             psTime=localtime(&lTime);
  936.             stringf(b,"RCVD: %02d/%02d/%02d %02d:%02d:%02d %s\n",
  937.                 psTime->tm_year,
  938.                 psTime->tm_mon+1,
  939.                 psTime->tm_mday,
  940.                 psTime->tm_hour,
  941.                 psTime->tm_min,
  942.                 psTime->tm_sec,
  943.                 rcvd_from);
  944.             n=strlen(b);
  945.             r=0;
  946.             while (r<routes)
  947.                 writeln(asRoute[r++].path,b,n);
  948.         }
  949.         if (*fileline)
  950.         {
  951.             currpos=lseek(path,0L,1);
  952.             filesize=atol(fileline+6);
  953.             lseek(path,filesize,1);
  954.             n=readln(path,b,80);
  955.             if (n!=2 || *b!='~')
  956.             {
  957.                 pmlog(LOG_ERR,"file lost: sync error");
  958.                 strncpy(fileline,"LOST",4);
  959.                 filesize=0;
  960.                 if (iDebug)
  961.                     writeln(iDebug,fileline,strlen(fileline));
  962.             }
  963.             lseek(path,currpos,0);
  964.             n=strlen(fileline);
  965.             r=0;
  966.             while (r<routes)
  967.             {
  968.                 writeln(asRoute[r].path,b,n);
  969.                 writeln(asRoute[r++].path,"\n",1);
  970.             }
  971.             while (filesize)
  972.             {
  973.                 if (filesize>BUF_SIZE)
  974.                     n=BUF_SIZE;
  975.                 else
  976.                     n=filesize;
  977.                 errno=211;
  978.                 n=read(path,b,n);
  979.                 if (!n || n==ERR)
  980.                 {
  981.                     pmlog(LOG_ERR,"read (file): %m");
  982.                     goto die;
  983.                 }
  984.                 r=0;
  985.                 while (r<routes)
  986.                     write(asRoute[r++].path,b,n);
  987.                 filesize-=n;
  988.             }
  989.             r=0;
  990.             while (r<routes)
  991.             {
  992.                 /* don't terminate service file */
  993.                 if (asRoute[r].type!=RT_SERV)
  994.                     write(asRoute[r].path,"~\n",2);
  995.                 r++;
  996.             }
  997.         }
  998.         else
  999.         {
  1000.             r=0;
  1001.             while (r<routes)
  1002.                 writeln(asRoute[r++].path,"\n",1);
  1003.             while (1)
  1004.             {
  1005.                 errno=211;
  1006.                 n=readln(path,b,BUF_SIZE);
  1007.                 if (!n || n==ERR)
  1008.                 {
  1009.                     pmlog(LOG_ERR,"read (msg): %m");
  1010.                     goto die;
  1011.                 }
  1012.                 if (n==2 && *b=='~')
  1013.                     break;
  1014.  
  1015.                 r=0;
  1016.                 while (r<routes)
  1017.                     writeln(asRoute[r++].path,b,n);
  1018.             }
  1019.             r=0;
  1020.             while (r<routes)
  1021.             {
  1022.                 /* don't terminate service file */
  1023.                 if (asRoute[r].type!=RT_SERV)
  1024.                     write(asRoute[r].path,"~\n",2);
  1025.                 r++;
  1026.             }
  1027.         }
  1028.         r=0;
  1029.         while (r<routes)
  1030.         {
  1031.             tag(asRoute[r].path);
  1032.             close(asRoute[r].path);
  1033.             r++;
  1034.         }
  1035.         
  1036.         currpos=lseek(path,0L,1);
  1037.         lseek(path,frompos,0);
  1038.         write(path,"f",1);
  1039.         lseek(path,currpos,0);
  1040.     }
  1041.     goto dun;
  1042.  
  1043. die:
  1044.     strcpy(b,"*** READ ERROR IN POSTMAN ***\n");
  1045.     n=strlen(b);
  1046.     r=0;
  1047.     while (r<routes)
  1048.     {
  1049.         writeln(asRoute[r].path,b,n);
  1050.         writeln(asRoute[r].path,"~\n",2);
  1051.         tag(asRoute[r].path);
  1052.         close(asRoute[r].path);
  1053.         r++;
  1054.     }
  1055.  
  1056. dun:
  1057.     if (_ss_size(path,0L)==ERR)
  1058.         pmlog(LOG_ERR,"_ss_size 0: %m");
  1059.     close(path);
  1060.     if (unlink(file)==ERR)
  1061.         pmlog(LOG_ERR,"unlink %s: %m",file);
  1062.     if (iDebug)
  1063.         wstringf(iDebug,"processing of %s complete\n",file);
  1064. }
  1065.  
  1066. void
  1067. Service(file)
  1068. char *file;
  1069. {
  1070.     int path;
  1071.     int outfile;
  1072.     int status;
  1073.     int n;
  1074.     char *args[10];
  1075.     char **ppc;
  1076.  
  1077.     if (iDebug)
  1078.         wstringf(iDebug,"Service(\"%s\")\n",file);
  1079.  
  1080.     if (ChkTag(file))
  1081.         return;
  1082.  
  1083.     path=open(file,O_EXCL|O_RDWR);
  1084.     if (path==ERR)
  1085.     {
  1086.         if (errno==253)
  1087.         {
  1088.             if (iDebug)
  1089.                 wstringf(iDebug,"File should not be busy!\n");
  1090.             return;
  1091.         }
  1092.         pmlog(LOG_ERR,"open %s: %m",file);
  1093.         return;
  1094.     }
  1095.  
  1096.     errno=211;
  1097.     n=readln(path,fromline,80);
  1098.     if (!n || n==ERR)
  1099.     {
  1100.         pmlog(LOG_ERR,"read (from): %m");
  1101.         close(path);
  1102.         return;
  1103.     }
  1104.     if (iDebug)
  1105.         writeln(iDebug,fromline,n);
  1106.     fromline[n]=0;
  1107.  
  1108.     if (strncmp(fromline,"FROM: ",6))
  1109.     {
  1110.         pmlog(LOG_ERR,"unexpected header in %s\n",file);
  1111.         close(path);
  1112.         return;
  1113.     }
  1114.  
  1115.     while (n>1)
  1116.     {
  1117.         errno=211;
  1118.         n=readln(path,b,BUF_SIZE);
  1119.         if (!n || n==ERR)
  1120.         {
  1121.             pmlog(LOG_ERR,"read (hdr): %m");
  1122.             close(path);
  1123.             return;
  1124.         }
  1125.     }
  1126.  
  1127.     strcpy(b,file);
  1128.     strcut(b,'.');
  1129.     pw=getpwnam(b);
  1130.     if (!pw || !pw->pw_shell | !*pw->pw_shell)
  1131.     {
  1132.         pmlog(LOG_ERR,"cant find service '%s'",b);
  1133.         close(path);
  1134.         return;
  1135.     }
  1136.     if (*pw->pw_shell!='!')
  1137.     {
  1138.         pmlog(LOG_ERR,"unknown service code '%s'",pw->pw_shell);
  1139.         close(path);
  1140.         return;
  1141.     }
  1142.  
  1143.     _pm_temp(tempfile);
  1144.     strcat(tempfile,".tmp");
  1145.     outfile=create(tempfile,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  1146.     if (outfile==ERR)
  1147.     {
  1148.         pmlog(LOG_ERR,"create %s: %m",tempfile);
  1149.         close(path);
  1150.         return;
  1151.     }
  1152.  
  1153.     if (pw->pw_dir && *pw->pw_dir)
  1154.     if (chdir(pw->pw_dir)==ERR)
  1155.     {
  1156.         pmlog(LOG_ERR,"chd %s: %m",pw->pw_dir);
  1157.         close(path);
  1158.         return;
  1159.     }
  1160. #ifdef _OS9
  1161.     setpr(getpid(),pw->pw_pri);
  1162. #endif
  1163.     setuid(pw->pw_uid);
  1164.  
  1165.     close(0); dup(path);
  1166.     close(1); dup(outfile);
  1167.     close(2); dup(outfile);
  1168.  
  1169.     strcpy(b,pw->pw_shell);
  1170.  
  1171.     /* should process into b for %f=from, %s=subj here */
  1172.  
  1173.     if (iDebug)
  1174.         wstringf(iDebug,"forking '%s'\n",b);
  1175.  
  1176. retry1:
  1177.     ppc=arglist(b,0);
  1178.     if (!ppc)
  1179.     {
  1180.         pmlog(LOG_ERR,"arglist (malloc): %m");
  1181.         sleep(60);
  1182.         goto retry1;
  1183.     }
  1184.  
  1185.     if (_fork(*ppc+1,ppc,environ)==ERR)
  1186.         pmlog(LOG_ERR,"fork: %s: %m",*ppc+1);
  1187.     else
  1188.     {
  1189.         wait(&status);
  1190.         if (status)
  1191.         {
  1192.             errno=status;
  1193.             wstringf(2,"%s exited with error: %m",b);
  1194.         }
  1195.     }
  1196.     free(ppc);
  1197.  
  1198.     close(0); close(1); close(2);
  1199.     dup(hLock); dup(hLock); dup(hLock);
  1200.  
  1201.     if (_gs_size(outfile))
  1202.     {
  1203.         close(outfile);
  1204.         strcpy(b,fromline+6);
  1205.         strcut(b,' ');
  1206.         if (iDebug)
  1207.             wstringf(iDebug,"returning output to %s\n",b);
  1208.         args[0]="postman";
  1209.         args[1]="-t";
  1210.         args[2]=b;
  1211.         args[3]="-sOutput from service request";
  1212.         args[4]=tempfile;
  1213.         args[5]=0;
  1214.         if (_fork(*args,args,environ)==ERR)
  1215.              pmlog(LOG_ERR,"fork %s: %m",*args);
  1216.         else
  1217.             wait(0);
  1218.     }
  1219.     else
  1220.         close(outfile);
  1221.  
  1222.     setuid(0);
  1223.     if (chdir(SPL_DIR)==ERR)
  1224.     {
  1225.         pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
  1226.         exit(errno);
  1227.     }
  1228.     close(path);
  1229.     unlink(file);
  1230.  
  1231.     unlink(tempfile);
  1232. #ifdef _OS9
  1233.     setpr(getpid(),iPM_PRI);
  1234. #endif
  1235.     if (iDebug)
  1236.         wstringf(iDebug,"processing of %s complete\n",file);
  1237. }
  1238.  
  1239. pm_nu(path,node)
  1240. int path;
  1241. char *node;
  1242. {
  1243.     int n,found;
  1244.     char **args;
  1245.  
  1246.     if (!stricmp(node,hostname))
  1247.     {
  1248.         /* another node is sending me my info - ignore it */
  1249.         return(0);        
  1250.     }
  1251.  
  1252.     if (iDebug)
  1253.         wstringf(iDebug,"Processing nu for %s\n",node);
  1254.  
  1255.     resetroute=1;    /* force update of routing */
  1256.  
  1257.     found=_db9(DB_SEEK,hNet,node,strlen(node)+1);
  1258.     if (found==ERR)
  1259.     {
  1260.         pmlog(LOG_ERR,"DB9 seek %s: %m",node);
  1261.         return(ERR);
  1262.     }
  1263.  
  1264.     if (found)
  1265.     {
  1266.         if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
  1267.         {
  1268.             pmlog(LOG_ERR,"DB9 read %s: %m",node);
  1269.             return(ERR);
  1270.         }
  1271.     }
  1272.     else
  1273.     {
  1274.         memset(&sNode,0,sizeof(sNode));
  1275.         strcpy(sNode.acN_Name,node);
  1276.     }
  1277.  
  1278.     while (n=readln(path,b,BUF_SIZE))
  1279.     {
  1280.         if (!n)
  1281.         {
  1282.             n=ERR;
  1283.             errno=211;
  1284.         }
  1285.         if (n==ERR)
  1286.         {
  1287.             pmlog(LOG_ERR,"read (nu): %m");
  1288.             _db9(DB_ULOCK,hNet,0,0);
  1289.             return(ERR);
  1290.         }
  1291.         if (n==1)
  1292.             break;
  1293.  
  1294.         b[n-1]=0;
  1295.  
  1296.         switch (*b)
  1297.         {
  1298.         case 'P':
  1299.             args=arglist(b+1,'|');
  1300.             if (!args[0] || !args[1] || !args[2] || !args[3] || !args[4])
  1301.             {
  1302.                 pmlog("postman nu P: missing argument");
  1303.                 _db9(DB_ULOCK,hNet,0,0);
  1304.                 return(ERR);
  1305.             }
  1306.             strcpy(sNode.acN_ICode,args[0]);
  1307.             strcpy(sNode.acN_Phone,args[1]);
  1308.             sNode.wN_Speed=atoi(args[2]);
  1309.             strcpy(sNode.acN_ISDN,args[3]);
  1310.             strcpy(b,args[4]);
  1311.             if (*b)
  1312.             {
  1313.                 free(args);
  1314.                 args=arglist(b,'.');
  1315.                 if (!args[0] || !args[1] || !args[2] || !args[3])
  1316.                 {
  1317.                     pmlog(LOG_ERR,"postman nu P: bad INET");
  1318.                     memset(sNode.abN_INET,0,4);
  1319.                 }
  1320.                 else
  1321.                 {
  1322.                     sNode.abN_INET[0]=atoi(args[0]);
  1323.                     sNode.abN_INET[1]=atoi(args[1]);
  1324.                     sNode.abN_INET[2]=atoi(args[2]);
  1325.                     sNode.abN_INET[3]=atoi(args[3]);
  1326.                 }
  1327.             }
  1328.             else
  1329.                 memset(sNode.abN_INET,0,4);
  1330.             free(args);
  1331.             break;
  1332.  
  1333.         case 'D':
  1334.             strcpy(sNode.acN_Desc,b+1);
  1335.             break;
  1336.  
  1337.         case 'A':
  1338.             args=arglist(b+1,'|');
  1339.             if (!args[0] || !args[1] || !args[2] || !args[3] || !args[4])
  1340.             {
  1341.                 pmlog("postman nu A: missing argument");
  1342.                 _db9(DB_ULOCK,hNet,0,0);
  1343.                 return(ERR);
  1344.             }
  1345.             strcpy(sNode.acN_Addr,args[0]);
  1346.             strcpy(sNode.acN_City,args[1]);
  1347.             strcpy(sNode.acN_State,args[2]);
  1348.             strcpy(sNode.acN_Zip,args[3]);
  1349.             strcpy(sNode.acN_Country,args[4]);
  1350.             free(args);
  1351.             break;
  1352.  
  1353.         case 'O':            
  1354.             args=arglist(b+1,'|');
  1355.             if (!args[0] || !args[1])
  1356.             {
  1357.                 pmlog("postman nu O: missing argument");
  1358.                 _db9(DB_ULOCK,hNet,0,0);
  1359.                 return(ERR);
  1360.             }
  1361.             strcpy(sNode.acN_Sysop,args[0]);
  1362.             strcpy(sNode.acN_SPhone,args[1]);
  1363.             free(args);
  1364.             break;
  1365.  
  1366.         case 'T':
  1367.             args=arglist(b+1,'|');
  1368.             if (!args[0] || !args[1] || !args[2] || !args[3] ||
  1369.                 !args[4] || !args[5] || !args[6] || !args[7])
  1370.             {
  1371.                 pmlog("postman nu T: missing argument");
  1372.                 _db9(DB_ULOCK,hNet,0,0);
  1373.                 return(ERR);
  1374.             }
  1375.             sNode.cN_UTC=atoi(args[0]);
  1376.             sNode.bN_DST=atoi(args[1]);
  1377.             sNode.abN_WkdHrs[0]=atoi(args[2]);
  1378.             sNode.abN_WkdHrs[1]=atoi(args[3]);
  1379.             sNode.abN_WkeHrs[0]=atoi(args[4]);
  1380.             sNode.abN_WkeHrs[1]=atoi(args[5]);
  1381.             sNode.abN_NetHrs[0]=atoi(args[6]);
  1382.             sNode.abN_NetHrs[1]=atoi(args[7]);
  1383.             free(args);
  1384.             break;
  1385.  
  1386.         case 'S':
  1387.             args=arglist(b+1,'|');
  1388.             if (!args[0] || !args[1])
  1389.             {
  1390.                 pmlog("postman nu S: missing argument");
  1391.                 _db9(DB_ULOCK,hNet,0,0);
  1392.                 return(ERR);
  1393.             }
  1394.             sNode.bN_Status=atoi(args[0]);
  1395.             sNode.bN_MType=atoi(args[1]);
  1396.             free(args);
  1397.             break;
  1398.  
  1399.         case '1':
  1400.         case '2':
  1401.         case '3':
  1402.         case '4':
  1403.             n=*b-'1';
  1404.             if (b[1])
  1405.             {
  1406.                 args=arglist(b+1,'|');
  1407.                 if (!args[0] || !args[1] || !args[2] ||
  1408.                     !args[3] || !args[4])
  1409.                 {
  1410.                     pmlog("postman nu #: missing argument");
  1411.                     _db9(DB_ULOCK,hNet,0,0);
  1412.                     return(ERR);
  1413.                 }
  1414.                 strcpy(sNode.asNode2[n].acN2_Name,args[0]);
  1415.                 sNode.asNode2[n].bN2_MaxAge=atoi(args[1]);
  1416.                 sNode.asNode2[n].bN2_MinAge=atoi(args[2]);
  1417.                 sNode.asNode2[n].bN2_MaxSize=atoi(args[3]);
  1418.                 sNode.asNode2[n].bN2_MinSize=atoi(args[4]);
  1419.                 free(args);
  1420.             }
  1421.             else
  1422.                 memset(sNode.asNode2[n],0,sizeof(struct sNode2));
  1423.             break;
  1424.         default:
  1425.             pmlog(LOG_ERR,"postman nu: unknown code '%c'",*b);
  1426.             _db9(DB_ULOCK,hNet,0,0);
  1427.             return(ERR);
  1428.         }
  1429.     }
  1430.  
  1431.     if (found)
  1432.     {
  1433.         if (_db9(DB_WRITE,hNet,&sNode,sizeof(sNode))==ERR)
  1434.         {
  1435.             pmlog(LOG_ERR,"DB9 write %s: %m",node);
  1436.             return(ERR);
  1437.         }
  1438.     }
  1439.     else
  1440.     {
  1441.         if (_db9(DB_ADD,hNet,&sNode,sizeof(sNode))==ERR)
  1442.         {
  1443.             pmlog(LOG_ERR,"DB9 add %s: %m",node);
  1444.             return(ERR);
  1445.         }
  1446.     }
  1447. }
  1448.  
  1449. void
  1450. PostServ(file)
  1451. char *file;
  1452. {
  1453.     int path;
  1454.     int n;
  1455.     char *pcTemp;
  1456.  
  1457.     if (iDebug)
  1458.         wstringf(iDebug,"Service(\"%s\")\n",file);
  1459.  
  1460.     if (ChkTag(file))
  1461.         return;
  1462.  
  1463.     path=open(file,O_EXCL|O_RDWR);
  1464.     if (path==ERR)
  1465.     {
  1466.         pmlog(LOG_ERR,"open %s: %m",file);
  1467.         return;
  1468.     }    
  1469.  
  1470.     errno=211;
  1471.     n=readln(path,fromline,80);
  1472.     if (!n || n==ERR)
  1473.     {
  1474.         pmlog(LOG_ERR,"read (from): %m");
  1475.         close(path);
  1476.         return;
  1477.     }
  1478.     if (iDebug)
  1479.         writeln(iDebug,fromline,n);
  1480.     fromline[n]=0;
  1481.  
  1482.     if (strncmp(fromline,"FROM: ",6))
  1483.     {
  1484.         pmlog(LOG_ERR,"unexpected header in %s",file);
  1485.         close(path);
  1486.         return;
  1487.     }
  1488.  
  1489.     _pm_addr(fromline+6);
  1490.     if (stricmp(A_user,"postman"))
  1491.     {
  1492.         pmlog(LOG_ERR,"bad from '%s'",fromline+6);
  1493.         close(path);
  1494.         return;
  1495.     }
  1496.     if (!stricmp(A_host,hostname))
  1497.     {
  1498.         /* ignore nu from myself */
  1499.         close(path);
  1500.         unlink(file);
  1501.         return;
  1502.     }
  1503.  
  1504.     while (n>1)
  1505.     {
  1506.         errno=211;
  1507.         n=readln(path,b,BUF_SIZE);
  1508.         if (!n || n==ERR)
  1509.         {
  1510.             pmlog(LOG_ERR,"read (hdr): %m");
  1511.             close(path);
  1512.             return;
  1513.         }
  1514.     }
  1515.  
  1516.     while (n=readln(path,b,BUF_SIZE))
  1517.     {
  1518.         if (n==ERR)
  1519.         {
  1520.             pmlog(LOG_ERR,"read (cmd): %m");
  1521.             close(path);
  1522.             return;
  1523.         }
  1524.         if (n==1)
  1525.             continue;
  1526.         b[n-1]=0;
  1527.  
  1528.         pcTemp=strcut(b,' ');
  1529.         if (!strcmp(b,"nu"))
  1530.         {
  1531.             if (!pcTemp)
  1532.             {
  1533.                 pmlog(LOG_ERR,"postman cmd nu missing argument");
  1534.                 close(path);
  1535.                 return;
  1536.             }
  1537.             if (pm_nu(path,pcTemp))
  1538.             {
  1539.                 close(path);
  1540.                 return;
  1541.             }    
  1542.         }
  1543.         else
  1544.         {
  1545.             pmlog(LOG_ERR,"unknown postman cmd '%s'",b);
  1546.         }
  1547.     }
  1548.     close(path);
  1549.     unlink(file);
  1550. }
  1551.  
  1552. void
  1553. Scan()
  1554. {
  1555.     struct dirent *d;
  1556.     char *e;
  1557.     int n;
  1558.  
  1559.     if (iDebug)
  1560.         wstringf(iDebug,"Scan()\n");
  1561.  
  1562.     rewinddir(dp);
  1563.  
  1564.     while (d=readdir(dp))
  1565.     {
  1566.         e=d->d_name;
  1567.         while (*e && *e!='.')
  1568.             e++;
  1569.         if (!*e)
  1570.             continue;
  1571.  
  1572.         n=e-d->d_name;
  1573.  
  1574.         if (!strcmp(e,".mq"))
  1575.         {
  1576.             *rcvd_from=0;
  1577.             Process(d->d_name);
  1578.         }
  1579.         else
  1580.         if (!strcmp(e,".mh"))
  1581.         {
  1582.             *rcvd_from=0;
  1583.             Process(d->d_name);
  1584.         }
  1585.         else
  1586.         if (!strcmp(e,".sq"))
  1587.         {
  1588.             strcpy(rcvd_from,d->d_name);
  1589.             rcvd_from[n]=0;
  1590.             if (*hostname)
  1591.             {
  1592.                 strcat(rcvd_from,"@");
  1593.                 strcat(rcvd_from,hostname);
  1594.             }
  1595.             Process(d->d_name);
  1596.         }
  1597.         else
  1598.         if (!strcmp(e,".nq"))
  1599.         {
  1600.             strcpy(rcvd_from,d->d_name);
  1601.             rcvd_from[n]=0;
  1602.             Process(d->d_name);
  1603.         }
  1604.         else
  1605.         if (!strcmp(e,".si"))
  1606.         {
  1607.             Service(d->d_name);
  1608.         }
  1609.         else
  1610.         if (!strcmp(e,".pi"))
  1611.         {
  1612.             PostServ(d->d_name);
  1613.         }
  1614.     }
  1615. }
  1616.  
  1617. void
  1618. MailSyslog()
  1619. {
  1620. #ifndef _UNIX
  1621.     char *args[8];
  1622.     int hLog;
  1623.     struct fildes fd;
  1624.  
  1625.     hLog=open(LOG_FILE,0);
  1626.     if (hLog==ERR)
  1627.     {
  1628.         if (errno!=ENOENT)
  1629.             pmlog(LOG_ERR,"open %s: %m",LOG_FILE);
  1630.         return;
  1631.     }
  1632.     if (_gs_gfd(hLog,&fd,sizeof(fd))==ERR)
  1633.     {
  1634.         pmlog(LOG_ERR,"_gs_gfd %s: %m",LOG_FILE);
  1635.         close(hLog);
  1636.         return;
  1637.     }
  1638.     close(hLog);
  1639.  
  1640.     time(&lTime);
  1641.     psTime=localtime(&lTime);
  1642.     if (psTime->tm_mday==fd.fd_dcr[2])
  1643.         return;
  1644.  
  1645.     /* log file was not created today, rename and mail it */
  1646.     unlink("../syslog.old");
  1647.     if (_rename(LOG_FILE,"syslog.old")==ERR)
  1648.     {
  1649.         pmlog(LOG_ERR,"rename %s %s: %m",LOG_FILE,"syslog.old");
  1650.         return;
  1651.     }
  1652.  
  1653.     setuid(iPM_ID);
  1654.  
  1655.     args[0]="postman";
  1656.     args[1]="-tsysop";
  1657.     args[2]="-sSystem Log";
  1658.     args[3]="../syslog.old";
  1659.     args[4]=0;
  1660.     if (_fork(*args,args,environ)==ERR)
  1661.         pmlog(LOG_ERR,"fork %s: %m",*args);
  1662.     else
  1663.         wait(0);
  1664.  
  1665.     setuid(0);
  1666. #endif
  1667. }
  1668.  
  1669. Minute()
  1670. {
  1671. }
  1672.  
  1673. Hourly()
  1674. {
  1675. }
  1676.  
  1677. Nightly()
  1678. {
  1679.     MailSyslog();
  1680. }
  1681.  
  1682. void
  1683. Sleep()
  1684. {
  1685.     static int last_min;
  1686.     static int last_hour;
  1687.     static int last_mday;
  1688.  
  1689. tm_update:
  1690.     time(&lTime);
  1691.     psTime=localtime(&lTime);
  1692.  
  1693.     if (last_min!=psTime->tm_min)
  1694.     {
  1695.         Minute();
  1696.         last_min=psTime->tm_min;
  1697.         goto tm_update;
  1698.     }
  1699.  
  1700.     if (last_hour!=psTime->tm_hour)
  1701.     {
  1702.         Hourly();
  1703.         last_hour=psTime->tm_hour;
  1704.         goto tm_update;
  1705.     }
  1706.  
  1707.     if (last_mday!=psTime->tm_mday)
  1708.     {
  1709.         Nightly();
  1710.         last_mday=psTime->tm_mday;
  1711.         goto tm_update;
  1712.     }
  1713.  
  1714.     /* sleep until next minute */
  1715.     endpwent();
  1716.     sleep(60-psTime->tm_sec);
  1717. }
  1718.  
  1719. Daemon()
  1720. {
  1721.     openlog("postman",0,LOG_STGNET);
  1722.  
  1723.     if (chdir(SPL_DIR)==ERR)
  1724.     {
  1725.         pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
  1726.         exit(errno);
  1727.     }
  1728.     unlink(LOCK_FILE);
  1729.     hLock=create(LOCK_FILE,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  1730.     if (hLock==ERR)
  1731.     {
  1732.         if (errno==253)
  1733.             exit(0);    /* already running */
  1734.         pmlog(LOG_ERR,"creat %s: %m",LOCK_FILE);
  1735.         exit(errno);
  1736.     }
  1737.  
  1738.     if (iDebug)
  1739.     {
  1740.         iDebug=hLock=dup(iDebug);
  1741.     }
  1742.     else
  1743.     {
  1744.         close(0); close(1); close(2);
  1745.         dup(hLock); dup(hLock); dup(hLock);
  1746.     }
  1747.  
  1748.     hNet=open(STG_FILE,O_RDWR|O_BINARY);
  1749.     if (hNet==ERR)
  1750.     {
  1751.         pmlog(LOG_ERR,"open %s: %m",STG_FILE);
  1752.         exit(errno);
  1753.     }
  1754.  
  1755.     if (_db9(DB_OPEN,hNet,"nodes",6)==ERR)
  1756.     {
  1757.         pmlog(LOG_ERR,"DB9 open nodes: %m");
  1758.         exit(errno);
  1759.     }
  1760.  
  1761.     /* select case insensitive seek */
  1762.     if (_db9(DB_MATCH,hNet,-1,0)==ERR)
  1763.     {
  1764.         pmlog(LOG_ERR,"DB9 match c-i: %m");
  1765.         exit(errno);
  1766.     }
  1767.  
  1768.     dp=opendir(".");
  1769.     if (!dp)
  1770.     {
  1771.         pmlog(LOG_ERR,"opendir: %m");
  1772.         exit(errno);
  1773.     }
  1774.  
  1775. #ifdef _OS9
  1776.     setpr(getpid(),iPM_PRI);
  1777. #endif
  1778.  
  1779.     MailSyslog();
  1780.  
  1781.     while (1)
  1782.     {
  1783.         if (resetroute)
  1784.         {
  1785. /*            ResetRoute(); */
  1786.             resetroute=0;
  1787.         }
  1788.  
  1789.         Scan();
  1790.         Sleep();
  1791.     }
  1792. }
  1793.  
  1794. ForkDaemon()
  1795. {
  1796.     int hLock;
  1797.     char *args[2];
  1798.  
  1799.     if (chdir(SPL_DIR)==ERR)
  1800.     {
  1801.         pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
  1802.         /* don't exit w/error!!! */
  1803.         exit(0);
  1804.     }
  1805.  
  1806.     hLock=open(LOCK_FILE,O_RDWR);
  1807.     if (hLock==ERR && errno==253)
  1808.         exit(0);    /* postman already running */
  1809.  
  1810.     pmlog(LOG_ERR,"postman daemon has died - restarting");
  1811.  
  1812.     args[0]="@postman";
  1813.     args[1]=0;
  1814.  
  1815.     if (_fork(*args+1,args,environ)==ERR)
  1816.         pmlog(LOG_ERR,"fork postman: %m");
  1817.  
  1818.     exit(0);
  1819. }
  1820.  
  1821. NodeUpd(hSpool,flag)
  1822. int hSpool;
  1823. byte flag;
  1824. {
  1825.     int i;
  1826.  
  1827.     wstringf(hSpool,"nu %s\n",sNode.acN_Name);
  1828.  
  1829.     if (flag&NU_PHONE)
  1830.         wstringf(hSpool,"P%s|%s|%d|%s|%d.%d.%d.%d\n",
  1831.             sNode.acN_ICode,
  1832.             sNode.acN_Phone,
  1833.             (int)sNode.wN_Speed,
  1834.             sNode.acN_ISDN,
  1835.             (int)sNode.abN_INET[0],
  1836.             (int)sNode.abN_INET[1],
  1837.             (int)sNode.abN_INET[2],
  1838.             (int)sNode.abN_INET[3]);
  1839.     if (flag&NU_DESC)
  1840.         wstringf(hSpool,"D%s\n",sNode.acN_Desc);
  1841.     if (flag&NU_ADDR)
  1842.         wstringf(hSpool,"A%s|%s|%s|%s|%s\n",
  1843.             sNode.acN_Addr,
  1844.             sNode.acN_City,
  1845.             sNode.acN_State,
  1846.             sNode.acN_Zip,
  1847.             sNode.acN_Country);
  1848.     if (flag&NU_OPER)
  1849.         wstringf(hSpool,"O%s|%s\n",
  1850.             sNode.acN_Sysop,
  1851.             sNode.acN_SPhone);
  1852.     if (flag&NU_TIME)
  1853.         wstringf(hSpool,"T%d|%d|%d|%d|%d|%d|%d|%d\n",
  1854.             (int)sNode.cN_UTC,
  1855.             (int)sNode.bN_DST,
  1856.             (int)sNode.abN_WkdHrs[0],
  1857.             (int)sNode.abN_WkdHrs[1],
  1858.             (int)sNode.abN_WkeHrs[0],
  1859.             (int)sNode.abN_WkeHrs[1],
  1860.             (int)sNode.abN_NetHrs[0],
  1861.             (int)sNode.abN_NetHrs[1]);
  1862.     if (flag&NU_STATUS)
  1863.         wstringf(hSpool,"S%d|%d\n",
  1864.             (int)sNode.bN_Status,
  1865.             (int)sNode.bN_MType);
  1866.     if (flag&NU_ROUTE)
  1867.     {
  1868.         i=0;
  1869.         while (i<4)
  1870.         {
  1871.             if (!*sNode.asNode2[i].acN2_Name)
  1872.                 wstringf(hSpool,"%d\n",i+1);
  1873.             else
  1874.                 wstringf(hSpool,"%d%s|%d|%d|%d|%d\n",
  1875.                     i+1,
  1876.                     sNode.asNode2[i].acN2_Name,
  1877.                     (int)sNode.asNode2[i].bN2_MaxAge,
  1878.                     (int)sNode.asNode2[i].bN2_MinAge,
  1879.                     (int)sNode.asNode2[i].bN2_MaxSize,
  1880.                     (int)sNode.asNode2[i].bN2_MinSize);
  1881.             i++;
  1882.         }
  1883.     }
  1884.     wstringf(hSpool,"\n");
  1885. }
  1886.  
  1887. NetUpd(node)
  1888. char *node;
  1889. {
  1890.     int hSpool;
  1891.     int n;
  1892.  
  1893.     hNet=open(STG_FILE,O_RDWR|O_BINARY);
  1894.     if (hNet==ERR)
  1895.         exit(syserr("open %s: %m",STG_FILE));
  1896.  
  1897.     if (_db9(DB_OPEN,hNet,"nodes",6)==ERR)
  1898.         exit(syserr("DB9 open nodes: %m"));
  1899.  
  1900.     if (_db9(DB_MATCH,hNet,-1,0)==ERR)
  1901.         exit(syserr("DB9 match c-i: %m"));
  1902.  
  1903.     _pm_temp(tempfile);
  1904.     stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
  1905.  
  1906.     hSpool=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  1907.     if (hSpool==ERR)
  1908.         exit(syserr("create %s: %m",b));
  1909.  
  1910.     stringf(b,"FROM: postman");
  1911.     if (*hostname)
  1912.     {
  1913.         strcat(b,"@");
  1914.         strcat(b,hostname);
  1915.     }
  1916.     strcat(b,"\n");
  1917.     writeln(hSpool,b,80);
  1918.  
  1919.     strcpy(b,"TO  : postman@*\n");
  1920.     writeln(hSpool,b,80);
  1921.  
  1922.     writeln(hSpool,"\n",1);
  1923.  
  1924.     if (!node)
  1925.         node=hostname;
  1926.  
  1927.     /* loop here sending network update commands */
  1928.     if (*node=='*')
  1929.     {
  1930.         while (n=_db9(DB_NEXT,hNet,&sNode,sizeof(sNode)))
  1931.         {
  1932.             if (n==ERR)
  1933.                 exit(syserr("DB9 next node: %m"));
  1934.             _db9(DB_ULOCK,hNet,0,0);
  1935.  
  1936.             NodeUpd(hSpool,-1);    /* send all fields */
  1937.         }
  1938.     }
  1939.     else
  1940.     {
  1941.         n=_db9(DB_SEEK,hNet,node,strlen(node)+1);
  1942.         if (n==ERR)
  1943.             exit(syserr("DB9 seek %s: %m",node));
  1944.         if (!n)
  1945.             exit(syserr("node %s not found",node));
  1946.         if (_db9(DB_READ,hNet,&sNode,sizeof(sNode))==ERR)
  1947.             exit(syserr("DB9 read node: %m"));
  1948.  
  1949.         NodeUpd(hSpool,-1);    /* for now, update all fields */
  1950.         sNode.bN_Update=0;
  1951.  
  1952.         if (_db9(DB_WRITE,hNet,&sNode,sizeof(sNode))==ERR)
  1953.             exit(syserr("DB9 write node: %m"));
  1954.     }
  1955.  
  1956.     writeln(hSpool,"~\n",2);
  1957.     tag(hSpool);
  1958.     close(hSpool);
  1959.  
  1960.     /* put in queue */
  1961.     stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
  1962.     strcat(tempfile,".mq");
  1963.     if (_rename(b,tempfile)==ERR)
  1964.         exit(syserr("rename %s %s: %m",b,tempfile));
  1965.  
  1966.     exit(0);
  1967. }
  1968.  
  1969. Queue(file)
  1970. char *file;
  1971. {
  1972.     int hSpool;
  1973.  
  1974.     /* must be user 0 or a mail service to queue file directly */
  1975.     /* no, mail services must deliver the hard way */
  1976.     if (pw->pw_uid)
  1977. /*        if (!pw->pw_shell || *pw->pw_shell!='!') */
  1978.             Help();
  1979.  
  1980.     setuid(0);
  1981.  
  1982.     /* should already be in spl dir, but force the issue anyway */
  1983.     if (chdir(SPL_DIR)==ERR)
  1984.     {
  1985.         pmlog(LOG_ERR,"chd %s: %m",SPL_DIR);
  1986.         exit(errno);
  1987.     }
  1988.  
  1989.     hSpool=open(file,O_EXCL|O_RDWR);
  1990.     if (hSpool==ERR)
  1991.     {
  1992.         pmlog(LOG_ERR,"open %s: %m",file);
  1993.         exit(errno);
  1994.     }
  1995.     tag(hSpool);
  1996.     close(hSpool);
  1997.  
  1998.     stringf(b,"%s.sq",pw->pw_name);
  1999.  
  2000.     if (_rename(file,b)==ERR)
  2001.     {
  2002.         pmlog(LOG_ERR,"rename %s %s: %m",file,b);
  2003.         exit(errno);
  2004.     }
  2005.     ForkDaemon();
  2006. }
  2007.  
  2008. main(argc,argv)
  2009. char **argv;
  2010. {
  2011.     int hSpool,hMail;
  2012.     int n;
  2013.  
  2014.     gethostname(hostname,32);
  2015.  
  2016.     pw=getpwnam("postman");
  2017.     if (!pw)
  2018.         exit(syserr("user 'postman' not found"));
  2019.  
  2020.     iPM_ID=pw->pw_uid;
  2021. #ifdef _OS9
  2022.     iPM_PRI=pw->pw_pri;
  2023. #endif
  2024.  
  2025.     switch (**argv)
  2026.     {
  2027.     case '@':
  2028.         if (!getuid())
  2029.             Daemon();
  2030.  
  2031.     case '-':
  2032.     case '!':
  2033.         Interactive();
  2034.     }
  2035.  
  2036.     if (!*++argv)
  2037.         Help();
  2038.  
  2039.     if (!strcmp(*argv,"-#"))
  2040.     {
  2041.         wstringf(2,"postman: %s\n",STG_VER);
  2042.         exit(0);
  2043.     }
  2044.  
  2045.     /* check for option flags the hard way here */
  2046.     if (!stricmp(*argv,"-i"))
  2047.         Interactive();
  2048.  
  2049.     if (!stricmp(*argv,"-z") && !getuid())
  2050.     {
  2051.         iDebug=2;
  2052.         Daemon();
  2053.     }
  2054.  
  2055.     if (!stricmp(*argv,"-nu") && !getuid())
  2056.         NetUpd(*++argv);
  2057.  
  2058.     pw=getpwuid(getuid());
  2059.     if (!pw)
  2060.         exit(syserr("who are you?"));
  2061.  
  2062.     if (**argv && **argv!='-')
  2063.         Queue(*argv);
  2064.  
  2065.     if (strncmp(*argv,"-t",2))
  2066.         Help();
  2067.  
  2068.     /* set to user 0 and create temporary file */
  2069.     setuid(0);
  2070.     _pm_temp(tempfile);
  2071.     stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
  2072.  
  2073.     hSpool=create(b,O_EXCL|O_RDWR,S_IREAD|S_IWRITE);
  2074.     if (hSpool==ERR)
  2075.         exit(syserr("create %s: %m",b));
  2076.  
  2077.     if (pw->pw_gecos)
  2078.         strcut(pw->pw_gecos,':');
  2079.  
  2080.     strcpy(b,"FROM: ");
  2081.     strcat(b,pw->pw_name);
  2082.     if (*hostname)
  2083.     {
  2084.         strcat(b,"@");
  2085.         strcat(b,hostname);
  2086.     }
  2087.  
  2088.     if (pw->pw_gecos && *pw->pw_gecos)
  2089.     {
  2090.         strcat(b," (");
  2091.         strcat(b,pw->pw_gecos);
  2092.         strcat(b,")");
  2093.     }
  2094.  
  2095.     b[79]=0;
  2096.     strcat(b,"\n");
  2097.     writeln(hSpool,b,80);
  2098.  
  2099.     while (*argv && !strncmp(*argv,"-t",2))
  2100.     {
  2101.         (*argv)+=2;
  2102.         if (!**argv)
  2103.             argv++;
  2104.         strcpy(b,"TO  : ");
  2105.         strcat(b,*argv);
  2106.         argv++;
  2107.         b[79]=0;
  2108.         strcat(b,"\n");
  2109.         writeln(hSpool,b,80);
  2110.     }
  2111.  
  2112.     if (*argv && !strncmp(*argv,"-s",2))
  2113.     {
  2114.         (*argv)+=2;
  2115.         if (!**argv)
  2116.             argv++;
  2117.         strcpy(b,"SUBJ: ");
  2118.         strcat(b,*argv);
  2119.         argv++;
  2120.         b[79]=0;
  2121.         strcat(b,"\n");
  2122.         writeln(hSpool,b,80);
  2123.     }
  2124.  
  2125.     time(&lTime);
  2126.     psTime=localtime(&lTime);
  2127.  
  2128.     stringf(b,"DATE: %02d/%02d/%02d %02d:%02d:%02d\n",
  2129.         psTime->tm_year,
  2130.         psTime->tm_mon+1,
  2131.         psTime->tm_mday,
  2132.         psTime->tm_hour,
  2133.         psTime->tm_min,
  2134.         psTime->tm_sec);
  2135.     writeln(hSpool,b,80);
  2136.  
  2137.     writeln(hSpool,"\n",1);
  2138.  
  2139.     if (!*argv)
  2140.         exit(syserr("mail file not specified"));
  2141.  
  2142.     hMail=open(*argv,O_RDONLY);
  2143.  
  2144.     while (n=readln(hMail,b,80))
  2145.     {
  2146.         if (n==ERR)
  2147.             exit(syserr("readln %s: %m",*argv));
  2148.  
  2149.         if (n==2 && *b=='~')
  2150.         {
  2151.             strcpy(b,"~ \n");
  2152.             n=3;
  2153.         }
  2154.         writeln(hSpool,b,n);
  2155.     }
  2156.     close(hMail);
  2157.  
  2158.     writeln(hSpool,"~\n",2);
  2159.     tag(hSpool);
  2160.     close(hSpool);
  2161.  
  2162.     /* rename spool file to put in queue (.mq) */
  2163.     stringf(b,"%s/%s.tmp",SPL_DIR,tempfile);
  2164.     strcat(tempfile,".mq");
  2165.  
  2166.     if (_rename(b,tempfile)==ERR)
  2167.         exit(syserr("rename %s %s: %m",b,tempfile));
  2168.  
  2169.     /* check to insure a postman is spooling */
  2170.     ForkDaemon();
  2171. }
  2172.  
  2173. #ifdef BOGUS
  2174.     /* decide routing */
  2175.  
  2176.     if (_pm_test(pcTo))
  2177.     {
  2178.         pmlog(LOG_CRIT,"message cannot be delivered");
  2179.         exit(1);
  2180.     }
  2181.  
  2182.     pw=getpwnam(A_user);
  2183.     if (!pw)
  2184.     {
  2185.         pmlog(LOG_CRIT,"unknown user '%s'",A_user);
  2186.         exit(1);
  2187.     }
  2188.  
  2189.     /* deliver message */
  2190.  
  2191.     if (*argv)
  2192.     {
  2193.         close(0);
  2194.         if (open(*argv,O_RDONLY)==ERR)
  2195.         {
  2196.             pmlog(LOG_CRIT,"open %s: %m",*argv);
  2197.             exit(1);
  2198.         }
  2199.     }
  2200.  
  2201.     setuid(0);
  2202.  
  2203. #ifdef _OS9
  2204.     if (access(pw->pw_dir,0x83)==ERR)
  2205. #else
  2206.     if (access(pw->pw_dir,R_OK)==ERR)
  2207. #endif
  2208.     {
  2209. #ifdef _OS9
  2210.         strucs(pw->pw_dir);
  2211. #endif
  2212.  
  2213. #ifdef _OS9
  2214.         if (mknod(pw->pw_dir,O_RDWR)==ERR)
  2215. #else
  2216.         if (mkdir(pw->pw_dir,S_IREAD|S_IWRITE)==ERR)
  2217. #endif
  2218.         {
  2219.             pmlog(LOG_ERR,"makdir %s: %m",pw->pw_dir);
  2220.             exit(1);
  2221.         }
  2222.  
  2223.         /* set owner of directory */
  2224.         chown(pw->pw_dir,pw->pw_uid,-1);
  2225.     }
  2226.  
  2227.     strcpy(b,pw->pw_dir);
  2228.     strcat(b,"/mailbox");
  2229.  
  2230.     hTemp=open(b,O_RDWR);
  2231.     if (hTemp==ERR)
  2232.     {
  2233.         if (errno!=216)
  2234.         {
  2235.             pmlog(LOG_ERR,"open %s: %m",b);
  2236.             exit(1);
  2237.         }
  2238.  
  2239.         hTemp=create(b,O_RDWR,S_IREAD|S_IWRITE);
  2240.         if (hTemp==ERR)
  2241.         {
  2242.             pmlog(LOG_ERR,"create %s: %m",b);
  2243.             exit(1);
  2244.         }
  2245.         fchown(hTemp,pw->pw_uid,-1);
  2246.     }
  2247.  
  2248.     _ss_lock(hTemp,-1);
  2249.     lseek(hTemp,0L,2);
  2250.  
  2251.     stringf(b,"FROM: %s\n",pcFrom);
  2252.     writeln(hTemp,b,BUF_SIZE);
  2253.  
  2254.     stringf(b,"TO  : %s\n",pcTo);
  2255.     writeln(hTemp,b,BUF_SIZE);
  2256.  
  2257.     pcTemp=pcHead;
  2258.     while (pcTemp)
  2259.     {
  2260.         stringf(b,"%s\n",pcTemp+4);
  2261.         writeln(hTemp,b,80);
  2262.  
  2263.         pcTemp=*(char**)pcTemp;
  2264.     }
  2265.  
  2266.     writeln(hTemp,"\n",1);
  2267.  
  2268.     while (1)
  2269.     {
  2270.         n=read(0,b,BUF_SIZE);
  2271.         if (n==ERR)
  2272.         {
  2273.             pmlog(LOG_ERR,"error reading message: %m");
  2274.             break;
  2275.         }
  2276.         if (!n)
  2277.             break;
  2278.  
  2279.         write(hTemp,b,n);
  2280.     }
  2281.     writeln(hTemp,"~\n",2);
  2282.  
  2283.     close(hTemp);
  2284.  
  2285. #endif
  2286.