eefile.c

Go to the documentation of this file.
00001 /* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
00002  *      This software is quasi-public; it may be used freely with
00003  *      like software, but may NOT be sold or made part of licensed
00004          *      products without permission of the author.
00005  */
00006 /*
00007  * EEFILE       File reading/writing functions
00008  */
00009 
00010 #include "elle.h"
00011 #include <stdio.h>      /* Use "standard" I/O package for writing */
00012 #ifndef BUFSIZ
00013 #define BUFSIZ BUFSIZE  /* Some places use wrong name in stdio.h */
00014 #endif /*-BUFSIZ*/
00015 #if V6
00016         struct stat {
00017                 int st_dev;
00018                 int st_ino;
00019                 char *st_mode;
00020                 char st_nlink;
00021                 char st_uid;
00022                 char st_gid;
00023                 char st_size0;
00024                 char st_size;
00025                 int st_addr[8];
00026                 long st_atime;
00027                 long st_mtime;
00028         };
00029 #define ENOENT (2)      /* Syscall error - no such file or dir */
00030 #else
00031 #include <errno.h>
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #endif /*-V6*/
00035 
00036 #if TOPS20
00037 #include <sys/file.h>           /* Get open mode bits */
00038 #endif
00039 
00040 extern char *strerror();                /* Return error string for errno */
00041 extern struct buffer *make_buf(), *find_buf();
00042 
00043 char *fncons(), *last_fname();
00044 
00045 int hoardfd = -1;       /* Retain a FD here to ensure we can always write */
00046 
00047 /* Flags for iwritfile() */
00048 #define WF_SMASK 07     /* Source Mask */
00049 #define WF_SBUFF  0     /*   source: Buffer */
00050 #define WF_SREG   1     /*   source: Region */
00051 #define WF_SKILL 2      /*   source: Last Kill */
00052 #define WF_ASK 010      /* Ask for filename to write to */
00053 static int iwritfile();
00054 
00055 /* EFUN: "Find File" */
00056 /*      Ask user for a filename and do a find_file for it.
00057  *      If buffer exists for that filename, select that buffer.
00058  *      Else create a buffer for it, and read in the file if it exists.
00059  */
00060 f_ffile()
00061 {       int find_file();
00062 #if IMAGEN
00063         hack_file("Visit file: ", find_file);
00064 #else
00065         hack_file("Find file: ", find_file);
00066 #endif /*-IMAGEN*/
00067 }
00068 
00069 /* EFUN: "Read File" */
00070 /*      User read_file function, asks user for a filename and reads it
00071  */
00072 f_rfile() { u_r_file("Read file: "); }
00073 
00074 /* EFUN: "Visit File" */
00075 /*      Same as Read File, with different prompt.
00076  */
00077 f_vfile() { u_r_file("Visit file: "); }
00078 
00079 
00080 u_r_file(prompt)
00081 char *prompt;
00082 {       register char *f_name;
00083         register struct buffer *b;
00084 
00085         if((f_name = ask (prompt))==0)  /* prompt user for filename */
00086                 return;                         /* user punted... */
00087         b = cur_buf;
00088         if(*f_name == '\0')
00089           {     if (b -> b_fn == 0)
00090                         ding("No default file name.");
00091                 else read_file(b -> b_fn);
00092           }
00093         else read_file(f_name);
00094         chkfree(f_name);
00095 }
00096 
00097 /* EFUN: "Insert File" */
00098 /*      Asks for a filename and inserts the file at current location.
00099  *      Point is left at beginning, and the mark at the end.
00100  */
00101 f_ifile()
00102 {       int ins_file();
00103         hack_file("Insert file: ", ins_file);
00104 }
00105 
00106 /* EFUN: "Save File" */
00107 /*      Save current buffer to its default file name
00108  */
00109 f_sfile()
00110 {       if(cur_buf->b_flags&B_MODIFIED)
00111                 return(iwritfile(WF_SBUFF));    /* Write buffer, don't ask */
00112         else
00113           {     saynow("(No changes need to be written)");
00114                 return(1);
00115           }
00116 }
00117 
00118 #if FX_SAVEFILES || FX_WFEXIT
00119 /* EFUN: "Save All Files" */
00120 /*  F_SAVEFILES - Offer to save all modified files.
00121  *      With argument, doesn't ask.
00122  *      Returns 0 if user aborts or if an error happened.
00123  */
00124 f_savefiles()
00125 {       register struct buffer *b, *savb;
00126         register int res = 1;
00127         char *ans;
00128 
00129         savb = cur_buf;
00130         for (b = buf_head; res && b; b = b->b_next)
00131                 if ((b->b_flags & B_MODIFIED) && b->b_fn)
00132                   {     if(exp_p)               /* If arg, */
00133                           {     chg_buf(b);     /* just save, don't ask */
00134                                 res = f_sfile();
00135                                 continue;       /* Check next buffer */
00136                           }
00137                         /* Ask user whether to save */
00138                         ans = ask("Buffer %s contains changes - write out? ",
00139                                         b->b_name);
00140                         if(ans == 0)
00141                           {     res = 0;        /* User aborted */
00142                                 break;
00143                           }
00144                         if (upcase(*ans) == 'Y')
00145                           {     chg_buf(b);
00146                                 res = f_sfile();        /* Save File */
00147                           }
00148                         chkfree(ans);
00149                   }
00150         chg_buf(savb);
00151         return(res);
00152 }
00153 #endif /*FX_SAVEFILES||FX_WFEXIT*/
00154 
00155 /* EFUN: "Write File" */
00156 /*      Write out the buffer to an output file.
00157  */
00158 f_wfile()
00159 {       return iwritfile(WF_ASK|WF_SBUFF);
00160 }
00161 
00162 /* EFUN: "Write Region" */
00163 /*      Write region out to a file
00164  */
00165 f_wreg()
00166 {       return iwritfile(WF_ASK|WF_SREG);       /* Ask, write region */
00167 }
00168 
00169 #if FX_WLASTKILL
00170 /* EFUN: "Write Last Kill" (not EMACS) */
00171 /*      Write current kill buffer out to a file.
00172 **      This is mainly for MINIX.
00173 */
00174 extern int kill_ptr;            /* From EEF3 */
00175 extern SBSTR *kill_ring[];
00176 
00177 f_wlastkill()
00178 {       return iwritfile(WF_ASK|WF_SKILL);
00179 }
00180 #endif
00181 
00182 
00183 /* HACK_FILE - intermediate subroutine
00184  */
00185 hack_file(prompt, rtn)
00186 char *prompt;
00187 int (*rtn)();
00188 {       register char *f_name;
00189 
00190         if((f_name = ask(prompt)) == 0)
00191                 return;
00192         if (*f_name != '\0')                    /* Check for null answer */
00193                 (*rtn)(f_name);
00194         chkfree(f_name);
00195 }
00196 
00197 /* FIND_FILE(f_name)
00198  *      If there is a buffer whose fn == f_name, select that buffer.
00199  *      Else create one with name of the last section of f_name and
00200  *      read the file into that buffer.
00201  */
00202 find_file(f_name)
00203 register char *f_name;
00204 {       register struct buffer *b;
00205         register char *ans;
00206         char *lastn;
00207         int fd;
00208 
00209 #if IMAGEN
00210         char real_name[128];            /* File name w/ expanded ~ and $ */
00211         expand_file(real_name, f_name);
00212         f_name = real_name;
00213 #endif /*IMAGEN*/
00214 
00215         for (b = buf_head; b; b = b -> b_next)
00216                 if(b->b_fn && (strcmp (b -> b_fn, f_name) == 0))
00217                         break;
00218         if (b)                          /* if we found one */
00219           {     sel_buf(b);             /* go there */
00220                 return;                 /* and we are done */
00221           }
00222         if((fd = open(f_name,0)) < 0)   /* See if file exists */
00223           {     if(errno != ENOENT)     /* No, check reason */
00224                   {     ferr_ropn();    /* Strange error, complain */
00225                         return;         /* and do nothing else. */
00226                   }
00227           }
00228         else close(fd);                 /* Found!  Close FD, since the */
00229                                         /* read_file rtn will re-open. */
00230 
00231         lastn = last_fname(f_name);     /* Find buffer name */
00232         b = find_buf(lastn);            /* Is there a buffer of that name? */
00233         if (b && (ex_blen(b) || b->b_fn))
00234           {     ans = ask("Buffer %s contains %s, which buffer shall I use? ",
00235                         b -> b_name, b->b_fn ? b->b_fn : "something");
00236                 if(ans == 0) return;            /* Aborted */
00237                 if (*ans != '\0')               /* if null answer, use b */
00238                         b = make_buf(ans);      /* else use ans */
00239                 chkfree(ans);
00240           }
00241         else
00242                 b = make_buf(lastn);
00243         sel_buf(b);
00244         if(fd < 0)              /* If file doesn't exist, */
00245           {     set_fn(f_name); /* just say "new" and set filename */
00246                 return;         /* and return right away. */
00247           }
00248         if (read_file(f_name)==0)       /* File exists, read it in! */
00249           {     if(b->b_fn)             /* Failed... if filename, */
00250                   {     chkfree(b->b_fn);       /* flush the filename. */
00251                         b->b_fn = 0;
00252                   }
00253           }
00254 }
00255 
00256 /* READ_FILE(f_name)
00257  *      Reads file into current buffer, flushing any
00258  *      previous contents (if buffer modified, will ask about saving)
00259  *      Returns 0 if failed.
00260  */
00261 read_file(f_name)
00262 char *f_name;
00263 {
00264 #if IMAGEN
00265         struct stat s;
00266         char real_name[128];            /* File name w/ expanded ~ and $ */
00267 #endif /*IMAGEN*/
00268 
00269         if(!zap_buffer())       /* Flush the whole buffer */
00270                 return;         /* Unless user aborts */
00271 #if IMAGEN
00272         expand_file(real_name, f_name);
00273         f_name = real_name;             /* Hack, hack! */
00274 #endif /*IMAGEN*/
00275         set_fn(f_name);
00276         if (ins_file(f_name)==0)
00277                 return 0;
00278         f_bufnotmod();          /* Say not modified now */
00279 #if IMAGEN
00280         stat(f_name, &s);               /* Get file stat */
00281         cur_buf->b_mtime = s.st_mtime;  /*  and pick out last-modified time */
00282 #endif /*IMAGEN*/
00283         return 1;
00284 }
00285 
00286 /* INS_FILE(f_name)
00287  *      Inserts file named f_name into current buffer at current point
00288  *      Point is not moved; mark is set to end of inserted stuff.
00289  *      Returns 0 if failed, 1 if won.
00290  */
00291 ins_file (f_name)
00292 char *f_name;
00293 {       register int ifd;
00294         register SBSTR *sd;
00295         chroff insdot;                  /* To check for range of mods */
00296 
00297 #if IMAGEN
00298         char real_name[128];            /* File name w/ expanded ~ and $ */
00299         expand_file(real_name, f_name);
00300         f_name = real_name;
00301 #endif /*IMAGEN*/
00302 #if !(TOPS20)
00303         if((ifd = open(f_name,0)) < 0)
00304 #else
00305         if((ifd = open(f_name,O_RDONLY|O_UNCONVERTED)) < 0)
00306 #endif /*TOPS20*/
00307           {     ferr_ropn();            /* Can't open, complain */
00308                 return 0;               /* no redisplay */
00309           }
00310         errno = 0;
00311         if((sd = sb_fduse(ifd)) == 0)
00312           {     if (ifd >= SB_NFILES)
00313                         dingtoo(" Cannot read - too many internal files");
00314                 else if (errno)
00315                         ferr_ropn();
00316                 else errbarf("SB rtn cannot read file?");
00317                 close(ifd);
00318                 return 0;
00319           }
00320         sb_sins(cur_buf,sd);
00321         insdot = e_dot();
00322         f_setmark();                    /* Set mark at current ptr */
00323         if(cur_dot != insdot)           /* If pointer was advanced, */
00324                 buf_tmat(insdot);       /* then stuff was inserted */
00325         e_gocur();
00326         return 1;
00327 }
00328 
00329 ferr_ropn() { ferr(" Cannot read"); }
00330 ferr_wopn() { ferr(" Cannot write"); }
00331 ferr(str)
00332 char *str;
00333 {       saytoo(str);
00334         saytoo(" - ");
00335         dingtoo(strerror(errno));
00336 }
00337 
00338 
00339 /* IWRITFILE - auxiliary for writing files.
00340 **      Returns 1 if write successful, 0 if not.
00341 */
00342 static int
00343 iwritfile(flags)
00344 int flags;
00345 {       register struct buffer *b;
00346         register char *o_name;          /* output file name */
00347         int styp = flags & WF_SMASK;    /* Source type, one of WF_Sxxx */
00348         char *prompt;
00349 #ifdef STDWRITE
00350         register FILE *o_file;          /* output file pointer */
00351         char obuf[BUFSIZ];
00352         chroff dotcnt;
00353 #endif /*STDWRITE*/
00354         int ofd;                        /* output file FD */
00355         SBSTR *sd;
00356         char fname[FNAMSIZ];            /* To avoid chkfree hassle */
00357         char newname[FNAMSIZ];          /* for robustness */
00358         char oldname[FNAMSIZ];          /* ditto */
00359         int res;
00360         struct stat statb;
00361         int statres;
00362 #if IMAGEN
00363         struct stat s;
00364         char real_name[128];            /* File name w/ expanded ~ and $ */
00365 #endif /*IMAGEN*/
00366         res = 1;                        /* Let's keep track of success */
00367 
00368         /* Check for existence of source, and set prompt string */
00369         switch(styp)
00370           {
00371                 case WF_SBUFF:
00372                         prompt = "Write File: ";
00373                         break;
00374                 case WF_SREG:
00375                         if(!mark_p)
00376                           {     dingtoo(" No Mark!");
00377                                 return(0);
00378                           }
00379                         prompt = "Write Region: ";
00380                         break;
00381 #if FX_WLASTKILL
00382                 case WF_SKILL:
00383                         if(!kill_ring[kill_ptr])
00384                           {     dingtoo("No killed stuff");
00385                                 return(0);
00386                           }
00387                         prompt = "Write Last Kill: ";
00388                         break;
00389 #endif
00390                 default:                        /* Internal error */
00391                         errbarf("bad iwritfile arg");
00392                         return 0;
00393           }
00394 
00395         if (flags&WF_ASK)
00396           {     if((o_name = ask(prompt))==0)
00397                         return(0);              /* User punted. */
00398                 strcpy(&fname[0], o_name);      /* Copy filename onto stack */
00399                 chkfree(o_name);
00400           }
00401         o_name = &fname[0];
00402         b = cur_buf;
00403         if (!(flags&WF_ASK) || (*o_name == '\0'))
00404           {     if (b->b_fn == 0)
00405                   {     ding("No default file name.");
00406                         return(0);
00407                   }
00408                 strcpy(o_name, b->b_fn);
00409           }
00410 
00411 #if IMAGEN
00412         expand_file(real_name, o_name);
00413         o_name = real_name;             /* Hack, hack */
00414 #endif /*IMAGEN*/
00415 
00416         statres = stat(o_name,&statb);  /* Get old file's info (if any) */
00417 
00418 #if IMAGEN
00419         /* Now, make sure someone hasn't written the file behind our backs */
00420         if ((styp==WF_SBUFF) && !(flags&WF_ASK)
00421           && b->b_fn && stat(b->b_fn, &s) >= 0)
00422                 if (s.st_mtime != b->b_mtime)
00423                   {     char *ans;
00424                         ans = ask("Since you last read \"%s\", someone has changed it.\nDo you want to write it anyway (NOT RECOMMENDED!)? ",
00425                                    b->b_fn);
00426                         if (ans == 0 || upcase(*ans) != 'Y')
00427                           {
00428                                 ding("I suggest you either read it again, or\nwrite it to a temporary file, and merge the two versions manually.");
00429                                 if (ans) chkfree(ans);
00430                                 return(0);
00431                           }
00432                         if (ans) chkfree(ans);
00433                   }
00434 #endif /*IMAGEN*/
00435 
00436   /* Try to get around major UNIX screw of smashing files.
00437    * This still isn't perfect (screws up with long filenames) but...
00438    * 1. Write out to <newname>
00439    * 2. Rename <name> to <oldname> (may have to delete existing <oldname>)
00440    * 3. Rename <newname> to <name>.
00441    */
00442         fncons(oldname,ev_fno1,o_name,ev_fno2); /* Set up "old" filename */
00443         fncons(newname,ev_fnn1,o_name,ev_fnn2); /* Set up "new" filename */
00444         unlink(newname);                        /* Ensure we don't clobber */
00445         unhoard();                              /* Now give up saved FD */
00446 #if !(V6)       /* Standard V6 doesn't have access call */
00447         if(statres >= 0)                        /* If file exists, */
00448           {     if(access(o_name, 2) != 0)      /* check for write access */
00449                   {     ferr_wopn();
00450                         res = 0;        /* Failure */
00451                         goto wdone;
00452                   }
00453           }
00454 #endif /*-V6*/
00455 #ifdef STDWRITE
00456         if(flags&WF_ASK)
00457           {     if((o_file = fopen(newname, "w")) ==0)  /* Create new output file */
00458                   {     ferr_wopn();
00459                         res = 0;                /* Failure */
00460                         goto wdone;
00461                   }
00462                 setbuf(o_file,obuf);    /* Ensure always have buffer */
00463           }
00464         else    /* New stuff */
00465 #endif /*STDWRITE*/
00466           {
00467 #if !(TOPS20)
00468                 if((ofd = creat(newname,ev_filmod)) < 0)
00469 #else
00470                 if((ofd = open(newname,O_WRONLY|O_UNCONVERTED)) < 0)
00471 #endif /*TOPS20*/
00472                   {     ferr_wopn();
00473                         res = 0;                /* Failure */
00474                         goto wdone;
00475                   }
00476           }
00477         if (styp==WF_SBUFF)
00478                 set_fn(o_name);         /* Won, so set default fn for buff */
00479 #if IMAGEN
00480         saynow("Writing ");
00481         switch(styp)
00482           {     case WF_SBUFF:  saytoo(b->b_fn); break;
00483                 case WF_SREG:   saytoo("region"); break;
00484 #if FX_WLASTKILL
00485                 case WF_SKILL:  saytoo("last kill"); break;
00486 #endif
00487           }
00488         sayntoo("...");
00489 #else
00490         saynow("Writing...");
00491 #endif /*-IMAGEN*/
00492 
00493 #if !(TOPS20)                   /* T20 does all this already */
00494         if(statres >= 0)                /* Get old file's modes */
00495           {                             /* Try to duplicate them */
00496                 /* Do chmod first since after changing owner we may not
00497                 ** have permission to change mode, at least on V6.
00498                 */
00499                 chmod(newname,statb.st_mode & 07777);
00500 #if V6
00501                 chown(newname, (statb.st_gid<<8)|(statb.st_uid&0377));
00502 #else
00503                 chown(newname,statb.st_uid,statb.st_gid);
00504 #endif /*-V6*/
00505           }
00506 #if V6
00507         /* If no old file existed, and we are a V6 system, try to set
00508          * the modes explicitly.  On V7 we're OK because the user can
00509          * diddle "umask" to get whatever is desired.
00510          * On TOPS-20 of course everything is all peachy.
00511          */
00512         else chmod(newname, ev_filmod);
00513 #endif /*V6*/
00514 #endif /*TOPS20*/
00515 
00516 
00517 #ifdef STDWRITE
00518         if(flags&WF_ASK)
00519           {     switch(styp)
00520                   {
00521                         case WF_SBUFF:
00522                                 dotcnt = e_blen();
00523                                 e_gobob();
00524                                 break;
00525                         case WF_SREG:
00526                                 if((dotcnt = mark_dot - cur_dot) < 0)
00527                                   {     e_goff(dotcnt);
00528                                         dotcnt = -dotcnt;
00529                                   }
00530                                 else e_gocur();
00531                                 break;
00532                         /* WF_SKILL not implemented here */
00533                   }
00534                 while(--dotcnt >= 0)
00535                         putc(sb_getc(((SBBUF *)b)), o_file);
00536                 e_gocur();
00537                 fflush(o_file);                 /* Force everything out */
00538                 res = ferror(o_file);           /* Save result of stuff */
00539                 fclose(o_file);                 /* Now flush FD */
00540           }
00541         else    /* New stuff */
00542 #endif /*STDWRITE*/
00543           {
00544                 switch(styp)
00545                   {
00546                         case WF_SBUFF:
00547                                 res = sb_fsave((SBBUF *)b, ofd);
00548                                 break;
00549                         case WF_SREG:
00550                                 e_gocur();
00551                                 sd = e_copyn((chroff)(mark_dot - cur_dot));
00552                                 res = sbx_aout(sd, 2, ofd);
00553                                 sbs_del(sd);
00554                                 break;
00555 #if FX_WLASTKILL
00556                         case WF_SKILL:
00557                                 res = sbx_aout(kill_ring[kill_ptr], 2, ofd);
00558                                 break;
00559 #endif
00560                   }
00561                 close(ofd);
00562           }
00563         if(errno = res)
00564           {     ferr(" Output error");
00565                 res = 0;                /* Failure */
00566                 goto wdone;
00567           }
00568         else
00569                 res = 1;                /* Success so far */
00570         if(styp == WF_SBUFF)
00571                 f_bufnotmod();          /* Reset "buffer modified" flag */
00572 
00573         /* Here we effect the screw-prevention steps explained earlier. */
00574         /* TOPS-20, with generation numbers, need not worry about this. */
00575 #if TOPS20
00576         saynow("Written");
00577 
00578 #else /*-TOPS20*/
00579 #if IMAGEN      /* KLH -- This conditional bracketting is prone to lossage */
00580         /* Only create the .BAK file once per editing session!! */
00581         if ((styp==WF_SBUFF) || !(b->b_flags & B_BACKEDUP))
00582           {     if (styp==WF_SBUFF)
00583                         b->b_flags |= B_BACKEDUP;
00584 #endif /*IMAGEN*/
00585         unlink(oldname);        /* remove any existing "old" file */
00586         if(link(o_name,oldname) == 0)   /* Rename current to "old" */
00587                 unlink(o_name);
00588                 /* Here is the critical point... if we stop here, there is no
00589                  * longer any file with the appropriate filename!!!
00590                  */
00591 #if IMAGEN
00592           }
00593         else
00594                 unlink(o_name);
00595 #endif /*IMAGEN*/
00596         if(link(newname,o_name) == 0)   /* Rename "new" to current */
00597           {     unlink(newname);
00598 #if IMAGEN
00599                 sayntoo("OK");
00600 #else
00601                 saynow("Written");
00602 #endif /*-IMAGEN*/
00603           }
00604         else
00605           {     dingtoo("rename error!");
00606                 res = 0;
00607           }
00608 #endif /*-TOPS20*/
00609 
00610 #if IMAGEN
00611         /* Update the last-modified time for the file in this buffer */
00612         if ((styp == WF_SBUFF) && b->b_fn)
00613           {     stat(b->b_fn, &s);
00614                 b->b_mtime = s.st_mtime;
00615           }
00616 #endif /*IMAGEN*/
00617 
00618 wdone:
00619         hoard();                        /* Get back a retained FD */
00620         return(res);
00621 }
00622 
00623 /* FNCONS(dest,pre,f_name,post)
00624  *      Specialized routine to cons up a filename string into "dest",
00625  *      given prefix and postfix strings to be added onto last component of
00626  *      filename.
00627  */
00628 char *
00629 fncons(dest, pre, f_name, post)
00630 char *dest,*pre,*f_name,*post;
00631 {       register char *cp, *cp2;
00632         char *last_fname();
00633 
00634         cp = dest;
00635         *cp = 0;                        /* Make dest string null initially */
00636         cp2 = last_fname(f_name);       /* Get pointer to beg of last name */
00637         strncat(cp,f_name,cp2-f_name);  /* Copy first part of filename */
00638         if(pre) strcat(cp, pre);        /* If prefix exists, add it on */
00639         cp = last_fname(cp);            /* Recheck in case levels added */
00640         strcat(cp, cp2);                /* Now add last name */
00641         if(cp2 = post)                  /* If there's a postfix, must check */
00642           {     cp[FNAMELEN-strlen(cp2)] = 0;   /* and cut dest so postfix */
00643                 strcat(cp, cp2);                /* will fit on end. */
00644           }
00645         return(dest);
00646 }
00647 
00648 /* LAST_FNAME(string)
00649  *      Get the last component of a file name.  Returns pointer to
00650  *      start of component; does NOT copy string!
00651  */
00652 char *
00653 last_fname(f_name)
00654 char *f_name;
00655 {       register char *cp, *p;
00656         register int c;
00657 
00658         p = f_name;             /* pointer to last slash */
00659         cp = p;
00660         while(c = *cp++)
00661                 if(c == '/')
00662                         p = cp;         /* point to after the slash */
00663         return(p);
00664 }
00665 
00666 /* SET_FN(string)
00667  *      Set the default filename for current buffer to "string".
00668  */
00669 set_fn (string)
00670 char *string;
00671 {       register struct buffer *b;
00672         register char *str;
00673 #if IMAGEN
00674         register char *cp;
00675         register int len;
00676 #endif /*IMAGEN*/
00677         char *strdup();
00678 
00679         b = cur_buf;
00680         str = strdup(string);           /* Copy now in case copying self */
00681         if(b->b_fn)
00682                 chkfree(b->b_fn);
00683         b -> b_fn = str;
00684 #if IMAGEN
00685         /* Do mode determination based on file name (HACK HACK) */
00686         len = strlen(str);
00687         b->b_flags &= ~(B_CMODE|B_TEXTMODE);
00688         if (len > 4)
00689           {     if (strcmp(&str[len - 5], "draft") == 0)
00690                         b->b_flags |= B_TEXTMODE;
00691                 else
00692                   {     cp = &str[len - 4];
00693                         if (strcmp(cp, ".txt") == 0 ||
00694                             strcmp(cp, ".mss") == 0)
00695                                 b->b_flags |= B_TEXTMODE;
00696                   }
00697           }
00698         if (len > 2)
00699           {     cp = &str[len - 2];
00700                 if (strcmp(cp, ".h") == 0 || strcmp(cp, ".c") == 0)
00701                         b->b_flags |= B_CMODE;
00702           }
00703 #endif /*IMAGEN*/
00704         redp(RD_MODE);
00705 }
00706 
00707 /* SAVEWORLD - Attempt to save all changes user has made.
00708  *      Currently this amounts to writing out all modified buffers
00709  *      to the files $HOME/+buffername.  If a buffer is given as argument,
00710  *      only that buffer is saved.
00711  *      This is only called from the error handling routines with
00712  *      the TTY either gone or in normal (non-edit) mode.  The "grunt"
00713  *      flag says whether to output feedback during the saving process.
00714  */
00715 saveworld(bp, grunt)
00716 struct buffer *bp;
00717 int grunt;
00718 {       register struct buffer *b;
00719         register int wfd;
00720         char sfname[FNAMSIZ];
00721         struct buffer *sel_mbuf();
00722 
00723         unhoard();              /* Ensure a FD is free for writing */
00724         if(b = bp) goto once;
00725         while(!bp && (b = sel_mbuf(b)))
00726           {
00727         once:   strcat(strcat(strcpy(sfname,homedir),"/+"),b->b_name);
00728                 if(grunt) printf("Saving %s...",sfname);
00729 #if !(TOPS20)
00730                 if((wfd = creat(sfname, ev_filmod)) < 0)
00731 #else
00732                 if((wfd = open(sfname,O_WRONLY|O_UNCONVERTED)) < 0)
00733 #endif /*TOPS20*/
00734                   {     if(grunt)
00735                                 printf(" error - %s\n", strerror(errno));
00736                   }
00737                 else
00738                   {     sb_fsave((SBBUF *)b, wfd);
00739                         close(wfd);
00740                         if(grunt) printf("\n");
00741                   }
00742                 b->b_flags &= ~B_MODIFIED;
00743           }
00744         hoard();
00745 }
00746 
00747 /* HOARD, UNHOARD - Routines to save a FD for writing, to make sure
00748  *      that we can always write out a buffer no matter how many
00749  *      file descriptors we are currently using.
00750  */
00751 hoard()                 /* Stash away a FD */
00752 {       if(hoardfd <= 0)
00753 #if !(TOPS20)
00754                 hoardfd = open("nul:", 1);
00755 #else
00756                 hoardfd = open("/dev/null", 1);
00757 #endif
00758 }
00759 unhoard()               /* Give up our stashed FD so it can be re-used */
00760 {       close(hoardfd);
00761         hoardfd = -1;
00762 }
00763 
00764 #if IMAGEN
00765 #include <pwd.h>
00766 #include <ctype.h>
00767 
00768 /*
00769  * expand_file: expand any ~user-name/ or $env-var/ prefixes in sfn,
00770  * producing the full name in dfn
00771  */
00772 expand_file(dfn, sfn)
00773 register char *dfn, *sfn;
00774 {
00775         register char *sp, *tp;
00776         register int c;
00777         register struct passwd *pw;
00778         char ts[128];
00779 
00780         /* HORRIBLE, GROSS, DISGUSTING HACK: if the destination and
00781          * source strings are identical (same pointer), then do not
00782          * do any expansion--this happens to work with the current
00783          * structure very well, since multiple expansions may happen.
00784          */
00785         if (dfn == sfn)
00786                 return;
00787 
00788         ts[0] = 0;
00789 
00790         /* If have a leading $, then expand environment variable */
00791         if (*sfn == '$')
00792           {     ++sfn;
00793                 tp = ts;
00794                 while (*tp++ = *sfn)
00795                         if (!isalnum(*sfn))
00796                                 break;
00797                         else
00798                                 ++sfn;
00799                 *--tp = 0;              /* Just in case */
00800                 strcpy(ts, getenv(ts)); /* MARGINAL!! */
00801           }
00802         /* If have leading ~, then expand login name (null means $HOME) */
00803         else if (*sfn == '~')
00804           {     ++sfn;
00805                 if (*sfn == '/' || *sfn == 0)
00806                         strcpy(ts, getenv("HOME"));
00807                 else
00808                   {     tp = ts;
00809                         while (*sfn && *sfn != '/')
00810                                 *tp++ = *sfn++;
00811                         *tp = 0;
00812                         pw = (struct passwd *)getpwnam(ts);
00813                         if (! pw)
00814                                 strcpy(ts, "???");
00815                         else
00816                                 strcpy(ts, pw->pw_dir);
00817                   }
00818           }
00819 
00820         /* Now, ts is either empty or contains the expansion;
00821          * sfn has been updated correctly.
00822          */
00823         strcpy(dfn, ts);
00824         strcat(dfn, sfn);
00825 }
00826 #endif /*IMAGEN*/

Generated on Fri Apr 14 22:56:48 2006 for minix by  doxygen 1.4.6