home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 110_01 / yam7.c < prev    next >
Text File  |  1984-03-03  |  12KB  |  571 lines

  1. /*
  2. >>:yam7.c 9-8-81
  3.  * File open and close stuff
  4.  * This file assumes operation on a CP/M system
  5.  */
  6. #include "yam.h"
  7.  
  8.  
  9. struct fcb {    /* CP/M Version 2 fcb AS SEEN BY THE USER */
  10.     char    dr;        /* drive number */
  11.     char    fname[8];    /* fname[1] used by TAG2 */
  12.     char    ftype[3];    /* corresponds to extension in rt-11 */
  13.     char    ex;        /* file extent normally 0 */
  14.     char s1;        /* reserved for bdos's benefit */
  15.     char s2;        /* likewise, =0 on call to open,make,search */
  16.     char    rc;        /* record count for extent[ex]  0...128 */
  17.     char dmap[16];
  18.     char cr;        /* current record, initialized to 0 by usr */
  19.     unsigned recn;        /* highest record number */
  20.     char recovf;        /* overflow of above */
  21. };
  22.  
  23. #define CONST 2            /* bios console char ready */
  24. #define CONIN 3            /* bios cons char input */
  25. #define CONOUT 4        /* bios cons char output */
  26. #define SRCH 17         /*bdos search for file pattern*/
  27. #define SRCHNXT 18        /* search for next occurrence */
  28. #define SETDMA 26        /* set address for read, write, etc. */
  29. #define SETATTRIB 30        /* update file attributes */
  30. #define SETGETUSER 32        /* set or get user number */
  31. #define COMPFILSIZ 35        /* compute file size into recn and recovf */
  32. #define UFNSIZE 15        /* a:foobar12.urk\0 is 15 chars */
  33.  
  34. openrx(name)
  35. char *name;
  36. {
  37.  
  38. #ifdef RESTRICTED
  39.     char *s;
  40.     if(s=cisubstr(name, ".com"))    /* upload .com files as .obj */
  41.         strcpy(s, ".OBJ");
  42.     if(cisubstr(name, "$$$"))
  43.         return ERROR;        /* don't allow upload of $$$.sub */
  44. #endif
  45. #ifdef LOGFILE
  46.     logfile(name, 'r');        /* record file xmsn */
  47. #endif
  48.     unspace(name);
  49.     lprintf("'%s' ", name);        /* show the name right away */
  50.     if(!Creamfile && fopen(name, fout) != ERROR) {
  51.         fclose(fout);
  52.         printf("Exists ", name);
  53. #ifdef XMODEM
  54.         return ERROR;
  55. #else
  56.         printf("Replace it (y/n)??");
  57.         if(tolower(getchar())!= 'y')
  58.             return ERROR;
  59. #endif
  60.     }
  61.     if(fcreat(name, fout)==ERROR){
  62.         printf("Can't create %s\n", name);
  63.         return ERROR;
  64.     }
  65.     Rfile= TRUE;
  66.     strcpy(Rname, name);
  67.     Dumping= !Squelch;
  68.     lprintf("Created%s\n", Dumping? "" : " recording OFF");
  69.     return OK;
  70. }
  71.  
  72. closerx(pad)
  73. {
  74.     if(Rfile) {
  75.         if(!Quiet)
  76.             lpstat("Closing %s", Rname);
  77. #ifdef BDSC
  78.         if(pad)
  79.             do
  80.                 putc(CPMEOF, fout);
  81.                 while(fout._nleft % SECSIZ);
  82. #endif
  83.         fflush(fout);
  84.         fclose(fout);
  85.         Rfile=FALSE;
  86.     }
  87. }
  88.  
  89. opentx(name)
  90. char *name;
  91. {
  92.     struct fcb *fp, *fcbaddr();
  93.     lprintf("'%s' ", name);
  94. #ifdef LOGFILE
  95.     logfile(name, 's');        /* record file xmsn */
  96. #endif
  97.     unspace(name);
  98.     if(fopen(name, fin)==ERROR){
  99.         printf("Can't open %s\n", name);
  100.         return ERROR;
  101.     }
  102. #ifdef RESTRICTED
  103.     if(cisubstr(name, ".bad")
  104.      || (fp=fcbaddr(fin._fd))==ERROR
  105.      || (fp->fname[1] & 0200)
  106.      ) {
  107.          fclose(fin); printf("\n'%s' Not for Distribution\n", name);
  108.         return ERROR;
  109.     }
  110. #endif
  111.     Tfile= TRUE;
  112.     strcpy(Tname, name);
  113.     lprintf("Open\n");
  114.     return OK;
  115. }
  116.  
  117. closetx()
  118. {
  119.     if(Tfile) {
  120.         fclose(fin);
  121.         if(!Quiet)
  122.             lpstat("%s closed", Tname);
  123.         Tfile=FALSE;
  124.     }
  125. }
  126. /* search the phone file for name */
  127. getphone(name, buffer)
  128. char *name, *buffer;
  129. {
  130.     closetx();
  131.  
  132.     if(fopen(PHONES, fin)==ERROR) {
  133.         printf("Cannot open %s\n", PHONES);
  134.         return ERROR;
  135.     } else {
  136.         while(fgets(buffer, fin))
  137.             if(cmdeq(buffer, name)) {
  138.                 fclose(fin);
  139.                 return OK;
  140.             }
  141.     }
  142.     printf("Can't find data for %s\n", name);
  143.     fclose(fin);
  144.     return ERROR;
  145. }
  146.  
  147. /* channge default disk and optionally, user number */
  148. chdir(p)
  149. char *p;
  150. {
  151.     unsigned newuser;
  152.  
  153.     newuser=user; *p=toupper(*p);
  154.     if(index(*p, DISKS)) {
  155.         defdisk= *p - 'A';
  156.         bdos(14, defdisk);
  157. #ifdef CDOS
  158.         return;
  159. #else
  160.         if(!isdigit(p[1]))
  161.             return;
  162.         if((newuser=atoi(p+1)) <= MAXUSER) {
  163.             bdos(SETGETUSER, newuser);
  164.             user=newuser;
  165.             return;
  166.         }
  167. #endif
  168.     }
  169.     printf("Disk %c and/or User %d Illegal\n", *p, newuser);
  170. }
  171.  
  172. /* fetch default disk and user number */
  173. initdd()
  174. {
  175.     Secpblk=SECPBLK;
  176.     defdisk= bdos(25,0);
  177. #ifdef CDOS
  178.     user=0;
  179. #else
  180.     user=bdos(SETGETUSER, 0377);
  181. #endif
  182. }
  183.  
  184. /*
  185.  * Z19 gets to use it's 25th line. pstat starts at 48th char
  186.  * note that a call to lpstat will erase what pstat displays
  187.  */
  188. /*VARARGS*/
  189. pstat(a,b,c)
  190. char *a, *b, *c;
  191. {
  192. #ifdef Z19
  193.     lprintf("\033x1\033j\033Y8P");
  194. #endif
  195.     lprintf(a,b,c);
  196. #ifdef Z19
  197.     lprintf("\033K\033k");
  198. #else
  199.     lprintf("\n");
  200. #endif
  201. }
  202.  
  203. /*
  204.  * Z19 gets to use it's 25th line. lpstat starts at col 1
  205.  * Rest of line is erased
  206.  */
  207. /*VARARGS*/
  208. lpstat(a,b,c)
  209. char *a, *b, *c;
  210. {
  211. #ifdef Z19
  212.     lprintf("\033x1\033j\033Y8 ");
  213. #endif
  214.     lprintf(a,b,c);
  215. #ifdef Z19
  216.     lprintf("\033K\033k");
  217. #else
  218.     lprintf("\n");
  219. #endif
  220. }
  221. char getcty()
  222. {
  223.     return bios(CONIN,0);
  224. }
  225. char putcty(c)
  226. char c;
  227. {
  228.     bios(CONOUT, c);
  229.     if(bios(CONST,0)) {
  230.         if((c=bios(CONIN,0))==XOFF)
  231.             bios(CONIN,0);
  232.         else
  233.             return c;
  234.     }
  235.     return FALSE;
  236. }
  237.  
  238. dolist(argc, argp)
  239. char **argp;
  240. {
  241.     int listfile();
  242.  
  243. #ifdef XMODEM
  244.  
  245.     printf("^S pauses, ^K skips to next file, ^X terminates\n");
  246.  
  247. #endif
  248.  
  249.     expand(listfile, argc, argp);
  250. }
  251.  
  252. listfile(name)
  253. char *name;
  254. {
  255.     int c;
  256.  
  257. #ifdef XMODEM
  258.     printf("\nListing '%s'\n\022", name);
  259. #endif
  260.     closetx();
  261.     if(opentx(name)==ERROR)
  262.         return ERROR;
  263.     else {
  264.         while((c=getc(fin))!=EOF && c != CPMEOF) {
  265.             if( !(c=putcty(c)))
  266.                 continue;
  267.             if(c==003 || c==CAN || c==013)
  268.                 break;
  269.         }
  270.         closetx();
  271. #ifdef XMODEM
  272.         sendline(024);    /* squelch in case user downloading */
  273. #endif        
  274.     }
  275.     /* cancel rest of files if ^C ^X */
  276.     if(c==003 || c==CAN)
  277.         return ERROR;
  278.     else
  279.         return OK;
  280. }
  281.  
  282. /* fill buf with count chars padding with ^Z for CPM */
  283. filbuf(buf, count)
  284. char *buf;
  285. {
  286.     register c, m;
  287.     m=count;
  288.     while((c=getc(fin))!=EOF) {
  289.         *buf++ =c;
  290.         if(--m == 0)
  291.             break;
  292.     }
  293.     if(m==count)
  294.         return 0;
  295.     else
  296.         while(--m>=0)
  297.             *buf++ = 032;
  298.     return count;
  299. }
  300.  
  301. dodir(argc, argp)
  302. char **argp;
  303. {
  304. /*    printf("Directory\n");*/
  305.     int pdirent();
  306.     cfast=0;        /* counter for 4 across format */
  307.     expand(pdirent, argc, argp);
  308. }
  309. pdirent(name)
  310. {
  311.     printf("%-14s%c", name, (++cfast&03)?' ':'\n');
  312. }
  313. #ifndef CDOS
  314. /* docomp does a directory listing showing sectors for each matched file
  315.  * and computes total transmission time of matched files in batch mode
  316.  * time is sum of:
  317.  *     number of files * open/close time (assumed 5 seconds)
  318.  *    time to xmit and ACK each sector assuming no path delay or error
  319.  *    disk i/o time at each end, not dependent on baud rate
  320.  */
  321. docomp(argc,argp)
  322. char **argp;
  323. {
  324.     unsigned compsecs();
  325.     unsigned spm;    /* sectors per minute-baud */
  326.     unsigned dminutes;    /* tenths of minutes */
  327.     cfast=Numsecs=Numblks=0;
  328. /*    printf("Directory\n");*/
  329.     expand(compsecs, argc, argp);
  330.  
  331.     spm= Baudrate/23;    /* (Baudrate*60)/(10 bits each char * 136 chars) */
  332.     dminutes= (Numfiles/2)+((10*(Numfiles+Numsecs))/spm)+(Numsecs/25);
  333.     printf("\n%u Files %u Blocks %u K\n",
  334.       Numfiles, Numblks, (Numblks*(Secpblk/8)));
  335.     printf("%u Sectors %u.%u Minutes Xmsn Time at %u Baud\n",
  336.       Numsecs, dminutes/10, dminutes%10, Baudrate);
  337.  
  338. }
  339. /* add file length (in CP/M 128 byte records) to Numsecs */
  340. unsigned compsecs(ufn)
  341. char *ufn;
  342. {
  343.     struct fcb fstat;
  344.     printf("%-14s", ufn);
  345.     unspace(ufn);
  346.     setfcb( &fstat, ufn);
  347.     bdos(COMPFILSIZ, &fstat);
  348.     Numsecs += fstat.recn;
  349.     Numblks += (fstat.recn+Secpblk)/Secpblk;
  350.     printf("%4u%c",fstat.recn, (++cfast&03)?' ':'\n');
  351. }
  352. #endif
  353.  
  354. expand(fnx, argc, argp)
  355. int (*fnx)();
  356. char **argp;
  357. {
  358.     char name[PATHLEN], *s;
  359.     Numfiles=0;
  360.  
  361.     if(argc<=0)
  362.         return e1xpand(fnx, "*.*");
  363.     else
  364.         while(--argc>=0) {
  365.             /* change b: to b:*.*     */
  366.             strcpy(name, *argp++);
  367.             if((s=index(':', name)) && *++s == 0)
  368.                 strcpy(s, "*.*");
  369.             if(e1xpand(fnx, name)==ERROR)
  370.                 return ERROR;
  371.         }
  372. }
  373.  
  374. /*
  375.  * e1xpand expands ambiguous pathname afnp
  376.  * calling fnx for each.
  377.  * Modified from: Parameter list builder by Richard Greenlaw
  378.  *                251 Colony Ct. Gahanna, Ohio 43230
  379.  */
  380. e1xpand(fnx, afnp)
  381. int (*fnx)();
  382. char *afnp;    /* possible ambiguous file name*/
  383. {
  384.     struct fcb sfcb, *pfcb;
  385.     char *p, *q, i, byteaddr;
  386.     int filecount, m;
  387.     char tbuf[SECSIZ];
  388.     struct {
  389.         char xYxx[UFNSIZE];        /* unambiguous file name */
  390.     } *fp;
  391.     int strcmp();
  392.  
  393.  
  394.     /* build CPM fcb   */
  395.     unspace(afnp);
  396.     if(setfcb(&sfcb, afnp) == ERROR) {
  397.         printf("%s is bad pattern\n", afnp);
  398.         return ERROR;
  399.     }
  400.  
  401.     if(Wrapped || (bufend-bufcq)<2048) {
  402.         dumprxbuff();        /* I need the space for building the pathlist */
  403.         clearbuff();        /* so the printer won't try to list dir's */
  404.         bufmark=bufst;
  405.     } else
  406.         bufmark=bufcq;
  407.  
  408.     /* Search disk directory for all ufns which match afn*/
  409.     for(fp=bufmark,filecount=0;; fp++,filecount++) {
  410. tryanother:
  411.         bdos(SETDMA, tbuf);
  412.         if((byteaddr=bdos(filecount? SRCHNXT:SRCH, &sfcb))==255)
  413.             break;
  414.         /* calculate pointer to filename fcb returned by bdos */
  415.         pfcb = (tbuf + 32 * (byteaddr % 4));
  416. #ifdef RESTRICTED
  417.         /* check for tag bit on 2nd byte of filename (TAG2) */
  418.         if(pfcb->fname[1]&0200)
  419.             goto tryanother;
  420. #endif
  421.         Numfiles++;
  422.         p = fp;
  423.         if(fp>bufend) {    /* Note: assumes some slop after bufend! */
  424.             printf("Out of Memory for pathname expansion\n");
  425.             return ERROR;
  426.         }
  427.         if(*(afnp+1) == ':') {
  428.             /* Drive spec.*/
  429.             *p++ = *afnp;
  430.             *p++ = ':';
  431.         }
  432.  
  433.         /*Copy filename from directory*/
  434.         q = pfcb;
  435.         for(i =8; i; --i)
  436.             *p++ = (0177& *++q);
  437.         *p++ = '.' ;
  438.  
  439.         /*Copy file extent*/
  440.         for(i = 3; i; --i)
  441.             *p++ = (0177& *++q);
  442.         *p = '\0' ;
  443.  
  444.     }
  445.  
  446.     qsort(bufmark, filecount, UFNSIZE, strcmp);
  447.  
  448.     for(fp=bufmark; --filecount>=0;) {
  449.         p=fp++;
  450.         /* execute desired function with real pathname */
  451.         if((*fnx)(p)==ERROR)
  452.             return ERROR;
  453.     }
  454. }
  455.  
  456. /*
  457.  * cisubstr(string, token) searches for lower case token in string s
  458.  * returns pointer to token within string if found, NULL otherwise
  459.  */
  460. char *cisubstr(s, t)
  461. char *s,*t;
  462. {
  463.     char *ss,*tt;
  464.     /* search for first char of token */
  465.     for(ss=s; *s; s++)
  466.         if(tolower(*s)==*t)
  467.             /* compare token with substring */
  468.             for(ss=s,tt=t; ;) {
  469.                 if(*tt==0)
  470.                     return s;
  471.                 if(tolower(*ss++) != *tt++)
  472.                     break;
  473.             }
  474.     return NULL;
  475. }
  476. #ifdef XMODEM
  477.  
  478. /*
  479.  * lprintf is like regular printf but uses direct output to console
  480.  * This prevents status printouts from disrupting file transfers, etc.
  481.  */
  482.  
  483. lprintf(a,b,c,d,e,f)
  484. char *a, *b, *c, *d, *e, *f;
  485. {
  486.     char lbuf[CMDLEN], *s;
  487.     /* format data into lbuf */
  488.     sprintf(lbuf, a,b,c,d,e,f);
  489.     /* now send lbuf to console directly */
  490.     for(s=lbuf; *s; ) {
  491.         if(*s=='\n') {
  492.             while(!COREADY)        /* expand \n to \r\n */
  493.                 ;
  494.             outp(CDATA, '\r');
  495.         }
  496.         while(!COREADY)
  497.             ;
  498.         outp(CDATA, *s++);
  499.     }
  500. }
  501. #endif
  502.  
  503. /* copy string s onto itself deleting spaces "hello there" > "hellothere" */
  504. unspace(s)
  505. char *s;
  506. {
  507.     char *p;
  508.     for(p=s; *s; s++)
  509.         if(*s != ' ')
  510.             *p++ = *s;
  511.     *p++ =0;
  512. }
  513.  
  514. #ifdef LOGFILE
  515. /*
  516.  * logfile keeps a record of files transmitted.
  517.  * Mode is 's' for send file, 'r' for receive file, 't' for type file
  518.  * Lifted from xcmodem by J. Wierda,R. Hart, and W. Earnest
  519.  */
  520. #define RPB 4    /* log records per buffer */
  521. #define LRL 32    /* logical rec length LRL*RPB == SECSIZ */
  522. logfile(name, mode)
  523. char *name;
  524. char mode;
  525. {
  526.     struct fcb *fcbaddr(),*fp;
  527.     int fd,rnum,bnum;
  528.     char *i, *lrec, lbuf[SECSIZ+2];
  529.     if(i=index(':', name))
  530.         name= ++i;        /* discard possible drive spec */
  531.     bdos(SETGETUSER, 0);    /* get it from user 0 */
  532.     fd=open(LOGFILE,2);
  533.     if(fd == ERROR) {    /* if file absent, create and initialize it */
  534.         fd = creat(LOGFILE);
  535.         if(fd == ERROR)
  536.             return;
  537.         else {
  538.             rnum=1;
  539.             fp=fcbaddr(fd);
  540.             fp->fname[1] |= 0200;    /* set TAG2 bit */
  541.             bdos(SETATTRIB, fp);    /* and update attributes */
  542.         }
  543.     }
  544.     else {
  545.         read(fd, lbuf, 1);
  546.         rnum=atoi(lbuf)+1;
  547.     }
  548.     setmem(lbuf, SECSIZ, 0);
  549.     sprintf(lbuf, "%d\r\n", rnum);
  550.     seek(fd,0,0);
  551.     write(fd, lbuf, 1);        /* update last record number */
  552.     bnum=rnum/RPB;
  553.     rnum=(rnum%RPB)*LRL;
  554.     seek(fd, bnum, 0);
  555.     if(rnum==0)
  556.         setmem(lbuf, SECSIZ, 0);
  557.     else
  558.         read(fd, lbuf, 1);
  559.     sprintf(&lbuf[rnum], "%s %c %u\r\n", name, mode, Baudrate);
  560.     seek(fd, bnum, 0);
  561.     write(fd,lbuf,1);
  562.     close(fd);
  563.     bdos(SETGETUSER, user);
  564. }
  565. #endif
  566. /
  567. logfile(name, mode)
  568. char *name;
  569. char mode;
  570. {
  571.     struct fc