+ /* Next, try to find the G-line... */
+ if ((flags & GLINE_GLOBAL) || IsMe(acptr)) /* don't bother if it's not me! */
+ agline = gline_find(mask, flags | GLINE_ANY | GLINE_EXACT);
+
+ /* We now have all the pieces to tell us what we've got; let's put
+ * it all together and convert the rest of the arguments.
+ */
+
+ /* Handle the local G-lines first... */
+ if (flags & GLINE_LOCAL) {
+ assert(acptr);
+
+ /* normalize the action, first */
+ if (action == GLINE_LOCAL_ACTIVATE || action == GLINE_MODIFY)
+ action = GLINE_ACTIVATE;
+ else if (action == GLINE_LOCAL_DEACTIVATE)
+ action = GLINE_DEACTIVATE;
+
+ if (action == GLINE_ACTIVATE) { /* get expiration and reason */
+ if (parc < 5) /* check parameter count... */
+ return need_more_params(sptr, "GLINE");
+
+ expire = atoi(parv[3]); /* get expiration... */
+ expire = abs_expire(expire); /* convert to absolute... */
+ reason = parv[parc - 1]; /* and reason */
+
+ if (IsMe(acptr)) {
+ if (agline) /* G-line already exists, so let's ignore it... */
+ return 0;
+
+ /* OK, create the local G-line */
+ Debug((DEBUG_DEBUG, "I am creating a local G-line here; target %s, "
+ "mask %s, operforce %s, action %s, expire %Tu, reason: %s",
+ target, mask, flags & GLINE_OPERFORCE ? "YES" : "NO",
+ action == GLINE_ACTIVATE ? "+" : "-", expire, reason));
+
+ return gline_add(cptr, sptr, mask, reason, expire, lastmod,
+ lifetime, flags | GLINE_ACTIVE);
+ }
+ } else if (IsMe(acptr)) { /* destroying a local G-line */
+ if (!agline) /* G-line doesn't exist, so let's complain... */
+ return send_reply(sptr, ERR_NOSUCHGLINE, mask);
+
+ /* Let's now destroy the G-line */;
+ Debug((DEBUG_DEBUG, "I am destroying a local G-line here; target %s, "
+ "mask %s, operforce %s, action %s", target, mask,
+ flags & GLINE_OPERFORCE ? "YES" : "NO",
+ action == GLINE_ACTIVATE ? "+" : "-"));
+
+ return gline_destroy(cptr, sptr, agline);
+ }
+
+ /* OK, we've converted arguments; if it's not for us, forward */
+ /* UPDATE NOTE: Once all servers are updated to u2.10.12.11, the
+ * format string in this sendcmdto_one() may be updated to omit
+ * <lastmod> for GLINE_ACTIVATE and to omit <expire>, <lastmod>,
+ * and <reason> for GLINE_DEACTIVATE.
+ */
+ assert(!IsMe(acptr));
+
+ Debug((DEBUG_DEBUG, "I am forwarding a local G-line to a remote server; "
+ "target %s, mask %s, operforce %s, action %c, expire %Tu, "
+ "lastmod %Tu, reason: %s", target, mask,
+ flags & GLINE_OPERFORCE ? "YES" : "NO",
+ action == GLINE_ACTIVATE ? '+' : '-', expire, CurrentTime,
+ reason));
+
+ sendcmdto_one(sptr, CMD_GLINE, acptr, "%C %s%c%s %Tu %Tu :%s",
+ acptr, flags & GLINE_OPERFORCE ? "!" : "",
+ action == GLINE_ACTIVATE ? '+' : '-', mask,
+ expire - CurrentTime, CurrentTime, reason);
+
+ return 0; /* all done */
+ }
+
+ /* can't modify a G-line that doesn't exist, so remap to activate */
+ if (!agline && action == GLINE_MODIFY)
+ action = GLINE_ACTIVATE;
+
+ /* OK, let's figure out what other parameters we may have... */
+ switch (action) {
+ case GLINE_LOCAL_ACTIVATE: /* locally activating a G-line */
+ case GLINE_LOCAL_DEACTIVATE: /* locally deactivating a G-line */
+ if (!agline) /* no G-line to locally activate or deactivate? */
+ return send_reply(sptr, ERR_NOSUCHGLINE, mask);
+ lastmod = agline->gl_lastmod;
+ break; /* no additional parameters to manipulate */
+
+ case GLINE_ACTIVATE: /* activating a G-line */
+ case GLINE_DEACTIVATE: /* deactivating a G-line */
+ /* in either of these cases, we have at least a lastmod parameter */
+ if (parc < 4)
+ return need_more_params(sptr, "GLINE");
+ else if (parc == 4) /* lastmod only form... */
+ lastmod = atoi(parv[3]);
+ /*FALLTHROUGH*/
+ case GLINE_MODIFY: /* modifying a G-line */
+ /* convert expire and lastmod, look for lifetime and reason */
+ if (parc > 4) { /* protect against fall-through from 4-param form */
+ expire = atoi(parv[3]); /* convert expiration and lastmod */
+ expire = abs_expire(expire);
+ lastmod = atoi(parv[4]);
+
+ flags |= GLINE_EXPIRE; /* we have an expiration time update */
+
+ if (parc > 6) { /* no question, have a lifetime and reason */
+ lifetime = atoi(parv[5]);
+ reason = parv[parc - 1];
+
+ flags |= GLINE_LIFETIME | GLINE_REASON;
+ } else if (parc == 6) { /* either a lifetime or a reason */
+ if (!agline || /* gline creation, has to be the reason */
+ /* trial-convert as lifetime, and if it doesn't fully convert,
+ * it must be the reason */
+ ((lifetime = strtoul(parv[5], &tmp, 10)) && !*tmp)) {
+ lifetime = 0;
+ reason = parv[5];
+
+ flags |= GLINE_REASON; /* have a reason update */
+ } else if (lifetime)
+ flags |= GLINE_LIFETIME; /* have a lifetime update */
+ }
+ }
+ }
+
+ if (!lastmod) /* must have a lastmod parameter by now */