home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Online / Samba / source / amiga_rcs / amiga.c < prev    next >
C/C++ Source or Header  |  2000-08-17  |  184KB  |  9,487 lines

  1. head    1.14;
  2. access;
  3. symbols
  4.     V1_15:1.14
  5.     V1_12:1.13
  6.     V1_11:1.12
  7.     V1_10:1.11
  8.     V1_9:1.10
  9.     V1_8:1.9
  10.     V1_7:1.8
  11.     V1_6:1.7
  12.     V1_5:1.6
  13.     V1_4:1.4
  14.     V1_3:1.3
  15.     V1_2:1.2
  16.     V1_1:1.1;
  17. locks
  18.     olsen:1.14; strict;
  19. comment    @ * @;
  20.  
  21.  
  22. 1.14
  23. date    2000.05.24.19.50.17;    author olsen;    state Exp;
  24. branches;
  25. next    1.13;
  26.  
  27. 1.13
  28. date    99.12.25.11.31.10;    author olsen;    state Exp;
  29. branches;
  30. next    1.12;
  31.  
  32. 1.12
  33. date    99.12.01.09.47.07;    author olsen;    state Exp;
  34. branches;
  35. next    1.11;
  36.  
  37. 1.11
  38. date    99.11.06.16.03.15;    author olsen;    state Exp;
  39. branches;
  40. next    1.10;
  41.  
  42. 1.10
  43. date    99.10.16.09.15.58;    author olsen;    state Exp;
  44. branches;
  45. next    1.9;
  46.  
  47. 1.9
  48. date    99.08.09.15.28.43;    author olsen;    state Exp;
  49. branches;
  50. next    1.8;
  51.  
  52. 1.8
  53. date    99.05.21.09.38.15;    author olsen;    state Exp;
  54. branches;
  55. next    1.7;
  56.  
  57. 1.7
  58. date    99.05.02.10.45.08;    author olsen;    state Exp;
  59. branches;
  60. next    1.6;
  61.  
  62. 1.6
  63. date    99.02.28.09.16.53;    author olsen;    state Exp;
  64. branches;
  65. next    1.5;
  66.  
  67. 1.5
  68. date    99.02.22.15.31.18;    author olsen;    state Exp;
  69. branches;
  70. next    1.4;
  71.  
  72. 1.4
  73. date    99.02.21.10.58.42;    author olsen;    state Exp;
  74. branches;
  75. next    1.3;
  76.  
  77. 1.3
  78. date    99.02.20.17.52.48;    author olsen;    state Exp;
  79. branches;
  80. next    1.2;
  81.  
  82. 1.2
  83. date    99.02.20.16.52.05;    author olsen;    state Exp;
  84. branches;
  85. next    1.1;
  86.  
  87. 1.1
  88. date    99.02.13.15.32.16;    author olsen;    state Exp;
  89. branches;
  90. next    ;
  91.  
  92.  
  93. desc
  94. @.
  95. @
  96.  
  97.  
  98. 1.14
  99. log
  100. @.
  101. @
  102. text
  103. @/*
  104.  * $Id: amiga.c 1.13 1999/12/25 11:31:10 olsen Exp olsen $
  105.  *
  106.  * :ts=4
  107.  *
  108.  * AmigaOS wrapper routines for Samba 2.0.0, using the AmiTCP V4 API
  109.  * and the SAS/C V6.58 compiler.
  110.  *
  111.  * Copyright (C) 1999-2000 by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>
  112.  *
  113.  * This program is free software; you can redistribute it and/or modify
  114.  * it under the terms of the GNU General Public License as published by
  115.  * the Free Software Foundation; either version 2 of the License, or
  116.  * (at your option) any later version.
  117.  *
  118.  * This program is distributed in the hope that it will be useful,
  119.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  120.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  121.  * GNU General Public License for more details.
  122.  *
  123.  * You should have received a copy of the GNU General Public License
  124.  * along with this program; if not, write to the Free Software
  125.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  126.  */
  127.  
  128. /******************************************************************************/
  129.  
  130. #include <bsdsocket/socketbasetags.h>
  131. #include <libraries/usergroup.h>
  132.  
  133. #include <intuition/intuition.h>
  134. #include <libraries/locale.h>
  135. #include <exec/execbase.h>
  136. #include <exec/memory.h>
  137. #include <dos/dosextens.h>
  138. #include <dos/dostags.h>
  139. #include <devices/timer.h>
  140. #include <utility/date.h>
  141.  
  142. #include <clib/usergroup_protos.h>
  143. #include <clib/socket_protos.h>
  144.  
  145. #include <clib/intuition_protos.h>
  146. #include <clib/utility_protos.h>
  147. #include <clib/locale_protos.h>
  148. #include <clib/timer_protos.h>
  149. #include <clib/alib_protos.h>
  150. #include <clib/exec_protos.h>
  151. #include <clib/dos_protos.h>
  152.  
  153. #include <sys/socket.h>
  154. #include <sys/ioctl.h>
  155. #include <sys/time.h>
  156. #include <sys/dir.h>
  157.  
  158. #include <net/if.h>
  159.  
  160. #include <constructor.h>
  161. #include <stdarg.h>
  162. #include <stdlib.h>
  163. #include <string.h>
  164. #include <unistd.h>
  165. #include <signal.h>
  166. #include <utime.h>
  167. #include <errno.h>
  168. #include <stdio.h>
  169. #include <fcntl.h>
  170. #include <inetd.h>
  171. #include <stat.h>
  172. #include <ios1.h>
  173. #include <dos.h>
  174.  
  175. #include <pragmas/usergroup_pragmas.h>
  176. #include <pragmas/socket_pragmas.h>
  177.  
  178. #include <pragmas/exec_sysbase_pragmas.h>
  179. #include <pragmas/intuition_pragmas.h>
  180. #include <pragmas/utility_pragmas.h>
  181. #include <pragmas/locale_pragmas.h>
  182. #include <pragmas/timer_pragmas.h>
  183. #include <pragmas/dos_pragmas.h>
  184.  
  185. /******************************************************************************/
  186.  
  187. /* This is for the "iface_struct" definition. */
  188. #include "interfaces.h"
  189.  
  190. /******************************************************************************/
  191.  
  192. /*#define DEBUG*/
  193. #include "Assert.h"
  194.  
  195. /******************************************************************************/
  196.  
  197. STATIC VOID ReportProblem(const char *fmt, ...);
  198. STATIC VOID ForbidDOSCleanup(VOID);
  199. STATIC VOID PermitDOS(VOID);
  200. STATIC VOID ForbidDOS(VOID);
  201. STATIC VOID UnblockDescriptorCleanup(VOID);
  202. STATIC BOOL IsDescriptorNonblocking(int fd);
  203. STATIC VOID BlockDescriptor(int fd);
  204. STATIC VOID UnblockDescriptor(int fd);
  205. STATIC VOID SaveDescriptorCleanup(VOID);
  206. STATIC VOID RestoreDescriptor(struct UFB *ufb);
  207. STATIC BOOL SaveDescriptor(struct UFB *ufb);
  208. STATIC VOID UnmangleName(char **namePtr, struct MangleInfo *mi);
  209. STATIC int MangleName(char ** namePtr,struct MangleInfo * mi);
  210. STATIC VOID CloseUnlinkUnlockCleanup(VOID);
  211. STATIC VOID OpenDirCleanup(VOID);
  212. STATIC int TranslateRelativePath(char **namePtr, char *replace, int maxReplaceLen);
  213. STATIC VOID MapDescriptorSets(const fd_set *input_fds, int num_input_fds, fd_set *socket_fds, int *max_socket_fd_ptr, fd_set *file_fds, int *max_file_fd_ptr);
  214. STATIC VOID RemapDescriptorSets(const fd_set *socket_fds, int max_socket_fd, const fd_set *file_fds, int max_file_fd, fd_set *output_fds, int num_output_fds);
  215. STATIC VOID ConvertFileInfoToStat(struct MsgPort *port, struct FileInfoBlock *fib, struct stat *st);
  216. STATIC BOOL do_match(STRPTR str, STRPTR regexp);
  217. STATIC VOID nstrcpy_blank(const size_t maxSize, char *to, const char *from);
  218. STATIC BOOL SetFileSocket(FILE *stream, int sockfd);
  219. STATIC VOID DaemonInit(VOID);
  220. STATIC struct tm *ConvertTime(ULONG seconds);
  221. STATIC VOID MapIoErrToErrno(VOID);
  222. STATIC int MapFileNameAmigaToUnix(const char *amiga, char *unix, int maxUnixLen);
  223. STATIC VOID FlushSTDOUT(VOID);
  224. STATIC VOID CleanupSambaSemaphore(VOID);
  225. STATIC BOOL SetupSambaSemaphore(VOID);
  226. STATIC VOID RemoveLockedRegionNode(struct UFB *ufb, LONG start, LONG stop);
  227. STATIC VOID DeleteLockedRegionNode(struct LockedRegionNode *lrn);
  228. STATIC LONG CreateLockedRegionNode(struct LockedRegionNode **resultPtr);
  229. STATIC VOID DeleteFileLockNode(struct FileLockNode *fln);
  230. STATIC LONG CreateFileLockNode(struct UFB *ufb, struct FileLockNode **resultPtr);
  231. STATIC LONG FindFileLockNodeByFileHandle(BPTR fileHandle, struct FileLockNode **resultPtr);
  232. STATIC VOID FindFileLockNodeByDrawerAndName(BPTR parentDir, STRPTR fileName, struct FileLockNode **resultPtr);
  233. STATIC VOID CleanupFileLocks(int fd);
  234. STATIC int HandleFileLocking(int cmd, struct flock *l, struct UFB *ufb);
  235. STATIC struct LockedRegionNode *FindCollidingRegion(struct FileLockNode *fln, LONG start, LONG stop, BOOL shared);
  236.  
  237. /******************************************************************************/
  238.  
  239. int amiga_sigmask(int signum);
  240. int amiga_sigblock(int sigmask);
  241. int amiga_sigsetmask(int sigmask);
  242. int amiga_unlink(char *name);
  243. int amiga_open(char *name, int mode, int prot);
  244. int amiga_chdir(char *path);
  245. DIR *amiga_opendir(char *dirName);
  246. VOID amiga_closedir(DIR *dir);
  247. struct dirent *amiga_readdir(DIR *dir);
  248. int amiga_mkdir(char *name, int mode);
  249. int amiga_rmdir(char *name);
  250. int amiga_creat(char *name, int prot);
  251. FILE *amiga_fopen(char *name, char *mode);
  252. int amiga_rename(char *old, char *new);
  253. char *amiga_getcwd(char *buf, size_t size);
  254. int amiga_ftruncate(int fd, off_t size);
  255. int amiga_accept(int sockfd, struct sockaddr *cliaddr, int *addrlen);
  256. int amiga_bind(int sockfd, struct sockaddr *name, int namelen);
  257. int amiga_close(int fd);
  258. int amiga_connect(int sockfd, struct sockaddr *name, int namelen);
  259. int amiga_getpeername(int sockfd, struct sockaddr *name, int *namelen);
  260. int amiga_getsockopt(int sockfd, int level, int optname, VOID *optval, int *optlen);
  261. int amiga_ioctl(int fd, unsigned long request, char *arg);
  262. int amiga_listen(int sockfd, int backlog);
  263. int amiga_read(int fd, VOID *data, unsigned int size);
  264. int amiga_recvfrom(int sockfd, VOID *buff, int len, int flags, struct sockaddr *from, int *fromlen);
  265. int amiga_select(int num_fds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout);
  266. int amiga_sendto(int sockfd, VOID *buff, int len, int flags, struct sockaddr *to, int tolen);
  267. int amiga_setsockopt(int sockfd, int level, int optname, VOID *optval, int optlen);
  268. int amiga_socket(int domain, int type, int protocol);
  269. int amiga_write(int fd, VOID *data, unsigned int size);
  270. int amiga_stat(char *name, struct stat *st);
  271. int amiga_lstat(char *name, struct stat *statstruct);
  272. int amiga_fstat(int fd, struct stat *st);
  273. int amiga_chmod(char *name, int mode);
  274. int amiga_dup(int fd);
  275. int amiga_dup2(int old_fd, int new_fd);
  276. int amiga_chown(char *name, uid_t uid, gid_t gid);
  277. int amiga_setegid(gid_t g);
  278. int amiga_seteuid(uid_t u);
  279. int amiga_gettimeofday(struct timeval *tv);
  280. int amiga_utime(char *name, struct utimbuf *time);
  281. VOID amiga_sleep(unsigned int seconds);
  282. char *amiga_crypt(char *key, char *salt);
  283. char *amiga_getpass(char *prompt);
  284. int amiga_setgid(gid_t id);
  285. int amiga_setgroups(int ngroups, gid_t *groups);
  286. gid_t amiga_getgid(VOID);
  287. struct group *amiga_getgrgid(gid_t gid);
  288. struct group *amiga_getgrnam(char *name);
  289. int amiga_getgroups(int ngroups, gid_t *groups);
  290. struct hostent *amiga_gethostbyaddr(char *addr, int len, int type);
  291. struct hostent *amiga_gethostbyname(char *name);
  292. struct netent *amiga_getnetbyname(char *name);
  293. int amiga_gethostname(char *hostname, int size);
  294. struct passwd *amiga_getpwnam(char *name);
  295. struct passwd *amiga_getpwuid(uid_t uid);
  296. uid_t amiga_getuid(VOID);
  297. gid_t amiga_getegid(VOID);
  298. uid_t amiga_geteuid(VOID);
  299. int amiga_initgroups(char *name, gid_t basegroup);
  300. int amiga_setuid(uid_t id);
  301. int amiga_umask(int mask);
  302. unsigned long amiga_inet_addr(char *addr);
  303. char *amiga_inet_ntoa(struct in_addr in);
  304. int amiga_getopt(int argc, char *argv[], char *opts);
  305. int amiga_system(char *cmd);
  306. int amiga_fork(VOID);
  307. VOID __tzset(VOID);
  308. time_t time(time_t *timeptr);
  309. struct tm *gmtime(const time_t *t);
  310. struct tm *localtime(const time_t *t);
  311. int amiga_strcasecmp(char *a, char *b);
  312. int amiga_strncasecmp(char *a, char *b, int len);
  313. VOID (*amiga_signal(int which,VOID (* action)(int)))(int);
  314. VOID amiga_alarm(int seconds);
  315. int amiga_waitpid(pid_t pid, int *status, int options);
  316. long amiga_setsid(VOID);
  317. int amiga_setreuid(uid_t real, uid_t eff);
  318. int amiga_setregid(gid_t real, gid_t eff);
  319. int amiga_fcntl(int fd, int cmd, unsigned long arg);
  320. int amiga_getsockname(int sockfd, struct sockaddr *name, int *namelen);
  321. int amiga_statfs(char *name, struct statfs *f);
  322. int amiga_execl(char *path, char *arg, ...);
  323. char *amiga_strerror(int error);
  324. int amiga_access(char *name, int modes);
  325. off_t amiga_lseek(int fd, off_t offset, int mode);
  326. int amiga_chroot(char *name);
  327. int amiga_kill(pid_t pid, int sig);
  328. pid_t amiga_getpid(VOID);
  329. int amiga_fgetc(FILE *in);
  330. char *amiga_fgets(char *str, int n, FILE *in);
  331. int amiga_fputs(const char *str, FILE *out);
  332. int amiga_puts(const char *str);
  333. int amiga_vfprintf(FILE *out, const char *fmt, va_list args);
  334. int amiga_fprintf(FILE *out, const char *fmt, ...);
  335. int amiga_printf(const char *fmt, ...);
  336. size_t amiga_fwrite(const void *data, size_t blockSize, size_t numBlocks, FILE *out);
  337. size_t amiga_fread(void *data, size_t blockSize, size_t numBlocks, FILE *in);
  338. int amiga_fclose(FILE *stream);
  339. int amiga_fflush(FILE *stream);
  340. int amiga_fseek(FILE *stream, long int offset, int mode);
  341. long int amiga_ftell(FILE *stream);
  342. int amiga_setvbuf(FILE *fp, char *buff, int type, size_t size);
  343. int amiga_fputc(int c,FILE *stream);
  344. VOID amiga_setbuf(FILE *stream,char *buffer);
  345.  
  346. /******************************************************************************/
  347.  
  348. VOID __regargs __chkabort(VOID);
  349. VOID _CXOVF(VOID);
  350. VOID __regargs _CXBRK(VOID);
  351.  
  352. /******************************************************************************/
  353.  
  354. /* These are in the Samba runtime library. */
  355. extern int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
  356. extern int snprintf (char *str, size_t count, const char *fmt, ...);
  357.  
  358. /******************************************************************************/
  359.  
  360. #define ZERO    ((BPTR)0L)
  361. #define ERROR    (-1)
  362. #define OK        (0)
  363. #define SAME    (0)
  364. #define NO        !
  365. #define NOT        !
  366. #define DONT    !
  367. #define CANNOT    !
  368. #define BUSY    (NULL)
  369. #define NO_FLAG    (0)
  370.  
  371. /******************************************************************************/
  372.  
  373. #define FLAG_IS_SET(v,f)    (((v) & (f)) == (f))
  374. #define FLAG_IS_CLEAR(v,f)    (((v) & (f)) == 0)
  375.  
  376. #define SET_FLAG(v,f)        (v |=  (f))
  377. #define CLEAR_FLAG(v,f)        (v &= ~(f))
  378.  
  379. /******************************************************************************/
  380.  
  381. #define STRING_IS_EMPTY(s)    (s[0] == '\0')
  382. #define NUM_ENTRIES(t)        (sizeof(t) / sizeof(t[0]))
  383.  
  384. /******************************************************************************/
  385.  
  386. #define FIB_IS_FILE(fib)    ((fib)->fib_DirEntryType < 0)
  387. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType >= 0 && (fib)->fib_DirEntryType != ST_SOFTLINK)
  388.  
  389. /******************************************************************************/
  390.  
  391. #define UFB_IS_SOCKET        0x0800
  392. #define UFB_IS_NON_BLOCKING    0x1000
  393. #define UFB_UNLINK            0x2000
  394. #define UFB_LOCKED            0x4000
  395.  
  396. #define UNIX_TIME_OFFSET    252482400
  397.  
  398. #define MAX_BSTR_LEN        256
  399. #define MAX_FILENAME_LEN    512
  400. #define MAX_FFS_NAME_LEN    30
  401.  
  402. /******************************************************************************/
  403.  
  404. long __oslibversion = 37;
  405.  
  406. /******************************************************************************/
  407.  
  408. extern struct Library * SysBase;
  409. extern struct Library * DOSBase;
  410. extern struct Library * UtilityBase;
  411.  
  412. /******************************************************************************/
  413.  
  414. STATIC struct Device * TimerBase;
  415. STATIC struct MsgPort * TimerPort;
  416. STATIC struct timerequest * TimerRequest;
  417. STATIC LONG MinutesWest;
  418.  
  419. /******************************************************************************/
  420.  
  421. STATIC struct Library * SocketBase;
  422. STATIC struct Library * UserGroupBase;
  423.  
  424. /******************************************************************************/
  425.  
  426. #if defined(_M68020) && defined(_M68881)
  427. #define MACHINE_TYPE "['020+FPU]"
  428. #elif defined(_M68020)
  429. #define MACHINE_TYPE "['020]"
  430. #else
  431. #define MACHINE_TYPE "[68k]"
  432. #endif
  433.  
  434. /******************************************************************************/
  435.  
  436. #include "Amiga_Samba_rev.h"
  437. char * VersionTag = VERSTAG " " MACHINE_TYPE " Samba version 2.0.0 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  438.  
  439. /******************************************************************************/
  440.  
  441. /* This is for backwards compatibility with Kickstart 2.04 and
  442.  * avoids a deadlock when trying to get a shared lock on
  443.  * a semaphore already held in exclusive mode by the same Task.
  444.  */
  445. STATIC VOID
  446. SafeObtainSemaphoreShared(struct SignalSemaphore * semaphore)
  447. {
  448.     /* Do it right with Kickstart 3.x. */
  449.     if(SysBase->lib_Version >= 39)
  450.     {
  451.         ObtainSemaphoreShared(semaphore);
  452.     }
  453.     else
  454.     {
  455.         /* Try to get the shared semaphore */
  456.         if(CANNOT AttemptSemaphoreShared(semaphore))
  457.         {
  458.             /* Check if we can get the exclusive version */
  459.             if(CANNOT AttemptSemaphore(semaphore))
  460.             {
  461.                 /* Oh well, wait for the shared lock */
  462.                 ObtainSemaphoreShared(semaphore);
  463.             }
  464.         }
  465.     }
  466. }
  467.  
  468. /******************************************************************************/
  469.  
  470. STATIC BOOL AllowBreak = TRUE;
  471.  
  472. STATIC BOOL
  473. CheckAbort(VOID)
  474. {
  475.     BOOL result;
  476.  
  477.     result = (BOOL)(AllowBreak && FLAG_IS_SET(SetSignal(0,SIGBREAKF_CTRL_C),SIGBREAKF_CTRL_C));
  478.  
  479.     return(result);
  480. }
  481.  
  482. VOID __regargs
  483. __chkabort(VOID)
  484. {
  485.     if(CheckAbort())
  486.         raise(SIGINT);
  487. }
  488.  
  489. int
  490. amiga_sigmask(int signum)
  491. {
  492.     int result = 0;
  493.  
  494.     ENTER();
  495.  
  496.     SHOWVALUE(signum);
  497.  
  498.     if(signum == SIGTERM || signum == SIGINT)
  499.         result = (1<<SIGINT);
  500.  
  501.     RETURN(result);
  502.     return(result);
  503. }
  504.  
  505. int
  506. amiga_sigblock(int sigmask)
  507. {
  508.     BOOL oldAllowBreak = AllowBreak;
  509.     int result = 0;
  510.  
  511.     ENTER();
  512.  
  513.     SHOWVALUE(sigmask);
  514.  
  515.     if(DONT AllowBreak)
  516.         result = (1<<SIGINT);
  517.  
  518.     if(FLAG_IS_SET(sigmask,(1<<SIGINT)))
  519.     {
  520.         AllowBreak = FALSE;
  521.  
  522.         if(oldAllowBreak != AllowBreak)
  523.         {
  524.             SocketBaseTags(
  525.                 SBTM_SETVAL(SBTC_BREAKMASK),NO_FLAG,
  526.             TAG_END);
  527.         }
  528.     }
  529.  
  530.     RETURN(result);
  531.     return(result);
  532. }
  533.  
  534. int
  535. amiga_sigsetmask(int sigmask)
  536. {
  537.     BOOL oldAllowBreak = AllowBreak;
  538.     int result = 0;
  539.  
  540.     ENTER();
  541.  
  542.     SHOWVALUE(sigmask);
  543.  
  544.     AllowBreak = FLAG_IS_CLEAR(sigmask,(1<<SIGINT));
  545.     if(oldAllowBreak != AllowBreak)
  546.     {
  547.         ULONG mask;
  548.  
  549.         if(AllowBreak)
  550.             mask = SIGBREAKF_CTRL_C;
  551.         else
  552.             mask = NO_FLAG;
  553.  
  554.         SocketBaseTags(
  555.             SBTM_SETVAL(SBTC_BREAKMASK),mask,
  556.         TAG_END);
  557.     }
  558.  
  559.     RETURN(result);
  560.     return(result);
  561. }
  562.  
  563. /******************************************************************************/
  564.  
  565. STATIC VOID
  566. ReportProblem(const char *fmt,...)
  567. {
  568.     extern const STRPTR _ProgramName;
  569.     BOOL useRequester = TRUE;
  570.     va_list varArgs;
  571.  
  572.     ASSERT(fmt != NULL);
  573.  
  574.     va_start(varArgs,fmt);
  575.  
  576.     /* Launched from Workbench? */
  577.     if(WBenchMsg == NULL)
  578.     {
  579.         if(DOSBase->lib_Version >= 37)
  580.         {
  581.             BPTR stream;
  582.  
  583.             /* Make a copy of the current terminal
  584.              * output stream. This avoids sending
  585.              * an error message through a redirected
  586.              * standard output stream, the output
  587.              * will go straight to the terminal.
  588.              */
  589.             stream = Open("CONSOLE:",MODE_NEWFILE);
  590.             if(stream != ZERO)
  591.             {
  592.                 struct FileHandle * fh = BADDR(stream);
  593.  
  594.                 /* Check if the output was redirected
  595.                  * to "NIL:"; if not, print the error
  596.                  * error message.
  597.                  */
  598.                 if(fh->fh_Type != NULL)
  599.                 {
  600.                     FPrintf(stream,"%s: ",_ProgramName);
  601.                     VFPrintf(stream,(STRPTR)fmt,(APTR)varArgs);
  602.                     FPrintf(stream,"\a\n");
  603.  
  604.                     useRequester = FALSE;
  605.                 }
  606.  
  607.                 Close(stream);
  608.             }
  609.         }
  610.     }
  611.  
  612.     /* Oh well, don't use the Shell for output. Put up a
  613.      * requester.
  614.      */
  615.     if(useRequester)
  616.     {
  617.         struct Library * IntuitionBase;
  618.  
  619.         IntuitionBase = OpenLibrary("intuition.library",37);
  620.         if(IntuitionBase != NULL)
  621.         {
  622.             struct Window * reqWindow;
  623.             struct EasyStruct es;
  624.             char title[100];
  625.  
  626.             snprintf(title,sizeof(title)-1,"Amiga Samba Error (%s)",FilePart(_ProgramName));
  627.             title[sizeof(title)-1] = '\0';
  628.  
  629.             memset(&es,0,sizeof(es));
  630.  
  631.             es.es_StructSize    = sizeof(es);
  632.             es.es_Title            = (STRPTR)title;
  633.             es.es_TextFormat    = (STRPTR)fmt;
  634.             es.es_GadgetFormat    = "Ok";
  635.  
  636.             reqWindow = BuildEasyRequestArgs(NULL,&es,0,(APTR)varArgs);
  637.             if(reqWindow != NULL)
  638.             {
  639.                 struct timerequest * timeRequest = NULL;
  640.                 struct MsgPort * timePort;
  641.                 BOOL timerOpen = FALSE;
  642.                 ULONG windowSignal;
  643.                 ULONG timerSignal;
  644.                 ULONG signals;
  645.                 BOOL done;
  646.  
  647.                 timePort = CreateMsgPort();
  648.                 if(timePort != NULL)
  649.                 {
  650.                     timeRequest = CreateIORequest(timePort,sizeof(*timeRequest));
  651.                     if(timeRequest != NULL)
  652.                     {
  653.                         if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)timeRequest,0) == OK)
  654.                             timerOpen = TRUE;
  655.                     }
  656.                 }
  657.  
  658.                 windowSignal = (1UL << reqWindow->UserPort->mp_SigBit);
  659.  
  660.                 if(timerOpen)
  661.                 {
  662.                     timerSignal = (1UL << timePort->mp_SigBit);
  663.  
  664.                     timeRequest->tr_node.io_Command    = TR_ADDREQUEST;
  665.                     timeRequest->tr_time.tv_secs    = 30;
  666.                     timeRequest->tr_time.tv_micro    = 0;
  667.  
  668.                     SendIO((struct IORequest *)timeRequest);
  669.                 }
  670.                 else
  671.                 {
  672.                     timerSignal = 0;
  673.                 }
  674.  
  675.                 DisplayBeep(reqWindow->WScreen);
  676.  
  677.                 done = FALSE;
  678.                 do
  679.                 {
  680.                     signals = Wait(windowSignal | timerSignal);
  681.  
  682.                     if(FLAG_IS_SET(signals,windowSignal))
  683.                     {
  684.                         if(SysReqHandler(reqWindow,NULL,FALSE) >= 0)
  685.                             done = TRUE;
  686.                     }
  687.  
  688.                     if(FLAG_IS_SET(signals,timerSignal))
  689.                     {
  690.                         done = TRUE;
  691.                     }
  692.                 }
  693.                 while(NOT done);
  694.  
  695.                 if(timerOpen)
  696.                 {
  697.                     if(CheckIO((struct IORequest *)timeRequest) == BUSY)
  698.                         AbortIO((struct IORequest *)timeRequest);
  699.  
  700.                     WaitIO((struct IORequest *)timeRequest);
  701.  
  702.                     CloseDevice((struct IORequest *)timeRequest);
  703.                 }
  704.  
  705.                 DeleteIORequest((struct IORequest *)timeRequest);
  706.                 DeleteMsgPort(timePort);
  707.  
  708.                 FreeSysRequest(reqWindow);
  709.             }
  710.  
  711.             CloseLibrary(IntuitionBase);
  712.         }
  713.     }
  714.  
  715.     va_end(varArgs);
  716. }
  717.  
  718. /******************************************************************************/
  719.  
  720. STATIC APTR OldWindowPtr;
  721. STATIC LONG ForbidCount;
  722.  
  723. STATIC VOID
  724. ForbidDOSCleanup(VOID)
  725. {
  726.     if(ForbidCount > 0)
  727.     {
  728.         struct Process * pr = (struct Process *)FindTask(NULL);
  729.  
  730.         pr->pr_WindowPtr = OldWindowPtr;
  731.  
  732.         ForbidCount = 0;
  733.     }
  734. }
  735.  
  736. STATIC VOID
  737. PermitDOS(VOID)
  738. {
  739.     ASSERT(ForbidCount > 0);
  740.  
  741.     if(--ForbidCount == 0)
  742.     {
  743.         struct Process * pr = (struct Process *)FindTask(NULL);
  744.  
  745.         pr->pr_WindowPtr = OldWindowPtr;
  746.     }
  747. }
  748.  
  749. STATIC VOID
  750. ForbidDOS(VOID)
  751. {
  752.     if(ForbidCount++ == 0)
  753.     {
  754.         struct Process * pr = (struct Process *)FindTask(NULL);
  755.  
  756.         OldWindowPtr = pr->pr_WindowPtr;
  757.         pr->pr_WindowPtr = (APTR)-1;
  758.     }
  759. }
  760.  
  761. /******************************************************************************/
  762.  
  763. #define SINGLE_CHARACTER_MODE    (1)
  764. #define BUFFERED_MODE            (0)
  765.  
  766. STATIC int MaxNonblockingDescriptor = -1;
  767.  
  768. STATIC VOID
  769. UnblockDescriptorCleanup(VOID)
  770. {
  771.     struct UFB * ufb;
  772.     int fd;
  773.  
  774.     /* We look for descriptors we switched into
  775.      * non-blocking mode and reset them back
  776.      * to blocking mode.
  777.      */
  778.     for(fd = 0 ; fd <= MaxNonblockingDescriptor ; fd++)
  779.     {
  780.         ufb = chkufb(fd);
  781.         if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  782.         {
  783.             SetMode((BPTR)ufb->ufbfh,BUFFERED_MODE);
  784.  
  785.             CLEAR_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  786.         }
  787.     }
  788. }
  789.  
  790. STATIC BOOL
  791. IsDescriptorNonblocking(int fd)
  792. {
  793.     struct UFB * ufb;
  794.     BOOL result = FALSE;
  795.  
  796.     /* Verify if a descriptor was switched into non-blocking mode. */
  797.     ufb = chkufb(fd);
  798.     if(ufb != NULL)
  799.         result = FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  800.  
  801.     return(result);
  802. }
  803.  
  804. STATIC VOID
  805. BlockDescriptor(int fd)
  806. {
  807.     struct UFB * ufb;
  808.  
  809.     /* This resets a file descriptor to blocking mode,
  810.      * once it has been set to blocking mode.
  811.      */
  812.     ufb = chkufb(fd);
  813.     if(ufb != NULL)
  814.     {
  815.         if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  816.         {
  817.             SetMode((BPTR)ufb->ufbfh,BUFFERED_MODE);
  818.  
  819.             CLEAR_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  820.         }
  821.     }
  822. }
  823.  
  824. STATIC VOID
  825. UnblockDescriptor(int fd)
  826. {
  827.     struct UFB * ufb;
  828.  
  829.     ufb = chkufb(fd);
  830.     if(ufb != NULL)
  831.     {
  832.         /* Make sure we got a file and it's not already
  833.          * in non-blocking mode.
  834.          */
  835.         if(FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET) && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_NON_BLOCKING))
  836.         {
  837.             /* Try to flip it into single character mode,
  838.              * which we treat as "non-blocking" mode.
  839.              */
  840.             if(SetMode((BPTR)ufb->ufbfh,SINGLE_CHARACTER_MODE))
  841.             {
  842.                 SET_FLAG(ufb->ufbflg,UFB_IS_NON_BLOCKING);
  843.  
  844.                 /* Remember which one we switched. */
  845.                 if(MaxNonblockingDescriptor < fd)
  846.                     MaxNonblockingDescriptor = fd;
  847.             }
  848.         }
  849.     }
  850. }
  851.  
  852. /******************************************************************************/
  853.  
  854. struct SavedDescriptorNode
  855. {
  856.     struct MinNode    sdn_MinNode;
  857.     struct UFB *    sdn_UFB;
  858.     BPTR            sdn_FileHandle;
  859. };
  860.  
  861. STATIC BOOL DescriptorListInitialized = FALSE;
  862. STATIC struct List DescriptorList;
  863.  
  864. STATIC VOID
  865. SaveDescriptorCleanup(VOID)
  866. {
  867.     /* This routine restores all file descriptors
  868.      * we used to map to sockets to use proper file
  869.      * handles.
  870.      */
  871.     if(DescriptorListInitialized)
  872.     {
  873.         struct SavedDescriptorNode * sdn;
  874.  
  875.         for(sdn = (struct SavedDescriptorNode *)DescriptorList.lh_Head ;
  876.             sdn->sdn_MinNode.mln_Succ != NULL ;
  877.             sdn = (struct SavedDescriptorNode *)sdn->sdn_MinNode.mln_Succ)
  878.         {
  879.             /* Make sure that if this file is bound to
  880.              * a socket, the socket is closed.
  881.              */
  882.             if(FLAG_IS_SET(sdn->sdn_UFB->ufbflg,UFB_IS_SOCKET))
  883.             {
  884.                 CloseSocket(sdn->sdn_UFB->ufbfh);
  885.  
  886.                 CLEAR_FLAG(sdn->sdn_UFB->ufbflg,UFB_IS_SOCKET);
  887.             }
  888.  
  889.             sdn->sdn_UFB->ufbfh = sdn->sdn_FileHandle;
  890.         }
  891.     }
  892. }
  893.  
  894. STATIC VOID
  895. RestoreDescriptor(struct UFB * ufb)
  896. {
  897.     ASSERT(ufb != NULL);
  898.  
  899.     /* This routine restores one particular file descriptor
  900.      * which was used as a socket to refer to a proper
  901.      * file handle.
  902.      */
  903.     if(DescriptorListInitialized)
  904.     {
  905.         struct SavedDescriptorNode * sdn;
  906.  
  907.         for(sdn = (struct SavedDescriptorNode *)DescriptorList.lh_Head ;
  908.             sdn->sdn_MinNode.mln_Succ != NULL ;
  909.             sdn = (struct SavedDescriptorNode *)sdn->sdn_MinNode.mln_Succ)
  910.         {
  911.             if(sdn->sdn_UFB == ufb)
  912.             {
  913.                 sdn->sdn_UFB->ufbfh = sdn->sdn_FileHandle;
  914.  
  915.                 Remove((struct Node *)sdn);
  916.                 free(sdn);
  917.  
  918.                 break;
  919.             }
  920.         }
  921.     }
  922. }
  923.  
  924. STATIC BOOL
  925. SaveDescriptor(struct UFB * ufb)
  926. {
  927.     struct SavedDescriptorNode * sdn;
  928.     BOOL result = FALSE;
  929.  
  930.     ASSERT(ufb != NULL);
  931.  
  932.     /* Set up the descriptor list, unless it's already
  933.      * initialized.
  934.      */
  935.     if(NOT DescriptorListInitialized)
  936.     {
  937.         NewList(&DescriptorList);
  938.         DescriptorListInitialized = TRUE;
  939.     }
  940.  
  941.     sdn = malloc(sizeof(*sdn));
  942.     if(sdn != NULL)
  943.     {
  944.         memset(sdn,0,sizeof(*sdn));
  945.  
  946.         /* Remember the file buffer and the file
  947.          * handle attached to the descriptor.
  948.          */
  949.         sdn->sdn_UFB        = ufb;
  950.         sdn->sdn_FileHandle    = ufb->ufbfh;
  951.  
  952.         AddHead(&DescriptorList,(struct Node *)sdn);
  953.  
  954.         result = TRUE;
  955.     }
  956.  
  957.     return(result);
  958. }
  959.  
  960. /******************************************************************************/
  961.  
  962. STATIC BOOL InitialCurrentDirInitialized = FALSE;
  963. STATIC BPTR InitialCurrentDir;
  964. STATIC BPTR ChangedCurrentDir;
  965.  
  966. CBMLIB_DESTRUCTOR(CloseLibsAndDevs)
  967. {
  968.     ENTER();
  969.  
  970.     /* Return to the directory we were in
  971.      * when we started.
  972.      */
  973.     if(InitialCurrentDirInitialized)
  974.     {
  975.         CurrentDir(InitialCurrentDir);
  976.         InitialCurrentDirInitialized = FALSE;
  977.     }
  978.  
  979.     /* If the current directory was changed, unlock it. */
  980.     if(ChangedCurrentDir != ZERO)
  981.     {
  982.         UnLock(ChangedCurrentDir);
  983.         ChangedCurrentDir = ZERO;
  984.     }
  985.  
  986.     CleanupSambaSemaphore();
  987.  
  988.     if(TimerRequest != NULL)
  989.     {
  990.         if(TimerRequest->tr_node.io_Device != NULL)
  991.             CloseDevice((struct IORequest *)TimerRequest);
  992.  
  993.         DeleteIORequest((struct IORequest *)TimerRequest);
  994.         TimerRequest = NULL;
  995.     }
  996.  
  997.     if(TimerPort != NULL)
  998.     {
  999.         DeleteMsgPort(TimerPort);
  1000.         TimerPort = NULL;
  1001.     }
  1002.  
  1003.     TimerBase = NULL;
  1004.  
  1005.     if(SocketBase != NULL)
  1006.     {
  1007.         CloseLibrary(SocketBase);
  1008.         SocketBase = NULL;
  1009.     }
  1010.  
  1011.     if(UserGroupBase != NULL)
  1012.     {
  1013.         CloseLibrary(UserGroupBase);
  1014.         UserGroupBase = NULL;
  1015.     }
  1016.  
  1017.     LEAVE();
  1018. }
  1019.  
  1020. CBMLIB_CONSTRUCTOR(OpenLibsAndDevs)
  1021. {
  1022.     extern STRPTR _ProgramName;
  1023.     BOOL sambaSemaphoreCreated;
  1024.     struct LocaleBase * LocaleBase;
  1025.     char *timerError = "";
  1026.     BPTR sambaLock;
  1027.     int result = ERROR;
  1028.  
  1029.     SETPROGRAMNAME(_ProgramName);
  1030.     SETDEBUGLEVEL(0);
  1031.  
  1032.     ENTER();
  1033.  
  1034.     SocketBase = OpenLibrary("bsdsocket.library",4);
  1035.     UserGroupBase = OpenLibrary("usergroup.library",1);
  1036.  
  1037.     if(SysBase->lib_Version >= 37)
  1038.     {
  1039.         TimerPort = CreateMsgPort();
  1040.         if(TimerPort != NULL)
  1041.         {
  1042.             TimerRequest = (struct timerequest *)CreateIORequest(TimerPort,sizeof(*TimerRequest));
  1043.             if(TimerRequest != NULL)
  1044.             {
  1045.                 if(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerRequest,NULL) == OK)
  1046.                     TimerBase = TimerRequest->tr_node.io_Device;
  1047.                 else
  1048.                     timerError = "opening \"timer.device\"";
  1049.             }
  1050.             else
  1051.             {
  1052.                 timerError = "creating timer I/O request";
  1053.             }
  1054.         }
  1055.         else
  1056.         {
  1057.             timerError = "creating timer message port";
  1058.         }
  1059.     }
  1060.  
  1061.     /* Try to determine this machine's time zone. */
  1062.     LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",38);
  1063.     if(LocaleBase != NULL)
  1064.     {
  1065.         struct Locale * locale;
  1066.  
  1067.         locale = OpenLocale(NULL);
  1068.         MinutesWest = locale->loc_GMTOffset;
  1069.         CloseLocale(locale);
  1070.  
  1071.         CloseLibrary((struct Library *)LocaleBase);
  1072.     }
  1073.  
  1074.     ForbidDOS();
  1075.  
  1076.     /* Try to get a lock on the "Samba:" directory,
  1077.      * just to make sure the assignment is in place.
  1078.      */
  1079.     sambaLock = Lock("Samba:",SHARED_LOCK);
  1080.     if(sambaLock != ZERO)
  1081.         UnLock(sambaLock);
  1082.  
  1083.     PermitDOS();
  1084.  
  1085.     /* Initialize the global process ID database. */
  1086.     sambaSemaphoreCreated = SetupSambaSemaphore();
  1087.  
  1088.     if(SocketBase != NULL && UserGroupBase != NULL && TimerBase != NULL &&
  1089.        sambaLock != ZERO && sambaSemaphoreCreated)
  1090.     {
  1091.         STATIC long h_errno = 0;
  1092.         struct timeval now;
  1093.         int error;
  1094.  
  1095.         error = SocketBaseTags(
  1096.             SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))),    &errno,
  1097.             SBTM_SETVAL(SBTC_HERRNOLONGPTR),            &h_errno,
  1098.             SBTM_SETVAL(SBTC_LOGTAGPTR),                _ProgramName,
  1099.             SBTM_SETVAL(SBTC_BREAKMASK),                SIGBREAKF_CTRL_C,
  1100.         TAG_END);
  1101.         if(error != OK)
  1102.         {
  1103.             ReportProblem("Error initializing socket data (error=%ld).",error);
  1104.             goto out;
  1105.         }
  1106.  
  1107.         error = ug_SetupContextTags(_ProgramName,
  1108.             UGT_ERRNOPTR(sizeof(errno)),&errno,
  1109.         TAG_END);
  1110.         if(error != OK)
  1111.         {
  1112.             ReportProblem("Error initializing user group data (error=%ld).",error);
  1113.             goto out;
  1114.         }
  1115.  
  1116.         /* Use a new random number seed. */
  1117.         GetSysTime((APTR)&now);
  1118.         srand(now.tv_secs);
  1119.     }
  1120.     else
  1121.     {
  1122.         if(SocketBase == NULL)
  1123.             ReportProblem("Error opening \"bsdsocket.library\" V4.");
  1124.         else if (UserGroupBase == NULL)
  1125.             ReportProblem("Error opening \"usergroup.library\" V1.");
  1126.         else if (TimerBase == NULL)
  1127.             ReportProblem("Error %s.",timerError);
  1128.         else if (sambaLock == ZERO)
  1129.             ReportProblem("Error finding \"Samba:\" assignment.");
  1130.         else if (NOT sambaSemaphoreCreated)
  1131.             ReportProblem("Error creating Samba semaphore.");
  1132.  
  1133.         goto out;
  1134.     }
  1135.  
  1136.     /* Initialize the current time zone variable. */
  1137.     __tzset();
  1138.  
  1139.     result = OK;
  1140.  
  1141. out:
  1142.  
  1143.     RETURN(result);
  1144.     return(result);
  1145. }
  1146.  
  1147. /******************************************************************************/
  1148.  
  1149. DESTRUCTOR_P(SocketExit,501)
  1150. {
  1151.     ENTER();
  1152.  
  1153.     SaveDescriptorCleanup();
  1154.     UnblockDescriptorCleanup();
  1155.     CloseUnlinkUnlockCleanup();
  1156.     ForbidDOSCleanup();
  1157.  
  1158.     LEAVE();
  1159. }
  1160.  
  1161. /******************************************************************************/
  1162.  
  1163. CONSTRUCTOR_P(DaemonInit,501)
  1164. {
  1165.     ENTER();
  1166.  
  1167.     DaemonInit();
  1168.  
  1169.     RETURN(0);
  1170.     return(0);
  1171. }
  1172.  
  1173. /******************************************************************************/
  1174.  
  1175. struct MangleInfo
  1176. {
  1177.     char    mi_Substitute[MAX_FILENAME_LEN];
  1178.     char *    mi_OldName;
  1179. };
  1180.  
  1181. STATIC VOID
  1182. UnmangleName(char ** namePtr,struct MangleInfo * mi)
  1183. {
  1184.     /* Reset the name pointer to its previous position. */
  1185.     (*namePtr) = mi->mi_OldName;
  1186. }
  1187.  
  1188. STATIC int
  1189. MangleName(char ** namePtr,struct MangleInfo * mi)
  1190. {
  1191.     char * name = (*namePtr);
  1192.     int result = ERROR;
  1193.  
  1194.     ENTER();
  1195.  
  1196.     if(TranslateRelativePath(&name,mi->mi_Substitute,sizeof(mi->mi_Substitute)) == OK)
  1197.     {
  1198.         char * replace = mi->mi_Substitute;
  1199.         int len,i;
  1200.  
  1201.         len = strlen(name);
  1202.  
  1203.         /* If there is one, strip the trailing slash. */
  1204.         if(len > 1 && name[len-1] == '/')
  1205.         {
  1206.             if(name != replace)
  1207.             {
  1208.                 strcpy(replace,name);
  1209.                 name = replace;
  1210.             }
  1211.  
  1212.             name[--len] = '\0';
  1213.         }
  1214.  
  1215.         if(strcmp(name,".") == SAME)
  1216.         {
  1217.             /* Convert to current directory. */
  1218.             name = "";
  1219.         }
  1220.         else if (strcmp(name,"..") == SAME)
  1221.         {
  1222.             /* Convert to parent directory. */
  1223.             name = "/";
  1224.         }
  1225.         else if (strncmp(name,"./",2) == SAME)
  1226.         {
  1227.             /* Retain just the name. */
  1228.             name += 2;
  1229.         }
  1230.         else if (strncmp(name,"../",3) == SAME)
  1231.         {
  1232.             /* Convert to parent directory. */
  1233.             name += 2;
  1234.         }
  1235.         else if (strncmp(name,"/",1) == SAME)
  1236.         {
  1237.             /* Ok, so this is an absolute path. We first
  1238.              * check for a few special cases, the first
  1239.              * being a reference to "/tmp".
  1240.              */
  1241.             if(Strnicmp(name,"/tmp",4) == SAME && (name[4] == '/' || name[4] == '\0'))
  1242.             {
  1243.                 if(name[4] == '/')
  1244.                 {
  1245.                     /* Convert "/tmp/foo" to "T:foo". */
  1246.                     strcpy(replace,"T:");
  1247.                     memmove(&replace[2],&name[5],strlen(&name[5])+1);
  1248.                 }
  1249.                 else
  1250.                 {
  1251.                     /* Convert "/tmp" to "T:". */
  1252.                     strcpy(replace,"T:");
  1253.                 }
  1254.  
  1255.                 name = replace;
  1256.             }
  1257.             else if(Strnicmp(name,"/dev/",5) == SAME)
  1258.             {
  1259.                 /* Except for "/dev/null" all references to
  1260.                  * files in "/dev" are redirected to nonexistant
  1261.                  * files. Note that this relies upon the fact
  1262.                  * that "NIL:" is not a true device.
  1263.                  */
  1264.                 if(Stricmp(name,"/dev/null") == SAME)
  1265.                     name = "NIL:";
  1266.                 else
  1267.                     name = "NIL:this_file_never_opens";
  1268.             }
  1269.             else
  1270.             {
  1271.                 int i,rest = 0,len = 0;
  1272.  
  1273.                 /* Find out how long the first component
  1274.                  * of the absolute path is.
  1275.                  */
  1276.                 for(i = 1 ; i <= strlen(name) ; i++)
  1277.                 {
  1278.                     if(name[i] == '/' || name[i] == '\0')
  1279.                     {
  1280.                         len = i-1;
  1281.  
  1282.                         /* Is there anything following
  1283.                          * the path name?
  1284.                          */
  1285.                         if(name[i] == '/')
  1286.                             rest = i+1;
  1287.  
  1288.                         break;
  1289.                     }
  1290.                 }
  1291.  
  1292.                 /* Copy the first component and
  1293.                  * attach a colon. "/foo" becomes
  1294.                  * "foo:" (without the trailing NUL
  1295.                  * byte, this will get attached
  1296.                  * later).
  1297.                  */
  1298.                 memmove(replace,&name[1],len);
  1299.                 replace[len++] = ':';
  1300.  
  1301.                 /* Now add the finishing touches. "/foo/bar" finally
  1302.                  * becomes "foo:bar" and "/foo" becomes "foo:" with the
  1303.                  * trailing NUL byte attached.
  1304.                  */
  1305.                 if(rest > 0)
  1306.                     memmove(&replace[len],&name[rest],strlen(&name[rest])+1);
  1307.                 else
  1308.                     replace[len] = '\0';
  1309.  
  1310.                 name = replace;
  1311.             }
  1312.         }
  1313.  
  1314.         /* Convert any "./" or "../" embedded in the name
  1315.          * if necessary.
  1316.          */
  1317.         for(i = 0 ; i < strlen(name) ; i++)
  1318.         {
  1319.             if(strncmp(&name[i],"./",2) == SAME ||
  1320.                strncmp(&name[i],"../",3) == SAME)
  1321.             {
  1322.                 char * from    = name;
  1323.                 char * to    = replace;
  1324.  
  1325.                 name = replace;
  1326.  
  1327.                 while((*from) != '\0')
  1328.                 {
  1329.                     if((*from) == '.')
  1330.                     {
  1331.                         if(from[1] == '/' || from[1] == '\0')
  1332.                         {
  1333.                             /* "."  -> "" (done)
  1334.                              * "./" -> "" (continue)
  1335.                              */
  1336.                             if(from[1] == '\0')
  1337.                                 break;
  1338.                             else
  1339.                                 from += 2;
  1340.                         }
  1341.                         else if (from[1] == '.' && (from[2] == '/' || from[2] == '\0'))
  1342.                         {
  1343.                             /* ".."  -> "/" (done)
  1344.                              * "../" -> "/" (continue)
  1345.                              */
  1346.                             (*to++) = '/';
  1347.  
  1348.                             if(from[2] == '\0')
  1349.                                 break;
  1350.                             else
  1351.                                 from += 3;
  1352.                         }
  1353.                         else
  1354.                         {
  1355.                             (*to++) = (*from++);
  1356.                         }
  1357.                     }
  1358.                     else
  1359.                     {
  1360.                         (*to++) = (*from++);
  1361.                     }
  1362.                 }
  1363.  
  1364.                 (*to) = '\0';
  1365.  
  1366.                 break;
  1367.             }
  1368.         }
  1369.  
  1370.         /* Reduce any "//" embedded in the name if
  1371.          * necessary.
  1372.          */
  1373.         for(i = 0 ; i < strlen(name)-1 ; i++)
  1374.         {
  1375.             if(name[i] == '/' && name[i+1] == '/')
  1376.             {
  1377.                 int position,len;
  1378.  
  1379.                 if(name != replace)
  1380.                 {
  1381.                     strcpy(replace,name);
  1382.                     name = replace;
  1383.                 }
  1384.  
  1385.                 len = strlen(name);
  1386.  
  1387.                 position = len - 1;
  1388.                 while(position > 1 && name[position] != ':')
  1389.                 {
  1390.                     /* "foo/bar//baz" -> "foo/baz" */
  1391.                     if(name[position] == '/' && name[position-1] == '/')
  1392.                     {
  1393.                         int componentLen;
  1394.  
  1395.                         /* Move in front of the name component preceding the "//". */
  1396.                         componentLen = 0;
  1397.                         for(i = position - 2 ; i > 0 && name[i] != ':' && name[i] != '/' ; i--)
  1398.                             componentLen++;
  1399.  
  1400.                         if(componentLen > 0)
  1401.                         {
  1402.                             memmove(&name[position - (componentLen + 1)],&name[position + 1],len - (position + 1));
  1403.  
  1404.                             len -= componentLen + 2;
  1405.                             name[len] = '\0';
  1406.  
  1407.                             position -= componentLen + 1;
  1408.                         }
  1409.                     }
  1410.  
  1411.                     position--;
  1412.                 }
  1413.  
  1414.                 break;
  1415.             }
  1416.         }
  1417.  
  1418.         D(("original name |%s|",(*namePtr)));
  1419.         D((" mangled name |%s|",name));
  1420.  
  1421.         /* Look for extra colon characters
  1422.          * embedded in the name (as in "foo:bar:baz"
  1423.          * or "foo/bar:baz") which really don't
  1424.          * belong here.
  1425.          */
  1426.         len = strlen(name);
  1427.         for(i = 0 ; i < len ; i++)
  1428.         {
  1429.             if(name[i] == ':' || name[i] == '/')
  1430.             {
  1431.                 int j;
  1432.  
  1433.                 for(j = i+1 ; j < len ; j++)
  1434.                 {
  1435.                     if(name[j] == ':')
  1436.                     {
  1437.                         errno = EINVAL; /* invalid name */
  1438.                         goto out;
  1439.                     }
  1440.                 }
  1441.  
  1442.                 break;
  1443.             }
  1444.         }
  1445.  
  1446.         /* Now check if the file name is longer than the
  1447.          * maximum supported by the ROM file system. This
  1448.          * is to avoid name space clashes.
  1449.          */
  1450.         if(strlen(FilePart((STRPTR)name)) > MAX_FFS_NAME_LEN)
  1451.         {
  1452.             LONG error = OK;
  1453.             BPTR fileLock;
  1454.  
  1455.             /* This is a tricky issue: the filing system we are talking
  1456.              * to may be able to handle more than 30 characters, but then
  1457.              * it may be not, it's impossible to tell. We adopt the following
  1458.              * strategy: we try to access the named file and compare its
  1459.              * name against the one reported by the file system. If the name
  1460.              * reported by the file system is shorter than the one provided,
  1461.              * but matches it otherwise, we will assume that trouble is underway
  1462.              * and back out backwards.
  1463.              */
  1464.  
  1465.             ForbidDOS();
  1466.  
  1467.             fileLock = Lock((STRPTR)name,SHARED_LOCK);
  1468.             if(fileLock != ZERO)
  1469.             {
  1470.                 struct FileInfoBlock __aligned fib;
  1471.  
  1472.                 if(Examine(fileLock,&fib))
  1473.                 {
  1474.                     STRPTR file_name = FilePart((STRPTR)name);
  1475.                     int len;
  1476.  
  1477.                     /* Now check if the name reported by the
  1478.                      * filing system is shorter than the
  1479.                      * one we asked for, but matches otherwise.
  1480.                      */
  1481.                     len = strlen(fib.fib_FileName);
  1482.                     if(strlen(file_name) > len && Strnicmp(file_name,fib.fib_FileName,len) == SAME)
  1483.                     {
  1484.                         /* The name is too long to handle. */
  1485.                         error = ERROR_LINE_TOO_LONG;
  1486.                     }
  1487.                 }
  1488.                 else
  1489.                 {
  1490.                     error = IoErr();
  1491.                 }
  1492.  
  1493.                 UnLock(fileLock);
  1494.             }
  1495.             else
  1496.             {
  1497.                 error = IoErr();
  1498.             }
  1499.  
  1500.             PermitDOS();
  1501.  
  1502.             /* We don't complain if the file does
  1503.              * not exist, but if it is currently in
  1504.              * use, on a volume that's not currently
  1505.              * mounted, etc. we will complain.
  1506.              */
  1507.             if(error != OK && error != ERROR_OBJECT_NOT_FOUND)
  1508.             {
  1509.                 SetIoErr(error);
  1510.                 MapIoErrToErrno();
  1511.  
  1512.                 goto out;
  1513.             }
  1514.         }
  1515.  
  1516.         mi->mi_OldName = (*namePtr);
  1517.         (*namePtr) = name;
  1518.  
  1519.         result = OK;
  1520.     }
  1521.  
  1522. out:
  1523.  
  1524.     RETURN(result);
  1525.     return(result);
  1526. }
  1527.  
  1528. /******************************************************************************/
  1529.  
  1530. STATIC int MaxOpenDescriptor = -1;
  1531.  
  1532. STATIC VOID
  1533. CloseUnlinkUnlockCleanup(VOID)
  1534. {
  1535.     struct UFB * ufb;
  1536.     int fd;
  1537.  
  1538.     ForbidDOS();
  1539.  
  1540.     /* Don't let anybody stop us. */
  1541.     signal(SIGINT,SIG_IGN);
  1542.     signal(SIGTERM,SIG_IGN);
  1543.  
  1544.     /* We look for descriptors we marked for
  1545.      * deletion.
  1546.      */
  1547.     for(fd = 0 ; fd <= MaxOpenDescriptor ; fd++)
  1548.     {
  1549.         CleanupFileLocks(fd);
  1550.  
  1551.         ufb = chkufb(fd);
  1552.         if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_UNLINK))
  1553.         {
  1554.             char fileName[MAX_FILENAME_LEN];
  1555.             BOOL removeIt;
  1556.  
  1557.             removeIt = NameFromFH((BPTR)ufb->ufbfh,fileName,sizeof(fileName));
  1558.  
  1559.             CLEAR_FLAG(ufb->ufbflg,UFB_UNLINK);
  1560.  
  1561.             close(fd);
  1562.  
  1563.             if(removeIt)
  1564.                 DeleteFile(fileName);
  1565.         }
  1566.     }
  1567.  
  1568.     PermitDOS();
  1569. }
  1570.  
  1571. int
  1572. amiga_unlink(char *name)
  1573. {
  1574.     struct MangleInfo mi;
  1575.     BPTR fileLock;
  1576.     int result = ERROR;
  1577.  
  1578.     chkabort();
  1579.  
  1580.     ASSERT(name != NULL);
  1581.  
  1582.     ENTER();
  1583.     SHOWSTRING(name);
  1584.  
  1585.     if(MangleName(&name,&mi) == OK)
  1586.     {
  1587.         LONG error = OK;
  1588.  
  1589.         ForbidDOS();
  1590.  
  1591.         fileLock = Lock(name,SHARED_LOCK);
  1592.         if(fileLock != ZERO)
  1593.         {
  1594.             struct FileInfoBlock __aligned fib;
  1595.  
  1596.             if(Examine(fileLock,&fib))
  1597.             {
  1598.                 UnLock(fileLock);
  1599.                 fileLock = ZERO;
  1600.  
  1601.                 /* Make sure that we get to remove
  1602.                  * a file, as the name implies.
  1603.                  */
  1604.                 if(FIB_IS_FILE(&fib))
  1605.                 {
  1606.                     if(DeleteFile(name))
  1607.                         result = OK;
  1608.                     else
  1609.                         error = IoErr();
  1610.                 }
  1611.                 else
  1612.                 {
  1613.                     errno = EISDIR;
  1614.                 }
  1615.             }
  1616.             else
  1617.             {
  1618.                 error = IoErr();
  1619.             }
  1620.  
  1621.             UnLock(fileLock);
  1622.         }
  1623.         else
  1624.         {
  1625.             error = IoErr();
  1626.         }
  1627.  
  1628.         PermitDOS();
  1629.  
  1630.         /* Check if we couldn't delete the file in
  1631.          * question because there still is a file
  1632.          * handle attached to it. If we can find that
  1633.          * file, we will mark it for deletion lateron
  1634.          * when the file is closed.
  1635.          */
  1636.         if(result != OK && error == ERROR_OBJECT_IN_USE)
  1637.         {
  1638.             char parentDirName[MAX_FILENAME_LEN];
  1639.             BOOL foundParentDirName;
  1640.             BPTR fileParentDir;
  1641.             int i;
  1642.  
  1643.             ASSERT(strlen(name) < sizeof(parentDirName));
  1644.  
  1645.             strcpy(parentDirName,name);
  1646.             foundParentDirName = FALSE;
  1647.  
  1648.             for(i = strlen(parentDirName)-1 ; i >= 0 ; i--)
  1649.             {
  1650.                 if(parentDirName[i] == ':')
  1651.                 {
  1652.                     if(parentDirName[i+1] != '\0')
  1653.                     {
  1654.                         parentDirName[i+1] = '\0';
  1655.                         foundParentDirName = TRUE;
  1656.                     }
  1657.  
  1658.                     break;
  1659.                 }
  1660.                 else if (parentDirName[i] == '/')
  1661.                 {
  1662.                     parentDirName[i] = '\0';
  1663.                     foundParentDirName = TRUE;
  1664.                     break;
  1665.                 }
  1666.             }
  1667.  
  1668.             /* Did we find this file's parent directory name? */
  1669.             if(foundParentDirName)
  1670.             {
  1671.                 D(("locking |%s|",parentDirName));
  1672.  
  1673.                 /* Get a lock on the file's parent directory. */
  1674.                 fileParentDir = Lock(parentDirName,SHARED_LOCK);
  1675.                 if(fileParentDir != ZERO)
  1676.                 {
  1677.                     BPTR descriptorParentDir;
  1678.                     BOOL gotIt = FALSE;
  1679.                     struct UFB * ufb;
  1680.                     int fd;
  1681.  
  1682.                     for(fd = 0 ; fd <= MaxOpenDescriptor ; fd++)
  1683.                     {
  1684.                         ufb = chkufb(fd);
  1685.                         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  1686.                         {
  1687.                             /* And also get a lock on the file
  1688.                              * descriptor's parent directory.
  1689.                              */
  1690.                             descriptorParentDir = ParentOfFH((BPTR)ufb->ufbfh);
  1691.                             if(descriptorParentDir != ZERO)
  1692.                             {
  1693.                                 /* Are the two pointing to the same drawer? */
  1694.                                 if(SameLock(fileParentDir,descriptorParentDir) == LOCK_SAME)
  1695.                                 {
  1696.                                     struct FileInfoBlock __aligned fib;
  1697.  
  1698.                                     if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  1699.                                     {
  1700.                                         /* Check if the two share the same name. */
  1701.                                         if(Stricmp(fib.fib_FileName,FilePart(name)) == SAME)
  1702.                                         {
  1703.                                             /* Mark this file for deletion. */
  1704.                                             SET_FLAG(ufb->ufbflg,UFB_UNLINK);
  1705.  
  1706.                                             gotIt = TRUE;
  1707.                                             error = OK;
  1708.                                             result = OK;
  1709.                                         }
  1710.                                     }
  1711.                                     else
  1712.                                     {
  1713.                                         SHOWMSG("couldn't examine the descriptor");
  1714.                                     }
  1715.                                 }
  1716.                                 else
  1717.                                 {
  1718.                                     SHOWMSG("file and descriptor don't live in the same drawer");
  1719.                                 }
  1720.  
  1721.                                 UnLock(descriptorParentDir);
  1722.                             }
  1723.                             else
  1724.                             {
  1725.                                 SHOWMSG("the descriptor doesn't have a parent directory (huh?!?)");
  1726.                             }
  1727.                         }
  1728.  
  1729.                         if(gotIt)
  1730.                             break;
  1731.                     }
  1732.  
  1733.                     UnLock(fileParentDir);
  1734.                 }
  1735.                 else
  1736.                 {
  1737.                     D(("couldn't get a lock on |%s|",parentDirName));
  1738.                 }
  1739.             }
  1740.             else
  1741.             {
  1742.                 D(("didn't find parent dir name of |%s|",name));
  1743.             }
  1744.         }
  1745.  
  1746.         /* Take care of the AmigaDOS error
  1747.          * code, if there is any.
  1748.          */
  1749.         if(result != OK && error != OK)
  1750.         {
  1751.             SetIoErr(error);
  1752.             MapIoErrToErrno();
  1753.         }
  1754.  
  1755.         UnmangleName(&name,&mi);
  1756.     }
  1757.  
  1758.     RETURN(result);
  1759.     return(result);
  1760. }
  1761.  
  1762. int
  1763. amiga_open(char *name,int mode,int prot)
  1764. {
  1765.     struct MangleInfo mi;
  1766.     int result = ERROR;
  1767.  
  1768.     chkabort();
  1769.  
  1770.     ASSERT(name != NULL);
  1771.  
  1772.     ENTER();
  1773.     SHOWSTRING(name);
  1774.     SHOWVALUE(mode);
  1775.     SHOWVALUE(prot);
  1776.  
  1777.     if(MangleName(&name,&mi) == OK)
  1778.     {
  1779.         /* Clear the "no delay" flag since the SAS/C
  1780.          * runtime library does not support it.
  1781.          */
  1782.         CLEAR_FLAG(mode,O_NONBLOCK);
  1783.  
  1784.         ForbidDOS();
  1785.  
  1786.         result = open(name,mode,prot);
  1787.         if(result != ERROR && MaxOpenDescriptor < result)
  1788.             MaxOpenDescriptor = result;
  1789.  
  1790.         PermitDOS();
  1791.  
  1792.         UnmangleName(&name,&mi);
  1793.     }
  1794.  
  1795.     RETURN(result);
  1796.     return(result);
  1797. }
  1798.  
  1799. /******************************************************************************/
  1800.  
  1801. STATIC char CurrentDirName[MAX_FILENAME_LEN] = "";
  1802.  
  1803. int
  1804. amiga_chdir(char *path)
  1805. {
  1806.     BOOL isAbsolutePath;
  1807.     struct MangleInfo mi;
  1808.     int result = ERROR;
  1809.  
  1810.     chkabort();
  1811.  
  1812.     ASSERT(path != NULL);
  1813.  
  1814.     ENTER();
  1815.     SHOWSTRING(path);
  1816.  
  1817.     /* Is this an absolute path? */
  1818.     isAbsolutePath = (BOOL)(path[0] == '/');
  1819.  
  1820.     if(MangleName(&path,&mi) == OK)
  1821.     {
  1822.         BPTR drawerLock;
  1823.  
  1824.         D(("chdir(\"%s\")",path));
  1825.  
  1826.         ForbidDOS();
  1827.  
  1828.         drawerLock = Lock(path,SHARED_LOCK);
  1829.         if(drawerLock != ZERO)
  1830.         {
  1831.             struct FileInfoBlock __aligned fib;
  1832.  
  1833.             if(Examine(drawerLock,&fib))
  1834.             {
  1835.                 /* We can only move into drawers. */
  1836.                 if(FIB_IS_DRAWER(&fib))
  1837.                 {
  1838.                     /* If necessary, get the name of
  1839.                      * the drawer to move into.
  1840.                      */
  1841.                     if(NOT isAbsolutePath)
  1842.                     {
  1843.                         UBYTE localName[MAX_FILENAME_LEN];
  1844.  
  1845.                         if(NameFromLock(drawerLock,localName,sizeof(localName)))
  1846.                             result = MapFileNameAmigaToUnix(localName,CurrentDirName,sizeof(CurrentDirName));
  1847.                         else
  1848.                             MapIoErrToErrno();
  1849.                     }
  1850.                     else
  1851.                     {
  1852.                         result = OK;
  1853.                     }
  1854.  
  1855.                     /* If everything went well,
  1856.                      * move into the drawer.
  1857.                      */
  1858.                     if(result == OK)
  1859.                     {
  1860.                         BPTR oldDrawer;
  1861.  
  1862.                         oldDrawer = CurrentDir(drawerLock);
  1863.  
  1864.                         /* Unlock the old drawer we came from
  1865.                          * unless we want to return to it
  1866.                          * when the program exits.
  1867.                          */
  1868.                         if(InitialCurrentDirInitialized)
  1869.                         {
  1870.                             UnLock(oldDrawer);
  1871.                         }
  1872.                         else
  1873.                         {
  1874.                             InitialCurrentDir = oldDrawer;
  1875.                             InitialCurrentDirInitialized = TRUE;
  1876.                         }
  1877.  
  1878.                         /* Make sure that this drawer is going
  1879.                          * to be unlocked when the program exits.
  1880.                          */
  1881.                         ChangedCurrentDir = drawerLock;
  1882.                     }
  1883.                 }
  1884.                 else
  1885.                 {
  1886.                     errno = ENOTDIR;
  1887.                 }
  1888.             }
  1889.             else
  1890.             {
  1891.                 MapIoErrToErrno();
  1892.             }
  1893.  
  1894.             if(result != OK)
  1895.                 UnLock(drawerLock);
  1896.         }
  1897.         else
  1898.         {
  1899.             MapIoErrToErrno();
  1900.         }
  1901.  
  1902.         PermitDOS();
  1903.  
  1904.         UnmangleName(&path,&mi);
  1905.  
  1906.         if(result == OK && isAbsolutePath)
  1907.             strcpy(CurrentDirName,path);
  1908.     }
  1909.  
  1910.     RETURN(result);
  1911.     return(result);
  1912. }
  1913.  
  1914. /******************************************************************************/
  1915.  
  1916. struct OpenDirNode
  1917. {
  1918.     struct MinNode            odn_MinNode;
  1919.     BPTR                    odn_FileLock;
  1920.     struct FileInfoBlock    odn_FIB;
  1921.     struct List                odn_VolumeList;
  1922.     DIR                        odn_DIR;
  1923.     BOOL                    odn_ReadingVolumes;
  1924.     struct dirent            odn_DirectoryEntry;
  1925.     struct Node *            odn_NextNode;
  1926.     ULONG                    odn_NextDirEntryIndex;
  1927.     LONG                    odn_ParentDirKey;
  1928. };
  1929.  
  1930. STATIC struct List OpenDirList;
  1931. STATIC BOOL OpenDirListInitialized = FALSE;
  1932.  
  1933. STATIC ULONG RootBlocks = 0;
  1934. STATIC ULONG RootBlocksUsed = 0;
  1935.  
  1936. STATIC VOID
  1937. OpenDirCleanup(VOID)
  1938. {
  1939.     struct OpenDirNode * odn;
  1940.  
  1941.     /* Unlock all directories still being scanned
  1942.      * when exit() was called.
  1943.      */
  1944.     for(odn = (struct OpenDirNode *)OpenDirList.lh_Head ;
  1945.         odn->odn_MinNode.mln_Succ != NULL ;
  1946.         odn = (struct OpenDirNode *)odn->odn_MinNode.mln_Succ)
  1947.     {
  1948.         UnLock(odn->odn_FileLock);
  1949.     }
  1950. }
  1951.  
  1952. DIR *
  1953. amiga_opendir(char *dirName)
  1954. {
  1955.     char localDirName[MAX_FILENAME_LEN];
  1956.     DIR *result = NULL;
  1957.  
  1958.     chkabort();
  1959.  
  1960.     ASSERT(dirName != NULL);
  1961.  
  1962.     ENTER();
  1963.  
  1964.     SHOWSTRING(dirName);
  1965.  
  1966.     /* Make sure that the directory list is
  1967.      * set up properly.
  1968.      */
  1969.     if(NOT OpenDirListInitialized)
  1970.     {
  1971.         NewList(&OpenDirList);
  1972.         OpenDirListInitialized = TRUE;
  1973.         atexit(OpenDirCleanup);
  1974.     }
  1975.  
  1976.     if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  1977.     {
  1978.         /* Check if we are to scan the virtual root directory. */
  1979.         if(strcmp(dirName,"/") == SAME)
  1980.         {
  1981.             struct OpenDirNode * odn;
  1982.  
  1983.             odn = malloc(sizeof(*odn));
  1984.             if(odn != NULL)
  1985.             {
  1986.                 struct DosList * dol;
  1987.  
  1988.                 RootBlocks = RootBlocksUsed = 0;
  1989.  
  1990.                 memset(odn,0,sizeof(*odn));
  1991.                 odn->odn_ReadingVolumes = TRUE;
  1992.                 odn->odn_DIR.dd_buf = (char *)odn;
  1993.                 NewList(&odn->odn_VolumeList);
  1994.  
  1995.                 AddHead(&OpenDirList,(struct Node *)odn);
  1996.  
  1997.                 result = &odn->odn_DIR;
  1998.  
  1999.                 /* Now collect all volumes in the system. */
  2000.                 dol = NextDosEntry(LockDosList(LDF_VOLUMES|LDF_READ),
  2001.                                                LDF_VOLUMES|LDF_READ);
  2002.                 while(dol != NULL)
  2003.                 {
  2004.                     /* Does the volume refer to a medium that is right
  2005.                      * now present in the drive?
  2006.                      */
  2007.                     if(dol->dol_Task != NULL)
  2008.                     {
  2009.                         struct InfoData __aligned id;
  2010.  
  2011.                         /* Is there a disk present? */
  2012.                         if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  2013.                         {
  2014.                             STRPTR name = BADDR(dol->dol_Name);
  2015.                             struct Node * node;
  2016.  
  2017.                             /* Collect the number of blocks used and
  2018.                              * available in our fake root directory.
  2019.                              * Not that it matters much...
  2020.                              */
  2021.                             if(id.id_BytesPerBlock == 512)
  2022.                             {
  2023.                                 RootBlocks        += id.id_NumBlocks;
  2024.                                 RootBlocksUsed    += id.id_NumBlocksUsed;
  2025.                             }
  2026.                             else
  2027.                             {
  2028.                                 RootBlocks        += (id.id_NumBlocks * id.id_BytesPerBlock) / 512;
  2029.                                 RootBlocksUsed    += (id.id_NumBlocksUsed * id.id_BytesPerBlock) / 512;
  2030.                             }
  2031.  
  2032.                             node = malloc(sizeof(*node) + ((int)name[0])+1);
  2033.                             if(node != NULL)
  2034.                             {
  2035.                                 /* Copy the name of the volume. */
  2036.                                 node->ln_Name = (char *)(node + 1);
  2037.                                 strncpy(node->ln_Name,&name[1],name[0]);
  2038.                                 node->ln_Name[ name[0] ] = '\0';
  2039.  
  2040.                                 AddTail(&odn->odn_VolumeList,node);
  2041.  
  2042.                                 if(odn->odn_NextNode == NULL)
  2043.                                     odn->odn_NextNode = node;
  2044.                             }
  2045.                         }
  2046.                     }
  2047.  
  2048.                     dol = NextDosEntry(dol,LDF_VOLUMES|LDF_READ);
  2049.                 }
  2050.  
  2051.                 UnLockDosList(LDF_VOLUMES|LDF_READ);
  2052.             }
  2053.             else
  2054.             {
  2055.                 errno = ENOMEM;
  2056.             }
  2057.         }
  2058.         else
  2059.         {
  2060.             struct MangleInfo mi;
  2061.  
  2062.             if(MangleName(&dirName,&mi) == OK)
  2063.             {
  2064.                 BPTR fileLock;
  2065.  
  2066.                 ForbidDOS();
  2067.  
  2068.                 fileLock = Lock(dirName,SHARED_LOCK);
  2069.                 if(fileLock != ZERO)
  2070.                 {
  2071.                     struct OpenDirNode * odn;
  2072.  
  2073.                     odn = malloc(sizeof(*odn));
  2074.                     if(odn != NULL)
  2075.                     {
  2076.                         BPTR parentDir;
  2077.  
  2078.                         memset(odn,0,sizeof(*odn));
  2079.  
  2080.                         parentDir = ParentDir(fileLock);
  2081.                         if(parentDir != ZERO)
  2082.                         {
  2083.                             if(Examine(parentDir,&odn->odn_FIB))
  2084.                                 odn->odn_ParentDirKey = odn->odn_FIB.fib_DiskKey;
  2085.  
  2086.                             UnLock(parentDir);
  2087.                         }
  2088.  
  2089.                         if(Examine(fileLock,&odn->odn_FIB))
  2090.                         {
  2091.                             /* Make sure that we are
  2092.                              * trying to read a drawer
  2093.                              * and not a file.
  2094.                              */
  2095.                             if(FIB_IS_DRAWER(&odn->odn_FIB))
  2096.                             {
  2097.                                 odn->odn_DIR.dd_buf = (char *)odn;
  2098.                                 odn->odn_FileLock = fileLock;
  2099.                                 NewList(&odn->odn_VolumeList);
  2100.  
  2101.                                 /* The lock has been "swallowed"
  2102.                                  * by the dir node; make sure that
  2103.                                  * we don't unlock it.
  2104.                                  */
  2105.                                 fileLock = ZERO;
  2106.  
  2107.                                 AddHead(&OpenDirList,(struct Node *)odn);
  2108.                                 result = &odn->odn_DIR;
  2109.                             }
  2110.                             else
  2111.                             {
  2112.                                 errno = ENOTDIR;
  2113.                             }
  2114.                         }
  2115.                         else
  2116.                         {
  2117.                             MapIoErrToErrno();
  2118.                         }
  2119.  
  2120.                         if(result == NULL)
  2121.                             free(odn);
  2122.                     }
  2123.                     else
  2124.                     {
  2125.                         errno = ENOMEM;
  2126.                     }
  2127.  
  2128.                     UnLock(fileLock);
  2129.                 }
  2130.                 else
  2131.                 {
  2132.                     MapIoErrToErrno();
  2133.                 }
  2134.  
  2135.                 PermitDOS();
  2136.  
  2137.                 UnmangleName(&dirName,&mi);
  2138.             }
  2139.         }
  2140.     }
  2141.  
  2142.     RETURN(result);
  2143.     return(result);
  2144. }
  2145.  
  2146. VOID
  2147. amiga_closedir(DIR *dir)
  2148. {
  2149.     if(dir != NULL)
  2150.     {
  2151.         struct OpenDirNode * odn = (struct OpenDirNode *)dir->dd_buf;
  2152.  
  2153.         if(odn != NULL)
  2154.         {
  2155.             struct Node * node;
  2156.  
  2157.             Remove((struct Node *)odn);
  2158.  
  2159.             while((node = RemHead(&odn->odn_VolumeList)) != NULL)
  2160.                 free(node);
  2161.  
  2162.             UnLock(odn->odn_FileLock);
  2163.             free(odn);
  2164.         }
  2165.     }
  2166.  
  2167.     chkabort();
  2168. }
  2169.  
  2170. struct dirent *
  2171. amiga_readdir(DIR *dir)
  2172. {
  2173.     struct dirent * result = NULL;
  2174.  
  2175.     chkabort();
  2176.  
  2177.     if(dir != NULL)
  2178.     {
  2179.         struct OpenDirNode * odn = (struct OpenDirNode *)dir->dd_buf;
  2180.  
  2181.         if(odn != NULL)
  2182.         {
  2183.             struct dirent * d = &odn->odn_DirectoryEntry;
  2184.  
  2185.             if(odn->odn_ReadingVolumes)
  2186.             {
  2187.                 /* The first directory entry points
  2188.                  * back to the directory itself.
  2189.                  */
  2190.                 if(odn->odn_NextDirEntryIndex == 0)
  2191.                 {
  2192.                     strcpy(d->d_name,".");
  2193.  
  2194.                     d->d_ino    = ++odn->odn_NextDirEntryIndex;
  2195.                     d->d_namlen    = strlen(d->d_name);
  2196.  
  2197.                     result = d;
  2198.                 }
  2199.                 else
  2200.                 {
  2201.                     /* Return the next volume in the list. */
  2202.                     if(odn->odn_NextNode != NULL && odn->odn_NextNode->ln_Succ != NULL)
  2203.                     {
  2204.                         ASSERT(sizeof(d->d_name) >= strlen(odn->odn_NextNode->ln_Name));
  2205.  
  2206.                         strcpy(d->d_name,odn->odn_NextNode->ln_Name);
  2207.  
  2208.                         odn->odn_NextNode = odn->odn_NextNode->ln_Succ;
  2209.  
  2210.                         d->d_ino    = odn->odn_NextDirEntryIndex++;
  2211.                         d->d_namlen    = strlen(d->d_name);
  2212.  
  2213.                         result = d;
  2214.                     }
  2215.                     else
  2216.                     {
  2217.                         errno = 0;
  2218.                     }
  2219.                 }
  2220.             }
  2221.             else
  2222.             {
  2223.                 if(odn->odn_NextDirEntryIndex == 0)
  2224.                 {
  2225.                     /* The first directory entry points
  2226.                      * back to the directory itself.
  2227.                      */
  2228.                     strcpy(d->d_name,".");
  2229.  
  2230.                     d->d_ino    = odn->odn_FIB.fib_DiskKey;
  2231.                     d->d_namlen    = strlen(d->d_name);
  2232.  
  2233.                     odn->odn_NextDirEntryIndex++;
  2234.                     result = d;
  2235.                 }
  2236.                 else if(odn->odn_NextDirEntryIndex == 1)
  2237.                 {
  2238.                     /* The second directory entry points
  2239.                      * to the parent directory.
  2240.                      */
  2241.                     strcpy(d->d_name,"..");
  2242.  
  2243.                     d->d_ino    = odn->odn_ParentDirKey;
  2244.                     d->d_namlen    = strlen(d->d_name);
  2245.  
  2246.                     odn->odn_NextDirEntryIndex++;
  2247.                     result = d;
  2248.                 }
  2249.                 else
  2250.                 {
  2251.                     ForbidDOS();
  2252.  
  2253.                     /* All other iterations pick up the
  2254.                      * next following directory entry.
  2255.                      */
  2256.                     if(ExNext(odn->odn_FileLock,&odn->odn_FIB))
  2257.                     {
  2258.                         ASSERT(sizeof(d->d_name) >= strlen(odn->odn_FIB.fib_FileName));
  2259.  
  2260.                         strcpy(d->d_name,odn->odn_FIB.fib_FileName);
  2261.  
  2262.                         d->d_ino    = odn->odn_FIB.fib_DiskKey;
  2263.                         d->d_namlen    = strlen(d->d_name);
  2264.  
  2265.                         result = d;
  2266.                     }
  2267.                     else
  2268.                     {
  2269.                         LONG error = IoErr();
  2270.  
  2271.                         if(error == ERROR_NO_MORE_ENTRIES)
  2272.                         {
  2273.                             errno = 0;
  2274.                         }
  2275.                         else
  2276.                         {
  2277.                             SetIoErr(error);
  2278.                             MapIoErrToErrno();
  2279.                         }
  2280.                     }
  2281.  
  2282.                     PermitDOS();
  2283.                 }
  2284.             }
  2285.         }
  2286.     }
  2287.  
  2288.     if(result != NULL)
  2289.         SHOWSTRING(result->d_name);
  2290.  
  2291.     return(result);
  2292. }
  2293.  
  2294. /******************************************************************************/
  2295.  
  2296. STATIC int
  2297. TranslateRelativePath(char **namePtr,char *replace,int maxReplaceLen)
  2298. {
  2299.     int result = ERROR;
  2300.     char * name;
  2301.  
  2302.     ASSERT(namePtr != NULL && (*namePtr) != NULL && replace != NULL);
  2303.  
  2304.     /* If we have a current directory all references should
  2305.      * be made relative to, do just that. Absolute paths
  2306.      * are not modified, though.
  2307.      */
  2308.     name = (*namePtr);
  2309.     if(NOT STRING_IS_EMPTY(CurrentDirName) && name[0] != '/')
  2310.     {
  2311.         int totalLen;
  2312.  
  2313.         SHOWMSG("Changing the directory name");
  2314.  
  2315.         /* Skip current dir modifiers, we just want the name. */
  2316.         if(strncmp(name,"./",2) == SAME)
  2317.             name += 2;
  2318.         else if (strcmp(name,".") == SAME)
  2319.             name = "";
  2320.  
  2321.         /* Get the current directory name and get
  2322.          * ready to attach the file name at the end.
  2323.          */
  2324.         totalLen = strlen(CurrentDirName);
  2325.  
  2326.         if(CurrentDirName[strlen(CurrentDirName)-1] != '/' &&
  2327.            CurrentDirName[strlen(CurrentDirName)-1] != ':' &&
  2328.            NOT STRING_IS_EMPTY(name))
  2329.         {
  2330.             totalLen++;
  2331.         }
  2332.  
  2333.         totalLen += strlen(name);
  2334.  
  2335.         /* Check if the complete string will fit. */
  2336.         if(totalLen < maxReplaceLen)
  2337.         {
  2338.             /* Put the file name together. */
  2339.             strcpy(replace,CurrentDirName);
  2340.             if(CurrentDirName[strlen(CurrentDirName)-1] != '/' && NOT STRING_IS_EMPTY(name))
  2341.                 strcat(replace,"/");
  2342.  
  2343.             strcat(replace,name);
  2344.  
  2345.             (*namePtr) = replace;
  2346.             SHOWSTRING(*namePtr);
  2347.  
  2348.             result = OK;
  2349.         }
  2350.         else
  2351.         {
  2352.             errno = ENAMETOOLONG;
  2353.         }
  2354.     }
  2355.     else
  2356.     {
  2357.         result = OK;
  2358.     }
  2359.  
  2360.     return(result);
  2361. }
  2362.  
  2363. /******************************************************************************/
  2364.  
  2365. int
  2366. amiga_mkdir(char *name,int mode)
  2367. {
  2368.     struct MangleInfo mi;
  2369.     BPTR dirLock;
  2370.     int result = ERROR;
  2371.  
  2372.     chkabort();
  2373.  
  2374.     ASSERT(name != NULL);
  2375.  
  2376.     ENTER();
  2377.     SHOWSTRING(name);
  2378.     SHOWVALUE(mode);
  2379.  
  2380.     if(MangleName(&name,&mi) == OK)
  2381.     {
  2382.         ForbidDOS();
  2383.  
  2384.         dirLock = CreateDir((STRPTR)name);
  2385.         if(dirLock != ZERO)
  2386.         {
  2387.             UnLock(dirLock);
  2388.             result = OK;
  2389.         }
  2390.         else
  2391.         {
  2392.             MapIoErrToErrno();
  2393.         }
  2394.  
  2395.         PermitDOS();
  2396.  
  2397.         UnmangleName(&name,&mi);
  2398.     }
  2399.  
  2400.     if(result == OK)
  2401.         result = amiga_chmod(name,mode);
  2402.  
  2403.     RETURN(result);
  2404.     return(result);
  2405. }
  2406.  
  2407. /******************************************************************************/
  2408.  
  2409. int
  2410. amiga_rmdir(char *name)
  2411. {
  2412.     struct MangleInfo mi;
  2413.     BPTR fileLock;
  2414.     int result = ERROR;
  2415.  
  2416.     chkabort();
  2417.  
  2418.     ENTER();
  2419.     SHOWSTRING(name);
  2420.  
  2421.     if(MangleName(&name,&mi) == OK)
  2422.     {
  2423.         ForbidDOS();
  2424.  
  2425.         fileLock = Lock(name,SHARED_LOCK);
  2426.         if(fileLock != ZERO)
  2427.         {
  2428.             struct FileInfoBlock __aligned fib;
  2429.  
  2430.             if(Examine(fileLock,&fib))
  2431.             {
  2432.                 UnLock(fileLock);
  2433.                 fileLock = ZERO;
  2434.  
  2435.                 /* Make sure that we get to remove a drawer,
  2436.                  * as the function name implies.
  2437.                  */
  2438.                 if(FIB_IS_DRAWER(&fib))
  2439.                 {
  2440.                     if(DeleteFile(name))
  2441.                         result = OK;
  2442.                     else
  2443.                         MapIoErrToErrno();
  2444.                 }
  2445.                 else
  2446.                 {
  2447.                     errno = ENOTDIR;
  2448.                 }
  2449.             }
  2450.             else
  2451.             {
  2452.                 MapIoErrToErrno();
  2453.             }
  2454.  
  2455.             UnLock(fileLock);
  2456.         }
  2457.         else
  2458.         {
  2459.             MapIoErrToErrno();
  2460.         }
  2461.  
  2462.         PermitDOS();
  2463.  
  2464.         UnmangleName(&name,&mi);
  2465.     }
  2466.  
  2467.     RETURN(result);
  2468.     return(result);
  2469. }
  2470.  
  2471. /******************************************************************************/
  2472.  
  2473. int
  2474. amiga_creat(char *name,int prot)
  2475. {
  2476.     struct MangleInfo mi;
  2477.     int result = ERROR;
  2478.  
  2479.     chkabort();
  2480.  
  2481.     ASSERT(name != NULL);
  2482.  
  2483.     ENTER();
  2484.     SHOWSTRING(name);
  2485.     SHOWVALUE(prot);
  2486.  
  2487.     if(MangleName(&name,&mi) == OK)
  2488.     {
  2489.         ForbidDOS();
  2490.         result = creat(name,prot);
  2491.         PermitDOS();
  2492.  
  2493.         UnmangleName(&name,&mi);
  2494.     }
  2495.  
  2496.     RETURN(result);
  2497.     return(result);
  2498. }
  2499.  
  2500. /******************************************************************************/
  2501.  
  2502. FILE *
  2503. amiga_fopen(char *name,char *mode)
  2504. {
  2505.     struct MangleInfo mi;
  2506.     FILE *result = NULL;
  2507.  
  2508.     chkabort();
  2509.  
  2510.     ASSERT(name != NULL && mode != NULL);
  2511.  
  2512.     ENTER();
  2513.     SHOWSTRING(name);
  2514.     SHOWSTRING(mode);
  2515.  
  2516.     if(MangleName(&name,&mi) == OK)
  2517.     {
  2518.         ForbidDOS();
  2519.         result = fopen(name,mode);
  2520.         PermitDOS();
  2521.  
  2522.         UnmangleName(&name,&mi);
  2523.     }
  2524.  
  2525.     RETURN(result);
  2526.     return(result);
  2527. }
  2528.  
  2529. /******************************************************************************/
  2530.  
  2531. int
  2532. amiga_rename(char *old,char *new)
  2533. {
  2534.     struct MangleInfo old_mi;
  2535.     struct MangleInfo new_mi;
  2536.     int result = ERROR;
  2537.  
  2538.     chkabort();
  2539.  
  2540.     ASSERT(old != NULL && new != NULL);
  2541.  
  2542.     ENTER();
  2543.     SHOWSTRING(old);
  2544.     SHOWSTRING(new);
  2545.  
  2546.     /* rename() causes the link named <from> to be renamed as <to>. If <to> exists,
  2547.      * it is first removed. Both <from> and <to> must be of the same type (that is,
  2548.      * both directories or both non-directories), and must reside on the same
  2549.      * file system.
  2550.      */
  2551.  
  2552.     if(MangleName(&old,&old_mi) == OK)
  2553.     {
  2554.         if(MangleName(&new,&new_mi) == OK)
  2555.         {
  2556.             ForbidDOS();
  2557.  
  2558.             D(("rename |%s| to |%s|",old,new));
  2559.  
  2560.             if(CANNOT Rename(old,new))
  2561.             {
  2562.                 LONG error = IoErr();
  2563.  
  2564.                 SHOWVALUE(error);
  2565.  
  2566.                 if(error == ERROR_OBJECT_EXISTS)
  2567.                 {
  2568.                     BPTR oldLock = Lock(old,SHARED_LOCK);
  2569.                     BPTR newLock = Lock(new,SHARED_LOCK);
  2570.  
  2571.                     if(oldLock != ZERO && newLock != ZERO && SameLock(oldLock,newLock) == LOCK_SAME)
  2572.                     {
  2573.                         result = OK;
  2574.                         error = OK;
  2575.  
  2576.                         SHOWMSG("Ok; same name");
  2577.  
  2578.                         UnLock(oldLock);
  2579.                         UnLock(newLock);
  2580.                     }
  2581.                     else
  2582.                     {
  2583.                         UnLock(oldLock);
  2584.                         UnLock(newLock);
  2585.  
  2586.                         if(DeleteFile(new))
  2587.                         {
  2588.                             if(Rename(old,new))
  2589.                             {
  2590.                                 result = OK;
  2591.                                 error = OK;
  2592.  
  2593.                                 SHOWMSG("Ok; after removing");
  2594.                             }
  2595.                             else
  2596.                             {
  2597.                                 error = IoErr();
  2598.                             }
  2599.                         }
  2600.                         else
  2601.                         {
  2602.                             error = IoErr();
  2603.                         }
  2604.                     }
  2605.                 }
  2606.  
  2607.                 if(error != OK)
  2608.                 {
  2609.                     SHOWVALUE(error);
  2610.  
  2611.                     SetIoErr(error);
  2612.                     MapIoErrToErrno();
  2613.                 }
  2614.             }
  2615.             else
  2616.             {
  2617.                 SHOWMSG("Ok");
  2618.  
  2619.                 result = OK;
  2620.             }
  2621.  
  2622.             PermitDOS();
  2623.  
  2624.             UnmangleName(&new,&new_mi);
  2625.         }
  2626.         else
  2627.         {
  2628.             SHOWMSG("MangleName new_mi failed");
  2629.         }
  2630.  
  2631.         UnmangleName(&old,&old_mi);
  2632.     }
  2633.     else
  2634.     {
  2635.         SHOWMSG("MangleName old_mi failed");
  2636.     }
  2637.  
  2638.     RETURN(result);
  2639.     return(result);
  2640. }
  2641.  
  2642. /******************************************************************************/
  2643.  
  2644. char *
  2645. amiga_getcwd(char *buf, size_t size)
  2646. {
  2647.     char *result = NULL;
  2648.  
  2649.     chkabort();
  2650.  
  2651.     ASSERT(buf != NULL);
  2652.  
  2653.     ENTER();
  2654.     SHOWVALUE(buf);
  2655.     SHOWVALUE(size);
  2656.  
  2657.     if(CurrentDirName[0] == '/')
  2658.     {
  2659.         strncpy(buf,CurrentDirName,size-1);
  2660.         buf[size-1] = '\0';
  2661.         result = buf;
  2662.     }
  2663.     else
  2664.     {
  2665.         BPTR oldDir;
  2666.  
  2667.         ForbidDOS();
  2668.  
  2669.         oldDir = CurrentDir(ZERO);
  2670.  
  2671.         if(NameFromLock(oldDir,buf,size))
  2672.         {
  2673.             if(MapFileNameAmigaToUnix(buf,buf,size) == OK)
  2674.                 result = buf;
  2675.         }
  2676.         else
  2677.         {
  2678.             MapIoErrToErrno();
  2679.         }
  2680.  
  2681.         CurrentDir(oldDir);
  2682.  
  2683.         PermitDOS();
  2684.     }
  2685.  
  2686.     SHOWSTRING(result);
  2687.  
  2688.     RETURN(result);
  2689.     return(result);
  2690. }
  2691.  
  2692. /******************************************************************************/
  2693.  
  2694. #define SET_FILESIZE_ERROR (-1)
  2695.  
  2696. int
  2697. amiga_ftruncate(int fd,off_t size)
  2698. {
  2699.     struct UFB * ufb;
  2700.     int result = ERROR;
  2701.  
  2702.     chkabort();
  2703.  
  2704.     ENTER();
  2705.     SHOWVALUE(fd);
  2706.     SHOWVALUE(size);
  2707.  
  2708.     ufb = chkufb(fd);
  2709.     if(ufb != NULL)
  2710.     {
  2711.         ForbidDOS();
  2712.  
  2713.         if(SetFileSize((BPTR)ufb->ufbfh,size,OFFSET_BEGINNING) != SET_FILESIZE_ERROR)
  2714.             result = OK;
  2715.         else
  2716.             MapIoErrToErrno();
  2717.  
  2718.         PermitDOS();
  2719.     }
  2720.     else
  2721.     {
  2722.         errno = EBADF;
  2723.     }
  2724.  
  2725.     RETURN(result);
  2726.     return(result);
  2727. }
  2728.  
  2729. /******************************************************************************/
  2730.  
  2731. int
  2732. amiga_accept(int sockfd,struct sockaddr *cliaddr,int *addrlen)
  2733. {
  2734.     struct UFB * ufb;
  2735.     int result = ERROR;
  2736.  
  2737.     chkabort();
  2738.  
  2739.     ASSERT(cliaddr != NULL && addrlen != NULL);
  2740.  
  2741.     ENTER();
  2742.     SHOWVALUE(sockfd);
  2743.     SHOWVALUE(cliaddr);
  2744.     SHOWVALUE(addrlen);
  2745.  
  2746.     ufb = chkufb(sockfd);
  2747.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2748.         result = accept(ufb->ufbfh,cliaddr,(LONG *)addrlen);
  2749.     else
  2750.         errno = ENOTSOCK;
  2751.  
  2752.     RETURN(result);
  2753.     return(result);
  2754. }
  2755.  
  2756. /******************************************************************************/
  2757.  
  2758. int
  2759. amiga_bind(int sockfd,struct sockaddr *name,int namelen)
  2760. {
  2761.     struct UFB * ufb;
  2762.     int result = ERROR;
  2763.  
  2764.     chkabort();
  2765.  
  2766.     ASSERT(name != NULL);
  2767.  
  2768.     ENTER();
  2769.     SHOWVALUE(sockfd);
  2770.     SHOWVALUE(name);
  2771.     SHOWVALUE(namelen);
  2772.  
  2773.     ufb = chkufb(sockfd);
  2774.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2775.         result = bind(ufb->ufbfh,name,namelen);
  2776.     else
  2777.         errno = ENOTSOCK;
  2778.  
  2779.     RETURN(result);
  2780.     return(result);
  2781. }
  2782.  
  2783. /******************************************************************************/
  2784.  
  2785. int
  2786. amiga_close(int fd)
  2787. {
  2788.     struct UFB * ufb;
  2789.     int result = ERROR;
  2790.  
  2791.     chkabort();
  2792.  
  2793.     ENTER();
  2794.     SHOWVALUE(fd);
  2795.  
  2796.     ufb = chkufb(fd);
  2797.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2798.     {
  2799.         result = CloseSocket(ufb->ufbfh);
  2800.         CLEAR_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  2801.  
  2802.         /* Make sure that the descriptor looks like a file again. */
  2803.         RestoreDescriptor(ufb);
  2804.  
  2805.         close(fd);
  2806.     }
  2807.     else
  2808.     {
  2809.         if(ufb != NULL)
  2810.         {
  2811.             /* Don't close the stdio streams! */
  2812.             if(fd == 0 || fd == 1 || fd == 2)
  2813.             {
  2814.                 D(("Attempt to muck with fd #%ld!",fd));
  2815.  
  2816.                 errno = EBADF;
  2817.             }
  2818.             else
  2819.             {
  2820.                 char fileName[MAX_FILENAME_LEN];
  2821.                 BOOL removeIt = FALSE;
  2822.  
  2823.                 if(FLAG_IS_SET(ufb->ufbflg,UFB_UNLINK))
  2824.                 {
  2825.                     removeIt = NameFromFH((BPTR)ufb->ufbfh,fileName,sizeof(fileName));
  2826.  
  2827.                     CLEAR_FLAG(ufb->ufbflg,UFB_UNLINK);
  2828.                 }
  2829.  
  2830.                 CleanupFileLocks(fd);
  2831.  
  2832.                 result = close(fd);
  2833.  
  2834.                 if(removeIt)
  2835.                     DeleteFile(fileName);
  2836.             }
  2837.         }
  2838.         else
  2839.         {
  2840.             errno = EBADF;
  2841.         }
  2842.     }
  2843.  
  2844.     RETURN(result);
  2845.     return(result);
  2846. }
  2847.  
  2848. /******************************************************************************/
  2849.  
  2850. int
  2851. amiga_connect(int sockfd,struct sockaddr *name,int namelen)
  2852. {
  2853.     struct UFB * ufb;
  2854.     int result = ERROR;
  2855.  
  2856.     chkabort();
  2857.  
  2858.     ASSERT(name != NULL && namelen > 0);
  2859.  
  2860.     ENTER();
  2861.     SHOWVALUE(sockfd);
  2862.     SHOWVALUE(name);
  2863.     SHOWVALUE(namelen);
  2864.  
  2865.     ufb = chkufb(sockfd);
  2866.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2867.         result = connect(ufb->ufbfh,name,namelen);
  2868.     else
  2869.         errno = ENOTSOCK;
  2870.  
  2871.     RETURN(result);
  2872.     return(result);
  2873. }
  2874.  
  2875. /******************************************************************************/
  2876.  
  2877. int
  2878. amiga_getpeername(int sockfd,struct sockaddr *name,int *namelen)
  2879. {
  2880.     struct UFB * ufb;
  2881.     int result = ERROR;
  2882.  
  2883.     chkabort();
  2884.  
  2885.     ASSERT(name != NULL && namelen != NULL);
  2886.  
  2887.     ENTER();
  2888.     SHOWVALUE(sockfd);
  2889.     SHOWVALUE(name);
  2890.     SHOWVALUE(namelen);
  2891.  
  2892.     ufb = chkufb(sockfd);
  2893.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2894.         result = getpeername(ufb->ufbfh,name,(LONG *)namelen);
  2895.     else
  2896.         errno = ENOTSOCK;
  2897.  
  2898.     RETURN(result);
  2899.     return(result);
  2900. }
  2901.  
  2902. /******************************************************************************/
  2903.  
  2904. int
  2905. amiga_getsockopt(int sockfd,int level,int optname,VOID *optval,int *optlen)
  2906. {
  2907.     struct UFB * ufb;
  2908.     int result = ERROR;
  2909.  
  2910.     chkabort();
  2911.  
  2912.     ASSERT(optval != NULL && optlen != NULL);
  2913.  
  2914.     ENTER();
  2915.     SHOWVALUE(sockfd);
  2916.     SHOWVALUE(level);
  2917.     SHOWVALUE(optname);
  2918.     SHOWVALUE(optval);
  2919.     SHOWVALUE(optlen);
  2920.  
  2921.     ufb = chkufb(sockfd);
  2922.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2923.         result = getsockopt(ufb->ufbfh,level,optname,optval,(LONG *)optlen);
  2924.     else
  2925.         errno = ENOTSOCK;
  2926.  
  2927.     RETURN(result);
  2928.     return(result);
  2929. }
  2930.  
  2931. /******************************************************************************/
  2932.  
  2933. int
  2934. amiga_ioctl(int fd,unsigned long request,char *arg)
  2935. {
  2936.     struct UFB * ufb;
  2937.     int result = ERROR;
  2938.  
  2939.     chkabort();
  2940.  
  2941.     ASSERT(arg != NULL);
  2942.  
  2943.     ENTER();
  2944.     SHOWVALUE(fd);
  2945.     SHOWVALUE(request);
  2946.     SHOWVALUE(arg);
  2947.  
  2948.     ufb = chkufb(fd);
  2949.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2950.         result = IoctlSocket(ufb->ufbfh,request,arg);
  2951.     else
  2952.         errno = ENOTSOCK;
  2953.  
  2954.     RETURN(result);
  2955.     return(result);
  2956. }
  2957.  
  2958. /******************************************************************************/
  2959.  
  2960. int
  2961. amiga_listen(int sockfd,int backlog)
  2962. {
  2963.     struct UFB * ufb;
  2964.     int result = ERROR;
  2965.  
  2966.     chkabort();
  2967.  
  2968.     ENTER();
  2969.     SHOWVALUE(sockfd);
  2970.     SHOWVALUE(backlog);
  2971.  
  2972.     ufb = chkufb(sockfd);
  2973.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  2974.         result = listen(ufb->ufbfh,backlog);
  2975.     else
  2976.         errno = ENOTSOCK;
  2977.  
  2978.     RETURN(result);
  2979.     return(result);
  2980. }
  2981.  
  2982. /******************************************************************************/
  2983.  
  2984. int
  2985. amiga_read(int fd,VOID *data,unsigned int size)
  2986. {
  2987.     struct UFB * ufb;
  2988.     int result;
  2989.  
  2990.     chkabort();
  2991.  
  2992.     ASSERT(data != NULL);
  2993.  
  2994.     ENTER();
  2995.     SHOWVALUE(fd);
  2996.     SHOWVALUE(data);
  2997.     SHOWVALUE(size);
  2998.  
  2999.     ufb = chkufb(fd);
  3000.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3001.     {
  3002.         SHOWMSG("input from socket");
  3003.         result = recv(ufb->ufbfh,data,size,0);
  3004.     }
  3005.     else
  3006.     {
  3007.         SHOWMSG("input from file");
  3008.         ForbidDOS();
  3009.         result = read(fd,data,size);
  3010.         PermitDOS();
  3011.     }
  3012.  
  3013.     RETURN(result);
  3014.     return(result);
  3015. }
  3016.  
  3017. /******************************************************************************/
  3018.  
  3019. int
  3020. amiga_recvfrom(int sockfd,VOID *buff,int len,int flags,struct sockaddr *from,int *fromlen)
  3021. {
  3022.     struct UFB * ufb;
  3023.     int result = ERROR;
  3024.  
  3025.     chkabort();
  3026.  
  3027.     ASSERT(buff != NULL && from != NULL && fromlen != NULL);
  3028.  
  3029.     ENTER();
  3030.     SHOWVALUE(sockfd);
  3031.     SHOWVALUE(buff);
  3032.     SHOWVALUE(len);
  3033.     SHOWVALUE(flags);
  3034.     SHOWVALUE(from);
  3035.     SHOWVALUE(fromlen);
  3036.  
  3037.     ufb = chkufb(sockfd);
  3038.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3039.         result = recvfrom(ufb->ufbfh,buff,len,flags,from,(LONG *)fromlen);
  3040.     else
  3041.         errno = ENOTSOCK;
  3042.  
  3043.     RETURN(result);
  3044.     return(result);
  3045. }
  3046.  
  3047. /******************************************************************************/
  3048.  
  3049. STATIC VOID
  3050. MapDescriptorSets(
  3051.     const fd_set *    input_fds,
  3052.     int                num_input_fds,
  3053.     fd_set *        socket_fds,
  3054.     int *            max_socket_fd_ptr,
  3055.     fd_set *        file_fds,
  3056.     int *            max_file_fd_ptr)
  3057. {
  3058.     FD_ZERO(socket_fds);
  3059.     FD_ZERO(file_fds);
  3060.  
  3061.     /* This routine maps file descriptor sets
  3062.      * from one format to another. We map
  3063.      * socket descriptors and regular file
  3064.      * descriptor sets.
  3065.      */
  3066.     if(input_fds != NULL && num_input_fds > 0)
  3067.     {
  3068.         int max_socket_fd = (*max_socket_fd_ptr);
  3069.         int max_file_fd = (*max_file_fd_ptr);
  3070.         struct UFB * ufb;
  3071.         int i;
  3072.  
  3073.         for(i = 0 ; i < num_input_fds ; i++)
  3074.         {
  3075.             if(FD_ISSET(i,input_fds))
  3076.             {
  3077.                 D(("fd to wait on #%ld",i));
  3078.  
  3079.                 ufb = chkufb(i);
  3080.                 if(ufb != NULL)
  3081.                 {
  3082.                     /* Is this a socket descriptor? */
  3083.                     if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3084.                     {
  3085.                         D(("fd #%ld is a socket.\n",i));
  3086.  
  3087.                         FD_SET(ufb->ufbfh,socket_fds);
  3088.  
  3089.                         if(max_socket_fd < ufb->ufbfh)
  3090.                             max_socket_fd = ufb->ufbfh;
  3091.                     }
  3092.                     else
  3093.                     {
  3094.                         D(("fd #%ld is a file.\n",i));
  3095.  
  3096.                         /* We only watch files bound to
  3097.                          * console streams.
  3098.                          */
  3099.                         if(IsInteractive((BPTR)ufb->ufbfh))
  3100.                         {
  3101.                             FD_SET(i,file_fds);
  3102.  
  3103.                             if(max_file_fd < i)
  3104.                                 max_file_fd = i;
  3105.                         }
  3106.                     }
  3107.                 }
  3108.             }
  3109.         }
  3110.  
  3111.         (*max_socket_fd_ptr)    = max_socket_fd;
  3112.         (*max_file_fd_ptr)        = max_file_fd;
  3113.     }
  3114. }
  3115.  
  3116. STATIC VOID
  3117. RemapDescriptorSets(
  3118.     const fd_set *    socket_fds,
  3119.     int                max_socket_fd,
  3120.     const fd_set *    file_fds,
  3121.     int                max_file_fd,
  3122.     fd_set *        output_fds,
  3123.     int                num_output_fds)
  3124. {
  3125.     /* This routine reverses the mapping established
  3126.      * above. We map the file and socket descriptor
  3127.      * sets back into the original set.
  3128.      */
  3129.     if(output_fds != NULL)
  3130.     {
  3131.         int fd;
  3132.  
  3133.         FD_ZERO(output_fds);
  3134.  
  3135.         for(fd = 0 ; fd <= max_socket_fd ; fd++)
  3136.         {
  3137.             if(FD_ISSET(fd,socket_fds))
  3138.             {
  3139.                 struct UFB * ufb;
  3140.                 int output_fd;
  3141.  
  3142.                 for(output_fd = 0 ; output_fd < num_output_fds ; output_fd++)
  3143.                 {
  3144.                     ufb = chkufb(output_fd);
  3145.                     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET) && ufb->ufbfh == fd)
  3146.                     {
  3147.                         D(("fd #%ld has data",output_fd));
  3148.                         FD_SET(output_fd,output_fds);
  3149.                         break;
  3150.                     }
  3151.                 }
  3152.             }
  3153.         }
  3154.  
  3155.         for(fd = 0 ; fd <= max_file_fd ; fd++)
  3156.         {
  3157.             if(FD_ISSET(fd,file_fds))
  3158.             {
  3159.                 D(("fd #%ld has data",fd));
  3160.                 FD_SET(fd,output_fds);
  3161.             }
  3162.         }
  3163.     }
  3164. }
  3165.  
  3166. int
  3167. amiga_select(int num_fds,fd_set *read_fds,fd_set *write_fds,fd_set *except_fds,struct timeval *timeout)
  3168. {
  3169.     fd_set socket_read_fds;
  3170.     fd_set socket_write_fds;
  3171.     fd_set socket_except_fds;
  3172.     int max_socket_fd;
  3173.     fd_set file_read_fds;
  3174.     fd_set file_write_fds;
  3175.     fd_set file_except_fds;
  3176.     struct UFB * ufb;
  3177.     int max_file_fd;
  3178.     int result = 0;
  3179.  
  3180.     chkabort();
  3181.  
  3182.     ENTER();
  3183.  
  3184.     if(num_fds > FD_SETSIZE)
  3185.     {
  3186.         D(("Warning: %ld descriptor sets to wait on requested; only %ld available.",num_fds,FD_SETSIZE));
  3187.         num_fds = FD_SETSIZE;
  3188.     }
  3189.  
  3190.     max_socket_fd = -1;
  3191.     max_file_fd = -1;
  3192.  
  3193.     MapDescriptorSets(read_fds,        num_fds,    &socket_read_fds,    &max_socket_fd,    &file_read_fds,        &max_file_fd);
  3194.     MapDescriptorSets(write_fds,    num_fds,    &socket_write_fds,    &max_socket_fd,    &file_write_fds,    &max_file_fd);
  3195.     MapDescriptorSets(except_fds,    num_fds,    &socket_except_fds,    &max_socket_fd,    &file_except_fds,    &max_file_fd);
  3196.  
  3197.     D(("number of socket fds to work on == %ld",max_socket_fd+1));
  3198.     D(("number of file   fds to work on == %ld",max_file_fd+1));
  3199.  
  3200.     /* Wait for socket input? */
  3201.     if(max_socket_fd != -1)
  3202.     {
  3203.         /* Wait for file input, too? */
  3204.         if(max_file_fd != -1 && (timeout == NULL || timeout->tv_secs > 0 || timeout->tv_micro > 0))
  3205.         {
  3206.             struct timeval stopWhen;
  3207.             struct timeval zero;
  3208.             BOOL gotSomething;
  3209.             ULONG breakMask;
  3210.             int i;
  3211.  
  3212.             /* We are going to poll all streams; for the timeout
  3213.              * feature to work, we absolutely must know when to
  3214.              * stop polling.
  3215.              *
  3216.              * Why aren't we using asynchronous DOS packets?
  3217.              * The answer is that once a packet is sent, you
  3218.              * cannot easily abort it. Polling is safer in
  3219.              * that respect. Yes, I know that ACTION_STACK
  3220.              * can be used to fake input to a console stream,
  3221.              * but I'd rather not rely upon it.
  3222.              */
  3223.             if(timeout != NULL)
  3224.             {
  3225.                 GetSysTime((APTR)&stopWhen);
  3226.                 AddTime((APTR)&stopWhen,(APTR)timeout);
  3227.             }
  3228.             else
  3229.             {
  3230.                 /* No timeout, poll until we are interrupted
  3231.                  * or get input from any of the files. It's
  3232.                  * not really necessary to initialize this
  3233.                  * timeval, but it keeps the compiler happy.
  3234.                  */
  3235.                 memset(&stopWhen,0,sizeof(stopWhen));
  3236.             }
  3237.  
  3238.             while(TRUE)
  3239.             {
  3240.                 /* Check for break signal. */
  3241.                 chkabort();
  3242.  
  3243.                 /* Delay for a tick to avoid busy-waiting. */
  3244.                 Delay(1);
  3245.  
  3246.                 /* This tells WaitSelect() to poll the sockets for input. */
  3247.                 zero.tv_secs    = 0;
  3248.                 zero.tv_micro    = 0;
  3249.  
  3250.                 /* Signals to stop on; we want to stop when a break signal arrives. */
  3251.                 if(AllowBreak)
  3252.                     breakMask = SIGBREAKF_CTRL_C;
  3253.                 else
  3254.                     breakMask = 0;
  3255.  
  3256.                 /* Check for socket input. */
  3257.                 result = WaitSelect(max_socket_fd+1,&socket_read_fds,&socket_write_fds,&socket_except_fds,&zero,&breakMask);
  3258.  
  3259.                 /* Stop if a break signal arrives. */
  3260.                 if((result < 0 && errno == EINTR) || FLAG_IS_SET(breakMask,SIGBREAKF_CTRL_C))
  3261.                     raise(SIGINT);
  3262.  
  3263.                 /* Stop if the return value from WaitSelect is negative. */
  3264.                 if(result < 0)
  3265.                     break;
  3266.  
  3267.                 /* Did we get any socket input? */
  3268.                 gotSomething = (BOOL)(result > 0);
  3269.                 if(NOT gotSomething)
  3270.                 {
  3271.                     /* Check all files for input. We also poll
  3272.                      * them for input, but each with a little
  3273.                      * delay of about 1/50 of a second. We stop
  3274.                      * as soon as we find one file that has
  3275.                      * input in it.
  3276.                      */
  3277.                     for(i = 0 ; i <= max_file_fd ; i++)
  3278.                     {
  3279.                         if(FD_ISSET(i,&file_read_fds) ||
  3280.                            FD_ISSET(i,&file_write_fds) ||
  3281.                            FD_ISSET(i,&file_except_fds))
  3282.                         {
  3283.                             ufb = chkufb(i);
  3284.                             if(ufb != NULL)
  3285.                             {
  3286.                                 if(WaitForChar((BPTR)ufb->ufbfh,1))
  3287.                                 {
  3288.                                     gotSomething = TRUE;
  3289.                                     break;
  3290.                                 }
  3291.                             }
  3292.                         }
  3293.                     }
  3294.                 }
  3295.  
  3296.                 /* Did we get any input at all? */
  3297.                 if(gotSomething)
  3298.                 {
  3299.                     BOOL gotInput;
  3300.  
  3301.                     /* Now retest all files and remember
  3302.                      * those that had input.
  3303.                      */
  3304.                     for(i = 0 ; i <= max_file_fd ; i++)
  3305.                     {
  3306.                         gotInput = FALSE;
  3307.  
  3308.                         if(FD_ISSET(i,&file_read_fds) ||
  3309.                            FD_ISSET(i,&file_write_fds) ||
  3310.                            FD_ISSET(i,&file_except_fds))
  3311.                         {
  3312.                             ufb = chkufb(i);
  3313.                             if(ufb != NULL)
  3314.                             {
  3315.                                 /* Does this one have input? */
  3316.                                 gotInput = WaitForChar((BPTR)ufb->ufbfh,1);
  3317.                             }
  3318.                         }
  3319.  
  3320.                         if(gotInput)
  3321.                         {
  3322.                             /* Mark one more descriptor as
  3323.                              * having input.
  3324.                              */
  3325.                             result++;
  3326.                         }
  3327.                         else
  3328.                         {
  3329.                             /* Mark this descriptor as
  3330.                              * not having any input.
  3331.                              */
  3332.                             FD_CLR(i,&file_read_fds);
  3333.                             FD_CLR(i,&file_write_fds);
  3334.                             FD_CLR(i,&file_except_fds);
  3335.                         }
  3336.                     }
  3337.                 }
  3338.  
  3339.                 /* Did we get any input? If so, stop polling. */
  3340.                 if(result > 0)
  3341.                     break;
  3342.  
  3343.                 /* If a timeout was set, check if we are already
  3344.                  * beyond the point of time when we should have
  3345.                  * stopped polling.
  3346.                  */
  3347.                 if(timeout != NULL)
  3348.                 {
  3349.                     struct timeval now;
  3350.  
  3351.                     GetSysTime((APTR)&now);
  3352.  
  3353.                     if((-CmpTime((APTR)&now,(APTR)&stopWhen)) >= 0)
  3354.                         break;
  3355.                 }
  3356.             }
  3357.         }
  3358.         else
  3359.         {
  3360.             ULONG breakMask;
  3361.  
  3362.             if(AllowBreak)
  3363.                 breakMask = SIGBREAKF_CTRL_C;
  3364.             else
  3365.                 breakMask = 0;
  3366.  
  3367.             result = WaitSelect(max_socket_fd+1,&socket_read_fds,&socket_write_fds,&socket_except_fds,timeout,&breakMask);
  3368.             if((result < 0 && errno == EINTR) || FLAG_IS_SET(breakMask,SIGBREAKF_CTRL_C))
  3369.                 raise(SIGINT);
  3370.         }
  3371.     }
  3372.     else
  3373.     {
  3374.         /* Wait for file input? */
  3375.         if(max_file_fd != -1 && (timeout == NULL || timeout->tv_secs > 0 || timeout->tv_micro > 0))
  3376.         {
  3377.             struct timeval stopWhen;
  3378.             BOOL gotSomething;
  3379.             int i;
  3380.  
  3381.             if(timeout != NULL)
  3382.             {
  3383.                 GetSysTime((APTR)&stopWhen);
  3384.                 AddTime((APTR)&stopWhen,(APTR)timeout);
  3385.             }
  3386.             else
  3387.             {
  3388.                 memset(&stopWhen,0,sizeof(stopWhen));
  3389.             }
  3390.  
  3391.             while(TRUE)
  3392.             {
  3393.                 chkabort();
  3394.  
  3395.                 Delay(1);
  3396.  
  3397.                 gotSomething = FALSE;
  3398.                 for(i = 0 ; i <= max_file_fd ; i++)
  3399.                 {
  3400.                     if(FD_ISSET(i,&file_read_fds) ||
  3401.                        FD_ISSET(i,&file_write_fds) ||
  3402.                        FD_ISSET(i,&file_except_fds))
  3403.                     {
  3404.                         ufb = chkufb(i);
  3405.                         if(ufb != NULL)
  3406.                         {
  3407.                             if(WaitForChar((BPTR)ufb->ufbfh,1))
  3408.                             {
  3409.                                 gotSomething = TRUE;
  3410.                                 break;
  3411.                             }
  3412.                         }
  3413.                     }
  3414.                 }
  3415.  
  3416.                 if(gotSomething)
  3417.                 {
  3418.                     BOOL gotInput;
  3419.  
  3420.                     for(i = 0 ; i <= max_file_fd ; i++)
  3421.                     {
  3422.                         gotInput = FALSE;
  3423.  
  3424.                         if(FD_ISSET(i,&file_read_fds) ||
  3425.                            FD_ISSET(i,&file_write_fds) ||
  3426.                            FD_ISSET(i,&file_except_fds))
  3427.                         {
  3428.                             ufb = chkufb(i);
  3429.                             if(ufb != NULL)
  3430.                             {
  3431.                                 /* Does this one have input? */
  3432.                                 gotInput = WaitForChar((BPTR)ufb->ufbfh,1);
  3433.                             }
  3434.                         }
  3435.  
  3436.                         if(gotInput)
  3437.                         {
  3438.                             result++;
  3439.                         }
  3440.                         else
  3441.                         {
  3442.                             FD_CLR(i,&file_read_fds);
  3443.                             FD_CLR(i,&file_write_fds);
  3444.                             FD_CLR(i,&file_except_fds);
  3445.                         }
  3446.                     }
  3447.                 }
  3448.  
  3449.                 if(result > 0)
  3450.                     break;
  3451.  
  3452.                 if(timeout != NULL)
  3453.                 {
  3454.                     struct timeval now;
  3455.  
  3456.                     GetSysTime((APTR)&now);
  3457.  
  3458.                     if((-CmpTime((APTR)&now,(APTR)&stopWhen)) >= 0)
  3459.                         break;
  3460.                 }
  3461.             }
  3462.         }
  3463.     }
  3464.  
  3465.     /* The descriptor sets remain unchanged in
  3466.      * case of error.
  3467.      */
  3468.     if(result >= 0)
  3469.     {
  3470.         RemapDescriptorSets(&socket_read_fds,    max_socket_fd,    &file_read_fds,        max_file_fd,    read_fds,    num_fds);
  3471.         RemapDescriptorSets(&socket_write_fds,    max_socket_fd,    &file_write_fds,    max_file_fd,    write_fds,    num_fds);
  3472.         RemapDescriptorSets(&socket_except_fds,    max_socket_fd,    &file_except_fds,    max_file_fd,    except_fds,    num_fds);
  3473.     }
  3474.  
  3475.     RETURN(result);
  3476.     return(result);
  3477. }
  3478.  
  3479. /******************************************************************************/
  3480.  
  3481. int
  3482. amiga_sendto(int sockfd,VOID *buff,int len,int flags,struct sockaddr *to,int tolen)
  3483. {
  3484.     struct UFB * ufb;
  3485.     int result = ERROR;
  3486.  
  3487.     chkabort();
  3488.  
  3489.     ASSERT(buff != NULL && to != NULL);
  3490.  
  3491.     ENTER();
  3492.     SHOWVALUE(sockfd);
  3493.     SHOWVALUE(buff);
  3494.     SHOWVALUE(len);
  3495.     SHOWVALUE(flags);
  3496.     SHOWVALUE(to);
  3497.     SHOWVALUE(tolen);
  3498.  
  3499.     ufb = chkufb(sockfd);
  3500.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3501.         result = sendto(ufb->ufbfh,buff,len,flags,to,tolen);
  3502.     else
  3503.         errno = ENOTSOCK;
  3504.  
  3505.     RETURN(result);
  3506.     return(result);
  3507. }
  3508.  
  3509. /******************************************************************************/
  3510.  
  3511. int
  3512. amiga_setsockopt(int sockfd,int level,int optname,VOID *optval,int optlen)
  3513. {
  3514.     struct UFB * ufb;
  3515.     int result = ERROR;
  3516.  
  3517.     chkabort();
  3518.  
  3519.     ASSERT(optval != NULL);
  3520.  
  3521.     ENTER();
  3522.     SHOWVALUE(sockfd);
  3523.     SHOWVALUE(level);
  3524.     SHOWVALUE(optname);
  3525.     SHOWVALUE(optval);
  3526.     SHOWVALUE(optlen);
  3527.  
  3528.     ufb = chkufb(sockfd);
  3529.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3530.         result = setsockopt(ufb->ufbfh,level,optname,optval,optlen);
  3531.     else
  3532.         errno = ENOTSOCK;
  3533.  
  3534.     RETURN(result);
  3535.     return(result);
  3536. }
  3537.  
  3538. /******************************************************************************/
  3539.  
  3540. int
  3541. amiga_socket(int domain,int type,int protocol)
  3542. {
  3543.     int result = ERROR;
  3544.     int fd;
  3545.  
  3546.     chkabort();
  3547.  
  3548.     ENTER();
  3549.     SHOWVALUE(domain);
  3550.     SHOWVALUE(type);
  3551.     SHOWVALUE(protocol);
  3552.  
  3553.     /* We open a regular file that is guaranteed to
  3554.      * open in any case and then attach a socket
  3555.      * in place of the original file handle.
  3556.      */
  3557.     fd = open("NIL:",O_RDWR,0777);
  3558.     if(fd != -1)
  3559.     {
  3560.         struct UFB * ufb;
  3561.  
  3562.         ufb = chkufb(fd);
  3563.         if(ufb != NULL)
  3564.         {
  3565.             /* Save the original file handle value. */
  3566.             if(SaveDescriptor(ufb))
  3567.             {
  3568.                 int sockfd;
  3569.  
  3570.                 /* Now create the real socket. */
  3571.                 sockfd = socket(domain,type,protocol);
  3572.                 if(sockfd != -1)
  3573.                 {
  3574.                     /* Put the socket in place of the file handle. */
  3575.                     SET_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  3576.                     ufb->ufbfh = sockfd;
  3577.  
  3578.                     result = fd;
  3579.                 }
  3580.                 else
  3581.                 {
  3582.                     close(fd);
  3583.                 }
  3584.             }
  3585.             else
  3586.             {
  3587.                 close(fd);
  3588.                 errno = ENOMEM;
  3589.             }
  3590.         }
  3591.         else
  3592.         {
  3593.             close(fd);
  3594.             errno = EBADF;
  3595.         }
  3596.     }
  3597.  
  3598.     RETURN(result);
  3599.     return(result);
  3600. }
  3601.  
  3602. /******************************************************************************/
  3603.  
  3604. int
  3605. amiga_write(int fd,VOID *data,unsigned int size)
  3606. {
  3607.     struct UFB * ufb;
  3608.     int result;
  3609.  
  3610.     chkabort();
  3611.  
  3612.     ASSERT(data != NULL);
  3613.  
  3614.     ENTER();
  3615.     SHOWVALUE(fd);
  3616.     SHOWVALUE(data);
  3617.     SHOWVALUE(size);
  3618.  
  3619.     ufb = chkufb(fd);
  3620.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3621.     {
  3622.         result = send(ufb->ufbfh,data,size,0);
  3623.     }
  3624.     else
  3625.     {
  3626.         ForbidDOS();
  3627.         result = write(fd,data,size);
  3628.         PermitDOS();
  3629.     }
  3630.  
  3631.     RETURN(result);
  3632.     return(result);
  3633. }
  3634.  
  3635. /******************************************************************************/
  3636.  
  3637. STATIC VOID
  3638. ConvertFileInfoToStat(
  3639.     struct MsgPort * port,
  3640.     struct FileInfoBlock * fib,
  3641.     struct stat * st)
  3642. {
  3643.     ULONG flags;
  3644.     int mode;
  3645.     long time;
  3646.  
  3647.     /* This routine converts the contents of a FileInfoBlock
  3648.      * into information to fill a Unix-like stat data structure
  3649.      * with.
  3650.      */
  3651.     flags = fib->fib_Protection ^ (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  3652.  
  3653.     if(FIB_IS_DRAWER(fib))
  3654.         mode = S_IFDIR;
  3655.     else
  3656.         mode = S_IFREG;
  3657.  
  3658.     if(FLAG_IS_SET(flags,FIBF_READ))
  3659.         SET_FLAG(mode,S_IRUSR);
  3660.  
  3661.     if(FLAG_IS_SET(flags,FIBF_WRITE) && FLAG_IS_SET(flags,FIBF_DELETE))
  3662.         SET_FLAG(mode,S_IWUSR);
  3663.  
  3664.     if(FLAG_IS_SET(flags,FIBF_EXECUTE))
  3665.         SET_FLAG(mode,S_IXUSR);
  3666.  
  3667.  
  3668.     if(FLAG_IS_SET(flags,FIBF_GRP_READ))
  3669.         SET_FLAG(mode,S_IRGRP);
  3670.  
  3671.     if(FLAG_IS_SET(flags,FIBF_GRP_WRITE) && FLAG_IS_SET(flags,FIBF_GRP_DELETE))
  3672.         SET_FLAG(mode,S_IWGRP);
  3673.  
  3674.     if(FLAG_IS_SET(flags,FIBF_GRP_EXECUTE))
  3675.         SET_FLAG(mode,S_IXGRP);
  3676.  
  3677.  
  3678.     if(FLAG_IS_SET(flags,FIBF_OTR_READ))
  3679.         SET_FLAG(mode,S_IROTH);
  3680.  
  3681.     if(FLAG_IS_SET(flags,FIBF_OTR_WRITE) && FLAG_IS_SET(flags,FIBF_OTR_DELETE))
  3682.         SET_FLAG(mode,S_IWOTH);
  3683.  
  3684.     if(FLAG_IS_SET(flags,FIBF_OTR_EXECUTE))
  3685.         SET_FLAG(mode,S_IXOTH);
  3686.  
  3687.     time = fib->fib_Date.ds_Days * 24*60*60 +
  3688.            fib->fib_Date.ds_Minute * 60 +
  3689.           (fib->fib_Date.ds_Tick / TICKS_PER_SECOND);
  3690.  
  3691.     memset(st,0,sizeof(*st));
  3692.  
  3693.     st->st_dev        = (u_long)port;
  3694.     st->st_ino        = fib->fib_DiskKey;
  3695.     st->st_mode        = mode;
  3696.     st->st_mtime    = UNIX_TIME_OFFSET + time + 60*MinutesWest;    /* translate from local time to UTC */
  3697.     st->st_atime    = st->st_mtime;
  3698.     st->st_ctime    = st->st_mtime;
  3699.     st->st_uid        = fib->fib_OwnerUID;
  3700.     st->st_gid        = fib->fib_OwnerGID;
  3701.  
  3702.     if(FIB_IS_FILE(fib))
  3703.     {
  3704.         st->st_nlink = 1;
  3705.         st->st_size  = fib->fib_Size;
  3706.     }
  3707.     else
  3708.     {
  3709.         st->st_nlink = 2;
  3710.     }
  3711. }
  3712.  
  3713. int
  3714. amiga_stat(char *name, struct stat *st)
  3715. {
  3716.     char localName[MAX_FILENAME_LEN];
  3717.     struct MangleInfo mi;
  3718.     int result = ERROR;
  3719.  
  3720.     chkabort();
  3721.  
  3722.     ASSERT(name != NULL && st != NULL);
  3723.  
  3724.     ENTER();
  3725.     SHOWSTRING(name);
  3726.     SHOWVALUE(st);
  3727.  
  3728.     if(TranslateRelativePath(&name,localName,sizeof(localName)) == OK)
  3729.     {
  3730.         char * originalName = name;
  3731.  
  3732.         if(MangleName(&name,&mi) == OK)
  3733.         {
  3734.             int len;
  3735.  
  3736.             SHOWSTRING(name);
  3737.             SHOWSTRING(originalName);
  3738.  
  3739.             len = strlen(name);
  3740.             if((strcmp(originalName,"/") == SAME) || (len > 1 && name[len-2] == ':' && name[len-1] == '/'))
  3741.             {
  3742.                 struct timeval now;
  3743.  
  3744.                 SHOWMSG("this is the virtual root directory");
  3745.  
  3746.                 /* This must be our virtual root directory.
  3747.                  * Make something up.
  3748.                  */
  3749.                 memset(st,0,sizeof(*st));
  3750.                 GetSysTime((APTR)&now);
  3751.  
  3752.                 /* Nobody may write to this "directory". */
  3753.                 st->st_dev        = (u_long)"Virtual Root Directory";
  3754.                 st->st_ino        = 1;
  3755.                 st->st_mode        = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
  3756.                 st->st_nlink    = 2;
  3757.                 st->st_mtime    = UNIX_TIME_OFFSET + now.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  3758.                 st->st_atime    = st->st_mtime;
  3759.                 st->st_ctime    = st->st_mtime;
  3760.  
  3761.                 result = OK;
  3762.             }
  3763.             else
  3764.             {
  3765.                 BPTR fileLock;
  3766.  
  3767.                 SHOWMSG("this is a drawer or a file");
  3768.  
  3769.                 ForbidDOS();
  3770.  
  3771.                 fileLock = Lock((STRPTR)name,SHARED_LOCK);
  3772.                 if(fileLock != ZERO)
  3773.                 {
  3774.                     struct FileInfoBlock __aligned fib;
  3775.  
  3776.                     if(Examine(fileLock,&fib))
  3777.                     {
  3778.                         BPTR parentDir;
  3779.  
  3780.                         /* Check if this is the root directory. */
  3781.                         parentDir = ParentDir(fileLock);
  3782.                         if(parentDir != ZERO)
  3783.                         {
  3784.                             /* This is not the root directory. */
  3785.                             UnLock(parentDir);
  3786.                         }
  3787.                         else
  3788.                         {
  3789.                             /* So this is the root directory. Make sure
  3790.                              * that we return proper protection bits for
  3791.                              * it, i.e. that the directory is always
  3792.                              * readable, writable, etc. This may be
  3793.                              * necessary since on the Amiga, root
  3794.                              * directories cannot have any protection
  3795.                              * bits set. Note that the "deletable"
  3796.                              * bits don't make much sense, but then
  3797.                              * these bits work together with the
  3798.                              * writable bits. The lowest four bits
  3799.                              * remain zero, which enables them all.
  3800.                              */
  3801.                             fib.fib_Protection = FIBF_OTR_READ |
  3802.                                                  FIBF_OTR_WRITE |
  3803.                                                  FIBF_OTR_EXECUTE |
  3804.                                                  FIBF_OTR_DELETE |
  3805.                                                  FIBF_GRP_READ |
  3806.                                                  FIBF_GRP_WRITE |
  3807.                                                  FIBF_GRP_EXECUTE |
  3808.                                                  FIBF_GRP_DELETE;
  3809.                         }
  3810.  
  3811.                         ConvertFileInfoToStat(((struct FileLock *)BADDR(fileLock))->fl_Task,&fib,st);
  3812.  
  3813.                         result = OK;
  3814.                     }
  3815.                     else
  3816.                     {
  3817.                         MapIoErrToErrno();
  3818.                     }
  3819.  
  3820.                     UnLock(fileLock);
  3821.                 }
  3822.                 else
  3823.                 {
  3824.                     LONG error = IoErr();
  3825.  
  3826.                     if(error == ERROR_OBJECT_IN_USE)
  3827.                     {
  3828.                         char parentName[MAX_FILENAME_LEN];
  3829.                         BPTR parentLock;
  3830.  
  3831.                         strcpy(parentName,name);
  3832.                         (*PathPart(parentName) = '\0');
  3833.  
  3834.                         parentLock = Lock(parentName,SHARED_LOCK);
  3835.                         if(parentLock != ZERO)
  3836.                         {
  3837.                             struct FileInfoBlock __aligned fib;
  3838.  
  3839.                             if(Examine(parentLock,&fib))
  3840.                             {
  3841.                                 STRPTR onlyFileName = FilePart(name);
  3842.  
  3843.                                 while(ExNext(parentLock,&fib))
  3844.                                 {
  3845.                                     if(Stricmp(fib.fib_FileName,onlyFileName) == SAME)
  3846.                                     {
  3847.                                         ConvertFileInfoToStat(((struct FileLock *)BADDR(parentLock))->fl_Task,&fib,st);
  3848.  
  3849.                                         result = OK;
  3850.                                         error = OK;
  3851.                                         break;
  3852.                                     }
  3853.                                 }
  3854.                             }
  3855.  
  3856.                             UnLock(parentLock);
  3857.                         }
  3858.                     }
  3859.  
  3860.                     if(error != OK)
  3861.                     {
  3862.                         SetIoErr(error);
  3863.  
  3864.                         MapIoErrToErrno();
  3865.                     }
  3866.                 }
  3867.  
  3868.                 PermitDOS();
  3869.             }
  3870.  
  3871.             if(result == OK)
  3872.             {
  3873.                 SHOWVALUE(st->st_dev);
  3874.                 SHOWVALUE(st->st_ino);
  3875.                 SHOWVALUE(st->st_size);
  3876.                 SHOWVALUE(st->st_nlink);
  3877.                 SHOWVALUE(st->st_mode);
  3878.                 SHOWVALUE(st->st_mtime);
  3879.                 SHOWVALUE(st->st_atime);
  3880.                 SHOWVALUE(st->st_ctime);
  3881.                 SHOWVALUE(st->st_uid);
  3882.                 SHOWVALUE(st->st_gid);
  3883.             }
  3884.             else
  3885.             {
  3886.                 SHOWVALUE(errno);
  3887.             }
  3888.  
  3889.             UnmangleName(&name,&mi);
  3890.         }
  3891.     }
  3892.  
  3893.     RETURN(result);
  3894.     return(result);
  3895. }
  3896.  
  3897. int
  3898. amiga_lstat(char *name, struct stat *statstruct)
  3899. {
  3900.     int result;
  3901.  
  3902.     chkabort();
  3903.  
  3904.     ENTER();
  3905.     SHOWSTRING(name);
  3906.     SHOWVALUE(statstruct);
  3907.  
  3908.     result = amiga_stat(name,statstruct);
  3909.  
  3910.     RETURN(result);
  3911.     return(result);
  3912. }
  3913.  
  3914. int
  3915. amiga_fstat(int fd,struct stat * st)
  3916. {
  3917.     struct UFB * ufb;
  3918.     int result = ERROR;
  3919.  
  3920.     chkabort();
  3921.  
  3922.     ASSERT(st != NULL);
  3923.  
  3924.     ENTER();
  3925.     SHOWVALUE(fd);
  3926.     SHOWVALUE(st);
  3927.  
  3928.     ufb = chkufb(fd);
  3929.     if(ufb != NULL)
  3930.     {
  3931.         if(FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  3932.         {
  3933.             long value;
  3934.             long size = sizeof(value);
  3935.  
  3936.             memset(st,0,sizeof(*st));
  3937.  
  3938.             st->st_dev    = (u_long)SocketBase;
  3939.             st->st_mode    = S_IFSOCK | S_IRUSR | S_IWUSR;
  3940.             st->st_uid    = geteuid();
  3941.             st->st_gid    = getegid();
  3942.  
  3943.             if(getsockopt(fd,SOL_SOCKET,SO_SNDBUF,&value,&size) == 0)
  3944.                 st->st_blksize = value;
  3945.  
  3946.             result = OK;
  3947.         }
  3948.         else
  3949.         {
  3950.             struct FileHandle * fileHandle = BADDR(ufb->ufbfh);
  3951.  
  3952.             /* Make sure that this stream doesn't
  3953.              * really refer to "NIL:".
  3954.              */
  3955.             if(fileHandle->fh_Type != NULL)
  3956.             {
  3957.                 struct FileInfoBlock __aligned fib;
  3958.  
  3959.                 ForbidDOS();
  3960.  
  3961.                 if(ExamineFH(ufb->ufbfh,&fib))
  3962.                 {
  3963.                     ConvertFileInfoToStat(fileHandle->fh_Type,&fib,st);
  3964.  
  3965.                     result = OK;
  3966.                 }
  3967.                 else
  3968.                 {
  3969.                     MapIoErrToErrno();
  3970.                 }
  3971.  
  3972.                 PermitDOS();
  3973.             }
  3974.             else
  3975.             {
  3976.                 struct timeval tv;
  3977.  
  3978.                 /* Make up some phony data for a NIL: file handle. */
  3979.                 memset(st,0,sizeof(*st));
  3980.  
  3981.                 GetSysTime((APTR)&tv);
  3982.  
  3983.                 st->st_dev        = (u_long)0;
  3984.                 st->st_mode        = S_IFREG | S_IRUSR | S_IWUSR;
  3985.                 st->st_mtime    = UNIX_TIME_OFFSET + tv.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  3986.                 st->st_atime    = st->st_mtime;
  3987.                 st->st_ctime    = st->st_mtime;
  3988.  
  3989.                 result = OK;
  3990.             }
  3991.         }
  3992.     }
  3993.     else
  3994.     {
  3995.         errno = EBADF;
  3996.     }
  3997.  
  3998.     RETURN(result);
  3999.     return(result);
  4000. }
  4001.  
  4002. /******************************************************************************/
  4003.  
  4004. int
  4005. amiga_chmod(char *name,int mode)
  4006. {
  4007.     struct MangleInfo mi;
  4008.     ULONG flags = 0;
  4009.     int result = ERROR;
  4010.  
  4011.     chkabort();
  4012.  
  4013.     ASSERT(name != NULL);
  4014.  
  4015.     ENTER();
  4016.     SHOWSTRING(name);
  4017.     SHOWVALUE(mode);
  4018.  
  4019.     /* Convert the file access modes into
  4020.      * Amiga typical protection bits.
  4021.      */
  4022.     if(FLAG_IS_SET(mode,S_IRUSR))
  4023.         SET_FLAG(flags,FIBF_READ);
  4024.  
  4025.     if(FLAG_IS_SET(mode,S_IWUSR))
  4026.     {
  4027.         SET_FLAG(flags,FIBF_WRITE);
  4028.         SET_FLAG(flags,FIBF_DELETE);
  4029.     }
  4030.  
  4031.     if(FLAG_IS_SET(mode,S_IXUSR))
  4032.         SET_FLAG(flags,FIBF_EXECUTE);
  4033.  
  4034.  
  4035.     if(FLAG_IS_SET(mode,S_IRGRP))
  4036.         SET_FLAG(flags,FIBF_GRP_READ);
  4037.  
  4038.     if(FLAG_IS_SET(mode,S_IWGRP))
  4039.     {
  4040.         SET_FLAG(flags,FIBF_GRP_WRITE);
  4041.         SET_FLAG(flags,FIBF_GRP_DELETE);
  4042.     }
  4043.  
  4044.     if(FLAG_IS_SET(mode,S_IXGRP))
  4045.         SET_FLAG(flags,FIBF_GRP_EXECUTE);
  4046.  
  4047.  
  4048.     if(FLAG_IS_SET(mode,S_IROTH))
  4049.         SET_FLAG(flags,FIBF_OTR_READ);
  4050.  
  4051.     if(FLAG_IS_SET(mode,S_IWOTH))
  4052.     {
  4053.         SET_FLAG(flags,FIBF_OTR_WRITE);
  4054.         SET_FLAG(flags,FIBF_OTR_DELETE);
  4055.     }
  4056.  
  4057.     if(FLAG_IS_SET(mode,S_IXOTH))
  4058.         SET_FLAG(flags,FIBF_OTR_EXECUTE);
  4059.  
  4060.     flags ^= (FIBF_READ|FIBF_WRITE|FIBF_EXECUTE|FIBF_DELETE);
  4061.  
  4062.     if(MangleName(&name,&mi) == OK)
  4063.     {
  4064.         ForbidDOS();
  4065.  
  4066.         if(SetProtection(name,flags))
  4067.         {
  4068.             result = OK;
  4069.         }
  4070.         else
  4071.         {
  4072.             LONG error = IoErr();
  4073.  
  4074.             /* Note sure about this one; is it really that important
  4075.              * that the file attribute change succeeds? This is a definite
  4076.              * FIXME.
  4077.              */
  4078.             if(error == ERROR_OBJECT_IN_USE)
  4079.             {
  4080.                 result = OK;
  4081.             }
  4082.             else
  4083.             {
  4084.                 SetIoErr(error);
  4085.  
  4086.                 MapIoErrToErrno();
  4087.             }
  4088.         }
  4089.  
  4090.         PermitDOS();
  4091.  
  4092.         UnmangleName(&name,&mi);
  4093.     }
  4094.  
  4095.     RETURN(result);
  4096.     return(result);
  4097. }
  4098.  
  4099. /******************************************************************************/
  4100.  
  4101. int
  4102. amiga_dup(int fd)
  4103. {
  4104.     struct UFB * ufb;
  4105.     int result = ERROR;
  4106.  
  4107.     chkabort();
  4108.  
  4109.     ENTER();
  4110.     SHOWVALUE(fd);
  4111.  
  4112.     ufb = chkufb(fd);
  4113.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  4114.     {
  4115.         fd = open("NIL:",O_RDWR,0777);
  4116.         if(fd != -1)
  4117.         {
  4118.             struct UFB * ufb2;
  4119.  
  4120.             ufb2 = chkufb(fd);
  4121.             if(ufb2 != NULL)
  4122.             {
  4123.                 if(SaveDescriptor(ufb2))
  4124.                 {
  4125.                     int sockfd;
  4126.  
  4127.                     sockfd = Dup2Socket(ufb->ufbfh,-1);
  4128.                     if(sockfd != -1)
  4129.                     {
  4130.                         SET_FLAG(ufb2->ufbflg,UFB_IS_SOCKET);
  4131.                         ufb2->ufbfh = sockfd;
  4132.  
  4133.                         result = fd;
  4134.                     }
  4135.                     else
  4136.                     {
  4137.                         close(fd);
  4138.                     }
  4139.                 }
  4140.                 else
  4141.                 {
  4142.                     close(fd);
  4143.                     errno = ENOMEM;
  4144.                 }
  4145.             }
  4146.             else
  4147.             {
  4148.                 close(fd);
  4149.                 errno = EBADF;
  4150.             }
  4151.         }
  4152.     }
  4153.     else
  4154.     {
  4155.         errno = ENOTSOCK;
  4156.     }
  4157.  
  4158.     RETURN(result);
  4159.     return(result);
  4160. }
  4161.  
  4162. /******************************************************************************/
  4163.  
  4164. int
  4165. amiga_dup2(int old_fd,int new_fd)
  4166. {
  4167.     struct UFB * old_ufb;
  4168.     struct UFB * new_ufb;
  4169.     int result = ERROR;
  4170.  
  4171.     chkabort();
  4172.  
  4173.     ENTER();
  4174.     SHOWVALUE(old_fd);
  4175.     SHOWVALUE(new_fd);
  4176.  
  4177.     old_ufb = chkufb(old_fd);
  4178.     new_ufb = chkufb(new_fd);
  4179.  
  4180.     if(old_ufb != NULL && FLAG_IS_SET(old_ufb->ufbflg,UFB_IS_SOCKET) && new_ufb != NULL)
  4181.     {
  4182.         int sockfd;
  4183.  
  4184.         if(FLAG_IS_SET(new_ufb->ufbflg,UFB_IS_SOCKET))
  4185.         {
  4186.             CloseSocket(new_ufb->ufbfh);
  4187.             sockfd = Dup2Socket(old_ufb->ufbfh,new_ufb->ufbfh);
  4188.         }
  4189.         else
  4190.         {
  4191.             if(SaveDescriptor(new_ufb))
  4192.             {
  4193.                 sockfd = Dup2Socket(old_ufb->ufbfh,-1);
  4194.             }
  4195.             else
  4196.             {
  4197.                 sockfd = -1;
  4198.                 errno = ENOMEM;
  4199.             }
  4200.         }
  4201.  
  4202.         if(sockfd != -1)
  4203.         {
  4204.             SET_FLAG(new_ufb->ufbflg,UFB_IS_SOCKET);
  4205.             new_ufb->ufbfh = sockfd;
  4206.  
  4207.             result = new_fd;
  4208.         }
  4209.     }
  4210.     else
  4211.     {
  4212.         errno = ENOTSOCK;
  4213.     }
  4214.  
  4215.     RETURN(result);
  4216.     return(result);
  4217. }
  4218.  
  4219. /******************************************************************************/
  4220.  
  4221. int
  4222. amiga_chown(char *name,uid_t uid,gid_t gid)
  4223. {
  4224.     struct MangleInfo mi;
  4225.     int result = ERROR;
  4226.  
  4227.     chkabort();
  4228.  
  4229.     ASSERT(name != NULL);
  4230.  
  4231.     ENTER();
  4232.     SHOWSTRING(name);
  4233.     SHOWVALUE(uid);
  4234.     SHOWVALUE(gid);
  4235.  
  4236.     if(MangleName(&name,&mi) == OK)
  4237.     {
  4238.         /* AmigaDOS 3.0 and up have a SetOwner() call. */
  4239.         if(DOSBase->lib_Version >= 39)
  4240.         {
  4241.             if(SetOwner(name,(((LONG)uid) << 16) | gid))
  4242.                 result = OK;
  4243.             else
  4244.                 MapIoErrToErrno();
  4245.         }
  4246.         else
  4247.         {
  4248.             struct DevProc * dvp;
  4249.  
  4250.             /* For 2.04 and 2.1 we'll have to do this
  4251.              * manually...
  4252.              */
  4253.             dvp = GetDeviceProc(name,NULL);
  4254.             if(dvp != NULL)
  4255.             {
  4256.                 char __aligned newName[MAX_BSTR_LEN];
  4257.  
  4258.                 newName[0] = strlen(name);
  4259.                 strncpy(&newName[1],name,newName[0]);
  4260.  
  4261.                 /* This is almost identical in operation to ACTION_SET_PROTECTION. */
  4262.                 if(DoPkt(dvp->dvp_Port,ACTION_SET_OWNER,dvp->dvp_Lock,MKBADDR(newName),(((LONG)uid) << 16) | gid,0,0))
  4263.                     result = OK;
  4264.                 else
  4265.                     MapIoErrToErrno();
  4266.  
  4267.                 FreeDeviceProc(dvp);
  4268.             }
  4269.             else
  4270.             {
  4271.                 MapIoErrToErrno();
  4272.             }
  4273.         }
  4274.  
  4275.         UnmangleName(&name,&mi);
  4276.     }
  4277.  
  4278.     RETURN(result);
  4279.     return(result);
  4280. }
  4281.  
  4282. /******************************************************************************/
  4283.  
  4284. int
  4285. amiga_setegid(gid_t g)
  4286. {
  4287.     int result;
  4288.  
  4289.     chkabort();
  4290.  
  4291.     ENTER();
  4292.     SHOWVALUE(g);
  4293.  
  4294.     result = setregid(-1,g);
  4295.  
  4296.     RETURN(result);
  4297.     return(result);
  4298. }
  4299.  
  4300. /******************************************************************************/
  4301.  
  4302. int
  4303. amiga_seteuid(uid_t u)
  4304. {
  4305.     int result;
  4306.  
  4307.     chkabort();
  4308.  
  4309.     ENTER();
  4310.     SHOWVALUE(u);
  4311.     result = setreuid(-1,u);
  4312.  
  4313.     RETURN(result);
  4314.     return(result);
  4315. }
  4316.  
  4317. /******************************************************************************/
  4318.  
  4319. int
  4320. amiga_gettimeofday(struct timeval *tv)
  4321. {
  4322.     chkabort();
  4323.  
  4324.     ENTER();
  4325.     SHOWVALUE(tv);
  4326.  
  4327.     if(tv != NULL)
  4328.     {
  4329.         GetSysTime((APTR)tv);
  4330.         tv->tv_secs += UNIX_TIME_OFFSET + 60*MinutesWest;    /* translate from local time to UTC */
  4331.  
  4332.         SHOWVALUE(tv->tv_secs);
  4333.         SHOWVALUE(tv->tv_micro);
  4334.     }
  4335.  
  4336.     RETURN(0);
  4337.     return(0);
  4338. }
  4339.  
  4340. /******************************************************************************/
  4341.  
  4342. int
  4343. amiga_utime(char *name,struct utimbuf *time)
  4344. {
  4345.     struct MangleInfo mi;
  4346.     struct DateStamp ds;
  4347.     int result = ERROR;
  4348.  
  4349.     chkabort();
  4350.  
  4351.     ASSERT(name != NULL);
  4352.  
  4353.     ENTER();
  4354.     SHOWSTRING(name);
  4355.     SHOWVALUE(time);
  4356.  
  4357.     /* Use the current time? */
  4358.     if(time == NULL)
  4359.     {
  4360.         DateStamp(&ds);
  4361.     }
  4362.     else
  4363.     {
  4364.         ULONG seconds;
  4365.  
  4366.         /* Convert the time given. */
  4367.         if(time->modtime < (UNIX_TIME_OFFSET + 60*MinutesWest))
  4368.             seconds = 0;
  4369.         else
  4370.             seconds = time->modtime - (UNIX_TIME_OFFSET + 60*MinutesWest);    /* translate from UTC to local time */
  4371.  
  4372.         ds.ds_Days        = (seconds / (24*60*60));
  4373.         ds.ds_Minute    = (seconds % (24*60*60)) / 60;
  4374.         ds.ds_Tick        = (seconds               % 60) * TICKS_PER_SECOND;
  4375.     }
  4376.  
  4377.     if(MangleName(&name,&mi) == OK)
  4378.     {
  4379.         ForbidDOS();
  4380.  
  4381.         if(SetFileDate((STRPTR)name,&ds))
  4382.         {
  4383.             result = OK;
  4384.         }
  4385.         else
  4386.         {
  4387.             LONG error = IoErr();
  4388.  
  4389.             /* Note sure about this one; is it really that important
  4390.              * that the file date change succeeds? This is a definite
  4391.              * FIXME.
  4392.              */
  4393.             if(error == ERROR_OBJECT_IN_USE)
  4394.             {
  4395.                 result = OK;
  4396.             }
  4397.             else
  4398.             {
  4399.                 SetIoErr(error);
  4400.  
  4401.                 MapIoErrToErrno();
  4402.             }
  4403.         }
  4404.  
  4405.         PermitDOS();
  4406.  
  4407.         UnmangleName(&name,&mi);
  4408.     }
  4409.  
  4410.     RETURN(result);
  4411.     return(result);
  4412. }
  4413.  
  4414. /******************************************************************************/
  4415.  
  4416. VOID
  4417. amiga_sleep(unsigned int seconds)
  4418. {
  4419.     chkabort();
  4420.  
  4421.     ENTER();
  4422.     SHOWVALUE(seconds);
  4423.  
  4424.     if(seconds > 0)
  4425.     {
  4426.         ULONG timerSignal = (1UL << TimerPort->mp_SigBit);
  4427.         ULONG signalsReceived;
  4428.         ULONG signalsToWaitFor;
  4429.  
  4430.         TimerRequest->tr_node.io_Command    = TR_ADDREQUEST;
  4431.         TimerRequest->tr_time.tv_secs        = seconds;
  4432.         TimerRequest->tr_time.tv_micro        = 0;
  4433.  
  4434.         SetSignal(0,timerSignal);
  4435.         SendIO((struct IORequest *)TimerRequest);
  4436.  
  4437.         signalsToWaitFor = timerSignal;
  4438.         if(AllowBreak)
  4439.             signalsToWaitFor |= SIGBREAKF_CTRL_C;
  4440.  
  4441.         signalsReceived = Wait(signalsToWaitFor);
  4442.  
  4443.         /* Did we get a break signal while we were sleeping? */
  4444.         if(FLAG_IS_SET(signalsReceived,SIGBREAKF_CTRL_C))
  4445.         {
  4446.             if(CheckIO((struct IORequest *)TimerRequest) == BUSY)
  4447.                 AbortIO((struct IORequest *)TimerRequest);
  4448.  
  4449.             WaitIO((struct IORequest *)TimerRequest);
  4450.  
  4451.             /* And pull the brakes... */
  4452.             raise(SIGINT);
  4453.         }
  4454.  
  4455.         /* Proper termination. */
  4456.         if(FLAG_IS_SET(signalsReceived,timerSignal))
  4457.         {
  4458.             WaitIO((struct IORequest *)TimerRequest);
  4459.         }
  4460.     }
  4461.  
  4462.     LEAVE();
  4463. }
  4464.  
  4465. /******************************************************************************/
  4466.  
  4467. char *
  4468. amiga_crypt(char *key,char *salt)
  4469. {
  4470.     char *result;
  4471.  
  4472.     chkabort();
  4473.  
  4474.     ASSERT(key != NULL && salt != NULL);
  4475.  
  4476.     ENTER();
  4477.     SHOWSTRING(key);
  4478.     SHOWVALUE(salt);
  4479.     result = crypt(key,salt);
  4480.  
  4481.     RETURN(result);
  4482.     return(result);
  4483. }
  4484.  
  4485. /******************************************************************************/
  4486.  
  4487. char *
  4488. amiga_getpass(char *prompt)
  4489. {
  4490.     char *result;
  4491.  
  4492.     chkabort();
  4493.  
  4494.     ENTER();
  4495.     SHOWSTRING(prompt);
  4496.     result = getpass(prompt);
  4497.  
  4498.     RETURN(result);
  4499.     return(result);
  4500. }
  4501.  
  4502. /******************************************************************************/
  4503.  
  4504. int
  4505. amiga_setgid(gid_t id)
  4506. {
  4507.     int result;
  4508.  
  4509.     chkabort();
  4510.  
  4511.     ENTER();
  4512.     SHOWVALUE(id);
  4513.     result = setgid(id);
  4514.  
  4515.     RETURN(result);
  4516.     return(result);
  4517. }
  4518.  
  4519. /******************************************************************************/
  4520.  
  4521. int
  4522. amiga_setgroups(int ngroups,gid_t *groups)
  4523. {
  4524.     int result;
  4525.  
  4526.     chkabort();
  4527.  
  4528.     ASSERT(groups != NULL);
  4529.  
  4530.     ENTER();
  4531.     SHOWVALUE(ngroups);
  4532.     SHOWVALUE(groups);
  4533.  
  4534.     result = setgroups(ngroups,groups);
  4535.  
  4536.     RETURN(result);
  4537.     return(result);
  4538. }
  4539.  
  4540. /******************************************************************************/
  4541.  
  4542. gid_t
  4543. amiga_getgid(VOID)
  4544. {
  4545.     int result;
  4546.  
  4547.     chkabort();
  4548.  
  4549.     ENTER();
  4550.     result = getgid();
  4551.  
  4552.     RETURN(result);
  4553.     return(result);
  4554. }
  4555.  
  4556. /******************************************************************************/
  4557.  
  4558. struct group *
  4559. amiga_getgrgid(gid_t gid)
  4560. {
  4561.     struct group *result;
  4562.  
  4563.     chkabort();
  4564.  
  4565.     ENTER();
  4566.     SHOWVALUE(gid);
  4567.  
  4568.     result = getgrgid(gid);
  4569.  
  4570.     RETURN(result);
  4571.     return(result);
  4572. }
  4573.  
  4574. /******************************************************************************/
  4575.  
  4576. struct group *
  4577. amiga_getgrnam(char * name)
  4578. {
  4579.     struct group *result;
  4580.  
  4581.     chkabort();
  4582.  
  4583.     ASSERT(name != NULL);
  4584.  
  4585.     ENTER();
  4586.     SHOWSTRING(name);
  4587.  
  4588.     result = getgrnam(name);
  4589.  
  4590.     RETURN(result);
  4591.     return(result);
  4592. }
  4593.  
  4594. /******************************************************************************/
  4595.  
  4596. int
  4597. amiga_getgroups(int ngroups, gid_t *groups)
  4598. {
  4599.     int result;
  4600.  
  4601.     chkabort();
  4602.  
  4603.     ASSERT(groups != NULL);
  4604.  
  4605.     ENTER();
  4606.     SHOWVALUE(ngroups);
  4607.     SHOWVALUE(groups);
  4608.  
  4609.     result = getgroups(ngroups,groups);
  4610.  
  4611.     RETURN(result);
  4612.     return(result);
  4613. }
  4614.  
  4615. /******************************************************************************/
  4616.  
  4617. struct hostent *
  4618. amiga_gethostbyaddr(char *addr, int len, int type)
  4619. {
  4620.     struct hostent *result;
  4621.  
  4622.     chkabort();
  4623.  
  4624.     ASSERT(addr != NULL);
  4625.  
  4626.     ENTER();
  4627.     SHOWVALUE(addr);
  4628.     SHOWVALUE(len);
  4629.     SHOWVALUE(type);
  4630.  
  4631.     result = gethostbyaddr(addr,len,type);
  4632.  
  4633.     RETURN(result);
  4634.     return(result);
  4635. }
  4636.  
  4637. /******************************************************************************/
  4638.  
  4639. struct hostent *
  4640. amiga_gethostbyname(char *name)
  4641. {
  4642.     struct hostent *result;
  4643.  
  4644.     chkabort();
  4645.  
  4646.     ASSERT(name != NULL);
  4647.  
  4648.     ENTER();
  4649.     SHOWSTRING(name);
  4650.  
  4651.     result = gethostbyname(name);
  4652.  
  4653.     RETURN(result);
  4654.     return(result);
  4655. }
  4656.  
  4657. /******************************************************************************/
  4658.  
  4659. struct netent *
  4660. amiga_getnetbyname(char *name)
  4661. {
  4662.     struct netent *result;
  4663.  
  4664.     chkabort();
  4665.  
  4666.     ASSERT(name != NULL);
  4667.  
  4668.     ENTER();
  4669.     SHOWSTRING(name);
  4670.  
  4671.     result = getnetbyname(name);
  4672.  
  4673.     RETURN(result);
  4674.     return(result);
  4675. }
  4676.  
  4677. /******************************************************************************/
  4678.  
  4679. int
  4680. amiga_gethostname(char *hostname,int size)
  4681. {
  4682.     int result;
  4683.  
  4684.     chkabort();
  4685.  
  4686.     ASSERT(hostname != NULL);
  4687.  
  4688.     ENTER();
  4689.     SHOWVALUE(hostname);
  4690.     SHOWVALUE(size);
  4691.  
  4692.     result = gethostname(hostname,size);
  4693.  
  4694.     if(result == 0)
  4695.         SHOWSTRING(hostname);
  4696.  
  4697.     RETURN(result);
  4698.     return(result);
  4699. }
  4700.  
  4701. /******************************************************************************/
  4702.  
  4703. struct passwd *
  4704. amiga_getpwnam(char *name)
  4705. {
  4706.     struct passwd *result;
  4707.  
  4708.     chkabort();
  4709.  
  4710.     ASSERT(name != NULL);
  4711.  
  4712.     ENTER();
  4713.     SHOWSTRING(name);
  4714.  
  4715.     result = getpwnam(name);
  4716.  
  4717.     RETURN(result);
  4718.     return(result);
  4719. }
  4720.  
  4721. /******************************************************************************/
  4722.  
  4723. struct passwd *
  4724. amiga_getpwuid(uid_t uid)
  4725. {
  4726.     struct passwd *result;
  4727.  
  4728.     chkabort();
  4729.  
  4730.     ENTER();
  4731.     SHOWVALUE(uid);
  4732.  
  4733.     result = getpwuid(uid);
  4734.  
  4735.     RETURN(result);
  4736.     return(result);
  4737. }
  4738.  
  4739. /******************************************************************************/
  4740.  
  4741. uid_t
  4742. amiga_getuid(VOID)
  4743. {
  4744.     uid_t result;
  4745.  
  4746.     chkabort();
  4747.  
  4748.     ENTER();
  4749.  
  4750.     result = getuid();
  4751.  
  4752.     RETURN(result);
  4753.     return(result);
  4754. }
  4755.  
  4756. /******************************************************************************/
  4757.  
  4758. gid_t
  4759. amiga_getegid(VOID)
  4760. {
  4761.     gid_t result;
  4762.  
  4763.     chkabort();
  4764.  
  4765.     ENTER();
  4766.     result = getegid();
  4767.  
  4768.     RETURN(result);
  4769.     return(result);
  4770. }
  4771.  
  4772. /******************************************************************************/
  4773.  
  4774. uid_t
  4775. amiga_geteuid(VOID)
  4776. {
  4777.     uid_t result;
  4778.  
  4779.     chkabort();
  4780.  
  4781.     ENTER();
  4782.  
  4783.     result = geteuid();
  4784.  
  4785.     RETURN(result);
  4786.     return(result);
  4787. }
  4788.  
  4789. /******************************************************************************/
  4790.  
  4791. int
  4792. amiga_initgroups(char *name, gid_t basegroup)
  4793. {
  4794.     int result;
  4795.  
  4796.     chkabort();
  4797.  
  4798.     ASSERT(name != NULL);
  4799.  
  4800.     ENTER();
  4801.     SHOWSTRING(name);
  4802.     SHOWVALUE(basegroup);
  4803.  
  4804.     result = initgroups(name,basegroup);
  4805.  
  4806.     RETURN(result);
  4807.     return(result);
  4808. }
  4809.  
  4810. /******************************************************************************/
  4811.  
  4812. int
  4813. amiga_setuid(uid_t id)
  4814. {
  4815.     int result;
  4816.  
  4817.     chkabort();
  4818.  
  4819.     ENTER();
  4820.     SHOWVALUE(id);
  4821.  
  4822.     result = setuid(id);
  4823.  
  4824.     RETURN(result);
  4825.     return(result);
  4826. }
  4827.  
  4828. /******************************************************************************/
  4829.  
  4830. int
  4831. amiga_umask(int mask)
  4832. {
  4833.     int result;
  4834.  
  4835.     chkabort();
  4836.  
  4837.     ENTER();
  4838.     SHOWVALUE(mask);
  4839.  
  4840.     result = umask(mask);
  4841.  
  4842.     RETURN(result);
  4843.     return(result);
  4844. }
  4845.  
  4846. /******************************************************************************/
  4847.  
  4848. unsigned long
  4849. amiga_inet_addr(char *addr)
  4850. {
  4851.     unsigned long result;
  4852.  
  4853.     chkabort();
  4854.  
  4855.     ASSERT(addr != NULL);
  4856.  
  4857.     ENTER();
  4858.     SHOWSTRING(addr);
  4859.  
  4860.     result = inet_addr(addr);
  4861.  
  4862.     RETURN(result);
  4863.     return(result);
  4864. }
  4865.  
  4866. /******************************************************************************/
  4867.  
  4868. char *
  4869. amiga_inet_ntoa(struct in_addr in)
  4870. {
  4871.     char *result;
  4872.  
  4873.     chkabort();
  4874.  
  4875.     ENTER();
  4876.     SHOWVALUE(in.s_addr);
  4877.  
  4878.     result = Inet_NtoA(in.s_addr);
  4879.     SHOWSTRING(result);
  4880.  
  4881.     RETURN(result);
  4882.     return(result);
  4883. }
  4884.  
  4885. /******************************************************************************/
  4886.  
  4887. int    opterr = 1;
  4888. int    optind = 1;
  4889. int    optopt;
  4890. char * optarg;
  4891.  
  4892. int
  4893. amiga_getopt(int argc, char * argv[], char *opts)
  4894. {
  4895.     STATIC int sp = 1;
  4896.     int c;
  4897.     char *cp;
  4898.  
  4899.     ASSERT(argc > 0 && argv != NULL && opts != NULL);
  4900.  
  4901.     if(sp == 1)
  4902.     {
  4903.         if(optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  4904.         {
  4905.             return(EOF);
  4906.         }
  4907.         else if(strcmp(argv[optind], "--") == NULL)
  4908.         {
  4909.             optind++;
  4910.             return(EOF);
  4911.         }
  4912.     }
  4913.  
  4914.     optopt = c = argv[optind][sp];
  4915.     if(c == ':' || (cp=index(opts, c)) == NULL)
  4916.     {
  4917.         if(opterr)
  4918.             fprintf(stderr, "%s%s%c\n", argv[0], ": illegal option -- ", c);
  4919.  
  4920.         if(argv[optind][++sp] == '\0')
  4921.         {
  4922.             optind++;
  4923.             sp = 1;
  4924.         }
  4925.  
  4926.         return('?');
  4927.     }
  4928.  
  4929.     if(*++cp == ':')
  4930.     {
  4931.         if(argv[optind][sp+1] != '\0')
  4932.         {
  4933.             optarg = &argv[optind++][sp+1];
  4934.         }
  4935.         else if(++optind >= argc)
  4936.         {
  4937.             if(opterr)
  4938.                 fprintf(stderr, "%s%s%c\n", argv[0], ": option requires an argument -- ", c);
  4939.  
  4940.             sp = 1;
  4941.             return('?');
  4942.         }
  4943.         else
  4944.         {
  4945.             optarg = argv[optind++];
  4946.         }
  4947.  
  4948.         sp = 1;
  4949.     }
  4950.     else
  4951.     {
  4952.         if(argv[optind][++sp] == '\0')
  4953.         {
  4954.             sp = 1;
  4955.             optind++;
  4956.         }
  4957.  
  4958.         optarg = NULL;
  4959.     }
  4960.  
  4961.     return(c);
  4962. }
  4963.  
  4964. /******************************************************************************/
  4965.  
  4966. /* This comes from util/lib.c */
  4967. STATIC BOOL
  4968. do_match(STRPTR str, STRPTR regexp)
  4969. {
  4970.     STRPTR p;
  4971.  
  4972.     for(p = regexp; (*p) != '\0' && (*str) != '\0' ; NULL)
  4973.     {
  4974.         switch(*p)
  4975.         {
  4976.             case '?':
  4977.  
  4978.                 str++;
  4979.                 p++;
  4980.  
  4981.                 break;
  4982.  
  4983.             /* Look for a character matching the one after the '*' */
  4984.             case '*':
  4985.  
  4986.                 p++;
  4987.  
  4988.                 if((*p) == '\0')
  4989.                     return(TRUE); /* Automatic match */
  4990.  
  4991.                 while((*str) != '\0')
  4992.                 {
  4993.                     while((*str) != '\0' && ToUpper(*p) != ToUpper(*str))
  4994.                         str++;
  4995.  
  4996.                     if(do_match(str,p))
  4997.                         return(TRUE);
  4998.  
  4999.                     if((*str) == '\0')
  5000.                         return(FALSE);
  5001.                     else
  5002.                         str++;
  5003.                 }
  5004.  
  5005.                 return(FALSE);
  5006.  
  5007.             default:
  5008.  
  5009.                 if(ToUpper(*str++) != ToUpper(*p++))
  5010.                     return(FALSE);
  5011.  
  5012.                 break;
  5013.         }
  5014.     }
  5015.  
  5016.     if((*p) == '\0' && (*str) == '\0')
  5017.         return(TRUE);
  5018.  
  5019.     if((*p) == '\0' && str[0] == '.' && str[1] == '\0')
  5020.         return(TRUE);
  5021.  
  5022.     if((*str) == '\0' && (*p) == '?')
  5023.     {
  5024.         while((*p) == '?')
  5025.             p++;
  5026.  
  5027.         return((BOOL)((*p) == '\0'));
  5028.     }
  5029.  
  5030.     if((*str) == '\0' && ((*p) == '*' && p[1] == '\0'))
  5031.         return(TRUE);
  5032.  
  5033.     return(FALSE);
  5034. }
  5035.  
  5036. STATIC VOID
  5037. nstrcpy_blank(const size_t maxSize,char *to,const char *from)
  5038. {
  5039.     size_t len = 0;
  5040.  
  5041.     while((*from) != '\0' && (*from) != ' ' && len < maxSize-1)
  5042.     {
  5043.         (*to++) = (*from++);
  5044.         len++;
  5045.     }
  5046.  
  5047.     (*to) = '\0';
  5048. }
  5049.  
  5050. STATIC VOID
  5051. fill_volume_list(struct List * list)
  5052. {
  5053.     struct DosList * dol;
  5054.  
  5055.     dol = NextDosEntry(LockDosList(LDF_VOLUMES|LDF_READ),
  5056.                                    LDF_VOLUMES|LDF_READ);
  5057.     while(dol != NULL)
  5058.     {
  5059.         /* Does the volume refer to a medium that is right
  5060.          * now present in the drive?
  5061.          */
  5062.         if(dol->dol_Task != NULL)
  5063.         {
  5064.             struct InfoData __aligned id;
  5065.  
  5066.             /* Is there a disk present? */
  5067.             if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  5068.             {
  5069.                 STRPTR name = BADDR(dol->dol_Name);
  5070.                 struct Node * node;
  5071.  
  5072.                 node = malloc(sizeof(*node) + ((int)name[0])+1);
  5073.                 if(node != NULL)
  5074.                 {
  5075.                     /* Copy the name of the volume. */
  5076.                     node->ln_Name = (char *)(node + 1);
  5077.                     strncpy(node->ln_Name,&name[1],name[0]);
  5078.                     node->ln_Name[ name[0] ] = '\0';
  5079.  
  5080.                     AddTail(list,node);
  5081.                 }
  5082.             }
  5083.         }
  5084.  
  5085.         dol = NextDosEntry(dol,LDF_VOLUMES|LDF_READ);
  5086.     }
  5087.  
  5088.     UnLockDosList(LDF_VOLUMES|LDF_READ);
  5089. }
  5090.  
  5091. STATIC int
  5092. deep_scan_drawer(char * drawerName,char * whichPattern,FILE * out)
  5093. {
  5094.     char * originalDrawerName;
  5095.     struct MangleInfo mi;
  5096.     int result = ERROR;
  5097.  
  5098.     originalDrawerName = drawerName;
  5099.     if(MangleName(&drawerName,&mi) == OK)
  5100.     {
  5101.         BPTR dirLock;
  5102.  
  5103.         dirLock = Lock(drawerName,SHARED_LOCK);
  5104.         if(dirLock != ZERO)
  5105.         {
  5106.             struct FileInfoBlock __aligned fib;
  5107.  
  5108.             if(Examine(dirLock,&fib))
  5109.             {
  5110.                 struct AnchorPath * ap;
  5111.  
  5112.                 ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  5113.                 if(ap != NULL)
  5114.                 {
  5115.                     BOOL stopped = FALSE;
  5116.                     BPTR oldDir;
  5117.                     LONG error;
  5118.  
  5119.                     oldDir = CurrentDir(dirLock);
  5120.  
  5121.                     memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  5122.                     ap->ap_Strlen        = MAX_FILENAME_LEN;
  5123.                     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  5124.  
  5125.                     if((error = MatchFirst("",ap)) == OK)
  5126.                     {
  5127.                         BOOL check;
  5128.  
  5129.                         do
  5130.                         {
  5131.                             D(("checking |%s|",ap->ap_Buf));
  5132.  
  5133.                             check = TRUE;
  5134.  
  5135.                             if(FIB_IS_FILE(&ap->ap_Info))
  5136.                             {
  5137.                                 SHOWMSG("this is a file");
  5138.                             }
  5139.                             else
  5140.                             {
  5141.                                 SHOWMSG("this is a drawer");
  5142.  
  5143.                                 if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  5144.                                 {
  5145.                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  5146.                                 }
  5147.                                 else
  5148.                                 {
  5149.                                     CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  5150.                                     check = FALSE;
  5151.                                 }
  5152.                             }
  5153.  
  5154.                             if(check)
  5155.                             {
  5156.                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  5157.  
  5158.                                 if(do_match(ap->ap_Info.fib_FileName,whichPattern))
  5159.                                 {
  5160.                                     D(("Output |%s/%s|",originalDrawerName,ap->ap_Buf));
  5161.                                     if(fprintf(out,"%s/%s\n",originalDrawerName,ap->ap_Buf) < 0)
  5162.                                     {
  5163.                                         stopped = TRUE;
  5164.                                         break;
  5165.                                     }
  5166.                                 }
  5167.                                 else
  5168.                                 {
  5169.                                     SHOWMSG("but its name does not match");
  5170.                                 }
  5171.                             }
  5172.                         }
  5173.                         while((error = MatchNext(ap)) == OK);
  5174.                     }
  5175.  
  5176.                     MatchEnd(ap);
  5177.  
  5178.                     CurrentDir(oldDir);
  5179.  
  5180.                     if(NOT stopped)
  5181.                     {
  5182.                         if(error == ERROR_NO_MORE_ENTRIES)
  5183.                         {
  5184.                             result = OK;
  5185.                         }
  5186.                         else if(error == ERROR_BREAK)
  5187.                         {
  5188.                             /* Don't do anything; we are going
  5189.                              * to delete the file anyway.
  5190.                              */
  5191.                         }
  5192.                         else
  5193.                         {
  5194.                             SetIoErr(error);
  5195.                             MapIoErrToErrno();
  5196.                         }
  5197.                     }
  5198.  
  5199.                     free(ap);
  5200.                 }
  5201.                 else
  5202.                 {
  5203.                     errno = ENOMEM;
  5204.                 }
  5205.             }
  5206.             else
  5207.             {
  5208.                 MapIoErrToErrno();
  5209.             }
  5210.  
  5211.             UnLock(dirLock);
  5212.         }
  5213.         else
  5214.         {
  5215.             MapIoErrToErrno();
  5216.         }
  5217.  
  5218.         UnmangleName(&drawerName,&mi);
  5219.     }
  5220.  
  5221.     return(result);
  5222. }
  5223.  
  5224. int
  5225. amiga_system(char *cmd)
  5226. {
  5227.     char redirectionFileBuffer[MAX_FILENAME_LEN];
  5228.     char *redirectionFile = redirectionFileBuffer;
  5229.     struct MangleInfo mi;
  5230.     int result = ERROR;
  5231.     char *stop;
  5232.     char *options;
  5233.     char *cmdName;
  5234.     int cmdLen,i;
  5235.     int quoteCount;
  5236.  
  5237.     chkabort();
  5238.  
  5239.     ASSERT(cmd != NULL);
  5240.  
  5241.     ENTER();
  5242.     SHOWSTRING(cmd);
  5243.  
  5244.     /* Handle two special cases for the smb client program,
  5245.      * which for reasons unknown to me resorts to calling
  5246.      * the Unix "ls" and "find" programs to collect lists
  5247.      * of files.
  5248.      *
  5249.      * The commands to watch for take the following forms:
  5250.      *
  5251.      *    /bin/ls file_to_list > output_filename
  5252.      *    find directory_to_list -name "pattern_to_list" -print > output_filename
  5253.      */
  5254.     stop = cmd;
  5255.     while((*stop) != ' ' && (*stop) != '\0')
  5256.         stop++;
  5257.  
  5258.     /* This will point behind the command name,
  5259.      * to the beginning of the list of options,
  5260.      * if any.
  5261.      */
  5262.     options = stop;
  5263.     while((*options) == ' ')
  5264.         options++;
  5265.  
  5266.     /* Now go and isolate the command name. */
  5267.     cmdName = cmd;
  5268.     cmdLen = stop-cmd;
  5269.     for(i = cmdLen - 1 ; i >= 0 ; i--)
  5270.     {
  5271.         if(cmd[i] == '/' || cmd[i] == ':')
  5272.         {
  5273.             cmdName = &cmd[i+1];
  5274.  
  5275.             stop = cmdName;
  5276.             while((*stop) != ' ' && (*stop) != '\0')
  5277.                 stop++;
  5278.  
  5279.             cmdLen = stop-cmdName;
  5280.  
  5281.             break;
  5282.         }
  5283.     }
  5284.  
  5285.     /* We have isolated the command name, now
  5286.      * find the redirection file name.
  5287.      */
  5288.     quoteCount = 0;
  5289.     strcpy(redirectionFile,"");
  5290.     for(i = 0 ; i < strlen(cmd) ; i++)
  5291.     {
  5292.         if(cmd[i] == '\"')
  5293.             quoteCount = (1-quoteCount);
  5294.  
  5295.         if(cmd[i] == '>' && quoteCount == 0)
  5296.         {
  5297.             char * from;
  5298.  
  5299.             from = &cmd[i+1];
  5300.             while((*from) == ' ')
  5301.                 from++;
  5302.  
  5303.             /* Note that we rely upon the
  5304.              * redirection file name not to contain
  5305.              * quote or escape characters.
  5306.              */
  5307.             nstrcpy_blank(sizeof(redirectionFileBuffer),redirectionFile,from);
  5308.             break;
  5309.         }
  5310.     }
  5311.  
  5312.     /* Now check which command we got. */
  5313.     if(cmdLen == 2 && Strnicmp(cmdName,"ls",2) == SAME)
  5314.     {
  5315.         char localDirName[MAX_FILENAME_LEN];
  5316.         char * dirName;
  5317.  
  5318.         dirName = ".";
  5319.  
  5320.         if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  5321.         {
  5322.             char whichPatternBuffer[MAX_FILENAME_LEN];
  5323.             char *whichPattern = whichPatternBuffer;
  5324.             BOOL oldAllowBreak = AllowBreak;
  5325.  
  5326.             /* We don't want to be interrupted. */
  5327.             AllowBreak = FALSE;
  5328.  
  5329.             /* Now find the pattern to use. */
  5330.             nstrcpy_blank(sizeof(whichPatternBuffer),whichPattern,options);
  5331.  
  5332.             SHOWMSG("doing `ls'");
  5333.             SHOWSTRING(whichPattern);
  5334.             SHOWSTRING(redirectionFile);
  5335.  
  5336.             /* What happens next is that the contents of the
  5337.              * current directory are scanned. All names
  5338.              * that match the given pattern are stored in the
  5339.              * redirection file.
  5340.              */
  5341.  
  5342.             if(MangleName(&redirectionFile,&mi) == OK)
  5343.             {
  5344.                 FILE * out;
  5345.  
  5346.                 ForbidDOS();
  5347.  
  5348.                 out = fopen(redirectionFile,"wb");
  5349.                 if(out != NULL)
  5350.                 {
  5351.                     SHOWSTRING(localDirName);
  5352.  
  5353.                     if(strcmp(localDirName,"/") == SAME)
  5354.                     {
  5355.                         struct List list;
  5356.                         struct Node * node;
  5357.  
  5358.                         SHOWMSG("listing volumes");
  5359.  
  5360.                         NewList(&list);
  5361.  
  5362.                         fill_volume_list(&list);
  5363.  
  5364.                         while((node = RemHead(&list)) != NULL)
  5365.                         {
  5366.                             D(("checking '%s'",node->ln_Name));
  5367.  
  5368.                             if(do_match(node->ln_Name,whichPattern))
  5369.                             {
  5370.                                 SHOWMSG(">>> matches");
  5371.  
  5372.                                 if(fprintf(out,"%s\n",node->ln_Name) < 0)
  5373.                                     break;
  5374.                             }
  5375.                             else
  5376.                             {
  5377.                                 SHOWMSG(">>> does not match");
  5378.                             }
  5379.  
  5380.                             free(node);
  5381.                         }
  5382.  
  5383.                         while((node = RemHead(&list)) != NULL)
  5384.                             free(node);
  5385.                     }
  5386.                     else
  5387.                     {
  5388.                         BPTR dirLock;
  5389.  
  5390.                         SHOWMSG("listing drawers");
  5391.  
  5392.                         dirLock = Lock("",SHARED_LOCK);
  5393.                         if(dirLock != ZERO)
  5394.                         {
  5395.                             struct FileInfoBlock __aligned fib;
  5396.  
  5397.                             if(Examine(dirLock,&fib))
  5398.                             {
  5399.                                 BOOL stopped = FALSE;
  5400.  
  5401.                                 while(ExNext(dirLock,&fib))
  5402.                                 {
  5403.                                     D(("checking '%s'",fib.fib_FileName));
  5404.  
  5405.                                     if(do_match(fib.fib_FileName,whichPattern))
  5406.                                     {
  5407.                                         SHOWMSG(">>> matches");
  5408.  
  5409.                                         if(fprintf(out,"%s\n",fib.fib_FileName) < 0)
  5410.                                         {
  5411.                                             stopped = TRUE;
  5412.                                             break;
  5413.                                         }
  5414.                                     }
  5415.                                     else
  5416.                                     {
  5417.                                         SHOWMSG(">>> does not match");
  5418.                                     }
  5419.                                 }
  5420.  
  5421.                                 if(NOT stopped)
  5422.                                 {
  5423.                                     LONG error = IoErr();
  5424.  
  5425.                                     if(error == ERROR_NO_MORE_ENTRIES)
  5426.                                     {
  5427.                                         result = OK;
  5428.                                     }
  5429.                                     else
  5430.                                     {
  5431.                                         SetIoErr(error);
  5432.                                         MapIoErrToErrno();
  5433.                                     }
  5434.                                 }
  5435.                             }
  5436.                             else
  5437.                             {
  5438.                                 MapIoErrToErrno();
  5439.                             }
  5440.  
  5441.                             UnLock(dirLock);
  5442.                         }
  5443.                         else
  5444.                         {
  5445.                             MapIoErrToErrno();
  5446.                         }
  5447.                     }
  5448.  
  5449.                     fclose(out);
  5450.  
  5451.                     if(result != OK)
  5452.                         DeleteFile(redirectionFile);
  5453.                 }
  5454.  
  5455.                 PermitDOS();
  5456.  
  5457.                 UnmangleName(&cmd,&mi);
  5458.             }
  5459.  
  5460.             AllowBreak = oldAllowBreak;
  5461.         }
  5462.     }
  5463.     else if (cmdLen == 4 && Strnicmp(cmdName,"find",4) == SAME)
  5464.     {
  5465.         char whichDrawerBuffer[MAX_FILENAME_LEN];
  5466.         char * whichDrawer = whichDrawerBuffer;
  5467.         char whichPattern[MAX_FILENAME_LEN];
  5468.         const int _nameLen = strlen("-name");
  5469.         BOOL oldAllowBreak = AllowBreak;
  5470.         struct List list;
  5471.         struct Node * node;
  5472.  
  5473.         NewList(&list);
  5474.  
  5475.         /* We don't want to be interrupted. */
  5476.         AllowBreak = FALSE;
  5477.  
  5478.         /* Now find the drawer to examine. */
  5479.         nstrcpy_blank(sizeof(whichDrawerBuffer),whichDrawer,options);
  5480.  
  5481.         /* Find the pattern to search for. */
  5482.         strcpy(whichPattern,"");
  5483.         for(i = 0 ; i < strlen(options) ; i++)
  5484.         {
  5485.             if(Strnicmp(&options[i],"-name",_nameLen) == SAME)
  5486.             {
  5487.                 const int maxLen = sizeof(whichPattern)-1;
  5488.                 int whichPatternLen;
  5489.                 int escapeCount;
  5490.                 int quoteCount;
  5491.                 char * from;
  5492.                 char * to;
  5493.  
  5494.                 /* `from' should now point straight at the
  5495.                  * search pattern, which is probably enclosed
  5496.                  * in quote characters.
  5497.                  */
  5498.                 from = &options[i+_nameLen];
  5499.                 while((*from) == ' ')
  5500.                     from++;
  5501.  
  5502.                 to = whichPattern;
  5503.                 whichPatternLen = 0;
  5504.                 quoteCount = 0;
  5505.                 escapeCount = 0;
  5506.                 while((*from) != '\0' && whichPatternLen < maxLen)
  5507.                 {
  5508.                     if(escapeCount != 0)
  5509.                     {
  5510.                         (*to++) = (*from++);
  5511.                         whichPatternLen++;
  5512.                         escapeCount = 0;
  5513.                     }
  5514.                     else if((*from) == '\\')
  5515.                     {
  5516.                         escapeCount = (1-escapeCount);
  5517.                         from++;
  5518.                     }
  5519.                     else if ((*from) == '\"')
  5520.                     {
  5521.                         quoteCount = (1-quoteCount);
  5522.                         from++;
  5523.                     }
  5524.                     else
  5525.                     {
  5526.                         if((*from) == ' ' && quoteCount == 0)
  5527.                         {
  5528.                             break;
  5529.                         }
  5530.                         else
  5531.                         {
  5532.                             (*to++) = (*from++);
  5533.                             whichPatternLen++;
  5534.                         }
  5535.                     }
  5536.                 }
  5537.  
  5538.                 (*to) = '\0';
  5539.             }
  5540.         }
  5541.  
  5542.         SHOWMSG("doing `find'");
  5543.         SHOWSTRING(whichDrawer);
  5544.         SHOWSTRING(whichPattern);
  5545.         SHOWSTRING(redirectionFile);
  5546.  
  5547.         /* Things are a little bit more complicated here. The
  5548.          * "find" program scans recursively through a directory
  5549.          * tree. We emulate this behaviour by having the MatchFirst/MatchNext
  5550.          * routines iterate through the directory tree. The
  5551.          * name of every file found is matched against the given
  5552.          * pattern and, if necessary, written to the redirection
  5553.          * file. Note that matching is performed only on the
  5554.          * file name, not on the entire path.
  5555.          */
  5556.  
  5557.         if(MangleName(&redirectionFile,&mi) == OK)
  5558.         {
  5559.             FILE * out;
  5560.  
  5561.             ForbidDOS();
  5562.  
  5563.             out = fopen(redirectionFile,"wb");
  5564.             if(out != NULL)
  5565.             {
  5566.                 char localDirName[MAX_FILENAME_LEN];
  5567.                 char * dirName;
  5568.  
  5569.                 dirName = whichDrawer;
  5570.  
  5571.                 if(TranslateRelativePath(&dirName,localDirName,sizeof(localDirName)) == OK)
  5572.                 {
  5573.                     D(("listing path '%s'",dirName));
  5574.  
  5575.                     if(strcmp(dirName,"/") == SAME)
  5576.                     {
  5577.                         SHOWMSG("checking all 'drawers' in the fake root");
  5578.  
  5579.                         fill_volume_list(&list);
  5580.  
  5581.                         while((node = RemHead(&list)) != NULL)
  5582.                         {
  5583.                             strcpy(localDirName,"/");
  5584.                             strcat(localDirName,node->ln_Name);
  5585.                             free(node);
  5586.  
  5587.                             D(("checking '%s'",localDirName));
  5588.  
  5589.                             result = deep_scan_drawer(localDirName,whichPattern,out);
  5590.                             if(result != OK)
  5591.                                 break;
  5592.                         }
  5593.  
  5594.                         while((node = RemHead(&list)) != NULL)
  5595.                             free(node);
  5596.                     }
  5597.                     else
  5598.                     {
  5599.                         SHOWMSG("checking only a local drawer");
  5600.  
  5601.                         result = deep_scan_drawer(dirName,whichPattern,out);
  5602.                     }
  5603.                 }
  5604.  
  5605.                 fclose(out);
  5606.  
  5607.                 if(result != OK)
  5608.                     DeleteFile(redirectionFile);
  5609.             }
  5610.  
  5611.             PermitDOS();
  5612.  
  5613.             UnmangleName(&cmd,&mi);
  5614.         }
  5615.  
  5616.         AllowBreak = oldAllowBreak;
  5617.     }
  5618.     else
  5619.     {
  5620.         if(MangleName(&cmd,&mi) == OK)
  5621.         {
  5622.             ForbidDOS();
  5623.             result = system(cmd);
  5624.             PermitDOS();
  5625.  
  5626.             UnmangleName(&cmd,&mi);
  5627.         }
  5628.     }
  5629.  
  5630.     RETURN(result);
  5631.     return(result);
  5632. }
  5633.  
  5634. /******************************************************************************/
  5635.  
  5636. int
  5637. amiga_fork(VOID)    /* dummy */
  5638. {
  5639.     int result;
  5640.  
  5641.     chkabort();
  5642.  
  5643.     ENTER();
  5644.  
  5645.     result = ERROR;
  5646.     errno = ENOSYS;
  5647.  
  5648.     RETURN(result);
  5649.     return(result);
  5650. }
  5651.  
  5652. /******************************************************************************/
  5653.  
  5654. STATIC BOOL
  5655. SetFileSocket(FILE *stream,int sockfd)
  5656. {
  5657.     struct UFB * ufb;
  5658.     BOOL success = FALSE;
  5659.  
  5660.     ASSERT(stream != NULL);
  5661.  
  5662.     ENTER();
  5663.  
  5664.     /* Check which buffer the file
  5665.      * is attached to.
  5666.      */
  5667.     ufb = chkufb(fileno(stream));
  5668.     if(ufb != NULL)
  5669.     {
  5670.         SHOWVALUE(ufb);
  5671.  
  5672.         /* Save the file handle. */
  5673.         if(SaveDescriptor(ufb))
  5674.         {
  5675.             /* And put the socket in its place. */
  5676.             ufb->ufbfh = sockfd;
  5677.             SET_FLAG(ufb->ufbflg,UFB_IS_SOCKET);
  5678.  
  5679.             success = TRUE;
  5680.         }
  5681.     }
  5682.     else
  5683.     {
  5684.         SHOWMSG("no ufb");
  5685.     }
  5686.  
  5687.     RETURN(success);
  5688.     return(success);
  5689. }
  5690.  
  5691. STATIC VOID
  5692. DaemonInit(VOID)
  5693. {
  5694.     struct DaemonMessage * dm;
  5695.     int sock;
  5696.  
  5697.     ENTER();
  5698.  
  5699.     /* This routine is called when the program starts up.
  5700.      * If it was launched by the INet super server, this
  5701.      * program will run as a daemon. We pick up its
  5702.      * socket input stream and attach it to our stdio
  5703.      * streams.
  5704.      */
  5705.     dm = (struct DaemonMessage *)((struct Process *)FindTask(NULL))->pr_ExitData;
  5706.     if(dm != NULL)
  5707.     {
  5708.         sock = ObtainSocket(dm->dm_ID,dm->dm_Family,dm->dm_Type,0);
  5709.         if(sock != -1)
  5710.         {
  5711.             BOOL success = FALSE;
  5712.             int sock_stdin;
  5713.             int sock_stdout;
  5714.             int sock_stderr;
  5715.  
  5716.             sock_stdin    = Dup2Socket(sock,-1);
  5717.             sock_stdout    = Dup2Socket(sock,-1);
  5718.             sock_stderr    = Dup2Socket(sock,-1);
  5719.  
  5720.             if(sock_stdin != -1 && sock_stdout != -1 && sock_stderr != -1)
  5721.             {
  5722.                 SHOWMSG("got all sockets");
  5723.  
  5724.                 D(("stdin  = sock %ld",sock_stdin));
  5725.                 D(("stdout = sock %ld",sock_stdout));
  5726.                 D(("stderr = sock %ld",sock_stderr));
  5727.  
  5728.                 if(SetFileSocket(stdin,sock_stdin) &&
  5729.                    SetFileSocket(stdout,sock_stdout) &&
  5730.                    SetFileSocket(stderr,sock_stderr))
  5731.                 {
  5732.                     SHOWMSG("and all streams are initialized");
  5733.  
  5734.                     success = TRUE;
  5735.                 }
  5736.                 else
  5737.                 {
  5738.                     SHOWMSG("failed to initialize streams");
  5739.                 }
  5740.             }
  5741.             else
  5742.             {
  5743.                 SHOWMSG("didn't get the sockets");
  5744.             }
  5745.  
  5746.             if(NO success)
  5747.             {
  5748.                 if(sock_stdin != -1)
  5749.                     CloseSocket(sock_stdin);
  5750.  
  5751.                 if(sock_stdout != -1)
  5752.                     CloseSocket(sock_stdout);
  5753.  
  5754.                 if(sock_stderr != -1)
  5755.                     CloseSocket(sock_stderr);
  5756.             }
  5757.         }
  5758.         else
  5759.         {
  5760.             SHOWMSG("no socket");
  5761.         }
  5762.     }
  5763.     else
  5764.     {
  5765.         SHOWMSG("No daemon message");
  5766.     }
  5767.  
  5768.     LEAVE();
  5769. }
  5770.  
  5771. /******************************************************************************/
  5772.  
  5773. VOID
  5774. __tzset(VOID)
  5775. {
  5776.     STATIC char TimeZoneName[20] = "";
  5777.  
  5778.     /* This routine sets up the internal
  5779.      * time zone variable according to
  5780.      * the local settings.
  5781.      */
  5782.     if(STRING_IS_EMPTY(TimeZoneName))
  5783.     {
  5784.         int hoursWest = MinutesWest / 60;
  5785.  
  5786.         if(hoursWest >= 0)
  5787.             sprintf(TimeZoneName,"GMT+%02d", hoursWest);
  5788.         else
  5789.             sprintf(TimeZoneName,"GMT-%02d",-hoursWest);
  5790.     }
  5791.  
  5792.     _TZ = TimeZoneName;
  5793. }
  5794.  
  5795. /******************************************************************************/
  5796.  
  5797. time_t
  5798. time(time_t *timeptr)
  5799. {
  5800.     time_t currentTime;
  5801.     struct timeval tv;
  5802.  
  5803.     chkabort();
  5804.  
  5805.     GetSysTime((APTR)&tv);
  5806.  
  5807.     currentTime = UNIX_TIME_OFFSET + tv.tv_secs + 60*MinutesWest;    /* translate from local time to UTC */
  5808.  
  5809.     if(timeptr != NULL)
  5810.         (*timeptr) = currentTime;
  5811.  
  5812.     return(currentTime);
  5813. }
  5814.  
  5815. /******************************************************************************/
  5816.  
  5817. STATIC struct tm *
  5818. ConvertTime(ULONG seconds)
  5819. {
  5820.     STATIC struct tm tm;
  5821.     struct ClockData clockData;
  5822.     ULONG delta;
  5823.  
  5824.     chkabort();
  5825.  
  5826.     Amiga2Date(seconds,&clockData);
  5827.  
  5828.     tm.tm_sec    = clockData.sec;
  5829.     tm.tm_min    = clockData.min;
  5830.     tm.tm_hour    = clockData.hour;
  5831.     tm.tm_mday    = clockData.mday;
  5832.     tm.tm_mon    = clockData.month - 1;
  5833.     tm.tm_year    = clockData.year - 1900;
  5834.     tm.tm_wday    = clockData.wday;
  5835.     tm.tm_isdst    = 0;
  5836.  
  5837.     clockData.mday    = 1;
  5838.     clockData.month    = 1;
  5839.  
  5840.     delta = Date2Amiga(&clockData);
  5841.  
  5842.     tm.tm_yday = (seconds - delta) / (24*60*60);
  5843.  
  5844.     return(&tm);
  5845. }
  5846.  
  5847. struct tm *
  5848. gmtime(const time_t *t)
  5849. {
  5850.     struct tm * result;
  5851.     ULONG seconds;
  5852.  
  5853.     if((*t) < UNIX_TIME_OFFSET)
  5854.         seconds = 0;
  5855.     else
  5856.         seconds = (*t) - UNIX_TIME_OFFSET;
  5857.  
  5858.     result = ConvertTime(seconds);
  5859.  
  5860.     return(result);
  5861. }
  5862.  
  5863. struct tm *
  5864. localtime(const time_t *t)
  5865. {
  5866.     struct tm * result;
  5867.     ULONG seconds;
  5868.  
  5869.     if((*t) < (UNIX_TIME_OFFSET + 60*MinutesWest))
  5870.         seconds = 0;
  5871.     else
  5872.         seconds = (*t) - (UNIX_TIME_OFFSET + 60*MinutesWest);    /* translate from UTC to local time */
  5873.  
  5874.     result = ConvertTime(seconds);
  5875.  
  5876.     return(result);
  5877. }
  5878.  
  5879. /******************************************************************************/
  5880.  
  5881. int
  5882. amiga_strcasecmp(char *a,char *b)
  5883. {
  5884.     int result;
  5885.  
  5886.     ASSERT(a != NULL && b != NULL);
  5887.  
  5888.     result = Stricmp((STRPTR)a,b);
  5889.  
  5890.     return(result);
  5891. }
  5892.  
  5893. int
  5894. amiga_strncasecmp(char *a,char *b,int len)
  5895. {
  5896.     int result;
  5897.  
  5898.     ASSERT(a != NULL && b != NULL);
  5899.  
  5900.     result = Strnicmp(a,b,len);
  5901.  
  5902.     return(result);
  5903. }
  5904.  
  5905. /******************************************************************************/
  5906.  
  5907. VOID
  5908. (*amiga_signal(int which,VOID (* action)(int)))(int)
  5909. {
  5910.     VOID (* result)(int);
  5911.  
  5912.     chkabort();
  5913.  
  5914.     ENTER();
  5915.  
  5916.     if(SIGABRT <= which && which <= SIGTERM)
  5917.         result = signal(which,action);
  5918.     else
  5919.         result = SIG_DFL;
  5920.  
  5921.     RETURN(result);
  5922.     return(result);
  5923. }
  5924.  
  5925. /******************************************************************************/
  5926.  
  5927. VOID
  5928. amiga_alarm(int seconds)    /* dummy */
  5929. {
  5930.     chkabort();
  5931.  
  5932.     ENTER();
  5933.  
  5934.     LEAVE();
  5935. }
  5936.  
  5937. /******************************************************************************/
  5938.  
  5939. int
  5940. amiga_waitpid(pid_t pid,int *status,int options)    /* dummy */
  5941. {
  5942.     int result;
  5943.  
  5944.     chkabort();
  5945.  
  5946.     ENTER();
  5947.  
  5948.     result = ERROR;
  5949.     errno = ENOSYS;
  5950.  
  5951.     RETURN(result);
  5952.     return(result);
  5953. }
  5954.  
  5955. /******************************************************************************/
  5956.  
  5957. long
  5958. amiga_setsid(VOID)
  5959. {
  5960.     long result;
  5961.  
  5962.     chkabort();
  5963.  
  5964.     ENTER();
  5965.  
  5966.     result = (long)setsid();
  5967.  
  5968.     RETURN(result);
  5969.     return(result);
  5970. }
  5971.  
  5972. /******************************************************************************/
  5973.  
  5974. int
  5975. amiga_setreuid(uid_t real, uid_t eff)
  5976. {
  5977.     int result;
  5978.  
  5979.     chkabort();
  5980.  
  5981.     ENTER();
  5982.  
  5983.     result = setreuid(real,eff);
  5984.  
  5985.     RETURN(result);
  5986.     return(result);
  5987. }
  5988.  
  5989. /******************************************************************************/
  5990.  
  5991. int
  5992. amiga_setregid(gid_t real, gid_t eff)
  5993. {
  5994.     int result;
  5995.  
  5996.     chkabort();
  5997.  
  5998.     ENTER();
  5999.  
  6000.     result = setregid(real,eff);
  6001.  
  6002.     RETURN(result);
  6003.     return(result);
  6004. }
  6005.  
  6006. /******************************************************************************/
  6007.  
  6008. int
  6009. amiga_getsockname(int sockfd,struct sockaddr *name,int *namelen)
  6010. {
  6011.     struct UFB * ufb;
  6012.     int result = ERROR;
  6013.  
  6014.     chkabort();
  6015.  
  6016.     ASSERT(name != NULL && namelen != NULL);
  6017.  
  6018.     ENTER();
  6019.  
  6020.     ufb = chkufb(sockfd);
  6021.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  6022.         result = getsockname(ufb->ufbfh,name,(LONG *)namelen);
  6023.     else
  6024.         errno = ENOTSOCK;
  6025.  
  6026.     RETURN(result);
  6027.     return(result);
  6028. }
  6029.  
  6030. /******************************************************************************/
  6031.  
  6032. int
  6033. amiga_statfs(char *name,struct statfs *f)
  6034. {
  6035.     char localName[MAX_FILENAME_LEN];
  6036.     int result = ERROR;
  6037.  
  6038.     chkabort();
  6039.  
  6040.     ASSERT(name != NULL && f != NULL);
  6041.  
  6042.     ENTER();
  6043.  
  6044.     SHOWSTRING(name);
  6045.     SHOWVALUE(f);
  6046.  
  6047.     if(TranslateRelativePath(&name,localName,sizeof(localName)) == OK)
  6048.     {
  6049.         /* Make up something for the virtual root directory. */
  6050.         if(strcmp(name,"/") == SAME)
  6051.         {
  6052.             memset(f,0,sizeof(*f));
  6053.  
  6054.             f->f_fsize = 512;
  6055.  
  6056.             /* Try to reuse the data from our last scan. */
  6057.             if(RootBlocks > 0 && RootBlocksUsed > 0)
  6058.             {
  6059.                 f->f_blocks    = RootBlocks;
  6060.                 f->f_bfree    = RootBlocks - RootBlocksUsed;
  6061.             }
  6062.             else
  6063.             {
  6064.                 f->f_blocks    = 0x7FFFFFFF/f->f_fsize;
  6065.                 f->f_bfree    = f->f_blocks - 1;
  6066.             }
  6067.  
  6068.             f->f_bsize    = f->f_fsize;
  6069.             f->f_bavail    = f->f_bfree;
  6070.  
  6071.             SHOWVALUE(f->f_fsize);
  6072.             SHOWVALUE(f->f_bsize);
  6073.             SHOWVALUE(f->f_blocks);
  6074.             SHOWVALUE(f->f_bfree);
  6075.             SHOWVALUE(f->f_bavail);
  6076.  
  6077.             result = OK;
  6078.         }
  6079.         else
  6080.         {
  6081.             struct MangleInfo mi;
  6082.             BPTR fileLock;
  6083.  
  6084.             if(MangleName(&name,&mi) == OK)
  6085.             {
  6086.                 ForbidDOS();
  6087.  
  6088.                 fileLock = Lock(name,SHARED_LOCK);
  6089.                 if(fileLock != ZERO)
  6090.                 {
  6091.                     struct InfoData __aligned id;
  6092.  
  6093.                     if(Info(fileLock,&id))
  6094.                     {
  6095.                         memset(f,0,sizeof(*f));
  6096.  
  6097.                         /* Make sure that these never drop to zero. */
  6098.                         if(id.id_NumBlocks == 0)
  6099.                             id.id_NumBlocks = 1;
  6100.  
  6101.                         if(id.id_BytesPerBlock == 0)
  6102.                             id.id_BytesPerBlock = 512;
  6103.  
  6104.                         f->f_fsize    = id.id_BytesPerBlock;                        /* fundamental file system block size */
  6105.                         f->f_blocks    = id.id_NumBlocks;                            /* total data blocks in file system */
  6106.                         f->f_bfree    = id.id_NumBlocks - id.id_NumBlocksUsed;    /* free blocks in fs */
  6107.                         f->f_bsize    = f->f_fsize;                                /* optimal transfer block size */
  6108.                         f->f_bavail    = f->f_bfree;                                /* free blocks avail to non-superuser */
  6109.  
  6110.                         SHOWVALUE(f->f_fsize);
  6111.                         SHOWVALUE(f->f_bsize);
  6112.                         SHOWVALUE(f->f_blocks);
  6113.                         SHOWVALUE(f->f_bfree);
  6114.                         SHOWVALUE(f->f_bavail);
  6115.  
  6116.                         result = OK;
  6117.                     }
  6118.                     else
  6119.                     {
  6120.                         MapIoErrToErrno();
  6121.                     }
  6122.  
  6123.                     UnLock(fileLock);
  6124.                 }
  6125.                 else
  6126.                 {
  6127.                     MapIoErrToErrno();
  6128.                 }
  6129.  
  6130.                 PermitDOS();
  6131.  
  6132.                 UnmangleName(&name,&mi);
  6133.             }
  6134.         }
  6135.     }
  6136.  
  6137.     RETURN(result);
  6138.     return(result);
  6139. }
  6140.  
  6141. /******************************************************************************/
  6142.  
  6143. int
  6144. amiga_execl(char *path,char *arg,...)    /* dummy */
  6145. {
  6146.     int result;
  6147.  
  6148.     chkabort();
  6149.  
  6150.     ENTER();
  6151.  
  6152.     result = ERROR;
  6153.     errno = ENOSYS;
  6154.  
  6155.     RETURN(result);
  6156.     return(result);
  6157. }
  6158.  
  6159. /******************************************************************************/
  6160.  
  6161. char *
  6162. amiga_strerror(int error)
  6163. {
  6164.     struct TagItem tags[2];
  6165.     char *result;
  6166.  
  6167.     chkabort();
  6168.  
  6169.     ENTER();
  6170.  
  6171.     tags[0].ti_Tag    = SBTM_GETVAL(SBTC_ERRNOSTRPTR);
  6172.     tags[0].ti_Data    = error;
  6173.     tags[1].ti_Tag    = TAG_END;
  6174.  
  6175.     SocketBaseTagList(tags);
  6176.  
  6177.     result = (char *)tags[0].ti_Data;
  6178.  
  6179.     RETURN(result);
  6180.     return(result);
  6181. }
  6182.  
  6183. /******************************************************************************/
  6184.  
  6185. int
  6186. amiga_access(char *name,int modes)
  6187. {
  6188.     struct MangleInfo mi;
  6189.     int result = ERROR;
  6190.  
  6191.     chkabort();
  6192.  
  6193.     ASSERT(name != NULL);
  6194.  
  6195.     ENTER();
  6196.  
  6197.     if(MangleName(&name,&mi) == OK)
  6198.     {
  6199.         ForbidDOS();
  6200.         result = access(name,modes);
  6201.         PermitDOS();
  6202.  
  6203.         UnmangleName(&name,&mi);
  6204.     }
  6205.  
  6206.     RETURN(result);
  6207.     return(result);
  6208. }
  6209.  
  6210. /******************************************************************************/
  6211.  
  6212. STATIC VOID
  6213. MapIoErrToErrno(VOID)
  6214. {
  6215.     /* This routine maps AmigaDOS error codes to
  6216.      * Unix error codes, as far as this is possible.
  6217.      * This table contains AmigaDOS error codes
  6218.      * the emulated routines won't generate. I have
  6219.      * included them for the sake of completeness.
  6220.      */
  6221.     struct { LONG IoErr; LONG errno; } MapTable[] =
  6222.     {
  6223.         ERROR_NO_FREE_STORE,            ENOMEM,
  6224.         ERROR_TASK_TABLE_FULL,            ENOMEM,
  6225.         ERROR_BAD_TEMPLATE,                EINVAL,
  6226.         ERROR_BAD_NUMBER,                EINVAL,
  6227.         ERROR_REQUIRED_ARG_MISSING,        EINVAL,
  6228.         ERROR_KEY_NEEDS_ARG,            EINVAL,
  6229.         ERROR_TOO_MANY_ARGS,            EINVAL,
  6230.         ERROR_UNMATCHED_QUOTES,            EINVAL,
  6231.         ERROR_LINE_TOO_LONG,            ENAMETOOLONG,
  6232.         ERROR_FILE_NOT_OBJECT,            ENOEXEC,
  6233.         ERROR_INVALID_RESIDENT_LIBRARY,    EIO,
  6234.         ERROR_NO_DEFAULT_DIR,            EIO,
  6235.         ERROR_OBJECT_IN_USE,            EBUSY,
  6236.         ERROR_OBJECT_EXISTS,            EBUSY,
  6237.         ERROR_DIR_NOT_FOUND,            ENOENT,
  6238.         ERROR_OBJECT_NOT_FOUND,            ENOENT,
  6239.         ERROR_BAD_STREAM_NAME,            EINVAL,
  6240.         ERROR_OBJECT_TOO_LARGE,            EFBIG,
  6241.         ERROR_ACTION_NOT_KNOWN,            ENOSYS,
  6242.         ERROR_INVALID_COMPONENT_NAME,    EINVAL,
  6243.         ERROR_INVALID_LOCK,                EBADF,
  6244.         ERROR_OBJECT_WRONG_TYPE,        EFTYPE,
  6245.         ERROR_DISK_NOT_VALIDATED,        EROFS,
  6246.         ERROR_DISK_WRITE_PROTECTED,        EROFS,
  6247.         ERROR_RENAME_ACROSS_DEVICES,    EXDEV,
  6248.         ERROR_DIRECTORY_NOT_EMPTY,        ENOTEMPTY,
  6249.         ERROR_TOO_MANY_LEVELS,            ENAMETOOLONG,
  6250.         ERROR_DEVICE_NOT_MOUNTED,        ENXIO,
  6251.         ERROR_SEEK_ERROR,                EIO,
  6252.         ERROR_COMMENT_TOO_BIG,            ENAMETOOLONG,
  6253.         ERROR_DISK_FULL,                ENOSPC,
  6254.         ERROR_DELETE_PROTECTED,            EACCES,
  6255.         ERROR_WRITE_PROTECTED,            EACCES,
  6256.         ERROR_READ_PROTECTED,            EACCES,
  6257.         ERROR_NOT_A_DOS_DISK,            EFTYPE,
  6258.         ERROR_NO_DISK,                    EACCES,
  6259.         ERROR_NO_MORE_ENTRIES,            EIO,
  6260.         ERROR_IS_SOFT_LINK,                EFTYPE,
  6261.         ERROR_OBJECT_LINKED,            EIO,
  6262.         ERROR_BAD_HUNK,                    ENOEXEC,
  6263.         ERROR_NOT_IMPLEMENTED,            ENOSYS,
  6264.         ERROR_RECORD_NOT_LOCKED,        EIO,
  6265.         ERROR_LOCK_COLLISION,            EACCES,
  6266.         ERROR_LOCK_TIMEOUT,                EIO,
  6267.         ERROR_UNLOCK_ERROR,                EIO,
  6268.         ERROR_BUFFER_OVERFLOW,            EIO,
  6269.         ERROR_BREAK,                    EINTR,
  6270.         ERROR_NOT_EXECUTABLE,            ENOEXEC
  6271.     };
  6272.  
  6273.     LONG ioErr = IoErr();
  6274.     int i;
  6275.  
  6276.     /* If nothing else matches, we can always
  6277.      * flag it as an I/O error.
  6278.      */
  6279.     errno = EIO;
  6280.  
  6281.     for(i = 0 ; i < NUM_ENTRIES(MapTable) ; i++)
  6282.     {
  6283.         if(MapTable[i].IoErr == ioErr)
  6284.         {
  6285.             errno = MapTable[i].errno;
  6286.             break;
  6287.         }
  6288.     }
  6289. }
  6290.  
  6291. /******************************************************************************/
  6292.  
  6293. off_t
  6294. amiga_lseek(int fd,off_t offset,int mode)
  6295. {
  6296.     struct UFB * ufb;
  6297.     off_t result = ERROR;
  6298.  
  6299.     ENTER();
  6300.     SHOWVALUE(fd);
  6301.     SHOWVALUE(offset);
  6302.     SHOWVALUE(mode);
  6303.  
  6304.     ForbidDOS();
  6305.  
  6306.     /* Make sure that we operate on a file. */
  6307.     ufb = chkufb(fd);
  6308.     if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6309.         result = lseek(fd,offset,mode);
  6310.     else
  6311.         errno = EBADF;
  6312.  
  6313.     PermitDOS();
  6314.  
  6315.     RETURN(result);
  6316.     return(result);
  6317. }
  6318.  
  6319. /******************************************************************************/
  6320.  
  6321. int
  6322. amiga_chroot(char *name)    /* dummy */
  6323. {
  6324.     int result = OK;
  6325.  
  6326.     ENTER();
  6327.  
  6328.     SHOWSTRING(name);
  6329.  
  6330.     RETURN(result);
  6331.     return(result);
  6332. }
  6333.  
  6334. /******************************************************************************/
  6335.  
  6336. STATIC int
  6337. MapFileNameAmigaToUnix(
  6338.     const char *    amiga,
  6339.     char *            unix,
  6340.     int                maxUnixLen)
  6341. {
  6342.     int len,destLen;
  6343.     int result = ERROR;
  6344.  
  6345.     /* This routine makes a Unix file
  6346.      * name generated from an AmigaDOS
  6347.      * file name. This involves a slight
  6348.      * change of syntax...
  6349.      */
  6350.     D(("amiga name |%s|",amiga));
  6351.  
  6352.     len = destLen = strlen(amiga);
  6353.     if(amiga[0] == '/')
  6354.     {
  6355.         destLen = 2 + len;
  6356.     }
  6357.     else
  6358.     {
  6359.         int i;
  6360.  
  6361.         for(i = 0 ; i < len ; i++)
  6362.         {
  6363.             if(amiga[i] == ':')
  6364.             {
  6365.                 if(amiga[i+1] != '\0')
  6366.                     destLen = 1 + len;
  6367.  
  6368.                 break;
  6369.             }
  6370.         }
  6371.     }
  6372.  
  6373.     if(destLen < maxUnixLen)
  6374.     {
  6375.         if(amiga[0] == '/')
  6376.         {
  6377.             /* `/foo\0' -> `../foo\0' */
  6378.             memmove(&unix[2],amiga,len+1);
  6379.             strncpy(unix,"..",2);
  6380.         }
  6381.         else
  6382.         {
  6383.             BOOL done = FALSE;
  6384.             int i;
  6385.  
  6386.             for(i = 0 ; i < len ; i++)
  6387.             {
  6388.                 if(amiga[i] == ':')
  6389.                 {
  6390.                     if(amiga[i+1] == '\0')
  6391.                     {
  6392.                         /* `foo:\0' -> `/foo\0' */
  6393.                         memmove(&unix[1],amiga,i);
  6394.                         unix[0] = '/';
  6395.                         unix[i+1] = '\0';
  6396.                     }
  6397.                     else
  6398.                     {
  6399.                         /* `foo:bar\0' -> `/foo/bar\0' */
  6400.                         memmove(&unix[1],amiga,len+1);
  6401.                         unix[0] = '/';
  6402.                         unix[i+1] = '/';
  6403.                     }
  6404.  
  6405.                     done = TRUE;
  6406.                     break;
  6407.                 }
  6408.             }
  6409.  
  6410.             if(NOT done && unix != amiga)
  6411.                 strcpy(unix,amiga);
  6412.         }
  6413.  
  6414.         D(("unix name |%s|",unix));
  6415.  
  6416.         result = OK;
  6417.     }
  6418.     else
  6419.     {
  6420.         SHOWMSG("unix name is too long to fit");
  6421.  
  6422.         errno = ENAMETOOLONG;
  6423.     }
  6424.  
  6425.     return(result);
  6426. }
  6427.  
  6428. /******************************************************************************/
  6429.  
  6430. STATIC VOID
  6431. FlushSTDOUT(VOID)
  6432. {
  6433.     /* Flush the standard output streams so that
  6434.      * any following output will be printed after
  6435.      * any buffered stdio output.
  6436.      */
  6437.     if(WBenchMsg == NULL)
  6438.     {
  6439.         struct UFB * ufb;
  6440.  
  6441.         /* Don't let anybody stop us. */
  6442.         signal(SIGINT,SIG_IGN);
  6443.         signal(SIGTERM,SIG_IGN);
  6444.  
  6445.         ufb = chkufb(fileno(stdout));
  6446.         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6447.             fflush(stdout);
  6448.  
  6449.         ufb = chkufb(fileno(stderr));
  6450.         if(ufb != NULL && FLAG_IS_CLEAR(ufb->ufbflg,UFB_IS_SOCKET))
  6451.             fflush(stderr);
  6452.     }
  6453. }
  6454.  
  6455. VOID
  6456. _CXOVF(VOID)
  6457. {
  6458.     /* This routine is called when a stack overflow occurs. */
  6459.     FlushSTDOUT();
  6460.     ReportProblem("Stack overflow");
  6461.  
  6462.     exit(RETURN_ERROR);
  6463. }
  6464.  
  6465. VOID __regargs
  6466. _CXBRK(VOID)
  6467. {
  6468.     extern STRPTR _ProgramName;
  6469.  
  6470.     FlushSTDOUT();
  6471.  
  6472.     /* This routine is called when the program is interrupted. */
  6473.     if(DOSBase->lib_Version >= 37)
  6474.     {
  6475.         PrintFault(ERROR_BREAK,_ProgramName);
  6476.     }
  6477.     else
  6478.     {
  6479.         const char *famousLastWords = ": *** Break";
  6480.         BPTR output = Output();
  6481.  
  6482.         Write(output,(APTR)famousLastWords,strlen(famousLastWords));
  6483.         Write(output,_ProgramName,strlen(_ProgramName));
  6484.         Write(output,"\n",1);
  6485.     }
  6486.  
  6487.     exit(RETURN_WARN);
  6488. }
  6489.  
  6490. /******************************************************************************/
  6491.  
  6492. STATIC STRPTR SambaSemaphoreName = "Amiga Samba";
  6493.  
  6494. struct SambaClientNode
  6495. {
  6496.     struct MinNode    scn_MinNode;
  6497.     struct Task *    scn_Task;
  6498.     pid_t            scn_PID;
  6499. };
  6500.  
  6501. struct SambaSemaphore
  6502. {
  6503.     struct SignalSemaphore    ss_Semaphore;
  6504.     struct List                ss_ClientList;
  6505.     pid_t                    ss_PID;
  6506.     struct List                ss_FileLockList;
  6507. };
  6508.  
  6509. STATIC struct SambaSemaphore *    SambaSemaphore;
  6510. STATIC struct SambaClientNode *    ThisClient;
  6511.  
  6512. STATIC VOID
  6513. CleanupSambaSemaphore(VOID)
  6514. {
  6515.     if(ThisClient != NULL)
  6516.     {
  6517.         /* Unregister the program. */
  6518.         ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6519.         Remove((struct Node *)ThisClient);
  6520.         ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6521.  
  6522.         FreeVec(ThisClient);
  6523.         ThisClient = NULL;
  6524.     }
  6525. }
  6526.  
  6527. STATIC BOOL
  6528. SetupSambaSemaphore(VOID)
  6529. {
  6530.     BOOL success = FALSE;
  6531.  
  6532.     /* We have to have the timer open to serialize the process IDs properly. */
  6533.     if(TimerBase != NULL)
  6534.     {
  6535.         Forbid();
  6536.  
  6537.         /* Try to find the global rendezvous semaphore. */
  6538.         SambaSemaphore = (struct SambaSemaphore *)FindSemaphore(SambaSemaphoreName);
  6539.         if(SambaSemaphore == NULL)
  6540.         {
  6541.             /* Couldn't find it. So, we create it... */
  6542.             SambaSemaphore = AllocMem(sizeof(*SambaSemaphore) + strlen(SambaSemaphoreName)+1,MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6543.             if(SambaSemaphore != NULL)
  6544.             {
  6545.                 /* Set up the name. */
  6546.                 SambaSemaphore->ss_Semaphore.ss_Link.ln_Name = (char *)(SambaSemaphore+1);
  6547.                 strcpy(SambaSemaphore->ss_Semaphore.ss_Link.ln_Name,SambaSemaphoreName);
  6548.  
  6549.                 /* Set the base value for all process IDs. */
  6550.                 SambaSemaphore->ss_PID = 936;
  6551.  
  6552.                 /* Clear the client list tasks are going to be registered with. */
  6553.                 NewList(&SambaSemaphore->ss_ClientList);
  6554.  
  6555.                 /* Clear the list we will use for keeping
  6556.                  * track of file segment locks.
  6557.                  */
  6558.                 NewList(&SambaSemaphore->ss_FileLockList);
  6559.  
  6560.                 AddSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6561.             }
  6562.         }
  6563.  
  6564.         Permit();
  6565.     }
  6566.  
  6567.     /* If possible, register this task. */
  6568.     if(SambaSemaphore != NULL)
  6569.     {
  6570.         struct SambaClientNode * scn;
  6571.  
  6572.         scn = AllocVec(sizeof(*scn),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6573.         if(scn != NULL)
  6574.         {
  6575.             /* That's me. */
  6576.             scn->scn_Task = FindTask(NULL);
  6577.  
  6578.             ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6579.  
  6580.             /* Register this program with a new process ID. */
  6581.             scn->scn_PID = SambaSemaphore->ss_PID++;
  6582.             AddTail(&SambaSemaphore->ss_ClientList,(struct Node *)scn);
  6583.  
  6584.             ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6585.  
  6586.             ThisClient = scn;
  6587.  
  6588.             success = TRUE;
  6589.         }
  6590.     }
  6591.  
  6592.     return(success);
  6593. }
  6594.  
  6595. int
  6596. amiga_kill(pid_t pid,int sig)
  6597. {
  6598.     struct SambaClientNode * scn;
  6599.     struct Task * found = NULL;
  6600.     int result = ERROR;
  6601.  
  6602.     chkabort();
  6603.  
  6604.     ENTER();
  6605.  
  6606.     ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6607.  
  6608.     /* Try to find the Samba program that responds
  6609.      * to the given process ID.
  6610.      */
  6611.     for(scn = (struct SambaClientNode *)SambaSemaphore->ss_ClientList.lh_Head ;
  6612.         scn->scn_MinNode.mln_Succ != NULL ;
  6613.         scn = (struct SambaClientNode *)scn->scn_MinNode.mln_Succ)
  6614.     {
  6615.         if(scn->scn_PID == pid)
  6616.         {
  6617.             found = scn->scn_Task;
  6618.             break;
  6619.         }
  6620.     }
  6621.  
  6622.     /* Did we find one? */
  6623.     if(found != NULL)
  6624.     {
  6625.         /* Kill the task or just do nothing? */
  6626.         if(sig == SIGTERM)
  6627.             Signal(found,SIGBREAKF_CTRL_C);
  6628.  
  6629.         result = OK;
  6630.     }
  6631.     else
  6632.     {
  6633.         errno = ESRCH;
  6634.     }
  6635.  
  6636.     ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6637.  
  6638.     RETURN(result);
  6639.     return(result);
  6640. }
  6641.  
  6642. pid_t
  6643. amiga_getpid(VOID)
  6644. {
  6645.     pid_t result;
  6646.  
  6647.     chkabort();
  6648.  
  6649.     ENTER();
  6650.  
  6651.     /* Return this program's process ID. */
  6652.     result = ThisClient->scn_PID;
  6653.  
  6654.     RETURN(result);
  6655.     return(result);
  6656. }
  6657.  
  6658. /******************************************************************************/
  6659.  
  6660. struct LockedRegionNode
  6661. {
  6662.     struct MinNode    lrn_MinNode;
  6663.     LONG            lrn_Start;
  6664.     LONG            lrn_Stop;
  6665.     pid_t            lrn_Owner;
  6666.     BOOL            lrn_Shared;
  6667. };
  6668.  
  6669. struct FileLockNode
  6670. {
  6671.     struct MinNode    fln_MinNode;
  6672.     struct List        fln_LockedRegionList;
  6673.     BPTR            fln_FileParentDir;
  6674.     UBYTE            fln_FileName[1];
  6675. };
  6676.  
  6677. STATIC VOID
  6678. RemoveLockedRegionNode(struct UFB * ufb,LONG start,LONG stop)
  6679. {
  6680.     if(FLAG_IS_SET(ufb->ufbflg,UFB_LOCKED))
  6681.     {
  6682.         BPTR fileHandle = (BPTR)ufb->ufbfh;
  6683.         struct FileLockNode * whichLock;
  6684.  
  6685.         /* Find the locked file this descriptor
  6686.          * buffer belongs to.
  6687.          */
  6688.         if(FindFileLockNodeByFileHandle(fileHandle,&whichLock) == OK && whichLock != NULL)
  6689.         {
  6690.             struct LockedRegionNode * lrn;
  6691.  
  6692.             /* Find the region to unlock and remove it. */
  6693.             for(lrn = (struct LockedRegionNode *)whichLock->fln_LockedRegionList.lh_Head ;
  6694.                 lrn->lrn_MinNode.mln_Succ != NULL ;
  6695.                 lrn = (struct LockedRegionNode *)lrn->lrn_MinNode.mln_Succ)
  6696.             {
  6697.                 if(lrn->lrn_Owner == ThisClient->scn_PID &&
  6698.                    lrn->lrn_Start == start &&
  6699.                    lrn->lrn_Stop  == stop)
  6700.                 {
  6701.                     SHOWMSG("unlocking all regions on this file");
  6702.  
  6703.                     Remove((struct Node *)lrn);
  6704.                     DeleteLockedRegionNode(lrn);
  6705.                     break;
  6706.                 }
  6707.             }
  6708.  
  6709.             /* Check if there are any locked regions left.
  6710.              * If not, mark the entire file as unlocked.
  6711.              */
  6712.             if(IsListEmpty(&whichLock->fln_LockedRegionList))
  6713.             {
  6714.                 SHOWMSG("no more regions are locked; removing the file lock node");
  6715.  
  6716.                 Remove((struct Node *)whichLock);
  6717.  
  6718.                 DeleteFileLockNode(whichLock);
  6719.  
  6720.                 CLEAR_FLAG(ufb->ufbflg,UFB_LOCKED);
  6721.             }
  6722.         }
  6723.     }
  6724. }
  6725.  
  6726. STATIC VOID
  6727. DeleteLockedRegionNode(struct LockedRegionNode * lrn)
  6728. {
  6729.     if(lrn != NULL)
  6730.         FreeMem(lrn,sizeof(*lrn));
  6731. }
  6732.  
  6733. STATIC LONG
  6734. CreateLockedRegionNode(struct LockedRegionNode ** resultPtr)
  6735. {
  6736.     struct LockedRegionNode * lrn;
  6737.     LONG error;
  6738.  
  6739.     lrn = AllocMem(sizeof(*lrn),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6740.     if(lrn != NULL)
  6741.     {
  6742.         lrn->lrn_Owner = ThisClient->scn_PID;
  6743.  
  6744.         error = OK;
  6745.     }
  6746.     else
  6747.     {
  6748.         error = ERROR_NO_FREE_STORE;
  6749.     }
  6750.  
  6751.     (*resultPtr) = lrn;
  6752.  
  6753.     return(error);
  6754. }
  6755.  
  6756. STATIC VOID
  6757. DeleteFileLockNode(struct FileLockNode * fln)
  6758. {
  6759.     if(fln != NULL)
  6760.     {
  6761.         UnLock(fln->fln_FileParentDir);
  6762.         FreeVec(fln);
  6763.     }
  6764. }
  6765.  
  6766. STATIC LONG
  6767. CreateFileLockNode(struct UFB * ufb,struct FileLockNode ** resultPtr)
  6768. {
  6769.     struct FileLockNode * result = NULL;
  6770.     BPTR fileHandle = (BPTR)ufb->ufbfh;
  6771.     struct FileInfoBlock __aligned fib;
  6772.     LONG error = OK;
  6773.  
  6774.     /* We store a lock on the file's parent directory
  6775.      * and the name of the file for later use in
  6776.      * comparisons.
  6777.      */
  6778.     if(ExamineFH(fileHandle,&fib))
  6779.     {
  6780.         struct FileLockNode * fln;
  6781.  
  6782.         fln = AllocVec(sizeof(*fln) + strlen(fib.fib_FileName),MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR);
  6783.         if(fln != NULL)
  6784.         {
  6785.             fln->fln_FileParentDir = ParentOfFH(fileHandle);
  6786.             if(fln->fln_FileParentDir != ZERO)
  6787.             {
  6788.                 strcpy(fln->fln_FileName,fib.fib_FileName);
  6789.  
  6790.                 NewList(&fln->fln_LockedRegionList);
  6791.  
  6792.                 result = fln;
  6793.                 fln = NULL;
  6794.             }
  6795.             else
  6796.             {
  6797.                 error = IoErr();
  6798.             }
  6799.  
  6800.             DeleteFileLockNode(fln);
  6801.         }
  6802.         else
  6803.         {
  6804.             error = ERROR_NO_FREE_STORE;
  6805.         }
  6806.     }
  6807.     else
  6808.     {
  6809.         error = IoErr();
  6810.     }
  6811.  
  6812.     (*resultPtr) = result;
  6813.  
  6814.     return(error);
  6815. }
  6816.  
  6817. STATIC LONG
  6818. FindFileLockNodeByFileHandle(BPTR fileHandle,struct FileLockNode ** resultPtr)
  6819. {
  6820.     struct FileLockNode * result = NULL;
  6821.     BPTR parentDir;
  6822.     LONG error;
  6823.  
  6824.     /* Determine the file's parent directory and
  6825.      * name. These will be compared against the
  6826.      * global file lock data.
  6827.      */
  6828.     parentDir = ParentOfFH(fileHandle);
  6829.     if(parentDir != ZERO)
  6830.     {
  6831.         struct FileInfoBlock __aligned this_fib;
  6832.  
  6833.         if(ExamineFH(fileHandle,&this_fib))
  6834.         {
  6835.             struct FileLockNode * fln;
  6836.  
  6837.             #if DEBUG
  6838.             {
  6839.                 char name[MAX_FILENAME_LEN];
  6840.  
  6841.                 if(NameFromFH(fileHandle,name,sizeof(name)))
  6842.                     D(("Looking for a lock on file |%s|",name));
  6843.             }
  6844.             #endif /* DEBUG */
  6845.  
  6846.             error = OK;
  6847.  
  6848.             for(fln = (struct FileLockNode *)SambaSemaphore->ss_FileLockList.lh_Head ;
  6849.                 fln->fln_MinNode.mln_Succ != NULL ;
  6850.                 fln = (struct FileLockNode *)fln->fln_MinNode.mln_Succ)
  6851.             {
  6852.                 /* To be identical, the files must reside in the
  6853.                  * same directories and bear the same names.
  6854.                  */
  6855.                 if(SameLock(fln->fln_FileParentDir,parentDir) == LOCK_SAME)
  6856.                 {
  6857.                     if(Stricmp(fln->fln_FileName,this_fib.fib_FileName) == SAME)
  6858.                     {
  6859.                         result = fln;
  6860.                         error = OK;
  6861.  
  6862.                         break;
  6863.                     }
  6864.                 }
  6865.             }
  6866.         }
  6867.         else
  6868.         {
  6869.             error = IoErr();
  6870.         }
  6871.  
  6872.         if(result != NULL)
  6873.             SHOWMSG("found one");
  6874.         else
  6875.             SHOWMSG("didn't find one");
  6876.  
  6877.         UnLock(parentDir);
  6878.     }
  6879.     else
  6880.     {
  6881.         error = IoErr();
  6882.     }
  6883.  
  6884.     (*resultPtr) = result;
  6885.  
  6886.     return(error);
  6887. }
  6888.  
  6889. STATIC VOID
  6890. FindFileLockNodeByDrawerAndName(BPTR dirLock,STRPTR fileName,struct FileLockNode ** resultPtr)
  6891. {
  6892.     struct FileLockNode * result = NULL;
  6893.     struct FileLockNode * fln;
  6894.  
  6895.     /* This is a somewhat simplied version of FindFileLockNodeByFileHandle()
  6896.      * which works with preset drawer and name data.
  6897.      */
  6898.  
  6899.     #if DEBUG
  6900.     {
  6901.         char name[MAX_FILENAME_LEN];
  6902.  
  6903.         if(NameFromLock(dirLock,name,sizeof(name)))
  6904.         {
  6905.             if(AddPart(name,fileName,sizeof(name)))
  6906.                 D(("Looking for a lock on file |%s|",name));
  6907.         }
  6908.     }
  6909.     #endif /* DEBUG */
  6910.  
  6911.     for(fln = (struct FileLockNode *)SambaSemaphore->ss_FileLockList.lh_Head ;
  6912.         fln->fln_MinNode.mln_Succ != NULL ;
  6913.         fln = (struct FileLockNode *)fln->fln_MinNode.mln_Succ)
  6914.     {
  6915.         if(SameLock(fln->fln_FileParentDir,dirLock) == LOCK_SAME)
  6916.         {
  6917.             if(Stricmp(fln->fln_FileName,fileName) == SAME)
  6918.             {
  6919.                 result = fln;
  6920.  
  6921.                 break;
  6922.             }
  6923.         }
  6924.     }
  6925.  
  6926.     if(result != NULL)
  6927.         SHOWMSG("found one");
  6928.     else
  6929.         SHOWMSG("didn't find one");
  6930.  
  6931.     (*resultPtr) = result;
  6932. }
  6933.  
  6934. STATIC struct LockedRegionNode *
  6935. FindCollidingRegion(struct FileLockNode * fln,LONG start,LONG stop,BOOL shared)
  6936. {
  6937.     struct LockedRegionNode * result = NULL;
  6938.     struct LockedRegionNode * lrn;
  6939.  
  6940.     /* This routine looks for a locked region that overlaps
  6941.      * with the specified region. It returns a pointer to the
  6942.      * region that would collide with the specified region if
  6943.      * a new lock were to be added.
  6944.      */
  6945.     for(lrn = (struct LockedRegionNode *)fln->fln_LockedRegionList.lh_Head ;
  6946.         lrn->lrn_MinNode.mln_Succ != NULL ;
  6947.         lrn = (struct LockedRegionNode *)lrn->lrn_MinNode.mln_Succ)
  6948.     {
  6949.         /* Do the regions overlap? */
  6950.         if(lrn->lrn_Start <= stop && start <= lrn->lrn_Stop)
  6951.         {
  6952.             /* Two shared regions may always overlap.
  6953.              * How about the rest?
  6954.              */
  6955.             if(NOT shared || NOT lrn->lrn_Shared)
  6956.             {
  6957.                 /* The lock owner may add as many exclusive
  6958.                  * or shared locks to the same region as
  6959.                  * necessary.
  6960.                  */
  6961.                 if(lrn->lrn_Owner == ThisClient->scn_PID)
  6962.                     continue;
  6963.  
  6964.                 /* So we found a region that would
  6965.                  * cause a collision.
  6966.                  */
  6967.                 result = lrn;
  6968.                 break;
  6969.             }
  6970.         }
  6971.     }
  6972.  
  6973.     return(result);
  6974. }
  6975.  
  6976. STATIC VOID
  6977. CleanupFileLocks(int fd)
  6978. {
  6979.     struct UFB * ufb;
  6980.  
  6981.     /* This routine removes all locked regions from a file
  6982.      * before it is eventually closed.
  6983.      */
  6984.  
  6985.     ufb = chkufb(fd);
  6986.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_LOCKED))
  6987.     {
  6988.         BPTR fileHandle = (BPTR)ufb->ufbfh;
  6989.         struct FileLockNode * whichLock;
  6990.  
  6991.         ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  6992.  
  6993.         if(FindFileLockNodeByFileHandle(fileHandle,&whichLock) == OK && whichLock != NULL)
  6994.         {
  6995.             struct LockedRegionNode * lrn_this;
  6996.             struct LockedRegionNode * lrn_next;
  6997.  
  6998.             SHOWMSG("unlocking all regions on this file");
  6999.  
  7000.             for(lrn_this = (struct LockedRegionNode *)whichLock->fln_LockedRegionList.lh_Head ;
  7001.                (lrn_next = (struct LockedRegionNode *)lrn_this->lrn_MinNode.mln_Succ) != NULL ;
  7002.                 lrn_this = lrn_next)
  7003.             {
  7004.                 if(lrn_this->lrn_Owner == ThisClient->scn_PID)
  7005.                 {
  7006.                     Remove((struct Node *)lrn_this);
  7007.                     DeleteLockedRegionNode(lrn_this);
  7008.                 }
  7009.             }
  7010.  
  7011.             if(IsListEmpty(&whichLock->fln_LockedRegionList))
  7012.             {
  7013.                 SHOWMSG("no more regions are locked; removing the file lock node");
  7014.  
  7015.                 Remove((struct Node *)whichLock);
  7016.  
  7017.                 DeleteFileLockNode(whichLock);
  7018.             }
  7019.         }
  7020.  
  7021.         CLEAR_FLAG(ufb->ufbflg,UFB_LOCKED);
  7022.  
  7023.         ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7024.     }
  7025. }
  7026.  
  7027. #define SEEK_ERROR (-1)
  7028.  
  7029. STATIC int
  7030. HandleFileLocking(int cmd,struct flock * l,struct UFB * ufb)
  7031. {
  7032.     int result = ERROR;
  7033.  
  7034.     /* This routine implements advisory file segment locking
  7035.      * similar to 4.4BSD, but not quite the same. The functionality
  7036.      * is a subset, somewhat similar to the functionality offered
  7037.      * by the AmigaDOS LockRecord() and UnlockRecord() functions.
  7038.      * This means for example that every unlock request must
  7039.      * match the size and position of the corresponding locking
  7040.      * request.
  7041.      *
  7042.      * This implementation was chosen because not every Amiga
  7043.      * filing system implements record locking and Samba
  7044.      * absolutely requires this functionality to work.
  7045.      */
  7046.     if(l != NULL && ufb != NULL)
  7047.     {
  7048.         /* Can we make sense of the input parameters? */
  7049.         if(F_RDLCK <= l->l_type && l->l_type <= F_WRLCK &&
  7050.           (l->l_whence == SEEK_SET || l->l_whence == SEEK_CUR || l->l_whence == SEEK_END))
  7051.         {
  7052.             struct LockedRegionNode * lrn = NULL;
  7053.             struct FileLockNode * fln = NULL;
  7054.             LONG error;
  7055.  
  7056.             if((cmd == F_SETLK || cmd == F_SETLKW) && (l->l_type != F_UNLCK))
  7057.             {
  7058.                 SHOWMSG("this is a lock request");
  7059.                 error = CreateFileLockNode(ufb,&fln);
  7060.                 if(error == OK)
  7061.                     error = CreateLockedRegionNode(&lrn);
  7062.             }
  7063.             else
  7064.             {
  7065.                 SHOWMSG("this is not a lock request");
  7066.                 error = OK;
  7067.             }
  7068.  
  7069.             if(error == OK)
  7070.             {
  7071.                 struct FileInfoBlock __aligned fib;
  7072.                 BPTR fileHandle = (BPTR)ufb->ufbfh;
  7073.                 BOOL dataIsValid = TRUE;
  7074.                 LONG currentPosition;
  7075.                 LONG start = 0;
  7076.                 LONG len = 0;
  7077.  
  7078.                 /* Now calculate the position of the
  7079.                  * first byte to lock and the number
  7080.                  * of bytes to lock.
  7081.                  */
  7082.                 switch(l->l_whence)
  7083.                 {
  7084.                     case SEEK_SET:
  7085.  
  7086.                         start = l->l_start;
  7087.  
  7088.                         if(l->l_len == 0)
  7089.                         {
  7090.                             if(ExamineFH(fileHandle,&fib))
  7091.                                 len = fib.fib_Size - start;
  7092.                             else
  7093.                                 dataIsValid = FALSE;
  7094.                         }
  7095.                         else
  7096.                         {
  7097.                             len = l->l_len;
  7098.                         }
  7099.  
  7100.                         break;
  7101.  
  7102.                     case SEEK_CUR:
  7103.  
  7104.                         currentPosition = Seek(fileHandle,0,OFFSET_CURRENT);
  7105.                         if(currentPosition != SEEK_ERROR)
  7106.                         {
  7107.                             start = currentPosition + l->l_start;
  7108.  
  7109.                             if(l->l_len == 0)
  7110.                             {
  7111.                                 if(ExamineFH(fileHandle,&fib))
  7112.                                     len = fib.fib_Size - start;
  7113.                                 else
  7114.                                     dataIsValid = FALSE;
  7115.                             }
  7116.                             else
  7117.                             {
  7118.                                 len = l->l_len;
  7119.                             }
  7120.                         }
  7121.                         else
  7122.                         {
  7123.                             dataIsValid = FALSE;
  7124.                         }
  7125.  
  7126.                         break;
  7127.  
  7128.                     case SEEK_END:
  7129.                     default:
  7130.  
  7131.                         if(ExamineFH(fileHandle,&fib))
  7132.                         {
  7133.                             start = fib.fib_Size + l->l_start;
  7134.  
  7135.                             if(l->l_len == 0)
  7136.                                 len = fib.fib_Size - start;
  7137.                             else
  7138.                                 len = l->l_len;
  7139.                         }
  7140.                         else
  7141.                         {
  7142.                             dataIsValid = FALSE;
  7143.                         }
  7144.  
  7145.                         break;
  7146.                 }
  7147.  
  7148.                 SHOWVALUE(start);
  7149.                 SHOWVALUE(len);
  7150.  
  7151.                 /* Did we get everything we needed? */
  7152.                 if(dataIsValid)
  7153.                 {
  7154.                     if(start >= 0 && len >= 0)
  7155.                     {
  7156.                         if(len > 0)
  7157.                         {
  7158.                             if(l->l_type == F_UNLCK)
  7159.                             {
  7160.                                 D(("unlocking %ld..%ld",start,start+len-1));
  7161.  
  7162.                                 ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7163.  
  7164.                                 RemoveLockedRegionNode(ufb,start,start+len-1);
  7165.  
  7166.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7167.  
  7168.                                 result = OK;
  7169.                             }
  7170.                             else if(cmd == F_SETLKW)
  7171.                             {
  7172.                                 BPTR parentDir;
  7173.  
  7174.                                 D(("  locking %ld..%ld",start,start+len-1));
  7175.  
  7176.                                 parentDir = ParentOfFH(fileHandle);
  7177.                                 if(parentDir != ZERO)
  7178.                                 {
  7179.                                     struct FileInfoBlock __aligned fib;
  7180.  
  7181.                                     if(ExamineFH(fileHandle,&fib))
  7182.                                     {
  7183.                                         BOOL shared = (BOOL)(l->l_type == F_RDLCK);
  7184.                                         struct FileLockNode * existing_fln;
  7185.                                         BOOL stopped = FALSE;
  7186.                                         BOOL locked;
  7187.  
  7188.                                         if(shared)
  7189.                                             D(("this is a shared lock; waiting for completion"));
  7190.                                         else
  7191.                                             D(("this is an exclusive lock; waiting for completion"));
  7192.  
  7193.                                         lrn->lrn_Start    = start;
  7194.                                         lrn->lrn_Stop    = start+len-1;
  7195.                                         lrn->lrn_Shared    = shared;
  7196.  
  7197.                                         /* Retry until we manage to lock the record. */
  7198.                                         locked = FALSE;
  7199.                                         do
  7200.                                         {
  7201.                                             ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7202.  
  7203.                                             FindFileLockNodeByDrawerAndName(parentDir,fib.fib_FileName,&existing_fln);
  7204.                                             if(existing_fln != NULL)
  7205.                                             {
  7206.                                                 SHOWMSG("that file is already locked by someone");
  7207.  
  7208.                                                 if(FindCollidingRegion(existing_fln,start,start+len-1,shared) == NULL)
  7209.                                                 {
  7210.                                                     SHOWMSG("but the locks don't collide");
  7211.  
  7212.                                                     AddTail(&existing_fln->fln_LockedRegionList,(struct Node *)lrn);
  7213.                                                     lrn = NULL;
  7214.  
  7215.                                                     locked = TRUE;
  7216.                                                 }
  7217.                                                 else
  7218.                                                 {
  7219.                                                     SHOWMSG("and the locks collide");
  7220.                                                 }
  7221.                                             }
  7222.                                             else
  7223.                                             {
  7224.                                                 SHOWMSG("nobody has any locks on this file");
  7225.  
  7226.                                                 AddTail(&SambaSemaphore->ss_FileLockList,(struct Node *)fln);
  7227.                                                 AddTail(&fln->fln_LockedRegionList,(struct Node *)lrn);
  7228.  
  7229.                                                 fln = NULL;
  7230.                                                 lrn = NULL;
  7231.  
  7232.                                                 locked = TRUE;
  7233.                                             }
  7234.  
  7235.                                             ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7236.  
  7237.                                             if(NOT locked)
  7238.                                             {
  7239.                                                 const int randMax = RAND_MAX / 65536;
  7240.                                                 LONG numRandomTicks;
  7241.  
  7242.                                                 if(CheckAbort())
  7243.                                                 {
  7244.                                                     stopped = TRUE;
  7245.                                                     break;
  7246.                                                 }
  7247.  
  7248.                                                 /* Wait a little before retrying
  7249.                                                  * the locking operation. We add
  7250.                                                  * a little randomness here to
  7251.                                                  * reduce the likelihood of two
  7252.                                                  * competing processes trying to
  7253.                                                  * lock the same file at the
  7254.                                                  * same time.
  7255.                                                  */
  7256.  
  7257.                                                 numRandomTicks = ((TICKS_PER_SECOND / 2) * (rand() / 65536)) / randMax;
  7258.  
  7259.                                                 if(numRandomTicks > 0)
  7260.                                                     Delay(numRandomTicks);
  7261.                                             }
  7262.                                         }
  7263.                                         while(NOT locked);
  7264.  
  7265.                                         if(stopped)
  7266.                                         {
  7267.                                             SHOWMSG("lock polling loop stopped");
  7268.  
  7269.                                             DeleteFileLockNode(fln);
  7270.                                             fln = NULL;
  7271.  
  7272.                                             DeleteLockedRegionNode(lrn);
  7273.                                             lrn = NULL;
  7274.  
  7275.                                             UnLock(parentDir);
  7276.                                             parentDir = ZERO;
  7277.  
  7278.                                             errno = EINTR;
  7279.  
  7280.                                             raise(SIGINT);
  7281.                                         }
  7282.  
  7283.                                         if(locked)
  7284.                                         {
  7285.                                             SHOWMSG("the file now has a lock set");
  7286.                                             SET_FLAG(ufb->ufbflg,UFB_LOCKED);
  7287.                                             result = OK;
  7288.                                         }
  7289.                                     }
  7290.                                     else
  7291.                                     {
  7292.                                         SHOWMSG("couldn't read this file's name");
  7293.                                         MapIoErrToErrno();
  7294.                                     }
  7295.  
  7296.                                     UnLock(parentDir);
  7297.                                 }
  7298.                                 else
  7299.                                 {
  7300.                                     SHOWMSG("couldn't get a lock on the file's parent directory");
  7301.                                     MapIoErrToErrno();
  7302.                                 }
  7303.                             }
  7304.                             else if(cmd == F_SETLK)
  7305.                             {
  7306.                                 BOOL shared = (BOOL)(l->l_type == F_RDLCK);
  7307.                                 struct FileLockNode * existing_fln;
  7308.                                 BOOL locked = FALSE;
  7309.  
  7310.                                 if(shared)
  7311.                                     D(("this is a shared lock"));
  7312.                                 else
  7313.                                     D(("this is an exclusive lock"));
  7314.  
  7315.                                 lrn->lrn_Start    = start;
  7316.                                 lrn->lrn_Stop    = start+len-1;
  7317.                                 lrn->lrn_Shared    = shared;
  7318.  
  7319.                                 ObtainSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7320.  
  7321.                                 if(FindFileLockNodeByFileHandle(fileHandle,&existing_fln) == OK)
  7322.                                 {
  7323.                                     if(existing_fln != NULL)
  7324.                                     {
  7325.                                         SHOWMSG("that file is already locked by someone else");
  7326.  
  7327.                                         if(FindCollidingRegion(existing_fln,start,start+len-1,shared) == NULL)
  7328.                                         {
  7329.                                             SHOWMSG("but the locks don't collide");
  7330.  
  7331.                                             AddTail(&existing_fln->fln_LockedRegionList,(struct Node *)lrn);
  7332.                                             lrn = NULL;
  7333.  
  7334.                                             locked = TRUE;
  7335.                                         }
  7336.                                         else
  7337.                                         {
  7338.                                             SHOWMSG("and the locks collide");
  7339.                                         }
  7340.                                     }
  7341.                                     else
  7342.                                     {
  7343.                                         SHOWMSG("nobody has any locks on this file");
  7344.  
  7345.                                         AddTail(&SambaSemaphore->ss_FileLockList,(struct Node *)fln);
  7346.                                         AddTail(&fln->fln_LockedRegionList,(struct Node *)lrn);
  7347.  
  7348.                                         fln = NULL;
  7349.                                         lrn = NULL;
  7350.  
  7351.                                         locked = TRUE;
  7352.                                     }
  7353.                                 }
  7354.  
  7355.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7356.  
  7357.                                 if(locked)
  7358.                                 {
  7359.                                     SHOWMSG("the file now has a lock set");
  7360.  
  7361.                                     SET_FLAG(ufb->ufbflg,UFB_LOCKED);
  7362.  
  7363.                                     result = OK;
  7364.                                 }
  7365.                                 else
  7366.                                 {
  7367.                                     errno = EACCES;
  7368.                                 }
  7369.                             }
  7370.                             else if (cmd == F_GETLK)
  7371.                             {
  7372.                                 struct FileLockNode * fln;
  7373.                                 LONG error;
  7374.  
  7375.                                 SafeObtainSemaphoreShared((struct SignalSemaphore *)SambaSemaphore);
  7376.  
  7377.                                 SHOWMSG("checking for possible lock collision");
  7378.  
  7379.                                 error = FindFileLockNodeByFileHandle(fileHandle,&fln);
  7380.                                 if(error == OK)
  7381.                                 {
  7382.                                     if(fln != NULL)
  7383.                                     {
  7384.                                         struct LockedRegionNode * lrn;
  7385.                                         BOOL shared;
  7386.  
  7387.                                         SHOWMSG("somebody has locked this file");
  7388.  
  7389.                                         shared = (BOOL)(l->l_type == F_RDLCK);
  7390.  
  7391.                                         lrn = FindCollidingRegion(fln,start,start+len-1,shared);
  7392.                                         if(lrn != NULL)
  7393.                                         {
  7394.                                             SHOWMSG("there is a possible lock collision");
  7395.  
  7396.                                             l->l_type    = (lrn->lrn_Shared ? F_RDLCK : F_WRLCK);
  7397.                                             l->l_whence    = SEEK_SET;
  7398.                                             l->l_start    = lrn->lrn_Start;
  7399.                                             l->l_len    = lrn->lrn_Stop - lrn->lrn_Start + 1;
  7400.                                             l->l_pid    = lrn->lrn_Owner;
  7401.                                         }
  7402.                                         else
  7403.                                         {
  7404.                                             SHOWMSG("there is no lock collision");
  7405.  
  7406.                                             l->l_type = F_UNLCK;
  7407.                                         }
  7408.                                     }
  7409.                                     else
  7410.                                     {
  7411.                                         SHOWMSG("nobody has locked this file");
  7412.  
  7413.                                         l->l_type = F_UNLCK;
  7414.                                     }
  7415.  
  7416.                                     result = OK;
  7417.                                 }
  7418.                                 else
  7419.                                 {
  7420.                                     SetIoErr(error);
  7421.  
  7422.                                     MapIoErrToErrno();
  7423.                                 }
  7424.  
  7425.                                 ReleaseSemaphore((struct SignalSemaphore *)SambaSemaphore);
  7426.                             }
  7427.                         }
  7428.                         else
  7429.                         {
  7430.                             SHOWMSG("zero length lock/unlock");
  7431.                             result = OK;
  7432.                         }
  7433.                     }
  7434.                     else
  7435.                     {
  7436.                         SHOWMSG("invalid start/len");
  7437.                         SHOWVALUE(start);
  7438.                         SHOWVALUE(len);
  7439.                         errno = EINVAL;
  7440.                     }
  7441.                 }
  7442.                 else
  7443.                 {
  7444.                     SHOWMSG("couldn't determine start/len");
  7445.                     MapIoErrToErrno();
  7446.                 }
  7447.             }
  7448.             else
  7449.             {
  7450.                 SHOWMSG("couldn't get the bookkeeping memory needed");
  7451.                 MapIoErrToErrno();
  7452.             }
  7453.  
  7454.             DeleteFileLockNode(fln);
  7455.             DeleteLockedRegionNode(lrn);
  7456.         }
  7457.         else
  7458.         {
  7459.             SHOWMSG("invalid lock type or seek offset");
  7460.             SHOWVALUE(l->l_type);
  7461.             SHOWVALUE(l->l_whence);
  7462.             errno = EINVAL;
  7463.         }
  7464.     }
  7465.     else
  7466.     {
  7467.         SHOWMSG("no flock or no ufb");
  7468.         SHOWVALUE(l);
  7469.         SHOWVALUE(ufb);
  7470.  
  7471.         errno = EINVAL;
  7472.     }
  7473.  
  7474.     RETURN(result);
  7475.     return(result);
  7476. }
  7477.  
  7478. int
  7479. amiga_fcntl(int fd,int cmd,unsigned long arg)
  7480. {
  7481.     struct UFB * ufb;
  7482.     struct flock * l;
  7483.     int result = ERROR;
  7484.  
  7485.     chkabort();
  7486.  
  7487.     ENTER();
  7488.  
  7489.     /* Don't try to lock data in a socket... */
  7490.     ufb = chkufb(fd);
  7491.     if(ufb == NULL || FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7492.         ufb = NULL;
  7493.  
  7494.     l = (struct flock *)arg;
  7495.  
  7496.     switch(cmd)
  7497.     {
  7498.         /* Get the first lock that blocks the lock description pointed to
  7499.          * by the third argument, arg, taken as a pointer to a struct
  7500.          * flock (see above).  The information retrieved overwrites the
  7501.          * information passed to fcntl in the flock structure.  If no
  7502.          * lock is found that would prevent this lock from being created,
  7503.          * the structure is left unchanged by this function call except
  7504.          * for the lock type which is set to F_UNLCK.
  7505.          */
  7506.         case F_GETLK:
  7507.  
  7508.             SHOWMSG("F_GETLK");
  7509.             result = HandleFileLocking(cmd,l,ufb);
  7510.             break;
  7511.  
  7512.         /* Set or clear a file segment lock according to the lock de-
  7513.          * scription pointed to by the third argument, arg, taken as a
  7514.          * pointer to a struct flock (see above).    F_SETLK is used to es-
  7515.          * tablish shared (or read) locks (F_RDLCK) or exclusive (or
  7516.          * write) locks, (F_WRLCK), as well as remove either type of lock
  7517.          * (F_UNLCK). If a shared or exclusive lock cannot be set, fcntl
  7518.          * returns immediately with EACCES.
  7519.          */
  7520.         case F_SETLK:
  7521.  
  7522.             SHOWMSG("F_SETLK");
  7523.             result = HandleFileLocking(cmd,l,ufb);
  7524.             break;
  7525.  
  7526.         /* This command is the same as F_SETLK except that if a shared or
  7527.          * exclusive lock is blocked by other locks, the process waits
  7528.          * until the request can be satisfied.  If a signal that is to be
  7529.          * caught is received while fcntl is waiting for a region, the
  7530.          * fcntl will be interrupted if the signal handler has not speci-
  7531.          * fied the SA_RESTART (see sigaction(2)).
  7532.          */
  7533.         case F_SETLKW:
  7534.  
  7535.             SHOWMSG("F_SETLKW");
  7536.             result = HandleFileLocking(cmd,l,ufb);
  7537.             break;
  7538.  
  7539.         /* Get descriptor status flags, as described below (arg is ig-
  7540.          * noted).
  7541.          */
  7542.         case F_GETFL:
  7543.  
  7544.             SHOWMSG("F_GETFL");
  7545.             result = IsDescriptorNonblocking(fd) ? O_NONBLOCK : 0;
  7546.             break;
  7547.  
  7548.         /* Set descriptor status flags to arg. */
  7549.         case F_SETFL:
  7550.  
  7551.             SHOWMSG("F_SETFL");
  7552.             if(FLAG_IS_SET(arg,O_NONBLOCK))
  7553.                 BlockDescriptor(fd);
  7554.             else
  7555.                 UnblockDescriptor(fd);
  7556.  
  7557.             result = OK;
  7558.             break;
  7559.  
  7560.         default:
  7561.  
  7562.             D(("Unknown command %ld",cmd));
  7563.             errno = ENOSYS;
  7564.             break;
  7565.     }
  7566.  
  7567.     RETURN(result);
  7568.     return(result);
  7569. }
  7570.  
  7571. /******************************************************************************/
  7572.  
  7573. int
  7574. amiga_fgetc(FILE *in)
  7575. {
  7576.     struct UFB * ufb;
  7577.     int result = ERROR;
  7578.  
  7579.     PUSH_ASSERTS();
  7580.  
  7581.     chkabort();
  7582.  
  7583.     ufb = chkufb(fileno(in));
  7584.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7585.     {
  7586.         UBYTE c;
  7587.  
  7588.         ENTER();
  7589.         SHOWMSG("input from socket");
  7590.  
  7591.         if(recv(ufb->ufbfh,&c,1,0) == 1)
  7592.             result = c;
  7593.     }
  7594.     else
  7595.     {
  7596.         result = fgetc(in);
  7597.     }
  7598.  
  7599.     RETURN(result);
  7600.     POP();
  7601.     return(result);
  7602. }
  7603.  
  7604. char *
  7605. amiga_fgets(char *str,int n,FILE * in)
  7606. {
  7607.     struct UFB * ufb;
  7608.     char *result;
  7609.  
  7610.     ENTER();
  7611.  
  7612.     ufb = chkufb(fileno(in));
  7613.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7614.     {
  7615.         char *s = str;
  7616.         LONG rc;
  7617.         UBYTE c;
  7618.  
  7619.         SHOWMSG("input from socket");
  7620.         result = str;
  7621.  
  7622.         while(--n > 0)
  7623.         {
  7624.             chkabort();
  7625.  
  7626.             rc = recv(ufb->ufbfh,&c,1,0);
  7627.             if(rc == 1)
  7628.             {
  7629.                 (*str++) = c;
  7630.  
  7631.                 if(c == '\n')
  7632.                     break;
  7633.             }
  7634.             else
  7635.             {
  7636.                 /* End of stream or nothing read? */
  7637.                 if(rc < 0 || str == s)
  7638.                     result = NULL;
  7639.  
  7640.                 break;
  7641.             }
  7642.         }
  7643.  
  7644.         if(result != NULL)
  7645.             (*str) = '\0';
  7646.     }
  7647.     else
  7648.     {
  7649.         result = fgets(str,n,in);
  7650.     }
  7651.  
  7652.     RETURN(result);
  7653.     return(result);
  7654. }
  7655.  
  7656. int
  7657. amiga_fputs(const char *str,FILE *out)
  7658. {
  7659.     struct UFB * ufb;
  7660.     int result;
  7661.  
  7662.     chkabort();
  7663.  
  7664.     ENTER();
  7665.  
  7666.     ufb = chkufb(fileno(out));
  7667.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7668.     {
  7669.         SHOWMSG("output to socket");
  7670.  
  7671.         if(NOT STRING_IS_EMPTY(str))
  7672.             result = send(ufb->ufbfh,str,strlen(str),0);
  7673.         else
  7674.             result = OK;
  7675.  
  7676.         if(result == OK)
  7677.             result = send(ufb->ufbfh,"\n",1,0);
  7678.     }
  7679.     else
  7680.     {
  7681.         result = fputs(str,out);
  7682.     }
  7683.  
  7684.     RETURN(result);
  7685.     return(result);
  7686. }
  7687.  
  7688. int
  7689. amiga_puts(const char *str)
  7690. {
  7691.     int result;
  7692.  
  7693.     result = amiga_fputs(str,stdout);
  7694.  
  7695.     return(result);
  7696. }
  7697.  
  7698. int
  7699. amiga_vfprintf(FILE *out,const char *fmt,va_list args)
  7700. {
  7701.     struct UFB * ufb;
  7702.     int result;
  7703.  
  7704.     chkabort();
  7705.  
  7706.     ENTER();
  7707.  
  7708.     ufb = chkufb(fileno(out));
  7709.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7710.     {
  7711.         char buffer[1024];
  7712.  
  7713.         SHOWMSG("output to socket");
  7714.  
  7715.         vsnprintf(buffer,sizeof(buffer)-1,fmt,args);
  7716.         buffer[sizeof(buffer)-1] = '\0';
  7717.  
  7718.         if(NOT STRING_IS_EMPTY(buffer))
  7719.             result = send(ufb->ufbfh,buffer,strlen(buffer),0);
  7720.         else
  7721.             result = 0;
  7722.     }
  7723.     else
  7724.     {
  7725.         result = vfprintf(out,fmt,args);
  7726.     }
  7727.  
  7728.     RETURN(result);
  7729.     return(result);
  7730. }
  7731.  
  7732. int
  7733. amiga_fprintf(FILE *out,const char *fmt,...)
  7734. {
  7735.     va_list args;
  7736.     int result;
  7737.  
  7738.     va_start(args,fmt);
  7739.     result = amiga_vfprintf(out,fmt,args);
  7740.     va_end(args);
  7741.  
  7742.     return(result);
  7743. }
  7744.  
  7745. int
  7746. amiga_printf(const char *fmt,...)
  7747. {
  7748.     va_list args;
  7749.     int result;
  7750.  
  7751.     va_start(args,fmt);
  7752.     result = amiga_vfprintf(stdout,fmt,args);
  7753.     va_end(args);
  7754.  
  7755.     return(result);
  7756. }
  7757.  
  7758. size_t
  7759. amiga_fwrite(const void *data,size_t blockSize,size_t numBlocks,FILE *out)
  7760. {
  7761.     struct UFB * ufb;
  7762.     size_t result;
  7763.  
  7764.     chkabort();
  7765.  
  7766.     ENTER();
  7767.  
  7768.     ufb = chkufb(fileno(out));
  7769.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7770.     {
  7771.         SHOWMSG("output to socket");
  7772.  
  7773.         result = send(ufb->ufbfh,(APTR)data,blockSize * numBlocks,0);
  7774.         if(result > 0)
  7775.             result = (result/blockSize);
  7776.     }
  7777.     else
  7778.     {
  7779.         result = fwrite(data,blockSize,numBlocks,out);
  7780.     }
  7781.  
  7782.     RETURN(result);
  7783.     return(result);
  7784. }
  7785.  
  7786. size_t
  7787. amiga_fread(void *data,size_t blockSize,size_t numBlocks,FILE *in)
  7788. {
  7789.     struct UFB * ufb;
  7790.     size_t result;
  7791.  
  7792.     chkabort();
  7793.  
  7794.     ENTER();
  7795.  
  7796.     ufb = chkufb(fileno(in));
  7797.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7798.     {
  7799.         SHOWMSG("input from socket");
  7800.  
  7801.         result = recv(ufb->ufbfh,(APTR)data,blockSize * numBlocks,0);
  7802.         if(result > 0)
  7803.             result = (result/blockSize);
  7804.     }
  7805.     else
  7806.     {
  7807.         result = fread(data,blockSize,numBlocks,in);
  7808.     }
  7809.  
  7810.     RETURN(result);
  7811.     return(result);
  7812. }
  7813.  
  7814. int
  7815. amiga_fclose(FILE * stream)
  7816. {
  7817.     struct UFB * ufb;
  7818.     int result;
  7819.  
  7820.     chkabort();
  7821.  
  7822.     ENTER();
  7823.  
  7824.     ufb = chkufb(fileno(stream));
  7825.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7826.         result = OK;
  7827.     else
  7828.         result = fclose(stream);
  7829.  
  7830.     RETURN(result);
  7831.     return(result);
  7832. }
  7833.  
  7834. int
  7835. amiga_fflush(FILE * stream)
  7836. {
  7837.     struct UFB * ufb;
  7838.     int result;
  7839.  
  7840.     chkabort();
  7841.  
  7842.     ENTER();
  7843.  
  7844.     ufb = chkufb(fileno(stream));
  7845.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7846.         result = OK;
  7847.     else
  7848.         result = fflush(stream);
  7849.  
  7850.     RETURN(result);
  7851.     return(result);
  7852. }
  7853.  
  7854. int
  7855. amiga_fseek(FILE * stream,long int offset,int mode)
  7856. {
  7857.     struct UFB * ufb;
  7858.     int result;
  7859.  
  7860.     chkabort();
  7861.  
  7862.     ENTER();
  7863.  
  7864.     ufb = chkufb(fileno(stream));
  7865.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7866.         result = OK;
  7867.     else
  7868.         result = fseek(stream,offset,mode);
  7869.  
  7870.     RETURN(result);
  7871.     return(result);
  7872. }
  7873.  
  7874. long int
  7875. amiga_ftell(FILE * stream)
  7876. {
  7877.     struct UFB * ufb;
  7878.     long int result;
  7879.  
  7880.     chkabort();
  7881.  
  7882.     ENTER();
  7883.  
  7884.     ufb = chkufb(fileno(stream));
  7885.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7886.         result = 0;
  7887.     else
  7888.         result = ftell(stream);
  7889.  
  7890.     RETURN(result);
  7891.     return(result);
  7892. }
  7893.  
  7894. /******************************************************************************/
  7895.  
  7896. int
  7897. amiga_setvbuf(FILE *stream,char *buff,int type,size_t size)
  7898. {
  7899.     struct UFB * ufb;
  7900.     int result;
  7901.  
  7902.     chkabort();
  7903.  
  7904.     ENTER();
  7905.  
  7906.     ufb = chkufb(fileno(stream));
  7907.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7908.         result = OK;
  7909.     else
  7910.         result = setvbuf(stream,buff,type,size);
  7911.  
  7912.     RETURN(result);
  7913.     return(result);
  7914. }
  7915.  
  7916. /******************************************************************************/
  7917.  
  7918. int
  7919. amiga_fputc(int c,FILE *stream)
  7920. {
  7921.     struct UFB * ufb;
  7922.     int result = ERROR;
  7923.  
  7924.     chkabort();
  7925.  
  7926.     ENTER();
  7927.  
  7928.     ufb = chkufb(fileno(stream));
  7929.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7930.     {
  7931.         UBYTE oneByte = c;
  7932.  
  7933.         if(send(ufb->ufbfh,&oneByte,1,0) > 0)
  7934.             result = OK;
  7935.     }
  7936.     else
  7937.     {
  7938.         result = fputc(c,stream);
  7939.     }
  7940.  
  7941.     RETURN(result);
  7942.     return(result);
  7943. }
  7944.  
  7945. /******************************************************************************/
  7946.  
  7947. VOID
  7948. amiga_setbuf(FILE *stream,char *buffer)
  7949. {
  7950.     struct UFB * ufb;
  7951.  
  7952.     chkabort();
  7953.  
  7954.     ENTER();
  7955.  
  7956.     ufb = chkufb(fileno(stream));
  7957.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7958.     {
  7959.         /* Do nothing */
  7960.     }
  7961.     else
  7962.     {
  7963.         setbuf(stream,buffer);
  7964.     }
  7965.  
  7966.     LEAVE();
  7967. }
  7968.  
  7969. /******************************************************************************/
  7970.  
  7971. int
  7972. amiga_recv(int fd,void *buff,size_t nbytes,int flags)
  7973. {
  7974.     struct UFB * ufb;
  7975.     int result = ERROR;
  7976.  
  7977.     ENTER();
  7978.  
  7979.     ufb = chkufb(fd);
  7980.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  7981.         result = recv(ufb->ufbfh,buff,nbytes,flags);
  7982.     else
  7983.         errno = EBADF;
  7984.  
  7985.     RETURN(result);
  7986.     return(result);
  7987. }
  7988.  
  7989. /******************************************************************************/
  7990.  
  7991. int
  7992. amiga_send(int fd,void *buff,size_t nbytes,int flags)
  7993. {
  7994.     struct UFB * ufb;
  7995.     int result = ERROR;
  7996.  
  7997.     ENTER();
  7998.  
  7999.     ufb = chkufb(fd);
  8000.     if(ufb != NULL && FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  8001.         result = send(ufb->ufbfh,buff,nbytes,flags);
  8002.     else
  8003.         errno = EBADF;
  8004.  
  8005.     RETURN(result);
  8006.     return(result);
  8007. }
  8008.  
  8009. /******************************************************************************/
  8010.  
  8011. int
  8012. amiga_smbrun(char *cmd,char *outfile,BOOL shared)
  8013. {
  8014.     struct MangleInfo mi_cmd;
  8015.     struct MangleInfo mi_outfile;
  8016.     int result = ERROR;
  8017.  
  8018.     ENTER();
  8019.  
  8020.     ForbidDOS();
  8021.  
  8022.     if(outfile == NULL)
  8023.         outfile = "/dev/null";
  8024.  
  8025.     if(MangleName(&cmd,&mi_cmd) == OK)
  8026.     {
  8027.         if(MangleName(&outfile,&mi_outfile) == OK)
  8028.         {
  8029.             BPTR in;
  8030.  
  8031.             in = Open("NIL:",MODE_OLDFILE);
  8032.             if(in != ZERO)
  8033.             {
  8034.                 BPTR out;
  8035.  
  8036.                 out = Open(outfile,MODE_NEWFILE);
  8037.                 if(out != ZERO)
  8038.                 {
  8039.                     if(SystemTags(cmd,
  8040.                         SYS_Input,        in,
  8041.                         SYS_Output,        out,
  8042.                         SYS_UserShell,    TRUE,
  8043.                         NP_WindowPtr,    NULL,
  8044.                     TAG_DONE) != -1)
  8045.                     {
  8046.                         result = OK;
  8047.                     }
  8048.                     else
  8049.                     {
  8050.                         MapIoErrToErrno();
  8051.                     }
  8052.  
  8053.                     Close(out);
  8054.                 }
  8055.                 else
  8056.                 {
  8057.                     MapIoErrToErrno();
  8058.                 }
  8059.  
  8060.                 Close(in);
  8061.             }
  8062.             else
  8063.             {
  8064.                 MapIoErrToErrno();
  8065.             }
  8066.  
  8067.             UnmangleName(&outfile,&mi_outfile);
  8068.         }
  8069.  
  8070.         UnmangleName(&cmd,&mi_cmd);
  8071.     }
  8072.  
  8073.     PermitDOS();
  8074.  
  8075.     RETURN(result);
  8076.     return(result);
  8077. }
  8078.  
  8079. /******************************************************************************/
  8080.  
  8081. #define IFBSIZE 1024
  8082. #define max(a,b) ( (a) > (b) ? (a) : (b) )
  8083.  
  8084. int
  8085. amiga_get_interfaces(struct iface_struct * ifaces,int max_interfaces)
  8086. {
  8087.     struct ifreq * ifr_end;
  8088.     struct ifreq * ifr;
  8089.     struct ifconf * ifc;
  8090.     struct ifreq ifr_copy;
  8091.     int sockfd = -1;
  8092.     int result = -1;
  8093.     int total = 0;
  8094.     int len;
  8095.  
  8096.     /* Make room for the interface information. I hope
  8097.      * that 1024 bytes will be sufficient.
  8098.      */
  8099.     ifc = malloc(sizeof(*ifc) + IFBSIZE);
  8100.     if(ifc == NULL)
  8101.     {
  8102.         errno = ENOMEM;
  8103.         goto out;
  8104.     }
  8105.  
  8106.     sockfd = socket(AF_INET,SOCK_STREAM,0);
  8107.     if(sockfd < 0)
  8108.         goto out;
  8109.  
  8110.     /* Now attempt to copy the interface information into
  8111.      * the buffer. As of this writing, support for the
  8112.      * SIOCGIFCONF ioctl() action is undocumented in all
  8113.      * currently existing TCP/IP stacks. Nevertheless,
  8114.      * it appears to work.
  8115.      */
  8116.     ifc->ifc_len = IFBSIZE;
  8117.     ifc->ifc_buf = (char *)(ifc+1);
  8118.  
  8119.     if(IoctlSocket(sockfd,SIOCGIFCONF,(char *)ifc) != OK)
  8120.         goto out;
  8121.  
  8122.     len = ifc->ifc_len;
  8123.  
  8124.     ifr = (struct ifreq *)ifc->ifc_buf;
  8125.     ifr_end = (struct ifreq *)((char *)ifr + len);
  8126.  
  8127.     /* Now check each interface, extracting the interface
  8128.      * information.
  8129.      */
  8130.     while(ifr < ifr_end && total < max_interfaces)
  8131.     {
  8132.         ifr_copy = (*ifr);
  8133.  
  8134.         /* Try to obtain the address information. */
  8135.         if(IoctlSocket(sockfd,SIOCGIFADDR,(char *)&ifr_copy) == OK)
  8136.         {
  8137.             struct in_addr ipaddr;
  8138.  
  8139.             /* We need to remember this for later. */
  8140.             ipaddr = (*(struct sockaddr_in *)&ifr_copy.ifr_addr).sin_addr;
  8141.  
  8142.             /* And query the interface flags; in particular, we are interested
  8143.              * in whether this interface is currrently "up", i.e. "online".
  8144.              */
  8145.             if(IoctlSocket(sockfd,SIOCGIFFLAGS,(char *)&ifr_copy) == OK)
  8146.             {
  8147.                 if(ifr_copy.ifr_flags & IFF_UP)
  8148.                 {
  8149.                     /* And finally obtain the interface net mask. */
  8150.                     if(IoctlSocket(sockfd,SIOCGIFNETMASK,(char *)&ifr_copy) == OK)
  8151.                     {
  8152.                         struct in_addr nmask;
  8153.  
  8154.                         nmask = ((struct sockaddr_in *)&ifr_copy.ifr_addr)->sin_addr;
  8155.  
  8156.                         strncpy(ifaces[total].name, ifr_copy.ifr_name, sizeof(ifaces[total].name)-1);
  8157.                         ifaces[total].name[sizeof(ifaces[total].name)-1] = '\0';
  8158.  
  8159.                         ifaces[total].ip = ipaddr;
  8160.                         ifaces[total].netmask = nmask;
  8161.  
  8162.                         total++;
  8163.                     }
  8164.                 }
  8165.             }
  8166.         }
  8167.  
  8168.         len = max(sizeof(struct sockaddr),ifr->ifr_addr.sa_len);
  8169.         ifr = (struct ifreq *)(((char *)ifr) + sizeof(ifr->ifr_name) + len);
  8170.     }
  8171.  
  8172.     result = total;
  8173.  
  8174.  out:
  8175.  
  8176.     if(ifc != NULL)
  8177.         free(ifc);
  8178.  
  8179.     if(sockfd != -1)
  8180.         CloseSocket(sockfd);
  8181.  
  8182.     return(result);
  8183. }
  8184.  
  8185. /******************************************************************************/
  8186.  
  8187. FILE *
  8188. amiga_popen(const char * command,const char * mode)
  8189. {
  8190.     /* For now, nothing happens here. */
  8191.  
  8192.     errno = EPIPE;
  8193.  
  8194.     return(NULL);
  8195. }
  8196.  
  8197. int
  8198. amiga_pclose(FILE * fp)
  8199. {
  8200.     /* Almost twice as much happens here. */
  8201.     return(OK);
  8202. }
  8203. @
  8204.  
  8205.  
  8206. 1.13
  8207. log
  8208. @.
  8209. @
  8210. text
  8211. @d2 1
  8212. a2 1
  8213.  * $Id: amiga.c 1.12 1999/12/01 09:47:07 olsen Exp olsen $
  8214. d9 1
  8215. a9 1
  8216.  * Copyright (C) 1999 by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>
  8217. d1372 1
  8218. d1380 1
  8219. a1380 1
  8220.                     if(strlen((STRPTR)name) > len && Strnicmp((STRPTR)name,fib.fib_FileName,len) == SAME)
  8221. d8081 19
  8222. @
  8223.  
  8224.  
  8225. 1.12
  8226. log
  8227. @.
  8228. @
  8229. text
  8230. @d2 1
  8231. a2 1
  8232.  * $Id: amiga.c 1.11 1999/11/06 16:03:15 olsen Exp olsen $
  8233. d7993 3
  8234. d8007 6
  8235. d8024 3
  8236. d8031 1
  8237. d8036 1
  8238. d8039 3
  8239. d8046 1
  8240. @
  8241.  
  8242.  
  8243. 1.11
  8244. log
  8245. @.
  8246. @
  8247. text
  8248. @d2 1
  8249. a2 1
  8250.  * $Id: amiga.c 1.10 1999/10/16 09:15:58 olsen Exp olsen $
  8251. d56 2
  8252. d85 5
  8253. d7973 88
  8254. @
  8255.  
  8256.  
  8257. 1.10
  8258. log
  8259. @.
  8260. @
  8261. text
  8262. @d2 1
  8263. a2 1
  8264.  * $Id: amiga.c 1.9 1999/08/09 15:28:43 olsen Exp olsen $
  8265. d36 1
  8266. d100 1
  8267. a100 1
  8268. STATIC int MangleName(char **namePtr, struct MangleInfo *mi);
  8269. d291 1
  8270. d1337 3
  8271. a1339 2
  8272.         /* Now check if the file name is longer than 30
  8273.          * characters. This is to avoid name space clashes.
  8274. d1341 1
  8275. a1341 1
  8276.         if(strlen(FilePart((STRPTR)name)) > 30)
  8277. d1343 61
  8278. a1403 2
  8279.             errno = ENAMETOOLONG; /* name is too long for us */
  8280.             goto out;
  8281. d4940 174
  8282. d5205 2
  8283. a5206 3
  8284.         char whichPatternBuffer[MAX_FILENAME_LEN];
  8285.         char *whichPattern = whichPatternBuffer;
  8286.         BOOL oldAllowBreak = AllowBreak;
  8287. d5208 1
  8288. a5208 2
  8289.         /* We don't want to be interrupted. */
  8290.         AllowBreak = FALSE;
  8291. d5210 5
  8292. a5214 2
  8293.         /* Now find the pattern to use. */
  8294.         nstrcpy_blank(sizeof(whichPatternBuffer),whichPattern,options);
  8295. d5216 2
  8296. a5217 3
  8297.         SHOWMSG("doing `ls'");
  8298.         SHOWSTRING(whichPattern);
  8299.         SHOWSTRING(redirectionFile);
  8300. d5219 2
  8301. a5220 5
  8302.         /* What happens next is that the contents of the
  8303.          * current directory are scanned. All file names
  8304.          * that match the given pattern are stored in the
  8305.          * redirection file.
  8306.          */
  8307. d5222 3
  8308. a5224 3
  8309.         if(MangleName(&redirectionFile,&mi) == OK)
  8310.         {
  8311.             FILE * out;
  8312. d5226 5
  8313. a5230 1
  8314.             ForbidDOS();
  8315. d5232 1
  8316. a5232 2
  8317.             out = fopen(redirectionFile,"wb");
  8318.             if(out != NULL)
  8319. d5234 1
  8320. a5234 1
  8321.                 BPTR dirLock;
  8322. d5236 4
  8323. a5239 2
  8324.                 dirLock = Lock("",SHARED_LOCK);
  8325.                 if(dirLock != ZERO)
  8326. d5241 31
  8327. a5271 1
  8328.                     struct FileInfoBlock __aligned fib;
  8329. d5273 4
  8330. a5276 1
  8331.                     if(Examine(dirLock,&fib))
  8332. d5278 1
  8333. a5278 1
  8334.                         BOOL stopped = FALSE;
  8335. d5280 4
  8336. a5283 1
  8337.                         while(ExNext(dirLock,&fib))
  8338. d5285 3
  8339. a5287 1
  8340.                             if(FIB_IS_FILE(&fib))
  8341. d5289 3
  8342. a5291 1
  8343.                                 if(do_match(fib.fib_FileName,whichPattern))
  8344. d5293 3
  8345. a5295 1
  8346.                                     if(fprintf(out,"%s\n",fib.fib_FileName) < 0)
  8347. d5297 11
  8348. a5307 2
  8349.                                         stopped = TRUE;
  8350.                                         break;
  8351. a5309 2
  8352.                             }
  8353.                         }
  8354. d5311 3
  8355. a5313 3
  8356.                         if(NOT stopped)
  8357.                         {
  8358.                             LONG error = IoErr();
  8359. d5315 10
  8360. a5324 3
  8361.                             if(error == ERROR_NO_MORE_ENTRIES)
  8362.                             {
  8363.                                 result = OK;
  8364. a5327 1
  8365.                                 SetIoErr(error);
  8366. d5330 6
  8367. a5337 4
  8368.                     else
  8369.                     {
  8370.                         MapIoErrToErrno();
  8371.                     }
  8372. d5339 4
  8373. a5342 5
  8374.                     UnLock(dirLock);
  8375.                 }
  8376.                 else
  8377.                 {
  8378.                     MapIoErrToErrno();
  8379. d5345 1
  8380. a5345 1
  8381.                 fclose(out);
  8382. d5347 1
  8383. a5347 2
  8384.                 if(result != OK)
  8385.                     DeleteFile(redirectionFile);
  8386. d5350 1
  8387. a5350 3
  8388.             PermitDOS();
  8389.  
  8390.             UnmangleName(&cmd,&mi);
  8391. a5351 2
  8392.  
  8393.         AllowBreak = oldAllowBreak;
  8394. d5360 4
  8395. d5456 2
  8396. a5457 2
  8397.                 struct MangleInfo mi;
  8398.                 BOOL hasDot;
  8399. d5459 1
  8400. a5459 1
  8401.                 hasDot = (BOOL)(strncmp(whichDrawer,"./",2) == SAME || strcmp(whichDrawer,".") == SAME);
  8402. d5461 1
  8403. a5461 1
  8404.                 if(MangleName(&whichDrawer,&mi) == OK)
  8405. d5463 1
  8406. a5463 1
  8407.                     BPTR dirLock;
  8408. d5465 1
  8409. a5465 2
  8410.                     dirLock = Lock(whichDrawer,SHARED_LOCK);
  8411.                     if(dirLock != ZERO)
  8412. d5467 1
  8413. a5467 1
  8414.                         struct FileInfoBlock __aligned fib;
  8415. d5469 3
  8416. a5471 1
  8417.                         if(Examine(dirLock,&fib))
  8418. d5473 3
  8419. a5475 8
  8420.                             struct AnchorPath * ap;
  8421.  
  8422.                             ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  8423.                             if(ap != NULL)
  8424.                             {
  8425.                                 BOOL stopped = FALSE;
  8426.                                 BPTR oldDir;
  8427.                                 LONG error;
  8428. d5477 1
  8429. a5477 1
  8430.                                 oldDir = CurrentDir(dirLock);
  8431. d5479 3
  8432. a5481 75
  8433.                                 memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  8434.                                 ap->ap_Strlen        = MAX_FILENAME_LEN;
  8435.                                 ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  8436.  
  8437.                                 if((error = MatchFirst("",ap)) == OK)
  8438.                                 {
  8439.                                     do
  8440.                                     {
  8441.                                         D(("checking |%s|",ap->ap_Buf));
  8442.  
  8443.                                         if(FIB_IS_FILE(&ap->ap_Info))
  8444.                                         {
  8445.                                             SHOWMSG("this is a file");
  8446.                                             SHOWSTRING(ap->ap_Info.fib_FileName);
  8447.  
  8448.                                             if(do_match(ap->ap_Info.fib_FileName,whichPattern))
  8449.                                             {
  8450.                                                 D(("Output |%s/%s|",whichDrawerBuffer,ap->ap_Buf));
  8451.                                                 if(fprintf(out,"%s%s/%s\n",(hasDot) ? "./" : "",whichDrawerBuffer,ap->ap_Buf) < 0)
  8452.                                                 {
  8453.                                                     stopped = TRUE;
  8454.                                                     break;
  8455.                                                 }
  8456.                                             }
  8457.                                             else
  8458.                                             {
  8459.                                                 SHOWMSG("but its name does not match");
  8460.                                             }
  8461.                                         }
  8462.                                         else
  8463.                                         {
  8464.                                             SHOWMSG("this is a drawer");
  8465.  
  8466.                                             if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  8467.                                                 SET_FLAG(ap->ap_Flags,APF_DODIR);
  8468.                                             else
  8469.                                                 CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  8470.                                         }
  8471.                                     }
  8472.                                     while((error = MatchNext(ap)) == OK);
  8473.                                 }
  8474.  
  8475.                                 MatchEnd(ap);
  8476.  
  8477.                                 CurrentDir(oldDir);
  8478.  
  8479.                                 if(NOT stopped)
  8480.                                 {
  8481.                                     if(error == ERROR_NO_MORE_ENTRIES)
  8482.                                     {
  8483.                                         result = OK;
  8484.                                     }
  8485.                                     else if(error == ERROR_BREAK)
  8486.                                     {
  8487.                                         /* Don't do anything; we are going
  8488.                                          * to delete the file anyway.
  8489.                                          */
  8490.                                     }
  8491.                                     else
  8492.                                     {
  8493.                                         SetIoErr(error);
  8494.                                         MapIoErrToErrno();
  8495.                                     }
  8496.                                 }
  8497.  
  8498.                                 free(ap);
  8499.                             }
  8500.                             else
  8501.                             {
  8502.                                 errno = ENOMEM;
  8503.                             }
  8504.                         }
  8505.                         else
  8506.                         {
  8507.                             MapIoErrToErrno();
  8508. d5484 2
  8509. a5485 1
  8510.                         UnLock(dirLock);
  8511. d5489 3
  8512. a5491 1
  8513.                         MapIoErrToErrno();
  8514. a5492 2
  8515.  
  8516.                     UnmangleName(&whichDrawer,&mi);
  8517. d7894 70
  8518. @
  8519.  
  8520.  
  8521. 1.9
  8522. log
  8523. @.
  8524. @
  8525. text
  8526. @d2 1
  8527. a2 1
  8528.  * $Id: amiga.c 1.8 1999/05/21 09:38:15 olsen Exp olsen $
  8529. d315 10
  8530. d326 30
  8531. a355 1
  8532. char * VersionTag = VERSTAG " Samba version 2.0.0 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  8533. d5164 3
  8534. d5208 1
  8535. a5208 1
  8536.                                                 if(fprintf(out,"%s/%s\n",whichDrawerBuffer,ap->ap_Buf) < 0)
  8537. a5964 2
  8538. #define SEEK_ERROR (-1)
  8539.  
  8540. a5980 1
  8541.     {
  8542. a5981 55
  8543.  
  8544.         /* Now comes the tricky bit; check if the lseek() call
  8545.          * was meant to *extend* the file.
  8546.          */
  8547.         if(result != OK)
  8548.         {
  8549.             struct FileInfoBlock __aligned fib;
  8550.  
  8551.             if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8552.             {
  8553.                 off_t new_offset = 0;
  8554.                 BOOL good = FALSE;
  8555.  
  8556.                 switch(mode)
  8557.                 {
  8558.                     case SEEK_SET:
  8559.  
  8560.                         new_offset = offset;
  8561.                         good = TRUE;
  8562.                         break;
  8563.  
  8564.                     case SEEK_CUR:
  8565.  
  8566.                         new_offset = Seek((BPTR)ufb->ufbfh,0,OFFSET_CURRENT);
  8567.                         if(new_offset != SEEK_ERROR)
  8568.                         {
  8569.                             new_offset += offset;
  8570.                             good = TRUE;
  8571.                         }
  8572.  
  8573.                         break;
  8574.  
  8575.                     case SEEK_END:
  8576.  
  8577.                         new_offset = fib.fib_Size + offset;
  8578.                         good = TRUE;
  8579.                         break;
  8580.                 }
  8581.  
  8582.                 if(good)
  8583.                 {
  8584.                     if(new_offset > fib.fib_Size)
  8585.                     {
  8586.                         /* Make the file larger; according to the BSD
  8587.                          * documentation, we should fill the newly
  8588.                          * allocated file area with zeroes. I'm not
  8589.                          * sure whether this belongs here.
  8590.                          */
  8591.                         if(SetFileSize((BPTR)ufb->ufbfh,new_offset,OFFSET_BEGINNING) != SET_FILESIZE_ERROR)
  8592.                             result = lseek(fd,offset,mode);
  8593.                     }
  8594.                 }
  8595.             }
  8596.         }
  8597.     }
  8598. a5982 1
  8599.     {
  8600. a5983 1
  8601.     }
  8602. d7047 1
  8603. a7047 1
  8604.                                 ObtainSemaphoreShared((struct SignalSemaphore *)SambaSemaphore);
  8605. @
  8606.  
  8607.  
  8608. 1.8
  8609. log
  8610. @.
  8611. @
  8612. text
  8613. @d2 1
  8614. a2 1
  8615.  * $Id: amiga.c 1.7 1999/05/02 10:45:08 olsen Exp olsen $
  8616. a216 2
  8617. VOID _CXOVF(VOID);
  8618. VOID __regargs _CXBRK(VOID);
  8619. a275 1
  8620. #define FIB_IS_DRAWER(fib)    ((fib)->fib_DirEntryType > 0)
  8621. d277 1
  8622. d316 1
  8623. a316 1
  8624. char * VersionTag = VERSTAG " Samba version 2.0.3 ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  8625. d7657 40
  8626. @
  8627.  
  8628.  
  8629. 1.7
  8630. log
  8631. @.
  8632. @
  8633. text
  8634. @d2 1
  8635. a2 1
  8636.  * $Id: amiga.c 1.6 1999/02/28 09:16:53 olsen Exp olsen $
  8637. d34 1
  8638. d1793 1
  8639. a1793 3
  8640.  
  8641.                 /* Is there a filing system mounted here? */
  8642.                 while(dol != NULL && dol->dol_Task != NULL)
  8643. d1795 4
  8644. a1798 4
  8645.                     struct InfoData __aligned id;
  8646.  
  8647.                     /* Is there a disk present? */
  8648.                     if(DoPkt(dol->dol_Task,ACTION_DISK_INFO,MKBADDR(&id),    0,0,0,0))
  8649. d1800 1
  8650. a1800 2
  8651.                         char *name = BADDR(dol->dol_Name);
  8652.                         struct Node * node;
  8653. d1802 2
  8654. a1803 5
  8655.                         /* Collect the number of blocks used and
  8656.                          * available in our fake root directory.
  8657.                          * Not that it matters much...
  8658.                          */
  8659.                         if(id.id_BytesPerBlock == 512)
  8660. d1805 17
  8661. a1821 8
  8662.                             RootBlocks        += id.id_NumBlocks;
  8663.                             RootBlocksUsed    += id.id_NumBlocksUsed;
  8664.                         }
  8665.                         else
  8666.                         {
  8667.                             RootBlocks        += (id.id_NumBlocks * id.id_BytesPerBlock) / 512;
  8668.                             RootBlocksUsed    += (id.id_NumBlocksUsed * id.id_BytesPerBlock) / 512;
  8669.                         }
  8670. d1823 7
  8671. a1829 7
  8672.                         node = malloc(sizeof(*node) + name[0]+1);
  8673.                         if(node != NULL)
  8674.                         {
  8675.                             /* Copy the name of the volume. */
  8676.                             node->ln_Name = (char *)(node + 1);
  8677.                             strncpy(node->ln_Name,&name[1],name[0]);
  8678.                             node->ln_Name[ name[0] ] = '\0';
  8679. d1831 1
  8680. a1831 1
  8681.                             AddTail(&odn->odn_VolumeList,node);
  8682. d1833 3
  8683. a1835 2
  8684.                             if(odn->odn_NextNode == NULL)
  8685.                                 odn->odn_NextNode = node;
  8686. d2338 1
  8687. a2338 1
  8688.      * it is first removed.Both <from> and <to> must be of the same type (that is,
  8689. d2471 1
  8690. a2471 1
  8691.     
  8692. d5957 1
  8693. a5957 1
  8694.     
  8695. d5961 1
  8696. a5961 1
  8697.     
  8698. d5965 1
  8699. a5965 1
  8700.     
  8701. d5967 1
  8702. a5967 1
  8703.     
  8704. d5976 1
  8705. a5976 1
  8706.     
  8707. d5978 1
  8708. a5978 1
  8709.     
  8710. d5983 1
  8711. a5983 1
  8712.     
  8713. @
  8714.  
  8715.  
  8716. 1.6
  8717. log
  8718. @.
  8719. @
  8720. text
  8721. @d2 1
  8722. a2 1
  8723.  * $Id: amiga.c 1.5 1999/02/22 15:31:18 olsen Exp olsen $
  8724. d81 1
  8725. d316 2
  8726. a317 2
  8727. #include "Amiga_Samba_2.0.0_rev.h"
  8728. char * VersionTag = VERSTAG " Ported by Olaf `Olsen' Barthel <olsen@@sourcery.han.de>";
  8729. d473 1
  8730. d487 74
  8731. a560 1
  8732.             EasyRequestArgs(NULL,&es,NULL,(APTR)varArgs);
  8733. d987 1
  8734. a987 1
  8735.     /* Initialize up the current time zone variable. */
  8736. d1170 2
  8737. a1171 1
  8738.             if(name[i] == '.')
  8739. d2332 6
  8740. d2343 65
  8741. a2407 1
  8742.             result = rename(old,new);
  8743. d2412 4
  8744. d2419 4
  8745. a2433 1
  8746.     BPTR oldDir;
  8747. d2443 1
  8748. a2443 5
  8749.     ForbidDOS();
  8750.  
  8751.     oldDir = CurrentDir(ZERO);
  8752.  
  8753.     if(NameFromLock(oldDir,buf,size))
  8754. d2445 3
  8755. a2447 2
  8756.         if(MapFileNameAmigaToUnix(buf,buf,size) == OK)
  8757.             result = buf;
  8758. d2451 5
  8759. a2455 2
  8760.         MapIoErrToErrno();
  8761.     }
  8762. d2457 11
  8763. a2467 1
  8764.     CurrentDir(oldDir);
  8765. d2469 2
  8766. a2470 1
  8767.     PermitDOS();
  8768. d3538 1
  8769. a3538 1
  8770.                 /* Nobody can write to this "directory". */
  8771. d3610 42
  8772. a3651 1
  8773.                     MapIoErrToErrno();
  8774. d3853 1
  8775. d3855 1
  8776. d3857 18
  8777. a3874 1
  8778.             MapIoErrToErrno();
  8779. d4024 1
  8780. a4024 1
  8781.         /* AmigaDOS 3.0 and up has a SetOwner() call. */
  8782. d4168 1
  8783. d4170 1
  8784. d4172 18
  8785. a4189 1
  8786.             MapIoErrToErrno();
  8787. d4769 1
  8788. a4769 1
  8789.             /* Look for a character matching  the one after the '*' */
  8790. d4805 1
  8791. a4805 1
  8792.     if((*p) == '\0' && str[0] == '.' && str[1] == 0)
  8793. d4941 6
  8794. d5102 10
  8795. d5140 1
  8796. d5143 2
  8797. d5189 2
  8798. d5920 2
  8799. d5933 2
  8800. d5938 1
  8801. d5940 55
  8802. d5996 1
  8803. d5998 3
  8804. d6179 1
  8805. a6179 1
  8806. STATIC STRPTR SambaSemaphoreName = "Amiga Samba 2.0.0";
  8807. d6725 1
  8808. a6725 1
  8809.      * This means for example, that every unlock request must
  8810. d7266 2
  8811. d7287 1
  8812. @
  8813.  
  8814.  
  8815. 1.5
  8816. log
  8817. @.
  8818. @
  8819. text
  8820. @d2 1
  8821. a2 1
  8822.  * $Id: amiga.c 1.4 1999/02/21 10:58:42 olsen Exp olsen $
  8823. d868 1
  8824. d891 4
  8825. a4607 2
  8826.     PUSH_ALL();
  8827.  
  8828. a4993 1
  8829.     POP();
  8830. d6044 3
  8831. d6051 1
  8832. d6068 3
  8833. d6133 4
  8834. d6183 4
  8835. d6211 3
  8836. d6254 4
  8837. d6299 5
  8838. d6308 1
  8839. d6311 3
  8840. d6316 5
  8841. a6320 1
  8842.                 if(NOT shared && NOT lrn->lrn_Shared && lrn->lrn_Owner == ThisClient->scn_PID)
  8843. d6323 3
  8844. d6340 4
  8845. a6349 2
  8846.         PUSH_ALL();
  8847.  
  8848. a6382 2
  8849.  
  8850.         POP();
  8851. d6393 12
  8852. a6404 3
  8853.     PUSH_ALL();
  8854.  
  8855.     /* Check for proper input. */
  8856. d6565 1
  8857. a6565 1
  8858.                                                 SHOWMSG("that file is already locked by someone else");
  8859. d6598 3
  8860. d6607 13
  8861. a6619 1
  8862.                                                 Delay(TICKS_PER_SECOND / 2);
  8863. a6833 2
  8864.     POP();
  8865.  
  8866. d7278 1
  8867. a7278 1
  8868.     int result;
  8869. @
  8870.  
  8871.  
  8872. 1.4
  8873. log
  8874. @.
  8875. @
  8876. text
  8877. @d2 1
  8878. a2 1
  8879.  * $Id: amiga.c 1.3 1999/02/20 17:52:48 olsen Exp olsen $
  8880. d98 1
  8881. a98 1
  8882. STATIC VOID CloseUnlinkCleanup(VOID);
  8883. d104 2
  8884. a108 1
  8885. STATIC int LockTheFile(int cmd, struct flock *l, struct UFB *ufb);
  8886. d114 10
  8887. d284 1
  8888. d322 10
  8889. d335 1
  8890. a335 1
  8891.     if(AllowBreak && FLAG_IS_SET(SetSignal(0,SIGBREAKF_CTRL_C),SIGBREAKF_CTRL_C))
  8892. d926 1
  8893. a926 1
  8894.     CloseUnlinkCleanup();
  8895. d1242 1
  8896. a1242 1
  8897. CloseUnlinkCleanup(VOID)
  8898. d1253 2
  8899. a1254 3
  8900.     /* We look for descriptors we switched into
  8901.      * non-blocking mode and reset them back
  8902.      * to blocking mode.
  8903. d1258 2
  8904. d1269 1
  8905. d2447 2
  8906. a5368 276
  8907. #define SEEK_ERROR (-1)
  8908.  
  8909. STATIC int
  8910. LockTheFile(int cmd,struct flock * l,struct UFB * ufb)
  8911. {
  8912.     int result = ERROR;
  8913.  
  8914.     /* Check for proper input. */
  8915.     if(l != NULL && ufb != NULL)
  8916.     {
  8917.         /* Can we make sense of the input parameters? */
  8918.         if(F_RDLCK <= l->l_type && l->l_type <= F_WRLCK &&
  8919.           (l->l_whence == SEEK_SET || l->l_whence == SEEK_CUR || l->l_whence == SEEK_END))
  8920.         {
  8921.             struct FileInfoBlock __aligned fib;
  8922.             BOOL dataIsValid = TRUE;
  8923.             LONG currentPosition;
  8924.             LONG start = 0;
  8925.             LONG len = 0;
  8926.  
  8927.             /* Now calculate the position of the
  8928.              * first byte to lock and the number
  8929.              * of bytes to lock.
  8930.              */
  8931.             switch(l->l_whence)
  8932.             {
  8933.                 case SEEK_SET:
  8934.  
  8935.                     start = l->l_start;
  8936.  
  8937.                     if(l->l_len == 0)
  8938.                     {
  8939.                         if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8940.                             len = fib.fib_Size - start;
  8941.                         else
  8942.                             dataIsValid = FALSE;
  8943.                     }
  8944.                     else
  8945.                     {
  8946.                         len = l->l_len;
  8947.                     }
  8948.  
  8949.                     break;
  8950.  
  8951.                 case SEEK_CUR:
  8952.  
  8953.                     currentPosition = Seek((BPTR)ufb->ufbfh,0,OFFSET_CURRENT);
  8954.                     if(currentPosition != SEEK_ERROR)
  8955.                     {
  8956.                         start = currentPosition + l->l_start;
  8957.  
  8958.                         if(l->l_len == 0)
  8959.                         {
  8960.                             if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8961.                                 len = fib.fib_Size - start;
  8962.                             else
  8963.                                 dataIsValid = FALSE;
  8964.                         }
  8965.                         else
  8966.                         {
  8967.                             len = l->l_len;
  8968.                         }
  8969.                     }
  8970.                     else
  8971.                     {
  8972.                         dataIsValid = FALSE;
  8973.                     }
  8974.  
  8975.                     break;
  8976.  
  8977.                 case SEEK_END:
  8978.                 default:
  8979.  
  8980.                     if(ExamineFH((BPTR)ufb->ufbfh,&fib))
  8981.                     {
  8982.                         start = fib.fib_Size + l->l_start;
  8983.  
  8984.                         if(l->l_len == 0)
  8985.                             len = fib.fib_Size - start;
  8986.                         else
  8987.                             len = l->l_len;
  8988.                     }
  8989.                     else
  8990.                     {
  8991.                         dataIsValid = FALSE;
  8992.                     }
  8993.  
  8994.                     break;
  8995.             }
  8996.  
  8997.             SHOWVALUE(start);
  8998.             SHOWVALUE(len);
  8999.  
  9000.             /* Did we get everything we needed? */
  9001.             if(dataIsValid)
  9002.             {
  9003.                 if(start >= 0 && len >= 0)
  9004.                 {
  9005.                     if(len > 0)
  9006.                     {
  9007.                         if(l->l_type == F_UNLCK)
  9008.                         {
  9009.                             D(("unlocking %ld..%ld",start,start+len-1));
  9010.  
  9011.                             if(UnLockRecord((BPTR)ufb->ufbfh,start,len))
  9012.                                 result = OK;
  9013.                             else
  9014.                                 MapIoErrToErrno();
  9015.                         }
  9016.                         else
  9017.                         {
  9018.                             D(("  locking %ld..%ld",start,start+len-1));
  9019.  
  9020.                             if(cmd == F_SETLKW)
  9021.                             {
  9022.                                 LONG mode = (l->l_type == F_WRLCK) ? REC_EXCLUSIVE : REC_SHARED;
  9023.  
  9024.                                 if(mode == REC_EXCLUSIVE)
  9025.                                     D(("this is an exclusive lock; waiting for completion"));
  9026.                                 else
  9027.                                     D(("this is a shared lock; waiting for completion"));
  9028.  
  9029.                                 /* Retry until we manage to lock the record. */
  9030.                                 while(CANNOT LockRecord((BPTR)ufb->ufbfh,start,len,mode,TICKS_PER_SECOND / 2))
  9031.                                     chkabort();
  9032.  
  9033.                                 result = OK;
  9034.                             }
  9035.                             else
  9036.                             {
  9037.                                 LONG mode = (l->l_type == F_WRLCK) ? REC_EXCLUSIVE_IMMED : REC_SHARED_IMMED;
  9038.  
  9039.                                 if(mode == REC_EXCLUSIVE_IMMED)
  9040.                                     D(("this is an exclusive lock"));
  9041.                                 else
  9042.                                     D(("this is a shared lock"));
  9043.  
  9044.                                 if(LockRecord((BPTR)ufb->ufbfh,start,len,mode,0))
  9045.                                     result = OK;
  9046.                                 else
  9047.                                     MapIoErrToErrno();
  9048.                             }
  9049.                         }
  9050.                     }
  9051.                     else
  9052.                     {
  9053.                         SHOWMSG("zero length lock/unlock");
  9054.                         result = OK;
  9055.                     }
  9056.                 }
  9057.                 else
  9058.                 {
  9059.                     SHOWMSG("invalid start/len");
  9060.                     SHOWVALUE(start);
  9061.                     SHOWVALUE(len);
  9062.                     errno = EINVAL;
  9063.                 }
  9064.             }
  9065.             else
  9066.             {
  9067.                 SHOWMSG("couldn't determine start/len");
  9068.                 MapIoErrToErrno();
  9069.             }
  9070.         }
  9071.         else
  9072.         {
  9073.             SHOWMSG("invalid lock type or seek offset");
  9074.             SHOWVALUE(l->l_type);
  9075.             SHOWVALUE(l->l_whence);
  9076.             errno = EINVAL;
  9077.         }
  9078.     }
  9079.     else
  9080.     {
  9081.         SHOWMSG("no flock or no ufb");
  9082.         SHOWVALUE(l);
  9083.         SHOWVALUE(ufb);
  9084.  
  9085.         errno = EINVAL;
  9086.     }
  9087.  
  9088.     return(result);
  9089. }
  9090.  
  9091. int
  9092. amiga_fcntl(int fd,int cmd,unsigned long arg)
  9093. {
  9094.     struct UFB * ufb;
  9095.     struct flock * l;
  9096.     int result = ERROR;
  9097.  
  9098.     chkabort();
  9099.  
  9100.     ENTER();
  9101.  
  9102.     /* Don't try to lock data in a socket... */
  9103.     ufb = chkufb(fd);
  9104.     if(ufb == NULL || FLAG_IS_SET(ufb->ufbflg,UFB_IS_SOCKET))
  9105.         ufb = NULL;
  9106.  
  9107.     l = (struct flock *)arg;
  9108.  
  9109.     switch(cmd)
  9110.     {
  9111.         /* Get the first lock that blocks the lock description pointed to
  9112.          * by the third argument, arg, taken as a pointer to a struct
  9113.          * flock (see above).  The information retrieved overwrites the
  9114.          * information passed to fcntl in the flock structure.  If no
  9115.          * lock is found that would prevent this lock from being created,
  9116.          * the structure is left unchanged by this function call except
  9117.          * for the lock type which is set to F_UNLCK.
  9118.          */
  9119.         case F_GETLK:
  9120.  
  9121.             SHOWMSG("F_GETLK");
  9122.             errno = ENOSYS;
  9123.             break;
  9124.  
  9125.         /* Set or clear a file segment lock according to the lock de-
  9126.          * scription pointed to by the third argument, arg, taken as a
  9127.          * pointer to a struct flock (see above).    F_SETLK is used to es-
  9128.          * tablish shared (or read) locks (F_RDLCK) or exclusive (or
  9129.          * write) locks, (F_WRLCK), as well as remove either type of lock
  9130.          * (F_UNLCK). If a shared or exclusive lock cannot be set, fcntl
  9131.          * returns immediately with EACCES.
  9132.          */
  9133.         case F_SETLK:
  9134.  
  9135.             result = LockTheFile(cmd,l,ufb);
  9136.             break;
  9137.  
  9138.         /* This command is the same as F_SETLK except that if a shared or
  9139.          * exclusive lock is blocked by other locks, the process waits
  9140.          * until the request can be satisfied.  If a signal that is to be
  9141.          * caught is received while fcntl is waiting for a region, the
  9142.          * fcntl will be interrupted if the signal handler has not speci-
  9143.          * fied the SA_RESTART (see sigaction(2)).
  9144.          */
  9145.         case F_SETLKW:
  9146.  
  9147.             result = LockTheFile(cmd,l,ufb);
  9148.             break;
  9149.  
  9150.         /* Get descriptor status flags, as described below (arg is ig-
  9151.          * noted).
  9152.          */
  9153.         case F_GETFL:
  9154.  
  9155.             result = IsDescriptorNonblocking(fd) ? O_NONBLOCK : 0;
  9156.             break;
  9157.  
  9158.         /* Set descriptor status flags to arg. */
  9159.         case F_SETFL:
  9160.  
  9161.             if(FLAG_IS_SET(arg,O_NONBLOCK))
  9162.                 BlockDescriptor(fd);
  9163.             else
  9164.                 UnblockDescriptor(fd);
  9165.  
  9166.             result = OK;
  9167.             break;
  9168.  
  9169.         default:
  9170.  
  9171.             D(("Unknown command %ld",cmd));
  9172.             result = ERROR;
  9173.             errno = ENOSYS;
  9174.             break;
  9175.     }
  9176.  
  9177.     RETURN(result);
  9178.     return(result);
  9179. }
  9180.  
  9181. /******************************************************************************/
  9182.  
  9183. d5863 1
  9184. d5912 5
  9185. d6010 853
  9186. @
  9187.  
  9188.  
  9189. 1.3
  9190. log
  9191. @.
  9192. @
  9193. text
  9194. @d2 1
  9195. a2 1
  9196.  * $Id: amiga.c 1.2 1999/02/20 16:52:05 olsen Exp olsen $
  9197. d222 2
  9198. d6599 53
  9199. @
  9200.  
  9201.  
  9202. 1.2
  9203. log
  9204. @.
  9205. @
  9206. text
  9207. @d2 1
  9208. a2 1
  9209.  * $Id: amiga.c 1.1 1999/02/13 15:32:16 olsen Exp olsen $
  9210. d4476 70
  9211. d4676 1
  9212. a4676 1
  9213.                 struct MangleInfo mi;
  9214. d4678 2
  9215. a4679 1
  9216.                 if(MangleName(&whichPattern,&mi) == OK)
  9217. d4681 1
  9218. a4681 1
  9219.                     BPTR dirLock;
  9220. d4683 1
  9221. a4683 2
  9222.                     dirLock = Lock("",SHARED_LOCK);
  9223.                     if(dirLock != ZERO)
  9224. d4685 1
  9225. a4685 1
  9226.                         struct AnchorPath * ap;
  9227. d4687 1
  9228. a4687 2
  9229.                         ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  9230.                         if(ap != NULL)
  9231. d4689 1
  9232. a4689 8
  9233.                             BOOL stopped = FALSE;
  9234.                             LONG error;
  9235.  
  9236.                             memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  9237.                             ap->ap_Strlen        = MAX_FILENAME_LEN;
  9238.                             ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  9239.  
  9240.                             if((error = MatchFirst(whichPattern,ap)) == OK)
  9241. d4691 1
  9242. a4691 13
  9243.                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  9244.  
  9245.                                 if(FIB_IS_DRAWER(&ap->ap_Info))
  9246.                                 {
  9247.                                     SHOWMSG("this is a drawer");
  9248.                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  9249.                                 }
  9250.                                 else
  9251.                                 {
  9252.                                     SHOWMSG("this is not a drawer");
  9253.                                 }
  9254.  
  9255.                                 do
  9256. d4693 1
  9257. a4693 10
  9258.                                     if(FIB_IS_FILE(&ap->ap_Info))
  9259.                                     {
  9260.                                         D(("Output |%s|",ap->ap_Buf));
  9261.                                         if(fprintf(out,"%s\n",ap->ap_Buf) < 0)
  9262.                                         {
  9263.                                             stopped = TRUE;
  9264.                                             break;
  9265.                                         }
  9266.                                     }
  9267.                                     else
  9268. d4695 2
  9269. a4696 1
  9270.                                         CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  9271. a4698 1
  9272.                                 while((error = MatchNext(ap)) == OK);
  9273. d4700 1
  9274. d4702 3
  9275. a4704 1
  9276.                             MatchEnd(ap);
  9277. d4706 1
  9278. a4706 1
  9279.                             if(NOT stopped)
  9280. d4708 6
  9281. a4713 15
  9282.                                 if(error == ERROR_NO_MORE_ENTRIES)
  9283.                                 {
  9284.                                     result = OK;
  9285.                                 }
  9286.                                 else if(error == ERROR_BREAK)
  9287.                                 {
  9288.                                     /* Don't do anything; we are going
  9289.                                      * to delete the file anyway.
  9290.                                      */
  9291.                                 }
  9292.                                 else
  9293.                                 {
  9294.                                     SetIoErr(error);
  9295.                                     MapIoErrToErrno();
  9296.                                 }
  9297. a4714 6
  9298.  
  9299.                             free(ap);
  9300.                         }
  9301.                         else
  9302.                         {
  9303.                             errno = ENOMEM;
  9304. a4715 2
  9305.  
  9306.                         UnLock(dirLock);
  9307. d4722 5
  9308. a4726 1
  9309.                     UnmangleName(&whichPattern,&mi);
  9310. d4831 1
  9311. a4831 2
  9312.                 char compiledPattern[2 * (MAX_FILENAME_LEN+1)];
  9313.                 LONG isWild;
  9314. d4833 1
  9315. a4833 3
  9316.                 isWild = ParsePatternNoCase(whichPattern,compiledPattern,sizeof(compiledPattern));
  9317.                 SHOWVALUE(isWild);
  9318.                 if(isWild != -1)
  9319. d4835 1
  9320. a4835 1
  9321.                     struct MangleInfo mi;
  9322. d4837 2
  9323. a4838 1
  9324.                     if(MangleName(&whichDrawer,&mi) == OK)
  9325. d4840 1
  9326. a4840 1
  9327.                         BPTR dirLock;
  9328. d4842 1
  9329. a4842 2
  9330.                         dirLock = Lock(whichDrawer,SHARED_LOCK);
  9331.                         if(dirLock != ZERO)
  9332. d4844 1
  9333. a4844 1
  9334.                             struct FileInfoBlock __aligned fib;
  9335. d4846 2
  9336. a4847 1
  9337.                             if(Examine(dirLock,&fib))
  9338. d4849 2
  9339. a4850 1
  9340.                                 struct AnchorPath * ap;
  9341. d4852 5
  9342. a4856 2
  9343.                                 ap = malloc(sizeof(*ap) + MAX_FILENAME_LEN);
  9344.                                 if(ap != NULL)
  9345. d4858 3
  9346. a4860 2
  9347.                                     BOOL stopped = FALSE;
  9348.                                     LONG error;
  9349. d4862 1
  9350. a4862 7
  9351.                                     memset(ap,0,sizeof(*ap) + MAX_FILENAME_LEN);
  9352.                                     ap->ap_Strlen        = MAX_FILENAME_LEN;
  9353.                                     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  9354.  
  9355.                                     if((error = MatchFirst("",ap)) == OK)
  9356.                                     {
  9357.                                         do
  9358. d4864 2
  9359. a4865 1
  9360.                                             D(("checking |%s|",ap->ap_Buf));
  9361. d4867 1
  9362. a4867 1
  9363.                                             if(FIB_IS_FILE(&ap->ap_Info))
  9364. d4869 2
  9365. a4870 4
  9366.                                                 SHOWMSG("this is a file");
  9367.                                                 SHOWSTRING(ap->ap_Info.fib_FileName);
  9368.  
  9369.                                                 if(MatchPatternNoCase(compiledPattern,ap->ap_Info.fib_FileName))
  9370. d4872 2
  9371. a4873 10
  9372.                                                     D(("Output |%s/%s|",whichDrawerBuffer,ap->ap_Buf));
  9373.                                                     if(fprintf(out,"%s/%s\n",whichDrawerBuffer,ap->ap_Buf) < 0)
  9374.                                                     {
  9375.                                                         stopped = TRUE;
  9376.                                                         break;
  9377.                                                     }
  9378.                                                 }
  9379.                                                 else
  9380.                                                 {
  9381.                                                     SHOWMSG("but its name does not match");
  9382. d4878 1
  9383. a4878 6
  9384.                                                 SHOWMSG("this is a drawer");
  9385.  
  9386.                                                 if(FLAG_IS_CLEAR(ap->ap_Flags,APF_DIDDIR))
  9387.                                                     SET_FLAG(ap->ap_Flags,APF_DODIR);
  9388.                                                 else
  9389.                                                     CLEAR_FLAG(ap->ap_Flags,APF_DIDDIR);
  9390. a4880 17
  9391.                                         while((error = MatchNext(ap)) == OK);
  9392.                                     }
  9393.  
  9394.                                     MatchEnd(ap);
  9395.  
  9396.                                     if(NOT stopped)
  9397.                                     {
  9398.                                         if(error == ERROR_NO_MORE_ENTRIES)
  9399.                                         {
  9400.                                             result = OK;
  9401.                                         }
  9402.                                         else if(error == ERROR_BREAK)
  9403.                                         {
  9404.                                             /* Don't do anything; we are going
  9405.                                              * to delete the file anyway.
  9406.                                              */
  9407.                                         }
  9408. d4883 6
  9409. a4888 2
  9410.                                             SetIoErr(error);
  9411.                                             MapIoErrToErrno();
  9412. d4891 4
  9413. d4896 1
  9414. a4896 3
  9415.                                     free(ap);
  9416.                                 }
  9417.                                 else
  9418. d4898 15
  9419. a4912 1
  9420.                                     errno = ENOMEM;
  9421. d4914 2
  9422. d4919 1
  9423. a4919 1
  9424.                                 MapIoErrToErrno();
  9425. a4920 2
  9426.  
  9427.                             UnLock(dirLock);
  9428. d4927 1
  9429. a4927 1
  9430.                         UnmangleName(&whichDrawer,&mi);
  9431. d4929 6
  9432. a4934 4
  9433.                 }
  9434.                 else
  9435.                 {
  9436.                     MapIoErrToErrno();
  9437. @
  9438.  
  9439.  
  9440. 1.1
  9441. log
  9442. @.
  9443. @
  9444. text
  9445. @d221 1
  9446. d1006 9
  9447. a1014 2
  9448.                 /* Convert any "/dev/" reference to "NIL:". */
  9449.                 name = "NIL:";
  9450. d1303 2
  9451. d1489 1
  9452. a1489 1
  9453.     BOOL isAbsolutePath = FALSE;
  9454. d4476 14
  9455. d4493 2
  9456. d4497 5
  9457. d4505 2
  9458. d4512 420
  9459. a4931 1
  9460.     if(MangleName(&cmd,&mi) == OK)
  9461. d4933 5
  9462. a4937 3
  9463.         ForbidDOS();
  9464.         result = system(cmd);
  9465.         PermitDOS();
  9466. d4939 2
  9467. a4940 1
  9468.         UnmangleName(&cmd,&mi);
  9469. d4944 1
  9470. d6244 1
  9471. a6244 1
  9472.     int result;
  9473. d6256 1
  9474. a6256 2
  9475.         result = recv(ufb->ufbfh,&c,1,0);
  9476.         if(result == 1)
  9477. a6257 2
  9478.  
  9479.         RETURN(result);
  9480. d6264 1
  9481. d6272 1
  9482. a6272 1
  9483.     char *result = NULL;
  9484. d6381 1
  9485. d6553 22
  9486. @
  9487.