1 /* needed to properly enable crypt() stuff on some systems */
3 /* needed for str[n]casecmp() on some systems if the above is defined */
4 #define _XOPEN_SOURCE_EXTENDED
12 #include <sys/types.h>
21 #include "sysdep_decls.h"
29 #include "dynloader.h"
33 * getuser() - retrieve named user into supplied buffer.
34 * returns 0 on success
36 int getuser(struct usersupp *usbuf, char name[]) {
38 char lowercase_name[32];
40 struct cdbdata *cdbus;
42 bzero(usbuf, sizeof(struct usersupp));
43 for (a=0; a<=strlen(name); ++a) {
44 lowercase_name[a] = tolower(name[a]);
47 cdbus = cdb_fetch(CDB_USERSUPP, lowercase_name, strlen(lowercase_name));
49 return(1); /* user not found */
52 memcpy(usbuf, cdbus->ptr,
53 ( (cdbus->len > sizeof(struct usersupp)) ?
54 sizeof(struct usersupp) : cdbus->len) );
61 * lgetuser() - same as getuser() but locks the record
63 int lgetuser(struct usersupp *usbuf, char *name)
67 retcode = getuser(usbuf,name);
69 begin_critical_section(S_USERSUPP);
76 * putuser() - write user buffer into the correct place on disk
78 void putuser(struct usersupp *usbuf, char *name)
80 char lowercase_name[32];
83 for (a=0; a<=strlen(name); ++a) {
84 lowercase_name[a] = tolower(name[a]);
87 cdb_store(CDB_USERSUPP,
88 lowercase_name, strlen(lowercase_name),
89 usbuf, sizeof(struct usersupp));
95 * lputuser() - same as putuser() but locks the record
97 void lputuser(struct usersupp *usbuf, char *name) {
99 end_critical_section(S_USERSUPP);
104 * Define a relationship between a user and a room
106 void CtdlSetRelationship(struct visit *newvisit,
107 struct usersupp *rel_user,
108 struct quickroom *rel_room) {
110 struct cdbdata *cdbvisit;
111 struct visit *visits;
116 cdbvisit = cdb_fetch(CDB_VISIT, &rel_user->usernum, sizeof(long));
117 if (cdbvisit != NULL) {
118 num_visits = cdbvisit->len / sizeof(struct visit);
119 visits = (struct visit *)
120 malloc(num_visits * sizeof(struct visit));
121 memcpy(visits, cdbvisit->ptr,
122 (num_visits * sizeof(struct visit)));
130 /* Replace an existing relationship if possible */
131 if (num_visits > 0) for (a=0; a<num_visits; ++a) {
132 if ( (!strcasecmp(visits[a].v_roomname, rel_room->QRname))
133 && (visits[a].v_generation == rel_room->QRgen) ) {
134 memcpy(&visits[a], newvisit, sizeof(struct visit));
139 /* Otherwise, define a new one */
142 visits = realloc(visits,
143 (num_visits * sizeof(struct visit)));
144 memcpy(&visits[num_visits-1], newvisit, sizeof(struct visit));
147 /* Now write the relationship back to disk */
149 &rel_user->usernum, sizeof(long),
151 (num_visits * sizeof(struct visit)));
156 * Locate a relationship between a user and a room
158 void CtdlGetRelationship(struct visit *vbuf,
159 struct usersupp *rel_user,
160 struct quickroom *rel_room) {
162 struct cdbdata *cdbvisit;
163 struct visit *visits;
167 bzero(vbuf, sizeof(struct visit));
168 strcpy(vbuf->v_roomname, rel_room->QRname);
169 vbuf->v_generation = rel_room->QRgen;
171 cdbvisit = cdb_fetch(CDB_VISIT, &rel_user->usernum, sizeof(long));
172 if (cdbvisit != NULL) {
173 if ((num_visits = cdbvisit->len / sizeof(struct visit)) == 0) {
177 visits = (struct visit *)
178 malloc(num_visits * sizeof(struct visit));
179 memcpy(visits, cdbvisit->ptr,
180 (num_visits * sizeof(struct visit)));
185 for (a=0; a<num_visits; ++a) {
187 if ( (!strcasecmp(visits[a].v_roomname, rel_room->QRname))
188 && (visits[a].v_generation == rel_room->QRgen) ) {
189 memcpy(vbuf, &visits[a], sizeof(struct visit));
198 * Is the user currently logged in an Aide?
201 if (CC->usersupp.axlevel >= 6) return(1);
207 * Is the user currently logged in an Aide *or* the room aide for this room?
209 int is_room_aide(void) {
210 if ( (CC->usersupp.axlevel >= 6)
211 || (CC->quickroom.QRroomaide == CC->usersupp.usernum) ) {
220 * getuserbynumber() - get user by number
221 * returns 0 if user was found
223 int getuserbynumber(struct usersupp *usbuf, long int number)
225 struct cdbdata *cdbus;
227 cdb_rewind(CDB_USERSUPP);
229 while(cdbus = cdb_next_item(CDB_USERSUPP), cdbus != NULL) {
230 bzero(usbuf, sizeof(struct usersupp));
231 memcpy(usbuf, cdbus->ptr,
232 ( (cdbus->len > sizeof(struct usersupp)) ?
233 sizeof(struct usersupp) : cdbus->len) );
235 if (usbuf->usernum == number) {
246 void cmd_user(char *cmdbuf)
254 extract(username,cmdbuf,0);
258 if ((CC->logged_in)) {
259 cprintf("%d Already logged in.\n",ERROR);
263 found_user = getuser(&CC->usersupp,username);
264 if (found_user != 0) {
265 p = (struct passwd *)getpwnam(username);
267 strcpy(autoname,p->pw_gecos);
268 for (a=0; a<strlen(autoname); ++a)
269 if (autoname[a]==',') autoname[a]=0;
270 found_user = getuser(&CC->usersupp,autoname);
273 if (found_user == 0) {
274 if (((CC->nologin)) && (CC->usersupp.axlevel < 6)) {
275 cprintf("%d %s: Too many users are already online (maximum is %d)\n",
276 ERROR+MAX_SESSIONS_EXCEEDED,
277 config.c_nodename,config.c_maxsessions);
280 strcpy(CC->curr_user,CC->usersupp.fullname);
281 cprintf("%d Password required for %s\n",
282 MORE_DATA,CC->curr_user);
286 cprintf("%d %s not found.\n",ERROR,username);
293 * session startup code which is common to both cmd_pass() and cmd_newu()
295 void session_startup(void) {
299 syslog(LOG_NOTICE,"user <%s> logged in",CC->curr_user);
301 lgetuser(&CC->usersupp,CC->curr_user);
302 ++(CC->usersupp.timescalled);
303 CC->fake_username[0] = '\0';
304 CC->fake_postname[0] = '\0';
305 CC->fake_hostname[0] = '\0';
306 CC->fake_roomname[0] = '\0';
307 CC->last_pager[0] = '\0';
308 time(&CC->usersupp.lastcall);
310 /* If this user's name is the name of the system administrator
311 * (as specified in setup), automatically assign access level 6.
313 if (!strcasecmp(CC->usersupp.fullname, config.c_sysadm)) {
314 CC->usersupp.axlevel = 6;
317 /******************************************************************************/
318 /* FIX It is safe to remove this segment during the cutover */
319 for (a=0; a<MAXROOMS; ++a) {
321 if (CC->usersupp.generation[a] != qr.QRgen)
322 CC->usersupp.generation[a]=(-1);
323 if (CC->usersupp.forget[a] != qr.QRgen)
324 CC->usersupp.forget[a]=(-1);
326 /******************************************************************************/
328 lputuser(&CC->usersupp,CC->curr_user);
330 /* Run any cleanup routines registered by loadable modules */
331 PerformSessionHooks(EVT_LOGIN);
333 cprintf("%d %s|%d|%d|%d|%u|%ld\n",OK,CC->usersupp.fullname,CC->usersupp.axlevel,
334 CC->usersupp.timescalled,CC->usersupp.posted,CC->usersupp.flags,
335 CC->usersupp.usernum);
336 usergoto(0,0); /* Enter the lobby */
337 rec_log(CL_LOGIN,CC->curr_user);
342 * misc things to be taken care of when a user is logged out
344 void logout(struct CitContext *who)
347 if (who->download_fp != NULL) {
348 fclose(who->download_fp);
349 who->download_fp = NULL;
351 if (who->upload_fp != NULL) {
355 /* Do modular stuff... */
356 PerformSessionHooks(EVT_LOGOUT);
360 void cmd_pass(char *buf)
366 extract(password,buf,0);
368 if ((CC->logged_in)) {
369 cprintf("%d Already logged in.\n",ERROR);
372 if (!strcmp(CC->curr_user,"")) {
373 cprintf("%d You must send a name with USER first.\n",ERROR);
376 if (getuser(&CC->usersupp,CC->curr_user)) {
377 cprintf("%d Can't find user record!\n",ERROR+INTERNAL_ERROR);
382 if (CC->usersupp.USuid == BBSUID) {
384 strproc(CC->usersupp.password);
385 code = strcasecmp(CC->usersupp.password,password);
388 p = (struct passwd *)getpwuid(CC->usersupp.USuid);
389 #ifdef ENABLE_AUTOLOGIN
391 if (!strcmp(p->pw_passwd,
392 (char *)crypt(password,p->pw_passwd))) {
394 lgetuser(&CC->usersupp, CC->curr_user);
395 strcpy(CC->usersupp.password, password);
396 lputuser(&CC->usersupp, CC->curr_user);
407 cprintf("%d Wrong password.\n",ERROR);
408 rec_log(CL_BADPW,CC->curr_user);
414 * Delete a user record *and* all of its related resources.
416 int purge_user(char *pname) {
418 struct usersupp usbuf;
420 struct cdbdata *cdbmb;
424 if (getuser(&usbuf, pname) != 0) {
425 lprintf(5, "Cannot purge user <%s> - not found\n", pname);
426 return(ERROR+NO_SUCH_USER);
429 /* FIX Don't delete a user who is currently logged in. */
431 /* Perform any purge functions registered by server extensions */
432 PerformUserHooks(usbuf.fullname, usbuf.usernum, EVT_PURGEUSER);
434 /* delete any messages in the user's mailbox */
435 cdbmb = cdb_fetch(CDB_MAILBOXES, &usbuf.usernum, sizeof(long));
437 num_mails = cdbmb->len / sizeof(long);
438 mailbox = (long *) cdbmb->ptr;
439 if (num_mails > 0) for (a=0; a<num_mails; ++a) {
440 cdb_delete(CDB_MSGMAIN, &mailbox[a], sizeof(long));
443 /* now delete the mailbox itself */
444 cdb_delete(CDB_MAILBOXES, &usbuf.usernum, sizeof(long));
447 /* delete any existing user/room relationships */
448 cdb_delete(CDB_VISIT, &usbuf.usernum, sizeof(long));
450 /* delete the userlog entry */
451 cdb_delete(CDB_USERSUPP, pname, strlen(pname));
453 /* remove the user's bio file */
454 sprintf(filename, "./bio/%ld", usbuf.usernum);
457 /* remove the user's picture */
458 sprintf(filename, "./userpics/%ld.gif", usbuf.usernum);
466 * create_user() - back end processing to create a new user
468 int create_user(char *newusername)
470 struct usersupp usbuf;
472 struct passwd *p = NULL;
475 strcpy(username, newusername);
478 #ifdef ENABLE_AUTOLOGIN
479 p = (struct passwd *)getpwnam(username);
482 strcpy(username, p->pw_gecos);
483 for (a=0; a<strlen(username); ++a) {
484 if (username[a] == ',') username[a] = 0;
486 CC->usersupp.USuid = p->pw_uid;
489 CC->usersupp.USuid = BBSUID;
492 if (!getuser(&usbuf,username)) {
493 return(ERROR+ALREADY_EXISTS);
496 strcpy(CC->curr_user,username);
497 strcpy(CC->usersupp.fullname,username);
498 strcpy(CC->usersupp.password,"");
501 /********************************************************/
502 /* FIX this can safely be removed during the cutover... */
503 for (a=0; a<MAXROOMS; ++a) {
504 CC->usersupp.lastseen[a]=0L;
505 CC->usersupp.generation[a]=(-1);
506 CC->usersupp.forget[a]=(-1);
508 /********************************************************/
510 /* These are the default flags on new accounts */
512 US_NEEDVALID|US_LASTOLD|US_DISAPPEAR|US_PAGINATOR|US_FLOORS;
514 CC->usersupp.timescalled = 0;
515 CC->usersupp.posted = 0;
516 CC->usersupp.axlevel = config.c_initax;
517 CC->usersupp.USscreenwidth = 80;
518 CC->usersupp.USscreenheight = 24;
519 time(&CC->usersupp.lastcall);
520 strcpy(CC->usersupp.USname, "");
521 strcpy(CC->usersupp.USaddr, "");
522 strcpy(CC->usersupp.UScity, "");
523 strcpy(CC->usersupp.USstate, "");
524 strcpy(CC->usersupp.USzip, "");
525 strcpy(CC->usersupp.USphone, "");
527 /* fetch a new user number */
528 CC->usersupp.usernum = get_new_user_number();
530 if (CC->usersupp.usernum == 1L) {
531 CC->usersupp.axlevel = 6;
534 /* add user to userlog */
535 putuser(&CC->usersupp,CC->curr_user);
536 if (getuser(&CC->usersupp,CC->curr_user)) {
537 return(ERROR+INTERNAL_ERROR);
539 rec_log(CL_NEWUSER,CC->curr_user);
547 * cmd_newu() - create a new user account
549 void cmd_newu(char *cmdbuf)
554 if ((CC->logged_in)) {
555 cprintf("%d Already logged in.\n",ERROR);
560 cprintf("%d %s: Too many users are already online (maximum is %d)\n",
561 ERROR+MAX_SESSIONS_EXCEEDED,
562 config.c_nodename,config.c_maxsessions);
565 extract(username,cmdbuf,0);
569 if (strlen(username)==0) {
570 cprintf("%d You must supply a user name.\n",ERROR);
574 a = create_user(username);
575 if ((!strcasecmp(username, "bbs")) ||
576 (!strcasecmp(username, "new")) ||
577 (!strcasecmp(username, ".")))
579 cprintf("%d '%s' is an invalid login name.\n", ERROR);
582 if (a==ERROR+ALREADY_EXISTS) {
583 cprintf("%d '%s' already exists.\n",
584 ERROR+ALREADY_EXISTS,username);
587 else if (a==ERROR+INTERNAL_ERROR) {
588 cprintf("%d Internal error - user record disappeared?\n",
589 ERROR+INTERNAL_ERROR);
596 cprintf("%d unknown error\n",ERROR);
598 rec_log(CL_NEWUSER,CC->curr_user);
606 void cmd_setp(char *new_pw)
608 if (!(CC->logged_in)) {
609 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
612 if (CC->usersupp.USuid != BBSUID) {
613 cprintf("%d Not allowed. Use the 'passwd' command.\n",ERROR);
617 if (strlen(new_pw)==0) {
618 cprintf("%d Password unchanged.\n",OK);
621 lgetuser(&CC->usersupp,CC->curr_user);
622 strcpy(CC->usersupp.password,new_pw);
623 lputuser(&CC->usersupp,CC->curr_user);
624 cprintf("%d Password changed.\n",OK);
625 rec_log(CL_PWCHANGE,CC->curr_user);
626 PerformSessionHooks(EVT_SETPASS);
630 * get user parameters
632 void cmd_getu(void) {
633 if (!(CC->logged_in)) {
634 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
637 getuser(&CC->usersupp,CC->curr_user);
638 cprintf("%d %d|%d|%d\n",
640 CC->usersupp.USscreenwidth,
641 CC->usersupp.USscreenheight,
642 (CC->usersupp.flags & US_USER_SET)
647 * set user parameters
649 void cmd_setu(char *new_parms)
652 if (num_parms(new_parms)!=3) {
653 cprintf("%d Usage error.\n",ERROR);
656 if (!(CC->logged_in)) {
657 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
660 lgetuser(&CC->usersupp,CC->curr_user);
661 CC->usersupp.USscreenwidth = extract_int(new_parms,0);
662 CC->usersupp.USscreenheight = extract_int(new_parms,1);
663 CC->usersupp.flags = CC->usersupp.flags & (~US_USER_SET);
664 CC->usersupp.flags = CC->usersupp.flags |
665 (extract_int(new_parms,2) & US_USER_SET);
666 lputuser(&CC->usersupp,CC->curr_user);
667 cprintf("%d Ok\n",OK);
671 * set last read pointer
673 void cmd_slrp(char *new_ptr)
678 if (!(CC->logged_in)) {
679 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
683 if (CC->curr_rm < 0) {
684 cprintf("%d No current room.\n",ERROR);
688 if (!strncasecmp(new_ptr,"highest",7)) {
689 newlr = CC->quickroom.QRhighest;
690 /* FIX ... if the current room is 1 (Mail), newlr needs to be set to the
691 * number of the highest mail message
695 newlr = atol(new_ptr);
698 lgetuser(&CC->usersupp, CC->curr_user);
700 /* old method - remove */
701 CC->usersupp.lastseen[CC->curr_rm] = newlr;
704 CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
705 vbuf.v_lastseen = newlr;
706 CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
708 lputuser(&CC->usersupp, CC->curr_user);
709 cprintf("%d %ld\n",OK,newlr);
714 * INVT and KICK commands
716 void cmd_invt_kick(char *iuser, int op)
718 { /* 1 = invite, 0 = kick out */
719 struct usersupp USscratch;
723 if (!(CC->logged_in)) {
724 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
728 if (CC->curr_rm < 0) {
729 cprintf("%d No current room.\n",ERROR);
733 if (is_room_aide()==0) {
734 cprintf("%d Higher access required.\n",
735 ERROR+HIGHER_ACCESS_REQUIRED);
739 /* FIX - with the new relationships scheme we can lock users out,
740 so it'll make sense to remove this routine */
741 if ( (op==1) && ((CC->quickroom.QRflags&QR_PRIVATE)==0) ) {
742 cprintf("%d Not a private room.\n",ERROR+NOT_HERE);
746 if (lgetuser(&USscratch,iuser)!=0) {
747 cprintf("%d No such user.\n",ERROR);
751 CtdlGetRelationship(&vbuf, &USscratch, &CC->quickroom);
754 /* old method -- FIX remove this when we're ready */
755 USscratch.generation[CC->curr_rm]=CC->quickroom.QRgen;
756 USscratch.forget[CC->curr_rm]=(-1);
759 vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
760 vbuf.v_flags = vbuf.v_flags | V_ACCESS;
764 /* old method -- FIX remove this when we're ready */
765 USscratch.generation[CC->curr_rm]=(-1);
766 USscratch.forget[CC->curr_rm]=CC->quickroom.QRgen;
769 vbuf.v_flags = vbuf.v_flags & ~V_ACCESS;
770 vbuf.v_flags = vbuf.v_flags | V_FORGET | V_LOCKOUT;
773 CtdlSetRelationship(&vbuf, &USscratch, &CC->quickroom);
775 lputuser(&USscratch,iuser);
777 /* post a message in Aide> saying what we just did */
778 sprintf(bbb,"%s %s %s> by %s",
780 ((op == 1) ? "invited to" : "kicked out of"),
781 CC->quickroom.QRname,
782 CC->usersupp.fullname);
785 if ((op==0)&&((CC->quickroom.QRflags&QR_PRIVATE)==0)) {
786 cprintf("%d Ok. (Not a private room, <Z>ap effect only)\n",OK);
789 cprintf("%d Ok.\n",OK);
796 * forget (Zap) the current room
798 void cmd_forg(void) {
801 if (!(CC->logged_in)) {
802 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
806 if (CC->curr_rm < 0) {
807 cprintf("%d No current room.\n",ERROR);
811 if (CC->curr_rm < 3) {
812 cprintf("%d You cannot forget this room.\n",ERROR+NOT_HERE);
817 cprintf("%d Aides cannot forget rooms.\n",ERROR);
821 lgetuser(&CC->usersupp,CC->curr_user);
822 CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
824 /* old method -- FIX remove this when we're ready */
825 CC->usersupp.forget[CC->curr_rm] = CC->quickroom.QRgen;
826 CC->usersupp.generation[CC->curr_rm] = (-1);
829 vbuf.v_flags = vbuf.v_flags | V_FORGET;
831 CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
832 lputuser(&CC->usersupp,CC->curr_user);
833 cprintf("%d Ok\n",OK);
838 * Get Next Unregistered User
840 void cmd_gnur(void) {
841 struct cdbdata *cdbus;
842 struct usersupp usbuf;
844 if (!(CC->logged_in)) {
845 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
849 if (CC->usersupp.axlevel < 6) {
850 cprintf("%d Higher access required.\n",
851 ERROR+HIGHER_ACCESS_REQUIRED);
855 if ((CitControl.MMflags&MM_VALID)==0) {
856 cprintf("%d There are no unvalidated users.\n",OK);
860 /* There are unvalidated users. Traverse the usersupp database,
861 * and return the first user we find that needs validation.
863 cdb_rewind(CDB_USERSUPP);
864 while (cdbus = cdb_next_item(CDB_USERSUPP), cdbus != NULL) {
865 bzero(&usbuf, sizeof(struct usersupp));
866 memcpy(&usbuf, cdbus->ptr,
867 ( (cdbus->len > sizeof(struct usersupp)) ?
868 sizeof(struct usersupp) : cdbus->len) );
870 if ((usbuf.flags & US_NEEDVALID)
871 &&(usbuf.axlevel > 0)) {
872 cprintf("%d %s\n",MORE_DATA,usbuf.fullname);
877 /* If we get to this point, there are no more unvalidated users.
878 * Therefore we clear the "users need validation" flag.
881 begin_critical_section(S_CONTROL);
883 CitControl.MMflags = CitControl.MMflags&(~MM_VALID);
885 end_critical_section(S_CONTROL);
886 cprintf("%d *** End of registration.\n",OK);
893 * get registration info for a user
895 void cmd_greg(char *who)
897 struct usersupp usbuf;
901 if (!(CC->logged_in)) {
902 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
906 if (!strcasecmp(who,"_SELF_")) strcpy(who,CC->curr_user);
908 if ((CC->usersupp.axlevel < 6) && (strcasecmp(who,CC->curr_user))) {
909 cprintf("%d Higher access required.\n",
910 ERROR+HIGHER_ACCESS_REQUIRED);
914 if (getuser(&usbuf,who) != 0) {
915 cprintf("%d '%s' not found.\n",ERROR+NO_SUCH_USER,who);
919 cprintf("%d %s\n",LISTING_FOLLOWS,usbuf.fullname);
920 cprintf("%ld\n",usbuf.usernum);
921 cprintf("%s\n",usbuf.password);
922 cprintf("%s\n",usbuf.USname);
923 cprintf("%s\n",usbuf.USaddr);
924 cprintf("%s\n%s\n%s\n",
925 usbuf.UScity,usbuf.USstate,usbuf.USzip);
926 strcpy(pbuf,usbuf.USphone);
928 for (a=0; a<strlen(pbuf); ++a) {
929 if ((pbuf[a]>='0')&&(pbuf[a]<='9')) {
930 b=strlen(usbuf.USphone);
931 usbuf.USphone[b]=pbuf[a];
932 usbuf.USphone[b+1]=0;
935 while(strlen(usbuf.USphone)<10) {
936 strcpy(pbuf,usbuf.USphone);
937 strcpy(usbuf.USphone," ");
938 strcat(usbuf.USphone,pbuf);
941 cprintf("(%c%c%c) %c%c%c-%c%c%c%c\n",
942 usbuf.USphone[0],usbuf.USphone[1],
943 usbuf.USphone[2],usbuf.USphone[3],
944 usbuf.USphone[4],usbuf.USphone[5],
945 usbuf.USphone[6],usbuf.USphone[7],
946 usbuf.USphone[8],usbuf.USphone[9]);
948 cprintf("%d\n",usbuf.axlevel);
949 cprintf("%s\n",usbuf.USemail);
956 void cmd_vali(char *v_args)
960 struct usersupp userbuf;
962 extract(user,v_args,0);
963 newax = extract_int(v_args,1);
965 if (!(CC->logged_in)) {
966 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
970 if (CC->usersupp.axlevel < 6) {
971 cprintf("%d Higher access required.\n",
972 ERROR+HIGHER_ACCESS_REQUIRED);
976 if (lgetuser(&userbuf,user)!=0) {
977 cprintf("%d '%s' not found.\n",ERROR+NO_SUCH_USER,user);
981 userbuf.axlevel = newax;
982 userbuf.flags = (userbuf.flags & ~US_NEEDVALID);
984 lputuser(&userbuf,user);
986 /* If the access level was set to zero, delete the user */
988 if (purge_user(user)==0) {
989 cprintf("%d %s Deleted.\n", OK, userbuf.fullname);
994 cprintf("%d ok\n",OK);
1000 * Traverse the user file...
1002 void ForEachUser(void (*CallBack)(struct usersupp *EachUser)) {
1003 struct usersupp usbuf;
1004 struct cdbdata *cdbus;
1006 cdb_rewind(CDB_USERSUPP);
1008 while(cdbus = cdb_next_item(CDB_USERSUPP), cdbus != NULL) {
1009 bzero(&usbuf, sizeof(struct usersupp));
1010 memcpy(&usbuf, cdbus->ptr,
1011 ( (cdbus->len > sizeof(struct usersupp)) ?
1012 sizeof(struct usersupp) : cdbus->len) );
1014 (*CallBack)(&usbuf);
1020 * List one user (this works with cmd_list)
1022 void ListThisUser(struct usersupp *usbuf) {
1023 if (usbuf->axlevel > 0) {
1024 if ((CC->usersupp.axlevel>=6)
1025 ||((usbuf->flags&US_UNLISTED)==0)
1026 ||((CC->internal_pgm))) {
1027 cprintf("%s|%d|%ld|%ld|%d|%d|",
1034 if (CC->usersupp.axlevel >= 6)
1035 cprintf("%s",usbuf->password);
1044 void cmd_list(void) {
1045 cprintf("%d \n",LISTING_FOLLOWS);
1046 ForEachUser(ListThisUser);
1052 * enter registration info
1054 void cmd_regi(void) {
1066 if (!(CC->logged_in)) {
1067 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1074 strcpy(tmpstate,"");
1076 strcpy(tmpphone,"");
1077 strcpy(tmpemail,"");
1079 cprintf("%d Send registration...\n",SEND_LISTING);
1081 while (client_gets(buf), strcmp(buf,"000")) {
1082 if (a==0) strcpy(tmpname,buf);
1083 if (a==1) strcpy(tmpaddr,buf);
1084 if (a==2) strcpy(tmpcity,buf);
1085 if (a==3) strcpy(tmpstate,buf);
1087 for (c=0; c<strlen(buf); ++c) {
1088 if ((buf[c]>='0')&&(buf[c]<='9')) {
1096 for (c=0; c<strlen(buf); ++c) {
1097 if ((buf[c]>='0')&&(buf[c]<='9')) {
1104 if (a==6) strncpy(tmpemail,buf,31);
1116 lgetuser(&CC->usersupp,CC->curr_user);
1117 strcpy(CC->usersupp.USname,tmpname);
1118 strcpy(CC->usersupp.USaddr,tmpaddr);
1119 strcpy(CC->usersupp.UScity,tmpcity);
1120 strcpy(CC->usersupp.USstate,tmpstate);
1121 strcpy(CC->usersupp.USzip,tmpzip);
1122 strcpy(CC->usersupp.USphone,tmpphone);
1123 strcpy(CC->usersupp.USemail,tmpemail);
1124 CC->usersupp.flags=(CC->usersupp.flags|US_REGIS|US_NEEDVALID);
1125 lputuser(&CC->usersupp,CC->curr_user);
1127 /* set global flag calling for validation */
1128 begin_critical_section(S_CONTROL);
1130 CitControl.MMflags = CitControl.MMflags | MM_VALID ;
1132 end_critical_section(S_CONTROL);
1133 cprintf("%d *** End of registration.\n",OK);
1138 * assorted info we need to check at login
1140 void cmd_chek(void) {
1145 if (!(CC->logged_in)) {
1146 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1150 getuser(&CC->usersupp,CC->curr_user); /* no lock is needed here */
1151 if ((REGISCALL!=0)&&((CC->usersupp.flags&US_REGIS)==0)) regis = 1;
1153 if (CC->usersupp.axlevel >= 6) {
1155 if (CitControl.MMflags&MM_VALID) vali = 1;
1159 /* check for mail */
1160 mail = NewMailCount();
1162 cprintf("%d %d|%d|%d\n",OK,mail,regis,vali);
1167 * check to see if a user exists
1169 void cmd_qusr(char *who)
1171 struct usersupp usbuf;
1173 if (getuser(&usbuf,who) == 0) {
1174 cprintf("%d %s\n",OK,usbuf.fullname);
1177 cprintf("%d No such user.\n",ERROR+NO_SUCH_USER);
1185 void cmd_ebio(void) {
1189 if (!(CC->logged_in)) {
1190 cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
1194 sprintf(buf,"./bio/%ld",CC->usersupp.usernum);
1195 fp = fopen(buf,"w");
1197 cprintf("%d Cannot create file\n",ERROR);
1200 cprintf("%d \n",SEND_LISTING);
1201 while(client_gets(buf), strcmp(buf,"000")) {
1202 fprintf(fp,"%s\n",buf);
1210 void cmd_rbio(char *cmdbuf)
1212 struct usersupp ruser;
1216 extract(buf,cmdbuf,0);
1217 if (getuser(&ruser,buf)!=0) {
1218 cprintf("%d No such user.\n",ERROR+NO_SUCH_USER);
1221 sprintf(buf,"./bio/%ld",ruser.usernum);
1223 fp = fopen(buf,"r");
1225 cprintf("%d %s has no bio on file.\n",
1226 ERROR+FILE_NOT_FOUND,ruser.fullname);
1229 cprintf("%d \n",LISTING_FOLLOWS);
1230 while (fgets(buf,256,fp)!=NULL) cprintf("%s",buf);
1236 * list of users who have entered bios
1238 void cmd_lbio(void) {
1241 struct usersupp usbuf;
1243 ls=popen("cd ./bio; ls","r");
1245 cprintf("%d Cannot open listing.\n",ERROR+FILE_NOT_FOUND);
1249 cprintf("%d\n",LISTING_FOLLOWS);
1250 while (fgets(buf,255,ls)!=NULL)
1251 if (getuserbynumber(&usbuf,atol(buf))==0)
1252 cprintf("%s\n",usbuf.fullname);
1259 * Administrative Get User Parameters
1261 void cmd_agup(char *cmdbuf) {
1262 struct usersupp usbuf;
1263 char requested_user[256];
1265 if ( (CC->internal_pgm==0)
1266 && ( (CC->logged_in == 0) || (is_aide()==0) ) ) {
1267 cprintf("%d Higher access required.\n",
1268 ERROR + HIGHER_ACCESS_REQUIRED);
1272 extract(requested_user, cmdbuf, 0);
1273 if (getuser(&usbuf, requested_user) != 0) {
1274 cprintf("%d No such user.\n", ERROR + NO_SUCH_USER);
1278 cprintf("%d %s|%s|%u|%d|%d|%d|%ld\n",
1293 * Administrative Set User Parameters
1295 void cmd_asup(char *cmdbuf) {
1296 struct usersupp usbuf;
1297 char requested_user[256];
1301 if ( (CC->internal_pgm==0)
1302 && ( (CC->logged_in == 0) || (is_aide()==0) ) ) {
1303 cprintf("%d Higher access required.\n",
1304 ERROR + HIGHER_ACCESS_REQUIRED);
1308 extract(requested_user, cmdbuf, 0);
1309 if (lgetuser(&usbuf, requested_user) != 0) {
1310 cprintf("%d No such user.\n", ERROR + NO_SUCH_USER);
1314 np = num_parms(cmdbuf);
1315 if (np > 1) extract(usbuf.password, cmdbuf, 1);
1316 if (np > 2) usbuf.flags = extract_int(cmdbuf, 2);
1317 if (np > 3) usbuf.timescalled = extract_int(cmdbuf, 3);
1318 if (np > 4) usbuf.posted = extract_int(cmdbuf, 4);
1320 newax = extract_int(cmdbuf, 5);
1321 if ((newax >=0) && (newax <= 6)) {
1322 usbuf.axlevel = extract_int(cmdbuf, 5);
1326 lputuser(&usbuf, requested_user);
1327 if (usbuf.axlevel == 0) {
1328 if (purge_user(requested_user)==0) {
1329 cprintf("%d %s deleted.\n", OK, requested_user);
1332 cprintf("%d Ok\n", OK);
1337 * Count the number of new mail messages the user has
1339 int NewMailCount() {
1340 int num_newmsgs = 0;
1341 struct cdbdata *cdbmb;
1346 cdbmb = cdb_fetch(CDB_MAILBOXES, &CC->usersupp.usernum, sizeof(long));
1347 if (cdbmb != NULL) {
1348 num_mails = cdbmb->len / sizeof(long);
1349 mailbox = (long *) cdbmb->ptr;
1350 if (num_mails > 0) for (a=0; a<num_mails; ++a) {
1351 if (mailbox[a] > (CC->usersupp.lastseen[1]))
1356 return(num_newmsgs);