home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / uucp / amigauucpsrc / lib / heirarchy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-29  |  5.5 KB  |  236 lines

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