home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 19 / AACD19.BIN / AACD / Programming / cvs-1.11 / source / amiga / amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-03  |  38.7 KB  |  2,363 lines

  1. /*
  2.  * $Id$
  3.  *
  4.  * :ts=4
  5.  *
  6.  * AmigaOS wrapper routines for GNU CVS, using the AmiTCP V3 API
  7.  * and the SAS/C V6.58 compiler.
  8.  *
  9.  * Written and adapted by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  */
  25.  
  26. #include <exec/memory.h>
  27.  
  28. #include <dos/dosextens.h>
  29. #include <dos/dostags.h>
  30.  
  31. #include <libraries/locale.h>
  32.  
  33. #include <bsdsocket/socketbasetags.h>
  34. #include <libraries/usergroup.h>
  35.  
  36. #include <clib/exec_protos.h>
  37. #include <clib/dos_protos.h>
  38. #include <clib/utility_protos.h>
  39. #include <clib/socket_protos.h>
  40. #include <clib/usergroup_protos.h>
  41. #include <clib/locale_protos.h>
  42. #include <clib/alib_protos.h>
  43.  
  44. #include <pragmas/exec_sysbase_pragmas.h>
  45. #include <pragmas/dos_pragmas.h>
  46. #include <pragmas/utility_pragmas.h>
  47. #include <pragmas/socket_pragmas.h>
  48. #include <pragmas/usergroup_pragmas.h>
  49. #include <pragmas/locale_pragmas.h>
  50.  
  51. #include <sys/types.h>
  52. #include <sys/socket.h>
  53. #include <sys/param.h>
  54. #include <sys/ioctl.h>
  55.  
  56. #include <constructor.h>
  57. #include <utime.h>
  58. #include <stdio.h>
  59. #include <errno.h>
  60. #include <dirent.h>
  61. #include <netdb.h>
  62. #include <stat.h>
  63. #include <signal.h>
  64. #include <stdlib.h>
  65. #include <time.h>
  66. #include <pwd.h>
  67. #include <grp.h>
  68. #include <dos.h>
  69.  
  70. #include <netinet/ip.h>
  71. #include <netinet/tcp.h>
  72.  
  73. #include <net/if.h>
  74. #include <unistd.h>
  75.  
  76. #include <ios1.h>
  77.  
  78. /****************************************************************************/
  79.  
  80. #include "_assert.h"
  81.  
  82. /****************************************************************************/
  83.  
  84. #include "error.h"
  85.  
  86. /****************************************************************************/
  87.  
  88. #define UNIX_TIME_OFFSET 252460800
  89.  
  90. /****************************************************************************/
  91.  
  92. #define ZERO ((BPTR)NULL)
  93.  
  94. #define SAME (0)
  95.  
  96. #define CANNOT !
  97. #define NOT !
  98.  
  99. /****************************************************************************/
  100.  
  101. /* This macro lets us long-align structures on the stack */
  102. #define D_S(type,name) \
  103.     char a_##name[sizeof(type)+3]; \
  104.     type *name = (type *)((LONG)(a_##name+3) & ~3)
  105.  
  106. /****************************************************************************/
  107.  
  108. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType >= 0 && \
  109.                              (fib)->fib_DirEntryType != ST_SOFTLINK && \
  110.                              (fib)->fib_DirEntryType != ST_LINKDIR)
  111.  
  112. /****************************************************************************/
  113.  
  114. extern void * xmalloc(size_t size);
  115. extern char * xstrdup(const char * const str);
  116.  
  117. /****************************************************************************/
  118.  
  119. extern struct Library * SysBase;
  120. extern struct Library * DOSBase;
  121. extern struct Library * UtilityBase;
  122.  
  123. /****************************************************************************/
  124.  
  125. static struct Library * SocketBase;
  126. static struct Library * UserGroupBase;
  127.  
  128. /****************************************************************************/
  129.  
  130. static struct Library * LocaleBase;
  131.  
  132. /****************************************************************************/
  133.  
  134. long __stack = 20000;
  135.  
  136. /****************************************************************************/
  137.  
  138. #define MAX_FILENAME_LEN 1024
  139.  
  140. static void
  141. get_next_buffer(char ** buffer_ptr)
  142. {
  143.     static char buffer_slots[8][MAX_FILENAME_LEN];
  144.     static int buffer_index;
  145.  
  146.     (*buffer_ptr) = buffer_slots[buffer_index];
  147.     buffer_index = (buffer_index + 1) % 8;
  148. }
  149.  
  150. /****************************************************************************/
  151.  
  152. static void
  153. correct_name(char ** name_ptr)
  154. {
  155.     char * buffer;
  156.     int len,i;
  157.     char * name;
  158.  
  159.     ENTER();
  160.  
  161.     name = (*name_ptr);
  162.     if(name[0] == '/')
  163.     {
  164.         BOOL done;
  165.  
  166.         SHOWSTRING(name);
  167.  
  168.         get_next_buffer(&buffer);
  169.  
  170.         done = FALSE;
  171.  
  172.         len = strlen(name);
  173.         for(i = 1 ; i <= len ; i++)
  174.         {
  175.             if(name[i] == '/' || name[i] == '\0')
  176.             {
  177.                 memcpy(buffer,name+1,i-1);
  178.                 buffer[i-1] = ':';
  179.                 strcpy(&buffer[i],&name[i+1]);
  180.                 done = TRUE;
  181.                 break;
  182.             }
  183.         }
  184.  
  185.         if(NOT done)
  186.             strcpy(buffer,name);
  187.  
  188.         SHOWSTRING(buffer);
  189.  
  190.         name = buffer;
  191.     }
  192.     else
  193.     {
  194.         len = strlen(name);
  195.  
  196.         SHOWSTRING(name);
  197.  
  198.         for(i = 0 ; i < len-1 ; i++)
  199.         {
  200.             if(name[i] == ':' && name[i+1] == '/')
  201.             {
  202.                 get_next_buffer(&buffer);
  203.  
  204.                 memcpy(buffer,name,i+1);
  205.                 strcpy(&buffer[i+1],&name[i+2]);
  206.  
  207.                 SHOWSTRING(buffer);
  208.  
  209.                 name = buffer;
  210.                 break;
  211.             }
  212.         }
  213.     }
  214.  
  215.     if(strncmp(name,"./",2) == SAME)
  216.     {
  217.         get_next_buffer(&buffer);
  218.  
  219.         strcpy(buffer,name+2);
  220.         name = buffer;
  221.     }
  222.     else if (strncmp(name,"../",3) == SAME)
  223.     {
  224.         get_next_buffer(&buffer);
  225.  
  226.         strcpy(buffer,name+3);
  227.         name = buffer;
  228.     }
  229.     else if (strcmp(name,".") == SAME)
  230.     {
  231.         get_next_buffer(&buffer);
  232.  
  233.         strcpy(buffer,"");
  234.         name = buffer;
  235.     }
  236.     else if (strcmp(name,"..") == SAME)
  237.     {
  238.         get_next_buffer(&buffer);
  239.  
  240.         strcpy(buffer,"/");
  241.         name = buffer;
  242.     }
  243.  
  244.     len = strlen(name);
  245.     if(len > 0 && name[len-1] == '/')
  246.         name[--len] = '\0';
  247.  
  248.     (*name_ptr) = name;
  249.  
  250.     LEAVE();
  251. }
  252.  
  253. /****************************************************************************/
  254.  
  255. void *
  256. amiga_valloc(size_t bytes)
  257. {
  258.     void * result;
  259.  
  260.     ENTER();
  261.     SHOWVALUE(bytes);
  262.  
  263.     result = malloc(bytes);
  264.  
  265.     RETURN(result);
  266.     return(result);
  267. }
  268.  
  269. /****************************************************************************/
  270.  
  271. int
  272. amiga_symlink(char *to,char *from)
  273. {
  274.     int result;
  275.  
  276.     ENTER();
  277.  
  278.     SHOWSTRING(to);
  279.     SHOWSTRING(from);
  280.  
  281.     result = -1;
  282.     errno = EINVAL;
  283.  
  284.     RETURN(result);
  285.     return(result);
  286. }
  287.  
  288. /****************************************************************************/
  289.  
  290. int
  291. amiga_readlink(char *path,char *buf,int buf_size)
  292. {
  293.     int result;
  294.  
  295.     ENTER();
  296.  
  297.     SHOWSTRING(path);
  298.  
  299.     result = -1;
  300.     errno = EINVAL;
  301.  
  302.     RETURN(result);
  303.     return(result);
  304. }
  305.  
  306. /****************************************************************************/
  307.  
  308. unsigned
  309. amiga_sleep(unsigned seconds)
  310. {
  311.     Delay(TICKS_PER_SECOND * seconds);
  312.  
  313.     return(0);
  314. }
  315.  
  316. /****************************************************************************/
  317.  
  318. unsigned long
  319. amiga_umask(unsigned long mask)
  320. {
  321.     return(0);
  322. }
  323.  
  324. /****************************************************************************/
  325.  
  326. unsigned long
  327. amiga_waitpid(unsigned long pid,int *stat_loc,int options)
  328. {
  329.     return(0);
  330. }
  331.  
  332. /****************************************************************************/
  333.  
  334. int
  335. amiga_utime(char *name,struct utimbuf *time)
  336. {
  337.     struct DateStamp ds;
  338.     int result = -1;
  339.  
  340.     ENTER();
  341.  
  342.     correct_name(&name);
  343.  
  344.     SHOWSTRING(name);
  345.  
  346.     /* Use the current time? */
  347.     if(time == NULL)
  348.     {
  349.         DateStamp(&ds);
  350.     }
  351.     else
  352.     {
  353.         unsigned MinutesWest;
  354.         ULONG seconds;
  355.  
  356.         if(LocaleBase == NULL)
  357.             LocaleBase = OpenLibrary("locale.library",38);
  358.  
  359.         if(LocaleBase != NULL)
  360.         {
  361.             struct Locale * loc;
  362.  
  363.             loc = OpenLocale(NULL);
  364.  
  365.             MinutesWest = loc->loc_GMTOffset;
  366.  
  367.             CloseLocale(loc);
  368.         }
  369.         else
  370.         {
  371.             MinutesWest = 0;
  372.         }
  373.  
  374.         /* Convert the time given. */
  375.         if(time->modtime < (UNIX_TIME_OFFSET + 60*MinutesWest))
  376.             seconds = 0;
  377.         else
  378.             seconds = time->modtime - (UNIX_TIME_OFFSET + 60*MinutesWest);    /* translate from UTC to local time */
  379.  
  380.         ds.ds_Days        = (seconds / (24*60*60));
  381.         ds.ds_Minute    = (seconds % (24*60*60)) / 60;
  382.         ds.ds_Tick        = (seconds               % 60) * TICKS_PER_SECOND;
  383.     }
  384.  
  385.     if(SetFileDate((STRPTR)name,&ds))
  386.         result = 0;
  387.  
  388.     RETURN(result);
  389.     return(result);
  390. }
  391.  
  392. /****************************************************************************/
  393.  
  394. int
  395. amiga_geteuid(void)
  396. {
  397.     return(0);
  398. }
  399.  
  400. /****************************************************************************/
  401.  
  402. int
  403. amiga_getuid(void)
  404. {
  405.     return(0);
  406. }
  407.  
  408. /****************************************************************************/
  409.  
  410. long
  411. amiga_getpid(void)
  412. {
  413.     static long old_pid = -1;
  414.     long result;
  415.  
  416.     ENTER();
  417.  
  418.     if(old_pid == -1)
  419.     {
  420.         struct Process * this_process;
  421.         LONG max_cli;
  422.         LONG which;
  423.         LONG i;
  424.  
  425.         this_process = (struct Process *)FindTask(NULL);
  426.  
  427.         Forbid();
  428.  
  429.         which = max_cli = MaxCli();
  430.  
  431.         for(i = 1 ; i <= max_cli ; i++)
  432.         {
  433.             if(FindCliProc(i) == this_process)
  434.             {
  435.                 which = i;
  436.                 break;
  437.             }
  438.         }
  439.  
  440.         Permit();
  441.  
  442.         old_pid = which;
  443.     }
  444.  
  445.     result = old_pid;
  446.  
  447.     RETURN(result);
  448.     return(result);
  449. }
  450.  
  451. /****************************************************************************/
  452.  
  453. char *
  454. amiga_getlogin(void)
  455. {
  456.     static char name[256];
  457.     int i;
  458.  
  459.     ENTER();
  460.  
  461.     if(GetVar("USER",name,sizeof(name),0) <= 0)
  462.     {
  463.         if(GetVar("LOGUSER",name,sizeof(name),0) <= 0)
  464.         {
  465.             if(GetVar("USERNAME",name,sizeof(name),0) <= 0)
  466.                 strcpy(name,"anonymous");
  467.         }
  468.     }
  469.  
  470.     for(i = strlen(name)-1 ; i >= 0 ; i--)
  471.     {
  472.         if(name[i] == ' ' || name[i] == '\t' || name[i] == '\r' || name[i] == '\n')
  473.             name[i] = '\0';
  474.         else
  475.             break;
  476.     }
  477.  
  478.     SHOWSTRING(name);
  479.  
  480.     RETURN(name);
  481.     return(name);
  482. }
  483.  
  484. /****************************************************************************/
  485.  
  486. struct passwd *
  487. amiga_getpwuid(int uid)
  488. {
  489.     static struct passwd pw;
  490.  
  491.     ENTER();
  492.  
  493.     SHOWVALUE(uid);
  494.  
  495.     memset(&pw,0,sizeof(pw));
  496.  
  497.     pw.pw_dir    = "CVSHOME:";        /* pseudo-home directory */
  498.     pw.pw_gid    = 1;                /* ZZZ wrong */
  499.     pw.pw_name    = amiga_getlogin();
  500.     pw.pw_uid    = uid;                /* ZZZ wrong */
  501.  
  502.     RETURN(&pw);
  503.     return(&pw);
  504. }
  505.  
  506. /****************************************************************************/
  507.  
  508. struct passwd *
  509. amiga_getpwnam(char *name)
  510. {
  511.     struct passwd * result;
  512.  
  513.     ENTER();
  514.  
  515.     SHOWSTRING(name);
  516.  
  517.     result = amiga_getpwuid(1);
  518.  
  519.     RETURN(result);
  520.     return(result);
  521. }
  522.  
  523. /****************************************************************************/
  524.  
  525. struct group *
  526. amiga_getgrnam(char *name)
  527. {
  528.     struct group * result;
  529.  
  530.     ENTER();
  531.  
  532.     result = NULL;
  533.  
  534.     RETURN(result);
  535.     return(result);
  536. }
  537.  
  538. /****************************************************************************/
  539.  
  540. char *
  541. amiga_getpass(const char *prompt)
  542. {
  543.     struct UFB * ufb;
  544.     char * result = NULL;
  545.  
  546.     ENTER();
  547.  
  548.     SHOWSTRING(prompt);
  549.  
  550.     ufb = chkufb(fileno(stdin));
  551.     if(ufb != NULL)
  552.     {
  553.         if(SetMode(ufb->ufbfh,DOSTRUE))
  554.         {
  555.             static char pwd_buf[128];
  556.             int len,c;
  557.  
  558.             fputs(prompt, stderr);
  559.             fflush(stderr);
  560.  
  561.             len = 0;
  562.             while(TRUE)
  563.             {
  564.                 c = -1;
  565.  
  566.                 while(TRUE)
  567.                 {
  568.                     if(CheckSignal(SIGBREAKF_CTRL_C))
  569.                     {
  570.                         SetMode(ufb->ufbfh,DOSFALSE);
  571.                         raise(SIGINT);
  572.                         SetMode(ufb->ufbfh,DOSTRUE);
  573.                     }
  574.  
  575.                     if(WaitForChar(ufb->ufbfh,TICKS_PER_SECOND / 2))
  576.                     {
  577.                         c = fgetc(stdin);
  578.                         if(c == '\003')
  579.                         {
  580.                             SetMode(ufb->ufbfh,DOSFALSE);
  581.                             raise(SIGINT);
  582.                             SetMode(ufb->ufbfh,DOSTRUE);
  583.                         }
  584.                         else
  585.                         {
  586.                             break;
  587.                         }
  588.                     }
  589.                 }
  590.  
  591.                 if(c == '\r' || c == '\n')
  592.                     break;
  593.  
  594.                 if(((c >= ' ' && c < 127) || (c >= 160)) && len < sizeof(pwd_buf)-1)
  595.                 {
  596.                     pwd_buf[len] = c;
  597.                     pwd_buf[len+1] = '\0';
  598.                 }
  599.             }
  600.  
  601.             SetMode(ufb->ufbfh,DOSFALSE);
  602.  
  603.             fputs("\n",stderr);
  604.  
  605.             SHOWSTRING(pwd_buf);
  606.  
  607.             result = pwd_buf;
  608.         }
  609.     }
  610.  
  611.     RETURN(result);
  612.     return(result);
  613. }
  614.  
  615. /****************************************************************************/
  616.  
  617. int
  618. amiga_gethostname(char * name,int namelen)
  619. {
  620.     static char hostname[256];
  621.     int i,len;
  622.  
  623.     ENTER();
  624.  
  625.     if(GetVar("HOST",hostname,sizeof(hostname),0) <= 0)
  626.     {
  627.         if(GetVar("HOSTNAME",hostname,sizeof(hostname),0) <= 0)
  628.             strcpy(hostname,"anonymous");
  629.     }
  630.  
  631.     for(i = strlen(hostname)-1 ; i >= 0 ; i--)
  632.     {
  633.         if(hostname[i] == ' ' || hostname[i] == '\t' || hostname[i] == '\r' || hostname[i] == '\n')
  634.             hostname[i] = '\0';
  635.         else
  636.             break;
  637.     }
  638.  
  639.     len = strlen(hostname);
  640.     if(len > namelen)
  641.         len = namelen;
  642.  
  643.     memcpy(name,hostname,len);
  644.     name[len] = '\0';
  645.  
  646.     SHOWSTRING(name);
  647.  
  648.     RETURN(0);
  649.     return(0);
  650. }
  651.  
  652. /****************************************************************************/
  653.  
  654. int
  655. amiga_pclose(FILE * pipe)
  656. {
  657.     ENTER();
  658.  
  659.     fclose(pipe);
  660.  
  661.     RETURN(0);
  662.     return(0);
  663. }
  664.  
  665. /****************************************************************************/
  666.  
  667. FILE *
  668. amiga_popen(char * command, const char * mode)
  669. {
  670.     FILE * result = NULL;
  671.     char temp_name[40];
  672.     BPTR output;
  673.  
  674.     ENTER();
  675.  
  676.     correct_name(&command);
  677.  
  678.     SHOWSTRING(command);
  679.     SHOWSTRING(mode);
  680.  
  681.     sprintf(temp_name,"PIPE:%08x.%08x",FindTask(NULL),time(NULL));
  682.  
  683.     output = Open(temp_name,MODE_NEWFILE);
  684.     if(output != ZERO)
  685.     {
  686.         LONG res;
  687.  
  688.         res = SystemTags(command,
  689.             SYS_Input,        Input(),
  690.             SYS_Output,        output,
  691.             SYS_Asynch,        TRUE,
  692.             SYS_UserShell,    TRUE,
  693.             NP_CloseInput,    FALSE,
  694.         TAG_END);
  695.  
  696.         switch(res)
  697.         {
  698.             case 0:
  699.                 result = fopen(temp_name,mode);
  700.                 break;
  701.  
  702.             case -1:
  703.                 errno = ENOMEM;
  704.                 Close(output);
  705.                 break;
  706.  
  707.             default:
  708.                 errno = EIO;
  709.                 break;
  710.         }
  711.     }
  712.     else
  713.     {
  714.         errno = EIO;
  715.     }
  716.  
  717.     RETURN(result);
  718.     return(result);
  719. }
  720.  
  721. /****************************************************************************/
  722.  
  723. static struct MsgPort magic_port;
  724.  
  725. /****************************************************************************/
  726.  
  727. #define ACTION_LOCATE_SOCKET    2050    /* arg1=domain, arg2=type, arg3=protocol -> lock (BPTR) */
  728. #define ACTION_COPY_DIR_SOCKET    2051    /* arg1=socket -> lock (BPTR) */
  729.  
  730. /****************************************************************************/
  731.  
  732. static void
  733. dispatch(void)
  734. {
  735.     struct FileHandle * fh;
  736.     struct FileLock * fl;
  737.     long fd;
  738.     struct DosPacket * dp;
  739.     struct Message * mn;
  740.     LONG res1,res2;
  741.  
  742.     ENTER();
  743.  
  744.     /* We arrive here with interrupt processing disabled. We don't need
  745.      * that and we certainly don't want that either.
  746.      */
  747.     Enable();
  748.  
  749.     /* There's always just one message waiting. */
  750.     mn = GetMsg(&magic_port);
  751.  
  752.     dp = (struct DosPacket *)mn->mn_Node.ln_Name;
  753.  
  754.     res1 = DOSFALSE;
  755.     res2 = 0;
  756.  
  757.     switch(dp->dp_Action)
  758.     {
  759.         case ACTION_FREE_LOCK: /* lock -> bool */
  760.  
  761.             SHOWMSG("ACTION_FREE_LOCK");
  762.  
  763.             fl = BADDR(dp->dp_Arg1);
  764.  
  765.             if(SocketBase != NULL)
  766.                 CloseSocket(fl->fl_Key);
  767.  
  768.             res1 = DOSTRUE;
  769.  
  770.             break;
  771.  
  772.         case ACTION_READ: /* socket,buffer (APTR),length -> length */
  773.  
  774.             SHOWMSG("ACTION_READ");
  775.             SHOWVALUE(dp->dp_Arg3);
  776.  
  777.             if(SocketBase != NULL)
  778.                 res1 = recv(dp->dp_Arg1,(APTR)dp->dp_Arg2,dp->dp_Arg3,0);
  779.  
  780.             break;
  781.  
  782.         case ACTION_WRITE: /* socket,buffer (APTR),length -> length */
  783.  
  784.             SHOWMSG("ACTION_WRITE");
  785.             SHOWVALUE(dp->dp_Arg3);
  786.  
  787.             if(SocketBase != NULL)
  788.                 res1 = send(dp->dp_Arg1,(APTR)dp->dp_Arg2,dp->dp_Arg3,0);
  789.  
  790.             break;
  791.  
  792.         case ACTION_END: /* socket -> bool */
  793.  
  794.             SHOWMSG("ACTION_END");
  795.  
  796.             if(SocketBase != NULL)
  797.                 CloseSocket(dp->dp_Arg1);
  798.  
  799.             res1 = DOSTRUE;
  800.  
  801.             break;
  802.  
  803.         case ACTION_FH_FROM_LOCK: /* file handle (BPTR), lock (BPTR) -> bool */
  804.  
  805.             SHOWMSG("ACTION_FH_FROM_LOCK");
  806.  
  807.             fh = BADDR(dp->dp_Arg1);
  808.             fl = BADDR(dp->dp_Arg2);
  809.  
  810.             fh->fh_Arg1 = fl->fl_Key;
  811.  
  812.             FreeVec(fl);
  813.  
  814.             res1 = DOSTRUE;
  815.  
  816.             break;
  817.  
  818.         case ACTION_LOCATE_SOCKET: /* domain, type, protocol -> lock (BPTR) */
  819.  
  820.             SHOWMSG("ACTION_LOCATE_SOCKET");
  821.  
  822.             if(SocketBase != NULL)
  823.                 fd = socket(dp->dp_Arg1,dp->dp_Arg2,dp->dp_Arg3);
  824.             else
  825.                 fd = -1;
  826.  
  827.             if(fd < 0)
  828.             {
  829.                 res2 = ERROR_NO_FREE_STORE;
  830.                 break;
  831.             }
  832.  
  833.             fl = AllocVec(sizeof(*fl),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  834.             if(fl == NULL)
  835.             {
  836.                 CloseSocket(fd);
  837.                 res2 = ERROR_NO_FREE_STORE;
  838.                 break;
  839.             }
  840.  
  841.             fl->fl_Key        = fd;
  842.             fl->fl_Access    = SHARED_LOCK;
  843.             fl->fl_Task        = &magic_port;
  844.  
  845.             res1 = MKBADDR(fl);
  846.  
  847.             break;
  848.  
  849.         case ACTION_COPY_DIR_SOCKET: /* socket -> lock (BPTR) */
  850.  
  851.             SHOWMSG("ACTION_COPY_DIR_SOCKET");
  852.  
  853.             if(SocketBase != NULL)
  854.                 fd = Dup2Socket(dp->dp_Arg1,-1);
  855.             else
  856.                 fd = -1;
  857.  
  858.             if(fd < 0)
  859.             {
  860.                 res2 = ERROR_NO_FREE_STORE;
  861.                 break;
  862.             }
  863.  
  864.             fl = AllocVec(sizeof(*fl),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  865.             if(fl == NULL)
  866.             {
  867.                 CloseSocket(fd);
  868.                 res2 = ERROR_NO_FREE_STORE;
  869.                 break;
  870.             }
  871.  
  872.             fl->fl_Key        = fd;
  873.             fl->fl_Access    = SHARED_LOCK;
  874.             fl->fl_Task        = &magic_port;
  875.  
  876.             res1 = MKBADDR(fl);
  877.  
  878.             break;
  879.  
  880.         default:
  881.  
  882.             D(("ACTION_??? (type=%ld)",dp->dp_Action));
  883.  
  884.             res2 = ERROR_ACTION_NOT_KNOWN;
  885.             break;
  886.     }
  887.  
  888.     SHOWVALUE(res1);
  889.     SHOWVALUE(res2);
  890.  
  891.     ReplyPkt(dp,res1,res2);
  892.  
  893.     /* Return to the entry state, that is with interrupts disabled
  894.      * since PutMsg() will turn them back on before it returns.
  895.      */
  896.     Disable();
  897.  
  898.     LEAVE();
  899. }
  900.  
  901. /****************************************************************************/
  902.  
  903. CBMLIB_DESTRUCTOR(close_libs)
  904. {
  905.     ENTER();
  906.  
  907.     if(LocaleBase != NULL)
  908.     {
  909.         CloseLibrary(LocaleBase);
  910.         LocaleBase = NULL;
  911.     }
  912.  
  913.     if(SocketBase != NULL)
  914.     {
  915.         CloseLibrary(SocketBase);
  916.         SocketBase = NULL;
  917.     }
  918.  
  919.     if(UserGroupBase != NULL)
  920.     {
  921.         CloseLibrary(UserGroupBase);
  922.         UserGroupBase = NULL;
  923.     }
  924.  
  925.     LEAVE();
  926. }
  927.  
  928. /****************************************************************************/
  929.  
  930. CBMLIB_CONSTRUCTOR(init_magic_port)
  931. {
  932.     ENTER();
  933.  
  934.     /* Don't try this at home kids! We're all trained professionals here. */
  935.     magic_port.mp_Flags    = 3;
  936.     magic_port.mp_SigTask = (APTR)dispatch;
  937.     NewList(&magic_port.mp_MsgList);
  938.  
  939.     RETURN(0);
  940.     return(0);
  941. }
  942.  
  943. /****************************************************************************/
  944.  
  945. static void
  946. initialize_libraries(void)
  947. {
  948.     ENTER();
  949.  
  950.     if(SocketBase == NULL && UserGroupBase == NULL)
  951.     {
  952.         SocketBase = OpenLibrary("bsdsocket.library",3);
  953.         if(SocketBase != NULL)
  954.         {
  955.             extern STRPTR _ProgramName;
  956.  
  957.             if(SocketBaseTags(
  958.                 SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),    &errno,
  959.                 SBTM_SETVAL(SBTC_LOGTAGPTR),                _ProgramName,
  960.                 SBTM_SETVAL(SBTC_BREAKMASK),                SIGBREAKF_CTRL_C,
  961.             TAG_END) != 0)
  962.             {
  963.                 CloseLibrary(SocketBase);
  964.                 SocketBase = NULL;
  965.             }
  966.         }
  967.  
  968.         UserGroupBase = OpenLibrary("usergroup.library",1);
  969.         if(UserGroupBase != NULL)
  970.         {
  971.             if(ug_SetupContextTags(_ProgramName,
  972.                 UGT_ERRNOPTR(sizeof(errno)),&errno,
  973.             TAG_END) != 0)
  974.             {
  975.                 CloseLibrary(UserGroupBase);
  976.                 UserGroupBase = NULL;
  977.             }
  978.         }
  979.  
  980.         if(SocketBase == NULL)
  981.         {
  982.             fprintf(stderr,"Could not open 'bsdsocket.library' V3; TCP/IP stack not running?\n");
  983.             exit(RETURN_FAIL);
  984.         }
  985.         else if (UserGroupBase == NULL)
  986.         {
  987.             fprintf(stderr,"Could not open 'usergroup.library' V1; TCP/IP stack not running?\n");
  988.             exit(RETURN_FAIL);
  989.         }
  990.     }
  991.  
  992.     LEAVE();
  993. }
  994.  
  995. /****************************************************************************/
  996.  
  997. VOID __regargs
  998. __chkabort(VOID)
  999. {
  1000.     if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  1001.         raise(SIGINT);
  1002. }
  1003.  
  1004. VOID __regargs
  1005. _CXBRK(VOID)
  1006. {
  1007.     extern STRPTR _ProgramName;
  1008.  
  1009.     /* Flush the standard output streams so that
  1010.      * any following output will be printed after
  1011.      * any buffered stdio output.
  1012.      */
  1013.     if(WBenchMsg == NULL)
  1014.     {
  1015.         /* Don't let anybody stop us. */
  1016.         signal(SIGINT,SIG_IGN);
  1017.         signal(SIGTERM,SIG_IGN);
  1018.  
  1019.         fflush(stdout);
  1020.         fflush(stderr);
  1021.     }
  1022.  
  1023.     /* This routine is called when the program is interrupted. */
  1024.     if(DOSBase->lib_Version >= 37)
  1025.     {
  1026.         PrintFault(ERROR_BREAK,_ProgramName);
  1027.     }
  1028.     else
  1029.     {
  1030.         const char *famousLastWords = ": *** Break";
  1031.         BPTR output = Output();
  1032.  
  1033.         Write(output,(APTR)famousLastWords,strlen(famousLastWords));
  1034.         Write(output,_ProgramName,strlen(_ProgramName));
  1035.         Write(output,"\n",1);
  1036.     }
  1037.  
  1038.     exit(RETURN_WARN);
  1039. }
  1040.  
  1041. /****************************************************************************/
  1042.  
  1043. char *
  1044. amiga_strerror(int code)
  1045. {
  1046.     char * result;
  1047.  
  1048.     ENTER();
  1049.  
  1050.     if(SocketBase != NULL)
  1051.     {
  1052.         struct TagItem tags[2];
  1053.  
  1054.         tags[0].ti_Tag    = SBTM_GETVAL(SBTC_ERRNOSTRPTR);
  1055.         tags[0].ti_Data    = code;
  1056.         tags[1].ti_Tag    = TAG_END;
  1057.  
  1058.         SocketBaseTagList(tags);
  1059.  
  1060.         result = (char *)tags[0].ti_Data;
  1061.     }
  1062.     else
  1063.     {
  1064.         result = strerror(code);
  1065.     }
  1066.  
  1067.     SHOWSTRING(result);
  1068.  
  1069.     RETURN(result);
  1070.     return(result);
  1071. }
  1072.  
  1073. /****************************************************************************/
  1074.  
  1075. int
  1076. amiga_mkdir(char *name,int mode)
  1077. {
  1078.     int result;
  1079.  
  1080.     ENTER();
  1081.  
  1082.     correct_name(&name);
  1083.  
  1084.     SHOWSTRING(name);
  1085.  
  1086.     result = mkdir(name);
  1087.  
  1088.     RETURN(result);
  1089.     return(result);
  1090. }
  1091.  
  1092. /****************************************************************************/
  1093.  
  1094. struct hostent *
  1095. amiga_gethostbyname(char *name)
  1096. {
  1097.     struct hostent *result;
  1098.  
  1099.     ENTER();
  1100.     SHOWSTRING(name);
  1101.  
  1102.     initialize_libraries();
  1103.  
  1104.     result = gethostbyname(name);
  1105.  
  1106.     RETURN(result);
  1107.     return(result);
  1108. }
  1109.  
  1110. struct servent *
  1111. amiga_getservbyname(char *name,char *proto)
  1112. {
  1113.     struct servent *result;
  1114.  
  1115.     ENTER();
  1116.  
  1117.     SHOWSTRING(name);
  1118.     SHOWSTRING(proto);
  1119.  
  1120.     initialize_libraries();
  1121.  
  1122.     result = getservbyname(name,proto);
  1123.  
  1124.     RETURN(result);
  1125.     return(result);
  1126. }
  1127.  
  1128. /****************************************************************************/
  1129.  
  1130. int
  1131. amiga_bind(int fd,struct sockaddr *name,int namelen)
  1132. {
  1133.     struct FileHandle * fh;
  1134.     struct UFB * ufb;
  1135.     int result = -1;
  1136.  
  1137.     ENTER();
  1138.  
  1139.     initialize_libraries();
  1140.  
  1141.     ufb = chkufb(fd);
  1142.     if(ufb == NULL)
  1143.     {
  1144.         errno = EIO;
  1145.         goto out;
  1146.     }
  1147.  
  1148.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1149.     if(fh->fh_Type != &magic_port)
  1150.     {
  1151.         errno = EBADF;
  1152.         goto out;
  1153.     }
  1154.  
  1155.     result = bind(fh->fh_Arg1,name,namelen);
  1156.  
  1157.  out:
  1158.  
  1159.     RETURN(result);
  1160.     return(result);
  1161. }
  1162.  
  1163. int
  1164. amiga_connect(int fd,struct sockaddr *name,int namelen)
  1165. {
  1166.     struct FileHandle * fh;
  1167.     struct UFB * ufb;
  1168.     int result = -1;
  1169.  
  1170.     ENTER();
  1171.  
  1172.     initialize_libraries();
  1173.  
  1174.     ufb = chkufb(fd);
  1175.     if(ufb == NULL)
  1176.     {
  1177.         errno = EIO;
  1178.         goto out;
  1179.     }
  1180.  
  1181.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1182.     if(fh->fh_Type != &magic_port)
  1183.     {
  1184.         errno = EBADF;
  1185.         goto out;
  1186.     }
  1187.  
  1188.     result = connect(fh->fh_Arg1,name,namelen);
  1189.  
  1190.  out:
  1191.  
  1192.     RETURN(result);
  1193.     return(result);
  1194. }
  1195.  
  1196. int
  1197. amiga_dup(int socketfd)
  1198. {
  1199.     struct FileHandle * fh;
  1200.     BPTR socket_lock = ZERO;
  1201.     BPTR socket_handle = ZERO;
  1202.     int fd = -1;
  1203.     struct UFB * ufb;
  1204.  
  1205.     ENTER();
  1206.  
  1207.     initialize_libraries();
  1208.  
  1209.     ufb = chkufb(socketfd);
  1210.     if(ufb == NULL)
  1211.     {
  1212.         errno = EIO;
  1213.         goto out;
  1214.     }
  1215.  
  1216.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1217.     if(fh->fh_Type != &magic_port)
  1218.     {
  1219.         errno = EBADF;
  1220.         goto out;
  1221.     }
  1222.  
  1223.     socket_lock = DoPkt(&magic_port,ACTION_COPY_DIR_SOCKET,fh->fh_Arg1,    0,0,0,0);
  1224.     if(socket_lock == ZERO)
  1225.     {
  1226.         errno = EIO;
  1227.         goto out;
  1228.     }
  1229.  
  1230.     socket_handle = OpenFromLock(socket_lock);
  1231.     if(socket_handle == ZERO)
  1232.     {
  1233.         errno = EIO;
  1234.         goto out;
  1235.     }
  1236.  
  1237.     socket_lock = ZERO;
  1238.  
  1239.     fd = open("NIL:",O_RDWR,0777);
  1240.     if(fd < 0)
  1241.         goto out;
  1242.  
  1243.     ufb = chkufb(fd);
  1244.     if(ufb == NULL)
  1245.     {
  1246.         int error;
  1247.  
  1248.         error = errno;
  1249.  
  1250.         close(fd);
  1251.         fd = -1;
  1252.  
  1253.         errno = error;
  1254.         goto out;
  1255.     }
  1256.  
  1257.     Close(ufb->ufbfh);
  1258.     ufb->ufbfh = socket_handle;
  1259.  
  1260.     socket_handle = ZERO;
  1261.  
  1262.  out:
  1263.  
  1264.     if(fd < 0)
  1265.     {
  1266.         if(socket_handle != ZERO)
  1267.             Close(socket_handle);
  1268.  
  1269.         UnLock(socket_lock);
  1270.     }
  1271.  
  1272.     RETURN(fd);
  1273.     return(fd);
  1274. }
  1275.  
  1276. int
  1277. amiga_recv(int fd,void *buff,size_t nbytes,int flags)
  1278. {
  1279.     struct FileHandle * fh;
  1280.     struct UFB * ufb;
  1281.     int result = -1;
  1282.  
  1283.     ENTER();
  1284.  
  1285.     initialize_libraries();
  1286.  
  1287.     ufb = chkufb(fd);
  1288.     if(ufb == NULL)
  1289.     {
  1290.         errno = EIO;
  1291.         goto out;
  1292.     }
  1293.  
  1294.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1295.     if(fh->fh_Type != &magic_port)
  1296.     {
  1297.         errno = EBADF;
  1298.         goto out;
  1299.     }
  1300.  
  1301.     result = recv(fh->fh_Arg1,buff,nbytes,flags);
  1302.  
  1303.  out:
  1304.  
  1305.     RETURN(result);
  1306.     return(result);
  1307. }
  1308.  
  1309. int
  1310. amiga_send(int fd,void *buff,size_t nbytes,int flags)
  1311. {
  1312.     struct FileHandle * fh;
  1313.     struct UFB * ufb;
  1314.     int result = -1;
  1315.  
  1316.     ENTER();
  1317.  
  1318.     initialize_libraries();
  1319.  
  1320.     ufb = chkufb(fd);
  1321.     if(ufb == NULL)
  1322.     {
  1323.         errno = EIO;
  1324.         goto out;
  1325.     }
  1326.  
  1327.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1328.     if(fh->fh_Type != &magic_port)
  1329.     {
  1330.         errno = EBADF;
  1331.         goto out;
  1332.     }
  1333.  
  1334.     result = send(fh->fh_Arg1,buff,nbytes,flags);
  1335.  
  1336.  out:
  1337.  
  1338.     RETURN(result);
  1339.     return(result);
  1340. }
  1341.  
  1342. int
  1343. amiga_shutdown(int fd,int how)
  1344. {
  1345.     struct FileHandle * fh;
  1346.     struct UFB * ufb;
  1347.     int result = -1;
  1348.  
  1349.     ENTER();
  1350.  
  1351.     initialize_libraries();
  1352.  
  1353.     ufb = chkufb(fd);
  1354.     if(ufb == NULL)
  1355.     {
  1356.         errno = EIO;
  1357.         goto out;
  1358.     }
  1359.  
  1360.     fh = (struct FileHandle *)BADDR(ufb->ufbfh);
  1361.     if(fh->fh_Type != &magic_port)
  1362.     {
  1363.         errno = EBADF;
  1364.         goto out;
  1365.     }
  1366.  
  1367.     result = shutdown(fh->fh_Arg1,how);
  1368.  
  1369.  out:
  1370.  
  1371.     RETURN(result);
  1372.     return(result);
  1373. }
  1374.  
  1375. int
  1376. amiga_socket(int domain,int type,int protocol)
  1377. {
  1378.     BPTR socket_lock;
  1379.     BPTR socket_handle = ZERO;
  1380.     int fd = -1;
  1381.     struct UFB * ufb;
  1382.  
  1383.     ENTER();
  1384.  
  1385.     initialize_libraries();
  1386.  
  1387.     socket_lock = DoPkt(&magic_port,ACTION_LOCATE_SOCKET,domain,type,protocol,    0,0);
  1388.     if(socket_lock == ZERO)
  1389.     {
  1390.         errno = EIO;
  1391.         goto out;
  1392.     }
  1393.  
  1394.     socket_handle = OpenFromLock(socket_lock);
  1395.     if(socket_handle == ZERO)
  1396.     {
  1397.         errno = EIO;
  1398.         goto out;
  1399.     }
  1400.  
  1401.     socket_lock = ZERO;
  1402.  
  1403.     fd = open("NIL:",O_RDWR,0777);
  1404.     if(fd < 0)
  1405.         goto out;
  1406.  
  1407.     ufb = chkufb(fd);
  1408.     if(ufb == NULL)
  1409.     {
  1410.         int error;
  1411.  
  1412.         error = errno;
  1413.  
  1414.         close(fd);
  1415.         fd = -1;
  1416.  
  1417.         errno = error;
  1418.         goto out;
  1419.     }
  1420.  
  1421.     Close(ufb->ufbfh);
  1422.     ufb->ufbfh = socket_handle;
  1423.  
  1424.     socket_handle = ZERO;
  1425.  
  1426.  out:
  1427.  
  1428.     if(fd < 0)
  1429.     {
  1430.         if(socket_handle != ZERO)
  1431.             Close(socket_handle);
  1432.  
  1433.         UnLock(socket_lock);
  1434.     }
  1435.  
  1436.     RETURN(fd);
  1437.     return(fd);
  1438. }
  1439.  
  1440. /****************************************************************************/
  1441.  
  1442. int
  1443. amiga_piped_child(char ** argv,int * to_fd_ptr,int * from_fd_ptr)
  1444. {
  1445.     int len,total_len,quotes,escape,argc,i,j;
  1446.     char * s;
  1447.     char * arg;
  1448.     char * command;
  1449.     BPTR input = ZERO;
  1450.     BPTR output = ZERO;
  1451.     char in_name[40];
  1452.     char out_name[40];
  1453.     int result = -1;
  1454.  
  1455.     ENTER();
  1456.  
  1457.     argc = 0;
  1458.     total_len = 0;
  1459.     for (i = 0 ; argv[i] != NULL ; i++)
  1460.     {
  1461.         argc++;
  1462.         arg = argv[i];
  1463.         len = strlen(arg);
  1464.         quotes = 0;
  1465.  
  1466.         for(j = 0 ; j < len ; j++)
  1467.         {
  1468.             if(arg[j] == ' ' && quotes == 0)
  1469.                 quotes = 2;
  1470.             else if (arg[j] == '\"')
  1471.                 total_len++;
  1472.         }
  1473.  
  1474.         total_len += len + quotes + 1;
  1475.     }
  1476.  
  1477.     command = malloc(total_len+1);
  1478.     if(command == NULL)
  1479.     {
  1480.         errno = ENOMEM;
  1481.         return(-1);
  1482.     }
  1483.  
  1484.     s = command;
  1485.  
  1486.     for (i = 0 ; i < argc ; i++)
  1487.     {
  1488.         arg = argv[i];
  1489.         len = strlen(arg);
  1490.         quotes = escape = 0;
  1491.  
  1492.         for(j = 0 ; j < len ; j++)
  1493.         {
  1494.             if(arg[j] == ' ')
  1495.                 quotes = 1;
  1496.             else if (arg[j] == '\"')
  1497.                 escape = 1;
  1498.  
  1499.             if(quotes && escape)
  1500.                 break;
  1501.         }
  1502.  
  1503.         if(quotes)
  1504.             (*s++) = '\"';
  1505.  
  1506.         for(j = 0 ; j < len ; j++)
  1507.         {
  1508.             if(arg[j] == '\"')
  1509.                 (*s++) = '*';
  1510.  
  1511.             (*s++) = arg[j];
  1512.         }
  1513.  
  1514.         if(quotes)
  1515.             (*s++) = '\"';
  1516.  
  1517.         if(i < argc-1)
  1518.             (*s++) = ' ';
  1519.     }
  1520.  
  1521.     (*s) = '\0';
  1522.  
  1523.     SHOWSTRING(command);
  1524.  
  1525.     sprintf(in_name,"PIPE:in_%08x.%08x",FindTask(NULL),time(NULL));
  1526.     sprintf(out_name,"PIPE:out_%08x.%08x",FindTask(NULL),time(NULL));
  1527.  
  1528.     input = Open(in_name,MODE_OLDFILE);
  1529.     output = Open(out_name,MODE_NEWFILE);
  1530.     if(input != ZERO && output != ZERO)
  1531.     {
  1532.         LONG res;
  1533.  
  1534.         res = SystemTags(command,
  1535.             SYS_Input,        input,
  1536.             SYS_Output,        output,
  1537.             SYS_Asynch,        TRUE,
  1538.             SYS_UserShell,    TRUE,
  1539.         TAG_END);
  1540.  
  1541.         switch(res)
  1542.         {
  1543.             case 0:
  1544.                 (*to_fd_ptr) = open(in_name,O_WRONLY,0777);
  1545.                 if((*to_fd_ptr) == -1)
  1546.                     break;
  1547.  
  1548.                 (*from_fd_ptr) = open(out_name,O_RDONLY,0777);
  1549.                 if((*from_fd_ptr) == -1)
  1550.                     break;
  1551.  
  1552.                 result = 0;
  1553.                 break;
  1554.  
  1555.             case -1:
  1556.                 errno = ENOMEM;
  1557.                 Close(input);
  1558.                 Close(output);
  1559.                 break;
  1560.  
  1561.             default:
  1562.                 errno = EIO;
  1563.                 break;
  1564.         }
  1565.     }
  1566.     else
  1567.     {
  1568.         if(input != ZERO)
  1569.             Close(input);
  1570.  
  1571.         if(output != ZERO)
  1572.             Close(output);
  1573.  
  1574.         errno = EIO;
  1575.     }
  1576.  
  1577.     RETURN(result);
  1578.     return(result);
  1579. }
  1580.  
  1581. /****************************************************************************/
  1582.  
  1583. int
  1584. amiga_isabsolute(char *filename)
  1585. {
  1586.     int result = 0;
  1587.     int i;
  1588.  
  1589.     ENTER();
  1590.  
  1591.     SHOWSTRING(filename);
  1592.  
  1593.     for(i = 1 ; i < strlen(filename) ; i++)
  1594.     {
  1595.         if(filename[i] == ':')
  1596.         {
  1597.             result = 1;
  1598.             break;
  1599.         }
  1600.     }
  1601.  
  1602.     RETURN(result);
  1603.     return(result);
  1604. }
  1605.  
  1606. /****************************************************************************/
  1607.  
  1608. char *
  1609. amiga_last_component(char *path)
  1610. {
  1611.     char * result;
  1612.  
  1613.     ENTER();
  1614.  
  1615.     SHOWSTRING(path);
  1616.  
  1617.     result = FilePart(path);
  1618.  
  1619.     RETURN(result);
  1620.     return(result);
  1621. }
  1622.  
  1623. /****************************************************************************/
  1624.  
  1625. static int
  1626. recursive_unlink_file_dir(char *f)
  1627. {
  1628.     D_S(struct FileInfoBlock,fib);
  1629.     BPTR lock;
  1630.     int res = 0;
  1631.  
  1632.     lock = Lock(f,SHARED_LOCK);
  1633.     if(lock != ZERO)
  1634.     {
  1635.         if(Examine(lock,fib))
  1636.         {
  1637.             if(FIB_IS_DRAWER(fib))
  1638.             {
  1639.                 char name[110];
  1640.  
  1641.                 name[0] = '\0';
  1642.  
  1643.                 while(ExNext(lock,fib))
  1644.                 {
  1645.                     if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  1646.                     {
  1647.                         res = -1;
  1648.                         break;
  1649.                     }
  1650.  
  1651.                     if(name[0] != '\0')
  1652.                     {
  1653.                         if(DeleteFile(name))
  1654.                         {
  1655.                             res = -1;
  1656.                             break;
  1657.                         }
  1658.  
  1659.                         name[0] = '\0';
  1660.                     }
  1661.  
  1662.                     if(FIB_IS_DRAWER(fib))
  1663.                     {
  1664.                         BPTR old_dir;
  1665.  
  1666.                         old_dir = CurrentDir(lock);
  1667.                         res = recursive_unlink_file_dir(fib->fib_FileName);
  1668.                         CurrentDir(old_dir);
  1669.  
  1670.                         if(res != 0)
  1671.                             break;
  1672.                     }
  1673.  
  1674.                     strcpy(name,fib->fib_FileName);
  1675.                 }
  1676.  
  1677.                 if(res == 0 && name[0] != '\0')
  1678.                 {
  1679.                     if(CANNOT DeleteFile(name))
  1680.                         res = -1;
  1681.                 }
  1682.             }
  1683.  
  1684.             UnLock(lock);
  1685.  
  1686.             if(res == 0)
  1687.             {
  1688.                 if(CANNOT DeleteFile(f))
  1689.                     res = -1;
  1690.             }
  1691.         }
  1692.         else
  1693.         {
  1694.             UnLock(lock);
  1695.         }
  1696.     }
  1697.  
  1698.     return(res);
  1699. }
  1700.  
  1701. int
  1702. amiga_unlink_file_dir(char * f)
  1703. {
  1704.     int res;
  1705.  
  1706.     ENTER();
  1707.  
  1708.     correct_name(&f);
  1709.  
  1710.     SHOWSTRING(f);
  1711.  
  1712.     res = recursive_unlink_file_dir(f);
  1713.  
  1714.     RETURN(res);
  1715.     return(res);
  1716. }
  1717.  
  1718. /****************************************************************************/
  1719.  
  1720. int
  1721. amiga_fncmp(char *n1,char *n2)
  1722. {
  1723.     int result;
  1724.  
  1725.     ENTER();
  1726.  
  1727.     SHOWSTRING(n1);
  1728.     SHOWSTRING(n2);
  1729.  
  1730.     result = Stricmp(n1,n2);
  1731.  
  1732.     RETURN(result);
  1733.     return(result);
  1734. }
  1735.  
  1736. /****************************************************************************/
  1737.  
  1738. void
  1739. amiga_fnfold(unsigned char *name)
  1740. {
  1741.     int c;
  1742.  
  1743.     while((c = (*name)) != '\0')
  1744.         (*name++) = ToLower(c);
  1745. }
  1746.  
  1747. /****************************************************************************/
  1748.  
  1749. int
  1750. amiga_fold_fn_char(int c)
  1751. {
  1752.     int result;
  1753.  
  1754.     result = ToLower(c);
  1755.  
  1756.     return(result);
  1757. }
  1758.  
  1759. /****************************************************************************/
  1760.  
  1761. typedef struct name_node
  1762. {
  1763.     struct name_node *    nn_next;
  1764.     char *                nn_name;
  1765.     BOOL                nn_wild;
  1766. } name_node_t;
  1767.  
  1768. static int
  1769. compare(char **a,char **b)
  1770. {
  1771.     return(Stricmp(*a,*b));
  1772. }
  1773.  
  1774. void
  1775. amiga_expand_wild(int argc,char ** argv,int * _argc,char *** _argv)
  1776. {
  1777.     struct AnchorPath * anchor;
  1778.     name_node_t * root;
  1779.     name_node_t * node;
  1780.     LONG name_plus;
  1781.     LONG name_total;
  1782.     LONG i;
  1783.  
  1784.     ENTER();
  1785.  
  1786.     anchor        = (struct AnchorPath *)xmalloc(sizeof(*anchor) + 2 * MAX_FILENAME_LEN);
  1787.     root        = NULL;
  1788.     name_plus    = 0;
  1789.     name_total    = 0;
  1790.  
  1791.     memset(anchor,0,sizeof(*anchor));
  1792.  
  1793.     anchor->ap_Strlen        = MAX_FILENAME_LEN;
  1794.     anchor->ap_BreakBits    = SIGBREAKF_CTRL_C;
  1795.  
  1796.     for(i = 0 ; i < argc ; i++)
  1797.     {
  1798.         if(i > 0 && ParsePatternNoCase(argv[i],anchor->ap_Buf,2 * MAX_FILENAME_LEN) > 0)
  1799.         {
  1800.             LONG result;
  1801.  
  1802.             result = MatchFirst(argv[i],anchor);
  1803.  
  1804.             while(result == 0)
  1805.             {
  1806.                 node = (name_node_t *)malloc(sizeof(*node) + strlen(anchor->ap_Buf) + 1);
  1807.                 if(node == NULL)
  1808.                 {
  1809.                     char buf[80];
  1810.  
  1811.                     MatchEnd(anchor);
  1812.  
  1813.                     sprintf(buf,"out of memory; can not allocate %lu bytes",
  1814.                         (unsigned long)(sizeof(*node) + strlen(anchor->ap_Buf) + 1));
  1815.  
  1816.                     error(1,0,buf);
  1817.                 }
  1818.  
  1819.                 node->nn_name = (char *)(node + 1);
  1820.                 node->nn_next = root;
  1821.                 node->nn_wild = TRUE;
  1822.  
  1823.                 strcpy(node->nn_name,anchor->ap_Buf);
  1824.  
  1825.                 root = node;
  1826.  
  1827.                 name_plus++;
  1828.                 name_total++;
  1829.  
  1830.                 result = MatchNext(anchor);
  1831.             }
  1832.  
  1833.             MatchEnd(anchor);
  1834.         }
  1835.         else
  1836.         {
  1837.             node = (name_node_t *)xmalloc(sizeof(*node));
  1838.  
  1839.             node->nn_name = argv[i];
  1840.             node->nn_next = root;
  1841.             node->nn_wild = FALSE;
  1842.  
  1843.             root = node;
  1844.  
  1845.             name_total++;
  1846.         }
  1847.     }
  1848.  
  1849.     if(name_plus > 0)
  1850.     {
  1851.         char ** last_wild;
  1852.         char ** index;
  1853.  
  1854.         index = (char **)xmalloc(sizeof(char *) * (name_total + 1));
  1855.  
  1856.         (*_argc) = name_total;
  1857.         (*_argv) = index;
  1858.  
  1859.         index = &(index[name_total]);
  1860.  
  1861.         (*index--) = NULL;
  1862.  
  1863.         node        = root;
  1864.         last_wild    = NULL;
  1865.  
  1866.         while(node != NULL)
  1867.         {
  1868.             if(node->nn_wild)
  1869.             {
  1870.                 if(last_wild == NULL)
  1871.                     last_wild = index;
  1872.             }
  1873.             else
  1874.             {
  1875.                 if(last_wild)
  1876.                 {
  1877.                     if((ULONG)last_wild - (ULONG)index > sizeof(char **))
  1878.                         qsort(index + 1,((ULONG)last_wild - (ULONG)index) / sizeof(char **),sizeof(char *),compare);
  1879.  
  1880.                     last_wild = NULL;
  1881.                 }
  1882.             }
  1883.  
  1884.             (*index--) = node->nn_name;
  1885.  
  1886.             node = node->nn_next;
  1887.         }
  1888.     }
  1889.     else
  1890.     {
  1891.         name_node_t * next;
  1892.  
  1893.         node = root;
  1894.  
  1895.         while(node != NULL)
  1896.         {
  1897.             next = node->nn_next;
  1898.  
  1899.             free(node);
  1900.  
  1901.             node = next;
  1902.         }
  1903.     }
  1904.  
  1905.     free(anchor);
  1906.  
  1907.     LEAVE();
  1908. }
  1909.  
  1910. /****************************************************************************/
  1911.  
  1912. int
  1913. amiga_access(char *name,int modes)
  1914. {
  1915.     int result;
  1916.  
  1917.     ENTER();
  1918.  
  1919.     correct_name(&name);
  1920.  
  1921.     SHOWSTRING(name);
  1922.     SHOWVALUE(modes);
  1923.  
  1924.     result = access(name,modes);
  1925.  
  1926.     RETURN(result);
  1927.     return(result);
  1928. }
  1929.  
  1930. static BPTR home_dir;
  1931.  
  1932. DEFAULT_DESTRUCTOR(restore_home_dir)
  1933. {
  1934.     if(home_dir != ZERO)
  1935.     {
  1936.         UnLock(CurrentDir(home_dir));
  1937.         home_dir = ZERO;
  1938.     }
  1939. }
  1940.  
  1941. int
  1942. amiga_chdir(char *path)
  1943. {
  1944.     int result;
  1945.  
  1946.     ENTER();
  1947.  
  1948.     if(home_dir == ZERO)
  1949.     {
  1950.         BPTR old_dir;
  1951.  
  1952.         /* This is tricky at best. chdir() will change the
  1953.          * current directory of this process and unlock the
  1954.          * previously active current directory lock. However,
  1955.          * the current directory lock with which this program
  1956.          * was launched *must not* be unlocked; the same lock
  1957.          * the program was launched with must be the one the
  1958.          * program exits with. This is what we are trying to
  1959.          * achieve here.
  1960.          */
  1961.         old_dir = Lock("",SHARED_LOCK);
  1962.         if(old_dir == ZERO)
  1963.         {
  1964.             errno = EIO;
  1965.             result = -1;
  1966.             goto out;
  1967.         }
  1968.  
  1969.         home_dir = CurrentDir(old_dir);
  1970.     }
  1971.  
  1972.     correct_name(&path);
  1973.  
  1974.     SHOWSTRING(path);
  1975.  
  1976.     result = chdir(path);
  1977.  
  1978.  out:
  1979.  
  1980.     RETURN(result);
  1981.     return(result);
  1982. }
  1983.  
  1984. int
  1985. amiga_creat(char *name,int prot)
  1986. {
  1987.     int result;
  1988.  
  1989.     ENTER();
  1990.  
  1991.     correct_name(&name);
  1992.  
  1993.     SHOWSTRING(name);
  1994.     SHOWVALUE(prot);
  1995.  
  1996.     result = creat(name,prot);
  1997.  
  1998.     RETURN(result);
  1999.     return(result);
  2000. }
  2001.  
  2002. FILE *
  2003. amiga_fopen(char *name,const char *modes)
  2004. {
  2005.     FILE * result;
  2006.  
  2007.     ENTER();
  2008.  
  2009.     correct_name(&name);
  2010.  
  2011.     SHOWSTRING(name);
  2012.     SHOWSTRING(modes);
  2013.  
  2014.     result = fopen(name,modes);
  2015.  
  2016.     RETURN(result);
  2017.     return(result);
  2018. }
  2019.  
  2020. int
  2021. amiga_stat(char *name, struct stat *st)
  2022. {
  2023.     int result;
  2024.  
  2025.     ENTER();
  2026.  
  2027.     correct_name(&name);
  2028.  
  2029.     SHOWSTRING(name);
  2030.  
  2031.     result = stat(name,st);
  2032.  
  2033.     RETURN(result);
  2034.     return(result);
  2035. }
  2036.  
  2037. int
  2038. amiga_lstat(char *name, struct stat *st)
  2039. {
  2040.     return(amiga_stat(name,st));
  2041. }
  2042.  
  2043. int
  2044. amiga_open(char *name,int mode,int prot)
  2045. {
  2046.     int result;
  2047.  
  2048.     ENTER();
  2049.  
  2050.     correct_name(&name);
  2051.  
  2052.     SHOWSTRING(name);
  2053.     SHOWVALUE(mode);
  2054.  
  2055.     result = open(name,mode);
  2056.  
  2057.     RETURN(result);
  2058.     return(result);
  2059. }
  2060.  
  2061. void *
  2062. amiga_opendir(char *dir_name)
  2063. {
  2064.     void * result;
  2065.  
  2066.     ENTER();
  2067.  
  2068.     correct_name(&dir_name);
  2069.  
  2070.     SHOWSTRING(dir_name);
  2071.  
  2072.     result = opendir(dir_name);
  2073.  
  2074.     RETURN(result);
  2075.     return(result);
  2076. }
  2077.  
  2078. int
  2079. amiga_rename(char *old,char *new)
  2080. {
  2081.     int result;
  2082.  
  2083.     ENTER();
  2084.  
  2085.     correct_name(&old);
  2086.     correct_name(&new);
  2087.  
  2088.     SHOWSTRING(old);
  2089.     SHOWSTRING(new);
  2090.  
  2091.     result = rename(old,new);
  2092.     if(result == -1 && errno == EEXIST)
  2093.     {
  2094.         unlink(new);
  2095.         result = rename(old,new);
  2096.     }
  2097.  
  2098.     RETURN(result);
  2099.     return(result);
  2100. }
  2101.  
  2102. int
  2103. amiga_rmdir(char *name)
  2104. {
  2105.     int result;
  2106.  
  2107.     ENTER();
  2108.  
  2109.     correct_name(&name);
  2110.  
  2111.     SHOWSTRING(name);
  2112.  
  2113.     result = rmdir(name);
  2114.  
  2115.     RETURN(result);
  2116.     return(result);
  2117. }
  2118.  
  2119. int
  2120. amiga_unlink(char *name)
  2121. {
  2122.     int result;
  2123.  
  2124.     ENTER();
  2125.  
  2126.     correct_name(&name);
  2127.  
  2128.     SHOWSTRING(name);
  2129.  
  2130.     result = unlink(name);
  2131.  
  2132.     RETURN(result);
  2133.     return(result);
  2134. }
  2135.  
  2136. int
  2137. amiga_chmod(char *name,int mode)
  2138. {
  2139.     int result;
  2140.  
  2141.     ENTER();
  2142.  
  2143.     correct_name(&name);
  2144.  
  2145.     SHOWSTRING(name);
  2146.  
  2147.     result = chmod(name,mode | S_IREAD | S_IWRITE | S_IDELETE);
  2148.  
  2149.     RETURN(result);
  2150.     return(result);
  2151. }
  2152.  
  2153. /****************************************************************************/
  2154.  
  2155. char *
  2156. amiga_cvs_temp_name(void)
  2157. {
  2158.     extern char *Tmpdir;
  2159.     char *value;
  2160.     char *retval;
  2161.     int max_len;
  2162.     int len;
  2163.  
  2164.     ENTER();
  2165.  
  2166.     max_len = strlen (Tmpdir) + 40;
  2167.  
  2168.     value = xmalloc (max_len);
  2169.  
  2170.     strcpy(value,Tmpdir);
  2171.     len = strlen(value);
  2172.     while(len > 0 && value[len-1] == '/')
  2173.         value[--len] = '\0';
  2174.  
  2175.     AddPart(value,"cvsXXXXXX",max_len);
  2176.  
  2177.     retval = mktemp (value);
  2178.  
  2179.     if (retval == NULL)
  2180.         error (1, errno, "cannot generate temporary filename");
  2181.  
  2182.     SHOWSTRING(value);
  2183.  
  2184.     RETURN(value);
  2185.     return(value);
  2186. }
  2187.  
  2188. /****************************************************************************/
  2189.  
  2190. static int amiga_rcmd(char **remote_hostname, int remote_port,char *local_user, char *remote_user,char *command)
  2191. {
  2192.   struct hostent *remote_hp;
  2193.   struct hostent *local_hp;
  2194.   struct sockaddr_in remote_isa;
  2195.   struct sockaddr_in local_isa;
  2196.   char local_hostname[80];
  2197.   char ch;
  2198.   int s;
  2199.   int local_port;
  2200.   int rs;
  2201.  
  2202.   remote_hp = amiga_gethostbyname(*remote_hostname);
  2203.   if(!remote_hp)
  2204.     {
  2205.     perror("couldn't get remote host address");
  2206.     exit(1);
  2207.     }
  2208.  
  2209.   /* Copy remote IP address into socket address structure */
  2210.   memset(&remote_isa,0,sizeof(remote_isa));
  2211.   remote_isa.sin_family = AF_INET;
  2212.   remote_isa.sin_port = htons(remote_port);
  2213.   memcpy(&remote_isa.sin_addr, remote_hp->h_addr, sizeof(remote_isa.sin_addr));
  2214.  
  2215.   amiga_gethostname(local_hostname, 80);
  2216.   local_hp = amiga_gethostbyname(local_hostname);
  2217.   if(!local_hp)
  2218.     {
  2219.     perror("couldn't get local host address");
  2220.     exit(1);
  2221.     }
  2222.  
  2223.   /* Copy local IP address into socket address structure */
  2224.   memset(&local_isa,0,sizeof(local_isa));
  2225.   local_isa.sin_family = AF_INET;
  2226.   memcpy(&local_isa.sin_addr, local_hp->h_addr, sizeof(local_isa.sin_addr));
  2227.  
  2228.   /* Create the local socket */
  2229.   s = amiga_socket(AF_INET, SOCK_STREAM, 0);
  2230.   if(s < 0)
  2231.     {
  2232.     perror("socket failed\n");
  2233.     exit(1);
  2234.     }
  2235.  
  2236.   /* Bind local socket with a port from IPPORT_RESERVED/2 to IPPORT_RESERVED - 1
  2237.      this requires the OPER privilege under VMS -- to allow communication with
  2238.      a stock rshd under UNIX */
  2239.  
  2240.   for(local_port = IPPORT_RESERVED - 1; local_port >= IPPORT_RESERVED/2; local_port--)
  2241.     {
  2242.     local_isa.sin_port = htons(local_port);
  2243.     rs = amiga_bind(s, (struct sockaddr *)&local_isa, sizeof(local_isa));
  2244.     if(rs == 0)
  2245.       break;
  2246.     }
  2247.  
  2248.   /* Bind local socket to an unprivileged port.  A normal rshd will drop the
  2249.      connection; you must be running a patched rshd invoked through inetd for
  2250.      this connection method to work */
  2251.  
  2252.   if (rs != 0)
  2253.     for(local_port = IPPORT_USERRESERVED - 1;
  2254.         local_port > IPPORT_RESERVED;
  2255.         local_port--)
  2256.       {
  2257.       local_isa.sin_port = htons(local_port);
  2258.       rs = amiga_bind(s, (struct sockaddr *)&local_isa, sizeof(local_isa));
  2259.       if(rs == 0)
  2260.         break;
  2261.       }
  2262.  
  2263.   rs = amiga_connect(s, (struct sockaddr *) &remote_isa, sizeof(remote_isa));
  2264.   if(rs == -1)
  2265.     {
  2266.     fprintf(stderr, "connect: errno = %d\n", errno);
  2267.     close(s);
  2268.     exit(2);
  2269.     }
  2270.  
  2271.   /* Now supply authentication information */
  2272.  
  2273.   /* Auxiliary port number for error messages, we don't use it */
  2274.   write(s, "0\0", 2);
  2275.  
  2276.   /* Who are we */
  2277.   write(s, local_user, strlen(local_user) + 1);
  2278.  
  2279.   /* Who do we want to be */
  2280.   write(s, remote_user, strlen(remote_user) + 1);
  2281.  
  2282.   /* What do we want to run */
  2283.   write(s, command, strlen(command) + 1);
  2284.  
  2285.   /* NUL is sent back to us if information is acceptable */
  2286.   read(s, &ch, 1);
  2287.   if(ch != '\0')
  2288.     {
  2289.     errno = EPERM;
  2290.     return -1;
  2291.     }
  2292.  
  2293.   return s;
  2294. }
  2295.  
  2296. static char *cvs_server;
  2297. static char *command;
  2298.  
  2299. extern int trace;
  2300.  
  2301. void
  2302. amiga_start_server (int *tofd, int *fromfd,char *client_user, char *server_user,char *server_host, char *server_cvsroot)
  2303. {
  2304.   int fd, port;
  2305.   char *portenv;
  2306.   struct servent *sptr;
  2307.  
  2308.   if (! (cvs_server = getenv ("CVS_SERVER")))
  2309.       cvs_server = "cvs";
  2310.   command = xmalloc (strlen (cvs_server)
  2311.              + strlen (server_cvsroot)
  2312.              + 50);
  2313.   sprintf(command, "%s server", cvs_server);
  2314.  
  2315.   portenv = getenv("CVS_RCMD_PORT");
  2316.   if (portenv)
  2317.       port = atoi(portenv);
  2318.   else if ((sptr = amiga_getservbyname("shell", "tcp")) != NULL)
  2319.       port = sptr->s_port;
  2320.   else
  2321.       port = 514; /* shell/tcp */
  2322.  
  2323.   if(trace)
  2324.     {
  2325.     fprintf(stderr, "amiga_start_server(): connecting to %s:%d\n",
  2326.             server_host, port);
  2327.     fprintf(stderr, "local_user = %s, remote_user = %s, CVSROOT = %s\n",
  2328.             client_user, (server_user ? server_user : client_user),
  2329.             server_cvsroot);
  2330.     }
  2331.  
  2332.   fd = amiga_rcmd(&server_host, port,
  2333.             client_user,
  2334.             (server_user ? server_user : client_user),
  2335.             command);
  2336.  
  2337.   if (fd < 0)
  2338.      error (1, errno, "cannot start server via rcmd()");
  2339.  
  2340.   (*tofd) = fd;
  2341.   (*fromfd) = fd;
  2342.  
  2343.   free (command);
  2344. }
  2345.  
  2346. void
  2347. amiga_shutdown_server (int fd)
  2348. {
  2349.     /* FIXME: shutdown on files seems to have no bad effects */
  2350.     if (amiga_shutdown (fd, 2) < 0 && errno != ENOTSOCK)
  2351.         error (1, 0, "couldn't shutdown server connection");
  2352.     if (close (fd) < 0)
  2353.         error (1, 0, "couldn't close server connection");
  2354. }
  2355.  
  2356. /****************************************************************************/
  2357.  
  2358. void
  2359. amiga_system_initialize(int * _argc,char *** _argv)
  2360. {
  2361.     amiga_expand_wild((*_argc),(*_argv),_argc,_argv);
  2362. }
  2363.