home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / maint / part03 < prev    next >
Encoding:
Text File  |  1992-05-13  |  72.1 KB  |  2,560 lines

  1. Newsgroups: comp.sources.unix
  2. From: peirce@gw.wmich.edu (Leonard J. Peirce)
  3. Subject: v26i051: maint - full-screen file and directory maintenance tool, Part03/07
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: peirce@gw.wmich.edu (Leonard J. Peirce)
  8. Posting-Number: Volume 26, Issue 51
  9. Archive-Name: maint/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 7)."
  18. # Contents:  mark.c text.c xecute.c
  19. # Wrapped by vixie@cognition.pa.dec.com on Thu May 14 23:05:42 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'mark.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'mark.c'\"
  23. else
  24. echo shar: Extracting \"'mark.c'\" \(26500 characters\)
  25. sed "s/^X//" >'mark.c' <<'END_OF_FILE'
  26. X/******************************************************************************
  27. X*******************************************************************************
  28. X
  29. X   Site:    Western Michigan University Academic Computer Center
  30. X
  31. X   System:    Directory/File System Maintenance
  32. X  
  33. X   Program:    maint
  34. X
  35. X   Version=01    Level=00    01/24/92    Leonard J. Peirce
  36. X
  37. X   Purpose:    Associate commands with individual file entries or cancel
  38. X        all commands for a file.
  39. X
  40. X   Arguments:    See individual routines
  41. X
  42. X   External variables:    See individual routines
  43. X
  44. X   External functions:
  45. X
  46. X    Defined:    mark_text, mark_delete, mark_copy_ren, mark_protect,
  47. X            mark_group, mark_owner, mark_rename, mark_cancel,
  48. X            mark_repeat
  49. X
  50. X    Called:        new_comm, add_filetype, prot_str_to_val, prompt_getstr,
  51. X            free_comstr, squeeze_str
  52. X
  53. X   Files accessed:    See individual routines
  54. X
  55. X   Return codes:    See individual routines
  56. X
  57. X   Compiling instructions:    See Makefile
  58. X
  59. X   Linking instructions:    See Makefile
  60. X
  61. X   Other information:    (C) Copyright 1992, Leonard J. Peirce
  62. X
  63. X********************************************************************************
  64. X*******************************************************************************/
  65. X
  66. X/******************************************************************************/
  67. X/*                                                                            */
  68. X/*                        # I N C L U D E   F I L E S                         */
  69. X/*                                                                            */
  70. X/******************************************************************************/
  71. X
  72. X#include <ctype.h>
  73. X#include <math.h>
  74. X#include <malloc.h>
  75. X#ifdef ultrix
  76. X#include <cursesX.h>
  77. X#else
  78. X#include <curses.h>
  79. X#endif
  80. X#include <string.h>
  81. X#include <grp.h>
  82. X#include <pwd.h>
  83. X#include "maint.h"
  84. X
  85. X/******************************************************************************/
  86. X/*                                                                            */
  87. X/*                             # D E F I N E S                                */
  88. X/*                                                                            */
  89. X/******************************************************************************/
  90. X
  91. X/******************************************************************************/
  92. X/*                                                                            */
  93. X/*          S T R U C T U R E S ,   U N I O N S ,   T Y P E D E F S           */
  94. X/*                                                                            */
  95. X/******************************************************************************/
  96. X
  97. X/******************************************************************************/
  98. X/*                                                                            */
  99. X/*   E X T E R N A L   D E F I N I T I O N S   &   D E C L A R A T I O N S    */
  100. X/*                                                                            */
  101. X/******************************************************************************/
  102. X
  103. extern     int      main_rows;
  104. X
  105. X#ifndef ultrix
  106. extern     void      free();
  107. X#endif
  108. X
  109. extern     COM_DEF  *new_comm();
  110. X
  111. extern     u_short  add_filetype();
  112. X
  113. extern     short      prot_str_to_val();
  114. X
  115. extern     void      prompt_getstr(),
  116. X          squeeze_str(),
  117. X          free_comstr();
  118. X
  119. X     int      mark_text(),
  120. X          mark_delete(),
  121. X          mark_copy_ren(),
  122. X          mark_protect(),
  123. X          mark_group(),
  124. X          mark_owner(),
  125. X          mark_rename(),
  126. X          mark_repeat();
  127. X
  128. X     void      mark_cancel();
  129. X
  130. X/******************************************************************************/
  131. X/*                                                                            */
  132. X/*     S T A T I C   D E F I N I T I O N S   &   D E C L A R A T I O N S      */
  133. X/*                                                                            */
  134. X/******************************************************************************/
  135. X
  136. static     short      prot_abs_to_val();
  137. X
  138. X/*******************************************************************************
  139. X********************************************************************************
  140. X
  141. X  Function:    mark_delete
  142. X
  143. X  Purpose:    The selected file is to be deleted; allocate memory for the
  144. X        command structure (if necessary), link it to the entry, and
  145. X        set up the command structure so that the file can be deleted.
  146. X
  147. X  Global variables:
  148. X
  149. X    Name            Examine/Modify/Use/Read/Write
  150. X    ----            -----------------------------
  151. X    none
  152. X
  153. X  Return Codes:
  154. X
  155. X    Code            Reason
  156. X    ----            ------
  157. X      0            completed successfully
  158. X     -1            problems allocating memory
  159. X
  160. X  Termination Codes:
  161. X
  162. X    Code            Reason
  163. X    ----            ------
  164. X    SUCCESS
  165. X    FAILURE
  166. X
  167. X********************************************************************************
  168. X*******************************************************************************/
  169. X
  170. int mark_delete(ent)
  171. X                    /*******   FORMAL  PARAMETERS   *******/
  172. register ENT_DEF  *ent;            /* entry for file to be deleted          */
  173. X
  174. X{    /*** mark_delete ***/
  175. X                    /********   LOCAL  VARIABLES   ********/
  176. register COM_DEF  *tptr;        /* temporary command structure ptr    */
  177. X
  178. X
  179. X   /* do we need a command structure or does the file already have one? */
  180. X
  181. X   if(ent->command == NULL)
  182. X   {
  183. X      /* we need command structure; allocate it and link it to the file entry */
  184. X
  185. X      tptr = new_comm();
  186. X
  187. X      if(tptr == NULL)
  188. X     return(FAILURE);        /* problems allocating memory          */
  189. X
  190. X      ent->command = tptr;        /* link it to the file entry          */
  191. X   }
  192. X   else
  193. X      tptr = ent->command;        /* else use the one already there     */
  194. X
  195. X   tptr->comm_del = 1;
  196. X
  197. X   /* deallocate all of the memory that might have been used for things
  198. X    * like renaming the file and for a text descriptor
  199. X    */
  200. X
  201. X   if(tptr->ren_name != NULL)        /* need to deallocate rename name?    */
  202. X   {
  203. X
  204. X      free(tptr->ren_name);
  205. X      tptr->comm_ren = 0;        /* make sure to shut of renaming      */
  206. X      tptr->ren_name = NULL;        /* reset the rename name stuff          */
  207. X      tptr->ren_len = 0;
  208. X   }
  209. X
  210. X   if(tptr->text != NULL)        /* need to deallocate text descrip?   */
  211. X   {
  212. X      free(tptr->text);
  213. X      tptr->comm_text = 0;        /* make sure to shut off text descrip */
  214. X      tptr->text = NULL;        /* reset the text descriptor stuff    */
  215. X      tptr->text_len = 0;
  216. X   }
  217. X
  218. X   return(SUCCESS);            /* no problem.....              */
  219. X
  220. X}    /*** mark_delete ***/
  221. X
  222. X/*******************************************************************************
  223. X********************************************************************************
  224. X
  225. X  Function:      mark_copy_ren
  226. X
  227. X  Purpose:      The selected file is to be copied or renamed; allocate the
  228. X        memory for the command structure (if necessary), link it to
  229. X        the file entry,    and set the command in the command structure.
  230. X
  231. X  Global variables:
  232. X                          
  233. X    Name            Examine/Modify/Use/Read/Write
  234. X    ----            -----------------------------
  235. X    none
  236. X
  237. X  Return Codes:
  238. X
  239. X    Code            Reason
  240. X    ----            ------
  241. X      0            completed successfully
  242. X     -1            problems allocating memory
  243. X
  244. X  Termination Codes:
  245. X
  246. X    Code            Reason
  247. X    ----            ------
  248. X    SUCCESS
  249. X    CANT_ALLOCATE        cannot allocate necessary memory
  250. X
  251. X********************************************************************************
  252. X*******************************************************************************/
  253. X   
  254. int mark_copy_ren(window,ent,command,prev_str,repeat)
  255. X                    /*******   FORMAL  PARAMETERS   *******/
  256. X     WINDOW      *window;        /* where to read/write              */
  257. register ENT_DEF  *ent;            /* entry for file to be deleted          */
  258. X     u_short  command;        /* either RENAME or COPY          */
  259. X     char      *prev_str;        /* string to use from mark_repeat()   */
  260. X     u_short  repeat;        /* set if called from mark_repeat()   */
  261. X            
  262. X{    /*** mark_copy_ren ***/
  263. X                    /********   LOCAL  VARIABLES   ********/
  264. register COM_DEF  *tptr;        /* temporary command structure ptr    */
  265. X     char      *dest_ptr;        /* temporary character pointer          */
  266. X     int      length;        /* length of string read in          */
  267. X     char      buf[FULL_SPEC_MAX+1],    /* array for new filename          */
  268. X          prompt[PROMPT_MAX+1];    /* prompt array                  */
  269. X
  270. X
  271. X   if(!repeat)
  272. X   {
  273. X      buf[0] = '\0';            /* reset the buffer              */
  274. X
  275. X      /* set up the prompt for the filename */
  276. X
  277. X      if(command == COPY)
  278. X     strcpy(prompt,"Copy to: ");
  279. X      else
  280. X     strcpy(prompt,"Rename to: ");
  281. X
  282. X      /* read in the file spec */
  283. X
  284. X      prompt_getstr(window,prompt,buf,main_rows,FULL_SPEC_MAX);
  285. X
  286. X      /* was anything specified for the filename? */
  287. X
  288. X      if(*buf == '\0')
  289. X     return(SUCCESS);
  290. X   }
  291. X   else
  292. X      strcpy(buf,prev_str);        /* use string from mark_repeat()      */
  293. X
  294. X   length = strlen(buf);
  295. X
  296. X   /* ok, we have a filename; now determine if we need to allocate a command
  297. X    * structure for this file or if one already exists from a previous command
  298. X    */
  299. X
  300. X   if(ent->command == NULL)
  301. X   {
  302. X      /* we need command structure; allocate it and link it to the file entry */
  303. X            
  304. X      tptr = new_comm();
  305. X
  306. X      if(tptr == NULL)
  307. X     exit(CANT_ALLOCATE);        /* problems allocating memory          */
  308. X
  309. X      ent->command = tptr;        /* link it to the file entry          */
  310. X   }
  311. X   else
  312. X   {
  313. X      tptr = ent->command;        /* else use the one already there     */
  314. X   }
  315. X
  316. X   /* is there already enough room to put the new name in a memory pool? if
  317. X    * there is, just reuse the memory we already have; otherwise, free up
  318. X    * the memory (if there is any) and allocate some to hold the new name
  319. X    */
  320. X
  321. X   if(command == COPY)
  322. X   {
  323. X      if(length > tptr->copy_len)
  324. X      {
  325. X     /* nope, we need more memory; first free the old memory if there
  326. X      * was any
  327. X      */
  328. X
  329. X     if(tptr->copy_len != 0)
  330. X        free(tptr->copy_name);
  331. X
  332. X     /* now allocate some new memory to hold the longer filename
  333. X      * AND the nul character
  334. X      */
  335. X
  336. X     tptr->copy_name = (char *) malloc((u_int) (length + 1));
  337. X
  338. X     if(tptr->copy_name == NULL)
  339. X     {
  340. X        exit(CANT_ALLOCATE);
  341. X     }
  342. X
  343. X     tptr->copy_len = length;    /* save the length of the memory      */
  344. X      }
  345. X
  346. X      dest_ptr = tptr->copy_name;    /* get where to copy the filename to  */
  347. X      tptr->comm_copy = 1;        /* set the command in the structure   */
  348. X   }
  349. X   else
  350. X   {
  351. X      if(length > tptr->ren_len)
  352. X      {
  353. X     /* nope, we need more memory; first free the old memory if there
  354. X      * was any
  355. X      */
  356. X
  357. X     if(tptr->ren_len != 0)
  358. X        free(tptr->ren_name);
  359. X
  360. X     /* now allocate some new memory to hold the longer filename
  361. X      * AND the nul character
  362. X      */
  363. X
  364. X     tptr->ren_name = (char *) malloc((u_int) (length + 1));
  365. X
  366. X     if(tptr->ren_name == NULL)
  367. X        exit(CANT_ALLOCATE);
  368. X
  369. X     tptr->ren_len = length;    /* save the length of the memory      */
  370. X      }
  371. X
  372. X      dest_ptr = tptr->ren_name;    /* get where to copy the filename to  */
  373. X      tptr->comm_ren = TRUE;        /* set the command in the structure   */
  374. X      tptr->comm_del = FALSE;        /* rename implies no delete          */
  375. X   }
  376. X
  377. X   strcpy(dest_ptr,buf);        /* copy it to the right place          */
  378. X
  379. X   return(SUCCESS);
  380. X
  381. X}    /*** mark_copy_ren ***/
  382. X
  383. X/*******************************************************************************
  384. X********************************************************************************
  385. X
  386. X  Function:      mark_text
  387. X
  388. X  Purpose:      The selected file is to get a text descriptor; allocate the
  389. X        memory for the command structure (if necessary), link it to
  390. X        the file entry,    and set the command in the command structure.
  391. X
  392. X  Global variables:
  393. X                          
  394. X    Name            Examine/Modify/Use/Read/Write
  395. X    ----            -----------------------------
  396. X    none
  397. X
  398. X  Return Codes:
  399. X
  400. X    Code            Reason
  401. X    ----            ------
  402. X    SUCCESS
  403. X    FAILURE
  404. X
  405. X  Termination Codes:
  406. X
  407. X    Code            Reason
  408. X    ----            ------
  409. X    SUCCESS
  410. X    FAILURE
  411. X
  412. X********************************************************************************
  413. X*******************************************************************************/
  414. X   
  415. int mark_text(window,ent,text,repeat)
  416. X                    /*******   FORMAL  PARAMETERS   *******/
  417. X     WINDOW      *window;        /* where to read/write              */
  418. register ENT_DEF  *ent;            /* entry for file to be deleted          */
  419. X     char      *text;        /* from mark_repeat              */
  420. X     u_short  repeat;        /* set if called by mark_repeat()     */
  421. X
  422. X{    /*** mark_text ***/
  423. X                    /********   LOCAL  VARIABLES   ********/
  424. register COM_DEF  *tptr;        /* temporary command structure ptr    */
  425. X     int      length;        /* length of string read in          */
  426. X     char      buf[TEXT_MAX+1];    /* array for text descriptor          */
  427. X
  428. X
  429. X   buf[0] = '\0';            /* reset the buffer              */
  430. X
  431. X   /* first put the character that marks the maximum number of characters
  432. X    * that can be specified for the text descriptor
  433. X    */
  434. X
  435. X   if(!repeat)
  436. X      prompt_getstr(window,"Text descriptor: ",buf,main_rows,TEXT_MAX);
  437. X   else
  438. X      strcpy(buf,text);            /* use text descrip from mark_repeat  */
  439. X
  440. X   length = strlen(buf);        /* make sure it's not too long          */
  441. X
  442. X   /* ok, we have the text descriptor; determine if we need to allocate a
  443. X    * command structure for this file or if one already exists from a
  444. X    * previous command
  445. X    */
  446. X
  447. X   if(ent->command == NULL)
  448. X   {
  449. X      /* we need command structure; allocate it and link it to the file entry */
  450. X
  451. X      tptr = new_comm();
  452. X
  453. X      if(tptr == NULL)
  454. X     return(FAILURE);        /* problems allocating memory          */
  455. X
  456. X      ent->command = tptr;        /* link it to the file entry          */
  457. X   }
  458. X   else
  459. X      tptr = ent->command;        /* else use the one already there     */
  460. X
  461. X   /* is there already enough room to store the text descriptor?
  462. X    * if there is, just reuse the memory we already have; otherwise,
  463. X    * allocate some new memory
  464. X    */
  465. X
  466. X   if(length > tptr->text_len)
  467. X   {
  468. X      /* we need more memory; first free up any old memory if there was any */
  469. X
  470. X      if(tptr->text_len != 0)
  471. X     free(tptr->text);
  472. X
  473. X      /* allocate some memory to hold the text descriptor AND the null char */
  474. X
  475. X      tptr->text = (char *) malloc((u_int) (length + 1));
  476. X
  477. X      if(tptr->text == NULL)
  478. X     exit(CANT_ALLOCATE);
  479. X
  480. X      tptr->text_len = length;        /* we have a new length              */
  481. X   }
  482. X
  483. X   if(length)
  484. X      strcpy(tptr->text,buf);        /* copy it to its resting place          */
  485. X   else
  486. X      tptr->text = NULL;
  487. X
  488. X   /* set the command in the command structure */
  489. X
  490. X   tptr->comm_text = TRUE;
  491. X   tptr->comm_del = FALSE;        /* text descriptor implies no delete  */
  492. X
  493. X   return(SUCCESS);
  494. X
  495. X}    /*** mark_text ***/
  496. X
  497. X/*******************************************************************************
  498. X********************************************************************************
  499. X
  500. X  Function:      mark_protect
  501. X
  502. X  Purpose:      The selected file is to be reprotected; allocate the memory
  503. X        for the command structure (if necessary), link it to the file
  504. X        entry,    and set the command in the command structure.
  505. X
  506. X  Global variables:
  507. X                          
  508. X    Name            Examine/Modify/Use/Read/Write
  509. X    ----            -----------------------------
  510. X    main_rows                X
  511. X
  512. X  Return Codes:
  513. X
  514. X    Code            Reason
  515. X    ----            ------
  516. X    SUCCESS
  517. X    FAILURE
  518. X
  519. X********************************************************************************
  520. X*******************************************************************************/
  521. X
  522. int mark_protect(window,ent,prot,repeat)
  523. X                    /*******   FORMAL  PARAMETERS   *******/
  524. X     WINDOW      *window;        /* where to read/write              */
  525. register ENT_DEF  *ent;            /* entry for file to be deleted          */
  526. X     u_short  prot,            /* from mark_repeat()              */
  527. X          repeat;        /* set if called from mark_repeat()   */
  528. X
  529. X{    /*** mark_protect ***/
  530. X                    /********   LOCAL  VARIABLES   ********/
  531. register COM_DEF  *tptr;        /* temporary command structure ptr    */
  532. X     u_short  prot_val;        /* temporary protection value          */
  533. X     char      buf[PROT_INP_MAX+1];    /* array for protection string          */
  534. X
  535. X
  536. X   if(!repeat)
  537. X   {
  538. X      buf[0] = '\0';            /* initialize input buffer          */
  539. X
  540. X      /* prompt for and read in the protection string */
  541. X
  542. X      prompt_getstr(window,"Protection: ",buf,main_rows,PROT_INP_MAX);
  543. X
  544. X      /* if nothing was specified for the protection string, just return from
  545. X       * right here
  546. X       */
  547. X
  548. X      if(*buf == '\0')
  549. X     return(SUCCESS);
  550. X
  551. X      squeeze_str(buf);            /* squeeze the blanks out          */
  552. X
  553. X      /* now determine if the protection string specified is valid */
  554. X
  555. X      if(prot_str_to_val(buf,&prot_val) == FAILURE)
  556. X      {
  557. X     /* maybe it's an absolute number; try to convert it */
  558. X
  559. X     if(prot_abs_to_val(buf,&prot_val) == FAILURE)
  560. X        return(FAILURE);        /* invalid protection string          */
  561. X      }
  562. X   }
  563. X   else
  564. X      prot_val = prot;            /* use value from mark_repeat()          */
  565. X
  566. X   /* at this point, the protection string has been edited and is considered
  567. X    * valid; get the integer value for the protection string and store it in
  568. X    * in the command structure; first, do we need a command structure or does
  569. X    * the file have one from a previous command?
  570. X    */
  571. X
  572. X   if(ent->command == NULL)
  573. X   {
  574. X      /* we need command structure; allocate it and link it to the file entry */
  575. X
  576. X      tptr = new_comm();
  577. X
  578. X      if(tptr == NULL)
  579. X     return(-1);            /* problems allocating memory          */
  580. X
  581. X      ent->command = tptr;        /* link it to the file entry          */
  582. X   }
  583. X   else
  584. X      tptr = ent->command;        /* else use the one already there     */
  585. X
  586. X   tptr->comm_prot = 1;            /* set the command in the structure   */
  587. X   tptr->prot = add_filetype(ent->type,prot_val);
  588. X   tptr->comm_del = 0;            /* protection implies no delete          */
  589. X
  590. X   return(SUCCESS);            /* fine.........              */
  591. X
  592. X}    /*** mark_protect ***/
  593. X
  594. X/*******************************************************************************
  595. X********************************************************************************
  596. X
  597. X  Function:      mark_cancel
  598. X
  599. X  Purpose:      Cancel all commands for the specified file entry and deallocate
  600. X        the command structure for the file.
  601. X
  602. X  Global variables:
  603. X                          
  604. X    Name            Examine/Modify/Use/Read/Write
  605. X    ----            -----------------------------
  606. X    none
  607. X
  608. X  Return Codes:
  609. X
  610. X    Code            Reason
  611. X    ----            ------
  612. X      0            completed successfully
  613. X     -1            problems allocating memory
  614. X
  615. X********************************************************************************
  616. X*******************************************************************************/
  617. X
  618. void mark_cancel(ent)
  619. X                    /*******   FORMAL  PARAMETERS   *******/
  620. X     ENT_DEF  *ent;            /* file entry pointer              */
  621. X
  622. X{    /*** mark_cancel ***/
  623. X
  624. X
  625. X   if(ent->command != NULL)
  626. X   {
  627. X      /* first free up any memory that might be  holding character strings */
  628. X
  629. X      free_comstr(ent->command);
  630. X
  631. X      ent->command = NULL;         /* no more structure for file entry   */
  632. X   }
  633. X
  634. X   return;
  635. X
  636. X}    /*** mark_cancel ***/
  637. X
  638. X/*******************************************************************************
  639. X********************************************************************************
  640. X
  641. X  Function:      mark_repeat
  642. X
  643. X  Purpose:      Repeat the last command on the current file.
  644. X
  645. X  Global variables:
  646. X                          
  647. X    Name            Examine/Modify/Use/Read/Write
  648. X    ----            -----------------------------
  649. X    none
  650. X
  651. X  Return Codes:
  652. X
  653. X    Code            Reason
  654. X    ----            ------
  655. X    SUCCESS
  656. X    FAILURE
  657. X
  658. X********************************************************************************
  659. X*******************************************************************************/
  660. X
  661. int mark_repeat(window,ent,prev_ptr,command)
  662. X                    /*******   FORMAL  PARAMETERS   *******/
  663. X     WINDOW      *window;        /* needed to pass along              */
  664. X     ENT_DEF  *ent,            /* what is to be marked              */
  665. X          *prev_ptr;        /* where to find previous mark          */
  666. X     u_short  command;        /* command to be used              */
  667. X
  668. X{    /*** mark_repeat ***/
  669. X                    /********   LOCAL  VARIABLES   ********/
  670. X     COM_DEF  *comm_ptr;        /* previous entry's commands          */
  671. X     int      retval;        /* return value                  */
  672. X
  673. X
  674. X   comm_ptr = prev_ptr->command;
  675. X
  676. X   switch(command)
  677. X   {
  678. X      case(DELETE):
  679. X
  680. X     retval = mark_delete(ent);
  681. X     break;
  682. X
  683. X      case(PROTECT):
  684. X
  685. X     retval = mark_protect(window,ent,comm_ptr->prot,TRUE);
  686. X     break;
  687. X
  688. X      case(RENAME):
  689. X
  690. X     retval = mark_copy_ren(window,ent,RENAME,comm_ptr->ren_name,TRUE);
  691. X     break;
  692. X
  693. X      case(COPY):
  694. X
  695. X     retval = mark_copy_ren(window,ent,COPY,comm_ptr->copy_name,TRUE);
  696. X     break;
  697. X
  698. X      case(OWNER):
  699. X
  700. X     retval = mark_owner(window,ent,comm_ptr->owner,TRUE);
  701. X     break;
  702. X
  703. X      case(GROUP):
  704. X
  705. X     retval = mark_group(window,ent,comm_ptr->group,TRUE);
  706. X     break;
  707. X
  708. X      case(TEXT):
  709. X
  710. X     retval = mark_text(window,ent,comm_ptr->text,TRUE);
  711. X     break;
  712. X
  713. X      default:
  714. X     break;
  715. X   }
  716. X
  717. X   return(retval);
  718. X
  719. X}    /*** mark_repeat ***/
  720. X
  721. X/*******************************************************************************
  722. X********************************************************************************
  723. X
  724. X  Function:      mark_group
  725. X
  726. X  Purpose:      Prompt for the new group of the file and look it up in the
  727. X        group file.  If it doesn't exist, just use the numeric version.
  728. X
  729. X  Global variables:
  730. X                          
  731. X    Name            Examine/Modify/Use/Read/Write
  732. X    ----            -----------------------------
  733. X    main_rows                X
  734. X
  735. X  Return Codes:
  736. X
  737. X    Code            Reason
  738. X    ----            ------
  739. X    SUCCESS
  740. X    FAILURE
  741. X    BAD_GROUP        invalid group specified
  742. X
  743. X********************************************************************************
  744. X*******************************************************************************/
  745. X
  746. int mark_group(window,ent,group,repeat)
  747. X                    /*******   FORMAL  PARAMETERS   *******/
  748. X     WINDOW      *window;        /* where to read/write              */
  749. X     ENT_DEF  *ent;            /* file entry pointer              */
  750. X     gid_t      group;        /* from mark_repeat()              */
  751. X     u_short  repeat;        /* set if called by mark_repeat()     */
  752. X
  753. X{    /*** mark_group ***/
  754. X                    /********   LOCAL  VARIABLES   ********/
  755. struct     group      *gid_ptr;        /* from getgrnam()              */
  756. X     COM_DEF  *tptr;        /* temporary pointer              */
  757. X     char      *tptr2;        /* for checking for digit string      */
  758. X     gid_t      gid;            /* temporary group id holder          */
  759. X     char      buf[ID_STR_MAX+1];    /* for getting group string          */
  760. X
  761. X
  762. X   if(!repeat)
  763. X   {
  764. X      prompt_getstr(window,"Change group to: ",buf,main_rows,ID_STR_MAX);
  765. X
  766. X      if(*buf == '\0')
  767. X     return(SUCCESS);
  768. X
  769. X      /* see if the group is valid */
  770. X
  771. X      gid_ptr = getgrnam(buf);
  772. X
  773. X      if(gid_ptr == NULL)
  774. X      {
  775. X     /* not found, try to use numeric value */
  776. X
  777. X     tptr2 = buf;
  778. X
  779. X     /* skip leading blanks first */
  780. X
  781. X     while(isspace(*tptr2))
  782. X        ++tptr2;
  783. X
  784. X     while(*tptr2 && isdigit(*tptr2))
  785. X        ++tptr2;
  786. X
  787. X     if(*tptr2 != '\0')
  788. X        return(BAD_GROUP);
  789. X
  790. X     /* it's ok; change it to a integer and store it */
  791. X
  792. X     gid = (gid_t) atoi(buf);
  793. X      }
  794. X      else
  795. X     gid = gid_ptr->gr_gid;        /* found; use it              */
  796. X   }
  797. X   else
  798. X      gid = group;            /* use group from mark_repeat()          */
  799. X
  800. X   if(ent->command == NULL)
  801. X   {
  802. X      /* we need command structure; allocate it and link it to the file entry */
  803. X
  804. X      tptr = new_comm();
  805. X
  806. X      if(tptr == NULL)
  807. X     return(FAILURE);        /* problems allocating memory          */
  808. X
  809. X      ent->command = tptr;        /* link it to the file entry          */
  810. X   }
  811. X   else
  812. X      tptr = ent->command;        /* else use the one already there     */
  813. X
  814. X   tptr->comm_grp = 1; 
  815. X   tptr->group = gid;
  816. X   tptr->comm_del = 0;            /* Group implies !Delete          */
  817. X
  818. X   return(SUCCESS);
  819. X
  820. X}    /*** mark_group ***/
  821. X
  822. X/*******************************************************************************
  823. X********************************************************************************
  824. X
  825. X  Function:      mark_owner
  826. X
  827. X  Purpose:      Prompt for the new owner of the file and look it up in the
  828. X        passwd file.  If it doesn't exist, just use the numeric version.
  829. X
  830. X  Global variables:
  831. X                          
  832. X    Name            Examine/Modify/Use/Read/Write
  833. X    ----            -----------------------------
  834. X    main_rows                X
  835. X
  836. X  Return Codes:
  837. X
  838. X    Code            Reason
  839. X    ----            ------
  840. X    SUCCESS
  841. X    FAILURE
  842. X    BAD_OWNER        invalid owner specified
  843. X
  844. X********************************************************************************
  845. X*******************************************************************************/
  846. X
  847. int mark_owner(window,ent,owner,repeat)
  848. X                    /*******   FORMAL  PARAMETERS   *******/
  849. X     WINDOW      *window;        /* where to read/write              */
  850. X     ENT_DEF *ent;            /* file entry pointer              */
  851. X     uid_t      owner;        /* from mark_repeat()              */
  852. X     u_short  repeat;        /* set if called by mark_repeat()     */
  853. X
  854. X{    /*** mark_owner ***/
  855. X                    /********   LOCAL  VARIABLES   ********/
  856. struct     passwd      *uid_ptr;        /* from getpwnam()              */
  857. X     COM_DEF  *tptr;        /* temporary pointer              */
  858. X     char      *tptr2;        /* for checking for digit string      */
  859. X     uid_t      uid;            /* temporary group id holder          */
  860. X     char      buf[ID_STR_MAX+1];    /* for getting group string          */
  861. X
  862. X
  863. X   if(!repeat)
  864. X   {
  865. X      prompt_getstr(window,"Change owner to: ",buf,main_rows,ID_STR_MAX);
  866. X
  867. X      if(*buf == '\0')
  868. X     return(SUCCESS);
  869. X
  870. X      /* see if the owner is valid */
  871. X
  872. X      uid_ptr = getpwnam(buf);
  873. X
  874. X      if(uid_ptr == NULL)
  875. X      {
  876. X     /* not found, try to use numeric value */
  877. X
  878. X     tptr2 = buf;
  879. X
  880. X     /* skip leading blanks first */
  881. X
  882. X     while(isspace(*tptr2))
  883. X        ++tptr2;
  884. X
  885. X     while(*tptr2 && isdigit(*tptr2))
  886. X        ++tptr2;
  887. X
  888. X     if(*tptr2 != '\0')
  889. X        return(BAD_OWNER);
  890. X
  891. X     /* it's ok; change it to a integer and store it */
  892. X
  893. X     uid = (uid_t) atoi(buf);
  894. X      }
  895. X      else
  896. X     uid = uid_ptr->pw_uid;        /* found; use it              */
  897. X   }
  898. X   else
  899. X      uid = owner;            /* use owner from mark_repeat()          */
  900. X
  901. X   if(ent->command == NULL)
  902. X   {
  903. X      /* we need command structure; allocate it and link it to the file entry */
  904. X
  905. X      tptr = new_comm();
  906. X
  907. X      if(tptr == NULL)
  908. X     return(FAILURE);        /* problems allocating memory          */
  909. X
  910. X      ent->command = tptr;        /* link it to the file entry          */
  911. X   }
  912. X   else
  913. X      tptr = ent->command;        /* else use the one already there     */
  914. X
  915. X   tptr->comm_own = 1; 
  916. X   tptr->owner = uid;
  917. X   tptr->comm_del = 0;
  918. X
  919. X   return(SUCCESS);
  920. X
  921. X}    /*** mark_owner ***/
  922. X
  923. X/*******************************************************************************
  924. X********************************************************************************
  925. X
  926. X  Function:      prot_abs_to_val
  927. X
  928. X  Purpose:      See if a string is an absolute protection mode and calculate
  929. X        the integer value if possible.
  930. X
  931. X  Global variables:
  932. X                          
  933. X    Name            Examine/Modify/Use/Read/Write
  934. X    ----            -----------------------------
  935. X    none
  936. X
  937. X  Return Codes:
  938. X
  939. X    Code            Reason
  940. X    ----            ------
  941. X    SUCCESS
  942. X    FAILURE
  943. X
  944. X********************************************************************************
  945. X*******************************************************************************/
  946. X
  947. static short prot_abs_to_val(buffer,mode)
  948. X                    /*******   FORMAL  PARAMETERS   *******/
  949. register char      *buffer;        /* mode string                  */
  950. X     u_short  *mode;        /* where to put the mode value          */
  951. X
  952. X{    /*** prot_abs_to_val ***/
  953. X                    /********   LOCAL  VARIABLES   ********/
  954. register int      temp;            /* temporary mode holder          */
  955. X
  956. X
  957. X   temp = 0;
  958. X
  959. X   while(*buffer >= '0' && *buffer <= '7')
  960. X   {
  961. X      temp = (temp << 3) + (*buffer - '0');
  962. X      ++buffer;
  963. X   }
  964. X
  965. X   while(isspace(*buffer))        /* skip any trailing whitespace          */
  966. X      ++buffer;
  967. X
  968. X   if(*buffer != '\0')
  969. X      return(FAILURE);
  970. X
  971. X   *mode = temp;
  972. X   return(SUCCESS);
  973. X
  974. X}    /*** prot_abs_to_val ***/
  975. END_OF_FILE
  976. if test 26500 -ne `wc -c <'mark.c'`; then
  977.     echo shar: \"'mark.c'\" unpacked with wrong size!
  978. fi
  979. # end of 'mark.c'
  980. fi
  981. if test -f 'text.c' -a "${1}" != "-c" ; then 
  982.   echo shar: Will not clobber existing file \"'text.c'\"
  983. else
  984. echo shar: Extracting \"'text.c'\" \(20210 characters\)
  985. sed "s/^X//" >'text.c' <<'END_OF_FILE'
  986. X/******************************************************************************
  987. X*******************************************************************************
  988. X
  989. X   Site:    Western Michigan University Academic Computer Center
  990. X
  991. X   System:    Directory/File System Maintenance
  992. X  
  993. X   Program:    maint
  994. X
  995. X   Version=01    Level=00    01/24/92    Leonard J. Peirce
  996. X
  997. X   Purpose:    Routines for dealing with text descriptors.
  998. X
  999. X   Arguments:    See individual routines
  1000. X
  1001. X   External variables:    See individual routines
  1002. X
  1003. X   External functions:
  1004. X
  1005. X          Defined:    create_text, put_text, read_text_des, text_match,
  1006. X            text_search
  1007. X
  1008. X          Called:    clear_mess, get_name, get_pool_mem, prompt_getstr,
  1009. X            put_pool, strindex
  1010. X
  1011. X   Files accessed:
  1012. X
  1013. X   Return codes:    See individual routines
  1014. X
  1015. X   Compiling instructions:    See Makefile
  1016. X
  1017. X   Linking instructions:    See Makefile
  1018. X
  1019. X   Other information:    (C) Copyright 1992, Leonard J. Peirce
  1020. X
  1021. X********************************************************************************
  1022. X*******************************************************************************/
  1023. X
  1024. X/******************************************************************************/
  1025. X/*                                                                            */
  1026. X/*                        # I N C L U D E   F I L E S                         */
  1027. X/*                                                                            */
  1028. X/******************************************************************************/
  1029. X
  1030. X#include <stdio.h>
  1031. X#ifdef ultrix
  1032. X#include <cursesX.h>
  1033. X#else
  1034. X#include <curses.h>
  1035. X#endif
  1036. X#include <string.h>
  1037. X#include "maint.h"
  1038. X
  1039. X/******************************************************************************/
  1040. X/*                                                                            */
  1041. X/*                             # D E F I N E S                                */
  1042. X/*                                                                            */
  1043. X/******************************************************************************/
  1044. X
  1045. X/******************************************************************************/
  1046. X/*                                                                            */
  1047. X/*          S T R U C T U R E S ,   U N I O N S ,   T Y P E D E F S           */
  1048. X/*                                                                            */
  1049. X/******************************************************************************/
  1050. X
  1051. X/******************************************************************************/
  1052. X/*                                                                            */
  1053. X/*   E X T E R N A L   D E F I N I T I O N S   &   D E C L A R A T I O N S    */
  1054. X/*                                                                            */
  1055. X/******************************************************************************/
  1056. X
  1057. extern     int      main_rows;
  1058. X
  1059. extern     char      *get_pool_mem();
  1060. X
  1061. extern     int      strindex();
  1062. X
  1063. extern     void      put_pool(),
  1064. X          prompt_getstr(),
  1065. X          clear_mess(),
  1066. X          *get_name();
  1067. X
  1068. X     char      *text_search(),
  1069. X          *text_match();
  1070. X
  1071. X     int      read_text_des(),
  1072. X          create_text();
  1073. X
  1074. X     void      put_text();
  1075. X
  1076. X/******************************************************************************/
  1077. X/*                                                                            */
  1078. X/*     S T A T I C   D E F I N I T I O N S   &   D E C L A R A T I O N S      */
  1079. X/*                                                                            */
  1080. X/******************************************************************************/
  1081. X
  1082. X/*******************************************************************************
  1083. X********************************************************************************
  1084. X
  1085. X  Function:    read_text_des
  1086. X
  1087. X  Purpose:    Attempt to read in the text descriptors from the text des-
  1088. X        criptor file for the current directory.
  1089. X
  1090. X  Global variables:
  1091. X
  1092. X    Name            Examine/Modify/Use/Read/Write
  1093. X    ----            -----------------------------
  1094. X    none
  1095. X
  1096. X  Return Codes:
  1097. X
  1098. X    Code            Reason
  1099. X    ----            ------
  1100. X    NO_FILE            file does not exist
  1101. X    CANT_OPEN        cannot open MAINT.TDF file
  1102. X    BAD_FILE        bad text descriptor file
  1103. X     0            text descriptor file successfully read
  1104. X
  1105. X  Termination Codes:
  1106. X
  1107. X    Code            Reason
  1108. X    ----            ------
  1109. X     none
  1110. X
  1111. X********************************************************************************
  1112. X*******************************************************************************/
  1113. X
  1114. int read_text_des(dirptr,curr_pool,dir_text,pool_length,num_file)
  1115. X                    /*******   FORMAL  PARAMETERS   *******/
  1116. register ENT_DEF  *dirptr;        /* pointer to directory entries          */
  1117. X     POOL_DEF **curr_pool;        /* pointer to pointer to current pool */
  1118. X     char      **dir_text;        /* directory text descriptor array    */
  1119. X     size_t      pool_length;        /* length of pool to allocate          */
  1120. X     short      num_file;        /* number of files in directory          */
  1121. X
  1122. X{    /*** read_text_des ***/
  1123. X                    /********   LOCAL  VARIABLES   ********/
  1124. X     FILE      *fptr;        /* text file pointer              */
  1125. X     ENT_DEF  *currptr;        /* current entry for searching          */
  1126. X     int      length;        /* length of string              */
  1127. X     char      *tptr,        /* temporary character pointer          */
  1128. X           *status,        /* return code status holder          */
  1129. X          *temp,
  1130. X          text_buf[TEXT_REC_MAX+10];
  1131. X
  1132. X
  1133. X   /* open the text descriptor file */
  1134. X
  1135. X   fptr = fopen(TEXT_FILE,"r");
  1136. X
  1137. X   if(fptr == NULL)
  1138. X      return(NO_FILE);            /* no problem; just no file          */
  1139. X   /* get the first record; this is the text descriptor for the directory;
  1140. X    * the format for this record is
  1141. X    *    >>><text descriptor for directory>
  1142. X    */
  1143. X
  1144. X   status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
  1145. X
  1146. X   if(status == NULL)
  1147. X   {
  1148. X      *dir_text = NULL;
  1149. X      fclose(fptr);
  1150. X      return(CANT_OPEN);
  1151. X   }
  1152. X
  1153. X   /* make sure this record is in the right form */
  1154. X
  1155. X   if(strindex(text_buf,">>>") != 0)
  1156. X   {
  1157. X      /* close the text descriptor file */
  1158. X
  1159. X      fclose(fptr);
  1160. X      return(BAD_FILE);
  1161. X   }
  1162. X
  1163. X   /* store this in the memory pools and set the dir_text pointer to point
  1164. X    * to it
  1165. X    */
  1166. X
  1167. X   length = strlen(text_buf);
  1168. X   text_buf[length - 1] = '\0';        /* lop off the \n              */
  1169. X
  1170. X   put_pool(dir_text,curr_pool,&text_buf[3],strlen(&text_buf[3]),pool_length);
  1171. X
  1172. X   /* skip the comment lines in the text descriptor file */
  1173. X
  1174. X   status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
  1175. X
  1176. X   while(status != NULL && text_buf[0] == '>')
  1177. X      status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
  1178. X
  1179. X   if(status == NULL)
  1180. X   {
  1181. X      fclose(fptr);
  1182. X      return(SUCCESS);            /* end-of-file here....              */
  1183. X   }
  1184. X
  1185. X   /* now get each text descriptor record and match it up with a filename */
  1186. X
  1187. X   /* set the current file entry pointer to actually pointer to one entry
  1188. X    * BEFORE the current entry; it will be updated inside text_search to
  1189. X    * point to the correct entry; this is done so that text_search can be
  1190. X    * more general
  1191. X    */
  1192. X
  1193. X   currptr = dirptr - 1;             /* set where we start to look          */
  1194. X
  1195. X   while(status != NULL)
  1196. X   {                         
  1197. X      /* search for a match with the filename in the text descriptor record */
  1198. X
  1199. X      length = strlen(text_buf);
  1200. X      text_buf[length - 1] = '\0';
  1201. X
  1202. X      if((tptr = text_search(dirptr,&currptr,text_buf,num_file)) != NULL)
  1203. X      {
  1204. X     /* match; store the text descriptor in a memory pool */
  1205. X
  1206. X/*     put_pool(&(currptr->text),curr_pool,tptr,(size_t) strlen(tptr),
  1207. X          pool_length);*/
  1208. X     put_pool(&temp,curr_pool,tptr,(size_t) strlen(tptr),
  1209. X          pool_length);
  1210. X     currptr->text = temp;
  1211. X      }
  1212. X
  1213. X      status = fgets(text_buf,TEXT_REC_MAX+1,fptr);
  1214. X   }
  1215. X
  1216. X   fclose(fptr);
  1217. X   return(SUCCESS);            /* everything done              */
  1218. X
  1219. X}    /*** read_text_des ***/
  1220. X
  1221. X/*******************************************************************************
  1222. X********************************************************************************
  1223. X
  1224. X  Function:    text_search
  1225. X
  1226. X  Purpose:    Search the directory entries for a match with the current
  1227. X        text descriptor record.  If one is found, return a pointer
  1228. X        to the actual text of the text descriptor and update the
  1229. X        current directory entry pointer to point to the NEXT entry
  1230. X        to check for a text descriptor match.
  1231. X
  1232. X  Global variables:
  1233. X
  1234. X    Name            Examine/Modify/Use/Read/Write
  1235. X    ----            -----------------------------
  1236. X    none
  1237. X
  1238. X  Return Codes:
  1239. X
  1240. X    Code            Reason
  1241. X    ----            ------
  1242. X    retval            pointer to actual text of text descriptor
  1243. X    NULL            no match for text descriptor
  1244. X
  1245. X  Termination Codes:
  1246. X
  1247. X    Code            Reason
  1248. X    ----            ------
  1249. X     none
  1250. X
  1251. X********************************************************************************
  1252. X*******************************************************************************/
  1253. X
  1254. char *text_search(dirptr,currptr,text_rec,num_file)
  1255. X                    /*******   FORMAL  PARAMETERS   *******/
  1256. X     ENT_DEF  *dirptr,        /* pointer to all directory entries   */
  1257. X           **currptr;        /* pointer to current directory entry */
  1258. X     char      *text_rec;        /* current text descriptor record     */
  1259. X     short      num_file;        /* number of files in directory          */
  1260. X
  1261. X{    /*** text_search ***/
  1262. X                    /********   LOCAL  VARIABLES   ********/
  1263. register ENT_DEF  *ptr;            /* current file entry pointer          */
  1264. X     ENT_DEF  *origptr;        /* original directory pointer          */
  1265. X     char      *retval;        /* return value                  */
  1266. X     u_long      curr_index;        /* index value for setting pointer    */
  1267. X
  1268. X
  1269. X   /* get pointer to directory that we need; this is the one following
  1270. X    * (modulo the number of files in the directory) the entry that we
  1271. X    * were on the last time through
  1272. X    */
  1273. X
  1274. X   curr_index = *currptr - dirptr;    /* get current entry index          */
  1275. X   curr_index = (curr_index + 1L) % (u_long) num_file;
  1276. X
  1277. X   ptr = dirptr + curr_index;        /* get pointer to the NEW entry          */
  1278. X
  1279. X   /* first check to see if we have a match with the current entry */
  1280. X
  1281. X   if((retval = text_match(ptr->filename,text_rec)) != NULL)
  1282. X   {
  1283. X      /* we have a match; return the pointer to the beginning of the
  1284. X       * actual text of the text descriptor AND update the currptr
  1285. X       * return value to point to the next entry so that the next time
  1286. X       * this routine is called, we can start up one after where we
  1287. X       * left off here
  1288. X       */
  1289. X
  1290. X      *currptr = ptr;            /* return pointer to current entry    */
  1291. X      return(retval);            /* match....                  */
  1292. X   }
  1293. X
  1294. X   /* no match with the current entry; search the entries until 1) we find a
  1295. X    * a match, or until we have examined all of the entries
  1296. X    */
  1297. X
  1298. X   origptr = ptr;            /* save where we are right now          */
  1299. X   curr_index = (curr_index + 1L) % (u_long) num_file;
  1300. X   ptr = dirptr + curr_index;
  1301. X
  1302. X   while(ptr != origptr)        /* until we are back where we started */
  1303. X   {
  1304. X      /* check for a match */
  1305. X
  1306. X      if((retval = text_match(ptr->filename,text_rec)) != NULL)
  1307. X      {
  1308. X     /* we have a match; return the pointer to the beginning of the
  1309. X      * actual text of the text descriptor AND update the currptr
  1310. X      * return value to point to the current directory entry so that
  1311. X      * we know where we left off last time through
  1312. X      */
  1313. X
  1314. X     *currptr = ptr;
  1315. X     return(retval);
  1316. X      }
  1317. X
  1318. X      /* update the current entry pointer to point to the next entry */
  1319. X
  1320. X      curr_index = (curr_index + 1L) % (u_long) num_file;
  1321. X      ptr = dirptr + curr_index;
  1322. X   }
  1323. X
  1324. X   return(NULL);            /* no match for this text descriptor  */
  1325. X
  1326. X}    /*** text_search ***/
  1327. X
  1328. X/*******************************************************************************
  1329. X********************************************************************************
  1330. X
  1331. X  Function:    text_match
  1332. X
  1333. X  Purpose:    Determine if a text descriptor record is the correct one
  1334. X        for a file entry.
  1335. X
  1336. X  Global variables:
  1337. X
  1338. X    Name            Examine/Modify/Use/Read/Write
  1339. X    ----            -----------------------------
  1340. X    none
  1341. X
  1342. X  Return Codes:
  1343. X
  1344. X    Code            Reason
  1345. X    ----            ------
  1346. X
  1347. X    NULL            no match for text descriptor record
  1348. X    text_rec + 1L        pointer to beginning of text descriptor part
  1349. X                of the record
  1350. X
  1351. X  Termination Codes:
  1352. X
  1353. X    Code            Reason
  1354. X    ----            ------
  1355. X     none
  1356. X
  1357. X********************************************************************************
  1358. X*******************************************************************************/
  1359. X
  1360. char *text_match(filename,text_rec)
  1361. X                    /*******   FORMAL  PARAMETERS   *******/
  1362. register char      *filename,        /* filename to look for              */
  1363. X          *text_rec;        /* current text descriptor record     */
  1364. X
  1365. X{    /*** text_match ***/
  1366. X
  1367. X
  1368. X   while((*filename == *text_rec) && (*filename != '\0'))
  1369. X   {
  1370. X      filename++;
  1371. X      text_rec++;
  1372. X   }
  1373. X
  1374. X   /* now check to see if we had a match */
  1375. X
  1376. X   if(*text_rec == ' ')
  1377. X   {
  1378. X      /* return a pointer to the beginning of the text descriptor */
  1379. X
  1380. X      return(text_rec + 1L);
  1381. X   }
  1382. X
  1383. X   return(NULL);            /* not correct record for file          */
  1384. X
  1385. X}    /*** text_match ***/
  1386. X
  1387. X/*******************************************************************************
  1388. X********************************************************************************
  1389. X
  1390. X  Function:    put_text
  1391. X
  1392. X  Purpose:    Put the text descriptor for the directory on the screen.
  1393. X
  1394. X  Global variables:
  1395. X
  1396. X    Name            Examine/Modify/Use/Read/Write
  1397. X    ----            -----------------------------
  1398. X    COLS                    X
  1399. X
  1400. X  Return Codes:
  1401. X
  1402. X    Code            Reason
  1403. X    ----            ------
  1404. X    SUCCESS            Everything fine
  1405. X    FAILURE            Error parsing new filename
  1406. X
  1407. X********************************************************************************
  1408. X*******************************************************************************/
  1409. X
  1410. void put_text(window,text_desc)
  1411. X                          /*******   FORMAL  PARAMETERS   *******/
  1412. X     WINDOW      *window;        /* where to write              */
  1413. X     char      *text_desc;         /* text descriptor buffer          */
  1414. X
  1415. X{    /*** put_text ***/
  1416. X                    /********   LOCAL  VARIABLES   ********/
  1417. X     size_t      length;        /* string length holder              */
  1418. static     char      buf[MAX_SCREEN_COLS+5], /* formatting buffer              */
  1419. X          spaces[] =        /* spaces array for centering stuff   */
  1420. X"                                                                    ";
  1421. X
  1422. X
  1423. X   if(text_desc != NULL)        /* is there anything to write?          */
  1424. X   {
  1425. X      length = (COLS - strlen(text_desc))/2;
  1426. X      spaces[length] = '\0';          /* make spaces for centering          */
  1427. X      cat(5,buf,spaces,text_desc,spaces," ");
  1428. X      buf[COLS] = '\0';            /* make sure we have the right length */
  1429. X      spaces[length] = ' ';        /* reset spaces array for next time   */
  1430. X
  1431. X      /* write directory text descriptor in reverse video at top of screen */
  1432. X
  1433. X      mvwaddstr(window,SPEC_WINDOW_ROWS-1,0,buf);
  1434. X   }
  1435. X   else
  1436. X   {
  1437. X      /* erase the one that might be on the screen, since this directory
  1438. X       * doesn't have a text descriptor
  1439. X       */
  1440. X
  1441. X      wmove(window,SPEC_WINDOW_ROWS-1,0);
  1442. X      wclrtoeol(window);
  1443. X   }
  1444. X
  1445. X   wrefresh(window);
  1446. X   return;
  1447. X
  1448. X}    /*** put_text ***/
  1449. X
  1450. X/*******************************************************************************
  1451. X********************************************************************************
  1452. X
  1453. X  Function:    create_text
  1454. X
  1455. X  Purpose:    Attempt to create the text descriptor file if the user wants
  1456. X        to.  The user is prompted for the text descriptor for the
  1457. X        directory and the file is written with the entry for the
  1458. X        text descriptor file itself.
  1459. X
  1460. X  Global variables:
  1461. X
  1462. X    Name            Examine/Modify/Use/Read/Write
  1463. X    ----            -----------------------------
  1464. X    none
  1465. X
  1466. X  Return Codes:
  1467. X
  1468. X    Code            Reason
  1469. X    ----            ------
  1470. X    DONT_CREATE        user does not want text descriptor file created
  1471. X    CANT_OPEN        error opening/writing text descriptor file
  1472. X    NEW_FILE        new text descriptor file created
  1473. X
  1474. X********************************************************************************
  1475. X*******************************************************************************/
  1476. X
  1477. int create_text(window)
  1478. X                    /*******   FORMAL  PARAMETERS   *******/
  1479. X     WINDOW      *window;        /* where to read/write              */
  1480. X
  1481. X{    /*** create_text ***/
  1482. X                    /********   LOCAL  VARIABLES   ********/
  1483. X     FILE      *fptr;        /* text file pointer              */
  1484. X     char      term_code,         /* keystroke read in              */
  1485. X          buf[MAX_SCREEN_COLS+1], /* for all kinds of output stuff    */
  1486. X          text_buf[DIR_TEXT_MAX+1]; /* buffer for reading from screen */
  1487. X
  1488. X
  1489. X   sprintf(buf,"Text descriptor file %s does not exist.  Create it? [y] ",
  1490. X       TEXT_FILE);
  1491. X
  1492. X   /* prompt the user to see if they want to create the text descriptor file */
  1493. X
  1494. X   info_mess(buf);
  1495. X   term_code = wgetch(window);        /* get their response              */
  1496. X   clear_mess(window);            /* clear the prompt from the screen   */
  1497. X
  1498. X   /* now see what key was pressed */
  1499. X
  1500. X   if(term_code == 'N' || term_code == 'n')
  1501. X      return(DONT_CREATE);        /* don't create the file here, either */
  1502. X
  1503. X   /* ok, we need to create the file; open it for writing */
  1504. X
  1505. X   fptr = fopen(TEXT_FILE,"w");
  1506. X
  1507. X   if(fptr == NULL)
  1508. X      return(CANT_OPEN);
  1509. X
  1510. X   /* the file has been opened ok; get the descriptor for the directory,
  1511. X    * format it, and write it to the text descriptor file
  1512. X    */
  1513. X
  1514. X   /* prompt for and read in the text descriptor for the directory itself */
  1515. X
  1516. X   prompt_getstr(window,"Text descriptor for directory: ",text_buf,main_rows,
  1517. X         DIR_TEXT_MAX);
  1518. X
  1519. X   text_buf[DIR_TEXT_MAX] = '\0';    /* make sure it's not too long          */
  1520. X   cat(4,buf,">>>",text_buf,"\n");    /* format it correctly              */
  1521. X
  1522. X   /* now write the directory text descriptor record to the file */
  1523. X
  1524. X   fputs(buf,fptr);
  1525. X   fputs(">\n",fptr);            /* write a spacing record          */
  1526. X
  1527. X   /* now write the text descriptor entry for the text descriptor file
  1528. X    * itself; this is so the user knows what the file is when they bring
  1529. X    * the text descriptors in
  1530. X    */
  1531. X
  1532. X   cat(3,buf,TEXT_FILE," text descriptor file\n"); 
  1533. X   fputs(buf,fptr);
  1534. X
  1535. X   fclose(fptr);
  1536. X   return(NEW_FILE);
  1537. X
  1538. X}    /*** create_text ***/
  1539. X
  1540. X/*******************************************************************************
  1541. X********************************************************************************
  1542. X
  1543. X  Function:    get_text
  1544. X
  1545. X  Purpose:    Set up and get the text descriptors for the current
  1546. X        directory.  Being able to update slot_width is essential
  1547. X        for proc_dir() and is one of the reasons this routine
  1548. X        exists.  slot_width is set in set_args() but set_args()
  1549. X        is only called from main().
  1550. X
  1551. X  Global variables:
  1552. X
  1553. X    Name            Examine/Modify/Use/Read/Write
  1554. X    ----            -----------------------------
  1555. X    args.text           X        X
  1556. X    args.text_startup       X
  1557. X
  1558. X  Return Codes:
  1559. X
  1560. X    Code            Reason
  1561. X    ----            ------
  1562. X    none
  1563. X
  1564. X********************************************************************************
  1565. X*******************************************************************************/
  1566. X
  1567. void get_text(args,dirptr,curr_pool,dir_text,mess_flag,slot_width,text_flag,
  1568. X          pool_length,num_file)
  1569. X
  1570. X                    /*******   FORMAL  PARAMETERS   *******/
  1571. X     ARG_DEF  *args;        /* run-time arguments              */
  1572. X     ENT_DEF  *dirptr;        /* pointer to directory information   */
  1573. X     POOL_DEF **curr_pool;        /* pointer to current memory pool     */
  1574. X     char      **dir_text,        /* pointer to directory text descrip  */
  1575. X          *mess_flag;        /* set if information mess on screen  */
  1576. X     short      *slot_width,        /* slot width for current directory   */
  1577. X          *text_flag;        /* set if descrip file was processed  */
  1578. X     size_t      pool_length;        /* length for allocating new pools    */
  1579. X     short      num_file;        /* number of files in directory          */
  1580. X
  1581. X{    /*** get_text ***/
  1582. X                    /********   LOCAL  VARIABLES   ********/
  1583. X     short      status;        /* return status from read_text_des() */
  1584. X
  1585. X
  1586. X   *text_flag = 0;
  1587. X
  1588. X   if(args->text)
  1589. X   {
  1590. X      /* yes, read in the text descriptors */
  1591. X
  1592. X      *text_flag = args->text;        /* set descrip flag for this direct.  */
  1593. X
  1594. X      if(args->text == DISPLAY_TEXT && !args->text_startup)
  1595. X     *slot_width += TEXT_MAX + 1;    /* assume we will get text descrips   */
  1596. X
  1597. X      status = read_text_des(dirptr,curr_pool,dir_text,pool_length,num_file);
  1598. X
  1599. X      /* check to see if there were any problems getting the text descriptors */
  1600. X
  1601. X      if(status == BAD_FILE)
  1602. X      {
  1603. X     info_mess("Invalid format for text descriptor file");
  1604. X     *mess_flag = 1;
  1605. X     *text_flag = 0;        /* no text descrips for directory     */
  1606. X
  1607. X     if(args->text == DISPLAY_TEXT)    /* only update slot_width if needed   */
  1608. X        *slot_width = *slot_width - (TEXT_MAX + 1);
  1609. X
  1610. X     sleep(1);
  1611. X      }
  1612. X      else if(status == CANT_OPEN)
  1613. X      {
  1614. X     info_mess("Cannot open text descriptor file");
  1615. X     *mess_flag = 1;
  1616. X     *text_flag = 0;        /* no text descrips for directory     */
  1617. X
  1618. X     if(args->text == DISPLAY_TEXT)    /* only update slot_width if needed   */
  1619. X        *slot_width = *slot_width - (TEXT_MAX + 1);
  1620. X
  1621. X     sleep(1);
  1622. X      }
  1623. X      else if(status == NO_FILE)
  1624. X      {
  1625. X     *text_flag = 0;        /* no text descrips for directory     */
  1626. X
  1627. X     if(args->text == DISPLAY_TEXT)    /* update slot_width if it needs it   */
  1628. X       *slot_width = *slot_width - (TEXT_MAX + 1);
  1629. X      }
  1630. X   }
  1631. X
  1632. X
  1633. X   return;
  1634. X
  1635. X}    /*** get_text ***/
  1636. END_OF_FILE
  1637. if test 20210 -ne `wc -c <'text.c'`; then
  1638.     echo shar: \"'text.c'\" unpacked with wrong size!
  1639. fi
  1640. # end of 'text.c'
  1641. fi
  1642. if test -f 'xecute.c' -a "${1}" != "-c" ; then 
  1643.   echo shar: Will not clobber existing file \"'xecute.c'\"
  1644. else
  1645. echo shar: Extracting \"'xecute.c'\" \(22377 characters\)
  1646. sed "s/^X//" >'xecute.c' <<'END_OF_FILE'
  1647. X/******************************************************************************
  1648. X*******************************************************************************
  1649. X
  1650. X   Site:    Western Michigan University Academic Computer Center
  1651. X
  1652. X   System:    Directory/File System Maintenance
  1653. X  
  1654. X   Program:    maint
  1655. X
  1656. X   Version=01    Level=00    01/24/92    Leonard J. Peirce
  1657. X
  1658. X   Purpose:    Execute the commands in a directory, informing the user of
  1659. X        the result of each.
  1660. X
  1661. X   Arguments:    See individual routines
  1662. X
  1663. X   External variables:    See individual routines
  1664. X
  1665. X   Maint external functions:
  1666. X
  1667. X    Defined:    xecute
  1668. X
  1669. X    Called:        free_comstr, mystrcpy
  1670. X
  1671. X   Files accessed:    Files with commands associated with them
  1672. X
  1673. X   Return codes:    See individual routines
  1674. X
  1675. X   Compiling instructions:    See Makefile
  1676. X
  1677. X   Linking instructions:    See Makefile
  1678. X
  1679. X   Other information:    (C) Copyright 1990, Leonard J. Peirce
  1680. X
  1681. X********************************************************************************
  1682. X*******************************************************************************/
  1683. X
  1684. X/******************************************************************************/
  1685. X/*                                                                            */
  1686. X/*                        # I N C L U D E   F I L E S                         */
  1687. X/*                                                                            */
  1688. X/******************************************************************************/
  1689. X
  1690. X#include <fcntl.h>
  1691. X#include <errno.h>
  1692. X#include <stdio.h>
  1693. X#include <string.h>
  1694. X#ifdef ultrix
  1695. X#include <cursesX.h>
  1696. X#else
  1697. X#include <curses.h>
  1698. X#endif
  1699. X#include "maint.h"
  1700. X#include <sys/stat.h>
  1701. X
  1702. X/******************************************************************************/
  1703. X/*                                                                            */
  1704. X/*                             # D E F I N E S                                */
  1705. X/*                                                                            */
  1706. X/******************************************************************************/
  1707. X
  1708. X#define XMESS_PAUSE 4            /* length of pause for error messages */
  1709. X
  1710. X/******************************************************************************/
  1711. X/*                                                                            */
  1712. X/*          S T R U C T U R E S ,   U N I O N S ,   T Y P E D E F S           */
  1713. X/*                                                                            */
  1714. X/******************************************************************************/
  1715. X
  1716. X/******************************************************************************/
  1717. X/*                                                                            */
  1718. X/*   E X T E R N A L   D E F I N I T I O N S   &   D E C L A R A T I O N S    */
  1719. X/*                                                                            */
  1720. X/******************************************************************************/
  1721. X
  1722. extern     char      *mystrcpy();
  1723. X
  1724. extern     int      unlink(),
  1725. X          chmod(),
  1726. X          rename(),
  1727. X          read(),
  1728. X          write(),
  1729. X          open(),
  1730. X          close(),
  1731. X          errno;
  1732. X
  1733. extern     void      free_comstr();
  1734. X
  1735. X     void      xecute();
  1736. X
  1737. X/******************************************************************************/
  1738. X/*                                                                            */
  1739. X/*     S T A T I C   D E F I N I T I O N S   &   D E C L A R A T I O N S      */
  1740. X/*                                                                            */
  1741. X/******************************************************************************/
  1742. X
  1743. static     char      *make_err_msg();
  1744. X
  1745. static     int      write_text(),
  1746. X          copy_file(),
  1747. X          rename_file();
  1748. X
  1749. static     void      make_xmess();
  1750. X
  1751. X/*******************************************************************************
  1752. X********************************************************************************
  1753. X
  1754. X  Function:    xecute
  1755. X
  1756. X  Purpose:    Execute all of the file commands for the current directory.
  1757. X        Display success and failure messages to the screen for each
  1758. X        of the files.
  1759. X
  1760. X  Global variables:
  1761. X
  1762. X    Name            Examine/Modify/Use/Read/Write
  1763. X    ----            -----------------------------
  1764. X    none
  1765. X
  1766. X  Return Codes:
  1767. X
  1768. X    Code            Reason
  1769. X    ----            ------
  1770. X    none
  1771. X
  1772. X********************************************************************************
  1773. X*******************************************************************************/
  1774. X
  1775. void xecute(ent,dir_text,num_file)
  1776. X                    /*******   FORMAL  PARAMETERS   *******/
  1777. X     ENT_DEF  *ent;            /* file entry pointer              */
  1778. X     char      *dir_text;        /* pointer to directory text descrip. */
  1779. X     short      num_file;        /* number of files in directory          */
  1780. X
  1781. X{    /*** xecute ***/
  1782. X                    /********   LOCAL  VARIABLES   ********/
  1783. X     int      status,        /* return code status holder          */
  1784. X          prefix_len,        /* length of message prefix string    */
  1785. X          text_write;        /* set to FAILURE if write_text fails */
  1786. register COM_DEF  *comm_ptr;        /* pointer to command structure          */
  1787. X     short      i;            /* loop and array index              */
  1788. X     char      buf[SPEC_MAX*2+10];    /* for formatting messages          */
  1789. X
  1790. X
  1791. X   text_write = SUCCESS;        /* assume it will work              */
  1792. X   i = 0;
  1793. X
  1794. X   while(i < num_file)
  1795. X   {
  1796. X      if(ent->command != NULL)        /* does this file have any commands?  */
  1797. X      {
  1798. X     comm_ptr = ent->command;    /* get a pointer to the comm struct   */
  1799. X
  1800. X     if(comm_ptr->comm_copy)
  1801. X     {
  1802. X        status = copy_file(ent->filename,comm_ptr->copy_name);
  1803. X        make_xmess(buf,ent->filename,&prefix_len,status,COPY,ent->type);
  1804. X        xmess(buf,prefix_len);
  1805. X
  1806. X        if(status != SUCCESS)
  1807. X        {
  1808. X           beep();
  1809. X           sleep(XMESS_PAUSE);    /* let user read error message          */
  1810. X        }
  1811. X
  1812. X        errno = 0;
  1813. X     }
  1814. X
  1815. X     if(comm_ptr->comm_ren)
  1816. X     {
  1817. X        status = rename_file(ent->filename,comm_ptr->ren_name);
  1818. X        make_xmess(buf,ent->filename,&prefix_len,status,RENAME,ent->type);
  1819. X        xmess(buf,prefix_len);
  1820. X
  1821. X        if(status != SUCCESS)
  1822. X        {
  1823. X           beep();
  1824. X           sleep(XMESS_PAUSE);
  1825. X        }
  1826. X
  1827. X        errno = 0;
  1828. X     }
  1829. X
  1830. X     if(comm_ptr->comm_prot)
  1831. X     {
  1832. X        if(chmod(ent->filename,(int) comm_ptr->prot) == 0)
  1833. X           status = SUCCESS;
  1834. X        else
  1835. X           status = FAILURE;
  1836. X
  1837. X        make_xmess(buf,ent->filename,&prefix_len,status,RENAME,ent->type);
  1838. X        xmess(buf,prefix_len);
  1839. X
  1840. X        if(status != SUCCESS)
  1841. X        {
  1842. X           beep();
  1843. X           sleep(XMESS_PAUSE);
  1844. X        }
  1845. X
  1846. X        errno = 0;
  1847. X     }
  1848. X
  1849. X     if(comm_ptr->comm_own)
  1850. X     {
  1851. X        if(chown(ent->filename,comm_ptr->owner,-1) == 0)
  1852. X           status = SUCCESS;
  1853. X        else
  1854. X           status = FAILURE;
  1855. X
  1856. X        make_xmess(buf,ent->filename,&prefix_len,status,OWNER,ent->type);
  1857. X        xmess(buf,prefix_len);
  1858. X
  1859. X        if(status != SUCCESS)
  1860. X        {
  1861. X           beep();
  1862. X           sleep(XMESS_PAUSE);
  1863. X        }
  1864. X
  1865. X        errno = 0;
  1866. X     }
  1867. X
  1868. X     if(comm_ptr->comm_grp)
  1869. X     {
  1870. X        if(chown(ent->filename,-1,comm_ptr->group) == 0)
  1871. X           status = SUCCESS;
  1872. X        else
  1873. X           status = FAILURE;
  1874. X
  1875. X        make_xmess(buf,ent->filename,&prefix_len,status,GROUP,ent->type);
  1876. X        xmess(buf,prefix_len);
  1877. X
  1878. X        if(status != SUCCESS)
  1879. X        {
  1880. X           beep();
  1881. X           sleep(XMESS_PAUSE);
  1882. X        }
  1883. X
  1884. X        errno = 0;
  1885. X     }
  1886. X
  1887. X     if(comm_ptr->comm_text != NULL && text_write == SUCCESS)
  1888. X     {
  1889. X        /* yes, write a text descriptor */
  1890. X
  1891. X        text_write = write_text(ent->filename,comm_ptr->text,
  1892. X                    dir_text,FALSE);
  1893. X
  1894. X        ent->text = NULL;        /* no more text descriptor          */
  1895. X     }
  1896. X
  1897. X     if(comm_ptr->comm_del)
  1898. X     {
  1899. X        if(ent->type != DIRECTORY)
  1900. X        {
  1901. X           /* nothing special, just use unlink */
  1902. X
  1903. X           if(unlink(ent->filename) == 0)
  1904. X          status = SUCCESS;
  1905. X           else
  1906. X          status = FAILURE;
  1907. X
  1908. X           make_xmess(buf,ent->filename,&prefix_len,status,DELETE,
  1909. X              ent->type);
  1910. X        }
  1911. X        else
  1912. X        {
  1913. X           if(rmdir(ent->filename) == 0)
  1914. X              status = SUCCESS;
  1915. X           else
  1916. X          status = FAILURE;
  1917. X
  1918. X           make_xmess(buf,ent->filename,&prefix_len,status,DELETE,
  1919. X              ent->type);
  1920. X        }
  1921. X
  1922. X        xmess(buf,prefix_len);
  1923. X
  1924. X        if(status != SUCCESS)
  1925. X        {
  1926. X           beep();
  1927. X           sleep(XMESS_PAUSE);
  1928. X        }
  1929. X
  1930. X        ent->text = NULL;        /* no more text descriptor          */
  1931. X        errno = 0;
  1932. X     }
  1933. X
  1934. X     free_comstr(ent->command);    /* free the command structure          */
  1935. X     ent->command = NULL;
  1936. X      }
  1937. X
  1938. X      if(ent->text != NULL && text_write == SUCCESS)
  1939. X      {
  1940. X     /* yes, write a text descriptor */
  1941. X
  1942. X     text_write = write_text(ent->filename,ent->text,dir_text,FALSE);
  1943. X      }
  1944. X
  1945. X      ++ent;
  1946. X      ++i;
  1947. X   }
  1948. X
  1949. X   text_write = write_text(NULLPTR,NULLPTR,NULLPTR,TRUE);
  1950. X   return;
  1951. X
  1952. X}    /*** xecute ***/     
  1953. X
  1954. X/*******************************************************************************
  1955. X********************************************************************************
  1956. X
  1957. X  Function:    copy_file
  1958. X
  1959. X  Purpose:    Copy the source file to the destination file.
  1960. X
  1961. X  Global variables:
  1962. X
  1963. X    Name            Examine/Modify/Use/Read/Write
  1964. X    ----            -----------------------------
  1965. X    none
  1966. X
  1967. X  Return Codes:
  1968. X
  1969. X    Code            Reason
  1970. X    ----            ------
  1971. X    SUCCESS
  1972. X    CANT_STAT        cannot stat source file
  1973. X    CANT_OPEN        cannot open source file
  1974. X    CANT_OPEN_DEST        cannot open destination file
  1975. X    CANT_WRITE        error writing to destination file
  1976. X    CANT_CHMOD        cannot do a chmod() on file
  1977. X
  1978. X********************************************************************************
  1979. X*******************************************************************************/
  1980. X
  1981. static int copy_file(source,dest)
  1982. X                    /*******   FORMAL  PARAMETERS   *******/
  1983. X     char      *source,        /* file to copy from              */
  1984. X          *dest;        /* file to copy to              */
  1985. X
  1986. X{    /*** copy_file ***/
  1987. X                    /********   LOCAL  VARIABLES   ********/
  1988. struct     stat      statbuf;        /* for stat on source file          */
  1989. X     char      buf[BUFSIZ+5];    /* read/write buffer              */
  1990. X     int      numbyte,        /* bytes read/written              */
  1991. X          badwrite,        /* loop control variable          */
  1992. X          inputfd,        /* input file descriptor          */
  1993. X          outputfd;        /* output file descriptor          */
  1994. X
  1995. X
  1996. X   if(stat(source,&statbuf) < 0)
  1997. X      return(CANT_STAT);
  1998. X
  1999. X   if((inputfd = open(source,O_RDONLY,0)) < 0)
  2000. X      return(CANT_OPEN);
  2001. X
  2002. X   /* see if the destination is a directory; if it is, we have some work to
  2003. X    * do to create the destination filename
  2004. X    */
  2005. X
  2006. X   if(stat(dest,&statbuf) == 0 && ((statbuf.st_mode & S_IFMT) == S_IFDIR))
  2007. X   {
  2008. X      /* it is a directory; cat the source name onto the destination name */
  2009. X
  2010. X      strcat(dest,"/");
  2011. X      strcat(dest,source);
  2012. X   }
  2013. X
  2014. X   if((outputfd = open(dest,O_WRONLY | O_TRUNC | O_CREAT,0)) < 0)
  2015. X   {
  2016. X      close(inputfd);
  2017. X      return(CANT_OPEN_DEST);
  2018. X   }
  2019. X
  2020. X   numbyte = read(inputfd,buf,BUFSIZ);
  2021. X   badwrite = FALSE;
  2022. X
  2023. X   while(numbyte > 0 && !badwrite)
  2024. X   {
  2025. X      if((write(outputfd,buf,numbyte)) == -1)
  2026. X     badwrite = TRUE;
  2027. X      else
  2028. X     numbyte = read(inputfd,buf,BUFSIZ);
  2029. X   }
  2030. X
  2031. X   close(inputfd);
  2032. X   close(outputfd);
  2033. X
  2034. X   if(badwrite)                /* did it work?                  */
  2035. X   {
  2036. X      unlink(dest);            /* nope, get rid of destination file  */
  2037. X      return(CANT_WRITE);
  2038. X   }
  2039. X
  2040. X   /* make sure the destination file has the same mode as the source */
  2041. X
  2042. X   if(chmod(dest,(int) statbuf.st_mode) != 0)
  2043. X      return(CANT_CHMOD);
  2044. X
  2045. X   return(SUCCESS);
  2046. X
  2047. X}    /*** copy_file ***/
  2048. X
  2049. X/*******************************************************************************
  2050. X********************************************************************************
  2051. X
  2052. X  Function:    rename_file
  2053. X
  2054. X  Purpose:    Rename the source file to the destination file.
  2055. X
  2056. X  Global variables:
  2057. X
  2058. X    Name            Examine/Modify/Use/Read/Write
  2059. X    ----            -----------------------------
  2060. X    none
  2061. X
  2062. X  Return Codes:
  2063. X
  2064. X    Code            Reason
  2065. X    ----            ------
  2066. X    SUCCESS
  2067. X    FAILURE
  2068. X    CANT_STAT        cannot stat destination file
  2069. X
  2070. X********************************************************************************
  2071. X*******************************************************************************/
  2072. X
  2073. static int rename_file(source,dest)
  2074. X                    /*******   FORMAL  PARAMETERS   *******/
  2075. X     char      *source,        /* file to be renamed              */
  2076. X          *dest;        /* file to rename to              */
  2077. X
  2078. X{    /*** rename_file ***/
  2079. X                    /********   LOCAL  VARIABLES   ********/
  2080. struct     stat      statbuf;        /* for stat on source file          */
  2081. X
  2082. X
  2083. X   /* see if the destination is a directory; if it is, we have some work to
  2084. X    * do to create the destination filename
  2085. X    */
  2086. X
  2087. X   if(stat(dest,&statbuf) == 0 && ((statbuf.st_mode & S_IFMT) == S_IFDIR))
  2088. X   {
  2089. X      /* it is a directory; cat the source name onto the destination name */
  2090. X
  2091. X      strcat(dest,"/");
  2092. X      strcat(dest,source);
  2093. X   }
  2094. X
  2095. X   if(rename(source,dest) != 0)
  2096. X      return(FAILURE);
  2097. X
  2098. X   return(SUCCESS);
  2099. X
  2100. X}    /*** rename_file ***/
  2101. X
  2102. X/*******************************************************************************
  2103. X********************************************************************************
  2104. X
  2105. X  Function:    make_xmess
  2106. X
  2107. X  Purpose:    Create a message for the xecute() routine by looking at
  2108. X        what is being performed and the status code.  First, the
  2109. X        action is determined to get the correct string.  Then, the
  2110. X        correct result string is determined, based on the action
  2111. X        type.  If an error occurred, errno is examined to see if an
  2112. X        intelligent error message can be constructed from it's value.
  2113. X
  2114. X  Global variables:
  2115. X
  2116. X    Name            Examine/Modify/Use/Read/Write
  2117. X    ----            -----------------------------
  2118. X    COLS               X
  2119. X
  2120. X  Return Codes:
  2121. X
  2122. X    Code            Reason
  2123. X    ----            ------
  2124. X    none
  2125. X
  2126. X********************************************************************************
  2127. X*******************************************************************************/
  2128. X
  2129. static void make_xmess(buf,filename,prefix_len,status,action,type)
  2130. X                    /*******   FORMAL  PARAMETERS   *******/
  2131. X     char      *buf,            /* where to put the message          */
  2132. X          *filename;        /* file being operated on          */
  2133. X     int      *prefix_len,        /* length of message prefix string    */
  2134. X          status;        /* status code to check              */
  2135. X     u_char      action,        /* what is happening              */
  2136. X          type;            /* type of file being acted upon      */
  2137. X
  2138. X{    /*** make_xmess ***/
  2139. X                    /********   LOCAL  VARIABLES   ********/
  2140. X     char      *msg_ptr,        /* pointer to action type message     */
  2141. X          *error_ptr,        /* pointer to errno message          */
  2142. X          *result_ptr;        /* pointer to result message          */
  2143. X     int      msg_len;        /* length of action message part      */
  2144. static     char      delete_msg[] = {"Delete "},
  2145. X          copy_msg[] = {"Copy "},
  2146. X          rename_msg[] = {"Rename "},
  2147. X          protect_msg[] = {"Protect "},
  2148. X          text_msg[] = {"Text "},
  2149. X          owner_msg[] = {"Change owner "},
  2150. X          group_msg[] = {"Change group "},
  2151. X          ok_msg[] = {"? [OK]"},
  2152. X          error_msg[] = {"? *ERROR*"},
  2153. X          null_msg[] = {""};
  2154. X
  2155. X
  2156. X   error_ptr = null_msg;        /* Suns don't like NULL too well....  */
  2157. X
  2158. X   switch(action)            /* what are we doing?              */
  2159. X   {
  2160. X      case(DELETE):
  2161. X     msg_ptr = delete_msg;
  2162. X     msg_len = sizeof(delete_msg);
  2163. X     break;
  2164. X      case(COPY):
  2165. X     msg_ptr = copy_msg;
  2166. X     msg_len = sizeof(copy_msg);
  2167. X     break;
  2168. X      case(RENAME):
  2169. X     msg_ptr = rename_msg;
  2170. X     msg_len = sizeof(rename_msg);
  2171. X     break;
  2172. X      case(PROTECT):
  2173. X     msg_ptr = protect_msg;
  2174. X     msg_len = sizeof(protect_msg);
  2175. X     break;
  2176. X      case(GROUP):
  2177. X     msg_ptr = group_msg;
  2178. X     msg_len = sizeof(group_msg);
  2179. X     break;
  2180. X      case(OWNER):
  2181. X     msg_ptr = owner_msg;
  2182. X     msg_len = sizeof(owner_msg);
  2183. X     break;
  2184. X      case(TEXT):
  2185. X     msg_ptr = text_msg;
  2186. X     msg_len = sizeof(text_msg);
  2187. X     break;
  2188. X      default:
  2189. X     break;                /* should NEVER get here....          */
  2190. X   }
  2191. X
  2192. X   if(status == SUCCESS)
  2193. X   {
  2194. X      /* the action worked; creating the message will be easy here */
  2195. X
  2196. X      result_ptr = ok_msg;
  2197. X   }
  2198. X   else if(status == FAILURE)
  2199. X   {
  2200. X      result_ptr = error_msg;
  2201. X
  2202. X      /* make an explicit error message if possible */
  2203. X
  2204. X      error_ptr = make_err_msg(status,action,type);
  2205. X   }
  2206. X   else
  2207. X   {
  2208. X      result_ptr = error_msg;
  2209. X   }
  2210. X
  2211. X   /* construct the message */
  2212. X
  2213. X   sprintf(buf,"%s%s%s%s",msg_ptr,filename,result_ptr,error_ptr);
  2214. X   *prefix_len = msg_len;
  2215. X   return;
  2216. X
  2217. X}    /*** make_xmess ***/
  2218. X
  2219. X/*******************************************************************************
  2220. X********************************************************************************
  2221. X
  2222. X  Function:    write_text
  2223. X
  2224. X  Purpose:    Inverted coroutine (to xecute()) to write text descriptor
  2225. X        records to the text descriptor fioel.  A record of length
  2226. X        zero signifies that the entry is to be deleted.
  2227. X
  2228. X  Global variables:
  2229. X
  2230. X    Name            Examine/Modify/Use/Read/Write
  2231. X    ----            -----------------------------
  2232. X    none
  2233. X
  2234. X  Return Codes:
  2235. X
  2236. X    Code            Reason
  2237. X    ----            ------
  2238. X    SUCCESS
  2239. X    FAILURE
  2240. X
  2241. X********************************************************************************
  2242. X*******************************************************************************/
  2243. X
  2244. static int write_text(filename,text,dir_text,eof_flag)
  2245. X                    /*******   FORMAL  PARAMETERS   *******/
  2246. X     char      *filename,        /* filename that has a text descrip   */
  2247. X          *text,        /* text descriptor              */
  2248. X          *dir_text;        /* directory text descriptor          */
  2249. X     u_char      eof_flag;        /* set if we're done              */
  2250. X
  2251. X{    /*** write_text ***/
  2252. X                    /********   LOCAL  VARIABLES   ********/
  2253. static     FILE      *fptr;        /* pointer to text descriptor file    */
  2254. static     u_char      state,        /* state variable              */
  2255. X          file_open;        /* set if file has been opened          */
  2256. X
  2257. X
  2258. X   /* special case where an attempt is made to close the file when nothing
  2259. X    * had been written to it
  2260. X    */
  2261. X
  2262. X   if(eof_flag == TRUE && !file_open)
  2263. X   {
  2264. X      state = 0;
  2265. X      return(SUCCESS);
  2266. X   }
  2267. X
  2268. X   if(state == 1)
  2269. X      goto lab0;
  2270. X
  2271. X   fptr = fopen(TEXT_FILE,"w");
  2272. X
  2273. X   if(fptr == NULL)
  2274. X      return(FALSE);
  2275. X
  2276. X   /* write the directory text descriptor record */
  2277. X
  2278. X   fprintf(fptr,">>>%s\n",dir_text);
  2279. X   fputs(">\n",fptr);
  2280. X
  2281. X   state = 1;
  2282. X   file_open = 1;
  2283. X
  2284. X   while(eof_flag == FALSE)
  2285. X   {
  2286. X      if(text != NULL)            /* NULL descriptor means delete it    */
  2287. X         fprintf(fptr,"%s %s\n",filename,text);
  2288. X
  2289. X      return(SUCCESS);            /* coroutine "read"              */
  2290. X
  2291. lab0: ;                    /* this is where we return          */
  2292. X   }
  2293. X
  2294. X   state = 0;
  2295. X   file_open = 0;
  2296. X   fclose(fptr);
  2297. X
  2298. X   return(SUCCESS);
  2299. X
  2300. X}    /*** write_text ***/
  2301. X
  2302. X/*******************************************************************************
  2303. X********************************************************************************
  2304. X
  2305. X  Function:    make_err_msg
  2306. X
  2307. X  Purpose:    Try to make an intelligent error message based on an action
  2308. X        and the value of errno.
  2309. X
  2310. X  Global variables:
  2311. X
  2312. X    Name            Examine/Modify/Use/Read/Write
  2313. X    ----            -----------------------------
  2314. X    errno               X
  2315. X
  2316. X  Return Codes:
  2317. X
  2318. X    Code            Reason
  2319. X    ----            ------
  2320. X    retptr            pointer to message
  2321. X
  2322. X********************************************************************************
  2323. X*******************************************************************************/
  2324. X
  2325. static char *make_err_msg(status,action,type)
  2326. X                    /*******   FORMAL  PARAMETERS   *******/
  2327. X     int      status;        /* status from attempted operation    */
  2328. X     u_char      action,        /* what command is being done          */
  2329. X          type;            /* type of file being acted upon      */
  2330. X
  2331. X{    /*** make_err_msg ***/
  2332. X                    /********   LOCAL  VARIABLES   ********/
  2333. X     char      *retptr = NULL;    /* message to return              */
  2334. X
  2335. X
  2336. X   /* first see if the status can be used to create an intelligent message */
  2337. X
  2338. X   if(status != FAILURE && status != SUCCESS)
  2339. X   {
  2340. X      /* yep, use it */
  2341. X
  2342. X      switch(status)
  2343. X      {
  2344. X     case(CANT_STAT):
  2345. X     case(CANT_OPEN):
  2346. X        retptr = " Cannot open source file";
  2347. X        break;
  2348. X     case(CANT_OPEN_DEST):
  2349. X        retptr = " Cannot open destination file";
  2350. X        break;
  2351. X     case(CANT_WRITE):
  2352. X        retptr = " Write to destination file failed";
  2353. X        break;
  2354. X     case(CANT_CHMOD):
  2355. X        retptr = " Cannot set protection mode on destination file";
  2356. X        break;
  2357. X     default:
  2358. X        break;
  2359. X      }
  2360. X
  2361. X      return(retptr);
  2362. X   }
  2363. X
  2364. X   /* nope, the status was no good to use; check the action and errno */
  2365. X
  2366. X   switch(action)
  2367. X   {
  2368. X      case(RENAME):
  2369. X
  2370. X     switch(errno)
  2371. X     {
  2372. X        case(ENOENT):
  2373. X           retptr = " Invalid destination specificiation";
  2374. X           break;
  2375. X        case(EACCES):
  2376. X           retptr = " Cannot open destination file";
  2377. X           break;
  2378. X        case(EPERM):
  2379. X           retptr = " Destination file exists";
  2380. X           break;
  2381. X        case(EXDEV):
  2382. X           retptr = " Destination file is on a different device";
  2383. X           break;
  2384. X          case(EROFS):
  2385. X           retptr = " Destination directory is in a read-only filesystem";
  2386. X           break;
  2387. X#if !defined(SYSV) || defined(sun)
  2388. X        case(ELOOP):
  2389. X           retptr = " Too many symbolic links in filename";
  2390. X           break;
  2391. X        case(EDQUOT):
  2392. X           retptr = " Disk quota exhausted";
  2393. X           break;
  2394. X#endif
  2395. X        case(ENOSPC):
  2396. X           retptr = " File system is full";
  2397. X           break;
  2398. X        default:
  2399. X           break; 
  2400. X     }
  2401. X
  2402. X     break;
  2403. X
  2404. X      case(COPY):
  2405. X
  2406. X     switch(errno)
  2407. X     {
  2408. X        case(EACCES):
  2409. X           retptr = " Cannot open destination file";
  2410. X           break;
  2411. X        case(EIO):
  2412. X           retptr = " I/O error";
  2413. X           break;
  2414. X#if !defined(SYSV) || defined(sun)
  2415. X        case(ELOOP):
  2416. X           retptr = " Too many symbolic links in filename";
  2417. X           break;
  2418. X        case(EDQUOT):
  2419. X           retptr = " Disk quota exhausted";
  2420. X           break;
  2421. X#endif
  2422. X        case(ENOENT):
  2423. X           retptr = " Invalid destination specificiation";
  2424. X           break;
  2425. X        case(ENOSPC):
  2426. X           retptr = " File system is full";
  2427. X           break;
  2428. X        default:
  2429. X           break;
  2430. X     }
  2431. X
  2432. X     break;
  2433. X
  2434. X      case(PROTECT):
  2435. X
  2436. X     switch(errno)
  2437. X     {
  2438. X        case(EACCES):
  2439. X           retptr = " Protection violation";
  2440. X           break;
  2441. X        case(EIO):
  2442. X           retptr = " I/O error";
  2443. X           break;
  2444. X        case(ENOENT):
  2445. X           retptr = " File does not exist";
  2446. X           break;
  2447. X        case(EPERM):
  2448. X           retptr = " Not owner of file";
  2449. X           break;
  2450. X        case(EROFS):
  2451. X           retptr = " File resides in a read-only filesystem";
  2452. X           break;
  2453. X        default:
  2454. X           break;
  2455. X     }
  2456. X
  2457. X     break;
  2458. X
  2459. X      case(DELETE):
  2460. X
  2461. X     if(type != DIRECTORY)
  2462. X     {
  2463. X        switch(errno)
  2464. X        {
  2465. X           case(ENOENT):
  2466. X          retptr = " File does not exist";
  2467. X          break;
  2468. X           case(EACCES):
  2469. X          retptr = " Protection violation";
  2470. X          break;
  2471. X           case(EPERM):
  2472. X          retptr = " Permission denied (mount point or not owner)";
  2473. X          break;
  2474. X           case(EIO):
  2475. X          retptr = " I/O error";
  2476. X          break;
  2477. X           default:
  2478. X          break;
  2479. X        }
  2480. X     }
  2481. X     else
  2482. X     {
  2483. X        /* trying to delete a directory with rmdir */
  2484. X
  2485. X        switch(errno)
  2486. X        {
  2487. X#if !defined(SYSV) || defined(sun)
  2488. X           case(ENOTEMPTY):
  2489. X          retptr = " Directory is not empty";
  2490. X          break;
  2491. X#endif
  2492. X           case(EPERM):
  2493. X          retptr = " Not owner";
  2494. X          break;
  2495. X           case(EBUSY):
  2496. X          retptr = " Mount point for a mounted file system";
  2497. X          break;
  2498. X           case(EIO):
  2499. X          retptr = " I/O error";
  2500. X          break;
  2501. X           default:
  2502. X          break;
  2503. X        }
  2504. X     }
  2505. X
  2506. X     break;
  2507. X
  2508. X      case(OWNER):
  2509. X      case(GROUP):
  2510. X
  2511. X     switch(errno)
  2512. X     {
  2513. X        case(ENOENT):
  2514. X           retptr = " File does not exist";
  2515. X           break;
  2516. X        case(EPERM):
  2517. X           retptr = " Must be superuser";
  2518. X           break;
  2519. X        case(EROFS):
  2520. X           retptr = " File resides in a read-only filesystem";
  2521. X           break;
  2522. X        default:
  2523. X           break;
  2524. X     }
  2525. X
  2526. X     break;
  2527. X
  2528. X      default:
  2529. X
  2530. X     break;
  2531. X   }
  2532. X
  2533. X   return(retptr);
  2534. X
  2535. X}    /*** make_err_msg ***/
  2536. END_OF_FILE
  2537. if test 22377 -ne `wc -c <'xecute.c'`; then
  2538.     echo shar: \"'xecute.c'\" unpacked with wrong size!
  2539. fi
  2540. # end of 'xecute.c'
  2541. fi
  2542. echo shar: End of archive 3 \(of 7\).
  2543. cp /dev/null ark3isdone
  2544. MISSING=""
  2545. for I in 1 2 3 4 5 6 7 ; do
  2546.     if test ! -f ark${I}isdone ; then
  2547.     MISSING="${MISSING} ${I}"
  2548.     fi
  2549. done
  2550. if test "${MISSING}" = "" ; then
  2551.     echo You have unpacked all 7 archives.
  2552.     rm -f ark[1-9]isdone
  2553. else
  2554.     echo You still need to unpack the following archives:
  2555.     echo "        " ${MISSING}
  2556. fi
  2557. ##  End of shell archive.
  2558. exit 0
  2559.