--- app_meetme.c.orig	2004-07-04 17:51:35.000000000 -0400
+++ app_meetme.c	2004-07-04 19:17:09.000000000 -0400
@@ -66,12 +66,13 @@
 "      'v' -- video mode\n"
 "      'q' -- quiet mode (don't play enter/leave sounds)\n"
 "      'M' -- enable music on hold when the conference has a single caller\n"
-"      'x' -- exit the conference if the last marked user left\n"
-"      'w' -- wait until a marked user has entered the conference\n"
+"      'x' -- exit the conference if the last admin user left\n"
+"      'w' -- wait until a admin user has entered the conference\n"
 "      'b' -- run AGI script specified in ${MEETME_AGI_BACKGROUND}\n"
 "         Default: conf-background.agi\n"
-"        (Note: This does not work with non-Zap channels in the same conference)\n"
+"         (Note: This does not work with non-Zap channels in the same conference)\n"
 "      's' -- Present menu (user or admin) when '*' is received ('send' to menu)\n"
+"      'r' -- Allow retry on wrong PIN\n"
 "      'a' -- set admin mode\n";
 
 static char *descrip2 =
@@ -96,29 +97,30 @@
 
 static struct ast_conference {
 	char confno[AST_MAX_EXTENSION];		/* Conference */
-	struct ast_channel *chan;	/* Announcements channel */
-	int fd;				/* Announcements fd */
-	int zapconf;			/* Zaptel Conf # */
-	int users;			/* Number of active users */
-	int markedusers;		  /* Number of marked users */
-	struct ast_conf_user *firstuser;  /* Pointer to the first user struct */
-	struct ast_conf_user *lastuser;   /* Pointer to the last user struct */
-	time_t start;			/* Start time (s) */
-	int isdynamic;			/* Created on the fly? */
-	int locked;			  /* Is the conference locked? */
-	char pin[AST_MAX_EXTENSION];			/* If protected by a PIN */
+	struct ast_channel *chan;		/* Announcements channel */
+	int fd;					/* Announcements fd */
+	int zapconf;				/* Zaptel Conf # */
+	int users;				/* Number of active users */
+	int admins;				/* Number of admin users */
+	struct ast_conf_user *firstuser;	/* Pointer to the first user struct */
+	struct ast_conf_user *lastuser;		/* Pointer to the last user struct */
+	time_t start;				/* Start time (s) */
+	int isdynamic;				/* Created on the fly? */
+	int locked;				/* Is the conference locked? */
+	char pin[AST_MAX_EXTENSION];		/* If protected by a PIN */
+	char pinadmin[AST_MAX_EXTENSION]; 	/* Admin PIN */
 	struct ast_conference *next;
 } *confs;
 
 struct ast_conf_user {
-	int user_no;		     /* User Number */
-	struct ast_conf_user *prevuser;  /* Pointer to the previous user */
-	struct ast_conf_user *nextuser;  /* Pointer to the next user */
-	int userflags;			 /* Flags as set in the conference */
-	int adminflags;			 /* Flags set by the Admin */
-	struct ast_channel *chan; 	 /* Connected channel */
-	char usrvalue[50];		 /* Custom User Value */
-	time_t jointime;		 /* Time the user joined the conference */
+	int user_no;			/* User Number */
+	struct ast_conf_user *prevuser;	/* Pointer to the previous user */
+	struct ast_conf_user *nextuser;	/* Pointer to the next user */
+	int userflags;			/* Flags as set in the conference */
+	int adminflags;			/* Flags set by the Admin */
+	struct ast_channel *chan;	/* Connected channel */
+	char usrvalue[50];		/* Custom User Value */
+	time_t jointime;		/* Time the user joined the conference */
 };
 
 #define ADMINFLAG_MUTED (1 << 1)	/* User is muted */
@@ -136,6 +138,7 @@
 #define LEAVE	1
 
 #define CONF_SIZE 320
+#define MAXRETRY 3
 
 #define CONFFLAG_ADMIN	(1 << 1)	/* If set the user has admin access on the conference */
 #define CONFFLAG_MONITOR (1 << 2)	/* If set the user can only receive audio from the conference */
