home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / yapp / part03 / conf.c next >
C/C++ Source or Header  |  1994-05-29  |  21KB  |  660 lines

  1. /* CONF.C */
  2. static   char sccsid[] = "@(#)conf.c 1.2 94/01/20 (c)1993 thalerd";
  3. /* PHASE 1: Conference Subsystem 
  4.          Be able to enter/exit the program, and move between conferences
  5.          Commands: join, next, quit, source
  6.          Files: rc files, cflist, login, logout, bull
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <errno.h>
  15. #include <time.h>
  16. #include <pwd.h> /* for participants */
  17. #include "config.h"
  18. #include "struct.h"
  19. #include "globals.h"
  20. #include "conf.h"
  21. #include "lib.h"
  22. #include "joq.h"
  23. #include "sum.h"
  24. #include "item.h"
  25. #include "range.h"
  26. #include "macro.h"
  27. #include "system.h"
  28. #include "change.h"
  29. #include "sep.h"
  30. #include "xalloc.h"
  31. #include "driver.h"  /* for source */
  32. #include "stats.h"   /* for get_config */
  33.  
  34. /******************************************************************************/
  35. /* PROCESS COMMAND LINE ARGUMENTS                                             */
  36. /******************************************************************************
  37. Function:    join(char *conference, short idx, int force)
  38. Called by:   command, main
  39. Arguments:   cf name or conference # to join, force flag
  40. Returns:   
  41. Calls:       source() for CONF/rc and WORK/.cfrc files
  42.              cat() for login
  43.              get_idx to find cf name in conflist
  44. Description: 
  45. *******************************************************************************/
  46. #define O_JOIN 0x0002
  47. char                   /* RETURNS: 1 on success, 0 else       */
  48. join(conf, force)      /* ARGUMENTS:                          */
  49. char *conf;            /*    Conference name to join          */
  50. int   force;           /*    Force Observe/join flags         */
  51. {
  52.     char        buff[MAX_LINE_LENGTH];
  53.     struct stat st;
  54.     time_t      t1;
  55.     char      **config;
  56.  
  57.     /* Initialize st_new structure */
  58.     st_new.outp       = st_glob.outp;
  59.     st_new.inp        = st_glob.inp;
  60.     st_new.mailsize   = st_glob.mailsize;
  61.     st_new.listtime   = st_glob.listtime;
  62.     st_new.c_security = st_new.i_current = st_new.c_status = 0;
  63.     st_new.sumtime    = 0;
  64. #ifdef NEWS
  65.     st_new.c_article = 0;
  66. #endif
  67.     strcpy(st_new.fullname, st_glob.fullname);
  68.  
  69.     /* Check for existence */
  70.     if (!conf) return 0; 
  71.     joinidx=get_idx(conf,conflist,maxconf);
  72.     if (joinidx<0) { 
  73.        printf("Cannot access conference %s.\n",conf);
  74.        return 0; 
  75.     } 
  76.     if(flags & O_DEBUG) printf("join: %hd dir=%s\n",joinidx,conflist[joinidx].location);
  77.  
  78.     /* Read in config file */
  79.     if (!(config=get_config(joinidx)))
  80.        return 0; 
  81.  
  82.     /* Pass security checks */
  83.     if (xsizeof(config)>CF_SECURITY) 
  84.        st_new.c_security=atoi(config[CF_SECURITY]);
  85. #ifdef NEWS
  86.     if (xsizeof(config)<=CF_NEWSGROUP)
  87.        st_new.c_security &= ~CT_NEWS;
  88. #endif
  89.     if (!checkpoint(joinidx,st_new.c_security)) {
  90.        if (st_new.c_security & CT_READONLY) 
  91.           force |= O_READONLY;
  92.        else {
  93.           return 0;
  94.        }
  95.     }
  96.  
  97.     /* Do stuff with WORK/.name.cf */
  98.     sprintf(buff,"%s/%s",work,config[CF_PARTFILE]);
  99.     if (flags & O_DEBUG) printf("join: Partfile=%s\n",buff);
  100.     if (stat(buff,&st)) { /* Not a member */
  101.        if (!((flags|force) & O_OBSERVE)) {
  102.  
  103.           /* Main JOQ cmd loop */
  104.           mode = M_JOQ;
  105.           if ((force & O_JOIN) || (status & S_MOTIF)) {
  106.              sprintf(buff,"You are being automatically registered in %s\n",
  107.               conflist[joinidx].location);
  108.              wputs(buff);
  109.              command("join",0);
  110.           } else {
  111.              printf("You are not a member of %s\nDo you wish to:",
  112.               conflist[joinidx].location);
  113.              while (mode==M_JOQ && get_command(NULL));
  114.           }
  115.  
  116.           if (status & S_QUIT) {
  117.              printf("registration aborted (didn't leave)\n");
  118.              status &= ~S_QUIT;
  119.              return 0;
  120.           }
  121.        }
  122.        t1 = (time_t)0;
  123.     } else {
  124.        t1 = st.st_mtime; /* last time .*.cf was touched */
  125.     }
  126.     if (flags & O_DEBUG) printf("join: t1=%x\n",t1);
  127.  
  128.     if (confidx>=0) leave(0,(char**)0);
  129.  
  130.     memcpy(&st_glob,&st_new,sizeof(st_new));
  131.  
  132.     confidx =joinidx; /* passed all security checks */
  133.     if (xsizeof(config)>CF_FWLIST)
  134.        fw = explode(config[CF_FWLIST],",");
  135.     else
  136.        fw = 0;
  137.     read_part(config[CF_PARTFILE],part,&st_glob,confidx);
  138.  
  139.     /* Set status */
  140.     if ((flags|force) & O_OBSERVE)
  141.        st_glob.c_status |=  CS_OBSERVER;
  142.     if ((flags|force) & O_READONLY)
  143.        st_glob.c_status |=  CS_NORESPONSE;
  144.  
  145.     /* Allow FW to be specified by login or by UID */
  146.     sprintf(buff,"%d",uid);
  147.     if (searcha(login,fw,0)>=0 || searcha(buff,fw,0)>=0 || uid==geteuid()) 
  148.        st_glob.c_status |=  CS_FW;
  149.     if (flags & O_DEBUG) printf("join: Status=%hd\n",(short)status);
  150.  
  151.     st_glob.sumtime = 0;
  152.     refresh_sum(0,confidx,sum,part,&st_glob);
  153.  
  154.     /* Source CONF/rc file and WORK/.cfrc files */
  155.     if (flags & O_SOURCE) {
  156.        mode = M_SANE;
  157.        source(conflist[confidx].location,"rc");
  158. /*     mode = M_OK;
  159.        source(work,".cfrc");
  160.  */
  161.     }
  162.  
  163.     /* Display login file */
  164.     sepinit(IS_START|IS_ITEM);
  165. /*printf("PARTTIME=%d\n",st_glob.parttime);*/
  166.     confsep("linmsg",confidx,&st_glob,part,0);
  167.     check_mail(1);
  168.  
  169.     /* Source WORK/.cfrc files */
  170.     if (flags & O_SOURCE) {
  171.        mode = M_OK;
  172.        source(work,".cfrc");
  173.     }
  174.     return 1;
  175. }
  176.  
  177. /******************************************************************************/
  178. /* FIND INDEX OF NAME IN AN ASSOCIATIVE LIST                                  */
  179. /******************************************************************************/
  180. short                  /* RETURNS: -1 on error, else index of elt in list */
  181. get_idx(elt,list,size) /* ARGUMENTS:                                      */
  182. char    *elt;          /*    String to match                              */
  183. assoc_t *list;         /*    List of elements to search                   */
  184. short    size;         /*    Number of elements in the list               */
  185. {
  186.    short i;
  187.  
  188.    for (i=1; i<size && !match(elt,list[i].name); i++);
  189.    return (i<size)? i : -1;
  190. }
  191.  
  192. /******************************************************************************/
  193. /* PROCESS COMMAND LINE ARGUMENTS                                             */
  194. /******************************************************************************
  195. Function:    leave
  196. Called by:   command
  197. Arguments:   
  198. Returns:   
  199. Calls:       cat() for logout
  200. Description: 
  201. *******************************************************************************/
  202. int                         /* RETURNS: error flag                 */
  203. leave(argc,argv)            /* ARGUMENTS: (none)                   */
  204. int argc;
  205. char **argv;
  206. {
  207.    char **config;
  208.    if (flags & O_DEBUG) printf("leave: %hd\n",confidx);
  209.    if (confidx<0) return 1; /* (noconf) */
  210.  
  211.    if (!argc || argv[0][0]!='a') { /* not "abort" */
  212.  
  213.       /* Display logout */
  214.       /* more(conflist[confidx].location,"logout"); */
  215.       sepinit(IS_START|IS_ITEM);
  216.       confsep("loutmsg",confidx,&st_glob,part,0);
  217.  
  218.       /* Write participation file unless observing */
  219.       if (!(st_glob.c_status & CS_OBSERVER)) {
  220.          if (!(config = get_config(confidx)))
  221.             return 1;
  222.          write_part(config[CF_PARTFILE]);
  223.       }
  224.    }
  225.  
  226.    /* Free config info */
  227.    xfree(fw);
  228.  
  229.    st_glob.sumtime = 0;
  230.    st_glob.c_status = 0; /* |= CS_OTHERCONF; */
  231.  
  232.    confidx = -1;
  233.    undefine(DM_SANE);
  234.  
  235.    /* Re-source system rc file */
  236.    mode = M_SUPERSANE;
  237.    source(bbsdir,"rc");
  238.    mode = M_OK;
  239.  
  240.    return (!argc || argv[0][0]!='a');
  241. }
  242.  
  243. /******************************************************************************/
  244. /* CHECK A LIST OF CONFERENCES FOR NEW ITEMS                                  */
  245. /******************************************************************************/
  246. int              /* RETURNS: (nothing)     */
  247. check(argc,argv) /* ARGUMENTS:             */
  248. int    argc;     /*    Number of arguments */
  249. char **argv;     /*    Argument list       */
  250. {
  251.    int i;
  252.    char **list,*cfname,sec,buff[MAX_LINE_LENGTH],**fw;
  253.    short size,idx,all=0,count=0,argidx=1;
  254.    partentry_t part2[MAX_ITEMS],*part3;
  255.    sumentry_t  sum2[MAX_ITEMS];
  256.    status_t   *st,st_temp;
  257.    struct stat stt;
  258.    char      **config;
  259.    long        force;
  260.  
  261.    /* Check for before/since dates */
  262.    st_glob.since = st_glob.before = 0;
  263.    if (argc>argidx) {
  264.       if (match(argv[argidx],"si_nce") 
  265.        || match(argv[argidx],"S=")) {
  266.          st_glob.since  = since(argc,argv,&argidx);
  267.          argidx++;
  268.       } else if (match(argv[argidx],"before") 
  269.        ||        match(argv[argidx],"B=")) {
  270.          st_glob.before = since(argc,argv,&argidx);
  271.          argidx++;
  272.       }
  273.    }
  274.  
  275.    if (argc>argidx) {            /* list given by user */
  276.       size = argc-argidx;
  277.       list = argv+argidx;
  278.    } else if (argv[0][0]=='l') { /* use conflist */
  279.       all  = 1;
  280.       size = maxconf-1;
  281.    } else {                      /* use .cflist */
  282.       refresh_list();
  283.       size = xsizeof(cflist);
  284.       list = cflist;
  285.    }
  286.  
  287.    sepinit(IS_START);
  288.    for (i=0; i<size && !(status & S_INT); i++) {
  289.       force = 0;
  290.       idx=(all)? i+1 : get_idx(list[i],conflist,maxconf);
  291.       cfname = (all)? compress(conflist[idx].name) : list[i];
  292.       if (idx<0 || !(config=get_config(idx))) {
  293.          printf("Cannot access conference %s.\n",cfname);
  294.          continue;
  295.       } 
  296.  
  297.       /* Pass security checks */
  298.       sec=(xsizeof(config)>CF_SECURITY)? atoi(config[CF_SECURITY]) : 0;
  299. #ifdef NEWS
  300.       if (xsizeof(config)<=CF_NEWSGROUP)
  301.          sec &= ~CT_NEWS;
  302. #endif
  303.       if (!checkpoint(idx,sec)) {
  304.          if (sec & CT_READONLY) {
  305.             force |= O_READONLY;
  306.          } else {
  307.             continue;
  308.          }
  309.       }
  310.  
  311. /*    if (idx==confidx)  */
  312.       if (!strcmp(conflist[idx].location,conflist[confidx].location)) {
  313.          refresh_sum(0,confidx,sum,part,&st_glob);
  314.          st = &st_glob;
  315.          part3=part;
  316.       } else {
  317.          st = &st_temp;
  318. #ifdef NEWS
  319.          st->c_article = 0;
  320. #endif
  321.          read_part(config[CF_PARTFILE],part2,st,idx); /* Read in partfile */
  322.  
  323.          /* Initialize c_status */
  324.          st->c_status = 0;
  325.          sprintf(buff,"%d",uid);
  326.          if (xsizeof(config)>CF_FWLIST)
  327.             fw = explode(config[CF_FWLIST],",");
  328.          else
  329.             fw = 0;
  330.          if (searcha(login,fw,0)>=0 || searcha(buff,fw,0)>=0 || uid==geteuid()) 
  331.             st->c_status |=  CS_FW;
  332.          else
  333.             st->c_status &= ~CS_FW;
  334.          xfree(fw);
  335.          if ((flags|force) & O_OBSERVE)
  336.             st->c_status |=  CS_OBSERVER;
  337.          else
  338.             st->c_status &= ~CS_OBSERVER;
  339.          if ((flags|force) & O_READONLY)
  340.             st->c_status |=  CS_NORESPONSE;
  341.          else
  342.             st->c_status &= ~CS_NORESPONSE;
  343.  
  344.          sprintf(buff,"%s/%s",work,config[CF_PARTFILE]);
  345.          st->parttime   = (stat(buff,&stt))? 0 : stt.st_mtime;
  346.          st->c_security = (xsizeof(config)>CF_SECURITY)? 
  347.           atoi(config[CF_SECURITY]) : 0;
  348.  
  349.          /* Read in sumfile */
  350.          get_status(st,sum2,part2,idx); 
  351.          part3=part2;
  352.       }
  353.       st->c_security = sec;
  354.  
  355.       if ((!st_glob.before || st->sumtime < st_glob.before)
  356.        &&  (st_glob.since <= st->sumtime)) {
  357.          st->count = (++count);
  358.          sepinit(IS_ITEM);
  359.          if (argc<2 && current==i) sepinit(IS_CFIDX);
  360.          confsep((argv[0][0]=='l')?"listmsg":"checkmsg",idx,st,part3,0);
  361.       }
  362.    }
  363.    return 1;
  364. }
  365.  
  366. /******************************************************************************/
  367. /* ADVANCE TO NEXT CONFERENCES WITH NEW ITEMS                                 */
  368. /******************************************************************************/
  369. int                                   /* RETURNS: (nothing)     */
  370. do_next(argc,argv)                    /* ARGUMENTS:             */
  371. int    argc;                          /*    Number of arguments */
  372. char **argv;                          /*    Argument list       */
  373. {                                     /* LOCAL VARIABLES:       */
  374.    char      **config,
  375.                buff[MAX_LINE_LENGTH];
  376.    char        sec;                   /*    Conference's security type     */
  377.    short       idx;
  378.    partentry_t part2[MAX_ITEMS];
  379.    sumentry_t  sum2[MAX_ITEMS];
  380.    status_t    st;
  381.    struct stat stt;
  382.  
  383.    if (argc>1) {
  384.       printf("Bad parameters near \"%s\"\n",argv[1]);
  385.       return 2;
  386.    }
  387.  
  388.    refresh_list(); /* make sure .cflist is current */
  389.    for (; current+1 < xsizeof(cflist) && !(status & S_INT); current++) {
  390.       idx=get_idx(cflist[current+1],conflist,maxconf);
  391.       if (idx<0 || !(config=get_config(idx))) {
  392.          printf("Cannot access conference %s.\n",cflist[current+1]);
  393.          continue;
  394.       } 
  395.  
  396.       /* Check security */
  397.       sec=(xsizeof(config)>CF_SECURITY)? atoi(config[CF_SECURITY]) : 0;
  398. #ifdef NEWS
  399.       if (xsizeof(config)<=CF_NEWSGROUP)
  400.          sec &= ~CT_NEWS;
  401. #endif
  402.       if (!(sec & CT_READONLY) && !checkpoint(idx,sec))
  403.          continue;
  404.  
  405. /*    if (idx==confidx)  */
  406.       if (!strcmp(conflist[idx].location,conflist[confidx].location)) {
  407.          refresh_sum(0,confidx,sum,part,&st_glob);
  408.          if (st_glob.i_newresp || st_glob.i_brandnew) {
  409.             join(cflist[++current],0);
  410.             return 1;
  411.          }
  412.       } else {
  413.          read_part(config[CF_PARTFILE],part2,&st,idx); /* Read in partfile */
  414.          sprintf(buff,"%s/%s",work,config[CF_PARTFILE]);
  415.          st.parttime   = (stat(buff,&stt))? 0 : stt.st_mtime;
  416.          st.c_security = (xsizeof(config)>CF_SECURITY)? 
  417.           atoi(config[CF_SECURITY]) : 0;
  418. #ifdef NEWS
  419.          st.c_article = 0;
  420. #endif
  421.          get_status(&st,sum2,part2,idx);  /* Read in sumfile */
  422.          st.sumtime = 0;
  423.          if (st.i_newresp || st.i_brandnew) {
  424.             join(cflist[++current],0);
  425.             return 1;
  426.          }
  427.       }
  428.       printf("No new items in %s\n",cflist[current+1]);
  429.    }
  430.    printf("No more conferences left.\n");
  431.    return 2;
  432. }
  433.  
  434. /******************************************************************************/
  435. /* RESIGN FROM (UNJOIN) THE CURRENT CONFERENCE                                */
  436. /******************************************************************************/
  437. int              /* RETURNS: (nothing)     */
  438. resign(argc,argv) /* ARGUMENTS:             */
  439. int    argc;      /*    Number of arguments */
  440. char **argv;      /*    Argument list       */
  441. {
  442.    char    buff[MAX_LINE_LENGTH];
  443.    char **config;
  444.  
  445.    if (argc>1) {
  446.       printf("Bad parameters near \"%s\"\n",argv[1]);
  447.       return 2;
  448.    }
  449.    if (st_glob.c_status & CS_OBSERVER) {
  450.       printf("But you don't belong to this conference!\n");
  451.       return 1;
  452.    }
  453.    if (get_yes("Are you sure you wish to resign? ")) {
  454.       if (!(config = get_config(confidx)))
  455.          return 1;
  456.       sprintf(buff,"%s/%s",work,config[CF_PARTFILE]);
  457.       rm(buff,SL_USER);
  458.       st_glob.c_status |= CS_OBSERVER;
  459.       printf("You are now just an observer.\n");
  460.    } 
  461.    return 1;
  462. }
  463.  
  464. /******************************************************************************/
  465. /* DETERMINE IF USER IS ALLOWED TO JOIN A CONFERENCE                          */
  466. /******************************************************************************/
  467. char                /* RETURNS: 1 if passed, 0 if failed */
  468. checkpoint(idx,sec) /* ARGUMENTS:                        */
  469. short idx;          /*    Conference # to checkpoint     */
  470. char  sec;          /*    Conference's security type     */
  471. {
  472.    char **password,**ulst,osec;
  473.    char buff[MAX_LINE_LENGTH];
  474.     
  475.     /* Do Security checks */
  476.     osec = sec;
  477.     sec &= CT_BASIC;
  478.     if (sec==CT_PRESELECT || sec==CT_PARANOID) {
  479.        if (!(ulst=grab_file(conflist[idx].location,"ulist",GF_WORD|GF_IGNCMT))) 
  480.           return 0;
  481.        sprintf(buff,"%d",uid);
  482.        if (searcha(login,ulst,0)<0 && searcha(buff,ulst,0)<0) {
  483.           if (!(osec & CT_READONLY))
  484.              printf("Access failed for %s\n", compress(conflist[idx].name));
  485.           xfree(ulst);
  486.           return 0;
  487.        }
  488.     } else ulst=0;
  489.     if (sec==CT_PASSWORD || sec==CT_PARANOID) {
  490.        if (!(password=grab_file(conflist[idx].location,"secret",0))) {
  491.           xfree(ulst);
  492.           return 0;
  493.        }
  494.        if (xsizeof(password)>0) {
  495.           printf("Password for %s: ",compress(conflist[idx].name));
  496.           if (strcmp(get_password(),password[0])) {
  497.              printf("UNK: Invalid password.\n");
  498.              xfree(password);
  499.              xfree(ulst);
  500.              return 0;
  501.           }
  502.        }
  503.        xfree(password);
  504.     }
  505.     xfree(ulst);
  506.     return 1;
  507. }
  508.  
  509. /******************************************************************************/
  510. /* GET INFORMATION ON CONFERENCE PARTICIPANTS                                 */
  511. /******************************************************************************/
  512. int                     /* RETURNS: (nothing)     */
  513. participants(argc,argv) /* ARGUMENTS:             */
  514. int    argc;            /*    Number of arguments */
  515. char **argv;            /*    Argument list       */
  516. {
  517.    char         **ulst,**namestr,
  518.                 **config;
  519.    struct passwd *pwd;
  520.    struct stat    st;
  521.    short          j,all=0,dump=0;
  522.    time_t         tparttime;
  523.    uid_t          tuid;
  524.    char           tlogin[L_cuserid];
  525.    char           tfullname[MAX_LINE_LENGTH];
  526.    char           twork[MAX_LINE_LENGTH];
  527.    char           buff[MAX_LINE_LENGTH];
  528.    char           file[MAX_LINE_LENGTH],file2[MAX_LINE_LENGTH];
  529.  
  530.    /* Save user info */
  531.    tuid = uid;                 strcpy(tlogin,login); 
  532.    strcpy(tfullname,st_glob.fullname); strcpy(twork,work);
  533.    tparttime = st_glob.parttime;
  534.    st_glob.count = 0;
  535.  
  536.    if (argc>1) { /* User list specified */
  537.       ulst = xalloc(argc-1,sizeof(char *));
  538.       for (j=1; j<argc; j++)
  539.          ulst[j-1] = xstrdup(argv[j]);
  540.    } else {
  541.       sprintf(file,"%s/ulist",conflist[confidx].location);
  542.       if
  543. (!(ulst=grab_file(conflist[confidx].location,"ulist",GF_WORD|GF_SILENT|GF_IGNCMT))) {
  544.          all = 1;
  545.          setpwent();
  546.       } else if (!((st_glob.c_security & CT_BASIC)==CT_PRESELECT 
  547.        ||          (st_glob.c_security & CT_BASIC)==CT_PARANOID)) {
  548.          dump=1;
  549.          sprintf(file2,"%s/ulist.tmp",conflist[confidx].location,"ulist");
  550.       }
  551.    }
  552.  
  553.    open_pipe();
  554.  
  555.    /* Process items */
  556.    sepinit(IS_START);
  557.    confsep("partmsg",confidx,&st_glob,part,0);
  558.  
  559.    for (j=0; !(status & S_INT); j++) {
  560.       if (all) {
  561.          if (!(pwd = getpwent())) break;
  562.       } else { 
  563.          if (j>=xsizeof(ulst)) break;
  564.          if (isdigit(ulst[j][0]))
  565.             pwd = getpwuid((uid_t)atoi(ulst[j]));
  566.          else
  567.             pwd = getpwnam(ulst[j]);
  568.          if (!pwd) {
  569.             printf(" User %s not found\n",ulst[j]);
  570.             if (dump) {
  571.                xfree(ulst[j]);
  572.                ulst[j] = 0;
  573.                dump = 2;
  574.             }
  575.             continue;
  576.          }
  577.       }
  578.  
  579.       if (!(config = get_config(confidx)))
  580.          return 1;
  581.  
  582.       sprintf(work,"%s/.cfdir",pwd->pw_dir);
  583.       sprintf(buff,"%s/%s",work,config[CF_PARTFILE]);
  584.       if (stat(buff,&st)) {
  585.          strcpy(work,pwd->pw_dir);
  586.          sprintf(buff,"%s/%s",work, config[CF_PARTFILE]);
  587.          if (stat(buff,&st)) {
  588.             if (dump) { /* someone resigned or deleted a part file */
  589.                xfree(ulst[j]);
  590.                ulst[j] = 0;
  591.                dump = 2;
  592.             } 
  593.             fprintf(st_glob.outp,"User %s not a member\n",pwd->pw_name);
  594.             fflush(st_glob.outp);
  595.             continue;
  596.          }
  597.       }
  598.       uid = pwd->pw_uid;
  599.       strcpy(login, pwd->pw_name);
  600.       namestr=explode(pwd->pw_gecos,expand("gecos",DM_VAR));
  601.       strcpy(st_glob.fullname,namestr[0]);
  602.       xfree(namestr);
  603.       st_glob.parttime = st.st_mtime;
  604.       st_glob.count++;
  605.       sepinit(IS_ITEM);
  606.       confsep("partmsg",confidx,&st_glob,part,0);
  607.  
  608.       if (all) {
  609.          sprintf(buff,"%s\n",login);
  610.          write_file(file,buff);
  611.       }
  612.    }
  613.    sepinit(IS_CFIDX);
  614.    confsep("partmsg",confidx,&st_glob,part,0);
  615.  
  616.    if (dump==2) { /* reset ulist file */
  617.       for (j=0; j<xsizeof(ulst); j++) {
  618.          if (ulst[j]) {
  619.             sprintf(buff,"%s\n",ulst[j]);
  620.             if (!write_file(file2,buff)) {
  621.                dump=3; 
  622.                break;
  623.             }
  624.          }
  625.       }
  626.    }
  627.    if (dump==2)
  628.       if (rename(file2,file)) error("renaming ",file);
  629.  
  630.    if (all) endpwent();
  631.    else xfree(ulst);
  632.  
  633.    /* Restore user info */
  634.    uid = tuid;                 
  635.    strcpy(login,tlogin); 
  636.    strcpy(st_glob.fullname,tfullname); 
  637.    st_glob.parttime = tparttime;
  638.    strcpy(work,twork);
  639.  
  640.    return 1;
  641. }
  642.  
  643. void
  644. log(idx,str)
  645. short idx;
  646. char *str;
  647. {
  648.    char buff[MAX_LINE_LENGTH],
  649.         file[MAX_LINE_LENGTH],
  650.         timestamp[MAX_LINE_LENGTH];
  651.    time_t t;
  652.  
  653.    sprintf(file, "%s/log", conflist[idx].location);
  654.    time(&t);
  655.    strcpy(timestamp,ctime(&t)+4);
  656.    timestamp[20]='\0';
  657.    sprintf(buff,"%s %s %s\n", timestamp, login, str);
  658.    write_file(file, buff);
  659. }
  660.