/* * Administrative Get User Parameters */ void cmd_agup(char *cmdbuf) { struct ctdluser usbuf; char requested_user[128]; if (CtdlAccessCheck(ac_aide)) { return; } extract_token(requested_user, cmdbuf, 0, '|', sizeof requested_user); if (CtdlGetUser(&usbuf, requested_user) != 0) { cprintf("%d No such user.\n", ERROR + NO_SUCH_USER); return; } cprintf("%d %s|%s|%u|%ld|%ld|%d|%ld|%ld|%d\n", CIT_OK, usbuf.fullname, usbuf.password, usbuf.flags, usbuf.timescalled, usbuf.posted, (int) usbuf.axlevel, usbuf.usernum, (long)usbuf.lastcall, usbuf.USuserpurge); }
/* * assorted info we need to check at login */ void cmd_chek(char *argbuf) { int mail = 0; int regis = 0; int vali = 0; if (CtdlAccessCheck(ac_logged_in)) { return; } CtdlGetUser(&CC->user, CC->curr_user); /* no lock is needed here */ if ((REGISCALL != 0) && ((CC->user.flags & US_REGIS) == 0)) regis = 1; if (CC->user.axlevel >= AxAideU) { if (CtdlGetConfigInt("MMflags") & MM_VALID) { vali = 1; } } /* check for mail */ mail = InitialMailCheck(); cprintf("%d %d|%d|%d|%s|\n", CIT_OK, mail, regis, vali, CC->cs_inet_email); }
/* * get user parameters */ void cmd_getu(char *cmdbuf) { if (CtdlAccessCheck(ac_logged_in)) return; CtdlGetUser(&CC->user, CC->curr_user); cprintf("%d 80|24|%d|\n", CIT_OK, (CC->user.flags & US_USER_SET)); }
/* * check to see if a user exists */ void cmd_qusr(char *who) { struct ctdluser usbuf; if (CtdlGetUser(&usbuf, who) == 0) { cprintf("%d %s\n", CIT_OK, usbuf.fullname); } else { cprintf("%d No such user.\n", ERROR + NO_SUCH_USER); } }
// // Implements the LIST commands // void nntp_list(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; char list_format[64]; char wildmat_pattern[1024]; struct nntp_list_data nld; extract_token(list_format, cmd, 1, ' ', sizeof list_format); extract_token(wildmat_pattern, cmd, 2, ' ', sizeof wildmat_pattern); if (strlen(wildmat_pattern) > 0) { nld.wildmat_pattern = wildmat_pattern; } else { nld.wildmat_pattern = NULL; } if ( (strlen(cmd) < 6) || (!strcasecmp(list_format, "ACTIVE")) ) { nld.list_format = NNTP_LIST_ACTIVE; } else if (!strcasecmp(list_format, "NEWSGROUPS")) { nld.list_format = NNTP_LIST_NEWSGROUPS; } else if (!strcasecmp(list_format, "OVERVIEW.FMT")) { nld.list_format = NNTP_LIST_OVERVIEW_FMT; } else { cprintf("501 syntax error , unsupported list format\r\n"); return; } // OVERVIEW.FMT delivers a completely different type of data than all of the // other LIST commands. It's a stupid place to put it. But that's how it's // written into RFC3977, so we have to handle it here. if (nld.list_format == NNTP_LIST_OVERVIEW_FMT) { cprintf("215 Order of fields in overview database.\r\n"); cprintf("Subject:\r\n"); cprintf("From:\r\n"); cprintf("Date:\r\n"); cprintf("Message-ID:\r\n"); cprintf("References:\r\n"); cprintf("Bytes:\r\n"); cprintf("Lines:\r\n"); cprintf(".\r\n"); return; } cprintf("215 list of newsgroups follows\r\n"); CtdlGetUser(&CC->user, CC->curr_user); CtdlForEachRoom(nntp_list_backend, &nld); cprintf(".\r\n"); }
void cmd_lrms(char *argbuf) { int FloorBeingSearched = (-1); if (!IsEmptyStr(argbuf)) FloorBeingSearched = extract_int(argbuf, 0); if (CtdlAccessCheck(ac_logged_in_or_guest)) return; CtdlGetUser(&CC->user, CC->curr_user); cprintf("%d Accessible rooms:\n", LISTING_FOLLOWS); CtdlForEachRoom(cmd_lrms_backend, &FloorBeingSearched); cprintf("000\n"); }
/* * TODODRW: change this into a CtdlModuleDo type function that returns alternative address info * for this local user. Something like CtdlModuleGoGetAddr(char *localuser, int type, char *alt_addr, size_t alt_addr_len) * where type can be ADDR_EMAIL, ADDR_FIDO, ADDR_UUCP, ADDR_WEB, ADDR_POSTAL etc etc. * This then begs the question of what should be returned. Is it wise to return a single char* using a comma as a * delimiter? Or would it be better to return a linked list of some kind? */ void local_to_inetemail(char *inetemail, char *localuser, size_t inetemail_len) { struct ctdluser us; struct vCard *v; strcpy(inetemail, ""); if (CtdlGetUser(&us, localuser) != 0) { return; } v = vcard_get_user(&us); if (v == NULL) { return; } extract_inet_email_addrs(inetemail, inetemail_len, NULL, 0, v, 1); vcard_free(v); }
/* * set the room admin for this room */ void cmd_seta(char *new_ra) { struct ctdluser usbuf; long newu; char buf[SIZ]; int post_notice; if (CtdlAccessCheck(ac_room_aide)) return; if (CtdlGetUser(&usbuf, new_ra) != 0) { newu = (-1L); } else { newu = usbuf.usernum; } CtdlGetRoomLock(&CC->room, CC->room.QRname); post_notice = 0; if (CC->room.QRroomaide != newu) { post_notice = 1; } CC->room.QRroomaide = newu; CtdlPutRoomLock(&CC->room); /* * We have to post the change notice _after_ writing changes to * the room table, otherwise it would deadlock! */ if (post_notice == 1) { if (!IsEmptyStr(usbuf.fullname)) snprintf(buf, sizeof buf, "%s is now the room admin for \"%s\".\n", usbuf.fullname, CC->room.QRname); else snprintf(buf, sizeof buf, "There is now no room admin for \"%s\".\n", CC->room.QRname); CtdlAideMessage(buf, "Admin Room Modification"); } cprintf("%d Ok\n", CIT_OK); }
// // Implements the NEWGROUPS command // void nntp_newgroups(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; char stringy_date[16]; char stringy_time[16]; char stringy_gmt[16]; struct tm tm; time_t thetime; extract_token(stringy_date, cmd, 1, ' ', sizeof stringy_date); extract_token(stringy_time, cmd, 2, ' ', sizeof stringy_time); extract_token(stringy_gmt, cmd, 3, ' ', sizeof stringy_gmt); memset(&tm, 0, sizeof tm); if (strlen(stringy_date) == 6) { sscanf(stringy_date, "%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday); tm.tm_year += 100; } else { sscanf(stringy_date, "%4d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday); tm.tm_year -= 1900; } tm.tm_mon -= 1; // tm_mon is zero based (0=January) tm.tm_isdst = (-1); // let the C library figure out whether DST is in effect sscanf(stringy_time, "%2d%2d%2d", &tm.tm_hour, &tm.tm_min ,&tm.tm_sec); thetime = mktime(&tm); if (!strcasecmp(stringy_gmt, "GMT")) { tzset(); thetime += timezone; } cprintf("231 list of new newsgroups follows\r\n"); CtdlGetUser(&CC->user, CC->curr_user); CtdlForEachRoom(nntp_newgroups_backend, &thetime); cprintf(".\r\n"); }
/* * Attempt to auto-create a new Citadel account using the nickname from Attribute Exchange */ int openid_create_user_via_ax(StrBuf *claimed_id, HashList *sreg_keys) { char *nickname = NULL; char *firstname = NULL; char *lastname = NULL; char new_password[32]; long len; const char *Key; void *Value; if (CtdlGetConfigInt("c_auth_mode") != AUTHMODE_NATIVE) return(1); if (CtdlGetConfigInt("c_disable_newu")) return(2); if (CC->logged_in) return(3); HashPos *HashPos = GetNewHashPos(sreg_keys, 0); while (GetNextHashPos(sreg_keys, HashPos, &len, &Key, &Value) != 0) { syslog(LOG_DEBUG, "%s = %s", Key, (char *)Value); if (cbmstrcasestr(Key, "value.nickname") != NULL) { nickname = (char *)Value; } else if ( (nickname == NULL) && (cbmstrcasestr(Key, "value.nickname") != NULL)) { nickname = (char *)Value; } else if (cbmstrcasestr(Key, "value.firstname") != NULL) { firstname = (char *)Value; } else if (cbmstrcasestr(Key, "value.lastname") != NULL) { lastname = (char *)Value; } } DeleteHashPos(&HashPos); if (nickname == NULL) { if ((firstname != NULL) || (lastname != NULL)) { char fullname[1024] = ""; if (firstname) strcpy(fullname, firstname); if (firstname && lastname) strcat(fullname, " "); if (lastname) strcat(fullname, lastname); nickname = fullname; } } if (nickname == NULL) { return(4); } syslog(LOG_DEBUG, "The desired account name is <%s>", nickname); len = cutuserkey(nickname); if (!CtdlGetUser(&CC->user, nickname)) { syslog(LOG_DEBUG, "<%s> is already taken by another user.", nickname); memset(&CC->user, 0, sizeof(struct ctdluser)); return(5); } /* The desired account name is available. Create the account and log it in! */ if (create_user(nickname, len, 1)) return(6); /* Generate a random password. * The user doesn't care what the password is since he is using OpenID. */ snprintf(new_password, sizeof new_password, "%08lx%08lx", random(), random()); CtdlSetPassword(new_password); /* Now attach the verified OpenID to this account. */ attach_openid(&CC->user, claimed_id); return(0); }
/* * RDIR command for room directory */ void cmd_rdir(char *cmdbuf) { char buf[256]; char comment[256]; FILE *fd; struct stat statbuf; DIR *filedir = NULL; struct dirent *filedir_entry; int d_namelen; char buf2[SIZ]; char mimebuf[64]; long len; if (CtdlAccessCheck(ac_logged_in)) return; CtdlGetRoom(&CC->room, CC->room.QRname); CtdlGetUser(&CC->user, CC->curr_user); if ((CC->room.QRflags & QR_DIRECTORY) == 0) { cprintf("%d not here.\n", ERROR + NOT_HERE); return; } if (((CC->room.QRflags & QR_VISDIR) == 0) && (CC->user.axlevel < AxAideU) && (CC->user.usernum != CC->room.QRroomaide)) { cprintf("%d not here.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } snprintf(buf, sizeof buf, "%s/%s", ctdl_file_dir, CC->room.QRdirname); filedir = opendir (buf); if (filedir == NULL) { cprintf("%d not here.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } cprintf("%d %s|%s/%s\n", LISTING_FOLLOWS, CtdlGetConfigStr("c_fqdn"), ctdl_file_dir, CC->room.QRdirname); snprintf(buf, sizeof buf, "%s/%s/filedir", ctdl_file_dir, CC->room.QRdirname); fd = fopen(buf, "r"); if (fd == NULL) fd = fopen("/dev/null", "r"); while ((filedir_entry = readdir(filedir))) { if (strcasecmp(filedir_entry->d_name, "filedir") && filedir_entry->d_name[0] != '.') { #ifdef _DIRENT_HAVE_D_NAMELEN d_namelen = filedir_entry->d_namlen; #else d_namelen = strlen(filedir_entry->d_name); #endif snprintf(buf, sizeof buf, "%s/%s/%s", ctdl_file_dir, CC->room.QRdirname, filedir_entry->d_name); stat(buf, &statbuf); /* stat the file */ if (!(statbuf.st_mode & S_IFREG)) { snprintf(buf2, sizeof buf2, "\"%s\" appears in the file directory for room \"%s\" but is not a regular file. Directories, named pipes, sockets, etc. are not usable in Citadel room directories.\n", buf, CC->room.QRname ); CtdlAideMessage(buf2, "Unusable data found in room directory"); continue; /* not a useable file type so don't show it */ } safestrncpy(comment, "", sizeof comment); fseek(fd, 0L, 0); /* rewind descriptions file */ /* Get the description from the descriptions file */ while ((fgets(buf, sizeof buf, fd) != NULL) && (IsEmptyStr(comment))) { buf[strlen(buf) - 1] = 0; if ((!strncasecmp(buf, filedir_entry->d_name, d_namelen)) && (buf[d_namelen] == ' ')) safestrncpy(comment, &buf[d_namelen + 1], sizeof comment); } len = extract_token (mimebuf, comment, 0,' ', 64); if ((len <0) || strchr(mimebuf, '/') == NULL) { snprintf (mimebuf, 64, "application/octetstream"); len = 0; } cprintf("%s|%ld|%s|%s\n", filedir_entry->d_name, (long)statbuf.st_size, mimebuf, &comment[len]); } } fclose(fd); closedir(filedir); cprintf("000\n"); }
/* * cmd_goto() - goto a new room */ void cmd_goto(char *gargs) { struct ctdlroom QRscratch; int c; int ok = 0; int ra; char augmented_roomname[ROOMNAMELEN]; char towhere[ROOMNAMELEN]; char password[32]; int transiently = 0; if (CtdlAccessCheck(ac_logged_in_or_guest)) return; extract_token(towhere, gargs, 0, '|', sizeof towhere); extract_token(password, gargs, 1, '|', sizeof password); transiently = extract_int(gargs, 2); CtdlGetUser(&CC->user, CC->curr_user); /* * Handle some of the macro named rooms */ convert_room_name_macros(towhere, sizeof towhere); /* First try a regular match */ c = CtdlGetRoom(&QRscratch, towhere); /* Then try a mailbox name match */ if (c != 0) { CtdlMailboxName(augmented_roomname, sizeof augmented_roomname, &CC->user, towhere); c = CtdlGetRoom(&QRscratch, augmented_roomname); if (c == 0) safestrncpy(towhere, augmented_roomname, sizeof towhere); } /* And if the room was found... */ if (c == 0) { /* Let internal programs go directly to any room. */ if (CC->internal_pgm) { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } /* See if there is an existing user/room relationship */ CtdlRoomAccess(&QRscratch, &CC->user, &ra, NULL); /* normal clients have to pass through security */ if (ra & UA_GOTOALLOWED) { ok = 1; } if (ok == 1) { if ((QRscratch.QRflags & QR_MAILBOX) && ((ra & UA_GOTOALLOWED))) { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } else if ((QRscratch.QRflags & QR_PASSWORDED) && ((ra & UA_KNOWN) == 0) && (strcasecmp(QRscratch.QRpasswd, password)) && (CC->user.axlevel < AxAideU) ) { cprintf("%d wrong or missing passwd\n", ERROR + PASSWORD_REQUIRED); return; } else if ((QRscratch.QRflags & QR_PRIVATE) && ((QRscratch.QRflags & QR_PASSWORDED) == 0) && ((QRscratch.QRflags & QR_GUESSNAME) == 0) && ((ra & UA_KNOWN) == 0) && (CC->user.axlevel < AxAideU) ) { syslog(LOG_DEBUG, "Failed to acquire private room\n"); } else { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } } } cprintf("%d room '%s' not found\n", ERROR + ROOM_NOT_FOUND, towhere); }
/* * send instant messages */ void cmd_sexp(char *argbuf) { int message_sent = 0; char x_user[USERNAME_SIZE]; char x_msg[1024]; char *lun; char *lem; char *x_big_msgbuf = NULL; if ((!(CC->logged_in)) && (!(CC->internal_pgm))) { cprintf("%d Not logged in.\n", ERROR + NOT_LOGGED_IN); return; } if (CC->fake_username[0]) lun = CC->fake_username; else lun = CC->user.fullname; lem = CC->cs_inet_email; extract_token(x_user, argbuf, 0, '|', sizeof x_user); extract_token(x_msg, argbuf, 1, '|', sizeof x_msg); if (!x_user[0]) { cprintf("%d You were not previously paged.\n", ERROR + NO_SUCH_USER); return; } if ((!strcasecmp(x_user, "broadcast")) && (CC->user.axlevel < AxAideU)) { cprintf("%d Higher access required to send a broadcast.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } /* This loop handles text-transfer pages */ if (!strcmp(x_msg, "-")) { message_sent = PerformXmsgHooks(lun, lem, x_user, ""); if (message_sent == 0) { if (CtdlGetUser(NULL, x_user)) cprintf("%d '%s' does not exist.\n", ERROR + NO_SUCH_USER, x_user); else cprintf("%d '%s' is not logged in " "or is not accepting pages.\n", ERROR + RESOURCE_NOT_OPEN, x_user); return; } unbuffer_output(); cprintf("%d Transmit message (will deliver to %d users)\n", SEND_LISTING, message_sent); x_big_msgbuf = malloc(SIZ); memset(x_big_msgbuf, 0, SIZ); while (client_getln(x_msg, sizeof x_msg) >= 0 && strcmp(x_msg, "000")) { x_big_msgbuf = realloc(x_big_msgbuf, strlen(x_big_msgbuf) + strlen(x_msg) + 4); if (!IsEmptyStr(x_big_msgbuf)) if (x_big_msgbuf[strlen(x_big_msgbuf)] != '\n') strcat(x_big_msgbuf, "\n"); strcat(x_big_msgbuf, x_msg); } PerformXmsgHooks(lun, lem, x_user, x_big_msgbuf); free(x_big_msgbuf); /* This loop handles inline pages */ } else { message_sent = PerformXmsgHooks(lun, lem, x_user, x_msg); if (message_sent > 0) { if (!IsEmptyStr(x_msg)) cprintf("%d Message sent", CIT_OK); else cprintf("%d Ok to send message", CIT_OK); if (message_sent > 1) cprintf(" to %d users", message_sent); cprintf(".\n"); } else { if (CtdlGetUser(NULL, x_user)) cprintf("%d '%s' does not exist.\n", ERROR + NO_SUCH_USER, x_user); else cprintf("%d '%s' is not logged in " "or is not accepting pages.\n", ERROR + RESOURCE_NOT_OPEN, x_user); } } }
/* * Validate recipients, count delivery types and errors, and handle aliasing * FIXME check for dupes!!!!! * * Returns 0 if all addresses are ok, ret->num_error = -1 if no addresses * were specified, or the number of addresses found invalid. * * Caller needs to free the result using free_recipients() */ recptypes *validate_recipients(const char *supplied_recipients, const char *RemoteIdentifier, int Flags) { struct CitContext *CCC = CC; recptypes *ret; char *recipients = NULL; char *org_recp; char this_recp[256]; char this_recp_cooked[256]; char append[SIZ]; long len; int num_recps = 0; int i, j; int mailtype; int invalid; struct ctdluser tempUS; struct ctdlroom tempQR; struct ctdlroom tempQR2; int err = 0; char errmsg[SIZ]; int in_quotes = 0; /* Initialize */ ret = (recptypes *) malloc(sizeof(recptypes)); if (ret == NULL) return(NULL); /* Set all strings to null and numeric values to zero */ memset(ret, 0, sizeof(recptypes)); if (supplied_recipients == NULL) { recipients = strdup(""); } else { recipients = strdup(supplied_recipients); } /* Allocate some memory. Yes, this allocates 500% more memory than we will * actually need, but it's healthier for the heap than doing lots of tiny * realloc() calls instead. */ len = strlen(recipients) + 1024; ret->errormsg = malloc(len); ret->recp_local = malloc(len); ret->recp_internet = malloc(len); ret->recp_ignet = malloc(len); ret->recp_room = malloc(len); ret->display_recp = malloc(len); ret->recp_orgroom = malloc(len); org_recp = malloc(len); ret->errormsg[0] = 0; ret->recp_local[0] = 0; ret->recp_internet[0] = 0; ret->recp_ignet[0] = 0; ret->recp_room[0] = 0; ret->recp_orgroom[0] = 0; ret->display_recp[0] = 0; ret->recptypes_magic = RECPTYPES_MAGIC; /* Change all valid separator characters to commas */ for (i=0; !IsEmptyStr(&recipients[i]); ++i) { if ((recipients[i] == ';') || (recipients[i] == '|')) { recipients[i] = ','; } } /* Now start extracting recipients... */ while (!IsEmptyStr(recipients)) { for (i=0; i<=strlen(recipients); ++i) { if (recipients[i] == '\"') in_quotes = 1 - in_quotes; if ( ( (recipients[i] == ',') && (!in_quotes) ) || (recipients[i] == 0) ) { safestrncpy(this_recp, recipients, i+1); this_recp[i] = 0; if (recipients[i] == ',') { strcpy(recipients, &recipients[i+1]); } else { strcpy(recipients, ""); } break; } } striplt(this_recp); if (IsEmptyStr(this_recp)) break; MSG_syslog(LOG_DEBUG, "Evaluating recipient #%d: %s\n", num_recps, this_recp); ++num_recps; strcpy(org_recp, this_recp); alias(this_recp); alias(this_recp); mailtype = alias(this_recp); for (j = 0; !IsEmptyStr(&this_recp[j]); ++j) { if (this_recp[j]=='_') { this_recp_cooked[j] = ' '; } else { this_recp_cooked[j] = this_recp[j]; } } this_recp_cooked[j] = '\0'; invalid = 0; errmsg[0] = 0; switch(mailtype) { case MES_LOCAL: if (!strcasecmp(this_recp, "sysop")) { ++ret->num_room; strcpy(this_recp, CtdlGetConfigStr("c_aideroom")); if (!IsEmptyStr(ret->recp_room)) { strcat(ret->recp_room, "|"); } strcat(ret->recp_room, this_recp); } else if ( (!strncasecmp(this_recp, "room_", 5)) && (!CtdlGetRoom(&tempQR, &this_recp_cooked[5])) ) { /* Save room so we can restore it later */ tempQR2 = CCC->room; CCC->room = tempQR; /* Check permissions to send mail to this room */ err = CtdlDoIHavePermissionToPostInThisRoom( errmsg, sizeof errmsg, RemoteIdentifier, Flags, 0 /* 0 = not a reply */ ); if (err) { ++ret->num_error; invalid = 1; } else { ++ret->num_room; if (!IsEmptyStr(ret->recp_room)) { strcat(ret->recp_room, "|"); } strcat(ret->recp_room, &this_recp_cooked[5]); if (!IsEmptyStr(ret->recp_orgroom)) { strcat(ret->recp_orgroom, "|"); } strcat(ret->recp_orgroom, org_recp); } /* Restore room in case something needs it */ CCC->room = tempQR2; } else if (CtdlGetUser(&tempUS, this_recp) == 0) { ++ret->num_local; strcpy(this_recp, tempUS.fullname); if (!IsEmptyStr(ret->recp_local)) { strcat(ret->recp_local, "|"); } strcat(ret->recp_local, this_recp); } else if (CtdlGetUser(&tempUS, this_recp_cooked) == 0) { ++ret->num_local; strcpy(this_recp, tempUS.fullname); if (!IsEmptyStr(ret->recp_local)) { strcat(ret->recp_local, "|"); } strcat(ret->recp_local, this_recp); } else { ++ret->num_error; invalid = 1; } break; case MES_INTERNET: /* Yes, you're reading this correctly: if the target * domain points back to the local system or an attached * Citadel directory, the address is invalid. That's * because if the address were valid, we would have * already translated it to a local address by now. */ if (IsDirectory(this_recp, 0)) { ++ret->num_error; invalid = 1; } else { ++ret->num_internet; if (!IsEmptyStr(ret->recp_internet)) { strcat(ret->recp_internet, "|"); } strcat(ret->recp_internet, this_recp); } break; case MES_IGNET: ++ret->num_ignet; if (!IsEmptyStr(ret->recp_ignet)) { strcat(ret->recp_ignet, "|"); } strcat(ret->recp_ignet, this_recp); break; case MES_ERROR: ++ret->num_error; invalid = 1; break; } if (invalid) { if (IsEmptyStr(errmsg)) { snprintf(append, sizeof append, "Invalid recipient: %s", this_recp); } else { snprintf(append, sizeof append, "%s", errmsg); } if ( (strlen(ret->errormsg) + strlen(append) + 3) < SIZ) { if (!IsEmptyStr(ret->errormsg)) { strcat(ret->errormsg, "; "); } strcat(ret->errormsg, append); } } else { if (IsEmptyStr(ret->display_recp)) { strcpy(append, this_recp); } else { snprintf(append, sizeof append, ", %s", this_recp); } if ( (strlen(ret->display_recp)+strlen(append)) < SIZ) { strcat(ret->display_recp, append); } } } free(org_recp); if ((ret->num_local + ret->num_internet + ret->num_ignet + ret->num_room + ret->num_error) == 0) { ret->num_error = (-1); strcpy(ret->errormsg, "No recipients specified."); } MSGM_syslog(LOG_DEBUG, "validate_recipients()\n"); MSG_syslog(LOG_DEBUG, " local: %d <%s>\n", ret->num_local, ret->recp_local); MSG_syslog(LOG_DEBUG, " room: %d <%s>\n", ret->num_room, ret->recp_room); MSG_syslog(LOG_DEBUG, " inet: %d <%s>\n", ret->num_internet, ret->recp_internet); MSG_syslog(LOG_DEBUG, " ignet: %d <%s>\n", ret->num_ignet, ret->recp_ignet); MSG_syslog(LOG_DEBUG, " error: %d <%s>\n", ret->num_error, ret->errormsg); free(recipients); return(ret); }