@@ -146,8 +149,8 @@
 #define CONFFLAG_VIDEO (1 << 7)		/* Set to enable video mode */
 #define CONFFLAG_AGI (1 << 8)		/* Set to run AGI Script in Background */
 #define CONFFLAG_MOH (1 << 9)		/* Set to have music on hold when user is alone in conference */
-#define CONFFLAG_ADMINEXIT (1 << 10)    /* If set the MeetMe will return if all marked with this flag left */
-#define CONFFLAG_WAITMARKED (1 << 11)		/* If set, the MeetMe will wait until a marked user enters */
+#define CONFFLAG_ADMINEXIT (1 << 10)	/* If set the MeetMe will return if all admin with this flag left */
+#define CONFFLAG_WAITADMIN (1 << 11)		/* If set, the MeetMe will wait until a admin user enters */
 
 
 static int careful_write(int fd, unsigned char *data, int len)
@@ -195,7 +198,7 @@
 	ast_mutex_unlock(&conflock);
 }
 
-static struct ast_conference *build_conf(char *confno, char *pin, int make, int dynamic)
+static struct ast_conference *build_conf(char *confno, char *pin, char *pinadmin, int make, int dynamic)
 {
 	struct ast_conference *cnf;
 	struct zt_confinfo ztc;
@@ -213,7 +216,8 @@
 			memset(cnf, 0, sizeof(struct ast_conference));
 			strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1);
 			strncpy(cnf->pin, pin, sizeof(cnf->pin) - 1);
-			cnf->markedusers = -1;
+			strncpy(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin) - 1);
+			cnf->admins = 0;
 			cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo");
 			if (cnf->chan) {
 				cnf->fd = cnf->chan->fds[0];	/* for use by conf_play() */
@@ -273,7 +277,7 @@
 static struct ast_cli_entry cli_show_confs = {
 	{ "show", "conferences", NULL }, confs_show,
 	"Show status of conferences", show_confs_usage, NULL };
-	
+
 static int conf_cmd(int fd, int argc, char **argv) {
 	/* Process the command */
 	struct ast_conference *cnf;
@@ -294,18 +298,20 @@
 	}
 	if (argc == 1) {
 		/* 'MeetMe': List all the conferences */	
-	now = time(NULL);
+		now = time(NULL);
 		cnf = confs;
 		if (!cnf) {
-		ast_cli(fd, "No active MeetMe conferences.\n");
-		return RESULT_SUCCESS;
-	}
-	ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation");
+			ast_cli(fd, "No active MeetMe conferences.\n");
+			return RESULT_SUCCESS;
+		}
+
+		ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation");
+
 		while(cnf) {
-			if (cnf->markedusers < 0)
+			if (cnf->admins < 0)
 				strcpy(cmdline, "N/A ");
 			else 
-				snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->markedusers);
+				snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->admins);
 			hr = (now - cnf->start) / 3600;
 			min = ((now - cnf->start) % 3600) / 60;
 			sec = (now - cnf->start) % 60;
@@ -320,6 +326,7 @@
 	}
 	if (argc < 3)
 		return RESULT_SHOWUSAGE;
+
 	strncpy(cmdline, argv[2], 100);	/* Argv 2: conference number */
 	if (strstr(argv[1], "lock")) {	
 		if (strcmp(argv[1], "lock") == 0) {
@@ -471,7 +478,7 @@
 	struct ast_conference *conf = ptr;
 	int res;
 	ast_mutex_lock(&conflock);
-	res = (conf->markedusers < 0);
+	res = (conf->admins < 0);
 	ast_mutex_unlock(&conflock);
 	return res;
 }
@@ -493,17 +500,18 @@
 	int retryzap;
 	int origfd;
 	int musiconhold = 0;
+	int lastadmin = 0;
 	int firstpass = 0;
-	int origquiet;
 	int ret = -1;
 	int x;
 	int menu_active = 0;
 	int using_pseudo = 0;
-
+	
 	struct ast_app *app;
 	char *agifile;
 	char *agifiledefault = "conf-background.agi";
 	char meetmesecs[30];
+	char pin[AST_MAX_EXTENSION];
 
 	ZT_BUFFERINFO bi;
 	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
@@ -518,15 +526,11 @@
 		goto outrun;
 	}
 	conf->users++;
