home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 28 / amigaformatcd28.iso / -seriously_amiga- / archivers / mpackppc-wos / src / dosos.c < prev    next >
C/C++ Source or Header  |  1998-04-27  |  7KB  |  310 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. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <ctype.h>
  28. #include <string.h>
  29. #include <errno.h>
  30. #include <sys/types.h>
  31. #include "xmalloc.h"
  32. #include "common.h"
  33.  
  34. int overwrite_files = 0;
  35. int didchat;
  36.  
  37. /* The name of the file we're writing */
  38. static char *output_fname = 0;
  39.  
  40. /* Characters that can be in filenames */
  41. #define GOODCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \
  42.                   "0123456789-_^$~!#%&{}@`'()"
  43.  
  44. /* Returns nonzero if "fname" is one of those magic device filenames */
  45. static int
  46. bad_filename(fname)
  47. char *fname;
  48. {
  49.     int len = strlen(fname);
  50.     if (len == 3) {
  51.     if (!cistrcmp(fname, "aux") || !cistrcmp(fname, "con") ||
  52.         !cistrcmp(fname, "nul") || !cistrcmp(fname, "prn")) return 1;
  53.     }
  54.     if (len == 4) {
  55.     if (!cistrcmp(fname, "com1") || !cistrcmp(fname, "com2") ||
  56.         !cistrcmp(fname, "com3") || !cistrcmp(fname, "com4") ||
  57.         !cistrcmp(fname, "lpt1") || !cistrcmp(fname, "lpt2") ||
  58.         !cistrcmp(fname, "lpt3")) return 1;
  59.     }
  60.     return 0;
  61. }
  62.  
  63. /* Generate a message-id */
  64. char *os_genid()
  65. {
  66.     static time_t curtime;
  67.     static char *hostname;
  68.     char *result;
  69.  
  70.     if (curtime == 0) {
  71.     time(&curtime);
  72.  
  73.     hostname = getenv("HOSTNAME");
  74.     if (!hostname) hostname="random-pc";
  75.     }
  76.  
  77.     result = xmalloc(25+strlen(hostname));
  78.     sprintf(result, "%lu@%s", curtime++, hostname);
  79.     return result;
  80. }
  81.  
  82. /* Create and return directory for a message-id */
  83. char *os_idtodir(id)
  84. char *id;
  85. {
  86.     static char buf[256];
  87.     int len = 0;
  88.     char *p;
  89.  
  90.     if (p = getenv("TMP")) {
  91.     strncpy(buf, p, 201);
  92.     buf[200] = '\0';        /* Ensure sufficiently short */
  93.     }
  94.     else {
  95.     strcpy(buf, "\\tmp");
  96.     (void)mkdir(buf);
  97.     }
  98.     strcat(buf, "\\parts");
  99.     (void)mkdir(buf);
  100.  
  101.     p = buf + strlen(buf);
  102.     *p++ = '\\';
  103.  
  104.     while (*id && len < 11) {
  105.     if (strchr(GOODCHARS, *id)) {
  106.         if (len++ == 8) *p++ = '.';
  107.         *p++ = *id;
  108.     }
  109.     id++;
  110.     }
  111.     *p = '\0';
  112.     if (!len || bad_filename(p-len)) {
  113.     *p++ = 'x';
  114.     *p = '\0';
  115.     }
  116.     if (mkdir(buf) == -1 && errno != EACCES) {
  117.     perror(buf);
  118.     return 0;
  119.     }
  120.     *p++ = '\\';
  121.     *p = '\0';
  122.     return buf;
  123. }
  124.  
  125. /*
  126.  * We are done with the directory returned by os_idtodir()
  127.  * Remove it
  128.  */
  129. os_donewithdir(dir)
  130. char *dir;
  131. {
  132.     char *p;
  133.  
  134.     /* Remove trailing slash */
  135.     p = dir + strlen(dir) - 1;
  136.     *p = '\0';
  137.  
  138.     rmdir(dir);
  139. }
  140.  
  141. /*
  142.  * Create a new file, with suggested filename "fname".
  143.  * "fname" may have come from an insecure source, so clean it up first.
  144.  * It may also be null.
  145.  * "contentType" is passed in for use by systems that have typed filesystems.
  146.  * "flags" contains a bit pattern describing attributes of the new file.
  147.  */
  148. FILE *os_newtypedfile(fname, contentType, flags, contentParams)
  149. char *fname;
  150. char *contentType;
  151. int flags;
  152. params contentParams;
  153. {
  154.     char *p, *q;
  155.     int len, sawdot;
  156.     static int filesuffix=0;
  157.     char buf[128], *descfname=0;
  158.     FILE *outfile = 0;
  159.  
  160.     if (!fname) fname = "";
  161.  
  162.     /* Chop off any leading drive specifier, convert / to \ */
  163.     if (*fname && fname[1] == ':') fname +=2;
  164.     for (p = fname; *p; p++) if (*p == '/') *p = '\\';
  165.  
  166.     /* If absolute path name, chop to tail */
  167.     if (*fname == '\\') {
  168.     p = strrchr(fname, '\\');
  169.     fname = p+1;
  170.     }
  171.  
  172.     /* Clean out bad characters, create directories along path,
  173.      * trim names to 8.3
  174.      */
  175.     for (p=q=fname, len=sawdot=0; *p; p++) {
  176.     if (*p == '\\') {
  177.         /* Don't let them go up a directory: change ".." to "XX" */
  178.         if (!strncmp(p, "\\..\\", 4)) {
  179.         p[1] = p[2] = 'X';
  180.         }
  181.         *q = '\0';
  182.  
  183.         /* Check for magic device filename */
  184.         if (!sawdot && bad_filename(q-len)) {
  185.         *--q = '\0';
  186.         }
  187.  
  188.         (void) mkdir(fname);
  189.         *q++ = '\\';
  190.         len = sawdot = 0;
  191.     }
  192.     else if (*p == '.' && !sawdot) {
  193.         /* First check for magic device filenames */
  194.         *q = '\0';
  195.         if (bad_filename(q-len)) q--;
  196.         
  197.         *q++ = '.';
  198.         sawdot++;
  199.         len = 0;
  200.     }
  201.     else if (len < (sawdot ? 3 : 8) && strchr(GOODCHARS, *p)) {
  202.         *q++ = *p;
  203.         len++;
  204.     }
  205.     }
  206.     *q = '\0';
  207.  
  208.     /* Check for magic device filename */
  209.     if (!sawdot && bad_filename(q-len)) {
  210.     *--q = '\0';
  211.     }
  212.  
  213.     if (!fname[0]) {
  214.     do {
  215.         if (outfile) fclose(outfile);
  216.         sprintf(buf, "part%d", ++filesuffix);
  217.     } while (outfile = fopen(buf, "r"));
  218.     fname = buf;
  219.     }
  220.     else if (!overwrite_files && (outfile = fopen(fname, "r"))) {
  221.     /* chop off suffix */
  222.     p = strrchr(fname, '\\');
  223.     if (!p) p = fname;
  224.     p = strchr(p, '.');
  225.     if (p) *p = '\0';
  226.  
  227.     /* append unique number */
  228.     do {
  229.         fclose(outfile);
  230.         sprintf(buf, "%s.%d", fname, ++filesuffix);
  231.      
  232.     } while (outfile = fopen(buf, "r"));
  233.     fname = buf;
  234.     }
  235.  
  236.     outfile = fopen(fname, (flags & FILE_BINARY) ? "wb" : "w");
  237.     if (!outfile) {
  238.     perror(fname);
  239.     }
  240.  
  241.     if (output_fname) free(output_fname);
  242.     output_fname = strsave(fname);
  243.  
  244.     if (strlen(fname) > sizeof(buf)-6) {
  245.     descfname = xmalloc(strlen(fname)+6);
  246.     }
  247.     else {
  248.     descfname = buf;
  249.     }
  250.     strcpy(descfname, fname);
  251.  
  252.     p = strrchr(descfname, '\\');
  253.     if (!p) p = descfname;
  254.     if (p = strrchr(p, '.')) *p = '\0';
  255.  
  256.     strcat(descfname, ".dsc");
  257.     (void) rename(TEMPFILENAME, descfname);
  258.     if (descfname != buf) free(descfname);
  259.     
  260.     fprintf(stdout, "%s (%s)\n", output_fname, contentType);
  261.     didchat = 1;
  262.  
  263.     return outfile;
  264. }
  265.  
  266. /*
  267.  * Close a file opened by os_newTypedFile()
  268.  */
  269. os_closetypedfile(outfile)
  270. FILE *outfile;
  271. {
  272.     fclose(outfile);
  273. }
  274.  
  275. /*
  276.  * (Don't) Handle a BinHex'ed file
  277.  */
  278. int
  279. os_binhex(inpart, part, nparts)
  280. struct part *inpart;
  281. int part;
  282. int nparts;
  283. {
  284.     return 1;
  285. }
  286.  
  287. /*
  288.  * Warn user that the MD5 digest of the last file created by os_newtypedfile()
  289.  * did not match that supplied in the Content-MD5: header.
  290.  */
  291. os_warnMD5mismatch()
  292. {
  293.     char *warning;
  294.  
  295.     warning = xmalloc(strlen(output_fname) + 100);
  296.     sprintf(warning, "%s was corrupted in transit",
  297.         output_fname);
  298.     warn(warning);
  299.     free(warning);
  300. }
  301.  
  302. /*
  303.  * Report an error (in errno) concerning a filename
  304.  */
  305. os_perror(file)
  306. char *file;
  307. {
  308.     perror(file);
  309. }
  310.