home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / lib / heirarchy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-24  |  5.5 KB  |  237 lines

  1. /*
  2.  *  HandleHeirarchy (prefix, newsgroupname, translate_only)
  3.  *
  4.  *  (c)Copyright 1992, Michael B. Smith, All Rights Reserved
  5.  *
  6.  *  This routine accepts the name of a newsgroup, in standard form, and
  7.  *  returns the fully qualified name of the directory that is referred
  8.  *  to. If requested, the directory heirarchy for the newsgroup is created.
  9.  *
  10.  *  For example, if newsgroupname == "comp.sys.amiga.misc" and
  11.  *  prefix == "uunews:", then the return value is:
  12.  *
  13.  *        uunews:comp/sys/amiga/misc
  14.  *
  15.  *  If translate_only is non-zero, no further action is taken. If zero,
  16.  *  the directory structure will be created whereever possible.
  17.  *
  18.  *  The directory creation code is fairly "expensive". However, since it
  19.  *  will only be executed once for each newsgroup, that's ok...
  20.  *
  21.  *  If an error occurs, NULL will be returned. IoErr() will be set for a
  22.  *  AmigaDOS error, IoErr() will be zero, otherwise.
  23.  *
  24.  *  The result value should be free()'ed by the caller, if non-NULL.
  25.  *
  26.  *  This routine requires the 2.04 includes to compile, but will run
  27.  *  on 1.3.
  28.  */
  29.  
  30. #include <utility/tagitem.h>
  31. #include <dos/exall.h>
  32. #include <dos/dosextens.h>
  33. #include <clib/dos_protos.h>        /* this is a 2.04 include */
  34. #include <exec/memory.h>
  35. #include <exec/lists.h>
  36. #include <clib/exec_protos.h>        /* this is a 2.04 include */
  37.  
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <stdio.h>
  41. #include "config.h"
  42.  
  43. #ifdef __GNUC__
  44. #include <signal.h>
  45. #endif
  46.  
  47. Prototype char *HandleHeirarchy (const char *, const char *, const int);
  48.  
  49. extern struct DosLibrary *DOSBase;
  50.  
  51. int DoCreate (const char *str);
  52.  
  53. char *HandleHeirarchy (const char *prefix,
  54.                const char *Newsgroup,
  55.                const int  translate_only)
  56. {
  57.     struct Process *my_proc = (struct Process *) FindTask (NULL);
  58.     BPTR
  59.     lk_home,        /* where we started at */
  60.     lk_uunews,        /* Lock ("uunews:", ACCESS_READ) */
  61.     lk_cur_level;        /* lock at current directory level */
  62.     int
  63. #ifdef __GNUC__
  64.     omask,
  65. #endif
  66.     pre_len   = strlen (prefix),
  67.     len      = strlen (Newsgroup);
  68.     long
  69.     windowptr = 0;        /* save my_proc->pr_WindowPtr */
  70.     char
  71.     *rslt,            /* result string being built */
  72.     *str      = NULL,   /* temporaries... */
  73.     *current,
  74.     *next;
  75.  
  76.     /* reset the error indicator */
  77.  
  78.     if (DOSBase->dl_lib.lib_Version < 36)
  79.     my_proc->pr_Result2 = 0;
  80.     else
  81.     SetIoErr (0);    /* this is a 2.04 only routine */
  82.  
  83.     /* if we don't have a newsgroup or a prefix, it's an error */
  84.  
  85.     if (!len)
  86.     return NULL;
  87.     if (!pre_len)
  88.     return NULL;
  89.  
  90.     if (!translate_only) {
  91. #ifdef __GNUC__
  92.     /* Note that we only lock interrupts if we are going to be making */
  93.     /* low-level dos.library calls. If translate_only is set, that      */
  94.     /* doesn't happen. Everything happens at a higher level.          */
  95.  
  96.     omask = sigsetmask (~0);
  97. #endif
  98.     /* move to where we our heirarchy base is */
  99.     lk_uunews = Lock ((unsigned char *) prefix, ACCESS_READ);
  100.     if (!lk_uunews) {
  101. #ifdef __GNUC__
  102.         sigsetmask (omask);
  103. #endif
  104. #ifdef DEBUG
  105.         printf ("Where is %s?\n", prefix);
  106. #endif
  107.         return NULL;
  108.     }
  109.  
  110.     lk_home = CurrentDir (lk_uunews);
  111.     }
  112.  
  113.     /* allocate and construct the result array */
  114.     rslt = malloc (len + pre_len + 2);
  115.  
  116.     strcpy (rslt, prefix);
  117.     if (pre_len && prefix[pre_len-1] != ':' && prefix[pre_len-1] != '/')
  118.     strcat(rslt, "/");
  119.     strcat (rslt, Newsgroup);
  120.  
  121.     /* get rid of the '.'s and replace with '/'s */
  122.     current = rslt;
  123.     while (*current) {
  124.     if (*current == '.')
  125.         *current = '/';
  126.     current++;
  127.     }
  128.  
  129. #ifdef DEBUG
  130.     printf ("input string = '%s'\noutput string = '%s'\n",
  131.     Newsgroup, rslt);
  132. #endif
  133.  
  134.     if (translate_only)
  135.     return rslt;
  136.  
  137.     /* Try to optimize the most likely occurence -- the structure exists */
  138.  
  139.     /* We don't want requestors, so lock them out. We will handle errors */
  140.     /* ourselves.                             */
  141.  
  142.     windowptr = (long) my_proc->pr_WindowPtr;
  143.     my_proc->pr_WindowPtr = (void *) -1;
  144.  
  145.     lk_cur_level = Lock ((unsigned char *) rslt, ACCESS_READ);
  146.     if (!lk_cur_level) {
  147.     /* Build the directory, piece by piece */
  148. #ifdef DEBUG
  149.     printf ("Doing it the hard way...\n");
  150. #endif
  151.     str = malloc (len + pre_len + 2);
  152.     current = str;
  153.     strcpy (str, rslt);
  154.     /* cycle thru each sub-directory */
  155.     while (next = strchr (current, '/')) {
  156.         *next = '\0';
  157.         if (!DoCreate (str))
  158.         goto die;
  159.         *next = '/';
  160.         current = next + 1;
  161.     }
  162.     /* handle the bottom-most level (which has no terminating '/') */
  163.     if (!DoCreate (str))
  164.         goto die;
  165.     lk_cur_level = Lock ((unsigned char *) rslt, ACCESS_READ);
  166.     }
  167.     if (lk_cur_level)
  168.     UnLock (lk_cur_level);
  169.     else {
  170. #ifdef DEBUG
  171.     printf ("Last lk_cur_level = NULL\n");
  172. #endif
  173.     goto die;
  174.     }
  175.  
  176.     if (0) {
  177. die:
  178. #ifdef DEBUG
  179.     printf ("I died. IoErr = %ld\n", IoErr ());
  180. #endif
  181.     free (rslt);
  182.     rslt = NULL;
  183.     }
  184.  
  185.     /* set back our window and home directory, release all resources */
  186.  
  187.     my_proc->pr_WindowPtr = (void *) windowptr;
  188.     lk_uunews = CurrentDir (lk_home);
  189.     UnLock (lk_uunews);
  190.     if (str)
  191.     free (str);
  192.  
  193. #ifdef __GNUC__
  194.     sigsetmask (omask);
  195. #endif
  196.  
  197.     return rslt;
  198. }
  199.  
  200. /*
  201.     DoCreate
  202.  
  203.     Actually create the directory referenced by 'str' if it
  204.     doesn't exist.
  205.  
  206.     Assumptions:
  207.  
  208.     my_proc->pr_WindowPtr == -1
  209.  
  210.     all directories above BaseName (str) have already been created
  211.  
  212.     interrupts are masked
  213. */
  214.  
  215. int DoCreate (const char *str)
  216. {
  217.     BPTR
  218.     lk_next_level;
  219.  
  220.     if (!(lk_next_level = Lock ((unsigned char *) str, ACCESS_READ))) {
  221.     lk_next_level = CreateDir ((unsigned char *) str);
  222. #ifdef DEBUG
  223.     printf ("Created %s\n", str);
  224. #endif
  225.     if (!lk_next_level) {
  226. #ifdef DEBUG
  227.         printf ("...failed\n");
  228. #endif
  229.         return 0;
  230.     }
  231.     }
  232.     UnLock (lk_next_level);
  233.  
  234.     return 1;
  235. }
  236.  
  237.