home *** CD-ROM | disk | FTP | other *** search
- /*
- * HandleHeirarchy (prefix, newsgroupname, translate_only)
- *
- * (c)Copyright 1992, Michael B. Smith, All Rights Reserved
- *
- * This routine accepts the name of a newsgroup, in standard form, and
- * returns the fully qualified name of the directory that is referred
- * to. If requested, the directory heirarchy for the newsgroup is created.
- *
- * For example, if newsgroupname == "comp.sys.amiga.misc" and
- * prefix == "uunews:", then the return value is:
- *
- * uunews:comp/sys/amiga/misc
- *
- * If translate_only is non-zero, no further action is taken. If zero,
- * the directory structure will be created whereever possible.
- *
- * The directory creation code is fairly "expensive". However, since it
- * will only be executed once for each newsgroup, that's ok...
- *
- * If an error occurs, NULL will be returned. IoErr() will be set for a
- * AmigaDOS error, IoErr() will be zero, otherwise.
- *
- * The result value should be free()'ed by the caller, if non-NULL.
- *
- * This routine requires the 2.04 includes to compile, but will run
- * on 1.3.
- */
-
- #include <utility/tagitem.h>
- #include <dos/exall.h>
- #include <dos/dosextens.h>
- #include <clib/dos_protos.h> /* this is a 2.04 include */
- #include <exec/memory.h>
- #include <exec/lists.h>
- #include <clib/exec_protos.h> /* this is a 2.04 include */
-
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include "config.h"
-
- #ifdef __GNUC__
- #include <signal.h>
- #endif
-
- Prototype char *HandleHeirarchy (const char *, const char *, const int);
-
- extern struct DosLibrary *DOSBase;
-
- int DoCreate (const char *str);
-
- char *HandleHeirarchy (const char *prefix,
- const char *Newsgroup,
- const int translate_only)
- {
- struct Process *my_proc = (struct Process *) FindTask (NULL);
- BPTR
- lk_home, /* where we started at */
- lk_uunews, /* Lock ("uunews:", ACCESS_READ) */
- lk_cur_level; /* lock at current directory level */
- int
- #ifdef __GNUC__
- omask,
- #endif
- pre_len = strlen (prefix),
- len = strlen (Newsgroup);
- long
- windowptr = 0; /* save my_proc->pr_WindowPtr */
- char
- *rslt, /* result string being built */
- *str = NULL, /* temporaries... */
- *current,
- *next;
-
- /* reset the error indicator */
-
- if (DOSBase->dl_lib.lib_Version < 36)
- my_proc->pr_Result2 = 0;
- else
- SetIoErr (0); /* this is a 2.04 only routine */
-
- /* if we don't have a newsgroup or a prefix, it's an error */
-
- if (!len)
- return NULL;
- if (!pre_len)
- return NULL;
-
- if (!translate_only) {
- #ifdef __GNUC__
- /* Note that we only lock interrupts if we are going to be making */
- /* low-level dos.library calls. If translate_only is set, that */
- /* doesn't happen. Everything happens at a higher level. */
-
- omask = sigsetmask (~0);
- #endif
- /* move to where we our heirarchy base is */
- lk_uunews = Lock ((unsigned char *) prefix, ACCESS_READ);
- if (!lk_uunews) {
- #ifdef __GNUC__
- sigsetmask (omask);
- #endif
- #ifdef DEBUG
- printf ("Where is %s?\n", prefix);
- #endif
- return NULL;
- }
-
- lk_home = CurrentDir (lk_uunews);
- }
-
- /* allocate and construct the result array */
- rslt = malloc (len + pre_len + 2);
-
- strcpy (rslt, prefix);
- if (pre_len && prefix[pre_len-1] != ':' && prefix[pre_len-1] != '/')
- strcat(rslt, "/");
- strcat (rslt, Newsgroup);
-
- /* get rid of the '.'s and replace with '/'s */
- current = rslt;
- while (*current) {
- if (*current == '.')
- *current = '/';
- current++;
- }
-
- #ifdef DEBUG
- printf ("input string = '%s'\noutput string = '%s'\n",
- Newsgroup, rslt);
- #endif
-
- if (translate_only)
- return rslt;
-
- /* Try to optimize the most likely occurence -- the structure exists */
-
- /* We don't want requestors, so lock them out. We will handle errors */
- /* ourselves. */
-
- windowptr = (long) my_proc->pr_WindowPtr;
- my_proc->pr_WindowPtr = (void *) -1;
-
- lk_cur_level = Lock ((unsigned char *) rslt, ACCESS_READ);
- if (!lk_cur_level) {
- /* Build the directory, piece by piece */
- #ifdef DEBUG
- printf ("Doing it the hard way...\n");
- #endif
- str = malloc (len + pre_len + 2);
- current = str;
- strcpy (str, rslt);
- /* cycle thru each sub-directory */
- while (next = strchr (current, '/')) {
- *next = '\0';
- if (!DoCreate (str))
- goto die;
- *next = '/';
- current = next + 1;
- }
- /* handle the bottom-most level (which has no terminating '/') */
- if (!DoCreate (str))
- goto die;
- lk_cur_level = Lock ((unsigned char *) rslt, ACCESS_READ);
- }
- if (lk_cur_level)
- UnLock (lk_cur_level);
- else {
- #ifdef DEBUG
- printf ("Last lk_cur_level = NULL\n");
- #endif
- goto die;
- }
-
- if (0) {
- die:
- #ifdef DEBUG
- printf ("I died. IoErr = %ld\n", IoErr ());
- #endif
- free (rslt);
- rslt = NULL;
- }
-
- /* set back our window and home directory, release all resources */
-
- my_proc->pr_WindowPtr = (void *) windowptr;
- lk_uunews = CurrentDir (lk_home);
- UnLock (lk_uunews);
- if (str)
- free (str);
-
- #ifdef __GNUC__
- sigsetmask (omask);
- #endif
-
- return rslt;
- }
-
- /*
- DoCreate
-
- Actually create the directory referenced by 'str' if it
- doesn't exist.
-
- Assumptions:
-
- my_proc->pr_WindowPtr == -1
-
- all directories above BaseName (str) have already been created
-
- interrupts are masked
- */
-
- int DoCreate (const char *str)
- {
- BPTR
- lk_next_level;
-
- if (!(lk_next_level = Lock ((unsigned char *) str, ACCESS_READ))) {
- lk_next_level = CreateDir ((unsigned char *) str);
- #ifdef DEBUG
- printf ("Created %s\n", str);
- #endif
- if (!lk_next_level) {
- #ifdef DEBUG
- printf ("...failed\n");
- #endif
- return 0;
- }
- }
- UnLock (lk_next_level);
-
- return 1;
- }
-
-