-	if (confflags & CONFFLAG_ADMINEXIT) {
-		if (conf->markedusers == -1) {
-			conf->markedusers = 1;
-		} else {
-			conf->markedusers++;
-		}
-	}
-      
-   	ast_mutex_lock(&conflock);
+
+	if (confflags & CONFFLAG_ADMIN) 
+		conf->admins++;
+
+	ast_mutex_lock(&conflock);
 	if (conf->firstuser == NULL) {
 		/* Fill the first new User struct */
 		user->user_no = 1;
@@ -553,38 +557,16 @@
 	user->userflags = confflags;
 	user->adminflags = 0;
 	ast_mutex_unlock(&conflock);
-	origquiet = confflags & CONFFLAG_QUIET;
-	while((confflags & CONFFLAG_WAITMARKED) && (conf->markedusers < 0)) {
-		confflags &= ~CONFFLAG_QUIET;
-		confflags |= origquiet;
-		/* XXX Announce that we're waiting on the conference lead to join */
-		if (!(confflags & CONFFLAG_QUIET)) {
-			res = ast_streamfile(chan, "vm-dialout", chan->language);
-			if (!res)
-				res = ast_waitstream(chan, "");
-		} else
-			res = 0;
-		/* If we're waiting with hold music, set to silent mode */
-		if (!res) {
-			confflags |= CONFFLAG_QUIET;
-			ast_moh_start(chan, NULL);
-			res = ast_safe_sleep_conditional(chan, 60000, confnonzero, conf);
-			ast_moh_stop(chan);
-		}
-		if (res < 0) {
-			ast_log(LOG_DEBUG, "Got hangup on '%s' already\n", chan->name);
-			goto outrun;
-		}
-	}
-	
-	if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) {
-		if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) {
-			if (ast_waitstream(chan, "") < 0)
-				goto outrun;
-		} else
-			goto outrun;
-	}
-
+	if (confflags & CONFFLAG_QUIET) {
+	} else {
+		if (conf->users == 1 && ! (confflags & CONFFLAG_WAITADMIN))
+			if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
+				ast_waitstream(chan, "");
+
+		if (confflags & CONFFLAG_WAITADMIN && conf->admins == 0)
+			if (!ast_streamfile(chan, "conf-waitforchairman", chan->language))
+				ast_waitstream(chan, "");
+ 	}
 	/* Set it into linear mode (write) */
 	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
 		ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name);
@@ -659,7 +641,7 @@
 		}
 	}
 	memset(&ztc, 0, sizeof(ztc));
-	/* Add us to the conference */
+
 	ztc.chan = 0;	
 	ztc.confno = conf->zapconf;
 	if (confflags & CONFFLAG_MONITOR)
@@ -681,11 +663,11 @@
 			"Uniqueid: %s\r\n"
 			"Meetme: %s\r\n",
 			chan->name, chan->uniqueid, conf->confno);
-
 	if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) {
 		firstpass = 1;
 		if (!(confflags & CONFFLAG_QUIET))
-			conf_play(conf, ENTER);
+			if (confflags & CONFFLAG_WAITADMIN && conf->admins >= 1)
+				conf_play(conf, ENTER);
 	}
 
 	if (confflags & CONFFLAG_AGI) {
@@ -721,16 +703,84 @@
 			x = 1;
 			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
 		}	
