home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -seriously_amiga- / archivers / mpackppc-wos / src / arcos.c < prev    next >
C/C++ Source or Header  |  1998-04-27  |  11KB  |  438 lines

  1. /* (C) Copyright 1993,1994 by Carnegie Mellon University
  2.  * All Rights Reserved.
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without
  6.  * fee, provided that the above copyright notice appear in all copies
  7.  * and that both that copyright notice and this permission notice
  8.  * appear in supporting documentation, and that the name of Carnegie
  9.  * Mellon University not be used in advertising or publicity
  10.  * pertaining to distribution of the software without specific,
  11.  * written prior permission.  Carnegie Mellon University makes no
  12.  * representations about the suitability of this software for any
  13.  * purpose.  It is provided "as is" without express or implied
  14.  * warranty.
  15.  *
  16.  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
  17.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  18.  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
  19.  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  20.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  21.  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  22.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23.  * SOFTWARE.
  24.  */
  25. /* Based on dosos.c */
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <ctype.h>
  29. #include <string.h>
  30. #include <errno.h>
  31. #include <sys/types.h>
  32. #include "xmalloc.h"
  33. #include "common.h"
  34.  
  35. char *getParam();
  36.  
  37. int overwrite_files = 0;
  38. int didchat;
  39.  
  40. /* The name of the file we're writing */
  41. static char *output_fname = 0;
  42.  
  43. /* Characters that can be in filenames */
  44. #define GOODCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_!'()+/=?[]`{|}~" /* some of those symbols are a tad dubious */
  45.  
  46. static unsigned long load, exec, acc;
  47. static fLoad, fExec, fAcc; /* flags to say if each set */
  48.  
  49. /* RISC OS needs this to find filetype, etc */
  50. /* Quite likely to be an empty function for many ports */
  51. /* no longer a hook function - rework at some point */
  52. os_parameterhook(contentParams)
  53. params contentParams;
  54. {
  55.     fLoad=fExec=fAcc=0;
  56.     if (contentParams) {
  57.         char *p;
  58.         p = getParam(contentParams, "load");
  59.         if (p) {
  60.             if (*p=='&')
  61.                 p++;
  62.             load=strtoul(p,NULL,16);
  63.             fLoad=1;
  64.         }
  65.         p = getParam(contentParams, "exec");
  66.         if (p) {
  67.             if (*p=='&')
  68.                 p++;
  69.             exec=strtoul(p,NULL,16);
  70.             fExec=1;
  71.         }
  72.         p = getParam(contentParams, "access");
  73.         if (p) {
  74.             if (*p=='&')
  75.                 p++;
  76.             acc=strtoul(p,NULL,16);
  77.             fAcc=1;
  78.         }
  79.     }
  80. }
  81.  
  82. static char *dir=NULL;
  83. static int offset[10];
  84. static int fFirst=0;
  85.  
  86. os_boundaryhookopen(depth)
  87. int depth;
  88. {
  89. /*    printf("((( %d '%s'\n",depth,dir?dir:"(null)"); */
  90.     if (dir) {
  91.         offset[depth]=strlen(dir);
  92.     } else {
  93.         offset[depth]=0;
  94.     }
  95.     if (depth>1)
  96.         fFirst=1;
  97. }
  98.  
  99. os_boundaryhookclose(depth)
  100. int depth;
  101. {
  102. /*    printf("))) %d '%s'\n",depth,dir?dir:"(null)"); */
  103.     if (dir) {
  104.         dir[offset[depth+1]]='\0';
  105.     }
  106. }
  107.  
  108. /* Generate a message-id */
  109. char *os_genid()
  110. {
  111.     static time_t curtime;
  112.     static char *hostname;
  113.     char *result;
  114.  
  115.     if (curtime == 0) {
  116.     time(&curtime);
  117.  
  118.     hostname = getenv("HOSTNAME");
  119.     if (!hostname) hostname="random-arc";
  120.     }
  121.  
  122.     result = xmalloc(25+strlen(hostname));
  123.     sprintf(result, "%lu@%s", curtime++, hostname);
  124.     return result;
  125. }
  126.  
  127. /* Create and return directory for a message-id */
  128. char *os_idtodir(id)
  129. char *id;
  130. {
  131.     static char buf[256];
  132.     int len = 0;
  133.     char *p;
  134.  
  135.     if (p = getenv("Wimp$ScrapDir")) {
  136.     strncpy(buf, p, 201);
  137.     buf[200] = '\0';        /* Ensure sufficiently short */
  138.     }
  139.     else {
  140.     strcpy(buf, "/tmp");
  141.     (void)mkdir(buf);
  142.     }
  143.     strcat(buf, "/mimeparts");
  144.     (void)mkdir(buf);
  145.  
  146.     p = buf + strlen(buf);
  147.     *p++ = '/';
  148.  
  149.     while (*id && len < 10) {
  150.     if (strchr(GOODCHARS, *id)) {
  151. /*        if (len++ == 8) *p++ = '.'; */
  152.         *p++ = *id;
  153.     }
  154.     id++;
  155.     }
  156.     *p = '\0';
  157.     if (mkdir(buf) == -1 && errno != EACCES) {
  158.     perror(buf);
  159.     return 0;
  160.     }
  161.     *p++ = '/';
  162.     *p = '\0';
  163.     return buf;
  164. }
  165.  
  166. /*
  167.  * We are done with the directory returned by os_idtodir()
  168.  * Remove it
  169.  */
  170. os_donewithdir(dir)
  171. char *dir;
  172. {
  173.     char *p;
  174.  
  175.     /* Remove trailing slash */
  176.     p = dir + strlen(dir) - 1;
  177.     *p = '\0';
  178.  
  179.     rmdir(dir);
  180. }
  181.  
  182. /*
  183.  * Create a new file, with suggested filename "fname".
  184.  * "fname" may have come from an insecure source, so clean it up first.
  185.  * It may also be null.
  186.  * "contentType" is passed in for use by systems that have typed filesystems.
  187.  * "flags" contains a bit pattern describing attributes of the new file.
  188.  */
  189. FILE *os_newtypedfile(fname, contentType, flags, contentParams)
  190. char *fname;
  191. char *contentType;
  192. int flags;
  193. params contentParams;
  194. {
  195.     char *p, *q;
  196.     int len, sawdot;
  197.     static int filesuffix=0;
  198.     char buf[128], *descfname=0;
  199.     FILE *outfile = 0;
  200.     int fRISCOS=0;
  201.     extern int __uname_control;
  202.     int uname_control_old;
  203.  
  204.     os_parameterhook(contentParams);
  205.  
  206.     if (!fname) fname = "";
  207.     len=strlen(fname);
  208.  
  209.     if (cistrcmp(contentType,"APPLICATION/RISCOS")==0) {
  210.         fRISCOS=1; /* It's definitely RISC OS */
  211.         /* check for directory */
  212.         if (len>5) {
  213.             if (strcmp(fname+len-5,",1000")==0 ||
  214.                 strcmp(fname+len-5,",2000")==0) {
  215.                 /* OK -- it's a RISC OS directory */
  216.                 int lendir=0;
  217.                 fname[len-5]='\0';
  218.                 if (dir) {
  219.                     lendir=strlen(dir);
  220.                     dir=xrealloc(dir,lendir+len-3);
  221.                     if (lendir)
  222.                         dir[lendir++]='.';
  223.                     strcpy(dir+lendir,fname);
  224.                 } else {
  225.                     dir=xmalloc(len);
  226.                     strcpy(dir,fname);
  227.                 }
  228.                 {
  229.                     int r[6];
  230.                     r[4]=0;
  231.                     if (os_file (0x08, dir, r)) {
  232.                         printf("couldn't create '%s'\n",dir);
  233.                     }
  234.                 }
  235. /*                printf("&&& just mkdir(%s)-ed -- fFirst=%d\n",dir,fFirst); */
  236.                 if (!fFirst) {
  237.                     if (lendir) lendir--;
  238.                     dir[lendir]='\0';
  239.                 }
  240.                 fFirst=0;
  241.                 return NULL; /* ignore dummy message body */
  242.             }
  243.         }
  244.     }
  245. /*    printf("*** file '%s'\n*** type '%s'\n",fname,contentType?contentType:"(null)"); */
  246.     fFirst=0;
  247.     /* Turn of UnixLib name mangling as it goes wrong for "foo.c.bar" */
  248.     uname_control_old=__uname_control;
  249.     __uname_control|=1;
  250.  
  251.     /* lose any RISC OS filetype (3 hex digits) appended after a ',' */
  252.     if (len>4 && fname[len-4]==',') {
  253.         int x;
  254.         fRISCOS=1;
  255.         for( x=len-3 ; x<len ; x++ )
  256.             if (!isxdigit(fname[x]))
  257.                 fRISCOS=0;
  258.         if (fRISCOS)
  259.             fname[len-4]='\0';
  260.     }
  261.     if (!fRISCOS) {
  262.         /* Chop off any drive specifier, convert \ to / */
  263.         if (*fname && fname[1] == ':') fname +=2;
  264.         for (p = fname; *p; p++) if (*p == '\\') *p = '/';
  265.  
  266.         /* If absolute path name, chop to tail */
  267.         if (*fname == '/') {
  268.             p = strrchr(fname, '/');
  269.             fname = p+1;
  270.         }
  271.     }
  272.     /* similarly for RISC OS pathnames */
  273.     if (strchr(fname,'$') || strchr(fname,'&') || strchr(fname,':')) {
  274.         fRISCOS=1;
  275.     p = strrchr(fname, '.');
  276.     fname = p+1;
  277.     }
  278.  
  279.     if (fRISCOS && dir && *dir) {
  280.         char *p;
  281.         p=xmalloc(strlen(fname)+strlen(dir)+2);
  282.         strcpy(p,dir);
  283.         strcat(p,".");
  284.         strcat(p,fname);
  285.         fname=p;
  286.     }
  287.  
  288.     if (!fRISCOS) {
  289.     /* Clean out bad characters, create directories along path */
  290.     for (p=q=fname, len=sawdot=0; *p; p++) {
  291.     if (*p == '/') {
  292.         if (!strncmp(p, "/../", 4)) {
  293.         p[1] = p[2] = 'X';
  294.         }
  295.         *q = '\0';
  296.         (void) mkdir(fname);
  297.         *q++ = '/';
  298.         len = sawdot = 0;
  299.     }
  300.     else if (*p == '.' && !sawdot) {
  301.         *q++ = '.';
  302.         sawdot++;
  303.         len = 0;
  304.     }
  305.     else if (/*len < (sawdot ? 3 : 8) &&*/ strchr(GOODCHARS, *p)) {
  306.         *q++ = *p;
  307.         len++;
  308.     }
  309.     }
  310.     *q = '\0';
  311.     }
  312.  
  313.     if (!fname[0]) {
  314.     do {
  315.         if (outfile) fclose(outfile);
  316.         sprintf(buf, "part%d", ++filesuffix);
  317.     } while (outfile = fopen(buf, "r"));
  318.     fname = buf;
  319.     }
  320.     else if (!overwrite_files && (outfile = fopen(fname, "r"))) {
  321.     /* chop off suffix */
  322.     p = strrchr(fname, '/');
  323.     if (!p) p = fname;
  324.     p = strchr(p, '.');
  325.     if (p) *p = '\0';
  326.  
  327.     /* append unique number */
  328.     do {
  329.         fclose(outfile);
  330.         sprintf(buf, "%s/%d", fname, ++filesuffix);
  331.  
  332.     } while (outfile = fopen(buf, "r"));
  333.     fname = buf;
  334.     }
  335.  
  336.     outfile = fopen(fname, (flags & FILE_BINARY) ? "wb" : "w");
  337.     if (!outfile) {
  338.         printf("++++ wouldn't open!!!!\n");
  339.     perror(fname);
  340.     }
  341.  
  342.     if (output_fname) free(output_fname);
  343.     output_fname = strsave(fname);
  344.  
  345.     if (strlen(fname) > sizeof(buf)-6) {
  346.     descfname = xmalloc(strlen(fname)+6);
  347.     }
  348.     else {
  349.     descfname = buf;
  350.     }
  351.     strcpy(descfname, fname);
  352.  
  353.     p = strrchr(descfname, '/');
  354.     if (!p) p = descfname;
  355.     if (p = strrchr(p, '.')) *p = '\0';
  356.  
  357.     strcat(descfname, "/dsc");
  358.     (void) rename(TEMPFILENAME, descfname);
  359.     if (descfname != buf) free(descfname);
  360.  
  361.     fprintf(stdout, "%s (%s)\n", output_fname, contentType);
  362.     didchat = 1;
  363.  
  364.     __uname_control=uname_control_old;
  365.     return outfile;
  366. }
  367.  
  368. /*
  369.  * Close a file opened by os_newTypedFile()
  370.  */
  371. os_closetypedfile(outfile)
  372. FILE *outfile;
  373. {
  374.     fclose(outfile);
  375.  
  376.     if (fLoad || fExec || fAcc) {
  377.         unsigned long args[6];
  378.         char *p;
  379.         args[2]=load;
  380.         args[3]=exec;
  381.         args[5]=acc;
  382.         if (fLoad && fExec && fAcc) {
  383. /*            printf("%x %x %x\n",load,exec,acc); */
  384.             p=(char*)os_file(1,output_fname,args);
  385.             if (p) printf("Failed to set file type/date/access '%s'\n",p+4);
  386.         } else {
  387.             if (fLoad) {
  388.                 p=(char*)os_file(2,output_fname,args);
  389.                 if (p) printf("Failed to set file load addr '%s'\n",p+4);
  390.             }
  391.             if (fExec) {
  392.                 p=(char*)os_file(3,output_fname,args);
  393.                 if (p) printf("Failed to set file exec addr '%s'\n",p+4);
  394.             }
  395.             if (fAcc) {
  396.                 p=(char*)os_file(5,output_fname,args);
  397.                 if (p) printf("Failed to set file access perms '%s'\n",p+4);
  398.             }
  399.         }
  400.     }
  401. }
  402.  
  403. /*
  404.  * (Don't) Handle a BinHex'ed file
  405.  */
  406. int
  407. os_binhex(inpart, part, nparts)
  408. struct part *inpart;
  409. int part;
  410. int nparts;
  411. {
  412.     return 1;
  413. }
  414.  
  415. /*
  416.  * Warn user that the MD5 digest of the last file created by os_newtypedfile()
  417.  * did not match that supplied in the Content-MD5: header.
  418.  */
  419. os_warnMD5mismatch()
  420. {
  421.     char *warning;
  422.  
  423.     warning = xmalloc(strlen(output_fname) + 100);
  424.     sprintf(warning, "%s was corrupted in transit",
  425.         output_fname);
  426.     warn(warning);
  427.     free(warning);
  428. }
  429.  
  430. /*
  431.  * Report an error (in errno) concerning a filename
  432.  */
  433. os_perror(file)
  434. char *file;
  435. {
  436.     perror(file);
  437. }
  438.