+
+		if (!(confflags & CONFFLAG_QUIET) && confflags & CONFFLAG_ADMIN && confflags & CONFFLAG_WAITADMIN) {
+			if (conf->admins == 1 && conf->users > 1 && confflags & CONFFLAG_ADMIN ) {
+				ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL);
+				if (!ast_streamfile(chan, "conf-userwilljoin", chan->language))
+					ast_waitstream(chan, "");
+			}
+			if (conf->users == 1 && ! (confflags & CONFFLAG_ADMIN))
+				if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
+					ast_waitstream(chan, "");
+		}
+
 		for(;;) {
 			outfd = -1;
 			ms = -1;
+			lastadmin = conf->admins;
+
 			c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
 			
 			/* Update the struct with the actual confflags */
 			user->userflags = confflags;
 			
+			if (confflags & CONFFLAG_WAITADMIN) {
+				if(conf->admins == 0) {
+					if (lastadmin != 0) {
+						if (!(confflags & CONFFLAG_QUIET))
+							if (!ast_streamfile(chan, "conf-adminhasleft", chan->language))
+								ast_waitstream(chan, "");
+						if(confflags & CONFFLAG_ADMINEXIT)
+							break;
+						else {
+							ztc.confmode = ZT_CONF_CONF;
+							if (ioctl(fd, ZT_SETCONF, &ztc)) {
+								ast_log(LOG_WARNING, "Error setting conference\n");
+								close(fd);
+								goto outrun;
+							}
+						}
+					}
+					if (musiconhold == 0 && confflags & CONFFLAG_MOH) {
+						ast_moh_start(chan, NULL);
+						musiconhold = 1;
+					} else {
+						ztc.confmode = ZT_CONF_CONF;
+						if (ioctl(fd, ZT_SETCONF, &ztc)) {
+							ast_log(LOG_WARNING, "Error setting conference\n");
+							close(fd);
+							goto outrun;
+						}
+					}
+				} else if(conf->admins >= 1 && lastadmin == 0) {
+					if (confflags & CONFFLAG_MONITOR)
+						ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
+					else if (confflags & CONFFLAG_TALKER)
+						ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
+					else
+						ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
+					if (ioctl(fd, ZT_SETCONF, &ztc)) {
+						ast_log(LOG_WARNING, "Error setting conference\n");
+						close(fd);
+						goto outrun;
+					}
+					if (musiconhold && confflags & CONFFLAG_MOH) {
+						ast_moh_stop(chan);
+						musiconhold = 0;
+					}
+					if ( !(confflags & CONFFLAG_QUIET)) {
+						if (!ast_streamfile(chan, "conf-placeintoconf", chan->language))
+							ast_waitstream(chan, "");
+						conf_play(conf, ENTER);
+					}
+				}
+			}					
+
+
+
 			/* trying to add moh for single person conf */
-			if (confflags & CONFFLAG_MOH) {
+			if (confflags & CONFFLAG_MOH && !( confflags & CONFFLAG_WAITADMIN)) {
 				if (conf->users == 1) {
 					if (musiconhold == 0) {
 						ast_moh_start(chan, NULL);
@@ -744,8 +794,13 @@
 				}
 			}
 			
-			/* Leave if the last marked user left */
-			if (conf->markedusers == 0) {
+			/* Leave if the last admin user left */
+			if (confflags & CONFFLAG_ADMINEXIT && conf->admins == 0) {
+				if (!(confflags & CONFFLAG_QUIET)) {
+					res = ast_streamfile(chan, "conf-adminhasleft", chan->language);
+					if (!res)
+						res = ast_waitstream(chan, "");
+				}
 				ret = -1;
 				break;
 			}
@@ -770,7 +825,7 @@
 					}
 				}
 				if (user->adminflags & ADMINFLAG_KICKME) {
-					//You have been kicked.
+					/* You have been kicked. */
 					if (!ast_streamfile(chan, "conf-kicked", chan->language))
 						ast_waitstream(chan, "");
 					ret = 0;
@@ -804,7 +859,7 @@
 					break;
 				} else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) {
 					if (musiconhold) {
-			   			ast_moh_stop(chan);
+						ast_moh_stop(chan);
 					}
 					if ((confflags & CONFFLAG_ADMIN)) {
 						/* Admin menu */
@@ -818,8 +873,8 @@
 								case 1: /* Un/Mute */
 									menu_active = 0;
 		 							if (ztc.confmode & ZT_CONF_TALKER) {
-	 						       		ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
-	 						       		confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
+										ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
+										confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
 									} else {
 										ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
 										confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
@@ -869,8 +924,8 @@
 								case 1: /* Un/Mute */
 									menu_active = 0;
 		 							if (ztc.confmode & ZT_CONF_TALKER) {
-	 						       		ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
-	 						       		confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
+										ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
+										confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
 									} else if (!(user->adminflags & ADMINFLAG_MUTED)) {
 										ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
 										confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
@@ -888,6 +943,53 @@
 											ast_waitstream(chan, "");
 									}
 									break;
+								case 9: /* Login as Admin */
+									/* Prompt user for pin if pin is required */
+									if (strlen(conf->pinadmin) > 0) {
+										res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
+										if (res >= 0) {
+											if (!strcasecmp(pin, conf->pinadmin)) {
+												/* Pin correct */
+												if (confflags & CONFFLAG_MONITOR)
+													ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
+												else if (confflags & CONFFLAG_TALKER)
+													ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
+												else
+													ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
+												if (ioctl(fd, ZT_SETCONF, &ztc)) {
+													ast_log(LOG_WARNING, "Error setting conference\n");
+													close(fd);
+													goto outrun;
+												}
+												if (musiconhold && confflags & CONFFLAG_MOH) {
+													ast_moh_stop(chan);
+													musiconhold = 0;
+												}
+												confflags |= CONFFLAG_ADMIN;
+												conf->admins++;
+												if (!(confflags & CONFFLAG_QUIET)) {
+													if (conf->admins == 1 && conf->users > 1 && confflags & CONFFLAG_ADMIN ) {
+														ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL);
+														if (!ast_streamfile(chan, "conf-userwilljoin", chan->language))
+															ast_waitstream(chan, "");
+													}
+													if (conf->users == 1 && (confflags & CONFFLAG_ADMIN))
+														if (!ast_streamfile(chan, "conf-onlyperson", chan->language))
+															ast_waitstream(chan, "");
+												}
+
+											} else {
+												/* Pin invalid */
+												res = ast_streamfile(chan, "conf-invalidpin", chan->language);
+												if (!res)
+													ast_waitstream(chan, "");
+											}
+												
+										} else {
+											goto outrun;
+										}
+										break;
+									}
 								default:
 									menu_active = 0;
 									/* Play an error message! */
@@ -898,7 +1000,7 @@
 						}
 					}
 					if (musiconhold) {
-			   			ast_moh_start(chan, NULL);
+						ast_moh_start(chan, NULL);
 					}
 				} else if (using_pseudo) {
 					if (f->frametype == AST_FRAME_VOICE) {
@@ -954,8 +1056,8 @@
 			chan->name, chan->uniqueid, conf->confno);
 		prev = NULL;
 		conf->users--;
-		if (confflags & CONFFLAG_ADMINEXIT) 
-			conf->markedusers--;
+		if (confflags & CONFFLAG_ADMIN) 
+			conf->admins--;
 		cur = confs;
 		if (!conf->users) {
 			/* No more users -- close this one out */
@@ -1040,9 +1142,9 @@
 					/* Query the user to enter a PIN */
 					ast_app_getdata(chan, "conf-getpin", dynamic_pin, AST_MAX_EXTENSION - 1, 0);
 				}
-				cnf = build_conf(confno, dynamic_pin, make, dynamic);
+				cnf = build_conf(confno, dynamic_pin,"", make, dynamic);
 			} else {
-				cnf = build_conf(confno, "", make, dynamic);
+				cnf = build_conf(confno, "", "", make, dynamic);
 			}
 		} else {
 			/* Check the config */
@@ -1055,16 +1157,23 @@
 			while(var) {
 				if (!strcasecmp(var->name, "conf")) {
 					/* Separate the PIN */
-					char *pin, *conf;
+					char *pin, *pinadmin, *conf;
 
-					if ((pin = ast_strdupa(var->value))) {
-						conf = strsep(&pin, "|,");
+					if ((pinadmin = ast_strdupa(var->value))) {
+						conf = strsep(&pinadmin, "|,");
+						pin = strsep(&pinadmin, "|,");
 						if (!strcasecmp(conf, confno)) {
 							/* Bingo it's a valid conference */
 							if (pin)
-								cnf = build_conf(confno, pin, make, dynamic);
+								if (pinadmin) 
+									cnf = build_conf(confno, pin, pinadmin, make, dynamic);
+								else
+									cnf = build_conf(confno, pin, "", make, dynamic);
 							else
-								cnf = build_conf(confno, "", make, dynamic);
+								if (pinadmin)
+									cnf = build_conf(confno, "", pinadmin, make, dynamic);
+								else
+									cnf = build_conf(confno, "", "", make, dynamic);
 							break;
 						}
 					}
@@ -1096,7 +1205,7 @@
 	}
 	localdata = ast_strdupa(data);
 	LOCAL_USER_ADD(u);
-	confnum = strsep(&localdata,"|");       
+	confnum = strsep(&localdata,"|");
 	conf = find_conf(chan, confnum, 0, 0, NULL);
 	if (conf)
 		count = conf->users;
@@ -1122,6 +1231,7 @@
 	int res=-1;
 	struct localuser *u;
 	char confno[AST_MAX_EXTENSION] = "";
+	char originconfno[AST_MAX_EXTENSION] = "";
 	int allowretry = 0;
 	int retrycnt = 0;
 	struct ast_conference *cnf;
@@ -1147,6 +1257,8 @@
 		strncpy(confno, tmp, sizeof(confno));
 		if (ast_strlen_zero(confno)) {
 			allowretry = 1;
+		} else {
+			strncpy(originconfno,confno,sizeof(confno));
 		}
 	}
 	if (info)
@@ -1176,7 +1288,9 @@
 		if (strchr(inflags, 'b'))
 			confflags |= CONFFLAG_AGI;
 		if (strchr(inflags, 'w'))
-			confflags |= CONFFLAG_WAITMARKED;
+			confflags |= CONFFLAG_WAITADMIN;
+		if (strchr(inflags, 'r'))
+			allowretry = 1;
 		if (strchr(inflags, 'd'))
 			dynamic = 1;
 		if (strchr(inflags, 'D')) {
@@ -1194,7 +1308,7 @@
 	}
 
 	do {
-		if (retrycnt > 3)
+		if (retrycnt > MAXRETRY)
 			allowretry = 0;
 		if (empty) {
 			int i, map[1024];
@@ -1296,7 +1410,7 @@
 				}
 			}
 		}
-		while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) {
+		while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt <= MAXRETRY)) {
 			/* Prompt user for conference number */
 			res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0);
 			if (res < 0) {
@@ -1317,7 +1431,7 @@
 				if (allowretry)
 					strcpy(confno, "");
 			} else {
-				if (!ast_strlen_zero(cnf->pin)) {
+				if ((!ast_strlen_zero(cnf->pin) && ! (confflags & CONFFLAG_ADMIN)) || (!ast_strlen_zero(cnf->pinadmin) && (confflags & CONFFLAG_ADMIN))) {
 					char pin[AST_MAX_EXTENSION];
 
 					if (*the_pin) {
@@ -1325,10 +1439,12 @@
 						res = 0;
 					} else {
 						/* Prompt user for pin if pin is required */
-						res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
+						if (++retrycnt <= MAXRETRY)
+							res = ast_app_getdata(chan, "conf-getpin", pin, sizeof(pin) - 1, 0);
+
 					}
 					if (res >= 0) {
-						if (!strcasecmp(pin, cnf->pin)) {
+						if ((!strcasecmp(pin, cnf->pin) && ! (confflags & CONFFLAG_ADMIN)) || (!strcasecmp(pin, cnf->pinadmin) && (confflags & CONFFLAG_ADMIN))) {
 							/* Pin correct */
 							allowretry = 0;
 							/* Run the conference */
@@ -1339,7 +1455,7 @@
 							if (!res)
 								ast_waitstream(chan, "");
 							res = -1;
-							if (allowretry)
+							if (allowretry && sizeof(originconfno) == 0)
 								strcpy(confno, "");
 						}
 					} else {
